livetext 0.9.30 → 0.9.33

Sign up to get free protection for your applications and to get access to all the features.
@@ -17,6 +17,8 @@ module Livetext::Standard
17
17
  include HTMLHelper
18
18
  include Livetext::Helpers
19
19
 
20
+ TTY = ::File.open("/dev/tty", "w")
21
+
20
22
  SimpleFormats = # Move this?
21
23
  { b: %w[<b> </b>],
22
24
  i: %w[<i> </i>],
@@ -25,18 +27,9 @@ module Livetext::Standard
25
27
 
26
28
  attr_reader :data
27
29
 
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 = []
35
- end
36
-
37
30
  # dumb name - bold, italic, teletype, striketrough
38
31
 
39
- def bits(args = nil, body = nil) # FIXME umm what is this?
32
+ def bits # FIXME umm what is this?
40
33
  b0, b1, i0, i1, t0, t1, s0, s1 = *api.args
41
34
  SimpleFormats[:b] = [b0, b1]
42
35
  SimpleFormats[:i] = [i0, i1]
@@ -51,29 +44,29 @@ module Livetext::Standard
51
44
  # end
52
45
  # end
53
46
 
54
- def backtrace(args = nil, body = nil)
47
+ def backtrace
55
48
  @backtrace = onoff(api.args.first)
56
49
  api.optional_blank_line
57
50
  end
58
51
 
59
- def comment(args = nil, body = nil)
52
+ def comment
60
53
  api.body
61
54
  api.optional_blank_line
62
55
  end
63
56
 
64
- def shell(args = nil, body = nil)
57
+ def shell
65
58
  cmd = api.data
66
59
  system(cmd)
67
60
  api.optional_blank_line
68
61
  end
69
62
 
70
- def func(args = nil, body = nil)
63
+ def func
71
64
  funcname = api.args[0]
72
65
  # check_disallowed(funcname) # should any be invalid?
73
66
  funcname = funcname.gsub(/\./, "__")
74
67
  func_def = <<~EOS
75
68
  def #{funcname}(param)
76
- #{api.body.to_a.join("\n")}
69
+ #{api.body(true).to_a.join("\n")}
77
70
  end
78
71
  EOS
79
72
  api.optional_blank_line
@@ -81,21 +74,21 @@ module Livetext::Standard
81
74
  return true
82
75
  end
83
76
 
84
- def h1(args = nil, body = nil); api.out wrapped(api.data, :h1); return true; end
85
- def h2(args = nil, body = nil); api.out wrapped(api.data, :h2); return true; end
86
- def h3(args = nil, body = nil); api.out wrapped(api.data, :h3); return true; end
87
- def h4(args = nil, body = nil); api.out wrapped(api.data, :h4); return true; end
88
- def h5(args = nil, body = nil); api.out wrapped(api.data, :h5); return true; end
89
- def h6(args = nil, body = nil); api.out wrapped(api.data, :h6); return true; end
77
+ def h1; api.out wrapped(api.data, :h1); return true; end
78
+ def h2; api.out wrapped(api.data, :h2); return true; end
79
+ def h3; api.out wrapped(api.data, :h3); return true; end
80
+ def h4; api.out wrapped(api.data, :h4); return true; end
81
+ def h5; api.out wrapped(api.data, :h5); return true; end
82
+ def h6; api.out wrapped(api.data, :h6); return true; end
90
83
 
91
- def list(args = nil, body = nil)
84
+ def list
92
85
  wrap :ul do
93
86
  api.body {|line| api.out wrapped(line, :li) }
94
87
  end
95
88
  api.optional_blank_line
96
89
  end
97
90
 
98
- def list!(args = nil, body = nil)
91
+ def list!
99
92
  wrap(:ul) do
100
93
  lines = api.body.each # enumerator
101
94
  loop do
@@ -108,40 +101,40 @@ module Livetext::Standard
108
101
  api.optional_blank_line
109
102
  end
110
103
 
111
- def shell!(args = nil, body = nil)
104
+ def shell!
112
105
  cmd = api.data
113
106
  system(cmd)
114
107
  api.optional_blank_line
115
108
  end
116
109
 
117
- def errout(args = nil, body = nil)
110
+ def errout
118
111
  ::STDERR.puts api.data
119
112
  api.optional_blank_line
120
113
  end
121
114
 
122
- def ttyout(args = nil, body = nil)
115
+ def ttyout
123
116
  TTY.puts api.data
124
117
  api.optional_blank_line
125
118
  end
126
119
 
127
- def say(args = nil, body = nil)
120
+ def say
128
121
  str = api.format(api.data)
129
122
  TTY.puts str
130
123
  api.optional_blank_line
131
124
  end
132
125
 
133
- def banner(args = nil, body = nil)
126
+ def banner
134
127
  str = api.format(api.data)
135
128
  num = str.length
136
129
  decor = "-"*num + "\n"
137
130
  puts decor + str + "\n" + decor
138
131
  end
139
132
 
140
- def quit(args = nil, body = nil)
133
+ def quit
141
134
  @output.close
142
135
  end
143
136
 
144
- def cleanup(args = nil, body = nil)
137
+ def cleanup
145
138
  api.args.each do |item|
146
139
  cmd = ::File.directory?(item) ? "rm -f #{item}/*" : "rm #{item}"
147
140
  system(cmd)
@@ -149,13 +142,9 @@ module Livetext::Standard
149
142
  api.optional_blank_line
150
143
  end
151
144
 
152
- def dot_def(args = nil, body = nil)
153
- # api.tty "in #{__FILE__}: api id = #{api.inspect}"
145
+ def dot_def
154
146
  name = api.args[0]
155
- # api.tty :dd1
156
- # api.tty name.inspect
157
147
  check_disallowed(name)
158
- # api.tty :dd2
159
148
  # Difficult to avoid eval here
160
149
  str = "def #{name}\n"
161
150
  str << api.body(true).join("\n")
@@ -164,7 +153,7 @@ module Livetext::Standard
164
153
  api.optional_blank_line
165
154
  end
166
155
 
167
- def set(args = nil, body = nil)
156
+ def set
168
157
  line = api.args.join(" ") # data.chomp
169
158
  pairs = Livetext::ParseSet.new(line).parse
170
159
  api.setvars(pairs)
@@ -173,7 +162,7 @@ module Livetext::Standard
173
162
 
174
163
  # FIXME really these should be one method...
175
164
 
176
- def variables!(args = nil, body = nil) # cwd, not FileDir - weird, fix later
165
+ def variables! # cwd, not FileDir - weird, fix later
177
166
  prefix = api.args[0]
178
167
  file = api.args[1]
179
168
  prefix = nil if prefix == "-" # FIXME dumb hack
@@ -184,12 +173,11 @@ module Livetext::Standard
184
173
  lines = api.body
185
174
  end
186
175
  pairs = Livetext::ParseGeneral.parse_vars(lines, prefix: nil)
187
- STDERR.puts "! pairs = #{pairs.inspect}"
188
176
  api.setvars(pairs)
189
177
  api.optional_blank_line
190
178
  end
191
179
 
192
- def variables(args = nil, body = nil)
180
+ def variables
193
181
  prefix = api.args[0]
194
182
  file = api.args[1]
195
183
  prefix = nil if prefix == "-" # FIXME dumb hack
@@ -200,12 +188,11 @@ STDERR.puts "! pairs = #{pairs.inspect}"
200
188
  lines = api.body
201
189
  end
202
190
  pairs = Livetext::ParseGeneral.parse_vars(lines, prefix: nil)
203
- STDERR.puts "pairs = #{pairs.inspect}"
204
191
  api.setvars(pairs)
205
192
  api.optional_blank_line
206
193
  end
207
194
 
208
- def heredoc(args = nil, body = nil)
195
+ def heredoc
209
196
  var = api.args[0]
210
197
  text = api.body.join("\n")
211
198
  rhs = ""
@@ -215,11 +202,11 @@ STDERR.puts "pairs = #{pairs.inspect}"
215
202
  end
216
203
  indent = @parent.indentation.last
217
204
  indented = " " * indent
218
- api.set(var, rhs.chomp)
205
+ api.setvar(var, rhs.chomp)
219
206
  api.optional_blank_line
220
207
  end
221
208
 
222
- def seek(args = nil, body = nil) # like include, but search upward as needed
209
+ def seek # like include, but search upward as needed
223
210
  file = api.args.first
224
211
  file = search_upward(file)
225
212
  check_file_exists(file)
@@ -227,14 +214,14 @@ STDERR.puts "pairs = #{pairs.inspect}"
227
214
  api.optional_blank_line
228
215
  end
229
216
 
230
- def dot_include(args = nil, body = nil) # dot command
231
- file = api.format(api.args.first) # allows for variables
217
+ def dot_include # dot command
218
+ file = api.expand_variables(api.args.first) # allows for variables
232
219
  check_file_exists(file)
233
220
  @parent.process_file(file)
234
221
  api.optional_blank_line
235
222
  end
236
223
 
237
- def inherit(args = nil, body = nil)
224
+ def inherit
238
225
  file = api.args.first
239
226
  upper = "../#{file}"
240
227
  got_upper, got_file = File.exist?(upper), File.exist?(file)
@@ -246,8 +233,9 @@ STDERR.puts "pairs = #{pairs.inspect}"
246
233
  api.optional_blank_line
247
234
  end
248
235
 
249
- def mixin(args = nil, body = nil)
236
+ def mixin
250
237
  name = api.args.first # Expect a module name
238
+ @mixins ||= []
251
239
  return if @mixins.include?(name)
252
240
  @mixins << name
253
241
  mod = Livetext::Handler::Mixin.get_module(name, @parent)
@@ -257,8 +245,9 @@ STDERR.puts "pairs = #{pairs.inspect}"
257
245
  api.optional_blank_line
258
246
  end
259
247
 
260
- def import(args = nil, body = nil)
248
+ def import
261
249
  name = api.args.first # Expect a module name
250
+ @imports ||= []
262
251
  return if @imports.include?(name)
263
252
  @imports << name
264
253
  mod = Livetext::Handler::Import.get_module(name, @parent)
@@ -268,7 +257,7 @@ STDERR.puts "pairs = #{pairs.inspect}"
268
257
  api.optional_blank_line
269
258
  end
270
259
 
271
- def copy(args = nil, body = nil)
260
+ def copy
272
261
  file = api.args.first
273
262
  ok = check_file_exists(file)
274
263
 
@@ -278,67 +267,67 @@ STDERR.puts "pairs = #{pairs.inspect}"
278
267
  [ok, file]
279
268
  end
280
269
 
281
- def r(args = nil, body = nil)
270
+ def r
282
271
  # FIXME api.data is broken
283
272
  # api.out api.data # No processing at all
284
273
  api.out api.args.join(" ")
285
274
  api.optional_blank_line
286
275
  end
287
276
 
288
- def raw(args = nil, body = nil)
277
+ def raw
289
278
  # No processing at all (terminate with __EOF__)
290
279
  api.raw_body {|line| api.out line } # no formatting
291
280
  api.optional_blank_line
292
281
  end
293
282
 
294
- def debug(args = nil, body = nil)
283
+ def debug
295
284
  self._debug = onoff(api.args.first)
296
285
  api.optional_blank_line
297
286
  end
298
287
 
299
- def passthru(args = nil, body = nil)
288
+ def passthru
300
289
  # FIXME - add check for args size? (helpers)
301
290
  @nopass = ! onoff(api.args.first)
302
291
  api.optional_blank_line
303
292
  end
304
293
 
305
- def nopass(args = nil, body = nil)
294
+ def nopass
306
295
  @nopass = true
307
296
  api.optional_blank_line
308
297
  end
309
298
 
310
- def para(args = nil, body = nil)
299
+ def para
311
300
  # FIXME - add check for args size? (helpers)
312
301
  @nopara = ! onoff(api.args.first)
313
302
  api.optional_blank_line
314
303
  end
315
304
 
316
- def nopara(args = nil, body = nil)
305
+ def nopara
317
306
  @nopara = true
318
307
  api.optional_blank_line
319
308
  end
320
309
 
321
- def heading(args = nil, body = nil)
310
+ def heading
322
311
  api.print "<center><font size=+1><b>"
323
312
  api.print api.data
324
313
  api.print "</b></font></center>"
325
314
  api.optional_blank_line
326
315
  end
327
316
 
328
- def newpage(args = nil, body = nil)
317
+ def newpage
329
318
  api.out '<p style="page-break-after:always;"></p>'
330
319
  api.out "<p/>"
331
320
  api.optional_blank_line
332
321
  end
333
322
 
334
- def mono(args = nil, body = nil)
323
+ def mono
335
324
  wrap ":pre" do
336
325
  api.body(true) {|line| api.out line }
337
326
  end
338
327
  api.optional_blank_line
339
328
  end
340
329
 
341
- def dlist(args = nil, body = nil)
330
+ def dlist
342
331
  delim = api.args.first
343
332
  wrap(:dl) do
344
333
  api.body do |line|
@@ -351,15 +340,14 @@ STDERR.puts "pairs = #{pairs.inspect}"
351
340
  api.optional_blank_line
352
341
  end
353
342
 
354
- def link(args = nil, body = nil)
343
+ def link
355
344
  url = api.args.first
356
345
  text = api.args[2..-1].join(" ")
357
346
  api.out "<a style='text-decoration: none' href='#{url}'>#{text}</a>"
358
347
  api.optional_blank_line
359
348
  end
360
349
 
361
- def xtable(args = nil, body = nil) # Borrowed from bookish - FIXME
362
- # TTY.puts "=== #{__method__} #{__FILE__} #{__LINE__}"
350
+ def xtable # Borrowed from bookish - FIXME
363
351
  title = api.data
364
352
  delim = " :: "
365
353
  api.out "<br><center><table width=90% cellpadding=5>"
@@ -389,13 +377,13 @@ STDERR.puts "pairs = #{pairs.inspect}"
389
377
  api.optional_blank_line
390
378
  end
391
379
 
392
- def image(args = nil, body = nil)
380
+ def image
393
381
  name = api.args[0]
394
382
  api.out "<img src='#{name}'></img>"
395
383
  api.optional_blank_line
396
384
  end
397
385
 
398
- def br(args = nil, body = nil)
386
+ def br
399
387
  num = api.args.first || "1"
400
388
  str = ""
401
389
  num.to_i.times { str << "<br>" }
@@ -31,13 +31,26 @@ class Livetext::UserAPI
31
31
  @live
32
32
  end
33
33
 
34
+ def include_file(file)
35
+ api.data = file
36
+ api.dot_include
37
+ end
38
+
39
+ def expand_variables(str)
40
+ @expander.expand_variables(str)
41
+ end
42
+
43
+ def expand_functions(str)
44
+ @expander.expand_functions(str)
45
+ end
46
+
34
47
  def setvar(var, val) # FIXME
35
- # Livetext::Vars[var] = val # Now indifferent and "safe"
36
48
  @live.vars.set(var, val)
37
49
  end
38
50
 
39
51
  def setvars(pairs)
40
- pairs = pairs.to_a if pairs.is_a?(Hash)
52
+ # STDERR.puts "#{__method__}: pairs = #{pairs.inspect} (#{pairs.class})"
53
+ pairs = pairs.to_a # could be Hash or Variables
41
54
  pairs.each do |var, value|
42
55
  @live.vars.set(var, value)
43
56
  end
@@ -48,8 +61,9 @@ class Livetext::UserAPI
48
61
  end
49
62
 
50
63
  def data=(value)
51
- @data = value
52
- @args = format(@data).chomp.split
64
+ @data = value.dup
65
+ # @args = format(@data).chomp.split
66
+ @data
53
67
  end
54
68
 
55
69
  def data
@@ -135,7 +149,6 @@ class Livetext::UserAPI
135
149
  end
136
150
 
137
151
  def format(line)
138
- return "" if line == "\n" || line.nil?
139
152
  line2 = @expander.format(line)
140
153
  line2
141
154
  end
@@ -2,5 +2,5 @@
2
2
  # Defining VERSION
3
3
 
4
4
  class Livetext
5
- VERSION = "0.9.30"
5
+ VERSION = "0.9.33"
6
6
  end
data/plugin/bookish.rb CHANGED
@@ -173,7 +173,7 @@ def simple_table(args = nil, body = nil)
173
173
  lines = api.body(true)
174
174
  maxw = nil
175
175
  lines.each do |line|
176
- api.format(line)
176
+ # api.format(line)
177
177
  cells = line.split(delim)
178
178
  wide = cells.map {|x| x.length }
179
179
  maxw = [0] * cells.size
@@ -0,0 +1,149 @@
1
+ The testgen.rb tool takes a .txt and generates a corresponding file
2
+ of MiniTest code.
3
+
4
+ $ ruby testgen.rb variables.txt # produces variables.rb
5
+
6
+ The tests here include:
7
+
8
+ variables.txt Variable expansion
9
+ functions.txt Function call evaluation
10
+ single.txt Single sigil (see Formatting below)
11
+ double.txt Double sigil (see Formatting below)
12
+ bracketed.txt Bracketed sigil (see Formatting below)
13
+
14
+
15
+ Variables:
16
+ ----------
17
+
18
+ 1. A variable begins with a $ and is followed by an alpha; periods may
19
+ be embedded, but each separate piece must "look like" an identifier
20
+
21
+ $x yes
22
+ $xyz yes
23
+ $xyz.abc yes
24
+ $x123 yes
25
+ $x.123 no
26
+ $345 no
27
+
28
+ 2. Rather than causing an error, invalid variables are rendered "as-is"
29
+ as soon as possible:
30
+ " $ " => " $ "
31
+ " $5 " => " $5 "
32
+ "...$" => "...$" (end of line)
33
+
34
+ 3. Actual variables may be user-defined or predefined. The latter usually
35
+ begin with a capital. This is only a convention so far, nothing that is
36
+ enforced.
37
+
38
+ 4. The $ may be escaped as needed. This is problematic.
39
+
40
+ 5. An unknown variable will not raise an error, but will be replaced with
41
+ a warning string.
42
+
43
+
44
+ Functions:
45
+ ----------
46
+
47
+ 1. A function looks like a variable name, but it has two $ in front.
48
+
49
+ 2. If followed by space, comma, end of line, or similar delimiter, it is
50
+ called with no parameter.
51
+
52
+ 3. Note that a function name may contain periods, but may not end with
53
+ one. "$$func." is parsed as a function call (with no parameter) plus a
54
+ period.
55
+
56
+ 4. Use a colon to pass a single parameter delimited by a space or end of line.
57
+ Colon at end of line is valid but probably pointless.
58
+
59
+ 5. Use brackets to pass a single parameter that contains spaces. The bracketed
60
+ parameter may be terminated by end of line instead of right bracket.
61
+
62
+ 6. Only one parameter (a string) may be passed, but the function may parse it
63
+ however it needs to.
64
+
65
+ 7. There is no enforcement of a parameter being "present or absent" except what
66
+ the function itself may enforce.
67
+
68
+ 8. An unknown function will not raise an error, but will be replaced with a warning
69
+ string.
70
+
71
+
72
+ Formatting:
73
+ -----------
74
+
75
+ 1. My formatting notation would be considered quirky by many people.
76
+ The sigils or markers are:
77
+ * bold
78
+ _ underscore
79
+ ` code/teletype
80
+ ~ strikethrough
81
+
82
+ 1. A single sigil is recognized basically at beginning of line or after a space.
83
+ my_func_name No italics here
84
+ M*A*S*H No boldface here
85
+
86
+ 2. A single sigil is terminated by a space or end of line.
87
+
88
+ 3. A single sigil "by itself" is rendered as-is (asterisk, underscore, whatever).
89
+
90
+ 4. An escaped single sigil is rendered as-is. (This is problematic.)
91
+
92
+ 5. A double sigil is recognized at start of line or after a space
93
+
94
+ 6. A double sigil is terminated by a space OR a comma OR a period. (The comma
95
+ and period cases seem very common to me; they are the whole justification
96
+ for the double sigil.) End of line also terminates it.
97
+
98
+ 7. A double sigil by itself is rendered as-is.
99
+
100
+ 8. A bracketed sigil is in general a sigil followed by: [ data ]
101
+
102
+ 9. An empty bracketed sigil simply "goes away"
103
+ " *[] " => " "
104
+
105
+ 10. End of line can terminate instead of right bracket -- but it may still be empty
106
+ and therefore go away.
107
+
108
+ 11. NOTE: These tests use only asterisks (bold), but the logic "should" be the same
109
+ for all sigils.
110
+
111
+
112
+
113
+ Order of evaluation, etc.:
114
+ --------------------------
115
+
116
+ 1. This logic is always a compromise between syntax and the code that parses it.
117
+ I prefer simplicity whenever possible, though it may introduce complexity in
118
+ other situations. I believe that the acceptable complexity of a workaround
119
+ depends on how commonplace the situation is and how onerous the workaround is.
120
+ These are both highly subjective.
121
+
122
+ 2. For example: Note that the simple formatting sigils may not be nested. However,
123
+ there are functions like $$bits provided (with the silly mnemonic "bold, italic,
124
+ teletype, strikthrough"). Every combination is provided (e.g., $$bi, $$bt).
125
+
126
+ 3. Note also: Formatting is only intra-line; it doesn't span lines. If you need to
127
+ work around this, use a heredoc or make your own .def for this.
128
+
129
+ 4. Finally: HTML or CSS may be inserted at will (possibly with some escaping). This
130
+ can be inline or "a file at a time" via such commands as .copy and .include
131
+
132
+ 5. For these reasons: Parsing is naive and simple. Variables are parsed first.
133
+
134
+ 6. Next, function calls are parsed. I said variables are parsed first; this implies
135
+ that a variable can be embedded in a function parameter. But be aware these are
136
+ "naive" substitutions (like C macros).
137
+ .set alpha = "some value"
138
+ Calling $$myfunc:$alpha (means: Calling $$myfunc:some value)
139
+ Better to say $$myfunc[$alpha] (means: Better to say $$myfunc[some value]
140
+
141
+ 7. Formatting is handled last. The four sigils (* _ ` ~) and their three modes
142
+ (single, double, bracketed) make 12 passes necessary for formatting. As this is
143
+ always single-line, it has not been observed to cause a delay so far.
144
+
145
+ 8. The call api.format(line) essentially expands variables, calls functions, and
146
+ finally does simple formatting. See classes Expansion and Formatter.
147
+
148
+ 9. User code (e.g. inside a .def) may also call expand_variables, expand_functions,
149
+ and Formatter.format separately.