livetext 0.9.11 → 0.9.13

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