livetext 0.9.14 → 0.9.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/lib/cmdargs.rb +93 -0
  3. data/lib/formatline.rb +56 -83
  4. data/lib/helpers.rb +142 -4
  5. data/lib/livetext.rb +11 -141
  6. data/lib/parser/file.rb +8 -0
  7. data/lib/parser/mixin.rb +28 -15
  8. data/lib/parser/set.rb +35 -26
  9. data/lib/parser/string.rb +19 -4
  10. data/lib/processor.rb +1 -4
  11. data/lib/standard.rb +56 -96
  12. data/plugin/bookish.rb +26 -22
  13. data/plugin/calibre.rb +1 -1
  14. data/plugin/livemagick.rb +10 -10
  15. data/plugin/markdown.rb +13 -11
  16. data/plugin/pyggish.rb +94 -84
  17. data/plugin/tutorial.rb +10 -5
  18. data/test/all.rb +0 -1
  19. data/test/snapshots/OMIT.txt +7 -8
  20. data/test/snapshots/clusion.txt +35 -0
  21. data/test/snapshots/error_inc_line_num/actual-error.txt +14 -0
  22. data/test/snapshots/error_inc_line_num/actual-output.txt +7 -0
  23. data/test/snapshots/error_inc_line_num/match-error.txt +1 -1
  24. data/test/snapshots/error_inc_line_num/out-sdiff.txt +14 -0
  25. data/test/snapshots/error_invalid_name/actual-error.txt +10 -0
  26. data/test/snapshots/error_invalid_name/actual-output.txt +0 -0
  27. data/test/snapshots/error_invalid_name/match-error.txt +1 -1
  28. data/test/snapshots/error_invalid_name/out-sdiff.txt +6 -0
  29. data/test/snapshots/error_line_num/match-error.txt +1 -1
  30. data/test/snapshots/error_mismatched_end/match-error.txt +1 -1
  31. data/test/snapshots/error_missing_end/actual-error.txt +10 -0
  32. data/test/snapshots/error_missing_end/actual-output.txt +0 -0
  33. data/test/snapshots/error_missing_end/match-error.txt +1 -1
  34. data/test/snapshots/error_missing_end/out-sdiff.txt +6 -0
  35. data/test/snapshots/error_no_such_copy/actual-error.txt +10 -0
  36. data/test/snapshots/error_no_such_copy/actual-output.txt +0 -0
  37. data/test/snapshots/error_no_such_copy/match-error.txt +1 -1
  38. data/test/snapshots/error_no_such_copy/out-sdiff.txt +5 -0
  39. data/test/snapshots/error_no_such_copy/source.lt3 +0 -1
  40. data/test/snapshots/error_no_such_inc/actual-error.txt +10 -0
  41. data/test/snapshots/error_no_such_inc/actual-output.txt +0 -0
  42. data/test/snapshots/error_no_such_inc/match-error.txt +1 -1
  43. data/test/snapshots/error_no_such_inc/out-sdiff.txt +6 -0
  44. data/test/snapshots/error_no_such_mixin/actual-error.txt +37 -0
  45. data/test/snapshots/error_no_such_mixin/actual-output.txt +0 -0
  46. data/test/snapshots/error_no_such_mixin/out-sdiff.txt +6 -0
  47. data/test/snapshots/simple_import/actual-error.txt +8 -0
  48. data/test/snapshots/simple_import/actual-output.txt +3 -0
  49. data/test/snapshots/simple_import/err-sdiff.txt +9 -0
  50. data/test/snapshots/simple_import/expected-error.txt +0 -0
  51. data/test/snapshots/simple_import/expected-output.txt +7 -0
  52. data/test/snapshots/simple_import/out-sdiff.txt +9 -0
  53. data/test/snapshots/simple_import/simple_import.rb +5 -0
  54. data/test/snapshots/simple_import/source.lt3 +7 -0
  55. data/test/snapshots/simple_include/source.lt3 +0 -1
  56. data/test/snapshots.rb +3 -2
  57. data/test/unit/all.rb +1 -0
  58. data/test/unit/formatline.rb +650 -0
  59. data/test/unit/parser/importable.rb +1 -1
  60. data/test/unit/parser/mixin.rb +1 -1
  61. data/test/unit/parser/set.rb +19 -12
  62. data/test/unit/parser/string.rb +14 -14
  63. metadata +32 -5
  64. data/test/formatting-tests.rb +0 -35
  65. data/test/formatting.rb +0 -103
  66. data/test/snapshots/formatting-tests.txt +0 -124
