livetext 0.9.13 → 0.9.19

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. data/README.lt3 +2 -2
  3. data/imports/bookish.rb +288 -0
  4. data/imports/calibre.rb +28 -0
  5. data/imports/livemagick.rb +133 -0
  6. data/imports/markdown.rb +44 -0
  7. data/imports/markdown_importable.rb +46 -0
  8. data/imports/pyggish.rb +204 -0
  9. data/imports/tutorial.rb +95 -0
  10. data/lib/cmdargs.rb +93 -0
  11. data/lib/errors.rb +4 -2
  12. data/lib/formatline.rb +56 -83
  13. data/lib/functions.rb +1 -1
  14. data/lib/handler/icanhaz.rb +35 -0
  15. data/lib/handler.rb +1 -0
  16. data/lib/helpers.rb +177 -4
  17. data/lib/livetext.rb +20 -139
  18. data/lib/parser/file.rb +8 -0
  19. data/lib/parser/general.rb +1 -1
  20. data/lib/parser/import.rb +1 -3
  21. data/lib/parser/mixin.rb +22 -30
  22. data/lib/parser/set.rb +35 -26
  23. data/lib/parser/string.rb +19 -4
  24. data/lib/processor.rb +2 -12
  25. data/lib/standard.rb +73 -107
  26. data/lib/userapi.rb +1 -4
  27. data/livetext.gemspec +2 -1
  28. data/plugin/bookish.rb +26 -22
  29. data/plugin/calibre.rb +1 -1
  30. data/plugin/livemagick.rb +10 -10
  31. data/plugin/markdown.rb +13 -11
  32. data/plugin/pyggish.rb +94 -84
  33. data/plugin/tutorial.rb +10 -5
  34. data/test/snapshots/OMIT.txt +11 -0
  35. data/test/snapshots/clusion.txt +84 -0
  36. data/test/snapshots/error_inc_line_num/match-error.txt +1 -0
  37. data/test/snapshots/error_invalid_name/match-error.txt +1 -0
  38. data/test/snapshots/error_line_num/match-error.txt +1 -0
  39. data/test/snapshots/error_mismatched_end/expected-output.txt +0 -2
  40. data/test/snapshots/error_mismatched_end/match-error.txt +1 -0
  41. data/test/snapshots/error_missing_end/match-error.txt +1 -0
  42. data/test/snapshots/error_no_such_copy/match-error.txt +1 -0
  43. data/test/snapshots/error_no_such_copy/source.lt3 +0 -1
  44. data/test/snapshots/error_no_such_inc/match-error.txt +1 -0
  45. data/test/snapshots/error_no_such_mixin/match-error.txt +1 -0
  46. data/test/snapshots/icanhaz/expected-output.txt +5 -0
  47. data/test/snapshots/icanhaz/match-error.txt +1 -0
  48. data/test/snapshots/icanhaz/simple_import.rb +5 -0
  49. data/test/snapshots/{error_no_such_mixin/actual-output.txt → icanhaz/source.lt3} +3 -4
  50. data/test/snapshots/{error_invalid_name/actual-output.txt → icanhaz2/expected-error.txt} +0 -0
  51. data/test/snapshots/icanhaz2/expected-output.txt +6 -0
  52. data/test/snapshots/icanhaz2/simple_canhaz.rb +5 -0
  53. data/test/snapshots/icanhaz2/source.lt3 +6 -0
  54. data/test/snapshots/predef_vars/match-output.txt +6 -0
  55. data/test/snapshots/{error_no_such_copy/actual-output.txt → simple_import/expected-error.txt} +0 -0
  56. data/test/snapshots/simple_import/expected-output.txt +7 -0
  57. data/test/snapshots/simple_import/simple_import.rb +5 -0
  58. data/test/snapshots/simple_import/source.lt3 +7 -0
  59. data/test/snapshots/simple_include/source.lt3 +0 -1
  60. data/test/snapshots.rb +103 -107
  61. data/test/unit/all.rb +1 -0
  62. data/test/unit/formatline.rb +650 -0
  63. data/test/unit/parser/general.rb +21 -21
  64. data/test/unit/parser/importable.rb +1 -1
  65. data/test/unit/parser/mixin.rb +2 -2
  66. data/test/unit/parser/set.rb +19 -12
  67. data/test/unit/parser/string.rb +14 -14
  68. data/test/unit/parser.rb +2 -0
  69. metadata +37 -46
  70. data/test/formatting.rb +0 -103
  71. data/test/snapshots/error_inc_line_num/actual-error.txt +0 -1
  72. data/test/snapshots/error_inc_line_num/actual-output.txt +0 -13
  73. data/test/snapshots/error_inc_line_num/expected-err-line1match.txt +0 -1
  74. data/test/snapshots/error_inc_line_num/out-sdiff.txt +0 -14
  75. data/test/snapshots/error_invalid_name/actual-error.txt +0 -10
  76. data/test/snapshots/error_invalid_name/expected-err-line1match.txt +0 -1
  77. data/test/snapshots/error_invalid_name/out-sdiff.txt +0 -6
  78. data/test/snapshots/error_line_num/actual-error.txt +0 -1
  79. data/test/snapshots/error_line_num/actual-output.txt +0 -5
  80. data/test/snapshots/error_line_num/expected-err-line1match.txt +0 -1
  81. data/test/snapshots/error_line_num/out-sdiff.txt +0 -6
  82. data/test/snapshots/error_mismatched_end/actual-error.txt +0 -1
  83. data/test/snapshots/error_mismatched_end/actual-output.txt +0 -8
  84. data/test/snapshots/error_mismatched_end/expected-err-line1match.txt +0 -1
  85. data/test/snapshots/error_mismatched_end/out-sdiff.txt +0 -9
  86. data/test/snapshots/error_missing_end/actual-error.txt +0 -1
  87. data/test/snapshots/error_missing_end/actual-output.txt +0 -5
  88. data/test/snapshots/error_missing_end/expected-err-line1match.txt +0 -1
  89. data/test/snapshots/error_missing_end/out-sdiff.txt +0 -6
  90. data/test/snapshots/error_name_not_permitted/OLD-exp-out +0 -4
  91. data/test/snapshots/error_no_such_copy/actual-error.txt +0 -10
  92. data/test/snapshots/error_no_such_copy/expected-err-line1match.txt +0 -1
  93. data/test/snapshots/error_no_such_copy/out-sdiff.txt +0 -5
  94. data/test/snapshots/error_no_such_inc/actual-error.txt +0 -10
  95. data/test/snapshots/error_no_such_inc/actual-output.txt +0 -0
  96. data/test/snapshots/error_no_such_inc/expected-err-line1match.txt +0 -1
  97. data/test/snapshots/error_no_such_inc/out-sdiff.txt +0 -6
  98. data/test/snapshots/error_no_such_mixin/actual-error.txt +0 -1
  99. data/test/snapshots/error_no_such_mixin/expected-err-line1match.txt +0 -1
  100. data/test/snapshots/error_no_such_mixin/out-sdiff.txt +0 -12
  101. data/test/snapshots/lines.txt +0 -124
  102. data/test/snapshots/predef_vars/actual-error.txt +0 -0
  103. data/test/snapshots/predef_vars/actual-output.txt +0 -6
  104. data/test/snapshots/predef_vars/expected-output.txt +0 -6
  105. data/test/snapshots/predef_vars/out-sdiff.txt +0 -7
  106. data/test/snapshots/simple_mixin/actual-error.txt +0 -2
  107. data/test/snapshots/simple_mixin/actual-output.txt +0 -4
  108. data/test/snapshots/simple_mixin/out-sdiff.txt +0 -6
  109. data/test/unit/parse_misc.rb +0 -60
  110. data/test/unit/parse_set.rb +0 -157
