livetext 0.9.11 → 0.9.13

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 (167) hide show
  1. checksums.yaml +4 -4
  2. data/lib/errors.rb +13 -0
  3. data/lib/formatline.rb +3 -5
  4. data/lib/functions.rb +6 -2
  5. data/lib/helpers.rb +21 -0
  6. data/lib/html.rb +32 -0
  7. data/lib/livetext/importable.rb +2 -0
  8. data/lib/livetext.rb +44 -42
  9. data/lib/parser/general.rb +38 -0
  10. data/lib/parser/import.rb +17 -0
  11. data/lib/parser/mixin.rb +46 -0
  12. data/lib/parser/set.rb +136 -0
  13. data/lib/parser/string.rb +55 -0
  14. data/lib/parser.rb +5 -0
  15. data/lib/processor.rb +22 -16
  16. data/lib/standard.rb +144 -292
  17. data/lib/userapi.rb +2 -1
  18. data/livetext.gemspec +1 -2
  19. data/test/all.rb +3 -0
  20. data/test/formatting.rb +2 -9
  21. data/test/{data → snapshots}/basic_formatting/expected-error.txt +0 -0
  22. data/test/{data → snapshots}/basic_formatting/expected-output.txt +0 -0
  23. data/test/{data → snapshots}/basic_formatting/source.lt3 +0 -0
  24. data/test/{data → snapshots}/block_comment/expected-error.txt +0 -0
  25. data/test/{data → snapshots}/block_comment/expected-output.txt +0 -0
  26. data/test/{data → snapshots}/block_comment/source.lt3 +0 -0
  27. data/test/{data → snapshots}/comments_ignored_1/expected-error.txt +0 -0
  28. data/test/{data → snapshots}/comments_ignored_1/expected-output.txt +0 -0
  29. data/test/{data → snapshots}/comments_ignored_1/source.lt3 +0 -0
  30. data/test/{data → snapshots}/copy_is_raw/expected-error.txt +0 -0
  31. data/test/{data → snapshots}/copy_is_raw/expected-output.txt +0 -0
  32. data/test/{data → snapshots}/copy_is_raw/rawtext.inc +0 -0
  33. data/test/{data → snapshots}/copy_is_raw/source.lt3 +0 -0
  34. data/test/{data → snapshots}/crap +0 -0
  35. data/test/{data → snapshots}/def_method/expected-error.txt +0 -0
  36. data/test/{data → snapshots}/def_method/expected-output.txt +0 -0
  37. data/test/{data → snapshots}/def_method/source.lt3 +0 -0
  38. data/test/{data/error_inc_line_num/expected-err-line1match.txt → snapshots/error_inc_line_num/actual-error.txt} +0 -0
  39. data/test/{data/error_inc_line_num/expected-output.txt → snapshots/error_inc_line_num/actual-output.txt} +0 -0
  40. data/test/{data/error_line_num → snapshots/error_inc_line_num}/expected-err-line1match.txt +0 -0
  41. data/test/snapshots/error_inc_line_num/expected-output.txt +13 -0
  42. data/test/{data → snapshots}/error_inc_line_num/file2.lt3 +0 -0
  43. data/test/snapshots/error_inc_line_num/out-sdiff.txt +14 -0
  44. data/test/{data → snapshots}/error_inc_line_num/source.lt3 +0 -0
  45. data/test/snapshots/error_invalid_name/actual-error.txt +10 -0
  46. data/test/{data/error_no_such_mixin/expected-output.txt → snapshots/error_invalid_name/actual-output.txt} +0 -0
  47. data/test/{data → snapshots}/error_invalid_name/expected-err-line1match.txt +0 -0
  48. data/test/{data → snapshots}/error_invalid_name/expected-output.txt +0 -0
  49. data/test/snapshots/error_invalid_name/out-sdiff.txt +6 -0
  50. data/test/{data → snapshots}/error_invalid_name/source.lt3 +0 -0
  51. data/test/snapshots/error_line_num/actual-error.txt +1 -0
  52. data/test/snapshots/error_line_num/actual-output.txt +5 -0
  53. data/test/snapshots/error_line_num/expected-err-line1match.txt +1 -0
  54. data/test/{data → snapshots}/error_line_num/expected-output.txt +0 -0
  55. data/test/snapshots/error_line_num/out-sdiff.txt +6 -0
  56. data/test/{data → snapshots}/error_line_num/source.lt3 +0 -0
  57. data/test/snapshots/error_mismatched_end/actual-error.txt +1 -0
  58. data/test/{data/error_mismatched_end/expected-output.txt → snapshots/error_mismatched_end/actual-output.txt} +0 -0
  59. data/test/{data → snapshots}/error_mismatched_end/expected-err-line1match.txt +0 -0
  60. data/test/snapshots/error_mismatched_end/expected-output.txt +8 -0
  61. data/test/snapshots/error_mismatched_end/out-sdiff.txt +9 -0
  62. data/test/{data → snapshots}/error_mismatched_end/source.lt3 +0 -0
  63. data/test/{data/error_missing_end/expected-err-line1match.txt → snapshots/error_missing_end/actual-error.txt} +0 -0
  64. data/test/{data/error_missing_end/expected-output.txt → snapshots/error_missing_end/actual-output.txt} +0 -0
  65. data/test/snapshots/error_missing_end/expected-err-line1match.txt +1 -0
  66. data/test/snapshots/error_missing_end/expected-output.txt +5 -0
  67. data/test/snapshots/error_missing_end/out-sdiff.txt +6 -0
  68. data/test/{data → snapshots}/error_missing_end/source.lt3 +0 -0
  69. data/test/{data/error_name_not_permitted/expected-output.txt → snapshots/error_name_not_permitted/OLD-exp-out} +0 -0
  70. data/test/{data/example_alpha/expected-error.txt → snapshots/error_name_not_permitted/expected-output.txt} +0 -0
  71. data/test/snapshots/error_name_not_permitted/match-error.txt +1 -0
  72. data/test/{data → snapshots}/error_name_not_permitted/source.lt3 +0 -0
  73. data/test/snapshots/error_no_such_copy/actual-error.txt +10 -0
  74. data/test/{data/example_alpha2/expected-error.txt → snapshots/error_no_such_copy/actual-output.txt} +0 -0
  75. data/test/snapshots/error_no_such_copy/expected-err-line1match.txt +1 -0
  76. data/test/{data → snapshots}/error_no_such_copy/expected-output.txt +0 -5
  77. data/test/snapshots/error_no_such_copy/out-sdiff.txt +5 -0
  78. data/test/{data → snapshots}/error_no_such_copy/source.lt3 +0 -0
  79. data/test/snapshots/error_no_such_inc/actual-error.txt +10 -0
  80. data/test/{data/functions/expected-error.txt → snapshots/error_no_such_inc/actual-output.txt} +0 -0
  81. data/test/snapshots/error_no_such_inc/expected-err-line1match.txt +1 -0
  82. data/test/{data → snapshots}/error_no_such_inc/expected-output.txt +0 -4
  83. data/test/snapshots/error_no_such_inc/out-sdiff.txt +6 -0
  84. data/test/{data → snapshots}/error_no_such_inc/source.lt3 +0 -0
  85. data/test/snapshots/error_no_such_mixin/actual-error.txt +1 -0
  86. data/test/snapshots/error_no_such_mixin/actual-output.txt +11 -0
  87. data/test/{data → snapshots}/error_no_such_mixin/expected-err-line1match.txt +0 -0
  88. data/test/snapshots/error_no_such_mixin/expected-output.txt +5 -0
  89. data/test/snapshots/error_no_such_mixin/out-sdiff.txt +12 -0
  90. data/test/{data → snapshots}/error_no_such_mixin/source.lt3 +0 -0
  91. data/test/{data/hello_world → snapshots/example_alpha}/expected-error.txt +0 -0
  92. data/test/{data → snapshots}/example_alpha/expected-output.txt +0 -0
  93. data/test/{data → snapshots}/example_alpha/source.lt3 +0 -0
  94. data/test/{data/more_complex_vars → snapshots/example_alpha2}/expected-error.txt +0 -0
  95. data/test/{data → snapshots}/example_alpha2/expected-output.txt +0 -0
  96. data/test/{data → snapshots}/example_alpha2/source.lt3 +0 -0
  97. data/test/{data → snapshots}/fixit +0 -0
  98. data/test/{data/predef_vars → snapshots/functions}/expected-error.txt +0 -0
  99. data/test/{data → snapshots}/functions/expected-output.txt +0 -0
  100. data/test/{data → snapshots}/functions/source.lt3 +0 -0
  101. data/test/{data/raw_lines → snapshots/hello_world}/expected-error.txt +0 -0
  102. data/test/{data → snapshots}/hello_world/expected-output.txt +0 -0
  103. data/test/{data → snapshots}/hello_world/source.lt3 +0 -0
  104. data/test/{data → snapshots}/lines.txt +0 -0
  105. data/test/{data/raw_text_block → snapshots/more_complex_vars}/expected-error.txt +0 -0
  106. data/test/{data → snapshots}/more_complex_vars/expected-output.txt +0 -0
  107. data/test/{data → snapshots}/more_complex_vars/source.lt3 +0 -0
  108. data/test/{data/simple_copy/expected-error.txt → snapshots/predef_vars/actual-error.txt} +0 -0
  109. data/test/snapshots/predef_vars/actual-output.txt +6 -0
  110. data/test/{data/simple_include → snapshots/predef_vars}/expected-error.txt +0 -0
  111. data/test/{data → snapshots}/predef_vars/expected-output.txt +1 -1
  112. data/test/snapshots/predef_vars/out-sdiff.txt +7 -0
  113. data/test/{data → snapshots}/predef_vars/source.lt3 +0 -0
  114. data/test/{data/simple_mixin → snapshots/raw_lines}/expected-error.txt +0 -0
  115. data/test/{data → snapshots}/raw_lines/expected-output.txt +0 -0
  116. data/test/{data → snapshots}/raw_lines/source.lt3 +0 -0
  117. data/test/{data/simple_vars → snapshots/raw_text_block}/expected-error.txt +0 -0
  118. data/test/{data → snapshots}/raw_text_block/expected-output.txt +0 -0
  119. data/test/{data → snapshots}/raw_text_block/rawtext.inc +0 -0
  120. data/test/{data → snapshots}/raw_text_block/source.lt3 +0 -0
  121. data/test/{data/single_raw_line → snapshots/simple_copy}/expected-error.txt +0 -0
  122. data/test/{data → snapshots}/simple_copy/expected-output.txt +0 -0
  123. data/test/{data → snapshots}/simple_copy/simplefile.inc +0 -0
  124. data/test/{data → snapshots}/simple_copy/source.lt3 +0 -0
  125. data/test/{data/table_with_heredocs → snapshots/simple_include}/expected-error.txt +0 -0
  126. data/test/{data → snapshots}/simple_include/expected-output.txt +0 -0
  127. data/test/{data → snapshots}/simple_include/simplefile.inc +0 -0
  128. data/test/{data → snapshots}/simple_include/source.lt3 +0 -0
  129. data/test/snapshots/simple_mixin/actual-error.txt +2 -0
  130. data/test/snapshots/simple_mixin/actual-output.txt +4 -0
  131. data/test/{data/subset.txt → snapshots/simple_mixin/expected-error.txt} +0 -0
  132. data/test/{data → snapshots}/simple_mixin/expected-output.txt +0 -0
  133. data/test/snapshots/simple_mixin/out-sdiff.txt +6 -0
  134. data/test/{data → snapshots}/simple_mixin/simple_mixin.rb +0 -0
  135. data/test/{data → snapshots}/simple_mixin/source.lt3 +0 -0
  136. data/test/snapshots/simple_vars/expected-error.txt +0 -0
  137. data/test/{data → snapshots}/simple_vars/expected-output.txt +0 -0
  138. data/test/{data → snapshots}/simple_vars/source.lt3 +0 -0
  139. data/test/snapshots/single_raw_line/expected-error.txt +0 -0
  140. data/test/{data → snapshots}/single_raw_line/expected-output.txt +0 -0
  141. data/test/{data → snapshots}/single_raw_line/source.lt3 +0 -0
  142. data/test/snapshots/subset.txt +0 -0
  143. data/test/snapshots/table_with_heredocs/expected-error.txt +0 -0
  144. data/test/{data → snapshots}/table_with_heredocs/expected-output.txt +0 -0
  145. data/test/{data → snapshots}/table_with_heredocs/source.lt3 +0 -0
  146. data/test/snapshots.rb +219 -0
  147. data/test/testlines.rb +2 -2
  148. data/test/unit/all.rb +3 -0
  149. data/test/unit/html.rb +38 -0
  150. data/test/unit/parse_misc.rb +60 -0
  151. data/test/unit/parse_set.rb +157 -0
  152. data/test/unit/parser/all.rb +3 -0
  153. data/test/unit/parser/general.rb +59 -0
  154. data/test/unit/parser/importable.rb +19 -0
  155. data/test/unit/parser/mixin.rb +19 -0
  156. data/test/unit/parser/set.rb +157 -0
  157. data/test/unit/parser/string.rb +130 -0
  158. data/test/unit/parser.rb +4 -0
  159. data/test/unit/standard.rb +23 -0
  160. data/test/unit/stringparser.rb +140 -0
  161. metadata +152 -99
  162. data/test/data/error_inc_line_num/FOO +0 -21
  163. data/test/data/error_missing_end/ERR +0 -32
  164. data/test/data/error_name_not_permitted/expected-error.txt +0 -1
  165. data/test/data/error_no_such_copy/expected-err-line1match.txt +0 -1
  166. data/test/data/error_no_such_inc/expected-err-line1match.txt +0 -1
  167. data/test/test.rb +0 -140
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2f49173986fc8a17fc77f35032e823f4818d404007d5aacd2d3d5a4a74f19e02
4
- data.tar.gz: 61c0eab54d60c23abe0c27a6b8adc16f621e35c347253b557f07ffc80b31f80e
3
+ metadata.gz: 8f9a5d4be00258f23687ca280b306794cb67f2e7c89ba1a453c60dfd59f4268d
4
+ data.tar.gz: 423d1901855f09e06f5448008e12095713110d1d4dc8ba4f31ddf871319d2bb3
5
5
  SHA512:
