livetext 0.9.27 → 0.9.32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/README.lt3 +3 -2
  3. data/imports/bookish.rb +1 -1
  4. data/lib/livetext/expansion.rb +108 -0
  5. data/lib/livetext/formatter.rb +223 -0
  6. data/lib/livetext/functions.rb +9 -0
  7. data/lib/livetext/helpers.rb +41 -29
  8. data/lib/livetext/html.rb +73 -0
  9. data/lib/livetext/more.rb +33 -13
  10. data/lib/livetext/parser/general.rb +1 -1
  11. data/lib/livetext/parser/set.rb +10 -3
  12. data/lib/livetext/processor.rb +5 -0
  13. data/lib/livetext/standard.rb +67 -67
  14. data/lib/livetext/userapi.rb +41 -19
  15. data/lib/livetext/version.rb +1 -1
  16. data/lib/livetext.rb +1 -1
  17. data/plugin/bookish.rb +1 -1
  18. data/plugin/bootstrap_menu.rb +140 -0
  19. data/plugin/misc/navbar.rb +162 -0
  20. data/test/extra/README.txt +149 -0
  21. data/test/extra/bracketed.rb +121 -0
  22. data/test/extra/bracketed.txt +44 -0
  23. data/test/extra/double.rb +121 -0
  24. data/test/extra/double.txt +44 -0
  25. data/test/extra/functions.rb +148 -0
  26. data/test/extra/functions.txt +58 -0
  27. data/test/extra/single.rb +139 -0
  28. data/test/extra/single.txt +52 -0
  29. data/test/extra/testgen.rb +104 -0
  30. data/test/extra/variables.rb +94 -0
  31. data/test/extra/variables.txt +35 -0
  32. data/test/snapshots/basic_formatting/expected-output.txt +2 -2
  33. data/test/snapshots/simple_vars/source.lt3 +1 -1
  34. data/test/snapshots/subset.txt +49 -49
  35. data/test/unit/all.rb +1 -2
  36. data/test/unit/parser/general.rb +2 -2
  37. data/test/unit/parser/set.rb +0 -9
  38. metadata +18 -34
  39. data/lib/livetext/funcall.rb +0 -87
  40. data/lib/livetext/lineparser.rb +0 -575
  41. data/test/snapshots/basic_formatting/actual-error.txt +0 -0
  42. data/test/snapshots/basic_formatting/actual-output.txt +0 -13
  43. data/test/snapshots/basic_formatting/err-sdiff.txt +0 -1
  44. data/test/snapshots/basic_formatting/out-sdiff.txt +0 -14
  45. data/test/snapshots/error_inc_line_num/README.txt +0 -20
  46. data/test/snapshots/error_invalid_name/foo +0 -5
  47. data/test/snapshots/functions/actual-error.txt +0 -19
  48. data/test/snapshots/functions/actual-output.txt +0 -0
  49. data/test/snapshots/functions/err-sdiff.txt +0 -20
  50. data/test/snapshots/more_complex_vars/actual-error.txt +0 -0
  51. data/test/snapshots/more_complex_vars/actual-output.txt +0 -4
  52. data/test/snapshots/more_complex_vars/err-sdiff.txt +0 -1
  53. data/test/snapshots/more_complex_vars/out-sdiff.txt +0 -5
  54. data/test/snapshots/more_functions/actual-error.txt +0 -19
  55. data/test/snapshots/more_functions/actual-output.txt +0 -0
  56. data/test/snapshots/more_functions/err-sdiff.txt +0 -20
  57. data/test/snapshots/raw_lines/actual-error.txt +0 -22
  58. data/test/snapshots/raw_lines/actual-output.txt +0 -0
  59. data/test/snapshots/raw_lines/err-sdiff.txt +0 -23
  60. data/test/snapshots/simple_vars/actual-error.txt +0 -0
  61. data/test/snapshots/simple_vars/actual-output.txt +0 -6
  62. data/test/snapshots/simple_vars/err-sdiff.txt +0 -1
  63. data/test/snapshots/simple_vars/out-sdiff.txt +0 -7
  64. data/test/snapshots/var_into_func/actual-error.txt +0 -19
  65. data/test/snapshots/var_into_func/actual-output.txt +0 -0
  66. data/test/snapshots/var_into_func/err-sdiff.txt +0 -20
  67. data/test/snapshots/var_into_func/out-sdiff.txt +0 -17
  68. data/test/unit/lineparser.rb +0 -359
  69. data/test/unit/new_lineparser.rb +0 -359
  70. data/test/unit/tokenizer.rb +0 -535
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 47f377b248a2fdc2136cf68dc4a05596629723072ef84ce52b6aaea0a02edb03
4
- data.tar.gz: 3867a6a0ca695985aed1555eefcc93193bb530dc1d43047f2c70c8b9b5f37744
3
+ metadata.gz: c6069fc394894011ca9f5ed2db3022b62a3a8c541c51566126551297e60eec74
4
+ data.tar.gz: b95803194c64a840262b4912e9116905c27a1879e4f6ec4309ae48404b31fa7e
5
5
  SHA512:
