livetext 0.9.21 → 0.9.25

Sign up to get free protection for your applications and to get access to all the features.
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