livetext 0.9.08 → 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/bin/livetext +0 -1
  3. data/lib/errors.rb +13 -0
  4. data/lib/formatline.rb +3 -5
  5. data/lib/functions.rb +6 -2
  6. data/lib/helpers.rb +21 -0
  7. data/lib/html.rb +32 -0
  8. data/lib/livetext/importable.rb +2 -0
  9. data/lib/livetext.rb +52 -46
  10. data/lib/parser/general.rb +38 -0
  11. data/lib/parser/import.rb +17 -0
  12. data/lib/parser/mixin.rb +46 -0
  13. data/lib/parser/set.rb +136 -0
  14. data/lib/parser/string.rb +55 -0
  15. data/lib/parser.rb +5 -0
  16. data/lib/processor.rb +26 -18
  17. data/lib/standard.rb +145 -292
  18. data/lib/userapi.rb +6 -5
  19. data/livetext.gemspec +1 -2
  20. data/test/all.rb +3 -0
  21. data/test/formatting.rb +2 -9
  22. data/test/{data → snapshots}/basic_formatting/expected-error.txt +0 -0
  23. data/test/{data → snapshots}/basic_formatting/expected-output.txt +0 -0
  24. data/test/{data → snapshots}/basic_formatting/source.lt3 +0 -0
  25. data/test/{data → snapshots}/block_comment/expected-error.txt +0 -0
  26. data/test/{data → snapshots}/block_comment/expected-output.txt +0 -0
  27. data/test/{data → snapshots}/block_comment/source.lt3 +0 -0
  28. data/test/{data → snapshots}/comments_ignored_1/expected-error.txt +0 -0
  29. data/test/{data → snapshots}/comments_ignored_1/expected-output.txt +0 -0
  30. data/test/{data → snapshots}/comments_ignored_1/source.lt3 +0 -0
  31. data/test/{data → snapshots}/copy_is_raw/expected-error.txt +0 -0
  32. data/test/{data → snapshots}/copy_is_raw/expected-output.txt +0 -0
  33. data/test/{data → snapshots}/copy_is_raw/rawtext.inc +0 -0
  34. data/test/{data → snapshots}/copy_is_raw/source.lt3 +0 -0
  35. data/test/{data → snapshots}/crap +0 -0
  36. data/test/{data → snapshots}/def_method/expected-error.txt +0 -0
  37. data/test/{data → snapshots}/def_method/expected-output.txt +0 -0
  38. data/test/{data → snapshots}/def_method/source.lt3 +0 -0
  39. data/test/{data/error_inc_line_num/expected-err-line1match.txt → snapshots/error_inc_line_num/actual-error.txt} +0 -0
  40. data/test/snapshots/error_inc_line_num/actual-output.txt +13 -0
  41. data/test/{data/error_line_num → snapshots/error_inc_line_num}/expected-err-line1match.txt +0 -0
  42. data/test/{data → snapshots}/error_inc_line_num/expected-output.txt +6 -0
  43. data/test/{data → snapshots}/error_inc_line_num/file2.lt3 +0 -0
  44. data/test/snapshots/error_inc_line_num/out-sdiff.txt +14 -0
  45. data/test/{data → snapshots}/error_inc_line_num/source.lt3 +0 -0
  46. data/test/snapshots/error_invalid_name/actual-error.txt +10 -0
  47. data/test/{data/error_no_such_mixin/expected-output.txt → snapshots/error_invalid_name/actual-output.txt} +0 -0
  48. data/test/{data → snapshots}/error_invalid_name/expected-err-line1match.txt +0 -0
  49. data/test/{data → snapshots}/error_invalid_name/expected-output.txt +0 -0
  50. data/test/snapshots/error_invalid_name/out-sdiff.txt +6 -0
  51. data/test/{data → snapshots}/error_invalid_name/source.lt3 +0 -0
  52. data/test/snapshots/error_line_num/actual-error.txt +1 -0
  53. data/test/snapshots/error_line_num/actual-output.txt +5 -0
  54. data/test/snapshots/error_line_num/expected-err-line1match.txt +1 -0
  55. data/test/{data → snapshots}/error_line_num/expected-output.txt +0 -0
  56. data/test/snapshots/error_line_num/out-sdiff.txt +6 -0
  57. data/test/{data → snapshots}/error_line_num/source.lt3 +0 -0
  58. data/test/snapshots/error_mismatched_end/actual-error.txt +1 -0
  59. data/test/snapshots/error_mismatched_end/actual-output.txt +8 -0
  60. data/test/{data → snapshots}/error_mismatched_end/expected-err-line1match.txt +0 -0
  61. data/test/{data → snapshots}/error_mismatched_end/expected-output.txt +2 -0
  62. data/test/snapshots/error_mismatched_end/out-sdiff.txt +9 -0
  63. data/test/{data → snapshots}/error_mismatched_end/source.lt3 +0 -0
  64. data/test/{data/error_missing_end/expected-err-line1match.txt → snapshots/error_missing_end/actual-error.txt} +0 -0
  65. data/test/snapshots/error_missing_end/actual-output.txt +5 -0
  66. data/test/snapshots/error_missing_end/expected-err-line1match.txt +1 -0
  67. data/test/{data → snapshots}/error_missing_end/expected-output.txt +1 -0
  68. data/test/snapshots/error_missing_end/out-sdiff.txt +6 -0
  69. data/test/{data → snapshots}/error_missing_end/source.lt3 +0 -0
  70. data/test/{data/error_name_not_permitted/expected-output.txt → snapshots/error_name_not_permitted/OLD-exp-out} +0 -0
  71. data/test/{data/example_alpha/expected-error.txt → snapshots/error_name_not_permitted/expected-output.txt} +0 -0
  72. data/test/snapshots/error_name_not_permitted/match-error.txt +1 -0
  73. data/test/{data → snapshots}/error_name_not_permitted/source.lt3 +0 -0
  74. data/test/snapshots/error_no_such_copy/actual-error.txt +10 -0
  75. data/test/{data/example_alpha2/expected-error.txt → snapshots/error_no_such_copy/actual-output.txt} +0 -0
  76. data/test/snapshots/error_no_such_copy/expected-err-line1match.txt +1 -0
  77. data/test/{data → snapshots}/error_no_such_copy/expected-output.txt +0 -1
  78. data/test/snapshots/error_no_such_copy/out-sdiff.txt +5 -0
  79. data/test/{data → snapshots}/error_no_such_copy/source.lt3 +1 -0
  80. data/test/snapshots/error_no_such_inc/actual-error.txt +10 -0
  81. data/test/{data/functions/expected-error.txt → snapshots/error_no_such_inc/actual-output.txt} +0 -0
  82. data/test/snapshots/error_no_such_inc/expected-err-line1match.txt +1 -0
  83. data/test/{data → snapshots}/error_no_such_inc/expected-output.txt +0 -0
  84. data/test/snapshots/error_no_such_inc/out-sdiff.txt +6 -0
  85. data/test/{data → snapshots}/error_no_such_inc/source.lt3 +0 -0
  86. data/test/snapshots/error_no_such_mixin/actual-error.txt +1 -0
  87. data/test/snapshots/error_no_such_mixin/actual-output.txt +11 -0
  88. data/test/{data → snapshots}/error_no_such_mixin/expected-err-line1match.txt +0 -0
  89. data/test/snapshots/error_no_such_mixin/expected-output.txt +5 -0
  90. data/test/snapshots/error_no_such_mixin/out-sdiff.txt +12 -0
  91. data/test/{data → snapshots}/error_no_such_mixin/source.lt3 +0 -0
  92. data/test/{data/hello_world → snapshots/example_alpha}/expected-error.txt +0 -0
  93. data/test/{data → snapshots}/example_alpha/expected-output.txt +0 -0
  94. data/test/{data → snapshots}/example_alpha/source.lt3 +0 -0
  95. data/test/{data/more_complex_vars → snapshots/example_alpha2}/expected-error.txt +0 -0
  96. data/test/{data → snapshots}/example_alpha2/expected-output.txt +0 -0
  97. data/test/{data → snapshots}/example_alpha2/source.lt3 +0 -0
  98. data/test/{data → snapshots}/fixit +0 -0
  99. data/test/{data/raw_lines → snapshots/functions}/expected-error.txt +0 -0
  100. data/test/{data → snapshots}/functions/expected-output.txt +0 -0
  101. data/test/{data → snapshots}/functions/source.lt3 +0 -0
  102. data/test/{data/raw_text_block → snapshots/hello_world}/expected-error.txt +0 -0
  103. data/test/{data → snapshots}/hello_world/expected-output.txt +0 -0
  104. data/test/{data → snapshots}/hello_world/source.lt3 +0 -0
  105. data/test/{data → snapshots}/lines.txt +4 -0
  106. data/test/{data/simple_copy → snapshots/more_complex_vars}/expected-error.txt +0 -0
  107. data/test/{data → snapshots}/more_complex_vars/expected-output.txt +0 -0
  108. data/test/{data → snapshots}/more_complex_vars/source.lt3 +0 -0
  109. data/test/{data/simple_include/expected-error.txt → snapshots/predef_vars/actual-error.txt} +0 -0
  110. data/test/snapshots/predef_vars/actual-output.txt +6 -0
  111. data/test/{data/simple_mixin → snapshots/predef_vars}/expected-error.txt +0 -0
  112. data/test/snapshots/predef_vars/expected-output.txt +6 -0
  113. data/test/snapshots/predef_vars/out-sdiff.txt +7 -0
  114. data/test/snapshots/predef_vars/source.lt3 +6 -0
  115. data/test/{data/simple_vars → snapshots/raw_lines}/expected-error.txt +0 -0
  116. data/test/{data → snapshots}/raw_lines/expected-output.txt +0 -0
  117. data/test/{data → snapshots}/raw_lines/source.lt3 +0 -0
  118. data/test/{data/single_raw_line → snapshots/raw_text_block}/expected-error.txt +0 -0
  119. data/test/{data → snapshots}/raw_text_block/expected-output.txt +0 -0
  120. data/test/{data → snapshots}/raw_text_block/rawtext.inc +0 -0
  121. data/test/{data → snapshots}/raw_text_block/source.lt3 +0 -0
  122. data/test/{data/table_with_heredocs → snapshots/simple_copy}/expected-error.txt +0 -0
  123. data/test/{data → snapshots}/simple_copy/expected-output.txt +0 -0
  124. data/test/{data → snapshots}/simple_copy/simplefile.inc +0 -0
  125. data/test/{data → snapshots}/simple_copy/source.lt3 +0 -0
  126. data/test/{data/subset.txt → snapshots/simple_include/expected-error.txt} +0 -0
  127. data/test/{data → snapshots}/simple_include/expected-output.txt +0 -0
  128. data/test/{data → snapshots}/simple_include/simplefile.inc +0 -0
  129. data/test/{data → snapshots}/simple_include/source.lt3 +0 -0
  130. data/test/snapshots/simple_mixin/actual-error.txt +2 -0
  131. data/test/snapshots/simple_mixin/actual-output.txt +4 -0
  132. data/test/snapshots/simple_mixin/expected-error.txt +0 -0
  133. data/test/{data → snapshots}/simple_mixin/expected-output.txt +0 -0
  134. data/test/snapshots/simple_mixin/out-sdiff.txt +6 -0
  135. data/test/{data → snapshots}/simple_mixin/simple_mixin.rb +0 -0
  136. data/test/{data → snapshots}/simple_mixin/source.lt3 +0 -0
  137. data/test/snapshots/simple_vars/expected-error.txt +0 -0
  138. data/test/{data → snapshots}/simple_vars/expected-output.txt +0 -0
  139. data/test/{data → snapshots}/simple_vars/source.lt3 +0 -0
  140. data/test/snapshots/single_raw_line/expected-error.txt +0 -0
  141. data/test/{data → snapshots}/single_raw_line/expected-output.txt +0 -0
  142. data/test/{data → snapshots}/single_raw_line/source.lt3 +0 -0
  143. data/test/snapshots/subset.txt +0 -0
  144. data/test/snapshots/table_with_heredocs/expected-error.txt +0 -0
  145. data/test/{data → snapshots}/table_with_heredocs/expected-output.txt +0 -0
  146. data/test/{data → snapshots}/table_with_heredocs/source.lt3 +0 -0
  147. data/test/snapshots.rb +219 -0
  148. data/test/testlines.rb +17 -7
  149. data/test/unit/all.rb +3 -0
  150. data/test/unit/html.rb +38 -0
  151. data/test/unit/parse_misc.rb +60 -0
  152. data/test/unit/parse_set.rb +157 -0
  153. data/test/unit/parser/all.rb +3 -0
  154. data/test/unit/parser/general.rb +59 -0
  155. data/test/unit/parser/importable.rb +19 -0
  156. data/test/unit/parser/mixin.rb +19 -0
  157. data/test/unit/parser/set.rb +157 -0
  158. data/test/unit/parser/string.rb +130 -0
  159. data/test/unit/parser.rb +4 -0
  160. data/test/unit/standard.rb +23 -0
  161. data/test/unit/stringparser.rb +140 -0
  162. metadata +152 -95
  163. data/test/data/error_name_not_permitted/expected-error.txt +0 -1
  164. data/test/data/error_no_such_copy/expected-err-line1match.txt +0 -1
  165. data/test/data/error_no_such_inc/expected-err-line1match.txt +0 -1
  166. data/test/extratests.txt +0 -20
  167. data/test/test.rb +0 -140
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f983f97d1e649079c9ae7b8c059c099eb3fb4b70b3df8afa026aefad4009f83e
4
- data.tar.gz: 5efeb66838ae1b36dff234d548e0835f6617af739c653d9e6af8888c68b09c02
3
+ metadata.gz: 8f9a5d4be00258f23687ca280b306794cb67f2e7c89ba1a453c60dfd59f4268d
4
+ data.tar.gz: 423d1901855f09e06f5448008e12095713110d1d4dc8ba4f31ddf871319d2bb3
5
5
  SHA512:
