amp-front 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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