livetext 0.9.25 → 0.9.26
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.
- checksums.yaml +4 -4
- data/imports/bookish.rb +1 -2
- data/lib/livetext/errors.rb +3 -0
- data/lib/livetext/formatline.rb +102 -15
- data/lib/livetext/funcall.rb +86 -2
- data/lib/livetext/global_helpers.rb +5 -0
- data/lib/livetext/handler/import.rb +2 -6
- data/lib/livetext/handler/mixin.rb +2 -6
- data/lib/livetext/helpers.rb +9 -11
- data/lib/livetext/lineparser.rb +441 -0
- data/lib/livetext/more.rb +158 -0
- data/lib/livetext/processor.rb +3 -1
- data/lib/livetext/skeleton.rb +5 -0
- data/lib/livetext/standard.rb +12 -8
- data/lib/livetext/userapi.rb +27 -10
- data/lib/livetext/version.rb +1 -1
- data/lib/livetext.rb +3 -152
- data/test/snapshots/basic_formatting/actual-error.txt +0 -0
- data/test/snapshots/basic_formatting/actual-output.txt +13 -0
- data/test/snapshots/basic_formatting/err-sdiff.txt +1 -0
- data/test/snapshots/basic_formatting/out-sdiff.txt +14 -0
- data/test/snapshots/error_invalid_name/foo +5 -0
- data/test/snapshots/import_bookish/expected-output.txt +4 -4
- data/test/snapshots/more_functions/actual-error.txt +0 -0
- data/test/snapshots/more_functions/actual-output.txt +37 -0
- data/test/snapshots/more_functions/err-sdiff.txt +1 -0
- data/test/snapshots/more_functions/expected-output.txt +1 -1
- data/test/snapshots/more_functions/out-sdiff.txt +38 -0
- data/test/snapshots/more_functions/source.lt3 +1 -1
- data/test/snapshots/simple_vars/actual-error.txt +0 -0
- data/test/snapshots/simple_vars/actual-output.txt +6 -0
- data/test/snapshots/simple_vars/err-sdiff.txt +1 -0
- data/test/snapshots/simple_vars/out-sdiff.txt +7 -0
- data/test/snapshots/subset.txt +2 -0
- data/test/snapshots/var_into_func/actual-error.txt +0 -0
- data/test/snapshots/var_into_func/actual-output.txt +16 -0
- data/test/snapshots/var_into_func/err-sdiff.txt +1 -0
- data/test/snapshots/var_into_func/expected-error.txt +0 -0
- data/test/snapshots/var_into_func/expected-output.txt +16 -0
- data/test/snapshots/var_into_func/out-sdiff.txt +17 -0
- data/test/snapshots/var_into_func/source.lt3 +16 -0
- data/test/unit/all.rb +3 -1
- data/test/unit/formatline.rb +143 -274
- data/test/unit/lineparser.rb +650 -0
- data/test/unit/parser/set.rb +13 -12
- data/test/unit/tokenizer.rb +534 -0
- metadata +26 -5
- data/test/snapshots/error_inc_line_num/OUT +0 -17
- data/test/snapshots/error_no_such_copy/duh +0 -26
- data/test/snapshots/error_no_such_copy/mystery.txt +0 -36
@@ -0,0 +1,441 @@
|
|
1
|
+
|
2
|
+
require_relative 'parsing'
|
3
|
+
require_relative 'funcall'
|
4
|
+
|
5
|
+
# Class LineParser handles the parsing of comments, dot commands, and
|
6
|
+
# simple formatting characters, as well as variables and functions.
|
7
|
+
|
8
|
+
class Livetext::LineParser < StringParser
|
9
|
+
include Livetext::ParsingConstants
|
10
|
+
include Livetext::LineParser::FunCall
|
11
|
+
|
12
|
+
FMTS = %w[* _ ~ `]
|
13
|
+
|
14
|
+
attr_reader :out
|
15
|
+
attr_reader :tokenlist
|
16
|
+
|
17
|
+
def initialize(line)
|
18
|
+
super
|
19
|
+
@token = Null.dup
|
20
|
+
@tokenlist = []
|
21
|
+
@live = Livetext.new
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.api
|
25
|
+
Livetext.new.main.api
|
26
|
+
end
|
27
|
+
|
28
|
+
def api
|
29
|
+
@live.main.api
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.parse!(line)
|
33
|
+
return nil if line.nil?
|
34
|
+
line.chomp!
|
35
|
+
x = self.new(line)
|
36
|
+
api.tty "\n-- string: #{line.inspect}" if $testme
|
37
|
+
t = x.tokenize
|
38
|
+
api.tty "-- Tokens: #{t.inspect}" if $testme
|
39
|
+
result = x.evaluate
|
40
|
+
api.tty "-- result: #{result.inspect}" if $testme
|
41
|
+
result
|
42
|
+
end
|
43
|
+
|
44
|
+
def parse_formatting
|
45
|
+
loop do
|
46
|
+
case peek
|
47
|
+
when Escape; grab; add peek; grab
|
48
|
+
when "*", "_", "`", "~"
|
49
|
+
marker peek
|
50
|
+
add peek
|
51
|
+
when LF
|
52
|
+
break if eos?
|
53
|
+
when nil
|
54
|
+
break
|
55
|
+
else
|
56
|
+
add peek
|
57
|
+
end
|
58
|
+
grab
|
59
|
+
end
|
60
|
+
add_token(:str)
|
61
|
+
@tokenlist
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.parse_formatting(str)
|
65
|
+
fmt = self.new(str)
|
66
|
+
loop do
|
67
|
+
case fmt.peek
|
68
|
+
when Escape; fmt.grab; fmt.add fmt.peek; fmt.grab
|
69
|
+
when "*", "_", "`", "~"
|
70
|
+
fmt.marker fmt.peek
|
71
|
+
fmt.add fmt.peek
|
72
|
+
when LF
|
73
|
+
break if fmt.eos?
|
74
|
+
when nil
|
75
|
+
break
|
76
|
+
else
|
77
|
+
fmt.add fmt.peek
|
78
|
+
end
|
79
|
+
fmt.grab
|
80
|
+
end
|
81
|
+
fmt.add_token(:str)
|
82
|
+
fmt.tokenlist
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.parse_variables(str)
|
86
|
+
return nil if str.nil?
|
87
|
+
x = self.new(str.chomp)
|
88
|
+
char = x.peek
|
89
|
+
loop do
|
90
|
+
char = x.grab
|
91
|
+
break if char == LF || char == nil
|
92
|
+
x.escaped if char == Escape
|
93
|
+
x.dollar if char == "$" # Could be $$
|
94
|
+
x.add char
|
95
|
+
end
|
96
|
+
x.add_token(:str)
|
97
|
+
result = x.evaluate
|
98
|
+
result
|
99
|
+
end
|
100
|
+
|
101
|
+
def embed(sym, str)
|
102
|
+
pre, post = SimpleFormats[sym]
|
103
|
+
pre + str + post
|
104
|
+
end
|
105
|
+
|
106
|
+
#########
|
107
|
+
|
108
|
+
def handle_simple_formatting(ch)
|
109
|
+
# api.tty "ch = #{ch.inspect}"
|
110
|
+
marker ch
|
111
|
+
add ch
|
112
|
+
# api.tty "token = #{@token.inspect} #{@tokenlist.inspect}"
|
113
|
+
c2 = grab
|
114
|
+
# api.tty "c2 = #{c2.inspect}"
|
115
|
+
end
|
116
|
+
|
117
|
+
def grab_string
|
118
|
+
weird = ["$", nil] # [Escape, "$", nil]
|
119
|
+
ch = grab
|
120
|
+
add ch # api.tty "-- gs @token = #{@token.inspect}"
|
121
|
+
loop do
|
122
|
+
ch = peek # api.tty "gs1 ch = #{ch.inspect}"
|
123
|
+
break if weird.include?(ch)
|
124
|
+
break if FMTS.include?(ch) && (self.prev == " ")
|
125
|
+
break if eos? # ch = grab # advance pointer # api.tty "gs3 ch = #{ch.inspect}"
|
126
|
+
add grab
|
127
|
+
end # ch = grab # advance pointer # api.tty "-- gs4 ch = #{ch.inspect}"; sleep 0.01
|
128
|
+
add_token :str
|
129
|
+
end
|
130
|
+
|
131
|
+
def grab_token(ch)
|
132
|
+
finish = false
|
133
|
+
# api.tty "#{__method__}: ch = #{ch.inspect}"
|
134
|
+
case ch
|
135
|
+
when nil; finish = true # do nothing
|
136
|
+
when LF; finish = true # do nothing - break if eos?
|
137
|
+
when Escape; ch = self.escaped; add ch
|
138
|
+
when "$"; dollar
|
139
|
+
when *FMTS; handle_simple_formatting(ch)
|
140
|
+
else grab_string
|
141
|
+
end
|
142
|
+
# api.tty "#{__method__}: AFTER CASE: api.data = #{api.data.inspect}"
|
143
|
+
[ch, finish, @token, @tokenlist]
|
144
|
+
end
|
145
|
+
|
146
|
+
def tokenize
|
147
|
+
ch = peek
|
148
|
+
loop do
|
149
|
+
ch = peek
|
150
|
+
stuff = grab_token(ch)
|
151
|
+
ch, finish, t, tlist = *stuff
|
152
|
+
break if finish
|
153
|
+
end
|
154
|
+
# api.tty "tokenize: i = #{self.i}"
|
155
|
+
# api.tty "tokenize: token = #{@token.inspect} tokenlist = #{@tokenlist.inspect}"
|
156
|
+
@tokenlist
|
157
|
+
end
|
158
|
+
|
159
|
+
# def self.get_vars
|
160
|
+
# grab
|
161
|
+
# case peek
|
162
|
+
# when LF, " ", nil
|
163
|
+
# add "$"
|
164
|
+
# add_token :str
|
165
|
+
# when "$"; double_dollar
|
166
|
+
## when "."; dollar_dot
|
167
|
+
# when /[A-Za-z]/
|
168
|
+
# add_token :str
|
169
|
+
# var = peek + grab_alpha_dot
|
170
|
+
# add_token(:var, var)
|
171
|
+
# else
|
172
|
+
# add "$" + peek
|
173
|
+
# add_token(:str)
|
174
|
+
# end
|
175
|
+
# end
|
176
|
+
#
|
177
|
+
# def self.parse_var_func # FIXME Hmm...
|
178
|
+
# loop do
|
179
|
+
# case peek
|
180
|
+
# when "$"
|
181
|
+
# dollar
|
182
|
+
# when LF
|
183
|
+
# break if eos?
|
184
|
+
# when nil
|
185
|
+
# break
|
186
|
+
# else
|
187
|
+
# add peek
|
188
|
+
# end
|
189
|
+
# grab
|
190
|
+
# end
|
191
|
+
# add_token(:str)
|
192
|
+
# @tokenlist
|
193
|
+
# end
|
194
|
+
|
195
|
+
def terminate?(terminators, ch)
|
196
|
+
if terminators.is_a? Regexp
|
197
|
+
terminators === ch
|
198
|
+
else
|
199
|
+
terminators.include?(ch)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def var_func_parse
|
204
|
+
char = self.peek
|
205
|
+
loop do
|
206
|
+
char = self.grab
|
207
|
+
break if char == LF || char == nil
|
208
|
+
self.escaped if char == Escape
|
209
|
+
self.dollar if char == "$" # Could be $$
|
210
|
+
self.add char
|
211
|
+
end
|
212
|
+
self.add_token(:str)
|
213
|
+
result = self.evaluate
|
214
|
+
result
|
215
|
+
end
|
216
|
+
|
217
|
+
def self.var_func_parse(str)
|
218
|
+
return nil if str.nil?
|
219
|
+
x = self.new(str.chomp)
|
220
|
+
char = x.peek
|
221
|
+
loop do
|
222
|
+
char = x.grab
|
223
|
+
break if char == LF || char == nil
|
224
|
+
x.escaped if char == Escape
|
225
|
+
x.dollar if char == "$" # Could be $$
|
226
|
+
x.add char
|
227
|
+
end
|
228
|
+
x.add_token(:str)
|
229
|
+
result = x.evaluate
|
230
|
+
result
|
231
|
+
end
|
232
|
+
|
233
|
+
def evaluate(tokens = @tokenlist)
|
234
|
+
@out = ""
|
235
|
+
return "" if tokens.empty?
|
236
|
+
gen = tokens.each
|
237
|
+
token = gen.next
|
238
|
+
loop do
|
239
|
+
break if token.nil?
|
240
|
+
sym, val = *token
|
241
|
+
case sym
|
242
|
+
when :str; eval_str(val)
|
243
|
+
when :var; eval_var(val)
|
244
|
+
when :func; eval_func(val, gen)
|
245
|
+
when *BITS; eval_bits(sym, val)
|
246
|
+
else
|
247
|
+
add_token :str
|
248
|
+
end
|
249
|
+
token = gen.next
|
250
|
+
end
|
251
|
+
@out
|
252
|
+
end
|
253
|
+
|
254
|
+
def add(str)
|
255
|
+
@token << str unless str.nil?
|
256
|
+
end
|
257
|
+
|
258
|
+
def add_token(kind, token = @token)
|
259
|
+
return if token.nil?
|
260
|
+
@tokenlist << [kind, token] unless token.empty?
|
261
|
+
@token = Null.dup
|
262
|
+
end
|
263
|
+
|
264
|
+
def grab_alpha
|
265
|
+
str = grab
|
266
|
+
loop do
|
267
|
+
break if eos?
|
268
|
+
break if terminate?(NoAlpha, peek)
|
269
|
+
str << grab
|
270
|
+
end
|
271
|
+
str
|
272
|
+
end
|
273
|
+
|
274
|
+
def grab_alpha_dot
|
275
|
+
str = grab # Null.dup
|
276
|
+
loop do
|
277
|
+
break if eos?
|
278
|
+
break if terminate?(NoAlphaDot, peek)
|
279
|
+
str << grab
|
280
|
+
end
|
281
|
+
str
|
282
|
+
end
|
283
|
+
|
284
|
+
def dollar
|
285
|
+
c1 = grab # $
|
286
|
+
c2 = grab # ...
|
287
|
+
case c2
|
288
|
+
when " "; add_token :str, "$ "
|
289
|
+
when LF, nil; add_token :str, "$"
|
290
|
+
when "$"; double_dollar
|
291
|
+
when "."; dollar_dot
|
292
|
+
when /[A-Za-z]/; add_token(:var, c2 + grab_alpha_dot)
|
293
|
+
else add_token(:str, "$" + c2)
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
def finish_token(str, kind)
|
298
|
+
add str
|
299
|
+
add_token :str
|
300
|
+
grab
|
301
|
+
end
|
302
|
+
|
303
|
+
def marker(char)
|
304
|
+
add_token :str
|
305
|
+
sym = Syms[char]
|
306
|
+
return if embedded?
|
307
|
+
grab
|
308
|
+
case peek
|
309
|
+
when Space; finish_token(char + " ", :str)
|
310
|
+
when LF, nil; finish_token(char, :str)
|
311
|
+
when char; double_marker(char)
|
312
|
+
when LBrack; long_marker(char)
|
313
|
+
else
|
314
|
+
str = peek + collect!(sym, Blank)
|
315
|
+
add str
|
316
|
+
add_token sym, str
|
317
|
+
grab
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
def double_marker(char)
|
322
|
+
sym = Syms[char]
|
323
|
+
kind = sym
|
324
|
+
case lookahead # first char after **
|
325
|
+
when Space, LF, nil
|
326
|
+
pre, post = SimpleFormats[sym]
|
327
|
+
add_token kind
|
328
|
+
else
|
329
|
+
str = collect!(sym, Punc)
|
330
|
+
add_token kind, str
|
331
|
+
grab
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
def long_marker(char)
|
336
|
+
sym = Syms[char]
|
337
|
+
grab # skip left bracket
|
338
|
+
kind = sym # "param_#{sym}".to_sym
|
339
|
+
arg = collect!(sym, Param, true)
|
340
|
+
add_token kind, arg
|
341
|
+
end
|
342
|
+
|
343
|
+
def collect_bracketed(sym, terminators)
|
344
|
+
str = Null.dup # next is not " ","*","["
|
345
|
+
grab # ZZZ
|
346
|
+
loop do
|
347
|
+
if peek == Escape
|
348
|
+
grab
|
349
|
+
str << grab
|
350
|
+
next
|
351
|
+
end
|
352
|
+
if terminate?(terminators, peek)
|
353
|
+
break
|
354
|
+
end
|
355
|
+
str << peek # not a terminator
|
356
|
+
grab
|
357
|
+
end
|
358
|
+
|
359
|
+
if peek == "]" # skip right bracket
|
360
|
+
grab
|
361
|
+
end
|
362
|
+
add str
|
363
|
+
str
|
364
|
+
rescue => err
|
365
|
+
::STDERR.puts "ERR = #{err}\n#{err.backtrace}"
|
366
|
+
end
|
367
|
+
|
368
|
+
def escaped
|
369
|
+
grab # Eat the backslash
|
370
|
+
ch = grab # Take next char
|
371
|
+
ch
|
372
|
+
end
|
373
|
+
|
374
|
+
def collect!(sym, terminators, bracketed=nil)
|
375
|
+
return collect_bracketed(sym, terminators) if bracketed
|
376
|
+
str = Null.dup # next is not " ","*","["
|
377
|
+
grab # ZZZ
|
378
|
+
loop do
|
379
|
+
case
|
380
|
+
when peek.nil?
|
381
|
+
return str
|
382
|
+
when peek == Escape
|
383
|
+
str << escaped
|
384
|
+
next
|
385
|
+
when terminate?(terminators, peek)
|
386
|
+
break
|
387
|
+
else
|
388
|
+
str << peek # not a terminator
|
389
|
+
end
|
390
|
+
grab
|
391
|
+
end
|
392
|
+
ungrab
|
393
|
+
add str
|
394
|
+
str
|
395
|
+
rescue => err
|
396
|
+
::STDERR.puts "ERR = #{err}\n#{err.backtrace}"
|
397
|
+
end
|
398
|
+
|
399
|
+
def varsub(name)
|
400
|
+
live = Livetext.new
|
401
|
+
value = live.vars[name]
|
402
|
+
result = value || "[#{name} is undefined]"
|
403
|
+
result
|
404
|
+
end
|
405
|
+
|
406
|
+
def embedded?
|
407
|
+
! (['"', "'", " ", nil].include? prev)
|
408
|
+
end
|
409
|
+
|
410
|
+
# private
|
411
|
+
|
412
|
+
def eval_bits(sym, val)
|
413
|
+
# api.tty "eb: #{[sym, val].inspect}"
|
414
|
+
val = Livetext.interpolate(val)
|
415
|
+
@out << embed(sym, val)
|
416
|
+
end
|
417
|
+
|
418
|
+
def eval_func(val, gen)
|
419
|
+
param = nil
|
420
|
+
arg = gen.peek rescue :bogus
|
421
|
+
unless arg == :bogus
|
422
|
+
if [:colon, :brackets].include? arg[0]
|
423
|
+
arg = gen.next # for real
|
424
|
+
param = arg[1]
|
425
|
+
# FIXME - unsure - interpolate again??
|
426
|
+
# param = Livetext.interpolate(param)
|
427
|
+
end
|
428
|
+
end
|
429
|
+
str = funcall(val, param)
|
430
|
+
@out << str
|
431
|
+
end
|
432
|
+
|
433
|
+
def eval_var(val)
|
434
|
+
@out << varsub(val)
|
435
|
+
end
|
436
|
+
|
437
|
+
def eval_str(val)
|
438
|
+
@out << val unless val == "\n" # BUG
|
439
|
+
end
|
440
|
+
|
441
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
|
2
|
+
# Class Livetext reopened (top level).
|
3
|
+
|
4
|
+
class Livetext
|
5
|
+
|
6
|
+
include Helpers
|
7
|
+
|
8
|
+
class Variables
|
9
|
+
def initialize(hash = {})
|
10
|
+
@vars = {}
|
11
|
+
hash.each_pair {|k, v| @vars[k.to_sym] = v }
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](var)
|
15
|
+
@vars[var.to_sym]
|
16
|
+
end
|
17
|
+
|
18
|
+
def []=(var, value)
|
19
|
+
@vars[var.to_sym] = value
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
Vars = Variables.new
|
24
|
+
|
25
|
+
TTY = ::File.open("/dev/tty", "w")
|
26
|
+
|
27
|
+
attr_reader :main, :sources
|
28
|
+
attr_accessor :nopass, :nopara
|
29
|
+
attr_accessor :body, :indentation
|
30
|
+
|
31
|
+
class << self
|
32
|
+
attr_accessor :output # bad solution?
|
33
|
+
end
|
34
|
+
|
35
|
+
def vars
|
36
|
+
@_vars
|
37
|
+
end
|
38
|
+
|
39
|
+
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
|
52
|
+
end
|
53
|
+
|
54
|
+
def peek_nextline
|
55
|
+
@main.peek_nextline # delegate
|
56
|
+
end
|
57
|
+
|
58
|
+
def nextline
|
59
|
+
@main.nextline # delegate
|
60
|
+
end
|
61
|
+
|
62
|
+
def sources
|
63
|
+
@main.sources # delegate
|
64
|
+
end
|
65
|
+
|
66
|
+
def save_location
|
67
|
+
@save_location # delegate
|
68
|
+
end
|
69
|
+
|
70
|
+
def save_location=(where)
|
71
|
+
@save_location = where # delegate
|
72
|
+
end
|
73
|
+
|
74
|
+
def dump(file = nil) # not a dot command!
|
75
|
+
file ||= ::STDOUT
|
76
|
+
file.puts @body
|
77
|
+
rescue => err
|
78
|
+
TTY.puts "#dump had an error: #{err.inspect}"
|
79
|
+
end
|
80
|
+
|
81
|
+
def graceful_error(err)
|
82
|
+
dump
|
83
|
+
raise err
|
84
|
+
end
|
85
|
+
|
86
|
+
def customize(mix: [], call: [], vars: {})
|
87
|
+
mix = Array(mix)
|
88
|
+
call = Array(call)
|
89
|
+
mix.each {|lib| mixin(lib) }
|
90
|
+
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) }
|
92
|
+
self
|
93
|
+
end
|
94
|
+
|
95
|
+
def initialize(output = ::STDOUT)
|
96
|
+
@source = nil
|
97
|
+
@_mixins = []
|
98
|
+
@_imports = []
|
99
|
+
@_outdir = "."
|
100
|
+
@no_puts = output.nil?
|
101
|
+
@body = ""
|
102
|
+
@main = Processor.new(self, output)
|
103
|
+
@indentation = [0]
|
104
|
+
@_vars = Livetext::Vars
|
105
|
+
@api = UserAPI.new(self)
|
106
|
+
initial_vars
|
107
|
+
end
|
108
|
+
|
109
|
+
def api
|
110
|
+
@api
|
111
|
+
end
|
112
|
+
|
113
|
+
def initial_vars
|
114
|
+
# Other predefined variables (see also setfile)
|
115
|
+
@api.setvar(:User, `whoami`.chomp)
|
116
|
+
@api.setvar(:Version, Livetext::VERSION)
|
117
|
+
end
|
118
|
+
|
119
|
+
def transform(text)
|
120
|
+
setfile!("(string)")
|
121
|
+
enum = text.each_line
|
122
|
+
front = text.match(/.*?\n/).to_a.first.chomp rescue ""
|
123
|
+
@main.source(enum, "STDIN: '#{front}...'", 0)
|
124
|
+
loop do
|
125
|
+
line = @main.nextline
|
126
|
+
break if line.nil?
|
127
|
+
process_line(line)
|
128
|
+
end
|
129
|
+
result = @body
|
130
|
+
# @body = ""
|
131
|
+
result
|
132
|
+
end
|
133
|
+
|
134
|
+
# EXPERIMENTAL and incomplete
|
135
|
+
def xform(*args, file: nil, text: nil, vars: {})
|
136
|
+
case
|
137
|
+
when file && text.nil?
|
138
|
+
xform_file(file)
|
139
|
+
when file.nil? && text
|
140
|
+
transform(text)
|
141
|
+
when file.nil? && text.nil?
|
142
|
+
raise "Must specify file or text"
|
143
|
+
when file && text
|
144
|
+
raise "Cannot specify file and text"
|
145
|
+
end
|
146
|
+
self.process_file(file)
|
147
|
+
self.body
|
148
|
+
end
|
149
|
+
|
150
|
+
def xform_file(file, vars: nil)
|
151
|
+
Livetext::Vars.replace(vars) unless vars.nil?
|
152
|
+
@_vars.replace(vars) unless vars.nil?
|
153
|
+
self.process_file(file)
|
154
|
+
self.body
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
|
data/lib/livetext/processor.rb
CHANGED
data/lib/livetext/skeleton.rb
CHANGED
data/lib/livetext/standard.rb
CHANGED
@@ -25,13 +25,13 @@ module Livetext::Standard
|
|
25
25
|
|
26
26
|
attr_reader :data
|
27
27
|
|
28
|
-
def data=(val) # FIXME this is weird, let's remove it soonish
|
29
|
-
|
30
|
-
|
28
|
+
def data=(val) # FIXME this is weird, let's remove it soonish and why are there two???
|
29
|
+
# api.tty ">>>> in #{__FILE__}: api id = #{api.object_id}"
|
30
|
+
val = val.chomp
|
31
|
+
api.data = val
|
32
|
+
api.args = format(val).split rescue []
|
31
33
|
@mixins = []
|
32
34
|
@imports = []
|
33
|
-
###
|
34
|
-
# api.data = val
|
35
35
|
end
|
36
36
|
|
37
37
|
# dumb name - bold, italic, teletype, striketrough
|
@@ -143,10 +143,14 @@ module Livetext::Standard
|
|
143
143
|
end
|
144
144
|
|
145
145
|
def dot_def(args = nil, body = nil)
|
146
|
+
# api.tty "in #{__FILE__}: api id = #{api.inspect}"
|
146
147
|
name = api.args[0]
|
147
|
-
|
148
|
+
# api.tty :dd1
|
149
|
+
# api.tty name.inspect
|
148
150
|
check_disallowed(name)
|
151
|
+
# api.tty :dd2
|
149
152
|
# Difficult to avoid eval here
|
153
|
+
str = "def #{name}\n"
|
150
154
|
str << api.body(true).join("\n")
|
151
155
|
str << "\nend\n"
|
152
156
|
eval str
|
@@ -172,7 +176,7 @@ module Livetext::Standard
|
|
172
176
|
else
|
173
177
|
lines = api.body
|
174
178
|
end
|
175
|
-
pairs = Livetext::ParseGeneral.parse_vars(
|
179
|
+
pairs = Livetext::ParseGeneral.parse_vars(lines, prefix: nil)
|
176
180
|
set_variables(pairs)
|
177
181
|
api.optional_blank_line
|
178
182
|
end
|
@@ -187,7 +191,7 @@ module Livetext::Standard
|
|
187
191
|
else
|
188
192
|
lines = api.body
|
189
193
|
end
|
190
|
-
pairs = Livetext::ParseGeneral.parse_vars(
|
194
|
+
pairs = Livetext::ParseGeneral.parse_vars(lines, prefix: nil)
|
191
195
|
set_variables(pairs)
|
192
196
|
api.optional_blank_line
|
193
197
|
end
|