data/lib/livetext.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # Class Livetext skeleton (top level).
2
2
 
3
3
  class Livetext
4
- VERSION = "0.9.14"
4
+ VERSION = "0.9.15"
5
5
  Path = File.expand_path(File.join(File.dirname(__FILE__)))
6
6
  end
7
7
 
@@ -9,13 +9,13 @@ end
9
9
 
10
10
  require 'fileutils'
11
11
 
12
- require 'helpers'
13
12
  require_relative 'errors'
14
13
  require_relative 'functions'
15
14
  require_relative 'userapi'
16
15
  require_relative 'standard'
17
16
  require_relative 'formatline'
18
17
  require_relative 'processor'
18
+ require_relative 'helpers'
19
19
 
20
20
  Plugins = File.expand_path(File.join(File.dirname(__FILE__), "../plugin"))
21
21
 
@@ -31,16 +31,6 @@ class Livetext
31
31
 
32
32
  Vars = {}
33
33
 
34
- Space = " "
35
- Sigil = "." # Can't change yet
36
-
37
- def self.rx(str, space=nil)
38
- Regexp.compile("^" + Regexp.escape(str) + "#{space}")
39
- end
40
-
41
- Comment = rx(Sigil, Livetext::Space)
42
- Dotcmd = rx(Sigil)
43
- Ddotcmd = /^ *\$\.[A-Za-z]/
44
34
 
45
35
  attr_reader :main
46
36
  attr_accessor :no_puts
@@ -60,16 +50,17 @@ class Livetext
60
50
  call = Array(call)
61
51
  mix.each {|lib| obj.mixin(lib) }
62
52
  call.each {|cmd| obj.main.send(cmd[1..-1]) } # ignores leading dot, no param
63
- vars.each_pair {|var, val| obj._setvar(var, val.to_s) }
53
+ vars.each_pair {|var, val| obj.setvar(var, val.to_s) }
64
54
  obj
65
55
  end
66
56
 
67
57
  def customize(mix: [], call: [], vars: {})
68
58
  mix = Array(mix)
69
59
  call = Array(call)
60
+ # FIXME HF won't this break??
70
61
  mix.each {|lib| mixin(lib) }
71
62
  call.each {|cmd| @main.send(cmd[1..-1]) } # ignores leading dot, no param
72
- vars.each_pair {|var, val| _setvar(var, val.to_s) }
63
+ vars.each_pair {|var, val| setvar(var, val.to_s) }
73
64
  self
74
65
  end
75
66
 
@@ -82,81 +73,17 @@ class Livetext
82
73
  @main = Processor.new(self, output)
83
74
  @indentation = [0]
84
75
  @_vars = Livetext::Vars
85
-
86
- # Other predefined variables (see also _setfile)
87
- _setvar(:User, `whoami`.chomp)
88
- _setvar(:Version, Livetext::VERSION)
89
- end
90
-
91
- def _parse_colon_args(args, hash) # really belongs in livetext
92
- h2 = hash.dup
93
- e = args.each
94
- loop do
95
- arg = e.next.chop.to_sym
96
- raise "_parse_args: #{arg} is unknown" unless hash.keys.include?(arg)
97
- h2[arg] = e.next
98
- end
99
- h2 = h2.reject {|k,v| v.nil? }
100
- h2.each_pair {|k, v| raise "#{k} has no value" if v.empty? }
101
- h2
102
- end
103
-
104
- def _get_arg(name, args) # really belongs in livetext
105
- raise "(#{name}) Expected an array" unless args.is_a? Array
106
- raise "(#{name}) Expected an arg" if args.empty?
107
- raise "(#{name}) Too many args: #{args.inspect}" if args.size > 1
108
- val = args[0]
109
- raise "Expected an argument '#{name}'" if val.nil?
110
- val
111
- end
112
-
113
- def mixin(mod)
114
- @main._mixin(mod)
115
- end
116
-
117
- def _setvar(var, val)
118
- str, sym = var.to_s, var.to_sym
119
- Livetext::Vars[str] = val
120
- Livetext::Vars[sym] = val
121
- @_vars[str] = val
122
- @_vars[sym] = val
76
+ initial_vars
123
77
  end
