livetext 0.7.1 → 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/livetext.rb +79 -480
  3. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: df24e0cbe9a3f4391eef57d4bd0574711e65e175
4
- data.tar.gz: 891f6d330f4e6d2fd0decd0f863ac40deb1f5d77
3
+ metadata.gz: 51b98abafb62da3270ae601664283dbdeddcbd18
4
+ data.tar.gz: 579b07876a855105028a3758980784eaa45dedaa
5
5
  SHA512:
6
- metadata.gz: c36b73c36a7098e92454da35e1a6087a1bd0e50b1c351e5f6a235ca2988df79e211b47a934a68fb8aaf494cdda07e022c3607eca24d0cc9cdfa52e6bea6b7e8f
7
- data.tar.gz: 8019031d4822367265d76cfc14218d1ab3c572068091936fff7fca59187f6f82c4c17101bec018ddaa0aee05c03b8cf2fdb6a332f6f1f20c3ec44b5fadfd454b
6
+ metadata.gz: f64fa18bf90f23c2ff4626dacce8a8ced320f45eb7e0c2d3b0b43d789b9d60ea24aa59177d9eedee4a5d91c280f2a0ddfe003b2cef1716aa4fa60635d70ab15a
7
+ data.tar.gz: 38ebabd3efb44a08ae48996fc08be4e7307bfd1b6f3f426c2938333658a02768703a7f0cfc181cb4d96b83dd91744a9012579ad6c51259c55ba8670e9a7ee020
data/lib/livetext.rb CHANGED
@@ -1,5 +1,15 @@
1
+ class Livetext
2
+ VERSION = "0.7.2"
3
+ end
4
+
1
5
  require 'fileutils'
2
6
 
7
+ $: << "/Users/Hal/Desktop/Personal/Dropbox/files/livetext/lib"
8
+
9
+ require 'functions'
10
+ require 'userapi'
11
+ require 'standard'
12
+
3
13
  Plugins = File.expand_path(File.join(File.dirname(__FILE__), "../dsl"))
4
14
 
5
15
  TTY = ::File.open("/dev/tty", "w")
@@ -8,9 +18,10 @@ require_relative "#{Plugins}/pyggish"
8
18
 
9
19
 
10
20
  class Livetext
11
- VERSION = "0.7.1"
12
21
 
13
- Space = " "
22
+ class Processor
23
+ include Livetext::Standard
24
+ include Livetext::UserAPI
14
25
 
15
26
  Disallowed = [:nil?, :===, :=~, :!~, :eql?, :hash, :<=>,
16
27
  :class, :singleton_class, :clone, :dup, :taint, :tainted?,
@@ -25,17 +36,64 @@ class Livetext
25
36
  :enum_for, :pretty_inspect, :==, :equal?, :!, :!=, :instance_eval,
26
37
  :instance_exec, :__send__, :__id__, :__binding__]
27
38
 
28
- class Functions # Functions will go here... user-def AND pre-def??
29
- def date
30
- Time.now.strftime("%F")
39
+ def initialize(parent, output)
40
+ @parent = parent
41
+ @_nopass = false
42
+ @_nopara = false
43
+ @output = output
44
+ @vars = {}
45
+ @sources = []
31
46
  end
32
47
 
33
- def time
34
- Time.now.strftime("%F")
48
+ def _error!(err, abort=true, trace=false)
49
+ STDERR.puts "Error: #{err} (at #{@sources.last[1]} line #{@sources.last[2]})"
50
+ # STDERR.puts err.backtrace if err.respond_to? :backtrace # trace
51
+ exit if abort
35
52
  end
