livetext 0.9.23 → 0.9.26

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/README.lt3 +6 -6
  3. data/bin/livetext +57 -40
  4. data/imports/bookish.rb +81 -81
  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 +13 -13
  9. data/imports/tutorial.rb +15 -15
  10. data/lib/cmdargs.rb +7 -4
  11. data/lib/{errors.rb → livetext/errors.rb} +4 -3
  12. data/lib/{formatline.rb → livetext/formatline.rb} +119 -18
  13. data/lib/livetext/funcall.rb +168 -0
  14. data/lib/{functions.rb → livetext/functions.rb} +0 -2
  15. data/lib/{global_helpers.rb → livetext/global_helpers.rb} +6 -3
  16. data/lib/{handler → livetext/handler}/import.rb +5 -9
  17. data/lib/livetext/handler/mixin.rb +33 -0
  18. data/lib/{handler.rb → livetext/handler.rb} +1 -1
  19. data/lib/{helpers.rb → livetext/helpers.rb} +78 -66
  20. data/lib/{html.rb → livetext/html.rb} +2 -3
  21. data/lib/livetext/lineparser.rb +441 -0
  22. data/lib/livetext/more.rb +158 -0
  23. data/lib/{parser → livetext/parser}/general.rb +0 -0
  24. data/lib/{parser → livetext/parser}/set.rb +0 -0
  25. data/lib/{parser → livetext/parser}/string.rb +0 -0
  26. data/lib/{parser.rb → livetext/parser.rb} +0 -3
  27. data/lib/{parsing.rb → livetext/parsing.rb} +0 -2
  28. data/lib/livetext/paths.rb +13 -0
  29. data/lib/{processor.rb → livetext/processor.rb} +18 -8
  30. data/lib/livetext/reopen.rb +12 -0
  31. data/lib/livetext/skeleton.rb +22 -0
  32. data/lib/{standard.rb → livetext/standard.rb} +150 -127
  33. data/lib/livetext/userapi.rb +170 -0
  34. data/lib/livetext/version.rb +6 -0
  35. data/lib/livetext.rb +14 -152
  36. data/plugin/bookish.rb +82 -81
  37. data/plugin/calibre.rb +3 -3
  38. data/plugin/livemagick.rb +17 -17
  39. data/plugin/markdown.rb +10 -10
  40. data/plugin/pyggish.rb +118 -118
  41. data/plugin/tutorial.rb +15 -15
  42. data/test/all.rb +6 -0
  43. data/test/snapshots/{error_inc_line_num → basic_formatting}/actual-error.txt +0 -0
  44. data/test/snapshots/basic_formatting/actual-output.txt +13 -0
  45. data/test/snapshots/basic_formatting/err-sdiff.txt +1 -0
  46. data/test/snapshots/basic_formatting/out-sdiff.txt +14 -0
  47. data/test/snapshots/def_method/expected-output.txt +2 -0
  48. data/test/snapshots/def_method/source.lt3 +4 -2
  49. data/test/snapshots/error_inc_line_num/{OUT → README.txt} +11 -8
  50. data/test/snapshots/error_inc_line_num/expected-output.txt +0 -6
  51. data/test/snapshots/error_inc_line_num/match-error.txt +1 -1
  52. data/test/snapshots/error_invalid_name/foo +5 -0
  53. data/test/snapshots/error_line_num/match-error.txt +1 -1
  54. data/test/snapshots/error_missing_end/expected-output.txt +0 -1
  55. data/test/snapshots/error_name_not_permitted/expected-output.txt +4 -0
  56. data/test/snapshots/error_name_not_permitted/match-error.txt +1 -1
  57. data/test/snapshots/error_no_such_copy/expected-output.txt +1 -0
  58. data/test/snapshots/error_no_such_mixin/expected-output.txt +1 -0
  59. data/test/snapshots/error_no_such_mixin/match-error.txt +1 -1
  60. data/test/snapshots/error_no_such_mixin/source.lt3 +1 -1
  61. data/test/snapshots/example_alpha/source.lt3 +2 -2
  62. data/test/snapshots/example_alpha2/expected-output.txt +0 -2
  63. data/test/snapshots/example_alpha2/source.lt3 +5 -4
  64. data/test/snapshots/import/expected-output.txt +2 -1
  65. data/test/snapshots/import/match-error.txt +1 -1
  66. data/test/snapshots/import/simple_import.rb +1 -1
  67. data/test/snapshots/import2/simple_import.rb +1 -1
  68. data/test/snapshots/import_bookish/expected-output.txt +4 -4
  69. data/test/snapshots/{error_invalid_name/actual-output.txt → more_functions/actual-error.txt} +0 -0
  70. data/test/snapshots/more_functions/actual-output.txt +37 -0
  71. data/test/snapshots/more_functions/err-sdiff.txt +1 -0
  72. data/test/snapshots/more_functions/expected-output.txt +1 -1
  73. data/test/snapshots/more_functions/out-sdiff.txt +38 -0
  74. data/test/snapshots/more_functions/source.lt3 +1 -1
  75. data/test/snapshots/raw_lines/expected-output.txt +0 -2
  76. data/test/snapshots/simple_import/simple_import.rb +1 -1
  77. data/test/snapshots/simple_mixin/simple_mixin.rb +1 -1
  78. data/test/snapshots/{error_missing_end/actual-output.txt → simple_vars/actual-error.txt} +0 -0
  79. data/test/snapshots/simple_vars/actual-output.txt +6 -0
  80. data/test/snapshots/simple_vars/err-sdiff.txt +1 -0
  81. data/test/snapshots/simple_vars/out-sdiff.txt +7 -0
  82. data/test/snapshots/single_raw_line/expected-output.txt +0 -2
  83. data/test/snapshots/subset.txt +9 -7
  84. data/test/snapshots/{error_no_such_copy/actual-output.txt → var_into_func/actual-error.txt} +0 -0
  85. data/test/snapshots/var_into_func/actual-output.txt +16 -0
  86. data/test/snapshots/var_into_func/err-sdiff.txt +1 -0
  87. data/test/snapshots/{error_no_such_inc/actual-output.txt → var_into_func/expected-error.txt} +0 -0
  88. data/test/snapshots/var_into_func/expected-output.txt +16 -0
  89. data/test/snapshots/var_into_func/out-sdiff.txt +17 -0
  90. data/test/snapshots/var_into_func/source.lt3 +16 -0
  91. data/test/snapshots.rb +16 -7
  92. data/test/unit/all.rb +3 -1
  93. data/test/unit/formatline.rb +145 -276
  94. data/test/unit/html.rb +1 -2
  95. data/test/unit/lineparser.rb +650 -0
  96. data/test/unit/parser/set.rb +13 -12
  97. data/test/unit/standard.rb +0 -1
  98. data/test/unit/tokenizer.rb +534 -0
  99. metadata +49 -39
  100. data/lib/funcall.rb +0 -93
  101. data/lib/parser/file.rb +0 -6
  102. data/lib/parser/mixin.rb +0 -34
  103. data/lib/userapi.rb +0 -164
  104. data/test/snapshots/error_inc_line_num/actual-output.txt +0 -17
  105. data/test/snapshots/error_invalid_name/actual-error.txt +0 -10
  106. data/test/snapshots/error_invalid_name/out-sdiff.txt +0 -6
  107. data/test/snapshots/error_missing_end/actual-error.txt +0 -10
  108. data/test/snapshots/error_missing_end/out-sdiff.txt +0 -6
  109. data/test/snapshots/error_no_such_copy/actual-error.txt +0 -10
  110. data/test/snapshots/error_no_such_copy/out-sdiff.txt +0 -5
  111. data/test/snapshots/error_no_such_inc/actual-error.txt +0 -10
  112. data/test/snapshots/error_no_such_inc/out-sdiff.txt +0 -6
  113. data/test/snapshots/error_no_such_mixin/actual-error.txt +0 -13
  114. data/test/snapshots/error_no_such_mixin/actual-output.txt +0 -0
  115. 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 :_data
