livetext 0.9.11 → 0.9.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (168) hide show
  1. checksums.yaml +4 -4
  2. data/README.lt3 +2 -2
  3. data/lib/cmdargs.rb +93 -0
  4. data/lib/errors.rb +15 -0
  5. data/lib/formatline.rb +59 -88
  6. data/lib/functions.rb +6 -2
  7. data/lib/handler/icanhaz.rb +35 -0
  8. data/lib/handler.rb +1 -0
  9. data/lib/helpers.rb +194 -0
  10. data/lib/html.rb +32 -0
  11. data/lib/livetext/importable.rb +2 -0
  12. data/lib/livetext.rb +35 -152
  13. data/lib/parser/file.rb +8 -0
  14. data/lib/parser/general.rb +38 -0
  15. data/lib/parser/import.rb +15 -0
  16. data/lib/parser/mixin.rb +38 -0
  17. data/lib/parser/set.rb +145 -0
  18. data/lib/parser/string.rb +70 -0
  19. data/lib/parser.rb +5 -0
  20. data/lib/processor.rb +23 -27
  21. data/lib/standard.rb +164 -346
  22. data/lib/userapi.rb +3 -5
  23. data/livetext.gemspec +1 -2
  24. data/plugin/bookish.rb +26 -22
  25. data/plugin/calibre.rb +1 -1
  26. data/plugin/livemagick.rb +10 -10
  27. data/plugin/markdown.rb +13 -11
  28. data/plugin/pyggish.rb +94 -84
  29. data/plugin/tutorial.rb +10 -5
  30. data/test/all.rb +3 -0
  31. data/test/snapshots/OMIT.txt +11 -0
  32. data/test/{data → snapshots}/basic_formatting/expected-error.txt +0 -0
  33. data/test/{data → snapshots}/basic_formatting/expected-output.txt +0 -0
  34. data/test/{data → snapshots}/basic_formatting/source.lt3 +0 -0
  35. data/test/{data → snapshots}/block_comment/expected-error.txt +0 -0
  36. data/test/{data → snapshots}/block_comment/expected-output.txt +0 -0
  37. data/test/{data → snapshots}/block_comment/source.lt3 +0 -0
  38. data/test/snapshots/clusion.txt +70 -0
  39. data/test/{data → snapshots}/comments_ignored_1/expected-error.txt +0 -0
  40. data/test/{data → snapshots}/comments_ignored_1/expected-output.txt +0 -0
  41. data/test/{data → snapshots}/comments_ignored_1/source.lt3 +0 -0
  42. data/test/{data → snapshots}/copy_is_raw/expected-error.txt +0 -0
  43. data/test/{data → snapshots}/copy_is_raw/expected-output.txt +0 -0
  44. data/test/{data → snapshots}/copy_is_raw/rawtext.inc +0 -0
  45. data/test/{data → snapshots}/copy_is_raw/source.lt3 +0 -0
  46. data/test/{data → snapshots}/crap +0 -0
  47. data/test/{data → snapshots}/def_method/expected-error.txt +0 -0
  48. data/test/{data → snapshots}/def_method/expected-output.txt +0 -0
  49. data/test/{data → snapshots}/def_method/source.lt3 +0 -0
  50. data/test/{data → snapshots}/error_inc_line_num/expected-output.txt +0 -0
  51. data/test/{data → snapshots}/error_inc_line_num/file2.lt3 +0 -0
  52. data/test/snapshots/error_inc_line_num/match-error.txt +1 -0
  53. data/test/{data → snapshots}/error_inc_line_num/source.lt3 +0 -0
  54. data/test/{data → snapshots}/error_invalid_name/expected-output.txt +0 -0
  55. data/test/snapshots/error_invalid_name/match-error.txt +1 -0
  56. data/test/{data → snapshots}/error_invalid_name/source.lt3 +0 -0
  57. data/test/{data → snapshots}/error_line_num/expected-output.txt +0 -0
  58. data/test/snapshots/error_line_num/match-error.txt +1 -0
  59. data/test/{data → snapshots}/error_line_num/source.lt3 +0 -0
  60. data/test/{data → snapshots}/error_mismatched_end/expected-output.txt +0 -2
  61. data/test/snapshots/error_mismatched_end/match-error.txt +1 -0
  62. data/test/{data → snapshots}/error_mismatched_end/source.lt3 +0 -0
  63. data/test/{data → snapshots}/error_missing_end/expected-output.txt +0 -0
  64. data/test/snapshots/error_missing_end/match-error.txt +1 -0
  65. data/test/{data → snapshots}/error_missing_end/source.lt3 +0 -0
  66. data/test/{data/error_no_such_mixin → snapshots/error_name_not_permitted}/expected-output.txt +0 -0
  67. data/test/snapshots/error_name_not_permitted/match-error.txt +1 -0
  68. data/test/{data → snapshots}/error_name_not_permitted/source.lt3 +0 -0
  69. data/test/{data → snapshots}/error_no_such_copy/expected-output.txt +0 -5
  70. data/test/snapshots/error_no_such_copy/match-error.txt +1 -0
  71. data/test/{data → snapshots}/error_no_such_copy/source.lt3 +0 -1
  72. data/test/{data → snapshots}/error_no_such_inc/expected-output.txt +0 -4
  73. data/test/snapshots/error_no_such_inc/match-error.txt +1 -0
  74. data/test/{data → snapshots}/error_no_such_inc/source.lt3 +0 -0
  75. data/test/snapshots/error_no_such_mixin/expected-output.txt +5 -0
  76. data/test/snapshots/error_no_such_mixin/match-error.txt +1 -0
  77. data/test/{data → snapshots}/error_no_such_mixin/source.lt3 +0 -0
  78. data/test/{data → snapshots}/example_alpha/expected-error.txt +0 -0
  79. data/test/{data → snapshots}/example_alpha/expected-output.txt +0 -0
  80. data/test/{data → snapshots}/example_alpha/source.lt3 +0 -0
  81. data/test/{data → snapshots}/example_alpha2/expected-error.txt +0 -0
  82. data/test/{data → snapshots}/example_alpha2/expected-output.txt +0 -0
  83. data/test/{data → snapshots}/example_alpha2/source.lt3 +0 -0
  84. data/test/{data → snapshots}/fixit +0 -0
  85. data/test/{data → snapshots}/functions/expected-error.txt +0 -0
  86. data/test/{data → snapshots}/functions/expected-output.txt +0 -0
  87. data/test/{data → snapshots}/functions/source.lt3 +0 -0
  88. data/test/{data → snapshots}/hello_world/expected-error.txt +0 -0
  89. data/test/{data → snapshots}/hello_world/expected-output.txt +0 -0
  90. data/test/{data → snapshots}/hello_world/source.lt3 +0 -0
  91. data/test/snapshots/icanhaz/expected-output.txt +5 -0
  92. data/test/snapshots/icanhaz/match-error.txt +1 -0
  93. data/test/snapshots/icanhaz/simple_import.rb +5 -0
  94. data/test/snapshots/icanhaz/source.lt3 +10 -0
  95. data/test/{data/more_complex_vars → snapshots/icanhaz2}/expected-error.txt +0 -0
  96. data/test/snapshots/icanhaz2/expected-output.txt +6 -0
  97. data/test/snapshots/icanhaz2/simple_canhaz.rb +5 -0
  98. data/test/snapshots/icanhaz2/source.lt3 +6 -0
  99. data/test/{data/predef_vars → snapshots/more_complex_vars}/expected-error.txt +0 -0
  100. data/test/{data → snapshots}/more_complex_vars/expected-output.txt +0 -0
  101. data/test/{data → snapshots}/more_complex_vars/source.lt3 +0 -0
  102. data/test/{data/raw_lines → snapshots/predef_vars}/expected-error.txt +0 -0
  103. data/test/snapshots/predef_vars/match-output.txt +6 -0
  104. data/test/{data → snapshots}/predef_vars/source.lt3 +0 -0
  105. data/test/{data/raw_text_block → snapshots/raw_lines}/expected-error.txt +0 -0
  106. data/test/{data → snapshots}/raw_lines/expected-output.txt +0 -0
  107. data/test/{data → snapshots}/raw_lines/source.lt3 +0 -0
  108. data/test/{data/simple_copy → snapshots/raw_text_block}/expected-error.txt +0 -0
  109. data/test/{data → snapshots}/raw_text_block/expected-output.txt +0 -0
  110. data/test/{data → snapshots}/raw_text_block/rawtext.inc +0 -0
  111. data/test/{data → snapshots}/raw_text_block/source.lt3 +0 -0
  112. data/test/{data/simple_include → snapshots/simple_copy}/expected-error.txt +0 -0
  113. data/test/{data → snapshots}/simple_copy/expected-output.txt +0 -0
  114. data/test/{data → snapshots}/simple_copy/simplefile.inc +0 -0
  115. data/test/{data → snapshots}/simple_copy/source.lt3 +0 -0
  116. data/test/{data/simple_mixin → snapshots/simple_import}/expected-error.txt +0 -0
  117. data/test/snapshots/simple_import/expected-output.txt +7 -0
  118. data/test/snapshots/simple_import/simple_import.rb +5 -0
  119. data/test/snapshots/simple_import/source.lt3 +7 -0
  120. data/test/{data/simple_vars → snapshots/simple_include}/expected-error.txt +0 -0
  121. data/test/{data → snapshots}/simple_include/expected-output.txt +0 -0
  122. data/test/{data → snapshots}/simple_include/simplefile.inc +0 -0
  123. data/test/{data → snapshots}/simple_include/source.lt3 +0 -1
  124. data/test/{data/single_raw_line → snapshots/simple_mixin}/expected-error.txt +0 -0
  125. data/test/{data → snapshots}/simple_mixin/expected-output.txt +0 -0
  126. data/test/{data → snapshots}/simple_mixin/simple_mixin.rb +0 -0
  127. data/test/{data → snapshots}/simple_mixin/source.lt3 +0 -0
  128. data/test/{data/table_with_heredocs → snapshots/simple_vars}/expected-error.txt +0 -0
  129. data/test/{data → snapshots}/simple_vars/expected-output.txt +0 -0
  130. data/test/{data → snapshots}/simple_vars/source.lt3 +0 -0
  131. data/test/{data/subset.txt → snapshots/single_raw_line/expected-error.txt} +0 -0
  132. data/test/{data → snapshots}/single_raw_line/expected-output.txt +0 -0
  133. data/test/{data → snapshots}/single_raw_line/source.lt3 +0 -0
  134. data/test/snapshots/subset.txt +0 -0
  135. data/test/snapshots/table_with_heredocs/expected-error.txt +0 -0
  136. data/test/{data → snapshots}/table_with_heredocs/expected-output.txt +0 -0
  137. data/test/{data → snapshots}/table_with_heredocs/source.lt3 +0 -0
  138. data/test/snapshots.rb +177 -0
  139. data/test/testlines.rb +2 -2
  140. data/test/unit/all.rb +4 -0
  141. data/test/unit/formatline.rb +650 -0
  142. data/test/unit/html.rb +38 -0
  143. data/test/unit/parser/all.rb +3 -0
  144. data/test/unit/parser/general.rb +59 -0
  145. data/test/unit/parser/importable.rb +19 -0
  146. data/test/unit/parser/mixin.rb +19 -0
  147. data/test/unit/parser/set.rb +164 -0
  148. data/test/unit/parser/string.rb +130 -0
  149. data/test/unit/parser.rb +6 -0
  150. data/test/unit/standard.rb +23 -0
  151. data/test/unit/stringparser.rb +140 -0
  152. metadata +137 -100
  153. data/test/data/error_inc_line_num/FOO +0 -21
  154. data/test/data/error_inc_line_num/expected-err-line1match.txt +0 -1
  155. data/test/data/error_invalid_name/expected-err-line1match.txt +0 -1
  156. data/test/data/error_line_num/expected-err-line1match.txt +0 -1
  157. data/test/data/error_mismatched_end/expected-err-line1match.txt +0 -1
  158. data/test/data/error_missing_end/ERR +0 -32
  159. data/test/data/error_missing_end/expected-err-line1match.txt +0 -1
  160. data/test/data/error_name_not_permitted/expected-error.txt +0 -1
  161. data/test/data/error_name_not_permitted/expected-output.txt +0 -4
  162. data/test/data/error_no_such_copy/expected-err-line1match.txt +0 -1
  163. data/test/data/error_no_such_inc/expected-err-line1match.txt +0 -1
  164. data/test/data/error_no_such_mixin/expected-err-line1match.txt +0 -1
  165. data/test/data/lines.txt +0 -124
  166. data/test/data/predef_vars/expected-output.txt +0 -6
  167. data/test/formatting.rb +0 -110
  168. data/test/test.rb +0 -140
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2f49173986fc8a17fc77f35032e823f4818d404007d5aacd2d3d5a4a74f19e02
4
- data.tar.gz: 61c0eab54d60c23abe0c27a6b8adc16f621e35c347253b557f07ffc80b31f80e
3
+ metadata.gz: d027612469e45b953a3e8589ebbedf1f746f87f50c4a90b502f4daac56d28605
4
+ data.tar.gz: b811285f434d3b2760e201eb403f864ba31cb12e31f21105fc8c4fe5e3b743a2
5
5
  SHA512:
6
- metadata.gz: '07389bbd1154d200f6f56b0373c0459bf140baeefa370d789224f2dedd53fe5120f0f7116e2c9d1381ff07a48f945786bb8e5f3478ac9002aea0f9443f61f579'
7
- data.tar.gz: 12829e57528407a55f842f8ad8de77b47396cb6fffb22d76feaf8d98d644ebf00fc50d447a24f453026980a7cb7631443e11f9f7d67121ce9529d583ef85e513
6
+ metadata.gz: 1e1b08d7d900ae551d7777576a7284d776422d2039813a764c3d9d9b0495ac14eec4e53225e1e0f3b97a1a548377f14b861e72d4b24d2a52055cd0f75404d2bf
7
+ data.tar.gz: 025055edd14e392750b482f4b0a9a973f213b24a5991bb9c7e9939c225a21bfe77398cc118983599a0fd1ccf1c1aa4c8bbf62874745a2cf5257410b747db72ee
data/README.lt3 CHANGED
@@ -1,5 +1,5 @@
1
- .mixin tutorial
2
- .mixin markdown
1
+ .icanhaz tutorial
2
+ .icanhaz markdown
3
3
 
4
4
  . copy basic.css
5
5
 
data/lib/cmdargs.rb ADDED
@@ -0,0 +1,93 @@
1
+ require_relative 'livetext'
2
+
3
+ =begin
4
+ Weird concepts to understand here...
5
+
6
+ 1. A Livetext dot-command (flush left) usually looks like:
7
+ .foobar
8
+ 2. A dot-command (left-indented) usually looks like:
9
+ $.foobar
10
+ 3. More generally, it may have any number of parameters (0, 1, ...)
11
+ .redirect somefile.txt append
12
+ 4. Variables and functions *can* appear (rare in practice??)
13
+ .redirect somefile$my_suffix $$my_mode
14
+ 5. A trailing # comment may appear
15
+ a. Stripped... saved in #raw ? #data ? #comment ? elsewhere?
16
+ b. NOT the "dot" as a comment!
17
+ 6. .foobar # This here is a comment
18
+ 7. #data accessor returns all data on the .foo line...
19
+ a. ...After the initial space
20
+ b. ...Including spaces
21
+ c. Including comment??
22
+ d. .foo This is o n l y a test.
23
+ # #data returns: "This is o n l y a test."
24
+ e. What about formatting???
25
+ f. What about: comments? variables? functions?
26
+
27
+ 7. Some commands have NO body while others have an OPTIONAL or REQUIRED body
28
+ a. Assume .cmd1 definition forbids a body (then a body is an error)
29
+ .cmd1 # may NOT have a body
30
+ b. Assume .cmd2 definition PERMITS a body
31
+ .cmd2 # may or MAY NOT have body/.end
32
+ c. Assume .cmd3 definition PERMITS a body
33
+ .cmd3 # REQUIRES a body/.end
34
+ . stuff...
35
+ .end
36
+ 8. Inside a body:
37
+ 8a. Leading dot has no special meaning (though the associated method may parse it!)
38
+ 8b. BUG? Currently leading dot is a comment INSIDE a body?
39
+ 8a. No leading char is special (though the associated method may parse it!)
40
+ 8a. No trailing #-comments (though the associated method may parse it!)
41
+ 8c. ?? We should or shouldn't look for variables/functions? or make it an option?
42
+ 8d. .end may naturally not be used (but see .raw where it may)
43
+ 9. the args accessor is a simple array of strings
44
+
45
+
46
+ =end
47
+
48
+ class Livetext::CmdData
49
+
50
+ attr_reader :data, :args, :nargs, :arity, :comment, :raw # , ...?
51
+
52
+ def initialize(data, body: false, arity: :N) # FIXME maybe just add **options ??
53
+ # arity: (num) fixed number 0 or more
54
+ # :N arbitrary number
55
+ # n1..n2 range
56
+ # body: true => this command has a body + .end
57
+ # how raw is raw?
58
+ # remove comment - always/sometimes/never?
59
+ # var_func_parse - always/sometimes/never?
60
+ # var_func_parse inside body??
61
+ @data = data.dup # comment? vars? funcs?
62
+ @raw = data.dup # comment? vars? funcs?
63
+ @args = data.split # simple array
64
+ @nargs = nargs # not really "needed"
65
+ check_num_args(nargs)
66
+
67
+ # @varfunc = _var_func_parse(data.dup)
68
+ end
69
+
70
+ def check_num_args(num)
71
+ num_range = /(\d{0,2})(\.\.)(\d{0,2})/
72
+ min, max = 0, 9999
73
+ md = num_range.match(@nargs).to_a
74
+ bad_args = nil
75
+ case
76
+ when @nargs == ":N" # arbitrary
77
+ # max already set
78
+ when md[2] == ".." # range: 4..6 1.. ..4
79
+ vmin, vmax = md.values_at(1, 2)
80
+ min = Integer(vmin) unless vmin.empty?
81
+ max = Integer(vmax) unless vmax.empty?
82
+ min, max = Integer(min), Integer(max)
83
+ when %r[^\d+$] =~ num
84
+ min = max = Integer(num) # can raise error
85
+ else
86
+ raise "Invalid value or range '#{num.inspect}'"
87
+ end
88
+
89
+ bad_args = @args.size.between?(min, max)
90
+ raise "Expected #{num} args but found #{@args.size}!" if bad_args
91
+ end
92
+
93
+ end
data/lib/errors.rb ADDED
@@ -0,0 +1,15 @@
1
+
2
+ # More later?
3
+
4
+ def make_exception(sym, str, target_class = Object)
5
+ return if target_class.constants.include?(sym)
6
+ klass = sym # :"#{sym}_Class"
7
+ target_class.const_set(klass, StandardError.dup)
8
+ define_method(sym) do |*args|
9
+ args = [] unless args.first
10
+ msg = str.dup
11
+ args.each.with_index {|arg, i| msg.sub!("%#{i+1}", arg) }
12
+ target_class.class_eval(klass.to_s).new(msg)
13
+ end
14
+ end
15
+
data/lib/formatline.rb CHANGED
@@ -1,4 +1,7 @@
1
- class FormatLine
1
+ # Class FormatLine handles the parsing of comments, dot commands, and
2
+ # simple formatting characters.
3
+
4
+ class FormatLine < StringParser
2
5
  SimpleFormats = {}
