livetext 0.9.21 → 0.9.25

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. checksums.yaml +4 -4
  2. data/README.lt3 +8 -8
  3. data/bin/livetext +57 -40
  4. data/imports/bookish.rb +89 -90
  5. data/imports/calibre.rb +3 -3
  6. data/imports/livemagick.rb +17 -17
  7. data/imports/markdown.rb +10 -10
  8. data/imports/pyggish.rb +15 -47
  9. data/imports/tutorial.rb +18 -18
  10. data/lib/cmdargs.rb +10 -6
  11. data/lib/{errors.rb → livetext/errors.rb} +1 -1
  12. data/lib/{formatline.rb → livetext/formatline.rb} +69 -125
  13. data/lib/livetext/funcall.rb +84 -0
  14. data/lib/{functions.rb → livetext/functions.rb} +16 -3
  15. data/lib/livetext/global_helpers.rb +37 -0
  16. data/lib/livetext/handler/import.rb +44 -0
  17. data/lib/livetext/handler/mixin.rb +37 -0
  18. data/lib/livetext/handler.rb +3 -0
  19. data/lib/{helpers.rb → livetext/helpers.rb} +89 -67
  20. data/lib/{html.rb → livetext/html.rb} +3 -2
  21. data/lib/{parser → livetext/parser}/general.rb +0 -3
  22. data/lib/{parser → livetext/parser}/set.rb +1 -6
  23. data/lib/{parser → livetext/parser}/string.rb +2 -2
  24. data/lib/{parser.rb → livetext/parser.rb} +0 -1
  25. data/lib/livetext/parsing.rb +29 -0
  26. data/lib/livetext/paths.rb +13 -0
  27. data/lib/livetext/processor.rb +89 -0
  28. data/lib/livetext/reopen.rb +12 -0
  29. data/lib/livetext/skeleton.rb +17 -0
  30. data/lib/{standard.rb → livetext/standard.rb} +152 -122
  31. data/lib/livetext/userapi.rb +153 -0
  32. data/lib/livetext/version.rb +6 -0
  33. data/lib/livetext.rb +66 -27
  34. data/plugin/bookish.rb +85 -85
  35. data/plugin/calibre.rb +3 -3
  36. data/plugin/livemagick.rb +17 -17
  37. data/plugin/markdown.rb +10 -10
  38. data/plugin/pyggish.rb +131 -162
  39. data/plugin/tutorial.rb +15 -16
  40. data/test/all.rb +6 -0
  41. data/test/snapshots/def_method/expected-output.txt +2 -0
  42. data/test/snapshots/def_method/source.lt3 +4 -2
  43. data/test/snapshots/error_inc_line_num/OUT +17 -0
  44. data/test/snapshots/error_inc_line_num/README.txt +20 -0
  45. data/test/snapshots/error_inc_line_num/expected-output.txt +0 -6
  46. data/test/snapshots/error_inc_line_num/match-error.txt +1 -1
  47. data/test/snapshots/error_line_num/match-error.txt +1 -1
  48. data/test/snapshots/error_missing_end/expected-output.txt +0 -1
  49. data/test/snapshots/error_name_not_permitted/expected-output.txt +4 -0
  50. data/test/snapshots/error_name_not_permitted/match-error.txt +1 -1
  51. data/test/snapshots/error_no_such_copy/duh +26 -0
  52. data/test/snapshots/error_no_such_copy/expected-output.txt +1 -0
  53. data/test/snapshots/error_no_such_copy/match-error.txt +1 -1
  54. data/test/snapshots/error_no_such_copy/mystery.txt +36 -0
  55. data/test/snapshots/error_no_such_inc/match-error.txt +1 -1
  56. data/test/snapshots/error_no_such_mixin/expected-output.txt +1 -0
  57. data/test/snapshots/error_no_such_mixin/match-error.txt +1 -1
  58. data/test/snapshots/error_no_such_mixin/source.lt3 +1 -1
  59. data/test/snapshots/example_alpha/source.lt3 +2 -2
  60. data/test/snapshots/example_alpha2/expected-output.txt +0 -2
  61. data/test/snapshots/example_alpha2/source.lt3 +5 -4
  62. data/test/snapshots/{icanhaz → import}/expected-output.txt +2 -1
  63. data/test/snapshots/import/match-error.txt +1 -0
  64. data/test/snapshots/{icanhaz → import}/simple_import.rb +1 -1
  65. data/test/snapshots/{icanhaz → import}/source.lt3 +2 -2
  66. data/test/snapshots/{icanhaz2 → import2}/expected-error.txt +0 -0
  67. data/test/snapshots/{icanhaz2 → import2}/expected-output.txt +3 -1
  68. data/test/snapshots/{icanhaz2/simple_canhaz.rb → import2/simple_import.rb} +1 -1
  69. data/test/snapshots/import2/source.lt3 +8 -0
  70. data/test/snapshots/import_bookish/expected-error.txt +0 -0
  71. data/test/snapshots/import_bookish/expected-output.txt +10 -0
  72. data/test/snapshots/import_bookish/source.lt3 +7 -0
  73. data/test/snapshots/import_bookish/toc.tmp +0 -0
  74. data/test/snapshots/mixin_bookish/expected-error.txt +0 -0
  75. data/test/snapshots/mixin_bookish/expected-output.txt +10 -0
  76. data/test/snapshots/mixin_bookish/source.lt3 +7 -0
  77. data/test/snapshots/mixin_bookish/toc.tmp +0 -0
  78. data/test/snapshots/more_functions/expected-error.txt +0 -0
  79. data/test/snapshots/more_functions/expected-output.txt +37 -0
  80. data/test/snapshots/more_functions/source.lt3 +40 -0
  81. data/test/snapshots/raw_lines/expected-output.txt +0 -2
  82. data/test/snapshots/simple_import/expected-output.txt +2 -0
  83. data/test/snapshots/simple_import/simple_import.rb +1 -1
  84. data/test/snapshots/simple_import/source.lt3 +3 -1
  85. data/test/snapshots/simple_mixin/simple_mixin.rb +1 -1
  86. data/test/snapshots/single_raw_line/expected-output.txt +0 -2
  87. data/test/snapshots/subset.txt +14 -14
  88. data/test/snapshots.rb +30 -13
  89. data/test/unit/formatline.rb +253 -134
  90. data/test/unit/html.rb +2 -3
  91. data/test/unit/parser/general.rb +1 -2
  92. data/test/unit/parser/mixin.rb +1 -3
  93. data/test/unit/parser/set.rb +8 -12
  94. data/test/unit/parser/string.rb +6 -6
  95. data/test/unit/parser.rb +0 -1
  96. data/test/unit/standard.rb +0 -2
  97. metadata +47 -30
  98. data/imports/markdown_importable.rb +0 -45
  99. data/lib/handler/icanhaz.rb +0 -35
  100. data/lib/handler.rb +0 -1
  101. data/lib/livetext/importable.rb +0 -2
  102. data/lib/parser/file.rb +0 -8
  103. data/lib/parser/import.rb +0 -15
  104. data/lib/parser/mixin.rb +0 -38
  105. data/lib/processor.rb +0 -83
  106. data/lib/userapi.rb +0 -160
  107. data/test/snapshots/icanhaz/match-error.txt +0 -1
  108. data/test/snapshots/icanhaz2/source.lt3 +0 -6
  109. 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 :_data