6
- metadata.gz: c4d46b9519adeee2385e686739b4b29580c76cacf71d6bc8ed3679573378a19e54833c199e000a8a457d7561d1c68855e9b64805cbd599f54eb61bd902f49a38
7
- data.tar.gz: 5183aa745907e4680f3b30b5a27dabc76373cc9e7926fb0df936b6f0e812681a9bc51b6533410532bdfe23e37774ba02981926cec8f5e16b4730e899a06a1489
6
+ metadata.gz: '046369b5d8a1c659fc210eea5134e79d9c8c0cfff0a2a833fff84b89001b115f4bd326fcf10cddcabc284e3abf964ad59e43330f7b4783dc4fba7d4255e66db9'
7
+ data.tar.gz: 20fb083bbd8d727c5e5774c784afa49f9a0edd58e339bdd4b7966916ffa94cbe335c6f702c841b67b75c053c88592b7b864eb9abef60aa96a9a949f5171769e0
data/README.lt3 CHANGED
@@ -7,8 +7,9 @@
7
7
 
8
8
  *[This README is currently mangled. Fixes coming soon!]
9
9
 
10
- Livetext is simply a tool for transforming text from one format into another. The source file
11
- has commands embedded in it, and the output is dependent on those commands.
10
+ Livetext is simply a tool for transforming text another format which may be HTML or some arbitrary
11
+ format (text or otherwise). The source file has commands embedded in it, and the output is dependent
12
+ on those commands.
12
13
 
13
14
  Why is this special? It's very flexible, very extensible, and it's extensible _[in Ruby].
14
15
 
data/imports/bookish.rb CHANGED
@@ -173,7 +173,7 @@ module Bookish
173
173
  lines = api.body(true)
174
174
  maxw = nil
175
175
  lines.each do |line|
176
- api.format(line)
176
+ # line = api.format(line)
177
177
  cells = line.split(delim)
178
178
  wide = cells.map {|x| x.length }
179
179
  maxw = [0] * cells.size