3
6
  SimpleFormats[:b] = %w[<b> </b>]
4
7
  SimpleFormats[:i] = %w[<i> </i>]
@@ -21,20 +24,11 @@ class FormatLine
21
24
 
22
25
  Syms = { "*" => :b, "_" => :i, "`" => :t, "~" => :s }
23
26
 
24
- def terminate?(terminators, ch)
25
- if terminators.is_a? Regexp
26
- terminators === ch
27
- else
28
- terminators.include?(ch)
29
- end
30
- end
31
-
32
27
  attr_reader :out
33
28
  attr_reader :tokenlist
34
29
 
35
30
  def initialize(line)
36
- @line = line
37
- @i = -1
31
+ super
38
32
  @token = Null.dup
39
33
  @tokenlist = []
40
34
  end
@@ -42,26 +36,27 @@ class FormatLine
42
36
  def self.parse!(line)
43
37
  return nil if line.nil?
44
38
  x = self.new(line.chomp)
45
- t = x.tokenize(line)
39
+ t = x.tokenize
40
+ # TTY.puts "tokens = \n#{t.inspect}\n "
46
41
  x.evaluate
47
42
  end
48
43
 
49
- def tokenize(line)
50
- grab
44
+ def tokenize
45
+ # add grab
51
46
  loop do
