livetext 0.5.2 → 0.5.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/livetext +20 -0
- data/lib/bookish.rb +212 -0
- data/lib/calibre.rb +24 -0
- data/lib/liveblog.rb +195 -0
- data/lib/livemagick.rb +131 -0
- data/lib/livetext.rb +605 -0
- data/lib/markdown.rb +30 -0
- data/lib/pyggish.rb +194 -0
- data/lib/tutorial.rb +89 -0
- data/livetext-0.5.2.gem +0 -0
- data/livetext.gemspec +99 -4
- data/test/cleanup +1 -0
- data/test/newtest +10 -0
- data/test/rawtext.inc +4 -0
- data/test/simple_mixin.rb +3 -0
- data/test/simplefile.inc +2 -0
- data/test/test.rb +77 -0
- data/test/testfiles/basic_formatting/expected-error.txt +0 -0
- data/test/testfiles/basic_formatting/expected-output.txt +10 -0
- data/test/testfiles/basic_formatting/source.ltx +8 -0
- data/test/testfiles/block_comment/expected-error.txt +0 -0
- data/test/testfiles/block_comment/expected-output.txt +5 -0
- data/test/testfiles/block_comment/source.ltx +19 -0
- data/test/testfiles/comments_ignored_1/expected-error.txt +0 -0
- data/test/testfiles/comments_ignored_1/expected-output.txt +4 -0
- data/test/testfiles/comments_ignored_1/source.ltx +7 -0
- data/test/testfiles/copy_is_raw/expected-error.txt +0 -0
- data/test/testfiles/copy_is_raw/expected-output.txt +7 -0
- data/test/testfiles/copy_is_raw/source.ltx +4 -0
- data/test/testfiles/def_method/expected-error.txt +2 -0
- data/test/testfiles/def_method/expected-output.txt +5 -0
- data/test/testfiles/def_method/source.ltx +10 -0
- data/test/testfiles/example_alpha/expected-error.txt +0 -0
- data/test/testfiles/example_alpha/expected-output.txt +23 -0
- data/test/testfiles/example_alpha/source.ltx +17 -0
- data/test/testfiles/example_alpha2/expected-error.txt +0 -0
- data/test/testfiles/example_alpha2/expected-output.txt +12 -0
- data/test/testfiles/example_alpha2/source.ltx +24 -0
- data/test/testfiles/fixit +6 -0
- data/test/testfiles/functions/expected-error.txt +0 -0
- data/test/testfiles/functions/expected-output.txt +8 -0
- data/test/testfiles/functions/source.ltx +11 -0
- data/test/testfiles/hello_world/expected-error.txt +0 -0
- data/test/testfiles/hello_world/expected-output.txt +2 -0
- data/test/testfiles/hello_world/source.ltx +2 -0
- data/test/testfiles/more_complex_vars/expected-error.txt +0 -0
- data/test/testfiles/more_complex_vars/expected-output.txt +4 -0
- data/test/testfiles/more_complex_vars/source.ltx +5 -0
- data/test/testfiles/raw_text_block/expected-error.txt +0 -0
- data/test/testfiles/raw_text_block/expected-output.txt +14 -0
- data/test/testfiles/raw_text_block/source.ltx +16 -0
- data/test/testfiles/sigil_can_change/expected-error.txt +0 -0
- data/test/testfiles/sigil_can_change/expected-output.txt +6 -0
- data/test/testfiles/sigil_can_change/source.ltx +11 -0
- data/test/testfiles/simple_copy/expected-error.txt +0 -0
- data/test/testfiles/simple_copy/expected-output.txt +7 -0
- data/test/testfiles/simple_copy/source.ltx +6 -0
- data/test/testfiles/simple_include/expected-error.txt +0 -0
- data/test/testfiles/simple_include/expected-output.txt +7 -0
- data/test/testfiles/simple_include/source.ltx +6 -0
- data/test/testfiles/simple_mixin/expected-error.txt +0 -0
- data/test/testfiles/simple_mixin/expected-output.txt +5 -0
- data/test/testfiles/simple_mixin/source.ltx +6 -0
- data/test/testfiles/simple_vars/expected-error.txt +0 -0
- data/test/testfiles/simple_vars/expected-output.txt +6 -0
- data/test/testfiles/simple_vars/source.ltx +7 -0
- data/test/testfiles/single_raw_line/expected-error.txt +0 -0
- data/test/testfiles/single_raw_line/expected-output.txt +10 -0
- data/test/testfiles/single_raw_line/source.ltx +8 -0
- metadata +76 -9
- 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
|
+
|