26
+ attr_reader :data
29
27
 
30
- def data=(val) # FIXME this is weird, let's remove it soonish
31
- @_data = val.chomp
32
- @_args = val.split rescue []
33
- @_mixins = []
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
- def bits(args = nil, body = nil)
38
- 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
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(@_args.first)
47
- _optional_blank_line
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
- _body
52
- _optional_blank_line
54
+ api.body
55
+ api.optional_blank_line
53
56
  end
54
57
 
55
58
  def shell(args = nil, body = nil)
56
- cmd = @_data.chomp
59
+ cmd = api.data
57
60
  system(cmd)
58
- _optional_blank_line
61
+ api.optional_blank_line
59
62
  end
60
63
 
61
64
  def func(args = nil, body = nil)
62
- funcname = @_args[0]
65
+ funcname = api.args[0]
63
66
  check_disallowed(funcname)
64
67
  func_def = <<~EOS
65
68
  def #{funcname}(param)
66
- #{_body.to_a.join("\n")}
69
+ #{api.body.to_a.join("\n")}
67
70
  end
68
71
  EOS
69
- _optional_blank_line
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); _out wrapped(@_data, :h1); end
74
- def h2(args = nil, body = nil); _out wrapped(@_data, :h2); end
75
- def h3(args = nil, body = nil); _out wrapped(@_data, :h3); end
76
- def h4(args = nil, body = nil); _out wrapped(@_data, :h4); end
77
- def h5(args = nil, body = nil); _out wrapped(@_data, :h5); end
78
- 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
79
83
 
