livetext 0.9.23 → 0.9.26

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/README.lt3 +6 -6
  3. data/bin/livetext +57 -40
  4. data/imports/bookish.rb +81 -81
  5. data/imports/calibre.rb +3 -3
  6. data/imports/livemagick.rb +17 -17
  7. data/imports/markdown.rb +10 -10
  8. data/imports/pyggish.rb +13 -13
  9. data/imports/tutorial.rb +15 -15
  10. data/lib/cmdargs.rb +7 -4
  11. data/lib/{errors.rb → livetext/errors.rb} +4 -3
  12. data/lib/{formatline.rb → livetext/formatline.rb} +119 -18
  13. data/lib/livetext/funcall.rb +168 -0
  14. data/lib/{functions.rb → livetext/functions.rb} +0 -2
  15. data/lib/{global_helpers.rb → livetext/global_helpers.rb} +6 -3
  16. data/lib/{handler → livetext/handler}/import.rb +5 -9
  17. data/lib/livetext/handler/mixin.rb +33 -0
  18. data/lib/{handler.rb → livetext/handler.rb} +1 -1
  19. data/lib/{helpers.rb → livetext/helpers.rb} +78 -66
  20. data/lib/{html.rb → livetext/html.rb} +2 -3
  21. data/lib/livetext/lineparser.rb +441 -0
  22. data/lib/livetext/more.rb +158 -0
  23. data/lib/{parser → livetext/parser}/general.rb +0 -0
  24. data/lib/{parser → livetext/parser}/set.rb +0 -0
  25. data/lib/{parser → livetext/parser}/string.rb +0 -0
  26. data/lib/{parser.rb → livetext/parser.rb} +0 -3
  27. data/lib/{parsing.rb → livetext/parsing.rb} +0 -2
  28. data/lib/livetext/paths.rb +13 -0
  29. data/lib/{processor.rb → livetext/processor.rb} +18 -8
  30. data/lib/livetext/reopen.rb +12 -0
  31. data/lib/livetext/skeleton.rb +22 -0
  32. data/lib/{standard.rb → livetext/standard.rb} +150 -127
  33. data/lib/livetext/userapi.rb +170 -0
  34. data/lib/livetext/version.rb +6 -0
  35. data/lib/livetext.rb +14 -152
  36. data/plugin/bookish.rb +82 -81
  37. data/plugin/calibre.rb +3 -3
  38. data/plugin/livemagick.rb +17 -17
  39. data/plugin/markdown.rb +10 -10
  40. data/plugin/pyggish.rb +118 -118
  41. data/plugin/tutorial.rb +15 -15
  42. data/test/all.rb +6 -0
  43. data/test/snapshots/{error_inc_line_num → basic_formatting}/actual-error.txt +0 -0
  44. data/test/snapshots/basic_formatting/actual-output.txt +13 -0
  45. data/test/snapshots/basic_formatting/err-sdiff.txt +1 -0
  46. data/test/snapshots/basic_formatting/out-sdiff.txt +14 -0
  47. data/test/snapshots/def_method/expected-output.txt +2 -0
  48. data/test/snapshots/def_method/source.lt3 +4 -2
  49. data/test/snapshots/error_inc_line_num/{OUT → README.txt} +11 -8
  50. data/test/snapshots/error_inc_line_num/expected-output.txt +0 -6
  51. data/test/snapshots/error_inc_line_num/match-error.txt +1 -1
  52. data/test/snapshots/error_invalid_name/foo +5 -0
  53. data/test/snapshots/error_line_num/match-error.txt +1 -1
  54. data/test/snapshots/error_missing_end/expected-output.txt +0 -1
  55. data/test/snapshots/error_name_not_permitted/expected-output.txt +4 -0
  56. data/test/snapshots/error_name_not_permitted/match-error.txt +1 -1
  57. data/test/snapshots/error_no_such_copy/expected-output.txt +1 -0
  58. data/test/snapshots/error_no_such_mixin/expected-output.txt +1 -0
  59. data/test/snapshots/error_no_such_mixin/match-error.txt +1 -1
  60. data/test/snapshots/error_no_such_mixin/source.lt3 +1 -1
  61. data/test/snapshots/example_alpha/source.lt3 +2 -2
  62. data/test/snapshots/example_alpha2/expected-output.txt +0 -2
  63. data/test/snapshots/example_alpha2/source.lt3 +5 -4
  64. data/test/snapshots/import/expected-output.txt +2 -1
  65. data/test/snapshots/import/match-error.txt +1 -1
  66. data/test/snapshots/import/simple_import.rb +1 -1
  67. data/test/snapshots/import2/simple_import.rb +1 -1
  68. data/test/snapshots/import_bookish/expected-output.txt +4 -4
  69. data/test/snapshots/{error_invalid_name/actual-output.txt → more_functions/actual-error.txt} +0 -0
  70. data/test/snapshots/more_functions/actual-output.txt +37 -0
  71. data/test/snapshots/more_functions/err-sdiff.txt +1 -0
  72. data/test/snapshots/more_functions/expected-output.txt +1 -1
  73. data/test/snapshots/more_functions/out-sdiff.txt +38 -0
  74. data/test/snapshots/more_functions/source.lt3 +1 -1
  75. data/test/snapshots/raw_lines/expected-output.txt +0 -2
  76. data/test/snapshots/simple_import/simple_import.rb +1 -1
  77. data/test/snapshots/simple_mixin/simple_mixin.rb +1 -1
  78. data/test/snapshots/{error_missing_end/actual-output.txt → simple_vars/actual-error.txt} +0 -0
  79. data/test/snapshots/simple_vars/actual-output.txt +6 -0
  80. data/test/snapshots/simple_vars/err-sdiff.txt +1 -0
  81. data/test/snapshots/simple_vars/out-sdiff.txt +7 -0
  82. data/test/snapshots/single_raw_line/expected-output.txt +0 -2
  83. data/test/snapshots/subset.txt +9 -7
  84. data/test/snapshots/{error_no_such_copy/actual-output.txt → var_into_func/actual-error.txt} +0 -0
  85. data/test/snapshots/var_into_func/actual-output.txt +16 -0
  86. data/test/snapshots/var_into_func/err-sdiff.txt +1 -0
  87. data/test/snapshots/{error_no_such_inc/actual-output.txt → var_into_func/expected-error.txt} +0 -0
  88. data/test/snapshots/var_into_func/expected-output.txt +16 -0
  89. data/test/snapshots/var_into_func/out-sdiff.txt +17 -0
  90. data/test/snapshots/var_into_func/source.lt3 +16 -0
  91. data/test/snapshots.rb +16 -7
  92. data/test/unit/all.rb +3 -1
  93. data/test/unit/formatline.rb +145 -276
  94. data/test/unit/html.rb +1 -2
  95. data/test/unit/lineparser.rb +650 -0
  96. data/test/unit/parser/set.rb +13 -12
  97. data/test/unit/standard.rb +0 -1
  98. data/test/unit/tokenizer.rb +534 -0
  99. metadata +49 -39
  100. data/lib/funcall.rb +0 -93
  101. data/lib/parser/file.rb +0 -6
  102. data/lib/parser/mixin.rb +0 -34
  103. data/lib/userapi.rb +0 -164
  104. data/test/snapshots/error_inc_line_num/actual-output.txt +0 -17
  105. data/test/snapshots/error_invalid_name/actual-error.txt +0 -10
  106. data/test/snapshots/error_invalid_name/out-sdiff.txt +0 -6
  107. data/test/snapshots/error_missing_end/actual-error.txt +0 -10
  108. data/test/snapshots/error_missing_end/out-sdiff.txt +0 -6
  109. data/test/snapshots/error_no_such_copy/actual-error.txt +0 -10
  110. data/test/snapshots/error_no_such_copy/out-sdiff.txt +0 -5
  111. data/test/snapshots/error_no_such_inc/actual-error.txt +0 -10
  112. data/test/snapshots/error_no_such_inc/out-sdiff.txt +0 -6
  113. data/test/snapshots/error_no_such_mixin/actual-error.txt +0 -13
  114. data/test/snapshots/error_no_such_mixin/actual-output.txt +0 -0
  115. data/test/snapshots/error_no_such_mixin/out-sdiff.txt +0 -6