52
- case curr
53
- when Escape; grab; add curr; grab; add curr
47
+ case peek
48
+ when Escape; grab; add peek; grab; add peek
54
49
  when "$"
55
50
  dollar
56
51
  when "*", "_", "`", "~"
57
- marker curr
58
- add curr
52
+ marker peek
53
+ add peek
59
54
  when LF
60
55
  break if @i >= line.size - 1
61
56
  when nil
62
57
  break
63
58
  else
64
- add curr
59
+ add peek
65
60
  end
66
61
  grab
67
62
  end
@@ -69,24 +64,33 @@ class FormatLine
69
64
  @tokenlist
70
65
  end
71
66
 
67
+ def terminate?(terminators, ch)
68
+ if terminators.is_a? Regexp
69
+ terminators === ch
70
+ else
71
+ terminators.include?(ch)
72
+ end
73
+ end
74
+
72
75
  def self.var_func_parse(str)
73
76
  return nil if str.nil?
74
77
  x = self.new(str.chomp)
75
- x.grab
76
- loop do
77
- case x.curr
78
- when Escape; x.grab; x.add x.curr; x.grab
79
- when "$"
80
- x.dollar
81
- when LF, nil
82
- break
83
- else
84
- x.add x.curr
85
- end
86
- x.grab
78
+ char = x.peek
79
+ loop do
80
+ char = x.grab
81
+ break if char == LF || char == nil
82
+ x.handle_escaping if char == Escape
83
+ x.dollar if char == "$"
84
+ x.add char
87
85
  end