53
+
54
+ def _disallowed?(name)
55
+ Disallowed.include?(name.to_sym)
56
+ end
57
+
58
+ def source(enum, file, line)
59
+ @sources.push([enum, file, line])
60
+ end
61
+
62
+ def peek_nextline
63
+ @sources.last[0].peek
64
+ rescue StopIteration
65
+ @sources.pop
66
+ nil
67
+ end
68
+
69
+ def nextline
70
+ return nil if @sources.empty?
71
+ line = @sources.last[0].next
72
+ @sources.last[2] += 1
73
+ line
74
+ rescue StopIteration
75
+ @sources.pop
76
+ nil
77
+ end
78
+
79
+ def grab_file(fname)
80
+ File.read(fname)
81
+ end
82
+
83
+ end
84
+
85
+ ####
86
+
87
+ Space = " "
88
+
89
+ def initialize(output = ::STDOUT)
90
+ @_mixins = []
91
+ @_outdir = "."
92
+ @_file_num = 0
93
+ @main = Processor.new(self, output)
36
94
  end
37
95
 
38
- def handle_line(line, sigil=".")
96
+ def process_line(line, sigil=".")
39
97
  nomarkup = true
40
98
  # FIXME inefficient
41
99
  scomment = rx(sigil, Livetext::Space) # apply these in order
@@ -45,42 +103,21 @@ class Livetext
45
103
  elsif line =~ sname
46
104
  handle_sname(line)
47
105
  else
48
- _passthru(line)
106
+ @main._passthru(line)
49
107
  end
50
108
  end
51
109
 
52
- def peek_nextline
53
- @sources.last[0].peek
54
- rescue StopIteration
55
- @sources.pop
56
- nil
57
- end
58
-
59
- def nextline
60
- return nil if @sources.empty?
61
- line = @sources.last[0].next
62
- @sources.last[2] += 1
63
- line
64
- rescue StopIteration
65
- @sources.pop
66
- nil
67
- end
68
-
69
110
  def process_file(fname)
70
111
  enum = File.readlines(fname).each
71
- _check_existence(fname, "No such file '#{fname}' to process")
72
- @sources.push [enum, fname, 0]
112
+ raise "No such file '#{fname}' to process" unless File.exist?(fname)
113
+ @main.source(enum, fname, 0)
73
114
  loop do
74
- line = nextline
115
+ line = @main.nextline
75
116
  break if line.nil?
76
- handle_line(line)
117
+ process_line(line)
77
118
  end
78
119
  end
79
120
 
80
- def grab_file(fname)
81
- File.read(fname)
82
- end
83
-
84
121
  def rx(str, space=nil)
85
122
  Regexp.compile("^" + Regexp.escape(str) + "#{space}")
86
123
  end
@@ -88,465 +125,27 @@ class Livetext
88
125
  def handle_scomment(line, sigil=".")
89
126
  end
90
127
 
91
- def _disallowed?(name)
92
- Livetext::Disallowed.include?(name.to_sym)
93
- end
94
-
95
128
  def _get_name(line, sigil=".")
96
- name, @_data = line.split(" ", 2)
129
+ name, data = line.split(" ", 2)
97
130
  name = name[1..-1] # chop off sigil
98
- @_args = @_data.split
99
- _error! "Name '#{name}' is not permitted" if _disallowed?(name)
131
+ @main.data = data
132
+ @main._error! "Name '#{name}' is not permitted" if @main._disallowed?(name)
100
133
  name = "_def" if name == "def"
101
134
  name = "_include" if name == "include"
102
- _error! "Mismatched 'end'" if name == "end"
135
+ @main._error! "Mismatched 'end'" if name == "end"
103
136
  name
104
137
  end
105
138
 
106
139
  def handle_sname(line, sigil=".")
107
140
  name = _get_name(line, sigil=".")
108
- unless self.respond_to?(name)
109
- _error! "Name '#{name}' is unknown"
141
+ unless @main.respond_to?(name)
142
+ @main._error! "Name '#{name}' is unknown"
110
143
  return
111
144
  end
112
- self.send(name)
145
+ @main.send(name)
113
146
  rescue => err
