livetext 0.7.1 → 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
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