124
78
 
125
- def _setfile(file)
126
- if file
127
- _setvar(:File, file)
128
- dir = File.dirname(File.expand_path(file))
129
- _setvar(:FileDir, dir)
130
- else
131
- _setvar(:File, "[no file]")
132
- _setvar(:FileDir, "[no dir]")
133
- end
134
- end
135
-
136
- def _setfile!(file)
137
- _setvar(:File, file)
138
- end
139
-
140
- def process_line(line) # FIXME inefficient?
141
- nomarkup = true
142
- case line # must apply these in order
143
- when Comment
144
- handle_scomment(line)
145
- when Dotcmd
146
- handle_dotcmd(line)
147
- when Ddotcmd
148
- indent = line.index("$") + 1
149
- @indentation.push(indent)
150
- line.sub!(/^ *\$/, "")
151
- handle_dotcmd(line)
152
- indentation.pop
153
- else
154
- @main._passthru(line)
155
- end
79
+ def initial_vars
80
+ # Other predefined variables (see also setfile)
81
+ setvar(:User, `whoami`.chomp)
82
+ setvar(:Version, Livetext::VERSION)
156
83
  end
157
84
 
158
85
  def transform(text)
159
- _setfile!("(string)")
86
+ setfile!("(string)")
160
87
  enum = text.each_line
161
88
  front = text.match(/.*?\n/).to_a.first.chomp rescue ""
162
89
  @main.source(enum, "STDIN: '#{front}...'", 0)
@@ -193,62 +120,5 @@ class Livetext
193
120
  self.body
194
121
  end
195
122
 