data/imports/pyggish.rb CHANGED
@@ -83,21 +83,21 @@ module Pyggish
83
83
  end
84
84
 
85
85
  def fragment
86
- lang = @_args.empty? ? :elixir : @_args.first.to_sym # ruby or elixir
87
- @_args = []
86
+ lang = api.args.empty? ? :elixir : api.args.first.to_sym # ruby or elixir
87
+ api.args = []
88
88
  send(lang)
89
- _out "\n"
89
+ api.out "\n"
90
90
  end
91
91
 
92
92
  def code # FIXME ?
93
93
  text = ""
94
- _body {|line| _out " " + line }
94
+ api.body {|line| api.out " " + line }
95
95
  end
96
96
 
97
97
  def mono
98
- _out "<pre>"
99
- _body {|line| _out " " + line }
100
- _out "</pre>"
98
+ api.out "<pre>"
99
+ api.body {|line| api.out " " + line }
100
+ api.out "</pre>"
101
101
  end
102
102
 
103
103
  def create_code_styles
@@ -145,28 +145,28 @@ module Pyggish
145
145
  end
146
146
 
147
147
  def ruby
148
- file = @_args.first
148
+ file = api.args.first
149
149
  if file.nil?
150
150
  code = " # Ruby code\n\n"
151
- _body {|line| code << " " + line + "\n" }
151
+ api.body {|line| code << " " + line + "\n" }
152
152
  else
