livetext 0.5.2 → 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/bin/livetext +20 -0
  3. data/lib/bookish.rb +212 -0
  4. data/lib/calibre.rb +24 -0
  5. data/lib/liveblog.rb +195 -0
  6. data/lib/livemagick.rb +131 -0
  7. data/lib/livetext.rb +605 -0
  8. data/lib/markdown.rb +30 -0
  9. data/lib/pyggish.rb +194 -0
  10. data/lib/tutorial.rb +89 -0
  11. data/livetext-0.5.2.gem +0 -0
  12. data/livetext.gemspec +99 -4
  13. data/test/cleanup +1 -0
  14. data/test/newtest +10 -0
  15. data/test/rawtext.inc +4 -0
  16. data/test/simple_mixin.rb +3 -0
  17. data/test/simplefile.inc +2 -0
  18. data/test/test.rb +77 -0
  19. data/test/testfiles/basic_formatting/expected-error.txt +0 -0
  20. data/test/testfiles/basic_formatting/expected-output.txt +10 -0
  21. data/test/testfiles/basic_formatting/source.ltx +8 -0
  22. data/test/testfiles/block_comment/expected-error.txt +0 -0
  23. data/test/testfiles/block_comment/expected-output.txt +5 -0
  24. data/test/testfiles/block_comment/source.ltx +19 -0
  25. data/test/testfiles/comments_ignored_1/expected-error.txt +0 -0
  26. data/test/testfiles/comments_ignored_1/expected-output.txt +4 -0
  27. data/test/testfiles/comments_ignored_1/source.ltx +7 -0
  28. data/test/testfiles/copy_is_raw/expected-error.txt +0 -0
  29. data/test/testfiles/copy_is_raw/expected-output.txt +7 -0
  30. data/test/testfiles/copy_is_raw/source.ltx +4 -0
  31. data/test/testfiles/def_method/expected-error.txt +2 -0
  32. data/test/testfiles/def_method/expected-output.txt +5 -0
  33. data/test/testfiles/def_method/source.ltx +10 -0
  34. data/test/testfiles/example_alpha/expected-error.txt +0 -0
  35. data/test/testfiles/example_alpha/expected-output.txt +23 -0
  36. data/test/testfiles/example_alpha/source.ltx +17 -0
  37. data/test/testfiles/example_alpha2/expected-error.txt +0 -0
  38. data/test/testfiles/example_alpha2/expected-output.txt +12 -0
  39. data/test/testfiles/example_alpha2/source.ltx +24 -0
  40. data/test/testfiles/fixit +6 -0
  41. data/test/testfiles/functions/expected-error.txt +0 -0
  42. data/test/testfiles/functions/expected-output.txt +8 -0
  43. data/test/testfiles/functions/source.ltx +11 -0
  44. data/test/testfiles/hello_world/expected-error.txt +0 -0
  45. data/test/testfiles/hello_world/expected-output.txt +2 -0
  46. data/test/testfiles/hello_world/source.ltx +2 -0
  47. data/test/testfiles/more_complex_vars/expected-error.txt +0 -0
  48. data/test/testfiles/more_complex_vars/expected-output.txt +4 -0
  49. data/test/testfiles/more_complex_vars/source.ltx +5 -0
  50. data/test/testfiles/raw_text_block/expected-error.txt +0 -0
  51. data/test/testfiles/raw_text_block/expected-output.txt +14 -0
  52. data/test/testfiles/raw_text_block/source.ltx +16 -0
  53. data/test/testfiles/sigil_can_change/expected-error.txt +0 -0
  54. data/test/testfiles/sigil_can_change/expected-output.txt +6 -0
  55. data/test/testfiles/sigil_can_change/source.ltx +11 -0
  56. data/test/testfiles/simple_copy/expected-error.txt +0 -0
  57. data/test/testfiles/simple_copy/expected-output.txt +7 -0
  58. data/test/testfiles/simple_copy/source.ltx +6 -0
  59. data/test/testfiles/simple_include/expected-error.txt +0 -0
  60. data/test/testfiles/simple_include/expected-output.txt +7 -0
  61. data/test/testfiles/simple_include/source.ltx +6 -0
  62. data/test/testfiles/simple_mixin/expected-error.txt +0 -0
  63. data/test/testfiles/simple_mixin/expected-output.txt +5 -0
  64. data/test/testfiles/simple_mixin/source.ltx +6 -0
  65. data/test/testfiles/simple_vars/expected-error.txt +0 -0
  66. data/test/testfiles/simple_vars/expected-output.txt +6 -0
  67. data/test/testfiles/simple_vars/source.ltx +7 -0
  68. data/test/testfiles/single_raw_line/expected-error.txt +0 -0
  69. data/test/testfiles/single_raw_line/expected-output.txt +10 -0
  70. data/test/testfiles/single_raw_line/source.ltx +8 -0
  71. metadata +76 -9
  72. data/dlt +0 -1