6
- metadata.gz: '07389bbd1154d200f6f56b0373c0459bf140baeefa370d789224f2dedd53fe5120f0f7116e2c9d1381ff07a48f945786bb8e5f3478ac9002aea0f9443f61f579'
7
- data.tar.gz: 12829e57528407a55f842f8ad8de77b47396cb6fffb22d76feaf8d98d644ebf00fc50d447a24f453026980a7cb7631443e11f9f7d67121ce9529d583ef85e513
6
+ metadata.gz: dfd42d9206980d3819e45fc174baf74378c01d13e61c8a8ce58f00bc3d3b7889b1bace1b74076c5491657978e704b55e6f82543e57ffdaa128993f6ec584c5e9
7
+ data.tar.gz: 570a8c6f92f4baaadad6c946871910e7ae2107741bef4212e16e7a49e90e1f929a8149c9f99553319a811eb42a6ce37fff0e15b8985235b91858f800d3ca77be
data/lib/errors.rb ADDED
@@ -0,0 +1,13 @@
1
+
2
+ # More later?
3
+
4
+ def make_exception(sym, str, target_class = Object)
5
+ return if target_class.constants.include?(sym)
6
+ target_class.const_set(sym, StandardError.dup)
7
+ define_method(sym) do |*args|
8
+ msg = str.dup
9
+ args.each.with_index {|arg, i| msg.sub!("%#{i+1}", arg) }
10
+ target_class.class_eval(sym.to_s).new(msg)
11
+ end
12
+ end
13
+
data/lib/formatline.rb CHANGED
@@ -1,3 +1,6 @@
1
+ # Class FormatLine handles the parsing of comments, dot commands, and
2
+ # simple formatting characters.
3
+
1
4
  class FormatLine
