livetext 0.9.23 → 0.9.26
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.lt3 +6 -6
- data/bin/livetext +57 -40
- data/imports/bookish.rb +81 -81
- data/imports/calibre.rb +3 -3
- data/imports/livemagick.rb +17 -17
- data/imports/markdown.rb +10 -10
- data/imports/pyggish.rb +13 -13
- data/imports/tutorial.rb +15 -15
- data/lib/cmdargs.rb +7 -4
- data/lib/{errors.rb → livetext/errors.rb} +4 -3
- data/lib/{formatline.rb → livetext/formatline.rb} +119 -18
- data/lib/livetext/funcall.rb +168 -0
- data/lib/{functions.rb → livetext/functions.rb} +0 -2
- data/lib/{global_helpers.rb → livetext/global_helpers.rb} +6 -3
- data/lib/{handler → livetext/handler}/import.rb +5 -9
- data/lib/livetext/handler/mixin.rb +33 -0
- data/lib/{handler.rb → livetext/handler.rb} +1 -1
- data/lib/{helpers.rb → livetext/helpers.rb} +78 -66
- data/lib/{html.rb → livetext/html.rb} +2 -3
- data/lib/livetext/lineparser.rb +441 -0
- data/lib/livetext/more.rb +158 -0
- data/lib/{parser → livetext/parser}/general.rb +0 -0
- data/lib/{parser → livetext/parser}/set.rb +0 -0
- data/lib/{parser → livetext/parser}/string.rb +0 -0
- data/lib/{parser.rb → livetext/parser.rb} +0 -3
- data/lib/{parsing.rb → livetext/parsing.rb} +0 -2
- data/lib/livetext/paths.rb +13 -0
- data/lib/{processor.rb → livetext/processor.rb} +18 -8
- data/lib/livetext/reopen.rb +12 -0
- data/lib/livetext/skeleton.rb +22 -0
- data/lib/{standard.rb → livetext/standard.rb} +150 -127
- data/lib/livetext/userapi.rb +170 -0
- data/lib/livetext/version.rb +6 -0
- data/lib/livetext.rb +14 -152
- data/plugin/bookish.rb +82 -81
- data/plugin/calibre.rb +3 -3
- data/plugin/livemagick.rb +17 -17
- data/plugin/markdown.rb +10 -10
- data/plugin/pyggish.rb +118 -118
- data/plugin/tutorial.rb +15 -15
- data/test/all.rb +6 -0
- data/test/snapshots/{error_inc_line_num → 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/def_method/expected-output.txt +2 -0
- data/test/snapshots/def_method/source.lt3 +4 -2
- data/test/snapshots/error_inc_line_num/{OUT → README.txt} +11 -8
- data/test/snapshots/error_inc_line_num/expected-output.txt +0 -6
- data/test/snapshots/error_inc_line_num/match-error.txt +1 -1
- data/test/snapshots/error_invalid_name/foo +5 -0
- data/test/snapshots/error_line_num/match-error.txt +1 -1
- data/test/snapshots/error_missing_end/expected-output.txt +0 -1
- data/test/snapshots/error_name_not_permitted/expected-output.txt +4 -0
- data/test/snapshots/error_name_not_permitted/match-error.txt +1 -1
- data/test/snapshots/error_no_such_copy/expected-output.txt +1 -0
- data/test/snapshots/error_no_such_mixin/expected-output.txt +1 -0
- data/test/snapshots/error_no_such_mixin/match-error.txt +1 -1
- data/test/snapshots/error_no_such_mixin/source.lt3 +1 -1
- data/test/snapshots/example_alpha/source.lt3 +2 -2
- data/test/snapshots/example_alpha2/expected-output.txt +0 -2
- data/test/snapshots/example_alpha2/source.lt3 +5 -4
- data/test/snapshots/import/expected-output.txt +2 -1
- data/test/snapshots/import/match-error.txt +1 -1
- data/test/snapshots/import/simple_import.rb +1 -1
- data/test/snapshots/import2/simple_import.rb +1 -1
- data/test/snapshots/import_bookish/expected-output.txt +4 -4
- data/test/snapshots/{error_invalid_name/actual-output.txt → 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/raw_lines/expected-output.txt +0 -2
- data/test/snapshots/simple_import/simple_import.rb +1 -1
- data/test/snapshots/simple_mixin/simple_mixin.rb +1 -1
- data/test/snapshots/{error_missing_end/actual-output.txt → 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/single_raw_line/expected-output.txt +0 -2
- data/test/snapshots/subset.txt +9 -7
- data/test/snapshots/{error_no_such_copy/actual-output.txt → 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/{error_no_such_inc/actual-output.txt → 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/snapshots.rb +16 -7
- data/test/unit/all.rb +3 -1
- data/test/unit/formatline.rb +145 -276
- data/test/unit/html.rb +1 -2
- data/test/unit/lineparser.rb +650 -0
- data/test/unit/parser/set.rb +13 -12
- data/test/unit/standard.rb +0 -1
- data/test/unit/tokenizer.rb +534 -0
- metadata +49 -39
- data/lib/funcall.rb +0 -93
- data/lib/parser/file.rb +0 -6
- data/lib/parser/mixin.rb +0 -34
- data/lib/userapi.rb +0 -164
- data/test/snapshots/error_inc_line_num/actual-output.txt +0 -17
- data/test/snapshots/error_invalid_name/actual-error.txt +0 -10
- data/test/snapshots/error_invalid_name/out-sdiff.txt +0 -6
- data/test/snapshots/error_missing_end/actual-error.txt +0 -10
- data/test/snapshots/error_missing_end/out-sdiff.txt +0 -6
- data/test/snapshots/error_no_such_copy/actual-error.txt +0 -10
- data/test/snapshots/error_no_such_copy/out-sdiff.txt +0 -5
- data/test/snapshots/error_no_such_inc/actual-error.txt +0 -10
- data/test/snapshots/error_no_such_inc/out-sdiff.txt +0 -6
- data/test/snapshots/error_no_such_mixin/actual-error.txt +0 -13
- data/test/snapshots/error_no_such_mixin/actual-output.txt +0 -0
- data/test/snapshots/error_no_such_mixin/out-sdiff.txt +0 -6
@@ -1,10 +1,8 @@
|
|
1
|
-
# p __FILE__
|
2
1
|
|
3
2
|
require 'pathname' # For _seek - remove later??
|
4
3
|
|
5
4
|
require_relative 'parser' # nested requires
|
6
5
|
require_relative 'html'
|
7
|
-
require_relative 'global_helpers'
|
8
6
|
require_relative 'helpers'
|
9
7
|
|
10
8
|
make_exception(:ExpectedOnOff, "Error: expected 'on' or 'off'")
|
@@ -25,322 +23,343 @@ module Livetext::Standard
|
|
25
23
|
t: ["<font size=+1><tt>", "</tt></font>"],
|
26
24
|
s: %w[<strike> </strike>] }
|
27
25
|
|
28
|
-
attr_reader :
|
26
|
+
attr_reader :data
|
29
27
|
|
30
|
-
def data=(val) # FIXME this is weird, let's remove it soonish
|
31
|
-
|
32
|
-
|
33
|
-
|
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 []
|
33
|
+
@mixins = []
|
34
|
+
@imports = []
|
34
35
|
end
|
35
36
|
|
36
37
|
# dumb name - bold, italic, teletype, striketrough
|
37
|
-
|
38
|
-
|
38
|
+
|
39
|
+
def bits(args = nil, body = nil) # FIXME umm what is this?
|
40
|
+
b0, b1, i0, i1, t0, t1, s0, s1 = *api.args
|
39
41
|
SimpleFormats[:b] = [b0, b1]
|
40
42
|
SimpleFormats[:i] = [i0, i1]
|
41
43
|
SimpleFormats[:t] = [t0, t1]
|
42
44
|
SimpleFormats[:s] = [s0, s1]
|
45
|
+
api.optional_blank_line
|
43
46
|
end
|
44
47
|
|
45
48
|
def backtrace(args = nil, body = nil)
|
46
|
-
@backtrace = onoff(
|
47
|
-
|
49
|
+
@backtrace = onoff(api.args.first)
|
50
|
+
api.optional_blank_line
|
48
51
|
end
|
49
52
|
|
50
53
|
def comment(args = nil, body = nil)
|
51
|
-
|
52
|
-
|
54
|
+
api.body
|
55
|
+
api.optional_blank_line
|
53
56
|
end
|
54
57
|
|
55
58
|
def shell(args = nil, body = nil)
|
56
|
-
cmd =
|
59
|
+
cmd = api.data
|
57
60
|
system(cmd)
|
58
|
-
|
61
|
+
api.optional_blank_line
|
59
62
|
end
|
60
63
|
|
61
64
|
def func(args = nil, body = nil)
|
62
|
-
funcname =
|
65
|
+
funcname = api.args[0]
|
63
66
|
check_disallowed(funcname)
|
64
67
|
func_def = <<~EOS
|
65
68
|
def #{funcname}(param)
|
66
|
-
#{
|
69
|
+
#{api.body.to_a.join("\n")}
|
67
70
|
end
|
68
71
|
EOS
|
69
|
-
|
72
|
+
api.optional_blank_line
|
70
73
|
Livetext::Functions.class_eval func_def
|
74
|
+
return true
|
71
75
|
end
|
72
76
|
|
73
|
-
def h1(args = nil, body = nil);
|
74
|
-
def h2(args = nil, body = nil);
|
75
|
-
def h3(args = nil, body = nil);
|
76
|
-
def h4(args = nil, body = nil);
|
77
|
-
def h5(args = nil, body = nil);
|
78
|
-
def h6(args = nil, body = nil);
|
77
|
+
def h1(args = nil, body = nil); api.out wrapped(api.data, :h1); return true; end
|
78
|
+
def h2(args = nil, body = nil); api.out wrapped(api.data, :h2); return true; end
|
79
|
+
def h3(args = nil, body = nil); api.out wrapped(api.data, :h3); return true; end
|
80
|
+
def h4(args = nil, body = nil); api.out wrapped(api.data, :h4); return true; end
|
81
|
+
def h5(args = nil, body = nil); api.out wrapped(api.data, :h5); return true; end
|
82
|
+
def h6(args = nil, body = nil); api.out wrapped(api.data, :h6); return true; end
|
79
83
|
|
80
84
|
def list(args = nil, body = nil)
|
81
85
|
wrap :ul do
|
82
|
-
|
86
|
+
api.body {|line| api.out wrapped(line, :li) }
|
83
87
|
end
|
84
|
-
|
88
|
+
api.optional_blank_line
|
85
89
|
end
|
86
90
|
|
87
91
|
def list!(args = nil, body = nil)
|
88
92
|
wrap(:ul) do
|
89
|
-
lines =
|
93
|
+
lines = api.body.each # enumerator
|
90
94
|
loop do
|
91
95
|
line = lines.next
|
92
|
-
line =
|
96
|
+
line = api.format(line)
|
93
97
|
str = line[0] == " " ? line : wrapped(line, :li)
|
94
|
-
|
98
|
+
api.out str
|
95
99
|
end
|
96
100
|
end
|
97
|
-
|
101
|
+
api.optional_blank_line
|
98
102
|
end
|
99
103
|
|
100
104
|
def shell!(args = nil, body = nil)
|
101
|
-
cmd =
|
105
|
+
cmd = api.data
|
102
106
|
system(cmd)
|
103
|
-
|
107
|
+
api.optional_blank_line
|
104
108
|
end
|
105
109
|
|
106
110
|
def errout(args = nil, body = nil)
|
107
|
-
::STDERR.puts
|
108
|
-
|
111
|
+
::STDERR.puts api.data
|
112
|
+
api.optional_blank_line
|
109
113
|
end
|
110
114
|
|
111
115
|
def ttyout(args = nil, body = nil)
|
112
|
-
TTY.puts
|
113
|
-
|
116
|
+
TTY.puts api.data
|
117
|
+
api.optional_blank_line
|
114
118
|
end
|
115
119
|
|
116
120
|
def say(args = nil, body = nil)
|
117
|
-
str =
|
121
|
+
str = api.format(api.data)
|
118
122
|
TTY.puts str
|
119
|
-
|
123
|
+
api.optional_blank_line
|
120
124
|
end
|
121
125
|
|
122
126
|
def banner(args = nil, body = nil)
|
123
|
-
str =
|
127
|
+
str = api.format(api.data)
|
124
128
|
num = str.length
|
125
129
|
decor = "-"*num + "\n"
|
126
130
|
puts decor + str + "\n" + decor
|
127
131
|
end
|
128
132
|
|
129
133
|
def quit(args = nil, body = nil)
|
130
|
-
puts @body
|
131
|
-
@body = ""
|
132
134
|
@output.close
|
133
135
|
end
|
134
136
|
|
135
137
|
def cleanup(args = nil, body = nil)
|
136
|
-
|
138
|
+
api.args.each do |item|
|
137
139
|
cmd = ::File.directory?(item) ? "rm -f #{item}/*" : "rm #{item}"
|
138
140
|
system(cmd)
|
139
141
|
end
|
142
|
+
api.optional_blank_line
|
140
143
|
end
|
141
144
|
|
142
145
|
def dot_def(args = nil, body = nil)
|
143
|
-
|
144
|
-
|
146
|
+
# api.tty "in #{__FILE__}: api id = #{api.inspect}"
|
147
|
+
name = api.args[0]
|
148
|
+
# api.tty :dd1
|
149
|
+
# api.tty name.inspect
|
145
150
|
check_disallowed(name)
|
151
|
+
# api.tty :dd2
|
146
152
|
# Difficult to avoid eval here
|
147
|
-
str
|
153
|
+
str = "def #{name}\n"
|
154
|
+
str << api.body(true).join("\n")
|
148
155
|
str << "\nend\n"
|
149
156
|
eval str
|
157
|
+
api.optional_blank_line
|
150
158
|
end
|
151
159
|
|
152
160
|
def set(args = nil, body = nil)
|
153
|
-
line =
|
161
|
+
line = api.data.chomp
|
154
162
|
pairs = Livetext::ParseSet.new(line).parse
|
155
163
|
set_variables(pairs)
|
164
|
+
api.optional_blank_line
|
156
165
|
end
|
157
166
|
|
158
167
|
# FIXME really these should be one method...
|
159
168
|
|
160
169
|
def variables!(args = nil, body = nil) # cwd, not FileDir - weird, fix later
|
161
|
-
prefix =
|
162
|
-
file =
|
170
|
+
prefix = api.args[0]
|
171
|
+
file = api.args[1]
|
163
172
|
prefix = nil if prefix == "-" # FIXME dumb hack
|
164
173
|
if file
|
165
174
|
here = "" # different for ! version
|
166
175
|
lines = File.readlines(here + file)
|
167
176
|
else
|
168
|
-
lines =
|
177
|
+
lines = api.body
|
169
178
|
end
|
170
|
-
pairs = Livetext::ParseGeneral.parse_vars(
|
179
|
+
pairs = Livetext::ParseGeneral.parse_vars(lines, prefix: nil)
|
171
180
|
set_variables(pairs)
|
181
|
+
api.optional_blank_line
|
172
182
|
end
|
173
183
|
|
174
184
|
def variables(args = nil, body = nil)
|
175
|
-
prefix =
|
176
|
-
file =
|
185
|
+
prefix = api.args[0]
|
186
|
+
file = api.args[1]
|
177
187
|
prefix = nil if prefix == "-" # FIXME dumb hack
|
178
188
|
if file
|
179
189
|
here = ::Livetext::Vars[:FileDir] + "/"
|
180
190
|
lines = File.readlines(here + file)
|
181
191
|
else
|
182
|
-
lines =
|
192
|
+
lines = api.body
|
183
193
|
end
|
184
|
-
pairs = Livetext::ParseGeneral.parse_vars(
|
194
|
+
pairs = Livetext::ParseGeneral.parse_vars(lines, prefix: nil)
|
185
195
|
set_variables(pairs)
|
196
|
+
api.optional_blank_line
|
186
197
|
end
|
187
198
|
|
188
199
|
def heredoc(args = nil, body = nil)
|
189
|
-
var =
|
190
|
-
text =
|
200
|
+
var = api.args[0]
|
201
|
+
text = api.body.join("\n")
|
191
202
|
rhs = ""
|
192
203
|
text.each_line do |line|
|
193
|
-
str =
|
204
|
+
str = api.format(line.chomp)
|
194
205
|
rhs << str + "<br>"
|
195
206
|
end
|
196
207
|
indent = @parent.indentation.last
|
197
208
|
indented = " " * indent
|
198
|
-
|
199
|
-
|
209
|
+
api.setvar(var, rhs.chomp)
|
210
|
+
# @parent.setvar(var, rhs.chomp)
|
211
|
+
api.optional_blank_line
|
200
212
|
end
|
201
213
|
|
202
214
|
def seek(args = nil, body = nil) # like include, but search upward as needed
|
203
|
-
file =
|
215
|
+
file = api.args.first
|
204
216
|
file = search_upward(file)
|
205
217
|
check_file_exists(file)
|
206
218
|
@parent.process_file(file)
|
207
|
-
|
219
|
+
api.optional_blank_line
|
208
220
|
end
|
209
221
|
|
210
222
|
def dot_include(args = nil, body = nil) # dot command
|
211
|
-
file =
|
223
|
+
file = api.format(api.args.first) # allows for variables
|
212
224
|
check_file_exists(file)
|
213
225
|
@parent.process_file(file)
|
214
|
-
|
215
|
-
rescue StandardError => err
|
216
|
-
p err
|
217
|
-
puts "-----"
|
218
|
-
err.backtrace.to_a.each {|x| puts x }
|
219
|
-
puts "-----"
|
220
|
-
exit
|
221
|
-
TTY.puts ">>> #{__method__}: rescue in process_file!!"
|
222
|
-
# _out @body
|
226
|
+
api.optional_blank_line
|
223
227
|
end
|
224
228
|
|
225
229
|
def inherit(args = nil, body = nil)
|
226
|
-
file =
|
230
|
+
file = api.args.first
|
227
231
|
upper = "../#{file}"
|
228
232
|
got_upper, got_file = File.exist?(upper), File.exist?(file)
|
229
233
|
good = got_upper || got_file
|
230
|
-
|
234
|
+
STDERR.puts "File #{file} not found (local or parent)" unless good
|
231
235
|
|
232
236
|
@parent.process_file(upper) if got_upper
|
233
237
|
@parent.process_file(file) if got_file
|
234
|
-
|
238
|
+
api.optional_blank_line
|
235
239
|
end
|
236
240
|
|
237
241
|
def mixin(args = nil, body = nil)
|
238
|
-
name =
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
mod = Livetext::ParseMixin.get_module(name)
|
243
|
-
# TTY.puts "#{__method__}: mod = #{mod.inspect}"
|
242
|
+
name = api.args.first # Expect a module name
|
243
|
+
return if @mixins.include?(name)
|
244
|
+
@mixins << name
|
245
|
+
mod = Livetext::Handler::Mixin.get_module(name, @parent)
|
244
246
|
self.extend(mod)
|
245
247
|
init = "init_#{name}"
|
246
248
|
self.send(init) rescue nil # if self.respond_to? init
|
247
|
-
|
249
|
+
api.optional_blank_line
|
248
250
|
end
|
249
251
|
|
250
252
|
def import(args = nil, body = nil)
|
251
|
-
name =
|
252
|
-
return if @
|
253
|
-
@
|
254
|
-
mod = Livetext::Handler::Import.get_module(name)
|
253
|
+
name = api.args.first # Expect a module name
|
254
|
+
return if @imports.include?(name)
|
255
|
+
@imports << name
|
256
|
+
mod = Livetext::Handler::Import.get_module(name, @parent)
|
255
257
|
self.extend(mod)
|
256
258
|
init = "init_#{name}"
|
257
259
|
self.send(init) rescue nil # if self.respond_to? init
|
258
|
-
|
260
|
+
api.optional_blank_line
|
259
261
|
end
|
260
262
|
|
261
263
|
def copy(args = nil, body = nil)
|
262
|
-
file =
|
263
|
-
check_file_exists(file)
|
264
|
-
|
265
|
-
|
264
|
+
file = api.args.first
|
265
|
+
ok = check_file_exists(file)
|
266
|
+
|
267
|
+
self.parent.graceful_error FileNotFound(file) unless ok # FIXME seems weird?
|
268
|
+
api.out grab_file(file)
|
269
|
+
api.optional_blank_line
|
270
|
+
[ok, file]
|
266
271
|
end
|
267
272
|
|
268
273
|
def r(args = nil, body = nil)
|
269
|
-
|
274
|
+
api.out api.data # No processing at all
|
275
|
+
api.optional_blank_line
|
270
276
|
end
|
271
277
|
|
272
278
|
def raw(args = nil, body = nil)
|
273
279
|
# No processing at all (terminate with __EOF__)
|
274
|
-
|
280
|
+
api.raw_body {|line| api.out line } # no formatting
|
281
|
+
api.optional_blank_line
|
275
282
|
end
|
276
283
|
|
277
284
|
def debug(args = nil, body = nil)
|
278
|
-
self._debug = onoff(
|
285
|
+
self._debug = onoff(api.args.first)
|
286
|
+
api.optional_blank_line
|
279
287
|
end
|
280
288
|
|
281
289
|
def passthru(args = nil, body = nil)
|
282
290
|
# FIXME - add check for args size? (helpers)
|
283
|
-
@
|
291
|
+
@nopass = ! onoff(api.args.first)
|
292
|
+
api.optional_blank_line
|
284
293
|
end
|
285
294
|
|
286
295
|
def nopass(args = nil, body = nil)
|
287
|
-
@
|
296
|
+
@nopass = true
|
297
|
+
api.optional_blank_line
|
288
298
|
end
|
289
299
|
|
290
300
|
def para(args = nil, body = nil)
|
291
301
|
# FIXME - add check for args size? (helpers)
|
292
|
-
@
|
302
|
+
@nopara = ! onoff(api.args.first)
|
303
|
+
api.optional_blank_line
|
293
304
|
end
|
294
305
|
|
295
306
|
def nopara(args = nil, body = nil)
|
296
|
-
@
|
307
|
+
@nopara = true
|
308
|
+
api.optional_blank_line
|
297
309
|
end
|
298
310
|
|
299
311
|
def heading(args = nil, body = nil)
|
300
|
-
|
301
|
-
|
302
|
-
|
312
|
+
api.print "<center><font size=+1><b>"
|
313
|
+
api.print api.data
|
314
|
+
api.print "</b></font></center>"
|
315
|
+
api.optional_blank_line
|
303
316
|
end
|
304
317
|
|
305
318
|
def newpage(args = nil, body = nil)
|
306
|
-
|
307
|
-
|
319
|
+
api.out '<p style="page-break-after:always;"></p>'
|
320
|
+
api.out "<p/>"
|
321
|
+
api.optional_blank_line
|
308
322
|
end
|
309
323
|
|
310
324
|
def mono(args = nil, body = nil)
|
311
325
|
wrap ":pre" do
|
312
|
-
|
326
|
+
api.body(true) {|line| api.out line }
|
313
327
|
end
|
314
|
-
|
328
|
+
api.optional_blank_line
|
315
329
|
end
|
316
330
|
|
317
331
|
def dlist(args = nil, body = nil)
|
318
|
-
delim =
|
332
|
+
delim = api.args.first
|
319
333
|
wrap(:dl) do
|
320
|
-
|
321
|
-
line =
|
334
|
+
api.body do |line|
|
335
|
+
line = api.format(line)
|
322
336
|
term, defn = line.split(delim)
|
323
|
-
|
324
|
-
|
337
|
+
api.out wrapped(term, :dt)
|
338
|
+
api.out wrapped(defn, :dd)
|
325
339
|
end
|
326
340
|
end
|
341
|
+
api.optional_blank_line
|
327
342
|
end
|
328
343
|
|
329
344
|
def link(args = nil, body = nil)
|
330
|
-
url =
|
331
|
-
text =
|
332
|
-
|
345
|
+
url = api.args.first
|
346
|
+
text = api.args[2..-1].join(" ")
|
347
|
+
api.out "<a style='text-decoration: none' href='#{url}'>#{text}</a>"
|
348
|
+
api.optional_blank_line
|
333
349
|
end
|
334
350
|
|
335
351
|
def xtable(args = nil, body = nil) # Borrowed from bookish - FIXME
|
336
|
-
|
352
|
+
# TTY.puts "=== #{__method__} #{__FILE__} #{__LINE__}"
|
353
|
+
title = api.data
|
337
354
|
delim = " :: "
|
338
|
-
|
339
|
-
lines =
|
355
|
+
api.out "<br><center><table width=90% cellpadding=5>"
|
356
|
+
lines = api.body(true)
|
340
357
|
maxw = nil
|
358
|
+
processed = []
|
341
359
|
lines.each do |line|
|
342
|
-
line =
|
360
|
+
line = api.format(line)
|
343
361
|
line.gsub!(/\n+/, "<br>")
|
362
|
+
processed << line
|
344
363
|
cells = line.split(delim)
|
345
364
|
wide = cells.map {|cell| cell.length }
|
346
365
|
maxw = [0] * cells.size
|
@@ -350,32 +369,36 @@ TTY.puts ">>> #{__method__}: rescue in process_file!!"
|
|
350
369
|
sum = maxw.inject(0, :+)
|
351
370
|
maxw.map! {|x| (x/sum*100).floor }
|
352
371
|
|
353
|
-
|
372
|
+
processed.each do |line|
|
354
373
|
cells = line.split(delim)
|
355
374
|
wrap :tr do
|
356
|
-
cells.each {|cell|
|
375
|
+
cells.each {|cell| api.out " <td valign=top>#{cell}</td>" }
|
357
376
|
end
|
358
377
|
end
|
359
|
-
|
378
|
+
api.out "</table></center>"
|
379
|
+
api.optional_blank_line
|
360
380
|
end
|
361
381
|
|
362
382
|
def image(args = nil, body = nil)
|
363
|
-
name =
|
364
|
-
|
383
|
+
name = api.args[0]
|
384
|
+
api.out "<img src='#{name}'></img>"
|
385
|
+
api.optional_blank_line
|
365
386
|
end
|
366
387
|
|
367
388
|
def br(args = nil, body = nil)
|
368
|
-
num =
|
369
|
-
|
370
|
-
num.to_i.times {
|
371
|
-
|
389
|
+
num = api.args.first || "1"
|
390
|
+
str = ""
|
391
|
+
num.to_i.times { str << "<br>" }
|
392
|
+
api.out str
|
393
|
+
api.optional_blank_line
|
372
394
|
end
|
373
395
|
|
374
396
|
def reflection # strictly experimental!
|
375
397
|
list = self.methods
|
376
398
|
obj = Object.instance_methods
|
377
399
|
diff = (list - obj).sort
|
378
|
-
|
379
|
-
|
400
|
+
api.out "#{diff.size} methods:"
|
401
|
+
api.out diff.inspect
|
402
|
+
api.optional_blank_line
|
380
403
|
end
|
381
404
|
end
|
@@ -0,0 +1,170 @@
|
|
1
|
+
|
2
|
+
# require_relative 'formatline' # FIXME meh, because of #format
|
3
|
+
require_relative 'lineparser' # FIXME meh, because of #format
|
4
|
+
|
5
|
+
# Encapsulate the UserAPI as a class
|
6
|
+
|
7
|
+
class Livetext::UserAPI
|
8
|
+
|
9
|
+
KBD = File.new("/dev/tty", "r")
|
10
|
+
TTY = File.new("/dev/tty", "w")
|
11
|
+
|
12
|
+
DotSpace = ". " # Livetext::Sigil + Livetext::Space
|
13
|
+
|
14
|
+
attr_accessor :data, :args
|
15
|
+
|
16
|
+
def initialize(live)
|
17
|
+
@live = live
|
18
|
+
@vars = live.vars
|
19
|
+
end
|
20
|
+
|
21
|
+
def api
|
22
|
+
@live.api
|
23
|
+
end
|
24
|
+
|
25
|
+
def dot
|
26
|
+
@live
|
27
|
+
end
|
28
|
+
|
29
|
+
def setvar(var, val)
|
30
|
+
Livetext::Vars[var] = val # Now indifferent and "safe"
|
31
|
+
end
|
32
|
+
|
33
|
+
def check_existence(file, msg)
|
34
|
+
STDERR.puts msg unless File.exist?(file)
|
35
|
+
end
|
36
|
+
|
37
|
+
def data=(value)
|
38
|
+
# TTY.puts "in #{__FILE__}: api = #{@live.api.inspect}"
|
39
|
+
@data = value
|
40
|
+
@args = format(@data).chomp.split
|
41
|
+
end
|
42
|
+
|
43
|
+
def args
|
44
|
+
return @args unless block_given?
|
45
|
+
@args.each {|arg| yield arg }
|
46
|
+
end
|
47
|
+
|
48
|
+
def vars
|
49
|
+
@vars
|
50
|
+
end
|
51
|
+
|
52
|
+
def optional_blank_line
|
53
|
+
peek = @live.peek_nextline # ???
|
54
|
+
return if peek.nil?
|
55
|
+
@line = @live.nextline if peek =~ /^ *$/
|
56
|
+
return true # This way, dot commands will usually return true
|
57
|
+
end
|
58
|
+
|
59
|
+
def comment?(str)
|
60
|
+
str.index(DotSpace) == 0
|
61
|
+
end
|
62
|
+
|
63
|
+
def trailing?(char)
|
64
|
+
return true if ["\n", " ", nil].include?(char)
|
65
|
+
return false
|
66
|
+
end
|
67
|
+
|
68
|
+
def end?(str)
|
69
|
+
return true if str == ".end" || str =~ / *\$\.end/
|
70
|
+
return false
|
71
|
+
end
|
72
|
+
|
73
|
+
def raw_body(tag = "__EOF__")
|
74
|
+
lines = []
|
75
|
+
@live.save_location = @live.sources.last
|
76
|
+
loop do
|
77
|
+
@line = @live.nextline
|
78
|
+
break if @line.nil?
|
79
|
+
break if @line.chomp.strip == tag
|
80
|
+
lines << @line
|
81
|
+
end
|
82
|
+
optional_blank_line
|
83
|
+
return lines unless block_given?
|
84
|
+
lines.each {|line| yield line }
|
85
|
+
end
|
86
|
+
|
87
|
+
def body(raw=false)
|
88
|
+
lines = []
|
89
|
+
end_found = false
|
90
|
+
loop do
|
91
|
+
@line = @live.nextline
|
92
|
+
break if @line.nil?
|
93
|
+
@line.chomp!
|
94
|
+
break if end?(@line)
|
95
|
+
next if comment?(@line)
|
96
|
+
@line = format(@line) unless raw
|
97
|
+
lines << @line
|
98
|
+
end
|
99
|
+
raise "Expected .end, found end of file" unless end?(@line) # use custom exception
|
100
|
+
optional_blank_line # FIXME Delete this??
|
101
|
+
return lines unless block_given?
|
102
|
+
lines.each {|line| yield line } # FIXME what about $. ?
|
103
|
+
end
|
104
|
+
|
105
|
+
def body_text(raw=false)
|
106
|
+
raw_body.join("\n")
|
107
|
+
end
|
108
|
+
|
109
|
+
def raw_body!
|
110
|
+
raw_body(Livetext::Sigil).join("\n")
|
111
|
+
end
|
112
|
+
|
113
|
+
def handle_escapes(str, set)
|
114
|
+
str = str.dup
|
115
|
+
set.each_char do |ch|
|
116
|
+
str.gsub!("\\#{ch}", ch)
|
117
|
+
end
|
118
|
+
str
|
119
|
+
end
|
120
|
+
|
121
|
+
def format(line)
|
122
|
+
return "" if line == "\n" || line.nil?
|
123
|
+
line2 = Livetext::LineParser.parse!(line)
|
124
|
+
line2
|
125
|
+
end
|
126
|
+
|
127
|
+
def passthru(line)
|
128
|
+
return if @live.nopass
|
129
|
+
out "<p>" if line == "\n" and ! @live.nopara
|
130
|
+
line = format(line)
|
131
|
+
out line
|
132
|
+
end
|
133
|
+
|
134
|
+
def out(str = "", file = nil)
|
135
|
+
return if str.nil?
|
136
|
+
return file.puts str unless file.nil?
|
137
|
+
@live.body << str
|
138
|
+
@live.body << "\n" unless str.end_with?("\n")
|
139
|
+
end
|
140
|
+
|
141
|
+
def out!(str = "")
|
142
|
+
@live.body << str # no newline
|
143
|
+
end
|
144
|
+
|
145
|
+
def tty(*args)
|
146
|
+
TTY.puts *args
|
147
|
+
end
|
148
|
+
|
149
|
+
def err(*args)
|
150
|
+
STDERR.puts *args
|
151
|
+
end
|
152
|
+
|
153
|
+
def puts(*args)
|
154
|
+
@live.output.puts *args
|
155
|
+
end
|
156
|
+
|
157
|
+
def print(*args)
|
158
|
+
@live.output.print *args
|
159
|
+
end
|
160
|
+
|
161
|
+
def debug=(val)
|
162
|
+
@live.debug = val
|
163
|
+
end
|
164
|
+
|
165
|
+
def debug(*args)
|
166
|
+
TTY.puts *args if @live.debug
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
|