@@ -0,0 +1,108 @@
1
+
2
+ class Livetext::Expansion
3
+
4
+ Ident = "[[:alpha:]]([[:alnum:]]|_)*"
5
+ Dotted = "#{Ident}(\\.#{Ident})*"
6
+ Func = "\\$\\$"
7
+ Var = "\\$"
8
+ Lbrack = "\\["
9
+ Colon = ":"
10
+
11
+ def initialize(instance)
12
+ @live = instance
13
+ end
14
+
15
+ def format(line)
16
+ return "" if line == "\n" || line.nil?
17
+ with_vars = expand_variables(line)
18
+ with_func = expand_function_calls(with_vars)
19
+ formatted = Formatter.format(with_func)
20
+ end
21
+
22
+ def expand_variables(str)
23
+ rx = Regexp.compile("(?<result>" + Var + Dotted + ")")
24
+ buffer = ""
25
+ loop do |i|
26
+ case # var or func or false alarm
27
+ when str.empty? # end of string
28
+ break
29
+ when str.slice(0..1) == "\\$" # escaped, ignore it
30
+ str.slice!(0..1)
31
+ buffer << "$"
32
+ when str.slice(0..1) == "$$" # func?
33
+ buffer << str.slice!(0..1)
34
+ when str.slice(0) == "$" # var?
35
+ vmatch = rx.match(str)
36
+ if vmatch.nil?
37
+ buffer << str.slice!(0)
38
+ next
39
+ end
40
+ vname = vmatch["result"]
41
+ str.sub!(vname, "")
42
+ vsym = vname[1..-1].to_sym
43
+ vars = @live.vars
44
+ buffer << vars.get(vsym)
45
+ else # other
46
+ char = str.slice!(0)
47
+ buffer << char
48
+ end
49
+ end
50
+ buffer
51
+ end
52
+
53
+ def funcall(name, param)
54
+ err = "[Error evaluating $$#{name}(#{param})]"
55
+ name = name.gsub(/\./, "__")
56
+ return if self.send?(name, param)
57
+ fobj = ::Livetext::Functions.new
58
+ result = fobj.send(name, param) rescue err
59
+ result.to_s
60
+ end
61
+
62
+ def expand_function_calls(str)
63
+ # Assume variables already resolved
64
+ pat1 = "(?<result>" + Func + Dotted + ")"
65
+ colon = ":"
66
+ lbrack = "\\["
67
+ rbrack = "\\]"
68
+ space_eol = "( |$)"
69
+ prx1 = "(?<param>[^ ]+)"
70
+ prx2 = "(?<param>.+)"
71
+ pat2 = "(?<full_param>#{colon}#{prx1})"
72
+ pat3 = "(?<full_param>#{lbrack}#{prx2}#{rbrack})"
73
+ rx = Regexp.compile("#{pat1}(#{pat2}|#{pat3})?")
74
+
75
+ buffer = ""
76
+ loop do |i|
77
+ case # Var or Func or false alarm
78
+ when str.nil?
79
+ return buffer
80
+ when str.empty? # end of string
81
+ break
82
+ when str.slice(0..1) == "$$" # Func?
83
+ fmatch = rx.match(str)
84
+ fname = fmatch["result"] # includes $$
85
+ param = fmatch["param"] # may be nil
86
+ full = fmatch["full_param"]
87
+ fsym = fname[2..-1] # no $$
88
+ #STDERR.puts "rx = #{rx.inspect}"
89
+ #STDERR.puts "fmatch = #{fmatch.inspect}"
90
+ #STDERR.puts "fname = #{fname.inspect}"
91
+ #STDERR.puts "param = #{param.inspect}"
92
+ #STDERR.puts "full = #{full.inspect}"
93
+ #STDERR.puts "fsym = #{fsym.inspect}"
94
+ str.sub!(fname, "")
95
+ str.sub!(full, "") if full
96
+ retval = funcall(fsym, param)
97
+ # puts "retval = #{retval.inspect}"
98
+ buffer << retval
99
+ else # other
100
+ char = str.slice!(0)
101
+ buffer << char
102
+ end
103
+ end
104
+ # STDERR.puts "buffer = #{buffer.inspect}"
105
+ buffer
106
+ end
107
+ end
108
+
@@ -0,0 +1,223 @@
1
+ module Formatter
2
+
3
+ ## Hmmm...
4
+ #
5
+ # Double: b, i, t, s
6
+ # Single: bits
7
+ # Brackt: bits
8
+ #
9
+
10
+
11
+ def self.format(str)
12
+ str = str.chomp
13
+ s2 = Double.process(str.chomp)
14
+ s3 = Bracketed.process(s2)
15
+ s4 = Single.process(s3)
16
+ s4
17
+ end
18
+
19
+ class Delimited
20
+ def initialize(str, marker, tag)
21
+ @str, @marker, @tag = str.dup, marker, tag
22
+ @buffer = ""
23
+ @cdata = ""
24
+ @state = :INITIAL
25
+ end
26
+
27
+ def status(where)
28
+ if $debug
29
+ STDERR.printf "%-11s %-7s #{@marker.inspect} \n #{' '*11} state = %-8s str = %-20s buffer = %-20s cdata = %-20s\n",
30
+ where, self.class, @state, @str.inspect, @buffer.inspect, @cdata.inspect
31
+ end
32
+ end
33
+
34
+ def front
35
+ @str[0]
36
+ end
37
+
38
+ def grab(n=1)
39
+ char = @str.slice!(0..(n-1)) # grab n chars
40
+ char
41
+ end
42
+
43
+ def grab_terminator
44
+ status("** grabterm 0")
45
+ @state = :LOOPING
46
+ # goes onto buffer by default
47
+ # Don't? what if searching for space_marker?
48
+ # @buffer << grab
49
+ end
50
+
51
+ def eol?
52
+ @str.empty?
53
+ end
54
+
55
+ def space?
56
+ front == " "
57
+ end
58
+
59
+ def escape?
60
+ front == "\\"
61
+ end
62
+
63
+ def terminated?
64
+ space? # Will be overridden except in Single
65
+ end
66
+
67
+ def marker?
68
+ @str.start_with?(@marker)
69
+ end
70
+
71
+ def space_marker?
72
+ @str.start_with?(" " + @marker)
73
+ end
74
+
75
+ def wrap(text)
76
+ status("** wrap 0")
77
+ if text.empty?
78
+ result = @marker
79
+ result = "" if @marker[1] == "["
80
+ return result
81
+ end
82
+ "<#{@tag}>#{text}</#{@tag}>"
83
+ end
84
+
85
+ def initial
86
+ status("** init 0")
87
+ n = @marker.length
88
+ case
89
+ when escape?
90
+ status("** esc i0")
91
+ grab # backslash
92
+ status("** esc i1")
93
+ @buffer << grab # char
94
+ status("** esc i2")
95
+ when space_marker?
96
+ status("** init 1")
97
+ @buffer << grab # append the space
98
+ grab(n) # eat the marker
99
+ @state = :CDATA
100
+ when marker?
101
+ status("** init 2")
102
+ grab(n) # Eat the marker
103
+ @state = :CDATA
104
+ when eol?
105
+ status("** init 3")
106
+ @state = :FINAL
107
+ else
108
+ status("** init 4")
109
+ @state = :BUFFER
110
+ end
111
+ end
112
+
113
+ def buffer
114
+ status("** buffer 0")
115
+ @buffer << grab
116
+ @state = :LOOPING
117
+ end
118
+
119
+ def cdata
120
+ status("** cdata 0")
121
+ case
122
+ when eol?
123
+ status("** cdata 1")
124
+ if @cdata.empty?
125
+ status("** cdata 2")
126
+ @buffer << @marker unless @marker[1] == "["
127
+ else
128
+ status("** cdata 3")
129
+ @buffer << wrap(@cdata)
130
+ end
131
+ @state = :FINAL
132
+ when terminated?
133
+ status("** cdata 4")
134
+ @buffer << wrap(@cdata)
135
+ grab_terminator # "*a *b" case???
136
+ @cdata = ""
137
+ @state = :LOOPING
138
+ else
139
+ status("** cdata 5")
140
+ @cdata << grab
141
+ @state = :CDATA
142
+ end
143
+ end
144
+
145
+ def looping
146
+ n = @marker.length
147
+ case
148
+ when escape?
149
+ status("** esc l0")
150
+ grab # backslash
151
+ status("** esc l1")
152
+ @buffer << grab # char
153
+ status("** esc l2")
154
+ when space_marker?
155
+ @buffer << grab # append the space
156
+ grab(n) # eat the marker
157
+ @state = :CDATA
158
+ when eol?
159
+ @state = :FINAL
160
+ else # includes marker not preceded by space!
161
+ @buffer << grab
162
+ end
163
+ end
164
+
165
+ def handle
166
+ loop do
167
+ break if @state == :FINAL
168
+ meth = @state.downcase
169
+ send(meth)
170
+ end
171
+ return @buffer
172
+ end
173
+
174
+ def self.process(str)
175
+ bold = self.new(str, "*", "b")
176
+ sb = bold.handle
177
+ # return sb
178
+ ital = self.new(sb, "_", "i")
179
+ si = ital.handle
180
+ code = self.new(si, "`", "tt")
181
+ sc = code.handle
182
+ stri = self.new(sc, "~", "strike")
183
+ si = stri.handle
184
+ si
185
+ end
186
+ end
187
+
188
+ class Single < Delimited
189
+ # Yeah, this one is that simple
190
+ end
191
+
192
+ class Double < Delimited
193
+ def initialize(str, sigil, tag)
194
+ super
195
+ # Convention: marker is "**", sigil is "*"
196
+ @marker = sigil + sigil
197
+ end
198
+
199
+ def terminated?
200
+ terms = [" ", ".", ","]
201
+ terms.include?(front)
202
+ end
203
+ end
204
+
205
+ class Bracketed < Delimited
206
+ def initialize(str, sigil, tag)
207
+ super
208
+ # Convention: marker is "*[", sigil is "*"
209
+ @marker = sigil + "["
210
+ end
211
+
212
+ def terminated?
213
+ front == "]" || eol?
214
+ end
215
+
216
+ def grab_terminator
217
+ @state = :LOOPING
218
+ grab
219
+ end
220
+ end
221
+
222
+ end
223
+
@@ -26,6 +26,15 @@ class Livetext::Functions
26
26
  "[Error evaluating $$isqrt(#{arg})]"
