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,164 @@
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
+ class String
23
+ # XXX: markdown escaping
24
+ def to_md(c=nil)
25
+ to_s
26
+ end
27
+
28
+ # " andrea censi " => [" andrea ", "censi "]
29
+ def mysplit
30
+ split.map{|x| x+" "}
31
+ end
32
+ end
33
+
34
+
35
+ module MaRuKu; module Out; module Markdown
36
+
37
+ DefaultLineLength = 40
38
+
39
+ def to_md(context={})
40
+ children_to_md(context)
41
+ end
42
+
43
+ def to_md_paragraph(context)
44
+ line_length = context[:line_length] || DefaultLineLength
45
+ wrap(@children, line_length, context)+"\n"
46
+ end
47
+
48
+ def to_md_li_span(context)
49
+ len = (context[:line_length] || DefaultLineLength) - 2
50
+ s = add_tabs(wrap(@children, len-2, context), 1, ' ')
51
+ s[0] = ?*
52
+ s + "\n"
53
+ end
54
+
55
+ def to_md_abbr_def(context)
56
+ "*[#{self.abbr}]: #{self.text}\n"
57
+ end
58
+
59
+ def to_md_ol(context)
60
+ len = (context[:line_length] || DefaultLineLength) - 2
61
+ md = ""
62
+ self.children.each_with_index do |li, i|
63
+ s = add_tabs(w=wrap(li.children, len-2, context), 1, ' ')+"\n"
64
+ s[0,4] = "#{i+1}. "[0,4]
65
+ # puts w.inspect
66
+ md += s
67
+ end
68
+ md + "\n"
69
+ end
70
+
71
+ def to_md_ul(context)
72
+ len = (context[:line_length] || DefaultLineLength) - 2
73
+ md = ""
74
+ self.children.each_with_index do |li, i|
75
+ w = wrap(li.children, len-2, context)
76
+ # puts "W: "+ w.inspect
77
+ s = add_indent(w)
78
+ # puts "S: " +s.inspect
79
+ s[0,1] = "-"
80
+ md += s
81
+ end
82
+ md + "\n"
83
+ end
84
+
85
+ def add_indent(s,char=" ")
86
+ t = s.split("\n").map{|x| char+x }.join("\n")
87
+ s << ?\n if t[-1] == ?\n
88
+ s
89
+ end
90
+
91
+ # Convert each child to html
92
+ def children_to_md(context)
93
+ array_to_md(@children, context)
94
+ end
95
+
96
+ def wrap(array, line_length, context)
97
+ out = ""
98
+ line = ""
99
+ array.each do |c|
100
+ if c.kind_of?(MDElement) && c.node_type == :linebreak
101
+ out << line.strip << " \n"; line="";
102
+ next
103
+ end
104
+
105
+ pieces =
106
+ if c.kind_of? String
107
+ c.to_md.mysplit
108
+ else
109
+ [c.to_md(context)].flatten
110
+ end
111
+
112
+ # puts "Pieces: #{pieces.inspect}"
113
+ pieces.each do |p|
114
+ if p.size + line.size > line_length
115
+ out << line.strip << "\n";
116
+ line = ""
117
+ end
118
+ line << p
119
+ end
120
+ end
121
+ out << line.strip << "\n" if line.size > 0
122
+ out << ?\n if not out[-1] == ?\n
123
+ out
124
+ end
125
+
126
+
127
+ def array_to_md(array, context, join_char='')
128
+ e = []
129
+ array.each do |c|
130
+ method = c.kind_of?(MDElement) ?
131
+ "to_md_#{c.node_type}" : "to_md"
132
+
133
+ if not c.respond_to?(method)
134
+ #raise "Object does not answer to #{method}: #{c.class} #{c.inspect[0,100]}"
135
+ # tell_user "Using default for #{c.node_type}"
136
+ method = 'to_md'
137
+ end
138
+
139
+ # puts "#{c.inspect} created with method #{method}"
140
+ h = c.send(method, context)
141
+
142
+ if h.nil?
143
+ raise "Nil md for #{c.inspect} created with method #{method}"
144
+ end
145
+
146
+ if h.kind_of?Array
147
+ e = e + h
148
+ else
149
+ e << h
150
+ end
151
+ end
152
+ e.join(join_char)
153
+ end
154
+
155
+ end end end
156
+
157
+ module MaRuKu; class MDDocument
158
+ alias old_md to_md
159
+ def to_md(context={})
160
+ s = old_md(context)
161
+ # puts s
162
+ s
163
+ end
164
+ end end
@@ -0,0 +1,56 @@
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
+ class MDElement
25
+
26
+ # Strips all formatting from the string
27
+ def to_s
28
+ children_to_s
29
+ end
30
+
31
+ def children_to_s
32
+ @children.join
33
+ end
34
+
35
+ # Generate an id for headers. Assumes @children is set.
36
+ def generate_id
37
+
38
+ title = children_to_s
39
+ title.gsub!(/ /,'_')
40
+ title.downcase!
41
+ title.gsub!(/[^\w_]/,'')
42
+ title.strip!
43
+
44
+ if title.size == 0
45
+ $uid ||= 0
46
+ $uid += 1
47
+ title = "id#{$uid}"
48
+ end
49
+
50
+ # random is a very bad idea
51
+ # title << "_" + rand(10000).to_s
52
+ title
53
+ end
54
+ end
55
+
56
+ end
@@ -0,0 +1,191 @@
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
+ # Boring stuff with strings.
23
+ module MaRuKu; module Strings
24
+
25
+ def add_tabs(s,n=1,char="\t")
26
+ s.split("\n").map{|x| char*n+x }.join("\n")
27
+ end
28
+
29
+ TabSize = 4;
30
+
31
+ def split_lines(s)
32
+ s.gsub("\r","").split("\n")
33
+ end
34
+
35
+ # This parses email headers. Returns an hash.
36
+ #
37
+ # +hash['data']+ is the message.
38
+ #
39
+ # Keys are downcased, space becomes underscore, converted to symbols.
40
+ #
41
+ # My key: true
42
+ #
43
+ # becomes:
44
+ #
45
+ # {:my_key => true}
46
+ #
47
+ def parse_email_headers(s)
48
+ keys={}
49
+ match = (s =~ /\A((\w[\w\s\_\-]+: .*\n)+)\s*\n/)
50
+ if match != 0
51
+ keys[:data] = s
52
+ else
53
+ keys[:data] = $'
54
+ headers = $1
55
+ headers.split("\n").each do |l|
56
+ # Fails if there are other ':' characters.
57
+ # k, v = l.split(':')
58
+ k, v = l.split(':', 2)
59
+ k, v = normalize_key_and_value(k, v)
60
+ k = k.to_sym
61
+ # puts "K = #{k}, V=#{v}"
62
+ keys[k] = v
63
+ end
64
+ end
65
+ keys
66
+ end
67
+
68
+ # Keys are downcased, space becomes underscore, converted to symbols.
69
+ def normalize_key_and_value(k,v)
70
+ v = v ? v.strip : true # no value defaults to true
71
+ k = k.strip
72
+
73
+ # check synonyms
74
+ v = true if ['yes','true'].include?(v.to_s.downcase)
75
+ v = false if ['no','false'].include?(v.to_s.downcase)
76
+
77
+ k = k.downcase.gsub(' ','_')
78
+ return k, v
79
+ end
80
+
81
+ # Returns the number of leading spaces, considering that
82
+ # a tab counts as `TabSize` spaces.
83
+ def number_of_leading_spaces(s)
84
+ n=0; i=0;
85
+ while i < s.size
86
+ c = s[i,1]
87
+ if c == ' '
88
+ i+=1; n+=1;
89
+ elsif c == "\t"
90
+ i+=1; n+=TabSize;
91
+ else
92
+ break
93
+ end
94
+ end
95
+ n
96
+ end
97
+
98
+ # This returns the position of the first real char in a list item
99
+ #
100
+ # For example:
101
+ # '*Hello' # => 1
102
+ # '* Hello' # => 2
103
+ # ' * Hello' # => 3
104
+ # ' * Hello' # => 5
105
+ # '1.Hello' # => 2
106
+ # ' 1. Hello' # => 5
107
+
108
+ def spaces_before_first_char(s)
109
+ case s.md_type
110
+ when :ulist
111
+ i=0;
112
+ # skip whitespace if present
113
+ while s[i,1] =~ /\s/; i+=1 end
114
+ # skip indicator (+, -, *)
115
+ i+=1
116
+ # skip optional whitespace
117
+ while s[i,1] =~ /\s/; i+=1 end
118
+ return i
119
+ when :olist
120
+ i=0;
121
+ # skip whitespace
122
+ while s[i,1] =~ /\s/; i+=1 end
123
+ # skip digits
124
+ while s[i,1] =~ /\d/; i+=1 end
125
+ # skip dot
126
+ i+=1
127
+ # skip whitespace
128
+ while s[i,1] =~ /\s/; i+=1 end
129
+ return i
130
+ else
131
+ tell_user "BUG (my bad): '#{s}' is not a list"
132
+ 0
133
+ end
134
+ end
135
+
136
+ # Counts the number of leading '#' in the string
137
+ def num_leading_hashes(s)
138
+ i=0;
139
+ while i<(s.size-1) && (s[i,1]=='#'); i+=1 end
140
+ i
141
+ end
142
+
143
+ # Strips initial and final hashes
144
+ def strip_hashes(s)
145
+ s = s[num_leading_hashes(s), s.size]
146
+ i = s.size-1
147
+ while i > 0 && (s[i,1] =~ /(#|\s)/); i-=1; end
148
+ s[0, i+1].strip
149
+ end
150
+
151
+ # change space to "_" and remove any non-word character
152
+ def sanitize_ref_id(x)
153
+ x.strip.downcase.gsub(' ','_').gsub(/[^\w]/,'')
154
+ end
155
+
156
+
157
+ # removes initial quote
158
+ def unquote(s)
159
+ s.gsub(/^>\s?/,'')
160
+ end
161
+
162
+ # toglie al massimo n caratteri
163
+ def strip_indent(s, n)
164
+ i = 0
165
+ while i < s.size && n>0
166
+ c = s[i,1]
167
+ if c == ' '
168
+ n-=1;
169
+ elsif c == "\t"
170
+ n-=TabSize;
171
+ else
172
+ break
173
+ end
174
+ i+=1
175
+ end
176
+ s[i, s.size]
177
+ end
178
+
179
+ def dbg_describe_ary(a, prefix='')
180
+ i = 0
181
+ a.each do |l|
182
+ puts "#{prefix} (#{i+=1})# #{l.inspect}"
183
+ end
184
+ end
185
+
186
+ def force_linebreak?(l)
187
+ l =~ / $/
188
+ end
189
+
190
+ end
191
+ end
@@ -0,0 +1,167 @@
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
+ class Module
24
+ def safe_attr_accessor1(symbol, klass)
25
+ attr_reader symbol
26
+ code = <<-EOF
27
+ def #{symbol}=(val)
28
+ if not val.kind_of? #{klass}
29
+ s = "\nCould not assign an object of type \#{val.class} to #{symbol}.\n\n"
30
+ s += "Tried to assign object of class \#{val.class}:\n"+
31
+ "\#{val.inspect}\n"+
32
+ "to \#{self.class}::#{symbol} constrained to be of class #{klass}.\n"
33
+ raise s
34
+ end
35
+ @#{symbol} = val
36
+ end
37
+
38
+ EOF
39
+ module_eval code
40
+ end
41
+
42
+ def safe_attr_accessor2(symbol, klass)
43
+ attr_accessor symbol
44
+ end
45
+
46
+ alias safe_attr_accessor safe_attr_accessor2
47
+ end
48
+
49
+ module MaRuKu
50
+
51
+ # I did not want to have a class for each possible element.
52
+ # Instead I opted to have only the class "MDElement"
53
+ # that represents eveything in the document (paragraphs, headers, etc).
54
+ #
55
+ # You can tell what it is by the variable `node_type`.
56
+ #
57
+ # In the instance-variable `children` there are the children. These
58
+ # can be of class 1) String or 2) MDElement.
59
+ #
60
+ # The @doc variable points to the document to which the MDElement
61
+ # belongs (which is an instance of Maruku, subclass of MDElement).
62
+ #
63
+ # Attributes are contained in the hash `attributes`.
64
+ # Keys are symbols (downcased, with spaces substituted by underscores)
65
+ #
66
+ # For example, if you write in the source document.
67
+ #
68
+ # Title: test document
69
+ # My property: value
70
+ #
71
+ # content content
72
+ #
73
+ # You can access `value` by writing:
74
+ #
75
+ # @doc.attributes[:my_property] # => 'value'
76
+ #
77
+ # from whichever MDElement in the hierarchy.
78
+ #
79
+ class MDElement
80
+ # See helpers.rb for the list of allowed #node_type values
81
+ safe_attr_accessor :node_type, Symbol
82
+
83
+ # Children are either Strings or MDElement
84
+ safe_attr_accessor :children, Array
85
+
86
+ # An attribute list, may not be nil
87
+ safe_attr_accessor :al, Array #Maruku::AttributeList
88
+
89
+ # These are the processed attributes
90
+ safe_attr_accessor :attributes, Hash
91
+
92
+ # Reference of the document (which is of class Maruku)
93
+ attr_accessor :doc
94
+
95
+ def initialize(node_type=:unset, children=[], meta={},
96
+ al=MaRuKu::AttributeList.new )
97
+ super();
98
+ self.children = children
99
+ self.node_type = node_type
100
+
101
+ @attributes = {}
102
+
103
+ meta.each do |symbol, value|
104
+ self.instance_eval "
105
+ def #{symbol}; @#{symbol}; end
106
+ def #{symbol}=(val); @#{symbol}=val; end"
107
+ self.send "#{symbol}=", value
108
+ end
109
+
110
+ self.al = al || AttributeList.new
111
+
112
+ self.meta_priv = meta
113
+ end
114
+
115
+ attr_accessor :meta_priv
116
+
117
+ def ==(o)
118
+ ok = o.kind_of?(MDElement) &&
119
+ (self.node_type == o.node_type) &&
120
+ (self.meta_priv == o.meta_priv) &&
121
+ (self.children == o.children)
122
+
123
+ if not ok
124
+ # puts "This:\n"+self.inspect+"\nis different from\n"+o.inspect+"\n\n"
125
+ end
126
+ ok
127
+ end
128
+ end
129
+
130
+ # This represents the whole document and holds global data.
131
+
132
+ class MDDocument
133
+
134
+ safe_attr_accessor :refs, Hash
135
+ safe_attr_accessor :footnotes, Hash
136
+
137
+ # This is an hash. The key might be nil.
138
+ safe_attr_accessor :abbreviations, Hash
139
+
140
+ # Attribute lists definition
141
+ safe_attr_accessor :ald, Hash
142
+
143
+ # The order in which footnotes are used. Contains the id.
144
+ safe_attr_accessor :footnotes_order, Array
145
+
146
+ safe_attr_accessor :latex_required_packages, Array
147
+
148
+ safe_attr_accessor :refid2ref, Hash
149
+
150
+ def initialize(s=nil)
151
+ super(:document)
152
+ @doc = self
153
+
154
+ self.refs = {}
155
+ self.footnotes = {}
156
+ self.footnotes_order = []
157
+ self.abbreviations = {}
158
+ self.ald = {}
159
+ self.latex_required_packages = []
160
+
161
+ parse_doc(s) if s
162
+ end
163
+ end
164
+
165
+
166
+ end # MaRuKu
167
+