26
+ attr_reader :data
26
27
 
27
28
  def data=(val) # FIXME this is weird, let's remove it soonish
28
- @_data = val.chomp
29
- @_args = val.split rescue []
30
- @_mixins = []
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
- def bits(args = nil, body = nil)
35
- b0, b1, i0, i1, t0, t1, s0, s1 = *@_args
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(@_args.first)
44
- _optional_blank_line
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
- _body
49
- _optional_blank_line
54
+ api.body
55
+ api.optional_blank_line
50
56
  end
51
57
 
52
58
  def shell(args = nil, body = nil)
53
- cmd = @_data.chomp
59
+ cmd = api.data
54
60
  system(cmd)
55
- _optional_blank_line
61
+ api.optional_blank_line
56
62
  end
57
63
 
58
64
  def func(args = nil, body = nil)
59
- funcname = @_args[0]
65
+ funcname = api.args[0]
60
66
  check_disallowed(funcname)
61
67
  func_def = <<~EOS
62
68
  def #{funcname}(param)
63
- #{_body.to_a.join("\n")}
69
+ #{api.body.to_a.join("\n")}
64
70
  end
65
71
  EOS
66
- _optional_blank_line
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); _out wrapped(@_data, :h1); end
71
- def h2(args = nil, body = nil); _out wrapped(@_data, :h2); end
72
- def h3(args = nil, body = nil); _out wrapped(@_data, :h3); end
73
- def h4(args = nil, body = nil); _out wrapped(@_data, :h4); end
74
- def h5(args = nil, body = nil); _out wrapped(@_data, :h5); end
75
- def h6(args = nil, body = nil); _out wrapped(@_data, :h6); end
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
- _body {|line| _out wrapped(line, :li) }
86
+ api.body {|line| api.out wrapped(line, :li) }
80
87
  end
81
- _optional_blank_line
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 = _body.each # enumerator
93
+ lines = api.body.each # enumerator
87
94
  loop do
88
95
  line = lines.next
89
- line = _format(line)
96
+ line = api.format(line)
90
97
  str = line[0] == " " ? line : wrapped(line, :li)
91
- _out str
98
+ api.out str
92
99
  end
93
100
  end
94
- _optional_blank_line
101
+ api.optional_blank_line
95
102
  end
96
103
 
97
104
  def shell!(args = nil, body = nil)
98
- cmd = @_data.chomp
105
+ cmd = api.data
99
106
  system(cmd)
100
- _optional_blank_line
107
+ api.optional_blank_line
101
108
  end
102
109
 
103
110
  def errout(args = nil, body = nil)