2
5
  SimpleFormats = {}
3
6
  SimpleFormats[:b] = %w[<b> </b>]
@@ -395,11 +398,6 @@ class FormatLine
395
398
 
396
399
  #####
397
400
 
398
- def showme(tag)
399
- char = @line[@cc]
400
- puts "--- #{tag}: ch=#{@ch.inspect} next=#{@next.inspect} (cc=#@cc:#{char.inspect}) out=#{@out.inspect}"
401
- end
402
-
403
401
  def embedded?
404
402
  ! (['"', "'", " ", nil].include? prev)
405
403
  end
data/lib/functions.rb CHANGED
@@ -1,6 +1,10 @@
1
- require 'standard' # FIXME
2
1
 
3
- class Livetext::Functions # Functions will go here... user-def AND pre-def??
2
+ require_relative 'standard' # FIXME?
3
+
4
+ # Class Functions is where '$$func' functions are stored dynamically...
5
+ # user-def AND pre-def??
6
+
7
+ class Livetext::Functions
4
8
  Formats = ::Livetext::Standard::SimpleFormats
5
9
 
6
10
  @param = nil
data/lib/helpers.rb ADDED
@@ -0,0 +1,21 @@
1
+
2
+ module Helpers
3
+
4
+ def check_disallowed(name)
5
+ # raise "Illegal name '#{name}'" if _disallowed?(name)
6
+ # FIXME use custom exception
7
+ raise DisallowedName, name if _disallowed?(name)
8
+ end
9
+
10
+ def check_file_exists(file)
11
+ raise FileNotFound(file) unless File.exist?(file)
12
+ end
13
+
14
+ def set_variables(pairs)
15
+ pairs.each do |pair|
16
+ var, value = *pair
17
+ @parent._setvar(var, value)
18
+ end
19
+ end
20
+
21
+ end
data/lib/html.rb ADDED
@@ -0,0 +1,32 @@
1
+ module HTMLHelper
2
+
3
+ def wrapped(str, *tags) # helper
4
+ open, close = open_close_tags(*tags)
5
+ open + str + close
6
+ end
7
+
8
+ def wrapped!(str, tag, **extras) # helper
9
+ open, close = open_close_tags(tag)
10
+ extras.each_pair do |name, value|
11
+ open.sub!(">", " #{name}='#{value}'>")
12
+ end
13
+ open + str + close
14
+ end
15
+
16
+ def wrap(*tags) # helper
17
+ open, close = open_close_tags(*tags)
18
+ _out open
19
+ yield
20
+ _out close
21
+ end
22
+
23
+ def open_close_tags(*tags)
24
+ open, close = "", ""
25
+ tags.each do |tag|
26
+ open << "<#{tag}>"
27
+ close.prepend("</#{tag}>")
28
+ end
29
+ [open, close]
30
+ end
31
+
32
+ end
@@ -0,0 +1,2 @@
1
+ class LiveText::Importable
2
+ end
data/lib/livetext.rb CHANGED
@@ -1,34 +1,48 @@
1
+ # Class Livetext skeleton (top level).
2
+
1
3
  class Livetext
