livetext 0.9.21 → 0.9.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. checksums.yaml +4 -4
  2. data/README.lt3 +8 -8
  3. data/bin/livetext +57 -40
  4. data/imports/bookish.rb +89 -90
  5. data/imports/calibre.rb +3 -3
  6. data/imports/livemagick.rb +17 -17
  7. data/imports/markdown.rb +10 -10
  8. data/imports/pyggish.rb +15 -47
  9. data/imports/tutorial.rb +18 -18
  10. data/lib/cmdargs.rb +10 -6
  11. data/lib/{errors.rb → livetext/errors.rb} +1 -1
  12. data/lib/{formatline.rb → livetext/formatline.rb} +69 -125
  13. data/lib/livetext/funcall.rb +84 -0
  14. data/lib/{functions.rb → livetext/functions.rb} +16 -3
  15. data/lib/livetext/global_helpers.rb +37 -0
  16. data/lib/livetext/handler/import.rb +44 -0
  17. data/lib/livetext/handler/mixin.rb +37 -0
  18. data/lib/livetext/handler.rb +3 -0
  19. data/lib/{helpers.rb → livetext/helpers.rb} +89 -67
  20. data/lib/{html.rb → livetext/html.rb} +3 -2
  21. data/lib/{parser → livetext/parser}/general.rb +0 -3
  22. data/lib/{parser → livetext/parser}/set.rb +1 -6
  23. data/lib/{parser → livetext/parser}/string.rb +2 -2
  24. data/lib/{parser.rb → livetext/parser.rb} +0 -1
  25. data/lib/livetext/parsing.rb +29 -0
  26. data/lib/livetext/paths.rb +13 -0
  27. data/lib/livetext/processor.rb +89 -0
  28. data/lib/livetext/reopen.rb +12 -0
  29. data/lib/livetext/skeleton.rb +17 -0
  30. data/lib/{standard.rb → livetext/standard.rb} +152 -122
  31. data/lib/livetext/userapi.rb +153 -0
  32. data/lib/livetext/version.rb +6 -0
  33. data/lib/livetext.rb +66 -27
  34. data/plugin/bookish.rb +85 -85
  35. data/plugin/calibre.rb +3 -3
  36. data/plugin/livemagick.rb +17 -17
  37. data/plugin/markdown.rb +10 -10
  38. data/plugin/pyggish.rb +131 -162
  39. data/plugin/tutorial.rb +15 -16
  40. data/test/all.rb +6 -0
  41. data/test/snapshots/def_method/expected-output.txt +2 -0
  42. data/test/snapshots/def_method/source.lt3 +4 -2
  43. data/test/snapshots/error_inc_line_num/OUT +17 -0
  44. data/test/snapshots/error_inc_line_num/README.txt +20 -0
  45. data/test/snapshots/error_inc_line_num/expected-output.txt +0 -6
  46. data/test/snapshots/error_inc_line_num/match-error.txt +1 -1
  47. data/test/snapshots/error_line_num/match-error.txt +1 -1
  48. data/test/snapshots/error_missing_end/expected-output.txt +0 -1
  49. data/test/snapshots/error_name_not_permitted/expected-output.txt +4 -0
  50. data/test/snapshots/error_name_not_permitted/match-error.txt +1 -1
  51. data/test/snapshots/error_no_such_copy/duh +26 -0
  52. data/test/snapshots/error_no_such_copy/expected-output.txt +1 -0
  53. data/test/snapshots/error_no_such_copy/match-error.txt +1 -1
  54. data/test/snapshots/error_no_such_copy/mystery.txt +36 -0
  55. data/test/snapshots/error_no_such_inc/match-error.txt +1 -1
  56. data/test/snapshots/error_no_such_mixin/expected-output.txt +1 -0
  57. data/test/snapshots/error_no_such_mixin/match-error.txt +1 -1
  58. data/test/snapshots/error_no_such_mixin/source.lt3 +1 -1
  59. data/test/snapshots/example_alpha/source.lt3 +2 -2
  60. data/test/snapshots/example_alpha2/expected-output.txt +0 -2
  61. data/test/snapshots/example_alpha2/source.lt3 +5 -4
  62. data/test/snapshots/{icanhaz → import}/expected-output.txt +2 -1
  63. data/test/snapshots/import/match-error.txt +1 -0
  64. data/test/snapshots/{icanhaz → import}/simple_import.rb +1 -1
  65. data/test/snapshots/{icanhaz → import}/source.lt3 +2 -2
  66. data/test/snapshots/{icanhaz2 → import2}/expected-error.txt +0 -0
  67. data/test/snapshots/{icanhaz2 → import2}/expected-output.txt +3 -1
  68. data/test/snapshots/{icanhaz2/simple_canhaz.rb → import2/simple_import.rb} +1 -1
  69. data/test/snapshots/import2/source.lt3 +8 -0
  70. data/test/snapshots/import_bookish/expected-error.txt +0 -0
  71. data/test/snapshots/import_bookish/expected-output.txt +10 -0
  72. data/test/snapshots/import_bookish/source.lt3 +7 -0
  73. data/test/snapshots/import_bookish/toc.tmp +0 -0
  74. data/test/snapshots/mixin_bookish/expected-error.txt +0 -0
  75. data/test/snapshots/mixin_bookish/expected-output.txt +10 -0
  76. data/test/snapshots/mixin_bookish/source.lt3 +7 -0
  77. data/test/snapshots/mixin_bookish/toc.tmp +0 -0
  78. data/test/snapshots/more_functions/expected-error.txt +0 -0
  79. data/test/snapshots/more_functions/expected-output.txt +37 -0
  80. data/test/snapshots/more_functions/source.lt3 +40 -0
  81. data/test/snapshots/raw_lines/expected-output.txt +0 -2
  82. data/test/snapshots/simple_import/expected-output.txt +2 -0
  83. data/test/snapshots/simple_import/simple_import.rb +1 -1
  84. data/test/snapshots/simple_import/source.lt3 +3 -1
  85. data/test/snapshots/simple_mixin/simple_mixin.rb +1 -1
  86. data/test/snapshots/single_raw_line/expected-output.txt +0 -2
  87. data/test/snapshots/subset.txt +14 -14
  88. data/test/snapshots.rb +30 -13
  89. data/test/unit/formatline.rb +253 -134
  90. data/test/unit/html.rb +2 -3
  91. data/test/unit/parser/general.rb +1 -2
  92. data/test/unit/parser/mixin.rb +1 -3
  93. data/test/unit/parser/set.rb +8 -12
  94. data/test/unit/parser/string.rb +6 -6
  95. data/test/unit/parser.rb +0 -1
  96. data/test/unit/standard.rb +0 -2
  97. metadata +47 -30
  98. data/imports/markdown_importable.rb +0 -45
  99. data/lib/handler/icanhaz.rb +0 -35
  100. data/lib/handler.rb +0 -1
  101. data/lib/livetext/importable.rb +0 -2
  102. data/lib/parser/file.rb +0 -8
  103. data/lib/parser/import.rb +0 -15
  104. data/lib/parser/mixin.rb +0 -38
  105. data/lib/processor.rb +0 -83
  106. data/lib/userapi.rb +0 -160
  107. data/test/snapshots/icanhaz/match-error.txt +0 -1
  108. data/test/snapshots/icanhaz2/source.lt3 +0 -6
  109. data/test/unit/parser/importable.rb +0 -19