88
86
  x.add_token(:str)
89
- x.evaluate
87
+ result = x.evaluate
88
+ result
89
+ end
90
+
91
+ def handle_escaping
92
+ grab
93
+ add grab
90
94
  end
91
95
 
92
96
  def embed(sym, str)
@@ -127,27 +131,6 @@ class FormatLine
127
131
  @out
128
132
  end
129
133
 
130
- def curr
131
- @line[@i]
132
- end
133
-
134
- def prev
135
- return nil if @i <= 0
136
- @line[@i-1]
137
- end
138
-
139
- def next!
140
- @line[@i+1]
141
- end
142
-
143
- def grab
144
- @line[@i+=1]
145
- end
146
-
147
- def ungrab
148
- @line[@i-=1]
149
- end
150
-
151
134
  def grab_colon_param
152
135
  grab # grab :
153
136
  param = ""
@@ -184,7 +167,7 @@ class FormatLine
184
167
  end
185
168
  end
186
169
 
187
- add curr
170
+ add peek
188
171
  grab
189
172
  param = nil if param.empty?
190
173
  param
@@ -204,8 +187,8 @@ class FormatLine
204
187
  str = Null.dup
205
188
  grab
206
189
  loop do
207
- break if curr.nil?
208
- str << curr
190
+ break if eos?
191
+ str << peek
209
192
  break if terminate?(NoAlpha, next!)
