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,87 @@
1
+ ##################################################################
2
+ # Licensing Information #
3
+ # #
4
+ # The following code is licensed, as standalone code, under #
5
+ # the Ruby License, unless otherwise directed within the code. #
6
+ # #
7
+ # For information on the license of this code when distributed #
8
+ # with and used in conjunction with the other modules in the #
9
+ # Amp project, please see the root-level LICENSE file. #
10
+ # #
11
+ # © Michael J. Edgar and Ari Brown, 2009-2010 #
12
+ # #
13
+ ##################################################################
14
+
15
+ module Amp
16
+ module Plugins
17
+ class Base
18
+ extend ModuleExtensions
19
+ cattr_accessor :module, :author
20
+ cattr_accessor_with_default :loaded_plugins, []
21
+
22
+ # This tracks all subclasses (and subclasses of subclasses, etc). Plus, this
23
+ # method is inherited, so Wool::Plugins::Git.all_subclasses will have all
24
+ # subclasses of Wool::Plugins::Git!
25
+ def self.all_plugins
26
+ @all_plugins ||= [self]
27
+ end
28
+
29
+ # When a Plugin subclass is subclassed, store the subclass and inform the
30
+ # next superclass up the inheritance hierarchy.
31
+ def self.inherited(klass)
32
+ self.all_plugins << klass
33
+ next_klass = self.superclass
34
+ while next_klass != Amp::Plugins::Base.superclass
35
+ next_klass.send(:inherited, klass)
36
+ next_klass = next_klass.superclass
37
+ end
38
+ end
39
+
40
+ # Creates a Plugin subclass with the given name. Also allows specifying
41
+ # the superclass to use.
42
+ #
43
+ # Reopens existing plugins if they already exist, for user customization.
44
+ def self.create(name, superclass=Amp::Plugins::Base)
45
+ unless (name = name.to_s) && name.size > 0
46
+ raise ArgumentError.new('name must be a non-empty string')
47
+ end
48
+ name = name[0,1].upcase + name[1..-1]
49
+ klass = nil
50
+ Amp::Plugins.class_eval do
51
+ if const_defined?(name)
52
+ klass = const_get(name)
53
+ else
54
+ klass = Class.new(superclass)
55
+ const_set(name, klass) # So the class has a name
56
+ end
57
+ yield klass if block_given?
58
+ end
59
+ klass
60
+ end
61
+
62
+ def self.load_rubygems_plugins
63
+ require 'rubygems'
64
+ files = Gem.find_files('amp_plugin.rb')
65
+ files.each do |file|
66
+ load file
67
+ end
68
+ end
69
+
70
+ # Generic initialization all plugins perform. Takes an options hash.
71
+ def initialize(opts={})
72
+ end
73
+
74
+ def inspect
75
+ "#<Amp::Plugin::#{self.module} #{self.class.name} by #{self.class.author}>"
76
+ end
77
+
78
+ def module
79
+ self.class.module || self.class.name
80
+ end
81
+
82
+ def load!
83
+ # Subclasses should implement this.
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,92 @@
1
+ ##################################################################
2
+ # Licensing Information #
3
+ # #
4
+ # The following code is licensed, as standalone code, under #
5
+ # the Ruby License, unless otherwise directed within the code. #
6
+ # #
7
+ # For information on the license of this code when distributed #
8
+ # with and used in conjunction with the other modules in the #
9
+ # Amp project, please see the root-level LICENSE file. #
10
+ # #
11
+ # © Michael J. Edgar and Ari Brown, 2009-2010 #
12
+ # #
13
+ ##################################################################
14
+ module Amp
15
+ # These are extensions to Amp modules. This module should be
16
+ # extended by any Amp modules seeking to take advantage of them.
17
+ # This prevents conflicts with other libraries defining extensions
18
+ # of the same name.
19
+ module ModuleExtensions
20
+ def singleton_class
21
+ class << self
22
+ self
23
+ end
24
+ end if RUBY_VERSION < "1.9"
25
+
26
+ # Creates a reader for the given instance variables on the class object.
27
+ def cattr_reader(*attrs)
28
+ attrs.each do |attr|
29
+ instance_eval("def #{attr}; @#{attr}; end")
30
+ end
31
+ end
32
+
33
+ # Creates a writer for the given instance variables on the class object.
34
+ def cattr_writer(*attrs)
35
+ attrs.each do |attr|
36
+ instance_eval("def #{attr}=(val); @#{attr} = val; end")
37
+ end
38
+ end
39
+
40
+ # Creates readers and writers for the given instance variables.
41
+ def cattr_accessor(*attrs)
42
+ cattr_reader(*attrs)
43
+ cattr_writer(*attrs)
44
+ end
45
+
46
+ def cattr_accessor_with_default(attr, default)
47
+ varname = "@#{attr}".to_sym
48
+ singleton_class.instance_eval do
49
+ define_method attr do
50
+ if instance_variable_defined?(varname)
51
+ instance_variable_get(varname)
52
+ else
53
+ instance_variable_set(varname, default)
54
+ default
55
+ end
56
+ end
57
+ end
58
+ cattr_writer(attr)
59
+ end
60
+
61
+ # Creates a DSL-friendly set-and-getter method. The method, when called with
62
+ # no arguments, acts as a getter. When called with arguments, it acts as a
63
+ # setter. Uses class instance variables - this is not for generating
64
+ # instance methods.
65
+ #
66
+ # @example
67
+ # class A
68
+ # cattr_get_and_setter :type
69
+ # end
70
+ # class B < A
71
+ # type :silly
72
+ # end
73
+ # p B.type # => :silly
74
+ def cattr_get_and_setter(*attrs)
75
+ attrs.each do |attr|
76
+ cattr_accessor attr
77
+ singleton_class.instance_eval do
78
+ alias_method "#{attr}_old_get".to_sym, attr
79
+ define_method attr do |*args, &blk|
80
+ if args.size > 0
81
+ send("#{attr}=", *args)
82
+ elsif blk != nil
83
+ send("#{attr}=", blk)
84
+ else
85
+ send("#{attr}_old_get")
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,136 @@
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
+ require 'rexml/document'
22
+
23
+ dir_path = File.expand_path(File.dirname(__FILE__))
24
+ $:.unshift dir_path
25
+
26
+ # :include:MaRuKu.txt
27
+ module MaRuKu
28
+
29
+ module In
30
+ module Markdown
31
+ module SpanLevelParser; end
32
+ module BlockLevelParser; end
33
+ end
34
+ # more to come?
35
+ end
36
+
37
+ module Out
38
+ # Functions for exporting to MarkDown.
39
+ module Markdown; end
40
+ # Functions for exporting to HTML.
41
+ module HTML; end
42
+ # Functions for exporting to ANSI
43
+ module Ansi; end
44
+ end
45
+
46
+ # These are strings utilities.
47
+ module Strings; end
48
+
49
+ module Helpers; end
50
+
51
+ module Errors; end
52
+
53
+ class MDElement
54
+ include REXML
55
+ include MaRuKu
56
+ include Out::Markdown
57
+ include Out::HTML
58
+ include Out::Ansi
59
+ include Strings
60
+ include Helpers
61
+ include Errors
62
+ end
63
+
64
+
65
+ class MDDocument < MDElement
66
+ include In::Markdown
67
+ include In::Markdown::SpanLevelParser
68
+ include In::Markdown::BlockLevelParser
69
+ end
70
+ end
71
+
72
+ # This is the public interface
73
+ class Maruku < MaRuKu::MDDocument; end
74
+
75
+
76
+
77
+ require 'rexml/document'
78
+
79
+ # Structures definition
80
+ require 'maruku/structures'
81
+ require 'maruku/structures_inspect'
82
+
83
+ require 'maruku/defaults'
84
+ # Less typing
85
+ require 'maruku/helpers'
86
+
87
+ # Code for parsing whole Markdown documents
88
+ require 'maruku/input/parse_doc'
89
+
90
+ # Ugly things kept in a closet
91
+ require 'maruku/string_utils'
92
+ require 'maruku/input/linesource'
93
+ require 'maruku/input/type_detection'
94
+
95
+ # A class for reading and sanitizing inline HTML
96
+ require 'maruku/input/html_helper'
97
+
98
+ # Code for parsing Markdown block-level elements
99
+ require 'maruku/input/parse_block'
100
+
101
+ # Code for parsing Markdown span-level elements
102
+ require 'maruku/input/charsource'
103
+ require 'maruku/input/parse_span_better'
104
+ require 'maruku/input/rubypants'
105
+
106
+ require 'maruku/input/extensions'
107
+
108
+ require 'maruku/attributes'
109
+
110
+ require 'maruku/structures_iterators'
111
+
112
+ require 'maruku/errors_management'
113
+
114
+ # Code for creating a table of contents
115
+ require 'maruku/toc'
116
+
117
+ # Version and URL
118
+ require 'maruku/version'
119
+
120
+
121
+ # Exporting to html
122
+ require 'maruku/output/to_html'
123
+
124
+ # Exporting to ansi terminal output
125
+ require 'maruku/output/to_ansi'
126
+
127
+ # Pretty print
128
+ require 'maruku/output/to_markdown'
129
+
130
+ # Exporting to text: strips all formatting (not complete)
131
+ require 'maruku/output/to_s'
132
+
133
+ # class Maruku is the global interface
134
+ require 'maruku/maruku'
135
+
136
+ $:.delete dir_path
@@ -0,0 +1,227 @@
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
+ def quote_if_needed
24
+ if /[\s\'\"]/.match self
25
+ inspect
26
+ else
27
+ self
28
+ end
29
+ end
30
+ end
31
+
32
+ module MaRuKu;
33
+ MagicChar = ':'
34
+
35
+ class AttributeList < Array
36
+
37
+ # An attribute list becomes
38
+ # {#id .cl key="val" ref}
39
+ # [ [:id, 'id'], [:class, 'id'], ['key', 'val'], [ :ref, 'ref' ]]
40
+
41
+ private :push
42
+
43
+ def push_key_val(key, val);
44
+ raise "Bad #{key.inspect}=#{val.inspect}" if not key and val
45
+ push [key, val]
46
+ end
47
+ def push_ref(ref_id);
48
+
49
+ raise "Bad :ref #{ref_id.inspect}" if not ref_id
50
+ push [:ref, ref_id+""]
51
+
52
+ # p "Now ", self ########################################
53
+ end
54
+ def push_class(val);
55
+ raise "Bad :id #{val.inspect}" if not val
56
+ push [:class, val]
57
+ end
58
+ def push_id(val);
59
+ raise "Bad :id #{val.inspect}" if not val
60
+ push [:id, val]
61
+ end
62
+
63
+ def to_s
64
+ map do |k,v|
65
+ case k
66
+ when :id; "#" + v.quote_if_needed
67
+ when :class; "." + v.quote_if_needed
68
+ when :ref; v.quote_if_needed
69
+ else k.quote_if_needed + "=" + v.quote_if_needed
70
+ end
71
+ end . join(' ')
72
+ end
73
+ alias to_md to_s
74
+ end
75
+
76
+ end
77
+
78
+ module MaRuKu; module In; module Markdown; module SpanLevelParser
79
+
80
+ def unit_tests_for_attribute_lists
81
+ [
82
+ [ "", [], "Empty lists are allowed" ],
83
+ [ "=", :throw, "Bad char to begin a list with." ],
84
+ [ "a =b", :throw, "No whitespace before `=`." ],
85
+ [ "a= b", :throw, "No whitespace after `=`." ],
86
+
87
+ [ "a b", [[:ref, 'a'],[:ref, 'b']], "More than one ref" ],
88
+ [ "a b c", [[:ref, 'a'],[:ref, 'b'],[:ref, 'c']], "More than one ref" ],
89
+ [ "hello notfound", [[:ref, 'hello'],[:ref, 'notfound']]],
90
+
91
+ [ "'a'", [[:ref, 'a']], "Quoted value." ],
92
+ [ '"a"' ],
93
+
94
+ [ "a=b", [['a','b']], "Simple key/val" ],
95
+ [ "'a'=b" ],
96
+ [ "'a'='b'" ],
97
+ [ "a='b'" ],
98
+
99
+ [ 'a="b\'"', [['a',"b\'"]], "Key/val with quotes" ],
100
+ [ 'a=b\''],
101
+ [ 'a="\\\'b\'"', [['a',"\'b\'"]], "Key/val with quotes" ],
102
+
103
+ ['"', :throw, "Unclosed quotes"],
104
+ ["'"],
105
+ ["'a "],
106
+ ['"a '],
107
+
108
+ [ "#a", [[:id, 'a']], "Simple ID" ],
109
+ [ "#'a'" ],
110
+ [ '#"a"' ],
111
+
112
+ [ "#", :throw, "Unfinished '#'." ],
113
+ [ ".", :throw, "Unfinished '.'." ],
114
+ [ "# a", :throw, "No white-space after '#'." ],
115
+ [ ". a", :throw, "No white-space after '.' ." ],
116
+
117
+ [ "a=b c=d", [['a','b'],['c','d']], "Tabbing" ],
118
+ [ " \ta=b \tc='d' "],
119
+ [ "\t a=b\t c='d'\t\t"],
120
+
121
+ [ ".\"a'", :throw, "Mixing quotes is bad." ],
122
+
123
+ ].map { |s, expected, comment|
124
+ @expected = (expected ||= @expected)
125
+ @comment = (comment ||= (last=@comment) )
126
+ (comment == last && (comment += (@count+=1).to_s)) || @count = 1
127
+ expected = [md_ial(expected)] if expected.kind_of? Array
128
+ ["{#{MagicChar}#{s}}", expected, "Attributes: #{comment}"]
129
+ }
130
+ end
131
+
132
+ def md_al(s=[]); AttributeList.new(s) end
133
+
134
+ # returns nil or an AttributeList
135
+ def read_attribute_list(src, con, break_on_chars)
136
+
137
+ separators = break_on_chars + [?=,?\ ,?\t]
138
+ escaped = Maruku::EscapedCharInQuotes
139
+
140
+ al = AttributeList.new
141
+ while true
142
+ src.consume_whitespace
143
+ break if break_on_chars.include? src.cur_char
144
+
145
+ case src.cur_char
146
+ when nil
147
+ maruku_error "Attribute list terminated by EOF:\n "+
148
+ "#{al.inspect}" , src, con
149
+ tell_user "I try to continue and return partial attribute list:\n"+
150
+ al.inspect
151
+ break
152
+ when ?= # error
153
+ maruku_error "In attribute lists, cannot start identifier with `=`."
154
+ tell_user "I try to continue"
155
+ src.ignore_char
156
+ when ?# # id definition
157
+ src.ignore_char
158
+ if id = read_quoted_or_unquoted(src, con, escaped, separators)
159
+ al.push_id id
160
+ else
161
+ maruku_error 'Could not read `id` attribute.', src, con
162
+ tell_user 'Trying to ignore bad `id` attribute.'
163
+ end
164
+ when ?. # class definition
165
+ src.ignore_char
166
+ if klass = read_quoted_or_unquoted(src, con, escaped, separators)
167
+ al.push_class klass
168
+ else
169
+ maruku_error 'Could not read `class` attribute.', src, con
170
+ tell_user 'Trying to ignore bad `class` attribute.'
171
+ end
172
+ else
173
+ if key = read_quoted_or_unquoted(src, con, escaped, separators)
174
+ if src.cur_char == ?=
175
+ src.ignore_char # skip the =
176
+ if val = read_quoted_or_unquoted(src, con, escaped, separators)
177
+ al.push_key_val(key, val)
178
+ else
179
+ maruku_error "Could not read value for key #{key.inspect}.",
180
+ src, con
181
+ tell_user "Ignoring key #{key.inspect}."
182
+ end
183
+ else
184
+ al.push_ref key
185
+ end
186
+ else
187
+ maruku_error 'Could not read key or reference.'
188
+ end
189
+ end # case
190
+ end # while true
191
+ al
192
+ end
193
+
194
+
195
+ # We need a helper
196
+ def is_ial(e); e.kind_of? MDElement and e.node_type == :ial end
197
+
198
+ def merge_ial(elements, src, con)
199
+
200
+ # Apply each IAL to the element before
201
+ elements.each_with_index do |e, i|
202
+ if is_ial(e) && i>= 1 then
203
+ before = elements[i-1]
204
+ after = elements[i+1]
205
+ if before.kind_of? MDElement
206
+ before.al = e.ial
207
+ elsif after.kind_of? MDElement
208
+ after.al = e.ial
209
+ else
210
+ maruku_error "It is not clear to me what element this IAL {:#{e.ial.to_md}} \n"+
211
+ "is referring to. The element before is a #{before.class.to_s}, \n"+
212
+ "the element after is a #{after.class.to_s}.\n"+
213
+ "\n before: #{before.inspect}"+
214
+ "\n after: #{after.inspect}",
215
+ src, con
216
+ # xxx dire se c'è empty vicino
217
+ end
218
+ end
219
+ end
220
+
221
+ if not Globals[:debug_keep_ials]
222
+ elements.delete_if {|x| is_ial(x) unless x == elements.first}
223
+ end
224
+ end
225
+
226
+ end end end end
227
+ #module MaRuKu; module In; module Markdown; module SpanLevelParser