data/imports/pyggish.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  require 'rouge'
2
2
 
3
+ # FIXME This file has suboptimal juju. See plugin/pyggish.rb also
4
+
3
5
  module Pyggish
4
6
  def self.pyg_change(code, klass, style)
5
7
  color = style[0..6]
@@ -29,7 +31,6 @@ module Pyggish
29
31
 
30
32
  def self.pyg_finalize(code, lexer=:elixir)
31
33
  Styles.each_pair {|klass, style| pyg_change(code, klass, style) }
32
- File.open("debug-pf1", "w") {|f| f.puts code }
33
34
  code.sub!(/<pre>/, "<pre>\n")
34
35
  code.gsub!(/<span class="[np]">/, "")
35
36
  code.gsub!(/<\/span>/, "")
@@ -37,9 +38,7 @@ File.open("debug-pf1", "w") {|f| f.puts code }
37
38
  code.sub!(/<td class="linenos"/, "<td width=2%></td><td width=5% bgcolor=#{color}")
38
39
  code.gsub!(/<td/, "<td valign=top ")
39
40
  code.gsub!(/ class="[^"]*?"/, "") # Get rid of remaining Pygments CSS
40
- File.open("debug-pf2", "w") {|f| f.puts code }
41
41
  lines = code.split("\n")
