livetext 0.8.77 → 0.8.78
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/lib/SAVE.formatline +297 -0
- data/lib/SAVE2.formatline.rb +707 -0
- data/lib/formatline.rb +282 -257
- data/lib/livetext.rb +4 -3
- data/lib/processor.rb +1 -1
- data/lib/standard.rb +5 -2
- data/lib/userapi.rb +8 -5
- data/test/data/SAVE.lines +284 -0
- data/test/data/basic_formatting/expected-output.txt +1 -1
- data/test/data/error_invalid_name/expected-output.txt +0 -1
- data/test/data/error_missing_end/expected-output.txt +0 -1
- data/test/data/example_alpha/expected-output.txt +3 -3
- data/test/data/example_alpha/source.lt3 +1 -1
- data/test/data/example_alpha2/expected-output.txt +3 -3
- data/test/data/example_alpha2/source.lt3 +2 -2
- data/test/data/lines.txt +6 -190
- data/test/data/simple_mixin/expected-output.txt +3 -0
- data/test/data/simple_mixin/simple_mixin.rb +1 -1
- data/test/data/simple_mixin/source.lt3 +1 -1
- data/test/data/subset.txt +0 -0
- data/test/test.rb +31 -14
- metadata +6 -2
data/lib/formatline.rb
CHANGED
|
@@ -1,297 +1,322 @@
|
|
|
1
1
|
class FormatLine
|
|
2
|
-
|
|
3
|
-
EOL = :eol
|
|
4
|
-
Alpha = /[a-z]/
|
|
5
|
-
Alpha2 = /[a-z0-9_]/
|
|
6
|
-
Other = Object
|
|
7
|
-
|
|
8
2
|
SimpleFormats = {}
|
|
9
3
|
SimpleFormats[:b] = %w[<b> </b>]
|
|
10
4
|
SimpleFormats[:i] = %w[<i> </i>]
|
|
11
5
|
SimpleFormats[:t] = ["<font size=+1><tt>", "</tt></font>"]
|
|
12
6
|
SimpleFormats[:s] = %w[<strike> </strike>]
|
|
7
|
+
|
|
8
|
+
Null = ""
|
|
9
|
+
Space = " "
|
|
10
|
+
Alpha = /[A-Za-z]/
|
|
11
|
+
AlNum = /[A-Za-z0-9_]/
|
|
12
|
+
LF = "\n"
|
|
13
|
+
LBrack = "["
|
|
14
|
+
|
|
15
|
+
Blank = [" ", nil, "\n"]
|
|
16
|
+
Punc = [")", ",", ".", " ", "\n"]
|
|
17
|
+
NoAlpha = /[^A-Za-z0-9_]/
|
|
18
|
+
Param = ["]", "\n", nil]
|
|
19
|
+
Escape = "\\" # not an ESC char
|
|
13
20
|
|
|
14
|
-
def
|
|
15
|
-
|
|
21
|
+
def terminate?(terminators, ch)
|
|
22
|
+
if terminators.is_a? Regexp
|
|
23
|
+
terminators === ch
|
|
24
|
+
else
|
|
25
|
+
terminators.include?(ch)
|
|
26
|
+
end
|
|
16
27
|
end
|
|
17
28
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
29
|
+
attr_reader :out
|
|
30
|
+
|
|
31
|
+
def initialize(line, context)
|
|
32
|
+
context ||= binding
|
|
33
|
+
@context = context
|
|
34
|
+
@line = line
|
|
35
|
+
@i = -1
|
|
36
|
+
@token = Null.dup
|
|
37
|
+
@tokenlist = []
|
|
22
38
|
end
|
|
23
39
|
|
|
24
|
-
def
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
40
|
+
def self.parse!(line, context = nil)
|
|
41
|
+
x = self.new(line.chomp, context)
|
|
42
|
+
x.tokenize(line)
|
|
43
|
+
x.evaluate # (context)
|
|
28
44
|
end
|
|
29
45
|
|
|
30
|
-
def
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
46
|
+
def tokenize(line)
|
|
47
|
+
grab
|
|
48
|
+
loop do
|
|
49
|
+
case curr
|
|
50
|
+
when Escape; go; add curr; grab
|
|
51
|
+
when "$"
|
|
52
|
+
_dollar
|
|
53
|
+
when "*", "_", "`", "~"
|
|
54
|
+
marker curr
|
|
55
|
+
add curr
|
|
56
|
+
when LF, nil
|
|
57
|
+
break
|
|
58
|
+
else
|
|
59
|
+
add curr
|
|
60
|
+
end
|
|
61
|
+
grab
|
|
62
|
+
end
|
|
63
|
+
add_token(:str)
|
|
64
|
+
@tokenlist
|
|
35
65
|
end
|
|
36
66
|
|
|
37
|
-
def
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
rescue StopIteration
|
|
41
|
-
EOL
|
|
67
|
+
def embed(sym, str)
|
|
68
|
+
pre, post = SimpleFormats[sym]
|
|
69
|
+
pre + str + post
|
|
42
70
|
end
|
|
43
71
|
|
|
44
|
-
def
|
|
45
|
-
@
|
|
72
|
+
def evaluate(tokens = @tokenlist)
|
|
73
|
+
@out = ""
|
|
74
|
+
return "" if tokens.empty?
|
|
75
|
+
gen = tokens.each
|
|
76
|
+
token = gen.next
|
|
77
|
+
loop do
|
|
78
|
+
break if token.nil?
|
|
79
|
+
sym, val = *token
|
|
80
|
+
case sym
|
|
81
|
+
when :str
|
|
82
|
+
@out << val unless val == "\n" # BUG
|
|
83
|
+
when :var
|
|
84
|
+
@out << varsub(val)
|
|
85
|
+
when :func
|
|
86
|
+
param = nil
|
|
87
|
+
arg = gen.peek
|
|
88
|
+
if [:colon, :brackets].include? arg[0]
|
|
89
|
+
arg = gen.next # for real
|
|
90
|
+
param = arg[1]
|
|
91
|
+
end
|
|
92
|
+
@out << funcall(val, param)
|
|
93
|
+
when :b, :i, :t, :s
|
|
94
|
+
@out << embed(sym, val)
|
|
95
|
+
else
|
|
96
|
+
add_token :str
|
|
97
|
+
end
|
|
98
|
+
token = gen.next
|
|
99
|
+
end
|
|
100
|
+
@out
|
|
46
101
|
end
|
|
47
102
|
|
|
48
|
-
def
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
103
|
+
def curr
|
|
104
|
+
@line[@i]
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def prev
|
|
108
|
+
@line[@i-1]
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def next!
|
|
112
|
+
@line[@i+1]
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def grab
|
|
116
|
+
@line[@i+=1]
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def grab_colon_param
|
|
120
|
+
grab # grab :
|
|
121
|
+
param = ""
|
|
122
|
+
loop do
|
|
123
|
+
case next!
|
|
124
|
+
when Escape
|
|
125
|
+
grab
|
|
126
|
+
param << next!
|
|
127
|
+
grab
|
|
128
|
+
when Space, LF, nil; break
|
|
129
|
+
else
|
|
130
|
+
param << next!
|
|
131
|
+
grab
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
param = nil if param.empty?
|
|
136
|
+
param
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def grab_func_param
|
|
140
|
+
grab # [
|
|
141
|
+
param = ""
|
|
142
|
+
loop do
|
|
143
|
+
case next!
|
|
144
|
+
when Escape
|
|
145
|
+
grab
|
|
146
|
+
param << next!
|
|
147
|
+
grab
|
|
148
|
+
when "]", LF, nil; break
|
|
149
|
+
else
|
|
150
|
+
param << next!
|
|
151
|
+
grab
|
|
152
|
+
end
|
|
56
153
|
end
|
|
154
|
+
|
|
155
|
+
add curr
|
|
156
|
+
grab
|
|
157
|
+
param = nil if param.empty?
|
|
158
|
+
param
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def add(str)
|
|
162
|
+
@token << str unless str.nil?
|
|
57
163
|
end
|
|
58
164
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
165
|
+
Syms = { "*" => :b, "_" => :i, "`" => :t, "~" => :s }
|
|
166
|
+
|
|
167
|
+
def add_token(kind, token = @token)
|
|
168
|
+
@tokenlist << [kind, token] unless token.empty?
|
|
169
|
+
@token = Null.dup
|
|
62
170
|
end
|
|
63
171
|
|
|
64
|
-
def
|
|
65
|
-
|
|
66
|
-
|
|
172
|
+
def grab_alpha
|
|
173
|
+
str = Null.dup
|
|
174
|
+
grab
|
|
175
|
+
loop do
|
|
176
|
+
break if curr.nil?
|
|
177
|
+
str << curr
|
|
178
|
+
break if terminate?(NoAlpha, next!)
|
|
179
|
+
grab
|
|
180
|
+
end
|
|
181
|
+
str
|
|
67
182
|
end
|
|
68
183
|
|
|
69
|
-
|
|
70
|
-
|
|
184
|
+
def _dollar
|
|
185
|
+
grab
|
|
186
|
+
case curr
|
|
187
|
+
when LF; add "$"; add_token :str
|
|
188
|
+
when " "; add "$ "; add_token :str
|
|
189
|
+
when nil; add "$"; add_token :str
|
|
190
|
+
when "$"; _double_dollar
|
|
191
|
+
when "."; _dollar_dot
|
|
192
|
+
when /[A-Za-z]/
|
|
193
|
+
add_token :str
|
|
194
|
+
var = curr + grab_alpha
|
|
195
|
+
add_token(:var, var)
|
|
196
|
+
else
|
|
197
|
+
add "$" + curr
|
|
198
|
+
add_token(:string)
|
|
199
|
+
end
|
|
200
|
+
end
|
|
71
201
|
|
|
72
|
-
def
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
202
|
+
def _double_dollar
|
|
203
|
+
case next!
|
|
204
|
+
when Space; add_token :string, "$$ "; grab; return
|
|
205
|
+
when LF, nil; add "$$"; add_token :str
|
|
206
|
+
when Alpha
|
|
207
|
+
add_token(:str, @token)
|
|
208
|
+
func = grab_alpha
|
|
209
|
+
add_token(:func, func)
|
|
210
|
+
case next!
|
|
211
|
+
when ":"; param = grab_colon_param; add_token(:colon, param)
|
|
212
|
+
when "["; param = grab_func_param; add_token(:brackets, param)
|
|
213
|
+
else # do nothing
|
|
214
|
+
end
|
|
215
|
+
else
|
|
216
|
+
grab; add_token :str, "$$" + curr; return
|
|
217
|
+
end
|
|
76
218
|
end
|
|
77
219
|
|
|
78
|
-
def
|
|
79
|
-
|
|
80
|
-
@buffer << "#{d0}#@substr#{d1}"
|
|
81
|
-
@substr = ""
|
|
220
|
+
def dollar_dot
|
|
221
|
+
add_token :ddot, @line[@i..-1]
|
|
82
222
|
end
|
|
83
223
|
|
|
84
|
-
def
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
224
|
+
def marker(char)
|
|
225
|
+
add_token :str
|
|
226
|
+
sym = Syms[char]
|
|
227
|
+
if embedded?
|
|
228
|
+
add char # ??? add_token "*", :string
|
|
229
|
+
return
|
|
230
|
+
end
|
|
231
|
+
grab
|
|
232
|
+
case curr
|
|
233
|
+
when Space
|
|
234
|
+
add char + " "
|
|
235
|
+
add_token :str
|
|
236
|
+
grab
|
|
237
|
+
when LF, nil
|
|
238
|
+
add char
|
|
239
|
+
add_token :str
|
|
240
|
+
when char; double_marker(char)
|
|
241
|
+
when LBrack; long_marker(char)
|
|
242
|
+
else
|
|
243
|
+
add curr
|
|
244
|
+
str = collect!(sym, Blank)
|
|
245
|
+
add_token sym, str
|
|
246
|
+
add curr # next char onto next token...
|
|
247
|
+
end
|
|
88
248
|
end
|
|
89
249
|
|
|
90
|
-
def
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
250
|
+
def double_marker(char)
|
|
251
|
+
sym = Syms[char]
|
|
252
|
+
grab
|
|
253
|
+
kind = sym # "string_#{char}".to_sym
|
|
254
|
+
case next! # first char after **
|
|
255
|
+
when Space, LF, nil
|
|
256
|
+
pre, post = SimpleFormats[sym]
|
|
257
|
+
add_token kind
|
|
258
|
+
else
|
|
259
|
+
str = collect!(sym, Punc)
|
|
260
|
+
grab unless next!.nil?
|
|
261
|
+
add_token kind, str
|
|
262
|
+
end
|
|
94
263
|
end
|
|
95
264
|
|
|
96
|
-
def
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
char = skip
|
|
113
|
-
case char
|
|
114
|
-
when "$", "*", "_", "`", "~"
|
|
115
|
-
emit(char)
|
|
116
|
-
skip
|
|
117
|
-
when " "
|
|
118
|
-
emit("\\ ")
|
|
119
|
-
skip
|
|
120
|
-
when EOL
|
|
121
|
-
emit("\\")
|
|
122
|
-
break
|
|
123
|
-
when Other
|
|
124
|
-
emit("\\") # logic??
|
|
125
|
-
end
|
|
126
|
-
when EOL
|
|
127
|
-
break
|
|
128
|
-
when "$" # var or func or $
|
|
129
|
-
case skip
|
|
130
|
-
when EOL
|
|
131
|
-
emit("$")
|
|
132
|
-
break
|
|
133
|
-
when Alpha
|
|
134
|
-
loop { ch = peek; break if ch == EOL; @vname << grab; break unless Alpha2 === peek }
|
|
135
|
-
vsub
|
|
136
|
-
when "$"
|
|
137
|
-
case skip
|
|
138
|
-
when EOL
|
|
139
|
-
emit("$$")
|
|
140
|
-
break
|
|
141
|
-
when Alpha
|
|
142
|
-
loop { ch = peek; break if ch == EOL; @fname << grab; break unless Alpha2 === peek }
|
|
143
|
-
case peek
|
|
144
|
-
when " " # no param - just call
|
|
145
|
-
@param = nil
|
|
146
|
-
fcall # no param? Hmm
|
|
147
|
-
when "[" # long param
|
|
148
|
-
skip
|
|
149
|
-
loop do
|
|
150
|
-
if peek == "\\"
|
|
151
|
-
skip
|
|
152
|
-
@param << grab
|
|
153
|
-
end
|
|
154
|
-
break if ["]", EOL].include?(peek)
|
|
155
|
-
@param << grab
|
|
156
|
-
end
|
|
157
|
-
skip
|
|
158
|
-
fcall
|
|
159
|
-
when ":" # param (single token or to-eol)
|
|
160
|
-
case skip
|
|
161
|
-
when ":" # param to eol
|
|
162
|
-
skip
|
|
163
|
-
loop { break if peek == EOL; @param << grab }
|
|
164
|
-
when Other # grab until space or eol
|
|
165
|
-
loop { @param << grab; break if [" ", EOL].include?(peek) }
|
|
166
|
-
fcall
|
|
167
|
-
end
|
|
168
|
-
when Other # no param - just call
|
|
169
|
-
fcall
|
|
170
|
-
end
|
|
171
|
-
when Other
|
|
172
|
-
emit "$$"
|
|
173
|
-
end
|
|
174
|
-
when Other
|
|
175
|
-
emit "$"
|
|
176
|
-
end
|
|
177
|
-
when "*"
|
|
178
|
-
case skip
|
|
179
|
-
when EOL
|
|
180
|
-
emit "*"
|
|
181
|
-
when " "
|
|
182
|
-
emit "*"
|
|
183
|
-
when "["
|
|
184
|
-
skip
|
|
185
|
-
loop do
|
|
186
|
-
if peek == "\\"
|
|
187
|
-
skip
|
|
188
|
-
@substr << grab
|
|
189
|
-
next
|
|
190
|
-
end
|
|
191
|
-
break if ["]", EOL].include?(peek)
|
|
192
|
-
@substr << grab
|
|
193
|
-
end
|
|
194
|
-
skip
|
|
195
|
-
bold
|
|
196
|
-
when Other
|
|
197
|
-
loop { @substr << grab; break if [" ", EOL].include?(peek) }
|
|
198
|
-
bold
|
|
199
|
-
end
|
|
200
|
-
when "_"
|
|
201
|
-
case skip
|
|
202
|
-
when EOL
|
|
203
|
-
emit "_"
|
|
204
|
-
when " "
|
|
205
|
-
emit "_"
|
|
206
|
-
when "["
|
|
207
|
-
skip
|
|
208
|
-
loop do
|
|
209
|
-
if peek == "\\"
|
|
210
|
-
skip
|
|
211
|
-
@substr << grab
|
|
212
|
-
next
|
|
213
|
-
end
|
|
214
|
-
break if ["]", EOL].include?(peek)
|
|
215
|
-
@substr << grab
|
|
216
|
-
end
|
|
217
|
-
skip
|
|
218
|
-
italics
|
|
219
|
-
when "_" # doubled...
|
|
220
|
-
skip
|
|
221
|
-
loop do
|
|
222
|
-
if peek == "\\"
|
|
223
|
-
skip
|
|
224
|
-
@substr << grab
|
|
225
|
-
next
|
|
226
|
-
end
|
|
227
|
-
break if [".", ",", ")", EOL].include?(peek)
|
|
228
|
-
@substr << grab
|
|
229
|
-
end
|
|
230
|
-
italics
|
|
231
|
-
when Other
|
|
232
|
-
loop { @substr << grab; break if [" ", EOL].include?(peek) }
|
|
233
|
-
italics
|
|
234
|
-
end
|
|
235
|
-
when "`"
|
|
236
|
-
case skip
|
|
237
|
-
when EOL
|
|
238
|
-
emit "`"
|
|
239
|
-
when " "
|
|
240
|
-
emit "`"
|
|
241
|
-
when "["
|
|
242
|
-
skip
|
|
243
|
-
loop do
|
|
244
|
-
if peek == "\\"
|
|
245
|
-
skip
|
|
246
|
-
@substr << grab
|
|
247
|
-
next
|
|
248
|
-
end
|
|
249
|
-
break if ["]", EOL].include?(peek)
|
|
250
|
-
@substr << grab
|
|
251
|
-
end
|
|
252
|
-
skip
|
|
253
|
-
ttype
|
|
254
|
-
when "`" # doubled...
|
|
255
|
-
skip
|
|
256
|
-
loop { break if [".", ",", ")", EOL].include?(peek); @substr << grab } # ";" ?? FIXME
|
|
257
|
-
ttype
|
|
258
|
-
when Other
|
|
259
|
-
loop { @substr << grab; break if [" ", EOL].include?(peek) }
|
|
260
|
-
ttype
|
|
261
|
-
end
|
|
262
|
-
when "~"
|
|
263
|
-
case skip
|
|
264
|
-
when EOL
|
|
265
|
-
emit "~"
|
|
266
|
-
when " "
|
|
267
|
-
emit "~"
|
|
268
|
-
when "["
|
|
269
|
-
skip
|
|
270
|
-
loop do
|
|
271
|
-
if peek == "\\"
|
|
272
|
-
skip
|
|
273
|
-
@substr << grab
|
|
274
|
-
next
|
|
275
|
-
end
|
|
276
|
-
break if ["]", EOL].include?(peek)
|
|
277
|
-
@substr << grab
|
|
278
|
-
end
|
|
279
|
-
skip
|
|
280
|
-
strike
|
|
281
|
-
when "~" # doubled...
|
|
282
|
-
skip
|
|
283
|
-
loop { break if [".", ",", ")", EOL].include?(peek); @substr << grab } # ";" ?? FIXME
|
|
284
|
-
strike
|
|
285
|
-
when Other
|
|
286
|
-
loop { @substr << grab; break if [" ", EOL].include?(peek) }
|
|
287
|
-
strike
|
|
288
|
-
end
|
|
289
|
-
when Other
|
|
290
|
-
keep
|
|
265
|
+
def long_marker(char)
|
|
266
|
+
sym = Syms[char]
|
|
267
|
+
# grab # skip left bracket
|
|
268
|
+
kind = sym # "param_#{sym}".to_sym
|
|
269
|
+
arg = collect!(sym, Param, true)
|
|
270
|
+
add_token kind, arg
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
def collect!(sym, terminators, param=false)
|
|
274
|
+
str = Null.dup # next is not " ","*","["
|
|
275
|
+
grab
|
|
276
|
+
loop do
|
|
277
|
+
if curr == Escape
|
|
278
|
+
str << grab # ch = escaped char
|
|
279
|
+
grab
|
|
280
|
+
next
|
|
291
281
|
end
|
|
282
|
+
break if terminate?(terminators, curr)
|
|
283
|
+
str << curr # not a terminator
|
|
284
|
+
grab
|
|
292
285
|
end
|
|
286
|
+
grab if param && curr == "]" # skip right bracket
|
|
287
|
+
add str
|
|
288
|
+
end
|
|
293
289
|
|
|
294
|
-
|
|
290
|
+
############
|
|
291
|
+
|
|
292
|
+
### From FormatLine:
|
|
293
|
+
|
|
294
|
+
def funcall(name, param)
|
|
295
|
+
result =
|
|
296
|
+
if self.respond_to?("func_" + name.to_s)
|
|
297
|
+
self.send("func_" + name.to_s, param)
|
|
298
|
+
else
|
|
299
|
+
fobj = ::Livetext::Functions.new
|
|
300
|
+
::Livetext::Functions.param = param # is this
|
|
301
|
+
::Livetext::Functions.context = @context # screwed up???
|
|
302
|
+
fobj.send(name)
|
|
303
|
+
end
|
|
304
|
+
result
|
|
295
305
|
end
|
|
296
|
-
end
|
|
297
306
|
|
|
307
|
+
def varsub(name)
|
|
308
|
+
result = Livetext::Vars[name]
|
|
309
|
+
result
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
#####
|
|
313
|
+
|
|
314
|
+
def showme(tag)
|
|
315
|
+
char = @line[@cc]
|
|
316
|
+
puts "--- #{tag}: ch=#{@ch.inspect} next=#{@next.inspect} (cc=#@cc:#{char.inspect}) out=#{@out.inspect}"
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
def embedded?
|
|
320
|
+
! (['"', "'", " ", nil].include? prev)
|
|
321
|
+
end
|
|
322
|
+
end
|