80
84
  def list(args = nil, body = nil)
81
85
  wrap :ul do
82
- _body {|line| _out wrapped(line, :li) }
86
+ api.body {|line| api.out wrapped(line, :li) }
83
87
  end
84
- _optional_blank_line
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 = _body.each # enumerator
93
+ lines = api.body.each # enumerator
90
94
  loop do
91
95
  line = lines.next
92
- line = _format(line)
96
+ line = api.format(line)
93
97
  str = line[0] == " " ? line : wrapped(line, :li)
94
- _out str
98
+ api.out str
95
99
  end
96
100
  end
97
- _optional_blank_line
101
+ api.optional_blank_line
98
102
  end
99
103
 
100
104
  def shell!(args = nil, body = nil)
101
- cmd = @_data.chomp
105
+ cmd = api.data
102
106
  system(cmd)
103
- _optional_blank_line
107
+ api.optional_blank_line
104
108
  end
105
109
 
106
110
  def errout(args = nil, body = nil)
107
- ::STDERR.puts @_data.chomp
108
- _optional_blank_line
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 @_data.chomp
113
- _optional_blank_line
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 = _format(@_data.chomp)
121
+ str = api.format(api.data)
118
122
  TTY.puts str
119
- _optional_blank_line
123
+ api.optional_blank_line
120
124
  end
121
125
 
122
126
  def banner(args = nil, body = nil)
123
- str = _format(@_data.chomp)
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
- @_args.each do |item|
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
- name = @_args[0]
144
- str = "def #{name}\n"
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 << _body(true).join("\n")
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 = _data.chomp
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 = _args[0]
162
- file = _args[1]
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 = _body
177
+ lines = api.body
169
178
  end
170
- pairs = Livetext::ParseGeneral.parse_vars(prefix, lines)
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 = _args[0]
176
- file = _args[1]
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 = _body
192
+ lines = api.body
183
193
  end
184
- pairs = Livetext::ParseGeneral.parse_vars(prefix, lines)
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 = @_args[0]
190
- text = _body.join("\n")
200
+ var = api.args[0]
201
+ text = api.body.join("\n")
191
202
  rhs = ""
192
203
  text.each_line do |line|
193
- str = Livetext.interpolate(line.chomp)
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
- @parent.setvar(var, rhs.chomp)
199
- _optional_blank_line
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 = @_args.first
215
+ file = api.args.first
204
216
  file = search_upward(file)