114
- _error!(err)
115
- end
116
-
117
- # include ::Livetext::Helpers
118
- def _error!(err, abort=true, trace=false)
119
- STDERR.puts "Error: #{err} (at #{@sources.last[1]} line #{@sources.last[2]})"
120
- STDERR.puts err.backtrace if trace
121
- exit if abort
122
- end
123
-
124
- def _check_existence(file, msg)
125
- _error! msg unless File.exist?(file)
126
- end
127
-
128
- def _source
129
- @input
130
- end
131
-
132
- def _args
133
- if block_given?
134
- @_args.each {|arg| yield arg }
135
- else
136
- @_args
137
- end
138
- end
139
-
140
- def _optional_blank_line
141
- @line = nextline if peek_nextline =~ /^ *$/
142
- end
143
-
144
- def _comment?(str, sigil=".")
145
- c1 = sigil + Livetext::Space
146
- c2 = sigil + sigil + Livetext::Space
147
- str.index(c1) == 0 || str.index(c2) == 0
148
- end
149
-
150
- def _trailing?(char)
151
- return true if ["\n", " ", nil].include?(char)
152
- return false
153
- end
154
-
155
- def _end?(str, sigil=".")
156
- cmd = sigil + "end"
157
- return false if str.index(cmd) != 0
158
- return false unless _trailing?(str[5])
159
- return true
160
- end
161
-
162
- def _raw_body(tag = "__EOF__", sigil = ".")
163
- lines = []
164
- loop do
165
- @line = nextline
166
- break if @line.chomp.strip == tag
167
- lines << @line
168
- end
169
- _optional_blank_line
170
- if block_given?
171
- lines.each {|line| yield @line }
172
- else
173
- lines
174
- end
175
- end
176
-
177
- def _body(sigil=".")
178
- lines = []
179
- loop do
180
- @line = nextline
181
- break if _end?(@line, sigil)
182
- next if _comment?(@line, sigil)
183
- lines << @line
184
- end
185
- _optional_blank_line
186
- if block_given?
187
- lines.each {|line| yield line }
188
- else
189
- lines
190
- end
191
- end
192
-
193
- def _body!(sigil=".")
194
- _body(sigil).join("\n")
195
- end
196
-
197
- def _basic_format(line, delim, tag)
198
- s = line.each_char
199
- c = s.next
200
- last = nil
201
- getch = -> { last = c; c = s.next }
202
- buffer = ""
203
- loop do
204
- case c
205
- when " "
206
- buffer << " "
207
- last = " "
208
- when delim
209
- if last == " " || last == nil
210
- buffer << "<#{tag}>"
211
- c = getch.call
212
- if c == "("
213
- loop { getch.call; break if c == ")"; buffer << c }
214
- buffer << "</#{tag}>"
215
- else
216
- loop { buffer << c; getch.call; break if c == " " || c == nil || c == "\n" }
217
- buffer << "</#{tag}>"
218
- buffer << " " if c == " "
219
- end
220
- else
221
- buffer << delim
222
- end
223
- else
224
- buffer << c
225
- end
226
- getch.call
227
- end
228
- buffer
229
- end
230
-
231
- def _handle_escapes(str, set)
232
- str = str.dup
233
- set.each_char do |ch|
234
- str.gsub!("\\#{ch}", ch)
235
- end
236
- str
237
- end
238
-
239
- def _formatting(line)
240
- l2 = _basic_format(line, "_", "i")
241
- l2 = _basic_format(l2, "*", "b")
242
- l2 = _basic_format(l2, "`", "tt")
243
- l2 = _handle_escapes(l2, "_*`")
244
- line.replace(l2)
245
- end
246
-
247
- def _substitution(line) # FIXME handle functions separately later??
248
- fobj = ::Livetext::Functions.new
249
- @funcs = ::Livetext::Functions.instance_methods
250
- @funcs.each do |func|
251
- name = ::Regexp.escape("$$#{func}")
252
- rx = /#{name}\b/
253
- line.gsub!(rx) do |str|
254
- val = fobj.send(func)
255
- str.sub(rx, val)
256
- end
257
- end
258
- @vars.each_pair do |var, val|
259
- name = ::Regexp.escape("$#{var}")
260
- rx = /#{name}\b/
261
- line.gsub!(rx, val)
262
- end
263
- line
264
- end
265
-
266
- def _passthru(line)
267
- return if @_nopass
268
- TTY.puts "nopara = #@_nopara"
269
- _puts "<p>" if line == "\n" and ! @_nopara
270
- _formatting(line)
271
- _substitution(line)
272
- _puts line
273
- end
274
-
275
- def _puts(*args)
276
- @output.puts *args
277
- end
278
-
279
- def _print(*args)
280
- @output.print *args
281
- end
282
-
283
- def _debug=(val)
284
- @_debug = val
147
+ @main._error!(err)
285
148
  end