27
27
  end
28
28
 
29
+ def reverse(param=nil) # again, just for testing
30
+ arg = param
31
+ if arg.nil? || arg.empty?
32
+ return "(reverse: No parameter)"
33
+ else
34
+ return arg.reverse
35
+ end
36
+ end
37
+
29
38
  def date(param=nil)
30
39
  Time.now.strftime("%F")
31
40
  end
@@ -1,5 +1,6 @@
1
1
 
2
2
  require_relative 'global_helpers'
3
+ require_relative 'expansion'
3
4
 
4
5
  module Livetext::Helpers
5
6
 
@@ -9,6 +10,8 @@ module Livetext::Helpers
9
10
  ESCAPING = { "'" => '&#39;', '&' => '&amp;', '"' => '&quot;',
10
11
  '<' => '&lt;', '>' => '&gt;' }
11
12
 
13
+ TTY = ::File.open("/dev/tty", "w")
14
+
12
15
  def friendly_error(err)
13
16
  return graceful_error(err) if self.respond_to?(:graceful_error)
14
17
  return self.parent.graceful_error(err) if self.respond_to?(:parent)
@@ -55,10 +58,8 @@ module Livetext::Helpers
55
58
  base = "#{name}#{ext}"
56
59
  paths.each do |path|
57
60
  file = path + base