2
- VERSION = "0.9.11"
4
+ VERSION = "0.9.13"
3
5
  Path = File.expand_path(File.join(File.dirname(__FILE__)))
4
6
  end
5
7
 
6
- require 'fileutils'
8
+ # $LOAD_PATH << Livetext::Path
7
9
 
8
- $: << Livetext::Path
10
+ require 'fileutils'
9
11
 
10
- require 'functions'
11
- require 'userapi'
12
- require 'standard'
13
- require 'formatline'
14
- require 'processor'
12
+ require_relative 'errors'
13
+ require_relative 'functions'
14
+ require_relative 'userapi'
15
+ require_relative 'standard'
16
+ require_relative 'formatline'
17
+ require_relative 'processor'
15
18
 
16
19
  Plugins = File.expand_path(File.join(File.dirname(__FILE__), "../plugin"))
17
20
 
18
21
  TTY = ::File.open("/dev/tty", "w")
19
22
 
23
+ # Class Livetext reopened (top level).
24
+
20
25
  class Livetext
26
+
21
27
  Vars = {}
22
28
 
29
+ Space = " "
30
+ Sigil = "." # Can't change yet
31
+
32
+ def self.rx(str, space=nil)
33
+ Regexp.compile("^" + Regexp.escape(str) + "#{space}")
34
+ end
35
+
36
+ Comment = rx(Sigil, Livetext::Space)
37
+ Dotcmd = rx(Sigil)
38
+ Ddotcmd = /^ *\$\.[A-Za-z]/
39
+
23
40
  attr_reader :main