6
- metadata.gz: 957fccd4430db4bd5dfcaa889829e753b180ee9a48635ba88769dd6e2645768cbff293c887d6202dcfc58474deaa56bc03ce18973f612ec138b85db636909988
7
- data.tar.gz: 18c66b6647b1bd78c75b5bf4c7d0b7b5649fc2f403b1013dedec8a7e0203fa0758ef17f5fd7f731705a9428ac993e8a449b6092b551a4708d84bf13848bdfd1b
6
+ metadata.gz: dfd42d9206980d3819e45fc174baf74378c01d13e61c8a8ce58f00bc3d3b7889b1bace1b74076c5491657978e704b55e6f82543e57ffdaa128993f6ec584c5e9
7
+ data.tar.gz: 570a8c6f92f4baaadad6c946871910e7ae2107741bef4212e16e7a49e90e1f929a8149c9f99553319a811eb42a6ce37fff0e15b8985235b91858f800d3ca77be
data/bin/livetext CHANGED
@@ -72,7 +72,6 @@ loop do
72
72
  @backtrace = true
73
73
  when "-m", "--mixin"
74
74
  mod = ARGV.shift
75
- STDERR.puts "Got mod: #{mod}"
76
75
  x.mixin(ARGV.shift)
77
76
  next
78
77
  when "-s", "--stdin"
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.08"
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 = []
@@ -74,6 +77,10 @@ class Livetext
74
77
  @main = Processor.new(self, output)