data/lib/functions.rb CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
- require_relative 'standard' # FIXME?
2
+ require_relative 'standard' # FIXME umm, why is this necessary??
3
3
 
4
4
  # Class Functions is where '$$func' functions are stored dynamically...
5
5
  # user-def AND pre-def??
@@ -0,0 +1,35 @@
1
+
2
+ class Livetext::Handler::ICanHaz
3
+ include Helpers
4
+
5
+ attr_reader :file
6
+
7
+ def initialize(name)
8
+ @name = name
9
+ @file = find_file(name)
10
+ end
11
+
12
+ def self.get_module(name)
13
+ handler = self.new(name)
14
+ const1 = Object.constants
15
+ @file = handler.file.sub(/.rb$/, "")
16
+ require @file # + ".rb"
17
+ const2 = Object.constants
18
+ names = (const2 - const1)
19
+ abort "Expected ONE new constant: #{names.inspect}" if names.size != 1
20
+ modname = names.first.to_s
21
+ newmod = Object.const_get("::" + modname)
22
+ newmod # return actual module
23
+ end
24
+
25
+ private
26
+
27
+ def cwd_root?
28
+ File.dirname(File.expand_path(".")) == "/"
29
+ end
30
+
31
+ def fname2module(name)
32
+ end
33
+
34
+ end
35
+
data/lib/handler.rb ADDED
@@ -0,0 +1 @@
1
+ require_relative 'handler/icanhaz'
data/lib/helpers.rb CHANGED
@@ -1,10 +1,117 @@
1
1
 