24
41
  attr_accessor :no_puts
25
42
  attr_accessor :body, :indentation
26
43
 
27
- # FIXME - phase out stupid 'parameters' method
28
-
29
44
  class << self
30
- attr_accessor :parameters # from outside world (process_text)
31
- attr_accessor :output # both bad solutions?
45
+ attr_accessor :output # bad solution?
32
46
  end
33
47
 
34
48
  def vars
@@ -54,17 +68,6 @@ class Livetext
54
68
  self
55
69
  end
56
70
 
57
- Space = " "
58
- Sigil = "." # Can't change yet
59
-
60
- def self.rx(str, space=nil)
61
- Regexp.compile("^" + Regexp.escape(str) + "#{space}")
62
- end
63
-
64
- Comment = rx(Sigil, Livetext::Space)
65
- Dotcmd = rx(Sigil)
66
- Ddotcmd = /^ *\$\.[A-Za-z]/
67
-
68
71
  def initialize(output = ::STDOUT)
69
72
  @source = nil
70
73
  @_mixins = []
@@ -115,9 +118,14 @@ class Livetext
115
118
  end
116
119
 
117
120
  def _setfile(file)
118
- _setvar(:File, file)
119
- dir = File.dirname(File.expand_path(file))
120
- _setvar(:FileDir, dir)
121
+ if file
122
+ _setvar(:File, file)
123
+ dir = File.dirname(File.expand_path(file))
124
+ _setvar(:FileDir, dir)
125
+ else
126
+ _setvar(:File, "[no file]")
127
+ _setvar(:FileDir, "[no dir]")
128
+ end
121
129
  end
122
130
 
123
131
  def _setfile!(file)
@@ -130,7 +138,6 @@ class Livetext
130
138
  when Comment
131
139
  handle_scomment(line)
132
140
  when Dotcmd
133
- # STDERR.puts "line = #{line.inspect}"
134
141
  handle_dotcmd(line)
135
142
  when Ddotcmd
136
143
  indent = line.index("$") + 1
@@ -185,7 +192,7 @@ class Livetext
185
192
 
186
193
  def process_file(fname, btrace=false)
187
194
  _setfile(fname)
188
- text = File.readlines(fname)
195
+ text = File.readlines(fname) # FIXME currently causes failure
189
196
  enum = text.each
190
197
  @backtrace = btrace
191
198
  @main.source(enum, fname, 0)