153
153
  code = "# Ruby code\n\n" + ::File.read(file)
154
154
  end
155
155
 
156
156
  html = format_ruby(code)
157
- _out html
157
+ api.out html
158
158
  end
159
159
 
160
160
  def elixir
161
- file = @_args.first
161
+ file = api.args.first
162
162
  if file.nil?
163
163
  code = ""
164
- _body {|line| code << " " + line + "\n" }
164
+ api.body {|line| code << " " + line + "\n" }
165
165
  else
166
166
  code = ::File.read(file)
167
167
  end
168
168
 
169
169
  html = format_elixir(code)
170
- _out html
170
+ api.out html
171
171
  end
172
172
  end
data/imports/tutorial.rb CHANGED
@@ -7,22 +7,22 @@ module Tutorial
7
7
 
8
8
  def title(args = nil, body = nil)
9
9
  h1
10
- _optional_blank_line
10
+ api.optional_blank_line
11
11
  end
12
12
 
13
13
  def section(args = nil, body = nil)
14
14
  h3
15
- _optional_blank_line
15
+ api.optional_blank_line
16
16
  end
17
17
 
18
18
  def code(args = nil, body = nil)
19
19
  first = true # dumb hack! fixes blank space
20
- _body do |line|
20
+ api.body do |line|
21
21
  tag, first = "<pre>", false if first
22
- _out "#{tag} #{escape_html(line)}" # indentation
22
+ api.out "#{tag} #{escape_html(line)}" # indentation
23
23
  end
24
- _out "</pre>"
25
- _optional_blank_line
24
+ api.out "</pre>"
25
+ api.optional_blank_line
26
26
  end
27
27
 
28
28
  def rx(str)
@@ -30,14 +30,14 @@ module Tutorial
30
30
  end
31
31
 
32
32
  def inout(args = nil, body = nil)
33
- src, out = _args
33
+ src, out = api.args
34
34
  t1 = ::File.readlines(src) rescue (abort "t1 = #{src}")