75
78
  @indentation = [0]
76
79
  @_vars = Livetext::Vars
80
+
81
+ # Other predefined variables (see also _setfile)
82
+ _setvar(:User, `whoami`.chomp)
83
+ _setvar(:Version, Livetext::VERSION)
77
84
  end
78
85
 
79
86
  def _parse_colon_args(args, hash) # really belongs in livetext
@@ -111,9 +118,14 @@ class Livetext
111
118
  end
112
119
 
113
120
  def _setfile(file)
114
- _setvar(:File, file)
115
- dir = File.dirname(File.expand_path(file))
116
- _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
117
129
  end
118
130
 
119
131
  def _setfile!(file)
@@ -126,7 +138,6 @@ class Livetext
126
138
  when Comment
127
139
  handle_scomment(line)
128
140
  when Dotcmd
129
- STDERR.puts "line = #{line.inspect}"
130
141
  handle_dotcmd(line)
131
142
  when Ddotcmd
132
143
  indent = line.index("$") + 1
@@ -170,7 +181,7 @@ class Livetext
170
181
  self.body
171
182
  end
172
183
 
173
- def xform_file(file) # , vars: {})
184
+ def xform_file(file, vars: nil)
174
185
  Livetext::Vars.replace(vars) unless vars.nil?
175
186
  @_vars.replace(vars) unless vars.nil?