58
- ::Livetext::TTY.puts " Checking: #{file}"
59
61
  return file if File.exist?(file)
60
62
  end
61
- ::Livetext::TTY.puts " ...oops"
62
63
  return nil
63
64
  end
64
65
 
@@ -99,14 +100,14 @@ module Livetext::Helpers
99
100
  when DotCmd
100
101
  success = handle_dotcmd(line)
101
102
  when DollarDot
102
- success = handle_dollar_dot
103
+ success = handle_dollar_dot(line)
103
104
  else
104
105
  api.passthru(line) # must succeed?
105
106
  end
106
107
  success
107
108
  end
108
109
 
109
- def handle_dollar_dot
110
+ def handle_dollar_dot(line)
110
111
  indent = line.index("$") + 1
111
112
  @indentation.push(indent)
112
113
  line.sub!(/^ *\$/, "")
@@ -115,9 +116,11 @@ module Livetext::Helpers
115
116
  success
116
117
  end
117
118
 
118
- def invoke_dotcmd(name)
119
- # FIXME Add cmdargs stuff... depends on name, etc.
120
- retval = @main.send(name)
119
+ def invoke_dotcmd(name, data0="")
120
+ api.data = data0.dup # should permit _ in function names at least
121
+ args0 = data0.split
122
+ api.args = args0.dup
123
+ retval = @main.send(name) # , *args)
121
124
  retval
122
125
  rescue => err
123
126
  graceful_error(err)
@@ -126,13 +129,13 @@ module Livetext::Helpers
126
129
  def handle_dotcmd(line, indent = 0)
127
130
  indent = @indentation.last # top of stack