35
35
  t2 = ::File.readlines(out) rescue (abort "t2 = #{out}")
36
36
  # To pacify markdown for README (FIXME later)
37
37
  t1 = t1.map {|x| " " + x.sub(/ +$/,"").gsub(/_/, "\\_") }.join
38
38
  t2 = t2.map {|x| " " + x.sub(/ +$/,"").gsub(/_/, "\\_") }.join
39
39
 
40
- _out <<-HTML
40
+ api.out <<-HTML
41
41
  <table width=80% cellpadding=4>
42
42
  <tr>
43
43
  <td width=50%><b>Input</b></td>
@@ -53,7 +53,7 @@ module Tutorial
53
53
  </tr>
54
54
  </table>
55
55
  HTML
56
- _optional_blank_line
56
+ api.optional_blank_line
57
57
  end
58
58
 
59
59
  def put_table(src, exp)
@@ -62,7 +62,7 @@ module Tutorial
62
62
  t1 = t1.map {|x| " " + x.sub(/ +$/,"").gsub(/_/, "\\_") }.join
63
63
  t2 = t2.map {|x| " " + x.sub(/ +$/,"").gsub(/_/, "\\_") }.join
64
64
 
65
- _out <<-HTML
65
+ api.out <<-HTML
66
66
  <font size=+1>
67
67
  <table width=80% cellpadding=4>
68
68
  <tr>
@@ -83,13 +83,13 @@ module Tutorial
83
83
  end
84
84
 
85
85
  def testcase(args = nil, body = nil)
86
- name = _args.first
87
- _out "\n<font size=+1><b>Test: </font><font size=+2><tt>#{name}</tt></font></b></h3><br>"
86
+ name = api.args.first
87
+ api.out "\n<font size=+1><b>Test: </font><font size=+2><tt>#{name}</tt></font></b></h3><br>"
88
88
  src, exp = "test/snapshots/#{name}/source.lt3", "test/snapshots/#{name}/expected-output.txt"
89
- @_args = [src, exp] # Better way to do this??
89
+ api.args = [src, exp] # Better way to do this??
90
90
  put_table(src, exp)
91
- _out "<br>"
92
- _optional_blank_line
91
+ api.out "<br>"
92
+ api.optional_blank_line
93
93
  end
94
94
  end
95
95
 
data/lib/cmdargs.rb CHANGED
@@ -1,4 +1,3 @@
1
- # p __FILE__
2
1
 
3
2
  require_relative 'livetext'
4
3
 
@@ -80,13 +79,13 @@ class Livetext::CmdData
80
79
  def check_num_args(num)
81
80
  num_range = /(\d{0,2})(\.\.)(\d{0,2})/ # Not "really" right...
82
81
  min, max = 0, 9999
83
- md = num_range.match(@nargs).to_a
82
+ mdata = num_range.match(@nargs).to_a
84
83
  bad_args = nil
85
84
  case
86
85
  when @nargs == ":N" # arbitrary
87
86
  # max already set
88
- when md[2] == ".." # range: 4..6 1.. ..4
89
- vmin, vmax = md.values_at(1, 2)
87
+ when mdata[2] == ".." # range: 4..6 1.. ..4
88
+ vmin, vmax = mdata.values_at(1, 2)
90
89
  min = Integer(vmin) unless vmin.empty?
91
90
  max = Integer(vmax) unless vmax.empty?
92
91
  min, max = Integer(min), Integer(max)
@@ -100,4 +99,8 @@ class Livetext::CmdData
100
99
  raise "Expected #{num} args but found #{@args.size}!" if bad_args
101
100
  end
102
101
 