286
149
 
287
- def _debug(*args)
288
- TTY.puts *args if @_debug
289
- end
290
-
291
- # include ::Livetext::Standard
292
-
293
- def comment
294
- junk = _body # do nothing with contents
295
- end
296
-
297
- def shell
298
- cmd = @_data
299
- _errout("Running: #{cmd}")
300
- system(cmd)
301
- end
302
-
303
- def func
304
- funcname = @_args[0]
305
- _error! "Illegal name '#{funcname}'" if _disallowed?(funcname)
306
- func_def = <<-EOS
307
- def #{funcname}
308
- #{_body!}
309
- end
310
- EOS
311
- Livetext::Functions.class_eval func_def
312
- end
313
-
314
- def shell!
315
- cmd = @_data
316
- system(cmd)
317
- end
318
-
319
- def errout
320
- TTY.puts @_data
321
- end
322
-
323
- def say
324
- str = _substitution(@_data)
325
- TTY.puts str
326
- _optional_blank_line
327
- end
328
-
329
- def banner
330
- str = _substitution(@_data)
331
- n = str.length - 1
332
- _errout "-"*n
333
- _errout str
334
- _errout "-"*n
335
- end
336
-
337
- def quit
338
- @output.close
339
- exit
340
- end
341
-
342
- def outdir
343
- @_outdir = @_args.first
344
- _optional_blank_line
345
- end
346
-
347
- def outdir! # FIXME ?
348
- @_outdir = @_args.first
349
- raise "No output directory specified" if @_outdir.nil?
350
- raise "No output directory specified" if @_outdir.empty?
351
- system("rm -f #@_outdir/*.html")
352
- _optional_blank_line
353
- end
354
-
355
- def _output(name)
356
- @output.close unless @output == STDOUT
357
- @output = File.open(@_outdir + "/" + name, "w")
358
- @output.puts "<meta charset='UTF-8'>\n\n"
359
- end
360
-
361
- def _append(name)
362
- @output.close unless @output == STDOUT
363
- @output = File.open(@_outdir + "/" + name, "a")
364
- @output.puts "<meta charset='UTF-8'>\n\n"
365
- end
366
-
367
- def output
368
- name = @_args.first
369
- _debug "Redirecting output to: #{name}"
370
- _output(name)
371
- end
372
-
373
- def append
374
- file = @_args[0]
375
- _append(file)
376
- end
377
-
378
- def next_output
379
- tag, num = @_args
380
- _next_output(tag, num)
381
- _optional_blank_line
382
- end
383
-
384
- def cleanup
385
- @_args.each do |item|
386
- if ::File.directory?(item)
387
- system("rm -f #{item}/*")
388
- else
389
- ::FileUtils.rm(item)
390
- end
391
- end
392
- end
393
-
394
- def _next_output(tag = "sec", num = nil)
395
- @_file_num = num ? num : @_file_num + 1
396
- @_file_num = @_file_num.to_i
397
- name = "#{'%03d' % @_file_num}-#{tag}.html"
398
- _output(name)
399
- end
400
-
401
- def _def
402
- name = @_args[0]
403
- str = "def #{name}\n"
404
- raise "Illegal name '#{name}'" if _disallowed?(name)
405
- str += _body!
406
- str += "end\n"
407
- eval str
408
- rescue => err
409
- _error!(err)
410
- end
411
-
412
- def nopass
413
- @_nopass = true
414
- end
415
-
416
- def set
417
- assigns = @_data.chomp.split(/, */)
418
- assigns.each do |a|
419
- var, val = a.split("=")
420
- val = val[1..-2] if val[0] == ?" and val[-1] == ?"
421
- val = val[1..-2] if val[0] == ?' and val[-1] == ?'
422
- @vars[var] = val
423
- end
424
- _optional_blank_line
425
- end
426
-
427
- def _include
428
- file = @_args.first
429
- _check_existence(file, "No such include file '#{file}'")
430
- process_file(file)
431
- _optional_blank_line
432
- end
433
-
434
- def include! # FIXME huh?
435
- file = @_args.first
436
- return unless File.exist?(file)
437
-
438
- lines = process_file(file)
439
- File.delete(file)
440
- _optional_blank_line
441
- end
442
-
443
- def mixin
444
- name = @_args.first # Expect a module name
445
- file = "#{Plugins}/" + name.downcase + ".rb"
446
- return if @_mixins.include?(name)
447
- file = "./#{name}.rb" unless File.exist?(file)
448
- _check_existence(file, "No such mixin '#{name}'")
449
-
450
- @_mixins << name
451
- meths = grab_file(file)
452
- modname = name.gsub("/","_").capitalize
453
- string = "module ::#{modname}\n#{meths}\nend"
454
- eval(string)
455
- newmod = Object.const_get("::" + modname)
456
- self.extend(newmod)
457
- init = "init_#{name}"
458
- self.send(init) if self.respond_to? init
459
- _optional_blank_line
460
- end
461
-
462
- def copy
463
- file = @_args.first
464
- _check_existence(file, "No such file '#{file}' to copy")
465
- @output.puts grab_file(file)
466
- _optional_blank_line
467
- end
468
-
469
- def r
470
- _puts @_data # No processing at all
471
- end
472
-
473
- def raw
474
- # No processing at all (terminate with __EOF__)
475
- _puts _raw_body
476
- end
477
-
478
- def debug
479
- arg = @_args.first
480
- self._debug = true
481
- self._debug = false if arg == "off"
482
- end
483
-
484
- def nopara
485
- @_nopara = true
486
- end
487
-
488
- def heading
489
- _print "<center><font size=+1><b>"
490
- _print @_data
491
- _print "</b></font></center>"
492
- end
493
-
494
- def newpage
495
- _puts '<p style="page-break-after:always;"></p>'
496
- _puts "<p/>"
497
- end
498
-
499
- def invoke(str)
500
- end
501
-
502
- def dlist
503
- delim = "~~"
504
- _puts "<table>"
505
- _body do |line|
506
- line = _formatting(line)
507
- term, defn = line.split(delim)
508
- _puts "<tr>"
509
- _puts "<td width=3%><td width=10%>#{term}</td><td>#{defn}</td>"
510
- _puts "</tr>"
511
- end
512
- _puts "</table>"
513
- end
514
-
515
- ###### Livetext
516
-
517
- def initialize(input = ::STDIN, output = ::STDOUT)
518
- @input = input
519
- @output = output
520
- @vars = {}
521
- @_mixins = []
522
- @source_files = []
523
- @sources = []
524
- @_outdir = "."
525
- @_file_num = 0
526
- @_nopass = false
527
- @_nopara = false
528
- end
529
-
530
- # def method_missing(name, *args)
531
- # ::TTY.puts "MM: #{name}"
532
- # name = "_def" if name.to_s == "def"
533
- # name = "_include" if name.to_s == "include"
534
- # @main.send(name, *args)
535
- # # $mods.reverse.each do |mod|
536
- # # if mod.respond_to?(name)
537
- # # mod.send(name, *args)
538
- # # return
539
- # # end
540
- # # end
541
- # _puts " Error: Method '#{name}' is not defined (from method_missing)"
542
- # puts caller.map {|x| " " + x }
543
- # exit
544
- # end
545
-
546
- end
547
-
548
- if $0 == __FILE__
549
- x = Livetext.new
550
- x.process_file(ARGV[0] || STDIN)
551
150
  end
552
151
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: livetext
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.7.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hal Fulton
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-15 00:00:00.000000000 Z
11
+ date: 2017-03-17 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A smart text processor extensible in Ruby
14
14
  email: rubyhacker@gmail.com