128
131
  line = line.sub(/# .*$/, "") # FIXME Could be problematic?
129
- name = get_name(line)
132
+ name, data = get_name_data(line)
130
133
  success = true # Be optimistic... :P
131
134
  case
132
135
  when name == :end # special case
133
136
  graceful_error EndWithoutOpening()
134
137
  when @main.respond_to?(name)
135
- success = invoke_dotcmd(name)
138
+ success = invoke_dotcmd(name, data)
136
139
  else
137
140
  graceful_error UnknownMethod(name)
138
141
  end
@@ -143,14 +146,20 @@ module Livetext::Helpers
143
146
  return true
144
147
  end
145
148
 
146
- def get_name(line)
147
- name, data = line.split(" ", 2)
148
- name = name[1..-1] # chop off sigil
149
+ def get_name_data(line)
150
+ line = line.chomp
151
+ blank = line.index(" ")
152
+ if blank
153
+ name = line[1..(blank-1)]
154
+ data0 = line[(blank+1)..-1]
155
+ else
156
+ name = line[1..-1]
157
+ data0 = ""
158
+ end
149
159
  name = "dot_" + name if %w[include def].include?(name)
150
160
  @main.check_disallowed(name)
151
- @main.data = data
152
- @main.api.data = data
153
- name.to_sym
161
+ @main.api.data = data0 # FIXME kill this?
162
+ [name.to_sym, data0]
154
163
  end
155
164
 
156
165
  def check_disallowed(name)
@@ -161,11 +170,13 @@ module Livetext::Helpers
161
170
  return File.exist?(file)
162
171
  end
163
172
 
173
+ def read_variables(file)
174
+ pairs = File.readlines(file).map {|x| x.chomp.split }
175
+ @api.setvars(pairs)
176
+ end
177
+
164
178
  def set_variables(pairs)
165
- pairs.each do |pair|
166
- var, value = *pair
167
- @parent.setvar(var, value)
168
- end
179
+ @api.setvars(pairs)
169
180
  end
170
181
 
171
182
  def grab_file(fname)
@@ -215,26 +226,27 @@ module Livetext::Helpers
215
226
  end
216
227
 
217
228
  def setvar(var, val)
218
- str, sym = var.to_s, var.to_sym
219
- Livetext::Vars[str] = val
220
- Livetext::Vars[sym] = val
221
- @_vars[str] = val
222
- @_vars[sym] = val
229
+ api.setvar(var, val)
230
+ # str, sym = var.to_s, var.to_sym
231
+ # Livetext::Vars[str] = val
232
+ # Livetext::Vars[sym] = val
233
+ # @_vars[str] = val
234
+ # @_vars[sym] = val
223
235
  end
224
236
 
225
237
  def setfile(file)
226
238
  if file
227
- setvar(:File, file)
239
+ api.setvar(:File, file)
228
240
  dir = File.dirname(File.expand_path(file))
229
- setvar(:FileDir, dir)
241
+ api.setvar(:FileDir, dir)
230
242
  else
231
- setvar(:File, "[no file]")
232
- setvar(:FileDir, "[no dir]")
243
+ api.setvar(:File, "[no file]")
244
+ api.setvar(:FileDir, "[no dir]")
233
245
  end
234
246
  end
235
247
 
236
248
  def setfile!(file) # FIXME why does this variant exist?
237
- setvar(:File, file)
249
+ api.setvar(:File, file)
238
250
  end
239
251
 
240
252
  end
data/lib/livetext/html.rb CHANGED
@@ -29,5 +29,78 @@ module HTMLHelper
29
29
  end
30
30
  [open, close]
31
31
  end
32
+ end
33
+
34
+ class HTML
35
+
36
+ def initialize(api)
37
+ @api = api
38
+ @indent = 0
39
+ end
40
+
41
+ def indented
42
+ " "*@indent
43
+ end
44
+
45
+ def indent(which)
46
+ case which
47
+ when :in, :right
48
+ @indent += 2
49
+ when :out, :left
50
+ @indent -= 2
51
+ else
52
+ abort "indent(#{which}) is nonsense"
53
+ end
54
+ end
55
+
56
+ def nav(**details, &block)
57
+ wrap(:nav, **details, &block)
58
+ end
32
59
 
60
+ def div(**details, &block)
61
+ wrap(:div, **details, &block)
62
+ end
63
+
64
+ def ul(**details, &block)
65
+ wrap(:ul, **details, &block)
66
+ end
67
+
68
+ def li(**details, &block)
69
+ wrap(:li, **details, &block)
70
+ end
71
+
72
+ def api
73
+ @api
74
+ end
75
+
76
+ def open_close_tags(*tags)
77
+ open, close = "", ""
78
+ tags.each do |tag|
79
+ open << "<#{tag}>"
80
+ close.prepend("</#{tag}>")
81
+ end
82
+ [open, close]
83
+ end
84
+
85
+ def wrap(*tags, **extras) # helper
86
+ open, close = open_close_tags(*tags)
87
+ extras.each_pair do |name, value|
88
+ open.sub!(">", " #{name}='#{value}'>")
89
+ end
90
+ api.out indented + open
91
+ indent(:in)
92
+ yield
93
+ indent(:out)
94
+ api.out indented + close
95
+ end
96
+
97
+ def tag(*tags, cdata: "", **extras) # helper
98
+ open, close = open_close_tags(*tags)
99
+ extras.each_pair do |name, value|
100
+ open.sub!(">", " #{name}='#{value}'>")
101
+ end
102
+ str = indented + open + cdata + close
103
+ str
104
+ end
33
105
  end
106
+
data/lib/livetext/more.rb CHANGED
@@ -6,6 +6,7 @@ class Livetext
6
6
  include Helpers
7
7
 
8
8
  class Variables
9
+ attr_reader :vars
9
10
  def initialize(hash = {})
10
11
  @vars = {}
11
12
  hash.each_pair {|k, v| @vars[k.to_sym] = v }
@@ -18,6 +19,21 @@ class Livetext
18
19
  def []=(var, value)
19
20
  @vars[var.to_sym] = value
20
21
  end
22
+
23
+ def get(var)
24
+ @vars[var.to_sym] || "[#{var} is undefined]"
25
+ end
26
+
27
+ def set(var, value)
28
+ @vars[var.to_sym] = value.to_s
29
+ end
30
+
31
+ def setvars(pairs)
32
+ pairs = pairs.to_a if pairs.is_a?(Hash)
33
+ pairs.each do |var, value|
34
+ api.setvar(var, value)
35
+ end
36
+ end
21
37
  end
22
38
 
23
39
  Vars = Variables.new
@@ -37,18 +53,10 @@ class Livetext
37
53
  end
38
54
 
39
55
  def self.interpolate(str)
40
- parse = Livetext::LineParser.new(str)
41
- parse.var_func_parse
42
- end
43
-
44
- def self.customize(mix: [], call: [], vars: {})
45
- obj = self.new
46
- mix = Array(mix)
47
- call = Array(call)
48
- mix.each {|lib| obj.mixin(lib) }
49
- call.each {|cmd| obj.main.send(cmd[1..-1]) } # ignores leading dot, no param
50
- vars.each_pair {|var, val| obj.setvar(var, val.to_s) }
51
- obj
56
+ expand = Livetext::Expansion.new(self)
57
+ str2 = expand.expand_variables(str)
58
+ str3 = expand.expand_function_calls(str2)
59
+ str3
52
60
  end
53
61
 
54
62
  def peek_nextline
@@ -83,12 +91,24 @@ class Livetext
83
91
  raise err
84
92
  end
85
93
 
94
+ def self.customize(mix: [], call: [], vars: {})
95
+ obj = self.new
96
+ mix = Array(mix)
97
+ call = Array(call)
98
+ mix.each {|lib| obj.mixin(lib) }
99
+ call.each {|cmd| obj.main.send(cmd[1..-1]) } # ignores leading dot, no param
100
+ # vars.each_pair {|var, val| obj.setvar(var, val.to_s) }
101
+ obj.api.setvars(vars)
102
+ obj
103
+ end
104
+
86
105
  def customize(mix: [], call: [], vars: {})
87
106
  mix = Array(mix)
88
107
  call = Array(call)
89
108
  mix.each {|lib| mixin(lib) }
90
109
  call.each {|cmd| @main.send(cmd[1..-1]) } # ignores leading dot, no param
91
- vars.each_pair {|var, val| @api.setvar(var, val.to_s) }
110
+ # vars.each_pair {|var, val| @api.set(var, val.to_s) }
111
+ api.setvars(vars)
92
112
  self
93
113
  end
94
114
 
@@ -24,7 +24,7 @@ class Livetext::ParseGeneral < StringParser
24
24
  lines.each do |line|
25
25
  next if line.strip.empty?
26
26
  var, value = line.split(" ", 2)
27
- val = Livetext.interpolate(value)
27
+ # val = Livetext.interpolate(value)
28
28
  var = prefix + "." + var if prefix
29
29
  pairs << [var, value]
30
30
  end