104
- STDERR.puts @_data.chomp
105
- _optional_blank_line
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 @_data.chomp
110
- _optional_blank_line
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 = _format(@_data.chomp)
121
+ str = api.format(api.data)
115
122
  TTY.puts str
116
- _optional_blank_line
123
+ api.optional_blank_line
117
124
  end
118
125
 
119
126
  def banner(args = nil, body = nil)
120
- str = _format(@_data.chomp)
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
- @_args.each do |item|
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 = @_args[0]
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 << _body(true).join("\n")
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 = _data.chomp
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 = _args[0]
159
- file = _args[1]
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 = _body
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 = _args[0]
173
- file = _args[1]
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 = _body
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 = @_args[0]
187
- text = _body.join("\n")
196
+ var = api.args[0]
197
+ text = api.body.join("\n")
188
198
  rhs = ""
189
199
  text.each_line do |line|
190
- str = Livetext.interpolate(line.chomp)
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
- @parent.setvar(var, rhs.chomp)
196
- _optional_blank_line
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 = @_args.first
211
+ file = api.args.first
201
212
  file = search_upward(file)
202
213
  check_file_exists(file)
203
214
  @parent.process_file(file)
204
- _optional_blank_line
215
+ api.optional_blank_line
205
216
  end
206
217
 
207
218
  def dot_include(args = nil, body = nil) # dot command
208
- file = _format(@_args.first) # allows for variables
219
+ file = api.format(api.args.first) # allows for variables
209
220
  check_file_exists(file)
210
221
  @parent.process_file(file)
211
- _optional_blank_line
222
+ api.optional_blank_line
212
223
  end
213
224
 
214
225
  def inherit(args = nil, body = nil)
215
- file = @_args.first
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
- _error!("File #{file} not found (local or parent)") unless good
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
- _optional_blank_line
234
+ api.optional_blank_line
224
235
  end
225
236
 
226
237
  def mixin(args = nil, body = nil)
227
- name = @_args.first # Expect a module name
228
- return if @_mixins.include?(name)
229
- @_mixins << name
230
- mod = Livetext::ParseMixin.get_module(name) # FIXME??
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
- _optional_blank_line
244
+ self.send(init) rescue nil # if self.respond_to? init
245
+ api.optional_blank_line
235
246
  end
236
247
 
237
- def icanhaz(args = nil, body = nil)
238
- name = @_args.first # Expect a module name
239
- return if @_mixins.include?(name)
240
- @_mixins << name
241
- mod = Livetext::Handler::ICanHaz.get_module(name) # FIXME??
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
- _optional_blank_line
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 = @_args.first
259
- check_file_exists(file)
260
- _out grab_file(file)
261
- _optional_blank_line
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
- _out @_data.chomp # No processing at all
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
- _raw_body {|line| _out line } # no formatting
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(@_args.first)
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
- @_nopass = ! onoff(_args.first)
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
- @_nopass = true
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
- @_nopara = ! onoff(_args.first)
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
- @_nopara = true
303
+ @nopara = true
304
+ api.optional_blank_line
293
305
  end
294
306
 
295
307
  def heading(args = nil, body = nil)
296
- _print "<center><font size=+1><b>"
297
- _print @_data.chomp
298
- _print "</b></font></center>"
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
- _out '<p style="page-break-after:always;"></p>'
303
- _out "<p/>"
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
- _body(true) {|line| _out line }
322
+ api.body(true) {|line| api.out line }
309
323
  end
310
- _optional_blank_line
324
+ api.optional_blank_line
311
325
  end
312
326
 
313
327
  def dlist(args = nil, body = nil)
314
- delim = _args.first
328
+ delim = api.args.first
315
329
  wrap(:dl) do
316
- _body do |line|
317
- line = _format(line)
330
+ api.body do |line|
331
+ line = api.format(line)
318
332
  term, defn = line.split(delim)
319
- _out wrapped(term, :dt)
320
- _out wrapped(defn, :dd)
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 = _args.first
327
- text = _args[2..-1].join(" ")
328
- _out "<a style='text-decoration: none' href='#{url}'>#{text}</a>"
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
- title = @_data.chomp
348
+ # TTY.puts "=== #{__method__} #{__FILE__} #{__LINE__}"
349
+ title = api.data
333
350
  delim = " :: "
334
- _out "<br><center><table width=90% cellpadding=5>"
335
- lines = _body(true)
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 = _format(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
- lines.each do |line|
368
+ processed.each do |line|
350
369
  cells = line.split(delim)
351
370
  wrap :tr do
352
- cells.each {|cell| _out " <td valign=top>#{cell}</td>" }
371
+ cells.each {|cell| api.out " <td valign=top>#{cell}</td>" }
353
372
  end
354
373
  end
355
- _out "</table></center>"
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 = @_args[0]
360
- _out "<img src='#{name}'></img>"
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 = _args.first || "1"
365
- out = ""
366
- num.to_i.times { out << "<br>" }
367
- _out out
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
+
@@ -0,0 +1,6 @@
1
+
2
+ # Defining VERSION
3
+
4
+ class Livetext
5
+ VERSION = "0.9.25"
6
+ end