amp-front 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. data/.document +5 -0
  2. data/.gitignore +24 -0
  3. data/Ampfile +3 -0
  4. data/Gemfile +10 -0
  5. data/Gemfile.lock +36 -0
  6. data/LICENSE +20 -0
  7. data/README.md +50 -0
  8. data/Rakefile +64 -0
  9. data/VERSION +1 -0
  10. data/design_docs/commands.md +91 -0
  11. data/design_docs/dependencies.md +35 -0
  12. data/design_docs/plugins.md +47 -0
  13. data/features/amp.feature +8 -0
  14. data/features/amp_help.feature +36 -0
  15. data/features/amp_plugin_list.feature +10 -0
  16. data/features/step_definitions/amp-front_steps.rb +23 -0
  17. data/features/support/env.rb +4 -0
  18. data/lib/amp-front.rb +30 -0
  19. data/lib/amp-front/dispatch/commands/base.rb +158 -0
  20. data/lib/amp-front/dispatch/commands/builtin/help.rb +23 -0
  21. data/lib/amp-front/dispatch/commands/builtin/plugin.rb +24 -0
  22. data/lib/amp-front/dispatch/commands/validations.rb +171 -0
  23. data/lib/amp-front/dispatch/runner.rb +86 -0
  24. data/lib/amp-front/help/entries/__default__.erb +31 -0
  25. data/lib/amp-front/help/entries/ampfiles.md +42 -0
  26. data/lib/amp-front/help/entries/commands.erb +6 -0
  27. data/lib/amp-front/help/entries/new-commands.md +81 -0
  28. data/lib/amp-front/help/help.rb +312 -0
  29. data/lib/amp-front/plugins/base.rb +87 -0
  30. data/lib/amp-front/support/module_extensions.rb +92 -0
  31. data/lib/amp-front/third_party/maruku.rb +136 -0
  32. data/lib/amp-front/third_party/maruku/attributes.rb +227 -0
  33. data/lib/amp-front/third_party/maruku/defaults.rb +71 -0
  34. data/lib/amp-front/third_party/maruku/errors_management.rb +92 -0
  35. data/lib/amp-front/third_party/maruku/helpers.rb +260 -0
  36. data/lib/amp-front/third_party/maruku/input/charsource.rb +326 -0
  37. data/lib/amp-front/third_party/maruku/input/extensions.rb +69 -0
  38. data/lib/amp-front/third_party/maruku/input/html_helper.rb +189 -0
  39. data/lib/amp-front/third_party/maruku/input/linesource.rb +111 -0
  40. data/lib/amp-front/third_party/maruku/input/parse_block.rb +615 -0
  41. data/lib/amp-front/third_party/maruku/input/parse_doc.rb +234 -0
  42. data/lib/amp-front/third_party/maruku/input/parse_span_better.rb +746 -0
  43. data/lib/amp-front/third_party/maruku/input/rubypants.rb +225 -0
  44. data/lib/amp-front/third_party/maruku/input/type_detection.rb +147 -0
  45. data/lib/amp-front/third_party/maruku/input_textile2/t2_parser.rb +163 -0
  46. data/lib/amp-front/third_party/maruku/maruku.rb +33 -0
  47. data/lib/amp-front/third_party/maruku/output/to_ansi.rb +223 -0
  48. data/lib/amp-front/third_party/maruku/output/to_html.rb +991 -0
  49. data/lib/amp-front/third_party/maruku/output/to_markdown.rb +164 -0
  50. data/lib/amp-front/third_party/maruku/output/to_s.rb +56 -0
  51. data/lib/amp-front/third_party/maruku/string_utils.rb +191 -0
  52. data/lib/amp-front/third_party/maruku/structures.rb +167 -0
  53. data/lib/amp-front/third_party/maruku/structures_inspect.rb +87 -0
  54. data/lib/amp-front/third_party/maruku/structures_iterators.rb +61 -0
  55. data/lib/amp-front/third_party/maruku/textile2.rb +1 -0
  56. data/lib/amp-front/third_party/maruku/toc.rb +199 -0
  57. data/lib/amp-front/third_party/maruku/usage/example1.rb +33 -0
  58. data/lib/amp-front/third_party/maruku/version.rb +40 -0
  59. data/lib/amp-front/third_party/trollop.rb +766 -0
  60. data/spec/amp-front_spec.rb +25 -0
  61. data/spec/command_specs/base_spec.rb +123 -0
  62. data/spec/command_specs/command_spec.rb +97 -0
  63. data/spec/command_specs/help_spec.rb +33 -0
  64. data/spec/command_specs/spec_helper.rb +37 -0
  65. data/spec/command_specs/validations_spec.rb +267 -0
  66. data/spec/dispatch_specs/runner_spec.rb +116 -0
  67. data/spec/dispatch_specs/spec_helper.rb +15 -0
  68. data/spec/help_specs/help_entry_spec.rb +78 -0
  69. data/spec/help_specs/help_registry_spec.rb +77 -0
  70. data/spec/help_specs/spec_helper.rb +15 -0
  71. data/spec/plugin_specs/base_spec.rb +36 -0
  72. data/spec/plugin_specs/spec_helper.rb +15 -0
  73. data/spec/spec.opts +1 -0
  74. data/spec/spec_helper.rb +33 -0
  75. data/spec/support_specs/module_extensions_spec.rb +104 -0
  76. data/spec/support_specs/spec_helper.rb +15 -0
  77. data/test/third_party_tests/test_trollop.rb +1181 -0
  78. metadata +192 -0
