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