amp-front 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +24 -0
- data/Ampfile +3 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +36 -0
- data/LICENSE +20 -0
- data/README.md +50 -0
- data/Rakefile +64 -0
- data/VERSION +1 -0
- data/design_docs/commands.md +91 -0
- data/design_docs/dependencies.md +35 -0
- data/design_docs/plugins.md +47 -0
- data/features/amp.feature +8 -0
- data/features/amp_help.feature +36 -0
- data/features/amp_plugin_list.feature +10 -0
- data/features/step_definitions/amp-front_steps.rb +23 -0
- data/features/support/env.rb +4 -0
- data/lib/amp-front.rb +30 -0
- data/lib/amp-front/dispatch/commands/base.rb +158 -0
- data/lib/amp-front/dispatch/commands/builtin/help.rb +23 -0
- data/lib/amp-front/dispatch/commands/builtin/plugin.rb +24 -0
- data/lib/amp-front/dispatch/commands/validations.rb +171 -0
- data/lib/amp-front/dispatch/runner.rb +86 -0
- data/lib/amp-front/help/entries/__default__.erb +31 -0
- data/lib/amp-front/help/entries/ampfiles.md +42 -0
- data/lib/amp-front/help/entries/commands.erb +6 -0
- data/lib/amp-front/help/entries/new-commands.md +81 -0
- data/lib/amp-front/help/help.rb +312 -0
- data/lib/amp-front/plugins/base.rb +87 -0
- data/lib/amp-front/support/module_extensions.rb +92 -0
- data/lib/amp-front/third_party/maruku.rb +136 -0
- data/lib/amp-front/third_party/maruku/attributes.rb +227 -0
- data/lib/amp-front/third_party/maruku/defaults.rb +71 -0
- data/lib/amp-front/third_party/maruku/errors_management.rb +92 -0
- data/lib/amp-front/third_party/maruku/helpers.rb +260 -0
- data/lib/amp-front/third_party/maruku/input/charsource.rb +326 -0
- data/lib/amp-front/third_party/maruku/input/extensions.rb +69 -0
- data/lib/amp-front/third_party/maruku/input/html_helper.rb +189 -0
- data/lib/amp-front/third_party/maruku/input/linesource.rb +111 -0
- data/lib/amp-front/third_party/maruku/input/parse_block.rb +615 -0
- data/lib/amp-front/third_party/maruku/input/parse_doc.rb +234 -0
- data/lib/amp-front/third_party/maruku/input/parse_span_better.rb +746 -0
- data/lib/amp-front/third_party/maruku/input/rubypants.rb +225 -0
- data/lib/amp-front/third_party/maruku/input/type_detection.rb +147 -0
- data/lib/amp-front/third_party/maruku/input_textile2/t2_parser.rb +163 -0
- data/lib/amp-front/third_party/maruku/maruku.rb +33 -0
- data/lib/amp-front/third_party/maruku/output/to_ansi.rb +223 -0
- data/lib/amp-front/third_party/maruku/output/to_html.rb +991 -0
- data/lib/amp-front/third_party/maruku/output/to_markdown.rb +164 -0
- data/lib/amp-front/third_party/maruku/output/to_s.rb +56 -0
- data/lib/amp-front/third_party/maruku/string_utils.rb +191 -0
- data/lib/amp-front/third_party/maruku/structures.rb +167 -0
- data/lib/amp-front/third_party/maruku/structures_inspect.rb +87 -0
- data/lib/amp-front/third_party/maruku/structures_iterators.rb +61 -0
- data/lib/amp-front/third_party/maruku/textile2.rb +1 -0
- data/lib/amp-front/third_party/maruku/toc.rb +199 -0
- data/lib/amp-front/third_party/maruku/usage/example1.rb +33 -0
- data/lib/amp-front/third_party/maruku/version.rb +40 -0
- data/lib/amp-front/third_party/trollop.rb +766 -0
- data/spec/amp-front_spec.rb +25 -0
- data/spec/command_specs/base_spec.rb +123 -0
- data/spec/command_specs/command_spec.rb +97 -0
- data/spec/command_specs/help_spec.rb +33 -0
- data/spec/command_specs/spec_helper.rb +37 -0
- data/spec/command_specs/validations_spec.rb +267 -0
- data/spec/dispatch_specs/runner_spec.rb +116 -0
- data/spec/dispatch_specs/spec_helper.rb +15 -0
- data/spec/help_specs/help_entry_spec.rb +78 -0
- data/spec/help_specs/help_registry_spec.rb +77 -0
- data/spec/help_specs/spec_helper.rb +15 -0
- data/spec/plugin_specs/base_spec.rb +36 -0
- data/spec/plugin_specs/spec_helper.rb +15 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +33 -0
- data/spec/support_specs/module_extensions_spec.rb +104 -0
- data/spec/support_specs/spec_helper.rb +15 -0
- data/test/third_party_tests/test_trollop.rb +1181 -0
- 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
|