2
2
  module Helpers
3
3
 
4
+ Space = " "
5
+ Sigil = "." # Can't change yet
6
+
7
+ def escape_html(string)
8
+ enc = string.encoding
9
+ unless enc.ascii_compatible?
10
+ if enc.dummy?
11
+ origenc = enc
12
+ enc = Encoding::Converter.asciicompat_encoding(enc)
13
+ string = enc ? string.encode(enc) : string.b
14
+ end
15
+ table = Hash[TABLE_FOR_ESCAPE_HTML__.map {|pair|pair.map {|s|s.encode(enc)}}]
16
+ string = string.gsub(/#{"['&\"<>]".encode(enc)}/, table)
17
+ string.encode!(origenc) if origenc
18
+ return string
19
+ end
20
+ string.gsub(/['&\"<>]/, TABLE_FOR_ESCAPE_HTML__)
21
+ end
22
+
23
+ def find_file(name, ext=".rb")
24
+ paths = [Livetext::Path.sub(/lib/, "imports/"), "./"]
25
+ base = "#{name}#{ext}"
26
+ paths.each do |path|
27
+ file = path + base
28
+ return file if File.exist?(file)
29
+ end
30
+
31
+ raise "No such mixin '#{name}'"
32
+
33
+ # # Really want to search upward??
34
+ # raise "No such mixin '#{name}'" if cwd_root?
35
+ # Dir.chdir("..") { find_file(name) }
36
+ end
37
+
38
+ def self.rx(str, space=nil)
39
+ Regexp.compile("^" + Regexp.escape(str) + "#{space}")
40
+ end
41
+
42
+ Comment = rx(Sigil, Space)
43
+ Dotcmd = rx(Sigil)
44
+ Ddotcmd = /^ *\$\.[A-Za-z]/
45
+
46
+ ## FIXME process_file[!] should call process[_text]
47
+
48
+ def process_file(fname, btrace=false)
49
+ setfile(fname)
50
+ text = File.readlines(fname)
51
+ enum = text.each
52
+ @backtrace = btrace
53
+ @main.source(enum, fname, 0)
54
+ line = nil
55
+ loop do
56
+ line = @main.nextline
57
+ break if line.nil?
58
+ process_line(line)
59
+ end
60
+ val = @main.finalize if @main.respond_to? :finalize
61
+ @body
62
+ end
63
+
64
+ def process_line(line) # FIXME inefficient?
65
+ nomarkup = true
66
+ case line # must apply these in order
67
+ when Comment
68
+ handle_scomment(line)
69
+ when Dotcmd
70
+ handle_dotcmd(line)
71
+ when Ddotcmd
72
+ indent = line.index("$") + 1
73
+ @indentation.push(indent)
74
+ line.sub!(/^ *\$/, "")
75
+ handle_dotcmd(line)
76
+ indentation.pop
77
+ else
78
+ @main._passthru(line)
79
+ end
80
+ end
81
+
82
+ def handle_dotcmd(line, indent = 0)
83
+ indent = @indentation.last # top of stack
84
+ line = line.sub(/# .*$/, "")
85
+ name = get_name(line).to_sym
86
+ result = nil
87
+ case
88
+ when name == :end # special case
89
+ puts @body
90
+ raise EndWithoutOpening()
91
+ when @main.respond_to?(name)
92
+ result = @main.send(name)
93
+ else
94
+ puts @body # earlier correct output, not flushed yet
95
+ raise "Name '#{name}' is unknown"
96
+ return
97
+ end
98
+ result
99
+ end
100
+
101
+ def handle_scomment(line)
102
+ end
103
+
104
+ def get_name(line)
105
+ name, data = line.split(" ", 2)
106
+ name = name[1..-1] # chop off sigil
107
+ name = "dot_" + name if %w[include def].include?(name)
108
+ @main.data = data
109
+ @main.check_disallowed(name)
110
+ name
111
+ end
112
+
4
113
  def check_disallowed(name)
5
- # raise "Illegal name '#{name}'" if _disallowed?(name)
6
- # FIXME use custom exception
7
- raise DisallowedName, name if _disallowed?(name)
114
+ raise DisallowedName(name) if disallowed?(name)
8
115
  end
9
116
 
10
117
  def check_file_exists(file)
@@ -14,8 +121,74 @@ module Helpers
14
121
  def set_variables(pairs)
15
122
  pairs.each do |pair|
16
123
  var, value = *pair
17
- @parent._setvar(var, value)
124
+ @parent.setvar(var, value)
125
+ end
126
+ end
127
+
128
+ def grab_file(fname)
129
+ File.read(fname)
130
+ end
131
+
132
+ def search_upward(file)
133
+ value = nil
134
+ return file if File.exist?(file)
135
+
136
+ count = 1
137
+ loop do
138
+ front = "../" * count
139
+ count += 1
140
+ here = Pathname.new(front).expand_path.dirname.to_s
141
+ break if here == "/"
142
+ path = front + file
143
+ value = path if File.exist?(path)
144
+ break if value
145
+ end
146
+ STDERR.puts "Cannot find #{file.inspect} from #{Dir.pwd}" unless value
147
+ return value
148
+ rescue
149
+ STDERR.puts "Can't find #{file.inspect} from #{Dir.pwd}"
150
+ return nil
151
+ end
152
+
153
+ def include_file(file)
154
+ @_args = [file]
155
+ dot_include
156
+ end
157
+
158
+ def onoff(arg) # helper
159
+ arg ||= "on"
160
+ raise ExpectedOnOff unless String === arg
161
+ case arg.downcase
162
+ when "on"
163
+ return true
164
+ when "off"
165
+ return false
166
+ else
167
+ raise ExpectedOnOff
18
168
  end
19
169
  end
20
170
 
171
+ def setvar(var, val)
172
+ str, sym = var.to_s, var.to_sym
173
+ Livetext::Vars[str] = val
174
+ Livetext::Vars[sym] = val
175
+ @_vars[str] = val
176
+ @_vars[sym] = val
177
+ end
178
+
179
+ def setfile(file)
180
+ if file
181
+ setvar(:File, file)
182
+ dir = File.dirname(File.expand_path(file))
183
+ setvar(:FileDir, dir)
184
+ else
185
+ setvar(:File, "[no file]")
186
+ setvar(:FileDir, "[no dir]")
187
+ end
188
+ end
189
+
190
+ def setfile!(file) # FIXME why does this variant exist?
191
+ setvar(:File, file)
192
+ end
193
+
21
194
  end
data/lib/livetext.rb CHANGED
@@ -1,8 +1,11 @@
1
1
  # Class Livetext skeleton (top level).
2
2
 
3
3
  class Livetext
4
- VERSION = "0.9.13"
4
+ VERSION = "0.9.19"
5
5
  Path = File.expand_path(File.join(File.dirname(__FILE__)))
6
+
7
+ module Handler
8
+ end
6
9
  end
7
10
 
8
11
  # $LOAD_PATH << Livetext::Path
@@ -15,27 +18,24 @@ require_relative 'userapi'
15
18
  require_relative 'standard'
16
19
  require_relative 'formatline'
17
20
  require_relative 'processor'
21
+ require_relative 'helpers'
22
+ require_relative 'handler'
18
23
 
19
24
  Plugins = File.expand_path(File.join(File.dirname(__FILE__), "../plugin"))
25
+ Imports = File.expand_path(File.join(File.dirname(__FILE__), "../imports"))
20
26
 
21
27
  TTY = ::File.open("/dev/tty", "w")
22
28
 
29
+ make_exception(:EndWithoutOpening, "Error: found .end with no opening command")
30
+
23
31
  # Class Livetext reopened (top level).
24
32
 
25
33
  class Livetext
26
34
 
27
- Vars = {}
28
-
29
- Space = " "
30
- Sigil = "." # Can't change yet
35
+ include Helpers
31
36
 
32
- def self.rx(str, space=nil)
33
- Regexp.compile("^" + Regexp.escape(str) + "#{space}")
34
- end
37
+ Vars = {}
35
38
 
36
- Comment = rx(Sigil, Livetext::Space)
37
- Dotcmd = rx(Sigil)
38
- Ddotcmd = /^ *\$\.[A-Za-z]/
39
39
 
40
40
  attr_reader :main
41
41
  attr_accessor :no_puts
@@ -55,16 +55,17 @@ class Livetext
55
55
  call = Array(call)
56
56
  mix.each {|lib| obj.mixin(lib) }
57
57
  call.each {|cmd| obj.main.send(cmd[1..-1]) } # ignores leading dot, no param
58
- vars.each_pair {|var, val| obj._setvar(var, val.to_s) }
58
+ vars.each_pair {|var, val| obj.setvar(var, val.to_s) }
59
59
  obj
60
60
  end
61
61
 
62
62
  def customize(mix: [], call: [], vars: {})
63
63
  mix = Array(mix)
64
64
  call = Array(call)
65
+ # FIXME HF won't this break??
65
66
  mix.each {|lib| mixin(lib) }
66
67
  call.each {|cmd| @main.send(cmd[1..-1]) } # ignores leading dot, no param
67
- vars.each_pair {|var, val| _setvar(var, val.to_s) }
68
+ vars.each_pair {|var, val| setvar(var, val.to_s) }
68
69
  self
69
70
  end
70
71
 
@@ -77,81 +78,17 @@ class Livetext
77
78
  @main = Processor.new(self, output)
78
79
  @indentation = [0]
79
80
  @_vars = Livetext::Vars
80
-
81
- # Other predefined variables (see also _setfile)
82
- _setvar(:User, `whoami`.chomp)
83
- _setvar(:Version, Livetext::VERSION)
84
- end
85
-
86
- def _parse_colon_args(args, hash) # really belongs in livetext
87
- h2 = hash.dup
88
- e = args.each
89
- loop do
90
- arg = e.next.chop.to_sym
91
- raise "_parse_args: #{arg} is unknown" unless hash.keys.include?(arg)
92
- h2[arg] = e.next
93
- end
94
- h2 = h2.reject {|k,v| v.nil? }
95
- h2.each_pair {|k, v| raise "#{k} has no value" if v.empty? }
96
- h2
81
+ initial_vars
97
82
  end
98
83
 
99
- def _get_arg(name, args) # really belongs in livetext
100
- raise "(#{name}) Expected an array" unless args.is_a? Array
101
- raise "(#{name}) Expected an arg" if args.empty?
102
- raise "(#{name}) Too many args: #{args.inspect}" if args.size > 1
103
- val = args[0]
104
- raise "Expected an argument '#{name}'" if val.nil?
105
- val
106
- end
107
-
108
- def mixin(mod)
109
- @main._mixin(mod)
110
- end
111
-
112
- def _setvar(var, val)
113
- str, sym = var.to_s, var.to_sym
114
- Livetext::Vars[str] = val
115
- Livetext::Vars[sym] = val
116
- @_vars[str] = val
117
- @_vars[sym] = val
118
- end
119
-
120
- def _setfile(file)
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
129
- end
130
-
131
- def _setfile!(file)
132
- _setvar(:File, file)
133
- end
134
-
135
- def process_line(line) # FIXME inefficient?
136
- nomarkup = true
137
- case line # must apply these in order
138
- when Comment
139
- handle_scomment(line)
140
- when Dotcmd
141
- handle_dotcmd(line)
142
- when Ddotcmd
143
- indent = line.index("$") + 1
144
- @indentation.push(indent)
145
- line.sub!(/^ *\$/, "")
146
- handle_dotcmd(line)
147
- indentation.pop
148
- else
149
- @main._passthru(line)
150
- end
84
+ def initial_vars
85
+ # Other predefined variables (see also setfile)
86
+ setvar(:User, `whoami`.chomp)
87
+ setvar(:Version, Livetext::VERSION)
151
88
  end
152
89
 
153
90
  def transform(text)
154
- _setfile!("(string)")
91
+ setfile!("(string)")
155
92
  enum = text.each_line
156
93
  front = text.match(/.*?\n/).to_a.first.chomp rescue ""
157
94
  @main.source(enum, "STDIN: '#{front}...'", 0)
@@ -188,61 +125,5 @@ class Livetext
188
125
  self.body
189
126
  end
190
127
 
191
- ## FIXME process_file[!] should call process[_text]
192
-
193
- def process_file(fname, btrace=false)
194
- _setfile(fname)
195
- text = File.readlines(fname) # FIXME currently causes failure
196
- enum = text.each
197
- @backtrace = btrace
198
- @main.source(enum, fname, 0)
199
- line = nil
200
- loop do
201
- line = @main.nextline
202
- break if line.nil?
203
- process_line(line)
204
- end
205
- val = @main.finalize if @main.respond_to? :finalize
206
- @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 = ""
212
- end
213
-
214
- def handle_scomment(line)
215
- end
216
-
217
- def _get_name(line)
218
- name, data = line.split(" ", 2)
219
- name = name[1..-1] # chop off sigil
220
- name = "_" + name if %w[include def].include?(name)
221
- @main.data = data
222
- @main.check_disallowed(name)
223
- name
224
- end
225
-
226
- def handle_dotcmd(line, indent = 0)
227
- indent = @indentation.last # top of stack
228
- line = line.sub(/# .*$/, "")
229
- name = _get_name(line).to_sym
230
- result = nil
231
- if @main.respond_to?(name)
232
- result = @main.send(name)
233
- else
234
- @main._error! "Name '#{name}' is unknown"
235
- return
236
- end
237
- result
238
- rescue => err
239
- STDERR.puts "Error: #{err.inspect}"
240
- # STDERR.puts err.backtrace
241
- # @main._error!(err)
242
- puts @body
243
- @body = ""
244
- return @body
245
- end
246
-
247
128
  end
248
129
 
@@ -0,0 +1,8 @@
1
+
2
+ require_relative '../livetext'
3
+
4
+ # Hmm. not today?
5
+
6
+ class Livetext::ParseFile
7
+
8
+ end
@@ -7,7 +7,7 @@ make_exception(:NilValue, "Error: nil value")
7
7
  make_exception(:NullString, "Error: null string")
8
8
  make_exception(:ExpectedString, "Error: expected a string")
9
9
 
10
- class Livetext::ParseMisc < StringParser
10
+ class Livetext::ParseGeneral < StringParser
11
11
 
12
12
  def initialize(str)
13
13
  super
data/lib/parser/import.rb CHANGED
@@ -4,9 +4,7 @@ require '../livetext/importable'
4
4
  make_exception(:BadVariableName, "Error: invalid variable name")
5
5
  make_exception(:NoEqualSign, "Error: no equal sign found")
6
6
 
7
- # FIXME probably belongs elsewhere?
8
-
9
- class Livetext::ParseImport
7
+ class Livetext::Handler::Import
10
8
  def use_import(name)
11
9
  require name
12
10
  include name
data/lib/parser/mixin.rb CHANGED
@@ -1,46 +1,38 @@
1
1
  require_relative '../livetext'
2
+ require_relative '../helpers'
2
3
  require_relative 'string'
3
4
 
4
- make_exception(:BadVariableName, "Error: invalid variable name")
5
5
  make_exception(:NoEqualSign, "Error: no equal sign found")
6
6
 
7
- # FIXME probably belongs elsewhere?
7
+ class Livetext::ParseMixin
8
+ include Helpers
8
9
 
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
10
+ def initialize(name)
11
+ @name = name
12
+ @file = find_file(name)
13
+ end
18
14
 
19
- def cwd_root?
20
- File.dirname(File.expand_path(".")) == "/"
15
+ def self.get_module(name)
16
+ parse = self.new(name)
17
+ modname, code = parse.read_mixin
18
+ eval(code) # Avoid in the future
19
+ newmod = Object.const_get("::" + modname)
20
+ # return actual module
21
+ newmod
21
22
  end
22
23
 
23
- def find_mixin(name)
24
- file = "#{Plugins}/" + name.downcase + ".rb"
25
- return file if File.exist?(file)
24
+ def read_mixin
25
+ modname = @name.gsub("/","_").capitalize
26
+ meths = grab_file(@file)
27
+ [modname, "module ::#{modname}; #{meths}\nend"]
28
+ end
26
29
 
27
- file = "./#{name}.rb"
28
- return file if File.exist?(file)
30
+ private
29
31
 
30
- raise "No such mixin '#{name}'" if cwd_root?
31
- Dir.chdir("..") { find_mixin(name) }
32
+ def cwd_root?
33
+ File.dirname(File.expand_path(".")) == "/"
32
34
  end
33
35
 
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
36
 
45
37
  end
46
38
 
data/lib/parser/set.rb CHANGED
@@ -17,22 +17,31 @@ class Livetext::ParseSet < StringParser
17
17
  super
18
18
  end
19
19
 
20
+ def wtf(note="")
21
+ TTY.puts "| PARSER: @i = #@i @len = #@len"
22
+ TTY.puts "|#{note}"
23
+ TTY.puts "| [" + @line.gsub(" ", "_") + "]"
24
+ TTY.print "| " # 0-based (one extra space)
25
+ @i.times { TTY.print "-" }
26
+ TTY.puts "^"
27
+ TTY.puts
28
+ end
29
+
20
30
  def parse
21
31
  pairs = []
22
-
32
+ char = nil
23
33
  loop do
24
- skip_spaces
25
- char = self.peek
26
34
  break if eos? # end of string
35
+ char = skip_spaces
27
36
  raise "Expected alpha to start var name" unless char =~ /[a-z]/i
28
37
  pairs << assignment
29
- skip_spaces
30
- char = self.peek
38
+ char = skip_spaces
31
39
  break if eos? # end of string
32
40
  case char
33
41
  when nil # end of string
34
42
  when ","
35
- self.next # skip comma
43
+ char = grab # skip comma
44
+ char = skip_spaces
36
45
  else
37
46
  raise "Expected comma or end of string (found #{char.inspect})"
38
47
  end
@@ -47,7 +56,7 @@ class Livetext::ParseSet < StringParser
47
56
  var = get_var
48
57
  skip_equal
49
58
  value = get_value
50
- value = FormatLine.var_func_parse(value)
59
+ value = FormatLine.var_func_parse(value) # FIXME broken now?
51
60
  pair = [var, value]
52
61
  pair
53
62
  end
@@ -55,11 +64,11 @@ class Livetext::ParseSet < StringParser
55
64
  def get_var
56
65
  name = ""
57
66
  loop do
58
- char = self.peek
67
+ char = peek
59
68
  break if eos? # end of string
60
69
  case char
61
70
  when /[a-zA-Z_\.0-9]/
62
- name << self.next
71
+ name << grab
63
72
  next
64
73
  when /[ =]/
65
74
  return name
@@ -73,11 +82,10 @@ class Livetext::ParseSet < StringParser
73
82
  def skip_equal
74
83
  found = false
75
84
  skip_spaces
76
- raise NoEqualSign unless self.peek == "="
85
+ raise NoEqualSign unless peek == "="
77
86
  found = true
78
- self.next # skip =... spaces too
79
- self.skip_spaces
80
- peek = self.peek
87
+ grab # skip =
88
+ skip_spaces # skip spaces too
81
89
  return peek # just for testing
82
90
  rescue StopIteration
83
91
  raise NoEqualSign unless found
@@ -85,40 +93,41 @@ class Livetext::ParseSet < StringParser
85
93
  end
86
94
 
87
95
  def escaped
88
- self.next # skip backslash
89
- self.next # return following char
96
+ grab # skip backslash
97
+ grab # return following char
90
98
  end
91
99
 
92
100
  make_exception(:BadQuotedString, "Bad quoted string: %1")
93
101
 
94
102
  def quoted_value
95
- quote = self.next # opening quote...
103
+ quote = grab # opening quote...
96
104
  value = ""
97
105
  char = nil
98
106
  loop do
99
- char = self.peek
100
- break if self.eos?
107
+ char = grab
108
+ break if eos?
101
109
  break if char == quote
110
+ # break if char.nil?
102
111
  char = escaped if char == "\\"
103
112
  value << char
104
- char = self.next
105
113
  end
106
114
  if char == quote
107
- char = self.next
115
+ # char = grab
108
116
  return value
109
117
  end
110
118
  raise BadQuotedString, quote + value
111
119
  end
112
120
 
113
121
  def unquoted_value
114
- # puts "#{__method__}: #{@line.inspect} i = #@i peek = #{self.peek.inspect}"
122
+ char = nil
115
123
  value = ""
116
124
  loop do
117
- char = self.peek
118
- break if self.eos?
125
+ char = peek
126
+ break if eos? # FIXME oops???
127
+ # break if char.nil?
119
128
  break if char == " " || char == ","
120
129
  value << char
121
- char = self.next
130
+ char = grab
122
131
  end
123
132
  value
124
133
  end
@@ -128,8 +137,8 @@ class Livetext::ParseSet < StringParser
128
137
  end
129
138
 
130
139
  def get_value
131
- char = self.peek
132
- value = quote?(char) ? quoted_value : unquoted_value
140
+ char = peek
141
+ value = quote?(char) ? quoted_value : unquoted_value
133
142
  value
134
143
  end
135
144
  end