176
187
  self.process_file(file)
@@ -181,7 +192,7 @@ class Livetext
181
192
 
182
193
  def process_file(fname, btrace=false)
183
194
  _setfile(fname)
184
- text = File.readlines(fname)
195
+ text = File.readlines(fname) # FIXME currently causes failure
185
196
  enum = text.each
186
197
  @backtrace = btrace
187
198
  @main.source(enum, fname, 0)
@@ -193,28 +204,23 @@ class Livetext
193
204
  end
194
205
  val = @main.finalize if @main.respond_to? :finalize
195
206
  @body
196
- rescue => err
197
- STDERR.puts "[process_file] fname = #{fname.inspect}\n line = #{line.inspect}"
198
- STDERR.puts "ERROR #{err} in process_file"
199
- err.backtrace.each {|x| STDERR.puts " " + x }
200
- @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 = ""
201
212
  end
202
213
 
203
214
  def handle_scomment(line)
204
215
  end
205
216
 
206
- def _check_name(name)
207
- @main._error! "Name '#{name}' is not permitted" if @main._disallowed?(name)
208
- @main._error! "Mismatched 'end'" if name == "end"
209
- name = "_" + name if %w[def include].include?(name)
210
- name
211
- end
212
-
213
217
  def _get_name(line)
214
218
  name, data = line.split(" ", 2)