@@ -197,28 +204,23 @@ class Livetext
197
204
  end
198
205
  val = @main.finalize if @main.respond_to? :finalize
199
206
  @body
200
- rescue => err
201
- STDERR.puts "[process_file] fname = #{fname.inspect}\n line = #{line.inspect}"
202
- STDERR.puts "ERROR #{err} in process_file"
203
- err.backtrace.each {|x| STDERR.puts " " + x }
204
- @body = ""
207
+ rescue => err
208
+ STDERR.puts "[process_file] fname = #{fname.inspect}\n line = #{line.inspect}"
209
+ STDERR.puts "ERROR #{err} in process_file"
210
+ err.backtrace.each {|x| STDERR.puts " " + x }
211
+ # @body = ""
205
212
  end
206
213
 
207
214
  def handle_scomment(line)
208
215
  end
209
216
 
210
- def _check_name(name)
211
- @main._error! "Name '#{name}' is not permitted" if @main._disallowed?(name)
212
- @main._error! "Mismatched 'end'" if name == "end"
213
- name = "_" + name if %w[def include].include?(name)
214
- name
215
- end
216
-
217
217
  def _get_name(line)
218
218
  name, data = line.split(" ", 2)
219
219
  name = name[1..-1] # chop off sigil
220
+ name = "_" + name if %w[include def].include?(name)
220
221
  @main.data = data
221
- name = _check_name(name)
222
+ @main.check_disallowed(name)
223
+ name
222
224
  end
223
225
 
224
226
  def handle_dotcmd(line, indent = 0)
@@ -235,7 +237,7 @@ class Livetext
235
237
  result
236
238
  rescue => err
237
239
  STDERR.puts "Error: #{err.inspect}"
238
- STDERR.puts err.backtrace
240
+ # STDERR.puts err.backtrace
239
241
  # @main._error!(err)
240
242
  puts @body
241
243
  @body = ""