data/lib/livemagick.rb ADDED
@@ -0,0 +1,131 @@
1
+ require 'rmagick'
2
+ include ::Magick
3
+
4
+ def image
5
+ xx, yy, bg = _args
6
+ xx, yy = xx.to_i, yy.to_i
7
+ @image = Image.new(xx,yy) { self.background_color = bg }
8
+ _optional_blank_line
9
+ end
10
+
11
+ def canvas
12
+ color, width, opacity = _args
13
+ opacity, width = opacity.to_i, width.to_i
14
+ @canvas = Draw.new
15
+ @canvas.fill_opacity(0)
16
+ @canvas.stroke('black')
17
+ @canvas.stroke_width(1)
18
+ _optional_blank_line
19
+ end
20
+
21
+ def rectangle
22
+ xy, wxh, stroke_color, stroke_width = _args
23
+ x, y = xy.split(",").map(&:to_i)
24
+ width, height = wxh.split("x").map(&:to_i)
25
+ stroke_width = stroke_width.to_i
26
+ _debug "rectangle: x=#{x} y=#{y} width=#{width} height=#{height} "
27
+ @canvas.stroke(stroke_color)
28
+ @canvas.stroke_width(stroke_width)
29
+ @canvas.rectangle(x, y, x+width, y+height)
30
+ end
31
+
32
+ def pen
33
+ @fill, @stroke = _args
34
+ @stroke = "black" if @stroke.nil? || @stroke.empty?
35
+ _debug "pen: fill=#@fill stroke=#@stroke"
36
+ _optional_blank_line
37
+ end
38
+
39
+ def font
40
+ size, font = _args
41
+ font = "Helvetica" if font.nil? || font.empty?
42
+ size = "32" if size.nil? || size.empty?
43
+ @size, @font = size.to_i, font
44
+ _debug "font: size=#@size font=#@font"
45
+ _optional_blank_line
46
+ end
47
+
48
+ def _text(xy, wxh, str, weight, gravity)
49
+ x, y = xy.split(",").map(&:to_i)
50
+ width, height = wxh.split("x").map(&:to_i)
51
+ font, fill, stroke, size = @font, @fill, @stroke, @size
52
+ @canvas.annotate(@image, width, height, x, y, str) do
53
+ self.font_family = font
54
+ self.fill = fill
55
+ self.stroke = stroke
56
+ self.pointsize = size
57
+ self.font_weight = weight
58
+ self.gravity = gravity
59
+ end
60
+ end
61
+
62
+ def text
63
+ xy, wxh, str = _data.split
64
+ weight, gravity = BoldWeight, CenterGravity
65
+ _text(xy, wxh, str, weight, gravity)
66
+ _optional_blank_line
67
+ end
68
+
69
+ def text!
70
+ xy, wxh = _data.split
71
+ str = _body.join
72
+ weight, gravity = BoldWeight, CenterGravity
73
+ _text(xy, wxh, str, weight, gravity)
74
+ _optional_blank_line
75
+ end
76
+
77
+ def draw
78
+ @canvas.draw(@image)
79
+ _optional_blank_line
80
+ end
81
+
82
+ def save
83
+ @image.write(_args.first)
84
+ _optional_blank_line
85
+ end
86
+
87
+ def save!
88
+ save
89
+ system("open #{_args.first}")
90
+ _optional_blank_line
91
+ end
92
+
93
+ =begin
94
+ draw.annotate(img, width, height, x, y, text) [ { additional parameters } ] -> draw
95
+ Description
96
+
97
+ Annotates a image with text. The text is positioned according to the gravity attribute around the rectangle described by the x, y, width, and height arguments. If either of the width or height arguments are 0, uses the image width-x and the image height-y to compute the rectangle width and height. The attributes described in annotate attributes, below, influence the appearance and position of the text. These attributes may be set in the Draw object before calling annotate, or within annotate's optional additional parameters block.
98
+
99
+ Note: all of the annotate attributes are set-only.
100
+ Arguments
101
+
102
+ img
103
+ the image or imagelist to be annotated
104
+ width
105
+ width of the rectangle within which the text is positioned
106
+ height
107
+ height of the rectangle within which the text is positioned
108
+ x
109
+ x offset of the rectangle
110
+ y
111
+ y offset of the rectangle
112
+ text
113
+ the text
114
+
115
+ Returns
116
+
117
+ self
118
+ Example
119
+
120
+ This example is an excerpt of colors.rb. Many other examples also use annotate.
121
+
122
+ title.annotate(montage, 0,0,0,40, 'Named Colors') {
123
+ self.font_family = 'Helvetica'
124
+ self.fill = 'white'
125
+ self.stroke = 'transparent'
126
+ self.pointsize = 32
127
+ self.font_weight = BoldWeight
128
+ self.gravity = NorthGravity
129
+ }
130
+
131
+ =end
data/lib/livetext.rb ADDED
@@ -0,0 +1,605 @@
1
+ require 'fileutils'
2
+
3
+ CWD = "." # File.dirname(__FILE__)
4
+
5
+ TTY = ::File.open("/dev/tty", "w")
6
+
7
+ require_relative "./pyggish"
8
+
9
+ class Enumerator
10
+ def remaining
11
+ array = []
12
+ loop { array << self.next }
13
+ array
14
+ end
15
+ end
16
+
17
+ class Livetext
18
+ VERSION = "0.5.3"
19
+
20
+ MainSigil = "."
21
+ Sigils = [MainSigil]
22
+ Space = " "
23
+
24
+ Objects = { MainSigil => nil }
25
+
26
+ Disallowed = [:_data=, :nil?, :===, :=~, :!~, :eql?, :hash, :<=>,
27
+ :class, :singleton_class, :clone, :dup, :taint, :tainted?,
28
+ :untaint, :untrust, :untrusted?, :trust, :freeze, :frozen?,
29
+ :to_s, :inspect, :methods, :singleton_methods, :protected_methods,
30
+ :private_methods, :public_methods, :instance_variables,
31
+ :instance_variable_get, :instance_variable_set,
32
+ :instance_variable_defined?, :remove_instance_variable,
33
+ :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send,
34
+ :respond_to?, :extend, :display, :method, :public_method,
35
+ :singleton_method, :define_singleton_method, :object_id, :to_enum,
36
+ :enum_for, :pretty_inspect, :==, :equal?, :!, :!=, :instance_eval,
37
+ :instance_exec, :__send__, :__id__, :__binding__]
38
+
39
+ class << self
40
+ attr_reader :main
41
+ end
42
+
43
+ def self.handle_line(line)
44
+ nomarkup = true
45
+ Livetext::Sigils.each do |sigil|
46
+ scomment = rx(sigil, Livetext::Space) # apply these in order
47
+ sname = rx(sigil)
48
+ case
49
+ when line =~ scomment
50
+ handle_scomment(sigil, line)
51
+ when line =~ sname
52
+ handle_sname(sigil, line)
53
+ else
54
+ obj = Livetext::Objects[sigil]
55
+ obj._passthru(line)
56
+ end
57
+ end
58
+ end
59
+
60
+
61
+ def self.handle_file(file)
62
+ file = File.new(file) if file.is_a? String
63
+ source = file.each_line
64
+ @main = Livetext::Objects[Livetext::MainSigil] = Livetext::System.new(source)
65
+ @main.file = ARGV[0]
66
+ @main.lnum = 0
67
+
68
+ loop do
69
+ line = @main._next_line
70
+ handle_line(line)
71
+ end
72
+
73
+ val = @main.finalize if @main.respond_to?(:finalize)
74
+ val
75
+ rescue => err
76
+ STDERR.puts "handle_file: #{err}"
77
+ end
78
+
79
+ def self.rx(str, space=nil)
80
+ Regexp.compile("^" + Regexp.escape(str) + "#{space}")
81
+ end
82
+
83
+ def self.handle_scomment(sigil, line)
84
+ end
85
+
86
+ def self._disallowed?(name)
87
+ Livetext::Disallowed.include?(name.to_sym)
88
+ end
89
+
90
+ def self._get_name(obj, sigil, line)
91
+ blank = line.index(" ") || line.index("\n")
92
+ name = line[1..(blank-1)]
93
+ abort "#{obj.where}: Name '#{name}' is not permitted" if _disallowed?(name)
94
+ obj._data = line[(blank+1)..-1]
95
+ name = "_def" if name == "def"
96
+ name = "_include" if name == "include"
97
+ abort "#{obj.where}: mismatched 'end'" if name == "end"
98
+ name
99
+ end
100
+
101
+ def self.handle_sname(sigil, line)
102
+ obj = Livetext::Objects[sigil]
103
+ name = _get_name(obj, sigil, line)
104
+ unless obj.respond_to?(name)
105
+ abort "#{obj.where}: '#{name}' is unknown"
106
+ return
107
+ end
108
+
109
+ if name == "notes"
110
+ obj.notes
111
+ else
112
+ obj.send(name)
113
+ end
114
+ rescue => err
115
+ STDERR.puts "ERROR on #{obj.file} line #{obj.lnum}"
116
+ STDERR.puts err.backtrace
117
+ end
118
+
119
+ end
120
+
121
+ class Livetext::Functions # Functions will go here... user-def AND pre-def??
122
+ def date
123
+ Time.now.strftime("%F")
124
+ end
125
+
126
+ def time
127
+ Time.now.strftime("%F")
128
+ end
129
+ end
130
+
131
+ module Livetext::Helpers
132
+ def _source
133
+ @input
134
+ end
135
+
136
+ def _data=(str)
137
+ str ||= ""
138
+ @_data = str
139
+ @_args = str.split
140
+ end
141
+
142
+ def _data
143
+ @_data
144
+ end
145
+
146
+ def _args
147
+ if block_given?
148
+ @_args.each {|arg| yield arg }
149
+ else
150
+ @_args
151
+ end
152
+ end
153
+
154
+ def _optional_blank_line
155
+ @line = _next_line if _peek_next_line =~ /^ *$/
156
+ end
157
+
158
+ def _comment?(str, sigil=Livetext::MainSigil)
159
+ c1 = sigil + Livetext::Space
160
+ c2 = sigil + sigil + Livetext::Space
161
+ str.index(c1) == 0 || str.index(c2) == 0
162
+ end
163
+
164
+ def _trailing?(char)
165
+ return true if ["\n", " ", nil].include?(char)
166
+ return false
167
+ end
168
+
169
+ def _end?(str, sigil=Livetext::MainSigil)
170
+ cmd = sigil + "end"
171
+ return false if str.index(cmd) != 0
172
+ return false unless _trailing?(str[5])
173
+ return true
174
+ end
175
+
176
+ def _raw_body(tag = "__EOF__", sigil = Livetext::MainSigil)
177
+ lines = []
178
+ loop do
179
+ @line = _next_line
180
+ break if @line.chomp.strip == tag
181
+ lines << @line
182
+ end
183
+ _optional_blank_line
184
+ if block_given?
185
+ lines.each {|line| yield @line }
186
+ else
187
+ lines
188
+ end
189
+ end
190
+
191
+ def _body(sigil=Livetext::MainSigil)
192
+ lines = []
193
+ loop do
194
+ @line = _next_line # no chomp needed
195
+ break if _end?(@line, sigil)
196
+ next if _comment?(@line, sigil)
197
+ lines << @line # _formatting(line) # FIXME ??
198
+ end
199
+ _optional_blank_line
200
+ if block_given?
201
+ lines.each {|line| yield line }
202
+ else
203
+ lines
204
+ end
205
+ end
206
+
207
+ def _body!(sigil=Livetext::MainSigil)
208
+ _body(sigil).join("\n")
209
+ end
210
+
211
+ def _basic_format(line, delim, tag)
212
+ s = line.each_char
213
+ c = s.next
214
+ last = nil
215
+ getch = -> { last = c; c = s.next }
216
+ buffer = ""
217
+ loop do
218
+ case c
219
+ when " "
220
+ buffer << " "
221
+ last = " "
222
+ when delim
223
+ if last == " " || last == nil
224
+ buffer << "<#{tag}>"
225
+ c = getch.call
226
+ if c == "("
227
+ loop { getch.call; break if c == ")"; buffer << c }
228
+ buffer << "</#{tag}>"
229
+ else
230
+ loop { buffer << c; getch.call; break if c == " " || c == nil || c == "\n" }
231
+ buffer << "</#{tag}>"
232
+ buffer << " " if c == " "
233
+ end
234
+ else
235
+ buffer << delim
236
+ end
237
+ else
238
+ buffer << c
239
+ end
240
+ getch.call
241
+ end
242
+ buffer
243
+ end
244
+
245
+ def _handle_escapes(str, set)
246
+ str = str.dup
247
+ set.each_char do |ch|
248
+ str.gsub!("\\#{ch}", ch)
249
+ end
250
+ str
251
+ end
252
+
253
+ def _formatting(line)
254
+ line = _basic_format(line, "_", "i")
255
+ line = _basic_format(line, "*", "b")
256
+ line = _basic_format(line, "`", "tt")
257
+ line = _handle_escapes(line, "_*`")
258
+ line
259
+ end
260
+
261
+ def OLD_formatting(line)
262
+ l2 = _formatting(line)
263
+ line.replace(l2)
264
+ return line
265
+ end
266
+
267
+ def _var_substitution(line) # FIXME handle functions separately later??
268
+ fobj = ::Livetext::Functions.new
269
+ @funcs = ::Livetext::Functions.instance_methods
270
+ @funcs.each do |func|
271
+ name = ::Regexp.escape("$$#{func}")
272
+ rx = /#{name}\b/
273
+ line.gsub!(rx) do |str|
274
+ val = fobj.send(func)
275
+ str.sub(rx, val)
276
+ end
277
+ end
278
+ @vars.each_pair do |var, val|
279
+ name = ::Regexp.escape("$#{var}")
280
+ rx = /#{name}\b/
281
+ line.gsub!(rx, val)
282
+ end
283
+ line
284
+ end
285
+
286
+ def _passthru(line)
287
+ return if @_nopass
288
+ _puts "<p>" if line == "\n" and ! @_nopara
289
+ OLD_formatting(line)
290
+ _var_substitution(line)
291
+ _puts line
292
+ end
293
+
294
+ def _puts(*args)
295
+ @output.puts *args
296
+ end
297
+
298
+ def _print(*args)
299
+ @output.print *args
300
+ end
301
+
302
+ def _peek_next_line
303
+ @input.peek
304
+ end
305
+
306
+ def _next_line
307
+ @line = @input.next
308
+ @lnum += 1
309
+ _debug "Line: #@lnum: #@line"
310
+ @line
311
+ end
312
+
313
+ def _debug=(val)
314
+ @_debug = val
315
+ end
316
+
317
+ def _debug(*args)
318
+ TTY.puts *args if @_debug
319
+ end
320
+ end
321
+
322
+ module Livetext::Standard
323
+ def comment
324
+ junk = _body # do nothing with contents
325
+ end
326
+
327
+ def shell
328
+ cmd = _data
329
+ _errout("Running: #{cmd}")
330
+ system(cmd)
331
+ end
332
+
333
+ def func
334
+ fname = @_args[0] # FIXME: don't permit 'initialize' (others?)
335
+ func_def = <<-EOS
336
+ def #{fname}
337
+ #{_body!}
338
+ end
339
+ EOS
340
+ ::Livetext::Functions.class_eval func_def
341
+ end
342
+
343
+ def shell!
344
+ cmd = _data
345
+ system(cmd)
346
+ end
347
+
348
+ def errout
349
+ TTY.puts _data
350
+ end
351
+
352
+ def say
353
+ str = _var_substitution(_data)
354
+ _optional_blank_line
355
+ end
356
+
357
+ def banner
358
+ str = _var_substitution(_data)
359
+ n = str.length - 1
360
+ _errout "-"*n
361
+ _errout str
362
+ _errout "-"*n
363
+ end
364
+
365
+ def quit
366
+ @output.close
367
+ exit
368
+ end
369
+
370
+ def outdir
371
+ @_outdir = @_args.first
372
+ _optional_blank_line
373
+ end
374
+
375
+ def outdir! # FIXME ?
376
+ @_outdir = @_args.first
377
+ raise "No output directory specified" if @_outdir.nil?
378
+ raise "No output directory specified" if @_outdir.empty?
379
+ system("rm -f #@_outdir/*.html")
380
+ _optional_blank_line
381
+ end
382
+
383
+ def _output(name)
384
+ @output.close unless @output == STDOUT
385
+ @output = File.open(@_outdir + "/" + name, "w")
386
+ @output.puts "<meta charset='UTF-8'>\n\n"
387
+ end
388
+
389
+ def _append(name)
390
+ @output.close unless @output == STDOUT
391
+ @output = File.open(@_outdir + "/" + name, "a")
392
+ @output.puts "<meta charset='UTF-8'>\n\n"
393
+ end
394
+
395
+ def output
396
+ name = @_args.first
397
+ _debug "Redirecting output to: #{name}"
398
+ _output(name)
399
+ end
400
+
401
+ def append
402
+ file = @_args[0]
403
+ _append(file)
404
+ end
405
+
406
+ def next_output
407
+ tag, num = @_args
408
+ _next_output(tag, num)
409
+ _optional_blank_line
410
+ end
411
+
412
+ def cleanup
413
+ @_args.each do |item|
414
+ if ::File.directory?(item)
415
+ system("rm -f #{item}/*")
416
+ else
417
+ ::FileUtils.rm(item)
418
+ end
419
+ end
420
+ end
421
+
422
+ def _next_output(tag = "sec", num = nil)
423
+ @_file_num = num ? num : @_file_num + 1
424
+ @_file_num = @_file_num.to_i
425
+ name = "#{'%03d' % @_file_num}-#{tag}.html"
426
+ _output(name)
427
+ end
428
+
429
+ def sigil
430
+ char = _args.first
431
+ raise "'#{char}' is not a single character" if char.length > 1
432
+ obj = Livetext::Objects[Livetext::MainSigil]
433
+ Livetext::Objects.replace(char => obj)
434
+ Livetext::MainSigil.replace(char)
435
+ _optional_blank_line
436
+ end
437
+
438
+ def _def
439
+ name = _args[0]
440
+ str = "def #{name}\n"
441
+ str += _body!
442
+ str += "end\n"
443
+ eval str
444
+ rescue => err
445
+ STDERR.puts "Syntax error in definition:\n#{err}\n#$!"
446
+ end
447
+
448
+ def nopass
449
+ @_nopass = true
450
+ end
451
+
452
+ def set
453
+ assigns = _data.chomp.split(/, */)
454
+ assigns.each do |a|
455
+ var, val = a.split("=")
456
+ val = val[1..-2] if val[0] == ?" and val[-1] == ?"
457
+ val = val[1..-2] if val[0] == ?' and val[-1] == ?'
458
+ @vars[var] = val
459
+ end
460
+ _optional_blank_line
461
+ end
462
+
463
+ def _include
464
+ file = _args.first
465
+ lines = ::File.readlines(file)
466
+ @file = file
467
+ # STDERR.puts "_include: ****** Set @file = #@file"
468
+ lines.each {|line| _debug " inc: #{line}" }
469
+ rem = @input.remaining
470
+ array = lines + rem
471
+ @input = array.each # FIXME .with_index
472
+ _optional_blank_line
473
+ end
474
+
475
+ def include!
476
+ file = _args.first
477
+ @file = file
478
+ # TTY.puts "include!: ****** file = #{file}"
479
+ existing = File.exist?(file)
480
+ return if not existing
481
+ lines = ::File.readlines(file)
482
+ File.delete(file)
483
+ lines.each {|line| _debug " inc: #{line}" }
484
+ rem = @input.remaining
485
+ array = lines + rem
486
+ @input = array.each # FIXME .with_index
487
+ _optional_blank_line
488
+ end
489
+
490
+ def mixin
491
+ name = _args.first
492
+ file = "#{CWD}/" + name + ".rb"
493
+ return if @_mixins.include?(file)
494
+ @_mixins << file
495
+ @file = file
496
+ # TTY.puts "mixin: ****** file = #{file} "
497
+ text = ::File.read(file)
498
+ self.class.class_eval(text)
499
+ init = "init_#{name}"
500
+ self.send(init) if self.respond_to? init
501
+ _optional_blank_line
502
+ end
503
+
504
+ def copy
505
+ file = _args.first
506
+ @file = file
507
+ # TTY.puts "copy: ****** file = #{file}"
508
+ @output.puts ::File.readlines(file)
509
+ _optional_blank_line
510
+ end
511
+
512
+ def r
513
+ _puts _data # No processing at all
514
+ end
515
+
516
+ def raw
517
+ # No processing at all (terminate with __EOF__)
518
+ _puts _raw_body
519
+ end
520
+
521
+ def debug
522
+ arg = _args.first
523
+ self._debug = true
524
+ self._debug = false if arg == "off"
525
+ end
526
+
527
+ def nopara
528
+ @_nopara = true
529
+ end
530
+
531
+ def heading
532
+ _print "<center><font size=+1><b>"
533
+ _print _data
534
+ _print "</b></font></center>"
535
+ end
536
+
537
+ def newpage
538
+ _puts '<p style="page-break-after:always;"></p>'
539
+ _puts "<p/>"
540
+ end
541
+
542
+ def invoke(str)
543
+ end
544
+
545
+ def dlist
546
+ delim = "~~"
547
+ _puts "<table>"
548
+ _body do |line|
549
+ # TTY.puts "Line = #{line}"
550
+ line = _formatting(line)
551
+ # TTY.puts "Line = #{line}\n "
552
+ term, defn = line.split(delim)
553
+ _puts "<tr>"
554
+ _puts "<td width=3%><td width=10%>#{term}</td><td>#{defn}</td>"
555
+ _puts "</tr>"
556
+ end
557
+ _puts "</table>"
558
+ end
559
+
560
+ end
561
+
562
+ class Livetext
563
+ METHS = (Livetext::Standard.instance_methods - Object.methods).sort
564
+ end
565
+
566
+
567
+ class Livetext::System < BasicObject
568
+ include ::Kernel
569
+ include ::Livetext::Helpers
570
+ include ::Livetext::Standard
571
+
572
+ attr_accessor :file, :lnum
573
+
574
+ def initialize(input = ::STDIN, output = ::STDOUT)
575
+ @input = input
576
+ @output = output
577
+ @vars = {}
578
+ @_mixins = []
579
+ @_outdir = "."
580
+ @_file_num = 0
581
+ @_nopass = false
582
+ @_nopara = false
583
+
584
+ @lnum = 0
585
+ end
586
+
587
+ def where
588
+ "Line #@lnum of #@file"
589
+ end
590
+
591
+ def method_missing(name, *args)
592
+ # Idea: Capture source line for error messages
593
+ _puts " Error: Method '#{name}' is not defined."
594
+ puts caller.map {|x| " " + x }
595
+ exit
596
+ end
597
+ end
598
+
599
+ ### FIXME - these are all top-level methods
600
+
601
+
602
+ if $0 == __FILE__
603
+ Livetext.handle_file(ARGV[0] || STDIN)
604
+ end
605
+