205
217
  check_file_exists(file)
206
218
  @parent.process_file(file)
207
- _optional_blank_line
219
+ api.optional_blank_line
208
220
  end
209
221
 
210
222
  def dot_include(args = nil, body = nil) # dot command
211
- file = _format(@_args.first) # allows for variables
223
+ file = api.format(api.args.first) # allows for variables
212
224
  check_file_exists(file)
213
225
  @parent.process_file(file)
214
- _optional_blank_line
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 = @_args.first
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
- _error!("File #{file} not found (local or parent)") unless good
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
- _optional_blank_line
238
+ api.optional_blank_line
235
239
  end
236
240
 
237
241
  def mixin(args = nil, body = nil)
238
- name = @_args.first # Expect a module name
239
- # TTY.puts "#{__method__}: name = #{name}"
240
- return if @_mixins.include?(name)
241
- @_mixins << name
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
- _optional_blank_line
249
+ api.optional_blank_line
248
250
  end
249
251
 
250
252
  def import(args = nil, body = nil)
251
- name = @_args.first # Expect a module name
252
- return if @_mixins.include?(name)
253
- @_mixins << name
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
- _optional_blank_line
260
+ api.optional_blank_line
259
261
  end
260
262
 
261
263
  def copy(args = nil, body = nil)
262
- file = @_args.first
263
- check_file_exists(file)
264
- _out grab_file(file)
265
- _optional_blank_line
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
- _out @_data.chomp # No processing at all
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
- _raw_body {|line| _out line } # no formatting
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(@_args.first)
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
- @_nopass = ! onoff(_args.first)
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
- @_nopass = true
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
- @_nopara = ! onoff(_args.first)
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
- @_nopara = true
307
+ @nopara = true
308
+ api.optional_blank_line
297
309
  end
298
310
 
299
311
  def heading(args = nil, body = nil)
300
- _print "<center><font size=+1><b>"
301
- _print @_data.chomp
302
- _print "</b></font></center>"
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
- _out '<p style="page-break-after:always;"></p>'
307
- _out "<p/>"
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
- _body(true) {|line| _out line }
326
+ api.body(true) {|line| api.out line }
313
327
  end
314
- _optional_blank_line
328
+ api.optional_blank_line
315
329
  end
316
330
 
317
331
  def dlist(args = nil, body = nil)
318
- delim = _args.first
332
+ delim = api.args.first
319
333
  wrap(:dl) do
320
- _body do |line|
321
- line = _format(line)
334
+ api.body do |line|
335
+ line = api.format(line)
322
336
  term, defn = line.split(delim)
323
- _out wrapped(term, :dt)
324
- _out wrapped(defn, :dd)
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 = _args.first
331
- text = _args[2..-1].join(" ")
332
- _out "<a style='text-decoration: none' href='#{url}'>#{text}</a>"
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
- title = @_data.chomp
352
+ # TTY.puts "=== #{__method__} #{__FILE__} #{__LINE__}"
353
+ title = api.data
337
354
  delim = " :: "
338
- _out "<br><center><table width=90% cellpadding=5>"
339
- lines = _body(true)
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 = _format(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
- lines.each do |line|
372
+ processed.each do |line|
354
373
  cells = line.split(delim)
355
374
  wrap :tr do
356
- cells.each {|cell| _out " <td valign=top>#{cell}</td>" }
375
+ cells.each {|cell| api.out " <td valign=top>#{cell}</td>" }
357
376
  end
358
377
  end
359
- _out "</table></center>"
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 = @_args[0]
364
- _out "<img src='#{name}'></img>"
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 = _args.first || "1"
369
- out = ""
370
- num.to_i.times { out << "<br>" }
371
- _out out
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
- _out "#{diff.size} methods:"
379
- _out diff.inspect
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
+
@@ -0,0 +1,6 @@
1
+
2
+ # Defining VERSION
3
+
4
+ class Livetext
5
+ VERSION = "0.9.26"
6
+ end