210
193
  grab
211
194
  end
@@ -216,8 +199,8 @@ class FormatLine
216
199
  str = Null.dup
217
200
  grab
218
201
  loop do
219
- break if curr.nil?
220
- str << curr
202
+ break if eos? # peek.nil?
203
+ str << peek
221
204
  break if terminate?(NoAlphaDot, next!)
222
205
  grab
223
206
  end
@@ -226,7 +209,7 @@ class FormatLine
226
209
 
227
210
  def dollar
228
211
  grab
229
- case curr
212
+ case peek
230
213
  when LF; add "$"; add_token :str
231
214
  when " "; add "$ "; add_token :str
232
215
  when nil; add "$"; add_token :str
@@ -234,10 +217,10 @@ class FormatLine
234
217
  # when "."; dollar_dot
235
218
  when /[A-Za-z]/
236
219
  add_token :str
237
- var = curr + grab_alpha_dot
220
+ var = peek + grab_alpha_dot
238
221
  add_token(:var, var)
239
222
  else
240
- add "$" + curr
223
+ add "$" + peek
241
224
  add_token(:string)
242
225
  end
243
226
  end
@@ -255,7 +238,7 @@ class FormatLine
255
238
  when "["; param = grab_func_param; add_token(:brackets, param)
256
239
  end