196
- ## FIXME process_file[!] should call process[_text]
197
-
198
- def process_file(fname, btrace=false)
199
- _setfile(fname)
200
- text = File.readlines(fname)
201
- enum = text.each
202
- @backtrace = btrace
203
- @main.source(enum, fname, 0)
204
- line = nil
205
- loop do
206
- line = @main.nextline
207
- break if line.nil?
208
- process_line(line)
209
- end
210
- val = @main.finalize if @main.respond_to? :finalize
211
- @body
212
- rescue => err
213
- STDERR.puts "[process_file] fname = #{fname.inspect}\n line = #{line.inspect}"
214
- STDERR.puts "ERROR #{err} in process_file"
215
- err.backtrace.each {|x| STDERR.puts " " + x }
216
- # @body = ""
217
- end
218
-
219
- def handle_scomment(line)
220
- end
221
-
222
- def _get_name(line)
223
- name, data = line.split(" ", 2)
224
- name = name[1..-1] # chop off sigil
225
- name = "_" + name if %w[include def].include?(name)
226
- @main.data = data
227
- @main.check_disallowed(name)
228
- name
229
- end
230
-
231
- def handle_dotcmd(line, indent = 0)
232
- indent = @indentation.last # top of stack
233
- line = line.sub(/# .*$/, "")
234
- name = _get_name(line).to_sym
235
- result = nil
236
- case
237
- when name == :end # special case
238
- puts @body
239
- raise EndWithoutOpening()
240
- when @main.respond_to?(name)
241
- result = @main.send(name)
242
- else
243
- @main._error! "Name '#{name}' is unknown"
244
- return
245
- end
246
- result
247
- rescue => err
248
- puts @body # earlier correct output, not flushed yet
249
- STDERR.puts "Error: #{err.inspect}"
250
- STDERR.puts err.backtrace
251
- end
252
-
253
123
  end
254
124
 
@@ -0,0 +1,8 @@
1
+
2
+ require_relative '../livetext'
3
+
4
+ # Hmm. not today?
5
+
6
+ class Livetext::ParseFile
7
+
8
+ end
data/lib/parser/mixin.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require_relative '../livetext'
2
+ require_relative '../helpers'
2
3
  require_relative 'string'
3
4
 
4
5
  make_exception(:BadVariableName, "Error: invalid variable name")
@@ -10,30 +11,42 @@ class Livetext::ParseMixin # < StringParser
10
11
 
11
12
  include Helpers
12
13
 
14
+ def initialize(name)
15
+ @name = name
16
+ @file = find_file(name)
17
+ end
18
+
19
+ def self.get_module(name)
20
+ parse = self.new(name)
21
+ modname, code = parse.read_mixin
22
+ eval(code) # Avoid in the future
23
+ newmod = Object.const_get("::" + modname)
24
+ # return actual module
25
+ newmod
26
+ end
27
+
28
+ def read_mixin
29
+ modname = @name.gsub("/","_").capitalize
30
+ meths = grab_file(@file)
31
+ [modname, "module ::#{modname}; #{meths}\nend"]
32
+ end
33
+
34
+ private
35
+
13
36
  def cwd_root?
14
37
  File.dirname(File.expand_path(".")) == "/"
15
38
  end
16
39
 
17
- def find_mixin(name)
18
- file = "#{Plugins}/" + name.downcase + ".rb"
40
+ def find_file(name, ext=".rb")
41
+ base = "./#{name}#{ext}"
42
+ file = "#{Plugins}/#{base}"
19
43
  return file if File.exist?(file)
20
44
 
21
- file = "./#{name}.rb"
45
+ file = base
22
46
  return file if File.exist?(file)
23
47
 
24
48
  raise "No such mixin '#{name}'" if cwd_root?
25
- Dir.chdir("..") { find_mixin(name) }
26
- end
27
-
28
- def use_mixin(name, file)
29
- modname = name.gsub("/","_").capitalize
30
- meths = grab_file(file)
31
- string = "module ::#{modname}; #{meths}\nend"
32
- eval(string)
33
- newmod = Object.const_get("::" + modname)
34
- self.extend(newmod)
35
- init = "init_#{name}"
36
- self.send(init) if self.respond_to? init
49
+ Dir.chdir("..") { find_file(name) }
37
50
  end
38
51
 
39
52
  end
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
data/lib/parser/string.rb CHANGED
@@ -5,14 +5,13 @@ class StringParser
5
5
  def initialize(line)
6
6
  raise NilValue if line.nil?
7
7
  raise ExpectedString unless String === line
8
- # raise NullString if line.empty?
9
8
  @line = line
10
9
  @len = @line.length
11
10
  @eos = @len == 0 ? true : false
12
11
  @i = 0
13
12
  end
14
13
 
15
- def next
14
+ def grab
16
15
  return nil if @eos
17
16
  char = @line[@i]
18
17
  @i += 1
@@ -20,6 +19,19 @@ class StringParser
20
19
  char
21
20
  end
22
21
 
22
+ def ungrab
23
+ @i -= 1 # FIXME what about eos...?
24
+ end
25
+
26
+ def next!
27
+ @line[@i + 1]
28
+ end
29
+
30
+ def prev
31
+ return nil if @i <= 0
32
+ @line[@i-1]
33
+ end
34
+
23
35
  def last?
24
36
  @i > @len - 1
25
37
  end
@@ -35,11 +47,14 @@ class StringParser
35
47
  end
36
48
 
37
49
  def skip_spaces
50
+ char = nil
38
51
  loop do
39
- break if peek != " "
52
+ char = peek
40
53
  break if eos?
41
- self.next
54
+ break if char != " "
55
+ grab
42
56
  end
57
+ char
43
58
  end
44
59
 
45
60
  end
data/lib/processor.rb CHANGED
@@ -45,7 +45,7 @@ class Livetext
45
45
  raise GenericError.new("Error: #{err}") if raise_error
46
46
  end
47
47
 
48
- def _disallowed?(name)
48
+ def disallowed?(name)
49
49
  Disallowed.include?(name.to_sym)
50
50
  end
51
51
 
@@ -71,8 +71,5 @@ class Livetext
71
71
  @sources.pop
72
72
  nil
73
73
  end
74
-
75
-
76
74
  end
77
-
78
75
  end