42
- # lines.each {|line| line << "\n" }
43
42
  n1 = lines.index {|x| x =~ /<pre>/ }
44
43
  n2 = lines.index {|x| x =~ /<\/pre>/ }
45
44
  # FIXME ?
@@ -48,12 +47,10 @@ File.open("debug-pf2", "w") {|f| f.puts code }
48
47
  lines[n1].sub!(/ 1$/, " 1 ")
49
48
  (n1+1).upto(n2) {|n| lines[n].replace(" " + lines[n] + " ") }
50
49
  code = lines.join("\n")
51
- File.open("debug-pf3", "w") {|f| f.puts code }
52
50
  code
53
51
  end
54
52
 
55
53
  def _process_code(text)
56
- File.open("debug-pc1", "w") {|f| f.puts text }
57
54
  lines = text.split("\n")
58
55
  lines = lines.select {|x| x !~ /##~ omit/ }
59
56
  @refs = {}
@@ -66,7 +63,6 @@ File.open("debug-pf3", "w") {|f| f.puts code }
66
63
  end
67
64
  lines.map! {|line| " " + line }
68
65
  text2 = lines.join("\n")
69
- File.open("debug-pc2", "w") {|f| f.puts text2 }
70
66
  text.replace(text2)
71
67
  end
72
68
 
@@ -86,50 +82,22 @@ File.open("debug-pf3", "w") {|f| f.puts code }
86
82
  result
87
83
  end
88
84
 
89
- def OLD_ruby
90
- file = @_args.first
91
- if file.nil?
92
- code = "# Ruby code\n"
93
- _body {|line| code << line + "\n" }
94
- else
95
- code = "# Ruby code\n\n" + ::File.read(file)
96
- end
97
-
98
- _process_code(code)
99
- html = _colorize(code, :ruby)
100
- _out "\n#{html}\n "
101
- end
102
-
103
- def OLD_elixir
104
- file = @_args.first
105
- if file.nil?
106
- code = ""
107
- _body {|line| code << line + "\n" }
108
- else
109
- code = ::File.read(file)
110
- end
111
-
112
- _process_code(code)
113
- html = _colorize(code, :elixir)
114
- _out "\n#{html}\n "
115
- end
116
-
117
85
  def fragment
118
- lang = @_args.empty? ? :elixir : @_args.first.to_sym # ruby or elixir
119
- @_args = []
86
+ lang = api.args.empty? ? :elixir : api.args.first.to_sym # ruby or elixir
87
+ api.args = []
120
88
  send(lang)
121
- _out "\n"
89
+ api.out "\n"
122
90
  end
123
91
 
124
92
  def code # FIXME ?
125
93
  text = ""
126
- _body {|line| _out " " + line }
94
+ api.body {|line| api.out " " + line }
127
95
  end
128
96
 
129
97
  def mono
130
- _out "<pre>"
131
- _body {|line| _out " " + line }
132
- _out "</pre>"
98
+ api.out "<pre>"
99
+ api.body {|line| api.out " " + line }
100
+ api.out "</pre>"
133
101
  end
134
102
 
135
103
  def create_code_styles
@@ -177,28 +145,28 @@ File.open("debug-pf3", "w") {|f| f.puts code }
177
145
  end
178
146
 
179
147
  def ruby
180
- file = @_args.first
148
+ file = api.args.first
181
149
  if file.nil?
182
150
  code = " # Ruby code\n\n"
183
- _body {|line| code << " " + line + "\n" }
151
+ api.body {|line| code << " " + line + "\n" }
184
152
  else
185
153
  code = "# Ruby code\n\n" + ::File.read(file)
186
154
  end
187
155
 
188
156
  html = format_ruby(code)
189
- _out html
157
+ api.out html
190
158
  end
191
159
 
192
160
  def elixir
193
- file = @_args.first
161
+ file = api.args.first
194
162
  if file.nil?
195
163
  code = ""
196
- _body {|line| code << " " + line + "\n" }
164
+ api.body {|line| code << " " + line + "\n" }
197
165
  else
198
166
  code = ::File.read(file)
199
167
  end
200
168
 
201
169
  html = format_elixir(code)
202
- _out html
170
+ api.out html
203
171
  end
204
172
  end
data/imports/tutorial.rb CHANGED
@@ -1,28 +1,28 @@
1
- # require 'cgi'
2
-
3
1
  require 'helpers'
4
2
 
3
+ # Created as an "ad hoc" lib for generating the README
4
+
5
5
  module Tutorial
6
- include Helpers
6
+ include Livetext::Helpers
7
7
 
8
8
  def title(args = nil, body = nil)
9
9
  h1
10
- _optional_blank_line
10
+ api.optional_blank_line
11
11
  end
12
12
 
13
13
  def section(args = nil, body = nil)
14
14
  h3
15
- _optional_blank_line
15
+ api.optional_blank_line
16
16
  end
17
17
 
18
18
  def code(args = nil, body = nil)
19
19
  first = true # dumb hack! fixes blank space
20
- _body do |line|
20
+ api.body do |line|
21
21
  tag, first = "<pre>", false if first
22
- _out "#{tag} #{escape_html(line)}" # indentation
22
+ api.out "#{tag} #{escape_html(line)}" # indentation
23
23
  end
24
- _out "</pre>"
25
- _optional_blank_line
24
+ api.out "</pre>"
25
+ api.optional_blank_line
26
26
  end
27
27
 
28
28
  def rx(str)
@@ -30,14 +30,14 @@ module Tutorial
30
30
  end
31
31
 
32
32
  def inout(args = nil, body = nil)
33
- src, out = _args
33
+ src, out = api.args
34
34
  t1 = ::File.readlines(src) rescue (abort "t1 = #{src}")
35
35
  t2 = ::File.readlines(out) rescue (abort "t2 = #{out}")
36
36
  # To pacify markdown for README (FIXME later)
37
37
  t1 = t1.map {|x| " " + x.sub(/ +$/,"").gsub(/_/, "\\_") }.join
38
38
  t2 = t2.map {|x| " " + x.sub(/ +$/,"").gsub(/_/, "\\_") }.join
39
39
 
40
- _out <<-HTML
40
+ api.out <<-HTML
41
41
  <table width=80% cellpadding=4>
42
42
  <tr>
43
43
  <td width=50%><b>Input</b></td>
@@ -53,7 +53,7 @@ module Tutorial
53
53
  </tr>
54
54
  </table>
55
55
  HTML
56
- _optional_blank_line
56
+ api.optional_blank_line
57
57
  end
58
58
 
59
59
  def put_table(src, exp)
@@ -62,7 +62,7 @@ module Tutorial
62
62
  t1 = t1.map {|x| " " + x.sub(/ +$/,"").gsub(/_/, "\\_") }.join
63
63
  t2 = t2.map {|x| " " + x.sub(/ +$/,"").gsub(/_/, "\\_") }.join
64
64
 
65
- _out <<-HTML
65
+ api.out <<-HTML
66
66
  <font size=+1>
67
67
  <table width=80% cellpadding=4>
68
68
  <tr>
@@ -83,13 +83,13 @@ module Tutorial
83
83
  end
84
84
 
85
85
  def testcase(args = nil, body = nil)
86
- name = _args.first
87
- _out "\n<font size=+1><b>Test: </font><font size=+2><tt>#{name}</tt></font></b></h3><br>"
86
+ name = api.args.first
87
+ api.out "\n<font size=+1><b>Test: </font><font size=+2><tt>#{name}</tt></font></b></h3><br>"
88
88
  src, exp = "test/snapshots/#{name}/source.lt3", "test/snapshots/#{name}/expected-output.txt"
89
- @_args = [src, exp] # Better way to do this??
89
+ api.args = [src, exp] # Better way to do this??
90
90
  put_table(src, exp)
91
- _out "<br>"
92
- _optional_blank_line
91
+ api.out "<br>"
92
+ api.optional_blank_line
93
93
  end
94
94
  end
95
95
 
data/lib/cmdargs.rb CHANGED
@@ -1,3 +1,4 @@
1
+
1
2
  require_relative 'livetext'
2
3
 
3
4
  =begin
@@ -65,27 +66,26 @@ class Livetext::CmdData
65
66
  # body: true => this command has a body + .end
66
67
  # how raw is raw?
67
68
  # remove comment - always/sometimes/never?
68
- # var_func_parse - always/sometimes/never?
69
- # var_func_parse inside body??
69
+ # interpolate - always/sometimes/never?
70
+ # interpolate inside body??
70
71
  @data = data.dup # comment? vars? funcs?
71
72
  @raw = data.dup # comment? vars? funcs?
72
73
  @args = data.split # simple array
73
74
  @nargs = nargs # not really "needed"
74
75
  check_num_args(nargs)
75
-
76
76
  # @varfunc = Livetext.interpolate(data.dup)
77
77
  end
78
78
 
79
79
  def check_num_args(num)
80
80
  num_range = /(\d{0,2})(\.\.)(\d{0,2})/ # Not "really" right...
81
81
  min, max = 0, 9999
82
- md = num_range.match(@nargs).to_a
82
+ mdata = num_range.match(@nargs).to_a
83
83
  bad_args = nil
84
84
  case
85
85
  when @nargs == ":N" # arbitrary
86
86
  # max already set
87
- when md[2] == ".." # range: 4..6 1.. ..4
88
- vmin, vmax = md.values_at(1, 2)
87
+ when mdata[2] == ".." # range: 4..6 1.. ..4
88
+ vmin, vmax = mdata.values_at(1, 2)
89
89
  min = Integer(vmin) unless vmin.empty?
90
90
  max = Integer(vmax) unless vmax.empty?
91
91
  min, max = Integer(min), Integer(max)
@@ -99,4 +99,8 @@ class Livetext::CmdData
99
99
  raise "Expected #{num} args but found #{@args.size}!" if bad_args
100
100
  end
101
101
 
102
+ def strip_comments(str)
103
+ str.sub!(/ # .*/, "")
104
+ end
105
+
102
106
  end
@@ -8,7 +8,7 @@ def make_exception(sym, str, target_class = Object)
8
8
  define_method(sym) do |*args|
9
9
  args = [] unless args.first
10
10
  msg = str.dup
11
- args.each.with_index {|arg, i| msg.sub!("%#{i+1}", arg) }
11
+ args.each.with_index {|arg, i| msg.sub!("%#{i+1}", arg.to_s) }
12
12
  target_class.class_eval(klass.to_s).new(msg)
13
13
  end
14
14
  end
@@ -1,28 +1,13 @@
1
+
2
+ require_relative 'parsing'
3
+ require_relative 'funcall'
4
+
1
5
  # Class FormatLine handles the parsing of comments, dot commands, and
2
6
  # simple formatting characters.
3
7
 
4
- class FormatLine < StringParser
5
- SimpleFormats = {}
6
- SimpleFormats[:b] = %w[<b> </b>]
7
- SimpleFormats[:i] = %w[<i> </i>]
8
- SimpleFormats[:t] = ["<font size=+1><tt>", "</tt></font>"]
9
- SimpleFormats[:s] = %w[<strike> </strike>]
10
-
11
- Null = ""
12
- Space = " "
13
- Alpha = /[A-Za-z]/
14
- AlNum = /[A-Za-z0-9_]/
15
- LF = "\n"
16
- LBrack = "["
17
-
18
- Blank = [" ", nil, "\n"]
19
- Punc = [")", ",", ".", " ", "\n"]
20
- NoAlpha = /[^A-Za-z0-9_]/
21
- NoAlphaDot = /[^.A-Za-z0-9_]/
22
- Param = ["]", "\n", nil]
23
- Escape = "\\" # not an ESC char
24
-
25
- Syms = { "*" => :b, "_" => :i, "`" => :t, "~" => :s }
8
+ class Livetext::FormatLine < StringParser
9
+ include Livetext::ParsingConstants
10
+ include Livetext::FormatLine::FunCall
26
11
 
27
12
  attr_reader :out
28
13
  attr_reader :tokenlist
@@ -37,22 +22,20 @@ class FormatLine < StringParser
37
22
  return nil if line.nil?
38
23
  x = self.new(line.chomp)
39
24
  t = x.tokenize
40
- # TTY.puts "tokens = \n#{t.inspect}\n "
41
25
  x.evaluate
42
26
  end
43
27
 
44
28
  def tokenize
45
- # add grab
46
29
  loop do
47
30
  case peek
48
- when Escape; grab; add peek; grab; add peek
31
+ when Escape; grab; add peek; grab
49
32
  when "$"
50
33
  dollar
51
34
  when "*", "_", "`", "~"
52
35
  marker peek
53
36
  add peek
54
37
  when LF
55
- break if eos? # @i >= line.size - 1
38
+ break if eos?
56
39
  when nil
57
40
  break
58
41
  else
@@ -72,6 +55,20 @@ class FormatLine < StringParser
72
55
  end
73
56
  end
74
57
 
58
+ def var_func_parse
59
+ char = self.peek
60
+ loop do
61
+ char = self.grab
62
+ break if char == LF || char == nil
63
+ self.handle_escaping if char == Escape
64
+ self.dollar if char == "$" # Could be $$
65
+ self.add char
66
+ end
67
+ self.add_token(:str)
68
+ result = self.evaluate
69
+ result
70
+ end
71
+
75
72
  def self.var_func_parse(str)
76
73
  return nil if str.nil?
77
74
  x = self.new(str.chomp)
@@ -80,7 +77,7 @@ class FormatLine < StringParser
80
77
  char = x.grab
81
78
  break if char == LF || char == nil
82
79
  x.handle_escaping if char == Escape
83
- x.dollar if char == "$"
80
+ x.dollar if char == "$" # Could be $$
84
81
  x.add char
85
82
  end
86
83
  x.add_token(:str)
@@ -107,22 +104,10 @@ class FormatLine < StringParser
107
104
  break if token.nil?
108
105
  sym, val = *token
109
106
  case sym
110
- when :str
111
- @out << val unless val == "\n" # BUG
112
- when :var
113
- @out << varsub(val)
114
- when :func
115
- param = nil
116
- arg = gen.peek
117
- if [:colon, :brackets].include? arg[0]
118
- arg = gen.next # for real
119
- param = arg[1]
120
- param = Livetext.interpolate(param)
121
- end
122
- @out << funcall(val, param)
123
- when :b, :i, :t, :s
124
- val = Livetext.interpolate(val)
125
- @out << embed(sym, val)
107
+ when :str; eval_str(val)
108
+ when :var; eval_var(val)
109
+ when :func; eval_func(val, gen)
110
+ when *BITS; eval_bits(sym, val)
126
111
  else
127
112
  add_token :str
128
113
  end
@@ -131,48 +116,6 @@ class FormatLine < StringParser
131
116
  @out
132
117
  end
133
118
 
134
- def grab_colon_param
135
- grab # grab :
136
- param = ""
137
- loop do
138
- case next!
139
- when Escape
140
- grab
141
- param << next!
142
- grab
143
- when Space, LF, nil; break
144
- else
145
- param << next!
146
- grab
147
- end
148
- end
149
-
150
- param = nil if param.empty?
151
- param
152
- end
153
-
154
- def grab_func_param
155
- grab # [
156
- param = ""
157
- loop do
158
- case next!
159
- when Escape
160
- grab
161
- param << next!
162
- grab
163
- when "]", LF, nil; break
164
- else
165
- param << next!
166
- grab
167
- end
168
- end
169
-
170
- add peek
171
- grab
172
- param = nil if param.empty?
173
- param
174
- end
175
-
176
119
  def add(str)
177
120
  @token << str unless str.nil?
178
121
  end
@@ -189,7 +132,7 @@ class FormatLine < StringParser
189
132
  loop do
190
133
  break if eos?
191
134
  str << peek
192
- break if terminate?(NoAlpha, next!)
135
+ break if terminate?(NoAlpha, lookahead)
193
136
  grab
194
137
  end
195
138
  str
@@ -201,7 +144,7 @@ class FormatLine < StringParser
201
144
  loop do
202
145
  break if peek.nil? # eos?
203
146
  str << peek
204
- break if terminate?(NoAlphaDot, next!)
147
+ break if terminate?(NoAlphaDot, lookahead)
205
148
  grab
206
149
  end
207
150
  str
@@ -216,7 +159,7 @@ class FormatLine < StringParser
216
159
  when "$"; double_dollar
217
160
  # when "."; dollar_dot
218
161
  when /[A-Za-z]/
219
- add_token :str
162
+ add_token :str
220
163
  var = peek + grab_alpha_dot
221
164
  add_token(:var, var)
222
165
  else
@@ -225,23 +168,6 @@ class FormatLine < StringParser
225
168
  end
226
169
  end
227
170
 
228
- def double_dollar
229
- case next!
230
- when Space; add_token :string, "$$ "; grab; return
231
- when LF, nil; add "$$"; add_token :str
232
- when Alpha
233
- add_token(:str, @token)
234
- func = grab_alpha
235
- add_token(:func, func)
236
- case next!
237
- when ":"; param = grab_colon_param; add_token(:colon, param)
238
- when "["; param = grab_func_param; add_token(:brackets, param)
239
- end
240
- else
241
- grab; add_token :str, "$$" + peek; return
242
- end
243
- end
244
-
245
171
  # def dollar_dot
246
172
  # add_token :ddot, @line[@i..-1]
247
173
  # end
@@ -276,7 +202,7 @@ class FormatLine < StringParser
276
202
  def double_marker(char)
277
203
  sym = Syms[char]
278
204
  kind = sym
279
- case next! # first char after **
205
+ case lookahead # first char after **
280
206
  when Space, LF, nil
281
207
  pre, post = SimpleFormats[sym]
282
208
  add_token kind
@@ -317,13 +243,12 @@ class FormatLine < StringParser
317
243
  add str
318
244
  str
319
245
  rescue => err
320
- STDERR.puts "ERR = #{err}\n#{err.backtrace}"
321
- STDERR.puts "=== str = #{str.inspect}"
246
+ ::STDERR.puts "ERR = #{err}\n#{err.backtrace}"
322
247
  end
323
248
 
324
249
  def escaped
325
- grab
326
- ch = grab
250
+ grab # Eat the backslash
251
+ ch = grab # Take next char
327
252
  ch
328
253
  end
329
254
 
@@ -350,28 +275,47 @@ class FormatLine < StringParser
350
275
  add str
351
276
  str
352
277
  rescue => err
353
- STDERR.puts "ERR = #{err}\n#{err.backtrace}"
354
- STDERR.puts "=== str = #{str.inspect}"
355
- end
356
-
357
- def funcall(name, param)
358
- err = "[Error evaluating $$#{name}(#{param})]"
359
- result =
360
- if self.respond_to?("func_" + name.to_s)
361
- self.send("func_" + name.to_s, param)
362
- else
363
- fobj = ::Livetext::Functions.new
364
- fobj.send(name, param) rescue err
365
- end
366
- result
278
+ ::STDERR.puts "ERR = #{err}\n#{err.backtrace}"
367
279
  end
368
280
 
369
281
  def varsub(name)
370
- result = Livetext::Vars[name] || "[#{name} is undefined]"
282
+ live = Livetext.new
283
+ value = live.vars[name]
284
+ result = value || "[#{name} is undefined]"
371
285
  result
372
286
  end
373
287
 
374
288
  def embedded?
375
289
  ! (['"', "'", " ", nil].include? prev)
376
290
  end
291
+
292
+ private
293
+
294
+ def eval_bits(sym, val)
295
+ val = Livetext.interpolate(val)
296
+ @out << embed(sym, val)
297
+ end
298
+
299
+ def eval_func(val, gen)
300
+ param = nil
301
+ arg = gen.peek rescue :bogus
302
+ unless arg == :bogus
303
+ if [:colon, :brackets].include? arg[0]
304
+ arg = gen.next # for real
305
+ param = arg[1]
306
+ # FIXME - unsure - interpolate again??
307
+ # param = Livetext.interpolate(param)
308
+ end
309
+ end
310
+ @out << funcall(val, param)
311
+ end
312
+
313
+ def eval_var(val)
314
+ @out << varsub(val)
315
+ end
316
+
317
+ def eval_str(val)
318
+ @out << val unless val == "\n" # BUG
319
+ end
320
+
377
321
  end
@@ -0,0 +1,84 @@
1
+
2
+ require_relative '../livetext'
3
+
4
+ # Parse function calls
5
+
6
+ module Livetext::FormatLine::FunCall
7
+
8
+ include Livetext::ParsingConstants
9
+
10
+ def param_loop(char)
11
+ param = ""
12
+ loop do
13
+ case lookahead
14
+ when Escape
15
+ param << escaped
16
+ when char, LF, nil
17
+ break
18
+ else
19
+ param << lookahead
20
+ grab
21
+ end
22
+ end
23
+ param = nil if param.empty?
24
+ param
25
+ end
26
+
27
+ def grab_colon_param
28
+ grab # grab :
29
+ param = param_loop(Space)
30
+ end
31
+
32
+ def grab_bracket_param
33
+ grab # [
34
+ param = param_loop("]")
35
+ grab # "]"
36
+ param
37
+ end
38
+
39
+ def funcall(name, param)
40
+ err = "[Error evaluating $$#{name}(#{param})]"
41
+ func_name = name # "func_" + name.to_s
42
+ result =
43
+ if self.send?(func_name, param) # self.respond_to?(func_name)
44
+ # do nothing
45
+ else
46
+ fobj = ::Livetext::Functions.new
47
+ fobj.send(name, param) rescue err
48
+ end
49
+ result.to_s
50
+ end
51
+
52
+ def double_dollar
53
+ case lookahead
54
+ when Space; add_token :string, "$$ "; grab; return
55
+ when LF, nil; add "$$"; add_token :str
56
+ when Alpha
57
+ add_token(:str, @token)
58
+ func = grab_alpha
59
+ add_token(:func, func)
60
+ param = grab_func_param # may be null/missing
61
+ else
62
+ grab; add_token :str, "$$" + peek; return
63
+ end
64
+ end
65
+
66
+ def grab_func_param
67
+ case lookahead
68
+ when "["
69
+ param = grab_bracket_param
70
+ add_token(:brackets, param)
71
+ when ":"
72
+ param = grab_colon_param
73
+ add_token(:colon, param)
74
+ else # do nothing
75
+ end
76
+ end
77
+
78
+ def escaped
79
+ grab # Eat the backslash
80
+ ch = grab # Take next char
81
+ ch
82
+ end
83
+
84
+ end