215
219
  name = name[1..-1] # chop off sigil
220
+ name = "_" + name if %w[include def].include?(name)
216
221
  @main.data = data
217
- name = _check_name(name)
222
+ @main.check_disallowed(name)
223
+ name
218
224
  end
219
225
 
220
226
  def handle_dotcmd(line, indent = 0)
@@ -230,10 +236,10 @@ class Livetext
230
236
  end
231
237
  result
232
238
  rescue => err
233
- STDERR.puts "Error was: #{err.inspect} (calling @main._error!)"
234
- STDERR.puts err.backtrace
235
- @main._error!(err)
236
- # puts @body
239
+ STDERR.puts "Error: #{err.inspect}"
240
+ # STDERR.puts err.backtrace
241
+ # @main._error!(err)
242
+ puts @body
237
243
  @body = ""
238
244
  return @body
239
245
  end
@@ -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,13 +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
- puts @parent.body
38
- STDERR.puts "[lib/processor] Error: #{err}" # (at #{where[1]} line #{where[2]})"
39
- raise "lib/processor error!"
43
+ # puts @parent.body
44
+ # puts "[lib/processor] Error: #{err}"
45
+ # puts err.backtrace.join("\n") if err.respond_to?(:backtrace)
46
+ STDERR.puts "Error: #{err}" # (at #{where[1]} line #{where[2]})"
40
47
  STDERR.puts err.backtrace if err.respond_to?(:backtrace) # && trace
41
- exit if abort
48
+ # raise "lib/processor error!" # FIXME
49
+ raise GenericError.new("Error: #{err}") if raise_error
42
50
  end
43
51
 
44
52
  def _disallowed?(name)
@@ -54,7 +62,7 @@ class Livetext
54
62
  rescue StopIteration
55
63
  @sources.pop
56
64
  nil
57
- rescue
65
+ rescue => err
58
66
  nil
59
67
  end
60
68