257
240
  else
258
- grab; add_token :str, "$$" + curr; return
241
+ grab; add_token :str, "$$" + peek; return
259
242
  end
260
243
  end
261
244
 
@@ -272,7 +255,7 @@ class FormatLine
272
255
  end
273
256
 
274
257
  grab
275
- case curr
258
+ case peek
276
259
  when Space
277
260
  add char + " "
278
261
  add_token :str
@@ -283,7 +266,7 @@ class FormatLine
283
266
  when char; double_marker(char)
284
267
  when LBrack; long_marker(char)
285
268
  else
286
- str = curr + collect!(sym, Blank)
269
+ str = peek + collect!(sym, Blank)
287
270
  add str
288
271
  add_token sym, str
289
272
  grab
@@ -316,21 +299,19 @@ class FormatLine
316
299
  str = Null.dup # next is not " ","*","["
317
300
  grab # ZZZ
318
301
  loop do
319
- if curr == Escape
320
- str << grab # ch = escaped char
302
+ if peek == Escape
321
303
  grab
304
+ str << grab
322
305
  next
323
306
  end
324
- if terminate?(terminators, curr)
307
+ if terminate?(terminators, peek)
325
308
  break
326
309
  end
327
- # STDERR.puts "#{curr.inspect} is not a terminator"
328
- str << curr # not a terminator
310
+ str << peek # not a terminator
329
311
  grab
330
- # STDERR.puts "After grab, curr is #{curr.inspect}"
331
312
  end
332
313
 
333
- if curr == "]" # skip right bracket
314
+ if peek == "]" # skip right bracket
334
315
  grab
335
316
  end
336
317
  add str
@@ -341,8 +322,8 @@ class FormatLine
341
322
  end
342
323
 
343
324
  def escaped
344
- ch = grab
345
325
  grab
326
+ ch = grab
346
327
  ch
347
328
  end
348
329
 
@@ -353,15 +334,15 @@ class FormatLine
353
334
  grab # ZZZ
354
335
  loop do
355
336
  case
356
- when curr.nil?
337
+ when peek.nil?
357
338
  return str
358
- when curr == Escape
339
+ when peek == Escape
359
340
  str << escaped
360
341
  next
361
- when terminate?(terminators, curr)
342
+ when terminate?(terminators, peek)
362
343
  break
363
344
  else
364
- str << curr # not a terminator
345
+ str << peek # not a terminator
365
346
  end
366
347
  grab
367
348
  end
@@ -373,17 +354,14 @@ class FormatLine
373
354
  STDERR.puts "=== str = #{str.inspect}"
374
355
  end
375
356
 
376
- ############
377
-
378
- ### From FormatLine:
379
-
380
357
  def funcall(name, param)
358
+ err = "[Error evaluating $$#{name}(#{param})]"
381
359
  result =
382
360
  if self.respond_to?("func_" + name.to_s)
383
361
  self.send("func_" + name.to_s, param)
384
362
  else
385
363
  fobj = ::Livetext::Functions.new
386
- fobj.send(name, param)
364
+ fobj.send(name, param) rescue err
387
365
  end
388
366
  result
389
367
  end
@@ -393,13 +371,6 @@ class FormatLine
393
371
  result
394
372
  end
395
373
 
396
- #####
397
-
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
374
  def embedded?
404
375
  ! (['"', "'", " ", nil].include? prev)
405
376
  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 umm, why is this necessary??
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
@@ -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 ADDED
@@ -0,0 +1,194 @@
1
+
2
+ module Helpers
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
+
113
+ def check_disallowed(name)
114
+ raise DisallowedName(name) if disallowed?(name)
115
+ end
116
+
117
+ def check_file_exists(file)
118
+ raise FileNotFound(file) unless File.exist?(file)
119
+ end
120
+
121
+ def set_variables(pairs)
122
+ pairs.each do |pair|
123
+ var, value = *pair
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
168
+ end
169
+ end
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
+
194
+ end