102
+ def strip_comments(str)
103
+ str.sub!(/ # .*/, "")
104
+ end
105
+
103
106
  end
@@ -1,5 +1,3 @@
1
- # p __FILE__
2
-
3
1
 
4
2
  # More later?
5
3
 
@@ -10,8 +8,11 @@ def make_exception(sym, str, target_class = Object)
10
8
  define_method(sym) do |*args|
11
9
  args = [] unless args.first
12
10
  msg = str.dup
13
- args.each.with_index {|arg, i| msg.sub!("%#{i+1}", arg) }
11
+ args.each.with_index {|arg, i| msg.sub!("%#{i+1}", arg.to_s) }
14
12
  target_class.class_eval(klass.to_s).new(msg)
15
13
  end
16
14
  end
17
15
 
16
+ make_exception(:EndWithoutOpening, "Error: found .end with no opening command")
17
+ make_exception(:UnknownMethod, "Error: name '%1' is unknown")
18
+
@@ -1,4 +1,3 @@
1
- # p __FILE__
2
1
 
3
2
  require_relative 'parsing'
4
3
  require_relative 'funcall'
@@ -21,15 +20,21 @@ class Livetext::FormatLine < StringParser
21
20
 
22
21
  def self.parse!(line)
23
22
  return nil if line.nil?
24
- x = self.new(line.chomp)
23
+ line.chomp!
24
+ x = self.new(line)
25
+ ::Livetext::TTY.puts "\n-- string: #{line.inspect}" if $testme
25
26
  t = x.tokenize
26
- x.evaluate
27
+ ::Livetext::TTY.puts "\n-- Tokens: #{t.inspect}" if $testme
28
+ result = x.evaluate
29
+ ::Livetext::TTY.puts "\n-- result: #{result.inspect}\n " if $testme
30
+ result
27
31
  end
28
32
 
29
33
  def tokenize
30
- # add grab
31
34
  loop do
32
- case peek
35
+ ch = peek
36
+ ::Livetext::TTY.puts "\n-- #{__method__}: ch1 = #{ch.inspect}\n " if $testme
37
+ case ch
33
38
  when Escape; grab; add peek; grab
34
39
  when "$"
35
40
  dollar
@@ -37,7 +42,65 @@ class Livetext::FormatLine < StringParser
37
42
  marker peek
38
43
  add peek
39
44
  when LF
40
- break if eos? # @i >= line.size - 1
45
+ break if eos?
46
+ when nil
47
+ break
48
+ else
49
+ add peek
50
+ end
51
+ ch = grab
52
+ # add ch
53
+ ::Livetext::TTY.puts "\n-- #{__method__}: !!! ch2 = #{ch.inspect}\n " if $testme
54
+ end
55
+ add_token(:str)
56
+ @tokenlist
57
+ end
58
+
59
+ def parse_formatting
60
+ loop do
61
+ case peek
62
+ when Escape; grab; add peek; grab
63
+ when "*", "_", "`", "~"
64
+ marker peek
65
+ add peek
66
+ when LF
67
+ break if eos?
68
+ when nil
69
+ break
70
+ else
71
+ add peek
72
+ end
73
+ grab
74
+ end
75
+ add_token(:str)
76
+ @tokenlist
77
+ end
78
+
79
+ def self.get_vars
80
+ grab
81
+ case peek
82
+ when LF, " ", nil
83
+ add "$"
84
+ add_token :str
85
+ when "$"; double_dollar
86
+ # when "."; dollar_dot
87
+ when /[A-Za-z]/
88
+ add_token :str
89
+ var = peek + grab_alpha_dot
90
+ add_token(:var, var)
91
+ else
92
+ add "$" + peek
93
+ add_token(:str)
94
+ end
95
+ end
96
+
97
+ def self.parse_var_func # FIXME Hmm...
98
+ loop do
99
+ case peek
100
+ when "$"
101
+ dollar
102
+ when LF
103
+ break if eos?
41
104
  when nil
42
105
  break
43
106
  else
@@ -57,6 +120,20 @@ class Livetext::FormatLine < StringParser
57
120
  end
58
121
  end
59
122
 
123
+ def var_func_parse
124
+ char = self.peek
125
+ loop do
126
+ char = self.grab
127
+ break if char == LF || char == nil
128
+ self.escaped if char == Escape
129
+ self.dollar if char == "$" # Could be $$
130
+ self.add char
131
+ end
132
+ self.add_token(:str)
133
+ result = self.evaluate
134
+ result
135
+ end
136
+
60
137
  def self.var_func_parse(str)
61
138
  return nil if str.nil?
62
139
  x = self.new(str.chomp)
@@ -64,7 +141,7 @@ class Livetext::FormatLine < StringParser
64
141
  loop do
65
142
  char = x.grab
66
143
  break if char == LF || char == nil
67
- x.handle_escaping if char == Escape
144
+ x.escaped if char == Escape
68
145
  x.dollar if char == "$" # Could be $$
69
146
  x.add char
70
147
  end
@@ -73,9 +150,20 @@ class Livetext::FormatLine < StringParser
73
150
  result
74
151
  end
75
152
 
76
- def handle_escaping
77
- grab
78
- add grab
153
+ def self.parse_variables(str)
154
+ return nil if str.nil?
155
+ x = self.new(str.chomp)
156
+ char = x.peek
157
+ loop do
158
+ char = x.grab
159
+ break if char == LF || char == nil
160
+ x.escaped if char == Escape
161
+ x.dollar if char == "$" # Could be $$
162
+ x.add char
163
+ end
164
+ x.add_token(:str)
165
+ result = x.evaluate
166
+ result
79
167
  end
80
168
 
81
169
  def embed(sym, str)
@@ -139,20 +227,31 @@ class Livetext::FormatLine < StringParser
139
227
  end
140
228
 
141
229
  def dollar
142
- grab
143
- case peek
144
- when LF; add "$"; add_token :str
145
- when " "; add "$ "; add_token :str
146
- when nil; add "$"; add_token :str
230
+ ch = grab # "$"
231
+ ::Livetext::TTY.puts "\n-- #{__method__}: ch1 = #{ch.inspect}\n self = #{self.inspect}" if $testme
232
+ ch = peek
233
+ ::Livetext::TTY.puts "\n-- #{__method__}: ch2 = #{ch.inspect}\n self = #{self.inspect}" if $testme
234
+ case ch
235
+ when " "
236
+ ::Livetext::TTY.puts "\n-- #{__method__}: (space)" if $testme
237
+ add "$ "
238
+ add_token :str
239
+ when LF, nil
240
+ ::Livetext::TTY.puts "\n-- #{__method__}: (LF/nil)" if $testme
241
+ add "$"
242
+ add_token :str
147
243
  when "$"; double_dollar
148
244
  # when "."; dollar_dot
149
245
  when /[A-Za-z]/
246
+ ::Livetext::TTY.puts "\n-- #{__method__}: (Alpha)" if $testme
150
247
  add_token :str
151
248
  var = peek + grab_alpha_dot
152
249
  add_token(:var, var)
153
250
  else
154
- add "$" + peek
155
- add_token(:string)
251
+ ch = grab # "$"
252
+ ::Livetext::TTY.puts "\n-- ch3 = #{ch.inspect}\n self = #{self.inspect}" if $testme
253
+ add "$" + ch
254
+ add_token(:str)
156
255
  end
157
256
  end
158
257
 
@@ -267,7 +366,9 @@ class Livetext::FormatLine < StringParser
267
366
  end
268
367
 
269
368
  def varsub(name)
270
- result = Livetext::Vars[name] || "[#{name} is undefined]"
369
+ live = Livetext.new
370
+ value = live.vars[name]
371
+ result = value || "[#{name} is undefined]"
271
372
  result
272
373
  end
273
374
 
@@ -0,0 +1,168 @@
1
+
2
+ require_relative '../livetext'
3
+
4
+ # Parse function calls
5
+
6
+ module Livetext::LineParser::FunCall
7
+
8
+ include Livetext::ParsingConstants
9
+
10
+ def param_loop(char)
11
+ param = ""
12
+ loop do
13
+ case peek
14
+ when Escape
15
+ param << escaped
16
+ when char, LF, nil
17
+ break
18
+ else
19
+ param << grab
20
+ end
21
+ end
22
+ param = nil if param.empty?
23
+ param
24
+ end
25
+
26
+ def grab_colon_param
27
+ grab # grab :
28
+ param = param_loop(Space)
29
+ end
30
+
31
+ def grab_bracket_param
32
+ grab # [
33
+ param = param_loop("]")
34
+ grab # "]"
35
+ param
36
+ end
37
+
38
+ def funcall(name, param)
39
+ err = "[Error evaluating $$#{name}(#{param})]"
40
+ result =
41
+ if self.send?(name, param)
42
+ # do nothing
43
+ else
44
+ fobj = ::Livetext::Functions.new
45
+ fobj.send(name, param) rescue err
46
+ end
47
+ result.to_s
48
+ end
49
+
50
+ def grab_func_with_param
51
+ add_token(:str, @token)
52
+ func = grab_alpha
53
+ add_token(:func, func)
54
+ param = grab_func_param # may be null/missing
55
+ param
56
+ end
57
+
58
+ def double_dollar
59
+ case peek
60
+ when Space; add_token :string, "$$ "; grab
61
+ when LF, nil; add "$$ "; add_token :str
62
+ when Alpha; param = grab_func_with_param
63
+ else grab; add_token :str, "$$" + peek
64
+ end
65
+ end
66
+
67
+ def grab_func_param
68
+ case peek
69
+ when "["
70
+ param = grab_bracket_param
71
+ add_token(:brackets, param)
72
+ when ":"
73
+ param = grab_colon_param
74
+ add_token(:colon, param)
75
+ else # do nothing
76
+ end
77
+ end
78
+
79
+ def escaped
80
+ grab # Eat the backslash
81
+ ch = grab # Take next char
82
+ ch
83
+ end
84
+
85
+ end
86
+
87
+
88
+ # FIXME...
89
+
90
+ module Livetext::FormatLine::FunCall
91
+
92
+ include Livetext::ParsingConstants
93
+
94
+ def param_loop(char)
95
+ param = ""
96
+ loop do
97
+ case peek
98
+ when Escape
99
+ param << escaped
100
+ when char, LF, nil
101
+ break
102
+ else
103
+ param << peek
104
+ grab
105
+ end
106
+ end
107
+ param = nil if param.empty?
108
+ param
109
+ end
110
+
111
+ def grab_colon_param
112
+ grab # grab :
113
+ param = param_loop(Space)
114
+ end
115
+
116
+ def grab_bracket_param
117
+ grab # [
118
+ param = param_loop("]")
119
+ grab # "]"
120
+ param
121
+ end
122
+
123
+ def funcall(name, param)
124
+ err = "[Error evaluating $$#{name}(#{param})]"
125
+ func_name = name # "func_" + name.to_s
126
+ result =
127
+ if self.send?(func_name, param) # self.respond_to?(func_name)
128
+ # do nothing
129
+ else
130
+ fobj = ::Livetext::Functions.new
131
+ fobj.send(name, param) rescue err
132
+ end
133
+ result.to_s
134
+ end
135
+
136
+ def double_dollar
137
+ case lookahead
138
+ when Space; add_token :string, "$$ "; grab; return
139
+ when LF, nil; add "$$"; add_token :str
140
+ when Alpha
141
+ add_token(:str, @token)
142
+ func = grab_alpha
143
+ add_token(:func, func)
144
+ param = grab_func_param # may be null/missing
145
+ else
146
+ grab; add_token :str, "$$" + peek; return
147
+ end
148
+ end
149
+
150
+ def grab_func_param
151
+ case lookahead
152
+ when "["
153
+ param = grab_bracket_param
154
+ add_token(:brackets, param)
155
+ when ":"
156
+ param = grab_colon_param
157
+ add_token(:colon, param)
158
+ else # do nothing
159
+ end
160
+ end
161
+
162
+ def escaped
163
+ grab # Eat the backslash
164
+ ch = grab # Take next char
165
+ ch
166
+ end
167
+
168
+ end
@@ -1,5 +1,3 @@
1
- # p __FILE__
2
-
3
1
 
4
2
  # Class Functions is where '$$func' functions are stored dynamically...
5
3
  # user-def AND pre-def??
@@ -1,14 +1,13 @@
1
- # p __FILE__
2
-
3
1
 
4
2
  module GlobalHelpers
5
3
 
6
4
  def check_disallowed(name)
5
+ api.tty "GLOBAL cdis"
7
6
  raise DisallowedName(name) if disallowed?(name)
8
7
  end
9
8
 
10
9
  def check_file_exists(file)
11
- raise FileNotFound(file) unless File.exist?(file)
10
+ graceful_error FileNotFound(file) unless File.exist?(file)
12
11
  end
13
12
 
14
13
  def grab_file(fname)
@@ -36,4 +35,8 @@ module GlobalHelpers
36
35
  return nil
37
36
  end
38
37
 
38
+ def cwd_root?
39
+ File.dirname(File.expand_path(".")) == "/"
40
+ end
41
+
39
42
  end
@@ -1,6 +1,7 @@
1
1
 
2
2
  require_relative '../helpers'
3
- require_relative '../global_helpers'
3
+
4
+ # Handle a .import
4
5
 
5
6
  class Livetext::Handler::Import
6
7
  include Livetext::Helpers
@@ -24,21 +25,16 @@ class Livetext::Handler::Import
24
25
  name
25
26
  end
26
27
 
27
- def self.get_module(filename)
28
+ def self.get_module(filename, parent)
29
+ # TTY.puts "#{__method__}: filename = #{filename.inspect}"
28
30
  handler = self.new(filename)
31
+ parent.graceful_error FileNotFound(filename) if handler.file.nil?
29
32
  @file = handler.file.sub(/.rb$/, "")
30
33
  require @file # + ".rb"
31
34
  modname = get_mod_name
32
- # TTY.puts "modname = #{modname.inspect}"
33
35
  newmod = Object.const_get("::" + modname)
34
36
  newmod # return actual module
35
37
  end
36
38
 
37
- private
38
-
39
- def cwd_root?
40
- File.dirname(File.expand_path(".")) == "/"
41
- end
42
-
43
39
  end
44
40
 
@@ -0,0 +1,33 @@
1
+
2
+ require_relative '../helpers'
3
+
4
+ # Handle a .mixin
5
+
6
+ class Livetext::Handler::Mixin
7
+ include Livetext::Helpers
8
+ include GlobalHelpers
9
+
10
+ attr_reader :file
11
+
12
+ def initialize(name, parent)
13
+ @name = name
14
+ @file = find_file(name, ".rb", "plugin")
15
+ parent.graceful_error FileNotFound(name) if @file.nil?
16
+ end
17
+
18
+ def self.get_module(filename, parent)
19
+ handler = self.new(filename, parent)
20
+ modname, code = handler.read_mixin
21
+ eval(code) # Avoid in the future
22
+ newmod = Object.const_get("::" + modname)
23
+ newmod # return actual module
24
+ end
25
+
26
+ def read_mixin
27
+ modname = @name.gsub("/","_").capitalize
28
+ meths = grab_file(@file) # already has .rb?
29
+ [modname, "module ::#{modname}; #{meths}\nend"]
30
+ end
31
+
32
+ end
33
+
@@ -1,3 +1,3 @@
1
- # p __FILE__
2
1
 
3
2
  require_relative 'handler/import'
3
+ require_relative 'handler/mixin'