@@ -0,0 +1,71 @@
1
+ #--
2
+ # Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
3
+ #
4
+ # This file is part of Maruku.
5
+ #
6
+ # Maruku is free software; you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation; either version 2 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # Maruku is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Maruku; if not, write to the Free Software
18
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
+ #++
20
+
21
+
22
+ module MaRuKu
23
+
24
+ Globals = {
25
+ :unsafe_features => false,
26
+ :on_error => :warning,
27
+
28
+
29
+ :use_numbered_headers => false,
30
+
31
+ :maruku_signature => false,
32
+ :code_background_color => '#fef',
33
+ :code_show_spaces => false,
34
+
35
+ :filter_html => false,
36
+
37
+ :html_math_output_mathml => true, # also set :html_math_engine
38
+ :html_math_engine => 'none', #ritex, itex2mml
39
+
40
+ :html_math_output_png => false,
41
+ :html_png_engine => 'none',
42
+ :html_png_dir => 'pngs',
43
+ :html_png_url => 'pngs/',
44
+ :html_png_resolution => 200,
45
+
46
+ :html_use_syntax => false,
47
+
48
+ :latex_use_listings => false,
49
+ :latex_cjk => false,
50
+ :latex_cache_file => "blahtex_cache.pstore", # cache file for blahtex filter
51
+
52
+ :debug_keep_ials => false,
53
+ :doc_prefix => ''
54
+ }
55
+
56
+ class MDElement
57
+ def get_setting(sym)
58
+ if self.attributes.has_key?(sym) then
59
+ return self.attributes[sym]
60
+ elsif self.doc && self.doc.attributes.has_key?(sym) then
61
+ return self.doc.attributes[sym]
62
+ elsif MaRuKu::Globals.has_key?(sym)
63
+ return MaRuKu::Globals[sym]
64
+ else
65
+ $stderr.puts "Bug: no default for #{sym.inspect}"
66
+ nil
67
+ end
68
+ end
69
+ end
70
+
71
+ end
@@ -0,0 +1,92 @@
1
+ #--
2
+ # Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
3
+ #
4
+ # This file is part of Maruku.
5
+ #
6
+ # Maruku is free software; you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation; either version 2 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # Maruku is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Maruku; if not, write to the Free Software
18
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
+ #++
20
+
21
+
22
+
23
+ #m Any method that detects formatting error calls the
24
+ #m maruku_error() method.
25
+ #m if @meta[:on_error] ==
26
+ #m
27
+ #m - :warning write on the standard err (or @error_stream if defined),
28
+ #m then do your best.
29
+ #m - :ignore be shy and try to continue
30
+ #m - :raise raises a MarukuException
31
+ #m
32
+ #m default is :raise
33
+
34
+ module MaRuKu
35
+
36
+ class Exception < RuntimeError
37
+ end
38
+
39
+ module Errors
40
+
41
+ def maruku_error(s,src=nil,con=nil)
42
+ policy = get_setting(:on_error)
43
+
44
+ case policy
45
+ when :ignore
46
+ when :raise
47
+ raise_error create_frame(describe_error(s,src,con))
48
+ when :warning
49
+ tell_user create_frame(describe_error(s,src,con))
50
+ else
51
+ raise "BugBug: policy = #{policy.inspect}"
52
+ end
53
+ end
54
+
55
+ def maruku_recover(s,src=nil,con=nil)
56
+ tell_user create_frame(describe_error(s,src,con))
57
+ end
58
+
59
+ alias error maruku_error
60
+
61
+ def raise_error(s)
62
+ raise MaRuKu::Exception, s, caller
63
+ end
64
+
65
+ def tell_user(s)
66
+ error_stream = self.attributes[:error_stream] || $stderr
67
+ error_stream << s
68
+ end
69
+
70
+ def create_frame(s)
71
+ n = 75
72
+ "\n" +
73
+ " "+"_"*n + "\n"+
74
+ "| Maruku tells you:\n" +
75
+ "+" + ("-"*n) +"\n"+
76
+ add_tabs(s,1,'| ') + "\n" +
77
+ "+" + ("-"*n) + "\n" +
78
+ add_tabs(caller[0, 5].join("\n"),1,'!') + "\n" +
79
+ "\\" + ("_"*n) + "\n"
80
+ end
81
+
82
+ def describe_error(s,src,con)
83
+ t = s
84
+ src && (t += "\n#{src.describe}\n")
85
+ con && (t += "\n#{con.describe}\n")
86
+ t
87
+ end
88
+
89
+ end # Errors
90
+ end # MaRuKu
91
+
92
+
@@ -0,0 +1,260 @@
1
+ #--
2
+ # Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
3
+ #
4
+ # This file is part of Maruku.
5
+ #
6
+ # Maruku is free software; you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation; either version 2 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # Maruku is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Maruku; if not, write to the Free Software
18
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
+ #++
20
+
21
+
22
+
23
+
24
+ # A series of helper functions for creating elements: they hide the
25
+ # particular internal representation.
26
+ #
27
+ # Please, always use these instead of creating MDElement.
28
+ #
29
+
30
+ module MaRuKu
31
+ module Helpers
32
+
33
+ # if the first is a md_ial, it is used as such
34
+ def md_el(node_type, children=[], meta={}, al=nil)
35
+ if (e=children.first).kind_of?(MDElement) and
36
+ e.node_type == :ial then
37
+ if al
38
+ al += e.ial
39
+ else
40
+ al = e.ial
41
+ end
42
+ children.shift
43
+ end
44
+ e = MDElement.new(node_type, children, meta, al)
45
+ e.doc = @doc
46
+ return e
47
+ end
48
+
49
+ def md_header(level, children, al=nil)
50
+ md_el(:header, children, {:level => level}, al)
51
+ end
52
+
53
+ # Inline code
54
+ def md_code(code, al=nil)
55
+ md_el(:inline_code, [], {:raw_code => code}, al)
56
+ end
57
+
58
+ # Code block
59
+ def md_codeblock(source, al=nil)
60
+ md_el(:code, [], {:raw_code => source}, al)
61
+ end
62
+
63
+ def md_quote(children, al=nil)
64
+ md_el(:quote, children, {}, al)
65
+ end
66
+
67
+ def md_li(children, want_my_par, al=nil)
68
+ md_el(:li, children, {:want_my_paragraph=>want_my_par}, al)
69
+ end
70
+
71
+ def md_footnote(footnote_id, children, al=nil)
72
+ md_el(:footnote, children, {:footnote_id=>footnote_id}, al)
73
+ end
74
+
75
+ def md_abbr_def(abbr, text, al=nil)
76
+ md_el(:abbr_def, [], {:abbr=>abbr, :text=>text}, al)
77
+ end
78
+
79
+ def md_abbr(abbr, title)
80
+ md_el(:abbr, [abbr], {:title=>title})
81
+ end
82
+
83
+ def md_html(raw_html, al=nil)
84
+ e = md_el(:raw_html, [], {:raw_html=>raw_html})
85
+ begin
86
+ # remove newlines and whitespace at begin
87
+ # end end of string, or else REXML gets confused
88
+ raw_html = raw_html.gsub(/\A\s*</,'<').
89
+ gsub(/>[\s\n]*\Z/,'>')
90
+
91
+ raw_html = "<marukuwrap>#{raw_html}</marukuwrap>"
92
+ e.instance_variable_set :@parsed_html,
93
+ REXML::Document.new(raw_html)
94
+ rescue REXML::ParseException => ex
95
+ e.instance_variable_set :@parsed_html, nil
96
+ maruku_recover "REXML cannot parse this block of HTML/XML:\n"+
97
+ add_tabs(raw_html,1,'|') + "\n"+ex.inspect
98
+ # " #{raw_html.inspect}\n\n"+ex.inspect
99
+ end
100
+ e
101
+ end
102
+
103
+ def md_link(children, ref_id, al=nil)
104
+ md_el(:link, children, {:ref_id=>ref_id.downcase}, al)
105
+ end
106
+
107
+ def md_im_link(children, url, title=nil, al=nil)
108
+ md_el(:im_link, children, {:url=>url,:title=>title}, al)
109
+ end
110
+
111
+ def md_image(children, ref_id, al=nil)
112
+ md_el(:image, children, {:ref_id=>ref_id}, al)
113
+ end
114
+
115
+ def md_im_image(children, url, title=nil, al=nil)
116
+ md_el(:im_image, children, {:url=>url,:title=>title},al)
117
+ end
118
+
119
+ def md_em(children, al=nil)
120
+ md_el(:emphasis, [children].flatten, {}, al)
121
+ end
122
+
123
+ def md_br()
124
+ md_el(:linebreak, [], {}, nil)
125
+ end
126
+
127
+ def md_hrule()
128
+ md_el(:hrule, [], {}, nil)
129
+ end
130
+
131
+ def md_strong(children, al=nil)
132
+ md_el(:strong, [children].flatten, {}, al)
133
+ end
134
+
135
+ def md_emstrong(children, al=nil)
136
+ md_strong(md_em(children), al)
137
+ end
138
+
139
+ # <http://www.example.com/>
140
+ def md_url(url, al=nil)
141
+ md_el(:immediate_link, [], {:url=>url}, al)
142
+ end
143
+
144
+ # <andrea@rubyforge.org>
145
+ # <mailto:andrea@rubyforge.org>
146
+ def md_email(email, al=nil)
147
+ md_el(:email_address, [], {:email=>email}, al)
148
+ end
149
+
150
+ def md_entity(entity_name, al=nil)
151
+ md_el(:entity, [], {:entity_name=>entity_name}, al)
152
+ end
153
+
154
+ # Markdown extra
155
+ def md_foot_ref(ref_id, al=nil)
156
+ md_el(:footnote_reference, [], {:footnote_id=>ref_id}, al)
157
+ end
158
+
159
+ def md_par(children, al=nil)
160
+ md_el(:paragraph, children, meta={}, al)
161
+ end
162
+
163
+ # [1]: http://url [properties]
164
+ def md_ref_def(ref_id, url, title=nil, meta={}, al=nil)
165
+ meta[:url] = url
166
+ meta[:ref_id] = ref_id
167
+ meta[:title] = title if title
168
+ md_el(:ref_definition, [], meta, al)
169
+ end
170
+
171
+ # inline attribute list
172
+ def md_ial(al)
173
+ al = Maruku::AttributeList.new(al) if
174
+ not al.kind_of?Maruku::AttributeList
175
+ md_el(:ial, [], {:ial=>al})
176
+ end
177
+
178
+ # Attribute list definition
179
+ def md_ald(id, al)
180
+ md_el(:ald, [], {:ald_id=>id,:ald=>al})
181
+ end
182
+
183
+ # Server directive <?target code... ?>
184
+ def md_xml_instr(target, code)
185
+ md_el(:xml_instr, [], {:target=>target, :code=>code})
186
+ end
187
+
188
+ end
189
+ end
190
+
191
+ module MaRuKu
192
+
193
+ class MDElement
194
+ # outputs abbreviated form (this should be eval()uable to get the document)
195
+ def inspect2
196
+ s =
197
+ case @node_type
198
+ when :paragraph
199
+ "md_par(%s)" % children_inspect
200
+ when :footnote_reference
201
+ "md_foot_ref(%s)" % self.footnote_id.inspect
202
+ when :entity
203
+ "md_entity(%s)" % self.entity_name.inspect
204
+ when :email_address
205
+ "md_email(%s)" % self.email.inspect
206
+ when :inline_code
207
+ "md_code(%s)" % self.raw_code.inspect
208
+ when :raw_html
209
+ "md_html(%s)" % self.raw_html.inspect
210
+ when :emphasis
211
+ "md_em(%s)" % children_inspect
212
+ when :strong
213
+ "md_strong(%s)" % children_inspect
214
+ when :immediate_link
215
+ "md_url(%s)" % self.url.inspect
216
+ when :image
217
+ "md_image(%s, %s)" % [
218
+ children_inspect,
219
+ self.ref_id.inspect]
220
+ when :im_image
221
+ "md_im_image(%s, %s, %s)" % [
222
+ children_inspect,
223
+ self.url.inspect,
224
+ self.title.inspect]
225
+ when :link
226
+ "md_link(%s,%s)" % [
227
+ children_inspect, self.ref_id.inspect]
228
+ when :im_link
229
+ "md_im_link(%s, %s, %s)" % [
230
+ children_inspect,
231
+ self.url.inspect,
232
+ self.title.inspect,
233
+ ]
234
+ when :ref_definition
235
+ "md_ref_def(%s, %s, %s)" % [
236
+ self.ref_id.inspect,
237
+ self.url.inspect,
238
+ self.title.inspect
239
+ ]
240
+ when :ial
241
+ "md_ial(%s)" % self.ial.inspect
242
+ else
243
+ return nil
244
+ end
245
+ if @al and not @al.empty? then
246
+ s = s.chop + ", #{@al.inspect})"
247
+ end
248
+ s
249
+ end
250
+
251
+ end
252
+
253
+ end
254
+
255
+
256
+
257
+
258
+
259
+
260
+
@@ -0,0 +1,326 @@
1
+ #--
2
+ # Copyright (C) 2006 Andrea Censi <andrea (at) rubyforge.org>
3
+ #
4
+ # This file is part of Maruku.
5
+ #
6
+ # Maruku is free software; you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation; either version 2 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # Maruku is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Maruku; if not, write to the Free Software
18
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
+ #++
20
+
21
+
22
+ module MaRuKu; module In; module Markdown; module SpanLevelParser
23
+
24
+ # a string scanner coded by me
25
+ class CharSourceManual; end
26
+
27
+ # a wrapper around StringScanner
28
+ class CharSourceStrscan; end
29
+
30
+ # A debug scanner that checks the correctness of both
31
+ # by comparing their output
32
+ class CharSourceDebug; end
33
+
34
+ # Choose!
35
+
36
+ CharSource = CharSourceManual # faster! 58ms vs. 65ms
37
+ #CharSource = CharSourceStrscan
38
+ #CharSource = CharSourceDebug
39
+
40
+
41
+ class CharSourceManual
42
+ include MaRuKu::Strings
43
+
44
+ def initialize(s, parent=nil)
45
+ raise "Passed #{s.class}" if not s.kind_of? String
46
+ @buffer = s
47
+ @buffer_index = 0
48
+ @parent = parent
49
+ end
50
+
51
+ # Return current char as a FixNum (or nil).
52
+ def cur_char; @buffer[@buffer_index] end
53
+
54
+ # Return the next n chars as a String.
55
+ def cur_chars(n); @buffer[@buffer_index,n] end
56
+
57
+ # Return the char after current char as a FixNum (or nil).
58
+ def next_char; @buffer[@buffer_index+1] end
59
+
60
+ def shift_char
61
+ c = @buffer[@buffer_index]
62
+ @buffer_index+=1
63
+ c
64
+ end
65
+
66
+ def ignore_char
67
+ @buffer_index+=1
68
+ nil
69
+ end
70
+
71
+ def ignore_chars(n)
72
+ @buffer_index+=n
73
+ nil
74
+ end
75
+
76
+ def current_remaining_buffer
77
+ @buffer[@buffer_index, @buffer.size-@buffer_index]
78
+ end
79
+
80
+ def cur_chars_are(string)
81
+ # There is a bug here
82
+ if false
83
+ r2 = /^.{#{@buffer_index}}#{Regexp.escape string}/m
84
+ @buffer =~ r2
85
+ else
86
+ cur_chars(string.size) == string
87
+ end
88
+ end
89
+
90
+ def next_matches(r)
91
+ r2 = /^.{#{@buffer_index}}#{r}/m
92
+ md = r2.match @buffer
93
+ return !!md
94
+ end
95
+
96
+ def read_regexp3(r)
97
+ r2 = /^.{#{@buffer_index}}#{r}/m
98
+ m = r2.match @buffer
99
+ if m
100
+ consumed = m.to_s.size - @buffer_index
101
+ # puts "Consumed #{consumed} chars (entire is #{m.to_s.inspect})"
102
+ ignore_chars consumed
103
+ else
104
+ # puts "Could not read regexp #{r2.inspect} from buffer "+
105
+ # " index=#{@buffer_index}"
106
+ # puts "Cur chars = #{cur_chars(20).inspect}"
107
+ # puts "Matches? = #{cur_chars(20) =~ r}"
108
+ end
109
+ m
110
+ end
111
+
112
+ def read_regexp(r)
113
+ r2 = /^#{r}/
114
+ rest = current_remaining_buffer
115
+ m = r2.match(rest)
116
+ if m
117
+ @buffer_index += m.to_s.size
118
+ # puts "#{r} matched #{rest.inspect}: #{m.to_s.inspect}"
119
+ end
120
+ return m
121
+ end
122
+
123
+ def consume_whitespace
124
+ while c = cur_char
125
+ if (c == ?\s || c == ?\t)
126
+ # puts "ignoring #{c}"
127
+ ignore_char
128
+ else
129
+ # puts "#{c} is not ws: "<<c
130
+ break
131
+ end
132
+ end
133
+ end
134
+
135
+ def read_text_chars(out)
136
+ s = @buffer.size; c=nil
137
+ while @buffer_index < s && (c=@buffer[@buffer_index]) &&
138
+ ((c>=?a && c<=?z) || (c>=?A && c<=?Z))
139
+ out << c
140
+ @buffer_index += 1
141
+ end
142
+ end
143
+
144
+ def describe
145
+ s = describe_pos(@buffer, @buffer_index)
146
+ if @parent
147
+ s += "\n\n" + @parent.describe
148
+ end
149
+ s
150
+ end
151
+ include SpanLevelParser
152
+ end
153
+
154
+ def describe_pos(buffer, buffer_index)
155
+ len = 75
156
+ num_before = [len/2, buffer_index].min
157
+ num_after = [len/2, buffer.size-buffer_index].min
158
+ num_before_max = buffer_index
159
+ num_after_max = buffer.size-buffer_index
160
+
161
+ # puts "num #{num_before} #{num_after}"
162
+ num_before = [num_before_max, len-num_after].min
163
+ num_after = [num_after_max, len-num_before].min
164
+ # puts "num #{num_before} #{num_after}"
165
+
166
+ index_start = [buffer_index - num_before, 0].max
167
+ index_end = [buffer_index + num_after, buffer.size].min
168
+
169
+ size = index_end- index_start
170
+
171
+ # puts "- #{index_start} #{size}"
172
+
173
+ str = buffer[index_start, size]
174
+ str.gsub!("\n",'N')
175
+ str.gsub!("\t",'T')
176
+
177
+ if index_end == buffer.size
178
+ str += "EOF"
179
+ end
180
+
181
+ pre_s = buffer_index-index_start
182
+ pre_s = [pre_s, 0].max
183
+ pre_s2 = [len-pre_s,0].max
184
+ # puts "pre_S = #{pre_s}"
185
+ pre =" "*(pre_s)
186
+
187
+ "-"*len+"\n"+
188
+ str + "\n" +
189
+ "-"*pre_s + "|" + "-"*(pre_s2)+"\n"+
190
+ # pre + "|\n"+
191
+ pre + "+--- Byte #{buffer_index}\n"+
192
+
193
+ "Shown bytes [#{index_start} to #{size}] of #{buffer.size}:\n"+
194
+ add_tabs(buffer,1,">")
195
+
196
+ # "CharSource: At character #{@buffer_index} of block "+
197
+ # " beginning with:\n #{@buffer[0,50].inspect} ...\n"+
198
+ # " before: \n ... #{cur_chars(50).inspect} ... "
199
+ end
200
+
201
+
202
+ require 'strscan'
203
+
204
+ class CharSourceStrscan
205
+ include SpanLevelParser
206
+ include MaRuKu::Strings
207
+
208
+ def initialize(s, parent=nil)
209
+ @s = StringScanner.new(s)
210
+ @parent = parent
211
+ end
212
+
213
+ # Return current char as a FixNum (or nil).
214
+ def cur_char
215
+ @s.peek(1)[0]
216
+ end
217
+
218
+ # Return the next n chars as a String.
219
+ def cur_chars(n);
220
+ @s.peek(n)
221
+ end
222
+
223
+ # Return the char after current char as a FixNum (or nil).
224
+ def next_char;
225
+ @s.peek(2)[1]
226
+ end
227
+
228
+ def shift_char
229
+ (@s.get_byte)[0]
230
+ end
231
+
232
+ def ignore_char
233
+ @s.get_byte
234
+ nil
235
+ end
236
+
237
+ def ignore_chars(n)
238
+ n.times do @s.get_byte end
239
+ nil
240
+ end
241
+
242
+ def current_remaining_buffer
243
+ @s.rest #nil #@buffer[@buffer_index, @buffer.size-@buffer_index]
244
+ end
245
+
246
+ def cur_chars_are(string)
247
+ cur_chars(string.size) == string
248
+ end
249
+
250
+ def next_matches(r)
251
+ len = @s.match?(r)
252
+ return !!len
253
+ end
254
+
255
+ def read_regexp(r)
256
+ string = @s.scan(r)
257
+ if string
258
+ return r.match(string)
259
+ else
260
+ return nil
261
+ end
262
+ end
263
+
264
+ def consume_whitespace
265
+ @s.scan(/\s+/)
266
+ nil
267
+ end
268
+
269
+ def describe
270
+ describe_pos(@s.string, @s.pos)
271
+ end
272
+
273
+ end
274
+
275
+
276
+ class CharSourceDebug
277
+ def initialize(s, parent)
278
+ @a = CharSourceManual.new(s, parent)
279
+ @b = CharSourceStrscan.new(s, parent)
280
+ end
281
+
282
+ def method_missing(methodname, *args)
283
+ a_bef = @a.describe
284
+ b_bef = @b.describe
285
+
286
+ a = @a.send(methodname, *args)
287
+ b = @b.send(methodname, *args)
288
+
289
+ # if methodname == :describe
290
+ # return a
291
+ # end
292
+
293
+ if a.kind_of? MatchData
294
+ if a.to_a != b.to_a
295
+ puts "called: #{methodname}(#{args})"
296
+ puts "Matchdata:\na = #{a.to_a.inspect}\nb = #{b.to_a.inspect}"
297
+ puts "AFTER: "+@a.describe
298
+ puts "AFTER: "+@b.describe
299
+ puts "BEFORE: "+a_bef
300
+ puts "BEFORE: "+b_bef
301
+ puts caller.join("\n")
302
+ exit
303
+ end
304
+ else
305
+ if a!=b
306
+ puts "called: #{methodname}(#{args})"
307
+ puts "Attenzione!\na = #{a.inspect}\nb = #{b.inspect}"
308
+ puts ""+@a.describe
309
+ puts ""+@b.describe
310
+ puts caller.join("\n")
311
+ exit
312
+ end
313
+ end
314
+
315
+ if @a.cur_char != @b.cur_char
316
+ puts "Fuori sincronia dopo #{methodname}(#{args})"
317
+ puts ""+@a.describe
318
+ puts ""+@b.describe
319
+ exit
320
+ end
321
+
322
+ return a
323
+ end
324
+ end
325
+
326
+ end end end end