brandish 0.1.1
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.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.rspec +3 -0
- data/.rubocop.yml +41 -0
- data/.travis.yml +5 -0
- data/.yardopts +1 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +10 -0
- data/LICENSE.txt +21 -0
- data/README.md +41 -0
- data/Rakefile +9 -0
- data/bin/brandish +16 -0
- data/brandish.gemspec +39 -0
- data/defaults/templates/html.liquid +39 -0
- data/lib/brandish.rb +51 -0
- data/lib/brandish/application.rb +163 -0
- data/lib/brandish/application/bench_command.rb +96 -0
- data/lib/brandish/application/build_command.rb +73 -0
- data/lib/brandish/application/initialize_command.rb +83 -0
- data/lib/brandish/application/serve_command.rb +150 -0
- data/lib/brandish/configure.rb +196 -0
- data/lib/brandish/configure/dsl.rb +135 -0
- data/lib/brandish/configure/dsl/form.rb +136 -0
- data/lib/brandish/configure/form.rb +32 -0
- data/lib/brandish/errors.rb +65 -0
- data/lib/brandish/execute.rb +26 -0
- data/lib/brandish/markup.rb +10 -0
- data/lib/brandish/markup/redcarpet.rb +14 -0
- data/lib/brandish/markup/redcarpet/format.rb +127 -0
- data/lib/brandish/markup/redcarpet/html.rb +95 -0
- data/lib/brandish/parser.rb +26 -0
- data/lib/brandish/parser/main.rb +237 -0
- data/lib/brandish/parser/node.rb +89 -0
- data/lib/brandish/parser/node/block.rb +98 -0
- data/lib/brandish/parser/node/command.rb +102 -0
- data/lib/brandish/parser/node/pair.rb +42 -0
- data/lib/brandish/parser/node/root.rb +83 -0
- data/lib/brandish/parser/node/string.rb +18 -0
- data/lib/brandish/parser/node/text.rb +114 -0
- data/lib/brandish/path_set.rb +163 -0
- data/lib/brandish/processor.rb +47 -0
- data/lib/brandish/processor/base.rb +144 -0
- data/lib/brandish/processor/block.rb +47 -0
- data/lib/brandish/processor/command.rb +47 -0
- data/lib/brandish/processor/context.rb +169 -0
- data/lib/brandish/processor/descend.rb +32 -0
- data/lib/brandish/processor/inline.rb +49 -0
- data/lib/brandish/processor/name_filter.rb +67 -0
- data/lib/brandish/processor/pair_filter.rb +96 -0
- data/lib/brandish/processors.rb +26 -0
- data/lib/brandish/processors/all.rb +19 -0
- data/lib/brandish/processors/all/comment.rb +29 -0
- data/lib/brandish/processors/all/embed.rb +56 -0
- data/lib/brandish/processors/all/if.rb +109 -0
- data/lib/brandish/processors/all/import.rb +95 -0
- data/lib/brandish/processors/all/literal.rb +42 -0
- data/lib/brandish/processors/all/verify.rb +47 -0
- data/lib/brandish/processors/common.rb +20 -0
- data/lib/brandish/processors/common/asset.rb +118 -0
- data/lib/brandish/processors/common/asset/paths.rb +93 -0
- data/lib/brandish/processors/common/group.rb +67 -0
- data/lib/brandish/processors/common/header.rb +86 -0
- data/lib/brandish/processors/common/markup.rb +127 -0
- data/lib/brandish/processors/common/output.rb +73 -0
- data/lib/brandish/processors/html.rb +18 -0
- data/lib/brandish/processors/html/group.rb +33 -0
- data/lib/brandish/processors/html/header.rb +46 -0
- data/lib/brandish/processors/html/markup.rb +131 -0
- data/lib/brandish/processors/html/output.rb +62 -0
- data/lib/brandish/processors/html/output/document.rb +127 -0
- data/lib/brandish/processors/html/script.rb +64 -0
- data/lib/brandish/processors/html/script/babel.rb +48 -0
- data/lib/brandish/processors/html/script/coffee.rb +47 -0
- data/lib/brandish/processors/html/script/vanilla.rb +45 -0
- data/lib/brandish/processors/html/style.rb +82 -0
- data/lib/brandish/processors/html/style/highlight.rb +89 -0
- data/lib/brandish/processors/html/style/sass.rb +64 -0
- data/lib/brandish/processors/html/style/vanilla.rb +71 -0
- data/lib/brandish/processors/latex.rb +15 -0
- data/lib/brandish/processors/latex/markup.rb +47 -0
- data/lib/brandish/scanner.rb +64 -0
- data/lib/brandish/version.rb +9 -0
- data/templates/initialize/Gemfile.tt +14 -0
- data/templates/initialize/brandish.config.rb.tt +49 -0
- metadata +296 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "forwardable"
|
|
5
|
+
|
|
6
|
+
module Brandish
|
|
7
|
+
# A set of paths that can be searched for a certain file. This is used for
|
|
8
|
+
# looking for certain files, like sources or templates. This can allow
|
|
9
|
+
# Brandish to provide "default" files.
|
|
10
|
+
#
|
|
11
|
+
# Despite its name, the order in which the paths are added to the pathset
|
|
12
|
+
# are important.
|
|
13
|
+
class PathSet
|
|
14
|
+
extend Forwardable
|
|
15
|
+
include Enumerable
|
|
16
|
+
|
|
17
|
+
# @!method clear
|
|
18
|
+
# Removes all of the paths from this pathset.
|
|
19
|
+
#
|
|
20
|
+
# @return [void]
|
|
21
|
+
def_delegator :@paths, :clear
|
|
22
|
+
|
|
23
|
+
# @!method each(&block)
|
|
24
|
+
# @overload each
|
|
25
|
+
# Returns an enumerable over all of the paths in the pathset.
|
|
26
|
+
#
|
|
27
|
+
# @return [::Enumerable<::Pathname>]
|
|
28
|
+
# @overload each(&block)
|
|
29
|
+
# Iterates over all of the paths in this pathset.
|
|
30
|
+
#
|
|
31
|
+
# @yield path For each path in the pathset.
|
|
32
|
+
# @yieldparam path [::Pathname] The path.
|
|
33
|
+
# @return [void]
|
|
34
|
+
def_delegator :@paths, :each
|
|
35
|
+
|
|
36
|
+
# Initialize the pathset.
|
|
37
|
+
def initialize
|
|
38
|
+
@paths = []
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Adds a path to this pathset.
|
|
42
|
+
#
|
|
43
|
+
# @param path [::String, ::Pathname]
|
|
44
|
+
# @return [self]
|
|
45
|
+
def <<(path)
|
|
46
|
+
@paths << ::Pathname.new(path)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Calls {#clear}, and then uses {#<<} to append the given path to the
|
|
50
|
+
# pathset, effectively replacing all of the paths in the pathset with the
|
|
51
|
+
# one given.
|
|
52
|
+
#
|
|
53
|
+
# @param path [::String, ::Pathname]
|
|
54
|
+
# @return [self]
|
|
55
|
+
def replace(path)
|
|
56
|
+
clear
|
|
57
|
+
self << path
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# The default options for {#find} and {#find_all}.
|
|
61
|
+
#
|
|
62
|
+
# @return [{::Symbol => ::Object}]
|
|
63
|
+
DEFAULT_FIND_OPTIONS = { file: true, allow_absolute: false }.freeze
|
|
64
|
+
|
|
65
|
+
# "Resolves" a path. This is resolved the exact same way that {#find}
|
|
66
|
+
# and {#find_all} are (with some slight variations), and so can be used
|
|
67
|
+
# as a sort of "name" for a certain path.
|
|
68
|
+
#
|
|
69
|
+
# @param path [::String, ::Pathname] The path to the file.
|
|
70
|
+
# @param options [{::Symbol => ::Object}] The options for resolution.
|
|
71
|
+
# @return [::Pathname] The resolved path.
|
|
72
|
+
def resolve(path, options = {})
|
|
73
|
+
options = DEFAULT_FIND_OPTIONS.merge(options)
|
|
74
|
+
path = ::Pathname.new(path)
|
|
75
|
+
if options[:allow_absolute]
|
|
76
|
+
path.cleanpath
|
|
77
|
+
else
|
|
78
|
+
::Pathname.new(path.expand_path("/").to_s.gsub(%r{\A(/|\\)}, ""))
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Finds a file in the pathset. If the file is returned, it is guarenteed
|
|
83
|
+
# to exist. Relative paths, that do not expand out of the relative path,
|
|
84
|
+
# are handled like you would expect - the path is appended to one of the
|
|
85
|
+
# paths in the set, and checked for existance. However, for a file that
|
|
86
|
+
# expands out of the relative path (e.g. `../a` or `a/../../b`), the
|
|
87
|
+
# behavior for expansion depends on the `allow_absolute` option. If
|
|
88
|
+
# `allow_absolute` is false (default), the path is expanded against `/`
|
|
89
|
+
# before it is joind with the paths in the set (e.g. `../a`, against
|
|
90
|
+
# `/path/to`, with `allow_absolute=false`, expands to `/path/to/a`).
|
|
91
|
+
# If `allow_absolute` is true, it directly expanding against the path
|
|
92
|
+
# (e.g. `../a`, against `/path/to`, with `allow_absolute=true`, expands
|
|
93
|
+
# to `/path/a`). `allow_absolute` should only be used if the given path
|
|
94
|
+
# is trusted. Absolute paths are handled in a similar manner; if
|
|
95
|
+
# `allow_absolute=false`, for `/a` against `/path/to`, it expands to
|
|
96
|
+
# `/path/to/a`; with `allow_absolute=true`, for `/a` against `/path/to`,
|
|
97
|
+
# it expands to `/a`.
|
|
98
|
+
#
|
|
99
|
+
# @example
|
|
100
|
+
# pathset
|
|
101
|
+
# # => #<PathSet ...>
|
|
102
|
+
# pathset.find("some/file")
|
|
103
|
+
# # => #<Pathname /path/to/some/file>
|
|
104
|
+
# pathset.find("not/real")
|
|
105
|
+
# # !> NoFileError
|
|
106
|
+
# pathset.find("/path/to/some/file")
|
|
107
|
+
# # !> NoFileError
|
|
108
|
+
# pathset.find("/path/to/some/file", allow_absolute: true)
|
|
109
|
+
# # => #<Pathname /path/to/some/file>
|
|
110
|
+
# pathset.find("../to/some/file")
|
|
111
|
+
# # !> NoFileError
|
|
112
|
+
# pathset.find("../to/some/file", allow_absolute: true)
|
|
113
|
+
# # => #<Pathname /path/to/some/file>
|
|
114
|
+
# @raise [NoFileError] If no file could be found.
|
|
115
|
+
# @param short [::String, ::Pathname] The "short" path to resolve.
|
|
116
|
+
# @param options [{::Symbol => ::Object}] The options for finding.
|
|
117
|
+
# @option (see #find_all)
|
|
118
|
+
# @return [::Pathname] The full absolute path to the file.
|
|
119
|
+
def find(short, options = {})
|
|
120
|
+
find_all(short, options).next
|
|
121
|
+
rescue ::StopIteration
|
|
122
|
+
fail NoFileError, "Could not find `#{short}' in any of the given paths (paths: #{@paths})"
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Finds all versions of the short path name in the paths in the path
|
|
126
|
+
# sets. If no block is given, it returns an enumerable; otherwise, if
|
|
127
|
+
# a block is given, it yields the joined path if it exists.
|
|
128
|
+
#
|
|
129
|
+
# @raise NoFileError If no file could be found.
|
|
130
|
+
# @param short [::String, ::Pathname] The "short" path to resolve.
|
|
131
|
+
# @param options [{::Symbol => ::Object}] The options for finding.
|
|
132
|
+
# @option options [Boolean] :allow_absolute (false)
|
|
133
|
+
# @option options [Boolean] :file (true) Whether or not the full path
|
|
134
|
+
# must be a file for it to be considered existant. This should be set
|
|
135
|
+
# to true, because in most cases, it's the desired behavior.
|
|
136
|
+
# @yield [path] For every file that exists.
|
|
137
|
+
# @yieldparam path [::Pathname] The path to the file. This is guarenteed
|
|
138
|
+
# to exist.
|
|
139
|
+
# @return [void]
|
|
140
|
+
def find_all(short, options = {})
|
|
141
|
+
return to_enum(:find_all, short, options) unless block_given?
|
|
142
|
+
short = ::Pathname.new(short)
|
|
143
|
+
options = DEFAULT_FIND_OPTIONS.merge(options)
|
|
144
|
+
|
|
145
|
+
@paths.reverse.each do |path|
|
|
146
|
+
joined = path_join(path, short, options)
|
|
147
|
+
yield joined if (options[:file] && joined.file?) || joined.exist?
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
nil
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
private
|
|
154
|
+
|
|
155
|
+
def path_join(path, short, options)
|
|
156
|
+
if options[:allow_absolute]
|
|
157
|
+
short.expand_path(path)
|
|
158
|
+
else
|
|
159
|
+
::Pathname.new(::File.join(path, short.expand_path("/")))
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "brandish/processor/base"
|
|
5
|
+
require "brandish/processor/context"
|
|
6
|
+
require "brandish/processor/name_filter"
|
|
7
|
+
require "brandish/processor/block"
|
|
8
|
+
require "brandish/processor/command"
|
|
9
|
+
require "brandish/processor/descend"
|
|
10
|
+
|
|
11
|
+
module Brandish
|
|
12
|
+
# Processors for Brandish. These just handle reshaping nodes so that they
|
|
13
|
+
# output nicely. This can be used for things like including, bold tags,
|
|
14
|
+
# etc.
|
|
15
|
+
module Processor
|
|
16
|
+
# A structure containing all of the processors available. This is a key
|
|
17
|
+
# value store, with the key being the format and the name, and the value
|
|
18
|
+
# being the actual processor.
|
|
19
|
+
#
|
|
20
|
+
# @return [{(::Symbol, ::Symbol) => Processor::Base}]
|
|
21
|
+
def self.all
|
|
22
|
+
@_processors ||= ::Hash.new
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Registers processors with the global registry. This interns the format
|
|
26
|
+
# and name of the processor. If the format and name pair already exists,
|
|
27
|
+
# it raises a {ProcessorError}.
|
|
28
|
+
#
|
|
29
|
+
# @example
|
|
30
|
+
# Processor.register [:html, :stripper] => self
|
|
31
|
+
# @example
|
|
32
|
+
# Processor.register [:all, :descend] => self
|
|
33
|
+
# @raise [ProcessorError] If one of the format and name pairs already
|
|
34
|
+
# exists.
|
|
35
|
+
# @param map [{(::Symbol, ::Symbol) => Processor::Base}] The processors to
|
|
36
|
+
# register.
|
|
37
|
+
# @return [void]
|
|
38
|
+
def self.register(map)
|
|
39
|
+
map.each do |(format, name), processor|
|
|
40
|
+
format, name = format.intern, name.intern
|
|
41
|
+
fail ProcessorError, "#{format}:#{name} already exists" \
|
|
42
|
+
if all.key?([format, name])
|
|
43
|
+
all[[format, name]] = processor
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Brandish
|
|
5
|
+
module Processor
|
|
6
|
+
# A processor. This responds to a set of methods that return updated
|
|
7
|
+
# versions of the nodes that are passed to them. Processors are all
|
|
8
|
+
# initialized at the same time, with a context. The processor is expected
|
|
9
|
+
# to add an object that responds to #call with arity matching `1` to the
|
|
10
|
+
# context using {Context#<<}. The processor is allowed to add any number
|
|
11
|
+
# of objects to the context using this, if need be; by default, the
|
|
12
|
+
# processor just adds itself.
|
|
13
|
+
#
|
|
14
|
+
# @abstract
|
|
15
|
+
# This class is not designed to be used and instantiated directly; this
|
|
16
|
+
# just provides common behavior for a processor. This class should be
|
|
17
|
+
# subclassed and proper behavior defined on a subclass.
|
|
18
|
+
class Base
|
|
19
|
+
# (see Processor.register)
|
|
20
|
+
def self.register(map)
|
|
21
|
+
Processor.register(map)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# The context associated with this processor.
|
|
25
|
+
#
|
|
26
|
+
# @return [Context]
|
|
27
|
+
attr_reader :context
|
|
28
|
+
|
|
29
|
+
# Initializes the processor with the given context. This adds the
|
|
30
|
+
# processor to the context, and sets the context for use on the
|
|
31
|
+
# processor.
|
|
32
|
+
#
|
|
33
|
+
# @param context [Context]
|
|
34
|
+
# @param options [::Object] The options for this processor.
|
|
35
|
+
def initialize(context, options = {})
|
|
36
|
+
@context = context
|
|
37
|
+
@context << self
|
|
38
|
+
@options = options
|
|
39
|
+
setup
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# This is called by {#initialize}. This allows subclasses to perform
|
|
43
|
+
# any nessicary setups without having to override {#initialize}. This
|
|
44
|
+
# does nothing by default.
|
|
45
|
+
#
|
|
46
|
+
# @return [void]
|
|
47
|
+
def setup; end
|
|
48
|
+
|
|
49
|
+
# Processes the given node. By default, it checks the classes of the
|
|
50
|
+
# inbound node, and maps them to `process_*` blocks. If it doesn't
|
|
51
|
+
# match, an `ArgumentError` is thrown.
|
|
52
|
+
#
|
|
53
|
+
# If this function returns a `nil` value, the node should be ignored.
|
|
54
|
+
# {Context#accept} acknowledges this, and skips over the remaining
|
|
55
|
+
# processors once a processor returns a `nil` value for a node.
|
|
56
|
+
#
|
|
57
|
+
# @raise [::ArgumentError] if the node given isn't one of
|
|
58
|
+
# {Parser::Node::Block}, {Parser::Node::Command}, {Parser::Node::Root},
|
|
59
|
+
# or {Parser::Node::Text}.
|
|
60
|
+
# @param node [Parser::Node] A parser node to handle.
|
|
61
|
+
# @return [Parser::Node, nil] The result of processing.
|
|
62
|
+
def call(node)
|
|
63
|
+
_fix_result(_switch_node(node), node)
|
|
64
|
+
rescue LocationError then fail
|
|
65
|
+
rescue => e
|
|
66
|
+
fail BuildError.new("#{e.class}: #{e.message}", node.location,
|
|
67
|
+
e.backtrace)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# (see Context#accept)
|
|
71
|
+
def accept(node)
|
|
72
|
+
context.accept(node)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Processes a block. By default, this performs no modifications on the
|
|
76
|
+
# node, and returns the node itself.
|
|
77
|
+
#
|
|
78
|
+
# @param node [Parser::Node::Block]
|
|
79
|
+
# @return [::Object]
|
|
80
|
+
def process_block(node)
|
|
81
|
+
node
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Processes a command. By default, this performs no modifications on the
|
|
85
|
+
# node, and returns the node itself.
|
|
86
|
+
#
|
|
87
|
+
# @param node [Parser::Node::Command]
|
|
88
|
+
# @return [::Object]
|
|
89
|
+
def process_command(node)
|
|
90
|
+
node
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Processes a root node. By default, this performs no modifications on
|
|
94
|
+
# the node, and returns the node itself.
|
|
95
|
+
#
|
|
96
|
+
# @param node [Parser::Node::Root]
|
|
97
|
+
# @return [::Object]
|
|
98
|
+
def process_root(node)
|
|
99
|
+
node
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Processes a text node. By default, this performs no modifications on
|
|
103
|
+
# the node, and returns the node itself.
|
|
104
|
+
#
|
|
105
|
+
# @param node [Parser::Node::Text]
|
|
106
|
+
# @return [::Object]
|
|
107
|
+
def process_text(node)
|
|
108
|
+
node
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# An optional post-process.
|
|
112
|
+
#
|
|
113
|
+
# @param root [Parser::Node::Root]
|
|
114
|
+
# @return [void]
|
|
115
|
+
def postprocess(root); end
|
|
116
|
+
|
|
117
|
+
private
|
|
118
|
+
|
|
119
|
+
def _switch_node(node)
|
|
120
|
+
case node
|
|
121
|
+
when Parser::Node::Block then process_block(node)
|
|
122
|
+
when Parser::Node::Command then process_command(node)
|
|
123
|
+
when Parser::Node::Root then process_root(node)
|
|
124
|
+
when Parser::Node::Text then process_text(node)
|
|
125
|
+
else
|
|
126
|
+
fail ArgumentError, "Expected node, got `#{node.class}'"
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def _fix_result(result, node)
|
|
131
|
+
case result
|
|
132
|
+
when Parser::Node, nil
|
|
133
|
+
result
|
|
134
|
+
when ::String
|
|
135
|
+
Parser::Node::Text.new(value: result, location: node.location)
|
|
136
|
+
.prevent_update
|
|
137
|
+
else
|
|
138
|
+
fail ArgumentError, "Unknown result type `#{result.class}' " \
|
|
139
|
+
"(given from #{self.class})"
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Brandish
|
|
5
|
+
module Processor
|
|
6
|
+
# A block processor. This is designed to act over a base to modify
|
|
7
|
+
# one specific block. The block name itself is specified on the
|
|
8
|
+
# class, and the class provides logic to only modify block nodes with
|
|
9
|
+
# the same name.
|
|
10
|
+
module Block
|
|
11
|
+
# Ruby hook.
|
|
12
|
+
#
|
|
13
|
+
# @api private
|
|
14
|
+
# @return [void]
|
|
15
|
+
def self.included(base)
|
|
16
|
+
base.include Processor::NameFilter
|
|
17
|
+
base.include Processor::Pairfilter
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Processes the block. If the node's name doesn't match the name for
|
|
21
|
+
# this class, it passes it on up to {Base#process_block}; otherwise,
|
|
22
|
+
# it passes it over to {#perform}.
|
|
23
|
+
#
|
|
24
|
+
# @param node [Parser::Node::Block]
|
|
25
|
+
# @return [::Object]
|
|
26
|
+
def process_block(node)
|
|
27
|
+
return super unless allowed_names.include?(node.name)
|
|
28
|
+
@node = node
|
|
29
|
+
@name = node.name
|
|
30
|
+
@pairs = node.pairs
|
|
31
|
+
@body = node.body
|
|
32
|
+
|
|
33
|
+
assert_valid_pairs
|
|
34
|
+
perform
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Performs the command adjustment. This must be subclassed and
|
|
38
|
+
# overwritten.
|
|
39
|
+
#
|
|
40
|
+
# @abstract
|
|
41
|
+
# @return [::Object]
|
|
42
|
+
def perform
|
|
43
|
+
fail NotImplementedError, "Please implement #{self.class}#perform"
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Brandish
|
|
5
|
+
module Processor
|
|
6
|
+
# A command processor. This is designed to act over a base to modify
|
|
7
|
+
# one specific command. The command name itself is specified on the
|
|
8
|
+
# class, and the class provides logic to only modify command nodes with
|
|
9
|
+
# the same name.
|
|
10
|
+
module Command
|
|
11
|
+
# Ruby hook.
|
|
12
|
+
#
|
|
13
|
+
# @api private
|
|
14
|
+
# @return [void]
|
|
15
|
+
def self.included(base)
|
|
16
|
+
base.include Processor::NameFilter
|
|
17
|
+
base.include Processor::PairFilter
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Processes the command. If the node's name doesn't match the name for
|
|
21
|
+
# this class, it passes it on up to {Base#process_command}; otherwise,
|
|
22
|
+
# it passes it over to {#perform}.
|
|
23
|
+
#
|
|
24
|
+
# @param node [Parser::Node::Command]
|
|
25
|
+
# @return [::Object]
|
|
26
|
+
def process_command(node)
|
|
27
|
+
return super unless allowed_names.include?(node.name)
|
|
28
|
+
@node = node
|
|
29
|
+
@name = node.name
|
|
30
|
+
@pairs = node.pairs
|
|
31
|
+
@body = nil
|
|
32
|
+
|
|
33
|
+
assert_valid_pairs
|
|
34
|
+
perform
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Performs the command adjustment. This must be subclassed and
|
|
38
|
+
# overwritten.
|
|
39
|
+
#
|
|
40
|
+
# @abstract
|
|
41
|
+
# @return [::Object]
|
|
42
|
+
def perform
|
|
43
|
+
fail NotImplementedError, "Please implement #{self.class}#perform"
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|