@@ -0,0 +1,38 @@
1
+
2
+ require_relative '../livetext'
3
+ require_relative 'string'
4
+
5
+ make_exception(:MismatchedQuotes, "Error: mismatched quotes")
6
+ make_exception(:NilValue, "Error: nil value")
7
+ make_exception(:NullString, "Error: null string")
8
+ make_exception(:ExpectedString, "Error: expected a string")
9
+
10
+ class Livetext::ParseMisc < StringParser
11
+
12
+ def initialize(str)
13
+ super
14
+ end
15
+
16
+ def strip_quotes
17
+ raise NullString if @line.empty?
18
+ start, stop = @line[0], @line[-1]
19
+ return @line unless %['"].include?(start)
20
+ raise MismatchedQuotes if start != stop
21
+ @line[1..-2]
22
+ end
23
+
24
+ def self.parse_vars(lines, prefix: nil)
25
+ lines.map! {|line| line.sub(/# .*/, "").strip } # strip comments
26
+ pairs = []
27
+ lines.each do |line|
28
+ next if line.strip.empty?
29
+ var, value = line.split(" ", 2)
30
+ val = FormatLine.var_func_parse(value)
31
+ var = prefix + "." + var if prefix
32
+ pairs << [var, value]
33
+ end
34
+ pairs
35
+ end
36
+
37
+ end
38
+
@@ -0,0 +1,17 @@
1
+
2
+ require '../livetext/importable'
3
+
4
+ make_exception(:BadVariableName, "Error: invalid variable name")
5
+ make_exception(:NoEqualSign, "Error: no equal sign found")
6
+
7
+ # FIXME probably belongs elsewhere?
8
+
9
+ class Livetext::ParseImport
10
+ def use_import(name)
11
+ require name
12
+ include name
13
+ init = "init_#{name}"
14
+ self.send(init) if self.respond_to? init
15
+ end
16
+ end
17
+
@@ -0,0 +1,46 @@
1
+ require_relative '../livetext'
2
+ require_relative 'string'
3
+
4
+ make_exception(:BadVariableName, "Error: invalid variable name")
5
+ make_exception(:NoEqualSign, "Error: no equal sign found")
6
+
7
+ # FIXME probably belongs elsewhere?
8
+
9
+ class Livetext::ParseMixin # < StringParser
10
+
11
+ # def self.parse(str)
12
+ # self.new(str).parse
13
+ # end
14
+ #
15
+ # def initialize(line)
16
+ # super
17
+ # end
18
+
19
+ def cwd_root?
20
+ File.dirname(File.expand_path(".")) == "/"
21
+ end
22
+
23
+ def find_mixin(name)
24
+ file = "#{Plugins}/" + name.downcase + ".rb"
25
+ return file if File.exist?(file)
26
+
27
+ file = "./#{name}.rb"
28
+ return file if File.exist?(file)
29
+
30
+ raise "No such mixin '#{name}'" if cwd_root?
31
+ Dir.chdir("..") { find_mixin(name) }
32
+ end
33
+
34
+ def use_mixin(name, file)
35
+ modname = name.gsub("/","_").capitalize
36
+ meths = grab_file(file)
37
+ string = "module ::#{modname}; #{meths}\nend"
38
+ eval(string)
39
+ newmod = Object.const_get("::" + modname)
40
+ self.extend(newmod)
41
+ init = "init_#{name}"
42
+ self.send(init) if self.respond_to? init
43
+ end
44
+
45
+ end
46
+
data/lib/parser/set.rb ADDED
@@ -0,0 +1,136 @@
1
+
2
+ require_relative '../livetext'
3
+ require_relative 'string'
4
+
5
+ make_exception(:BadVariableName, "Error: invalid variable name")
6
+ make_exception(:NoEqualSign, "Error: no equal sign found")
7
+
8
+ class Livetext::ParseSet < StringParser
9
+
10
+ attr_reader :line, :eos, :i, :len
11
+
12
+ def self.parse(str)
13
+ self.new(str).parse
14
+ end
15
+
16
+ def initialize(line)
17
+ super
18
+ end
19
+
20
+ def parse
21
+ pairs = []
22
+
23
+ loop do
24
+ skip_spaces
25
+ char = self.peek
26
+ break if eos? # end of string
27
+ raise "Expected alpha to start var name" unless char =~ /[a-z]/i
28
+ pairs << assignment
29
+ skip_spaces
30
+ char = self.peek
31
+ break if eos? # end of string
32
+ case char
33
+ when nil # end of string
34
+ when ","
35
+ self.next # skip comma
36
+ else
37
+ raise "Expected comma or end of string (found #{char.inspect})"
38
+ end
39
+ end
40
+ pairs
41
+ end
42
+
43
+ def assignment # one single var=value
44
+ pair = nil
45
+ var = value = nil
46
+ return if eos?
47
+ var = get_var
48
+ skip_equal
49
+ value = get_value
50
+ value = FormatLine.var_func_parse(value)
51
+ pair = [var, value]
52
+ pair
53
+ end
54
+
55
+ def get_var
56
+ name = ""
57
+ loop do
58
+ char = self.peek
59
+ break if eos? # end of string
60
+ case char
61
+ when /[a-zA-Z_\.0-9]/
62
+ name << self.next
63
+ next
64
+ when /[ =]/
65
+ return name
66
+ else
67
+ raise BadVariableName, char, name
68
+ end
69
+ end
70
+ raise NoEqualSign
71
+ end
72
+
73
+ def skip_equal
74
+ found = false
75
+ skip_spaces
76
+ raise NoEqualSign unless self.peek == "="
77
+ found = true
78
+ self.next # skip =... spaces too
79
+ self.skip_spaces
80
+ peek = self.peek
81
+ return peek # just for testing
82
+ rescue StopIteration
83
+ raise NoEqualSign unless found
84
+ return nil
85
+ end
86
+
87
+ def escaped
88
+ self.next # skip backslash
89
+ self.next # return following char
90
+ end
91
+
92
+ make_exception(:BadQuotedString, "Bad quoted string: %1")
93
+
94
+ def quoted_value
95
+ quote = self.next # opening quote...
96
+ value = ""
97
+ char = nil
98
+ loop do
99
+ char = self.peek
100
+ break if self.eos?
101
+ break if char == quote
102
+ char = escaped if char == "\\"
103
+ value << char
104
+ char = self.next
105
+ end
106
+ if char == quote
107
+ char = self.next
108
+ return value
109
+ end
110
+ raise BadQuotedString, quote + value
111
+ end
112
+
113
+ def unquoted_value
114
+ # puts "#{__method__}: #{@line.inspect} i = #@i peek = #{self.peek.inspect}"
115
+ value = ""
116
+ loop do
117
+ char = self.peek
118
+ break if self.eos?
119
+ break if char == " " || char == ","
120
+ value << char
121
+ char = self.next
122
+ end
123
+ value
124
+ end
125
+
126
+ def quote?(char)
127
+ char == ?" || char == ?'
128
+ end
129
+
130
+ def get_value
131
+ char = self.peek
132
+ value = quote?(char) ? quoted_value : unquoted_value
133
+ value
134
+ end
135
+ end
136
+
@@ -0,0 +1,55 @@
1
+ class StringParser
2
+
3
+ attr_reader :line, :eos, :i, :len
4
+
5
+ def initialize(line)
6
+ raise NilValue if line.nil?
7
+ raise ExpectedString unless String === line
8
+ # raise NullString if line.empty?
9
+ @line = line
10
+ @len = @line.length
11
+ @eos = @len == 0 ? true : false
12
+ @i = 0
13
+ end
14
+
15
+ def next
16
+ return nil if @eos
17
+ char = @line[@i]
18
+ @i += 1
19
+ @eos = true if @i > @len
20
+ char
21
+ end
22
+
23
+ def last?
24
+ @i > @len - 1
25
+ end
26
+
27
+ def eos?
28
+ @eos = true if last? # duh?
29
+ @eos
30
+ end
31
+
32
+ def peek
33
+ return nil if @eos
34
+ @line[@i]
35
+ end
36
+
37
+ def skip_spaces
38
+ loop do
39
+ break if peek != " "
40
+ break if eos?
41
+ self.next
42
+ end
43
+ end
44
+
45
+ end
46
+
47
+ =begin
48
+ skip
49
+ next! skip! peek!(?)
50
+ expect_alpha
51
+ expect_number
52
+ skip_spaces
53
+ expect_eos
54
+ =end
55
+
data/lib/parser.rb ADDED
@@ -0,0 +1,5 @@
1
+
2
+ require_relative 'parser/string'
3
+ require_relative 'parser/general'
4
+ require_relative 'parser/set'
5
+ require_relative 'parser/mixin'
data/lib/processor.rb CHANGED
@@ -1,21 +1,27 @@
1
+ # Class Livetext is the actual top-level class.
2
+
1
3
  class Livetext
2
4
 
5
+ # Class Processor does the actual work of processing input.
6
+
3
7
  class Processor
8
+
9
+ GenericError = Class.new(StandardError)
10
+
4
11
  include Livetext::Standard
5
12
  include Livetext::UserAPI
6
13
 
7
- Disallowed = [:nil?, :===, :=~, :!~, :eql?, :hash, :<=>,
8
- :class, :singleton_class, :clone, :dup, :taint, :tainted?,
9
- :untaint, :untrust, :untrusted?, :trust, :freeze, :frozen?,
10
- :to_s, :inspect, :methods, :singleton_methods, :protected_methods,
11
- :private_methods, :public_methods, :instance_variables,
12
- :instance_variable_get, :instance_variable_set,
13
- :instance_variable_defined?, :remove_instance_variable,
14
- :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send,
15
- :respond_to?, :extend, :display, :method, :public_method,
16
- :singleton_method, :define_singleton_method, :object_id, :to_enum,
17
- :enum_for, :pretty_inspect, :==, :equal?, :!, :!=, :instance_eval,
18
- :instance_exec, :__send__, :__id__, :__binding__]
14
+ Disallowed = %i[ ! != !~ <=> == === =~ __binding__ __id__ __send__ class
15
+ clone define_singleton_method display dup enum_for eql?
16
+ equal? extend freeze frozen? hash inspect instance_eval
17
+ instance_exec instance_of? instance_variable_defined?
18
+ instance_variable_get instance_variable_set instance_variables is_a?
19
+ kind_of? method methods nil? object_id
20
+ pretty_inspect private_methods protected_methods public_method
21
+ public_methods public_send remove_instance_variable
22
+ respond_to? send singleton_class singleton_method
23
+ singleton_methods taint tainted? tap to_enum
24
+ to_s trust untaint untrust untrusted?]
19
25
 
20
26
  def initialize(parent, output = nil)
21
27
  @parent = parent
@@ -32,15 +38,15 @@ class Livetext
32
38
  @output = io
33
39
  end
34
40
 
35
- def _error!(err, abort=true, trace=false)
41
+ def _error!(err, raise_error=false, trace=false) # FIXME much bullshit happens here
36
42
  where = @sources.last || @save_location
37
43
  # puts @parent.body
38
44
  # puts "[lib/processor] Error: #{err}"
39
45
  # puts err.backtrace.join("\n") if err.respond_to?(:backtrace)
40
- STDERR.puts "[lib/processor] Error: #{err}" # (at #{where[1]} line #{where[2]})"
46
+ STDERR.puts "Error: #{err}" # (at #{where[1]} line #{where[2]})"
41
47
  STDERR.puts err.backtrace if err.respond_to?(:backtrace) # && trace
42
48
  # raise "lib/processor error!" # FIXME
43
- exit if abort
49
+ raise GenericError.new("Error: #{err}") if raise_error
44
50
  end
45
51
 
46
52
  def _disallowed?(name)
@@ -56,7 +62,7 @@ class Livetext
56
62
  rescue StopIteration
57
63
  @sources.pop
58
64
  nil
59
- rescue
65
+ rescue => err
60
66
  nil
61
67
  end
62
68