inversion 1.3.1 → 1.4.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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/Examples.md +134 -0
- data/GettingStarted.md +50 -0
- data/Guide.md +14 -0
- data/{History.rdoc → History.md} +52 -43
- data/{README.rdoc → README.md} +43 -34
- data/Tags.md +555 -0
- data/bin/inversion +4 -8
- data/lib/inversion/cli/api.rb +75 -0
- data/lib/inversion/cli/tagtokens.rb +34 -0
- data/lib/inversion/cli/tree.rb +70 -0
- data/lib/inversion/cli.rb +406 -0
- data/lib/inversion/exceptions.rb +0 -1
- data/lib/inversion/mixins.rb +10 -11
- data/lib/inversion/parser.rb +5 -6
- data/lib/inversion/refinements.rb +18 -0
- data/lib/inversion/renderstate.rb +24 -25
- data/lib/inversion/sinatra.rb +0 -1
- data/lib/inversion/template/attrtag.rb +7 -5
- data/lib/inversion/template/begintag.rb +0 -1
- data/lib/inversion/template/calltag.rb +0 -1
- data/lib/inversion/template/codetag.rb +37 -28
- data/lib/inversion/template/commenttag.rb +0 -1
- data/lib/inversion/template/configtag.rb +3 -4
- data/lib/inversion/template/containertag.rb +1 -2
- data/lib/inversion/template/defaulttag.rb +1 -2
- data/lib/inversion/template/elsetag.rb +0 -1
- data/lib/inversion/template/elsiftag.rb +0 -1
- data/lib/inversion/template/endtag.rb +2 -3
- data/lib/inversion/template/escapetag.rb +1 -2
- data/lib/inversion/template/fortag.rb +2 -3
- data/lib/inversion/template/fragmenttag.rb +1 -2
- data/lib/inversion/template/iftag.rb +3 -1
- data/lib/inversion/template/importtag.rb +2 -3
- data/lib/inversion/template/includetag.rb +1 -2
- data/lib/inversion/template/node.rb +4 -5
- data/lib/inversion/template/pptag.rb +1 -2
- data/lib/inversion/template/publishtag.rb +2 -3
- data/lib/inversion/template/rescuetag.rb +1 -2
- data/lib/inversion/template/subscribetag.rb +3 -4
- data/lib/inversion/template/tag.rb +3 -4
- data/lib/inversion/template/textnode.rb +1 -2
- data/lib/inversion/template/timedeltatag.rb +1 -2
- data/lib/inversion/template/unlesstag.rb +0 -1
- data/lib/inversion/template/uriencodetag.rb +1 -2
- data/lib/inversion/template/yieldtag.rb +0 -1
- data/lib/inversion/template.rb +18 -22
- data/lib/inversion/tilt.rb +1 -2
- data/lib/inversion.rb +2 -3
- data/spec/helpers.rb +19 -13
- data/spec/inversion/mixins_spec.rb +1 -1
- data/spec/inversion/monkeypatches_spec.rb +1 -1
- data/spec/inversion/parser_spec.rb +1 -1
- data/spec/inversion/renderstate_spec.rb +1 -1
- data/spec/inversion/sinatra_spec.rb +1 -1
- data/spec/inversion/template/attrtag_spec.rb +1 -1
- data/spec/inversion/template/begintag_spec.rb +1 -1
- data/spec/inversion/template/calltag_spec.rb +1 -1
- data/spec/inversion/template/codetag_spec.rb +24 -1
- data/spec/inversion/template/commenttag_spec.rb +1 -1
- data/spec/inversion/template/configtag_spec.rb +1 -1
- data/spec/inversion/template/containertag_spec.rb +1 -1
- data/spec/inversion/template/defaulttag_spec.rb +1 -1
- data/spec/inversion/template/elsetag_spec.rb +1 -1
- data/spec/inversion/template/elsiftag_spec.rb +1 -1
- data/spec/inversion/template/endtag_spec.rb +1 -1
- data/spec/inversion/template/escapetag_spec.rb +1 -1
- data/spec/inversion/template/fortag_spec.rb +1 -1
- data/spec/inversion/template/fragmenttag_spec.rb +1 -1
- data/spec/inversion/template/iftag_spec.rb +1 -1
- data/spec/inversion/template/importtag_spec.rb +1 -1
- data/spec/inversion/template/includetag_spec.rb +1 -1
- data/spec/inversion/template/node_spec.rb +1 -1
- data/spec/inversion/template/pptag_spec.rb +1 -1
- data/spec/inversion/template/publishtag_spec.rb +1 -1
- data/spec/inversion/template/rescuetag_spec.rb +1 -1
- data/spec/inversion/template/subscribetag_spec.rb +1 -1
- data/spec/inversion/template/tag_spec.rb +1 -1
- data/spec/inversion/template/textnode_spec.rb +1 -1
- data/spec/inversion/template/timedeltatag_spec.rb +1 -1
- data/spec/inversion/template/unlesstag_spec.rb +1 -1
- data/spec/inversion/template/uriencodetag_spec.rb +1 -1
- data/spec/inversion/template/yieldtag_spec.rb +1 -1
- data/spec/inversion/template_spec.rb +1 -1
- data/spec/inversion/tilt_spec.rb +1 -1
- data/spec/inversion_spec.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +59 -45
- metadata.gz.sig +0 -0
- data/Examples.rdoc +0 -134
- data/GettingStarted.rdoc +0 -44
- data/Guide.rdoc +0 -47
- data/Manifest.txt +0 -86
- data/Rakefile +0 -7
- data/Tags.rdoc +0 -560
- data/lib/inversion/command.rb +0 -278
- data/lib/inversion/monkeypatches.rb +0 -21
@@ -0,0 +1,70 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'inversion'
|
4
|
+
require 'inversion/cli'
|
5
|
+
|
6
|
+
|
7
|
+
# Tree command
|
8
|
+
module Inversion::CLI::TreeCommand
|
9
|
+
extend Inversion::CLI::Subcommand
|
10
|
+
|
11
|
+
|
12
|
+
desc "Dump the node tree of a template."
|
13
|
+
long_desc %{
|
14
|
+
Load, parse, and dump the resulting node tree of a given
|
15
|
+
Inversion template. This is mostly useful for debugging custom
|
16
|
+
tags, but can also make it easier to diagnose strange template
|
17
|
+
behavior.
|
18
|
+
}
|
19
|
+
arg :TEMPLATE_PATH
|
20
|
+
command :tree do |tree|
|
21
|
+
|
22
|
+
tree.action do |globals, options, args|
|
23
|
+
path = args.first or exit_now!( "No template specified!" )
|
24
|
+
|
25
|
+
template = self.load_template( path ) or exit_now!('Template failed to load.')
|
26
|
+
|
27
|
+
self.output_blank_line
|
28
|
+
self.output_template_header( template )
|
29
|
+
self.output_template_nodes( template.node_tree )
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
###############
|
36
|
+
module_function
|
37
|
+
###############
|
38
|
+
|
39
|
+
### Output the given `tree` of nodes at the specified `indent` level.
|
40
|
+
def output_template_nodes( tree, indent=0 )
|
41
|
+
indenttxt = ' ' * indent
|
42
|
+
tree.each do |node|
|
43
|
+
self.prompt.say( indenttxt + node.as_comment_body )
|
44
|
+
self.output_template_nodes( node.subnodes, indent+4 ) if node.is_container?
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
### Dump the node tree of the given `templates`.
|
50
|
+
def dump_node_trees( templates )
|
51
|
+
templates.each do |path|
|
52
|
+
template = self.load_template( path )
|
53
|
+
self.output_blank_line
|
54
|
+
self.output_template_header( template )
|
55
|
+
self.output_template_nodes( template.node_tree )
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
### Output the given `tree` of nodes at the specified `indent` level.
|
61
|
+
def output_template_nodes( tree, indent=0 )
|
62
|
+
indenttxt = ' ' * indent
|
63
|
+
tree.each do |node|
|
64
|
+
self.prompt.say( indenttxt + node.as_comment_body )
|
65
|
+
self.output_template_nodes( node.subnodes, indent+4 ) if node.is_container?
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end # module Inversion::CLI::TreeCommand
|
70
|
+
|
@@ -0,0 +1,406 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
# vim: set noet nosta sw=4 ts=4 :
|
3
|
+
|
4
|
+
require 'loggability'
|
5
|
+
require 'gli'
|
6
|
+
require 'tty/prompt'
|
7
|
+
require 'tty/table'
|
8
|
+
require 'pastel'
|
9
|
+
|
10
|
+
require 'inversion' unless defined?( Inversion )
|
11
|
+
require 'inversion/mixins'
|
12
|
+
|
13
|
+
|
14
|
+
# Command class for the 'inversion' command-line tool.
|
15
|
+
class Inversion::CLI
|
16
|
+
extend Loggability,
|
17
|
+
Inversion::MethodUtilities,
|
18
|
+
GLI::App
|
19
|
+
|
20
|
+
|
21
|
+
# Write logs to Assemblage's logger
|
22
|
+
log_to :inversion
|
23
|
+
|
24
|
+
|
25
|
+
#
|
26
|
+
# GLI
|
27
|
+
#
|
28
|
+
|
29
|
+
# Set up global[:description] and options
|
30
|
+
program_desc 'Inversion'
|
31
|
+
|
32
|
+
# The command version
|
33
|
+
version Inversion::VERSION
|
34
|
+
|
35
|
+
# Use an OpenStruct for options instead of a Hash
|
36
|
+
use_openstruct( true )
|
37
|
+
|
38
|
+
# Subcommand options are independent of global[:ones]
|
39
|
+
subcommand_option_handling :normal
|
40
|
+
|
41
|
+
# Strict argument validation
|
42
|
+
arguments :strict
|
43
|
+
|
44
|
+
|
45
|
+
# Custom parameter types
|
46
|
+
accept Array do |value|
|
47
|
+
value.strip.split(/\s*,\s*/)
|
48
|
+
end
|
49
|
+
accept Pathname do |value|
|
50
|
+
Pathname( value.strip )
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
# Global options
|
55
|
+
desc 'Enable debugging output'
|
56
|
+
switch [:d, :debug]
|
57
|
+
|
58
|
+
desc 'Enable verbose output'
|
59
|
+
switch [:v, :verbose]
|
60
|
+
|
61
|
+
desc 'Set log level to LEVEL (one of %s)' % [Loggability::LOG_LEVELS.keys.join(', ')]
|
62
|
+
arg_name :LEVEL
|
63
|
+
flag [:l, :loglevel], must_match: Loggability::LOG_LEVELS.keys
|
64
|
+
|
65
|
+
desc 'Ignore unknown tags instead of displaying an error'
|
66
|
+
switch 'ignore-unknown-tags'
|
67
|
+
|
68
|
+
desc 'Add one or more PATHS to the template search path'
|
69
|
+
arg_name :PATH
|
70
|
+
flag [:p, :path], type: Pathname, multiple: true
|
71
|
+
|
72
|
+
|
73
|
+
#
|
74
|
+
# GLI Event callbacks
|
75
|
+
#
|
76
|
+
|
77
|
+
# Set up global options
|
78
|
+
pre do |global, command, options, args|
|
79
|
+
self.set_logging_level( global[:l] )
|
80
|
+
Loggability.format_with( :color ) if $stdout.tty?
|
81
|
+
|
82
|
+
|
83
|
+
# Include a 'lib' directory if there is one
|
84
|
+
$LOAD_PATH.unshift( 'lib' ) if File.directory?( 'lib' )
|
85
|
+
|
86
|
+
self.setup_pastel_aliases
|
87
|
+
self.setup_output( global )
|
88
|
+
|
89
|
+
# Configure Inversion's strictness
|
90
|
+
Inversion::Template.configure(
|
91
|
+
:ignore_unknown_tags => global.ignore_unknown_tags,
|
92
|
+
:template_paths => global.path,
|
93
|
+
)
|
94
|
+
|
95
|
+
true
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
# Write the error to the log on exceptions.
|
100
|
+
on_error do |exception|
|
101
|
+
|
102
|
+
case exception
|
103
|
+
when OptionParser::ParseError, GLI::CustomExit
|
104
|
+
msg = exception.full_message(highlight: false, order: :bottom)
|
105
|
+
self.log.debug( msg )
|
106
|
+
else
|
107
|
+
msg = exception.full_message(highlight: true, order: :bottom)
|
108
|
+
self.log.error( msg )
|
109
|
+
end
|
110
|
+
|
111
|
+
true
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
|
116
|
+
|
117
|
+
##
|
118
|
+
# Registered subcommand modules
|
119
|
+
singleton_attr_accessor :subcommand_modules
|
120
|
+
|
121
|
+
|
122
|
+
### Overridden -- Add registered subcommands immediately before running.
|
123
|
+
def self::run( * )
|
124
|
+
self.add_registered_subcommands
|
125
|
+
super
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
### Add the specified `mod`ule containing subcommands to the 'inversion' command.
|
130
|
+
def self::register_subcommands( mod )
|
131
|
+
self.subcommand_modules ||= []
|
132
|
+
self.subcommand_modules.push( mod )
|
133
|
+
mod.extend( GLI::DSL, GLI::AppSupport, Loggability )
|
134
|
+
mod.log_to( :inversion )
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
### Add the commands from the registered subcommand modules.
|
139
|
+
def self::add_registered_subcommands
|
140
|
+
self.subcommand_modules ||= []
|
141
|
+
self.subcommand_modules.each do |mod|
|
142
|
+
merged_commands = mod.commands.merge( self.commands )
|
143
|
+
self.commands.update( merged_commands )
|
144
|
+
command_objs = self.commands_declaration_order | self.commands.values
|
145
|
+
self.commands_declaration_order.replace( command_objs )
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
|
150
|
+
### Return the Pastel colorizer.
|
151
|
+
###
|
152
|
+
def self::pastel
|
153
|
+
@pastel ||= Pastel.new( enabled: $stdout.tty? )
|
154
|
+
end
|
155
|
+
|
156
|
+
|
157
|
+
### Return the TTY prompt used by the command to communicate with the
|
158
|
+
### user.
|
159
|
+
def self::prompt
|
160
|
+
@prompt ||= TTY::Prompt.new( output: $stderr )
|
161
|
+
end
|
162
|
+
|
163
|
+
|
164
|
+
### Discard the existing HighLine prompt object if one existed. Mostly useful for
|
165
|
+
### testing.
|
166
|
+
def self::reset_prompt
|
167
|
+
@prompt = nil
|
168
|
+
end
|
169
|
+
|
170
|
+
|
171
|
+
### Set the global logging `level` if it's defined.
|
172
|
+
def self::set_logging_level( level=nil )
|
173
|
+
if level
|
174
|
+
Loggability.level = level.to_sym
|
175
|
+
else
|
176
|
+
Loggability.level = :fatal
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
|
181
|
+
### Load any additional Ruby libraries given with the -r global option.
|
182
|
+
def self::require_additional_libs( requires)
|
183
|
+
requires.each do |path|
|
184
|
+
path = "inversion/#{path}" unless path.start_with?( 'inversion/' )
|
185
|
+
require( path )
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
|
190
|
+
### Setup pastel color aliases
|
191
|
+
###
|
192
|
+
def self::setup_pastel_aliases
|
193
|
+
self.pastel.alias_color( :headline, :bold, :white, :on_black )
|
194
|
+
self.pastel.alias_color( :success, :bold, :green )
|
195
|
+
self.pastel.alias_color( :error, :bold, :red )
|
196
|
+
self.pastel.alias_color( :up, :green )
|
197
|
+
self.pastel.alias_color( :down, :red )
|
198
|
+
self.pastel.alias_color( :unknown, :dark, :yellow )
|
199
|
+
self.pastel.alias_color( :disabled, :dark, :white )
|
200
|
+
self.pastel.alias_color( :quieted, :dark, :green )
|
201
|
+
self.pastel.alias_color( :acked, :yellow )
|
202
|
+
self.pastel.alias_color( :highlight, :bold, :yellow )
|
203
|
+
self.pastel.alias_color( :search_hit, :black, :on_white )
|
204
|
+
self.pastel.alias_color( :prompt, :cyan )
|
205
|
+
self.pastel.alias_color( :even_row, :bold )
|
206
|
+
self.pastel.alias_color( :odd_row, :reset )
|
207
|
+
end
|
208
|
+
|
209
|
+
|
210
|
+
### Set up the output levels and globals based on the associated `global` options.
|
211
|
+
def self::setup_output( global )
|
212
|
+
|
213
|
+
if global[:verbose]
|
214
|
+
$VERBOSE = true
|
215
|
+
Loggability.level = :info
|
216
|
+
end
|
217
|
+
|
218
|
+
if global[:debug]
|
219
|
+
$DEBUG = true
|
220
|
+
Loggability.level = :debug
|
221
|
+
end
|
222
|
+
|
223
|
+
if global[:loglevel]
|
224
|
+
Loggability.level = global[:loglevel]
|
225
|
+
end
|
226
|
+
|
227
|
+
end
|
228
|
+
|
229
|
+
|
230
|
+
#
|
231
|
+
# GLI subcommands
|
232
|
+
#
|
233
|
+
|
234
|
+
|
235
|
+
# Convenience module for subcommand registration syntax sugar.
|
236
|
+
module Subcommand
|
237
|
+
|
238
|
+
### Extension callback -- register the extending object as a subcommand.
|
239
|
+
def self::extended( mod )
|
240
|
+
Inversion::CLI.log.debug "Registering subcommands from %p" % [ mod ]
|
241
|
+
Inversion::CLI.register_subcommands( mod )
|
242
|
+
end
|
243
|
+
|
244
|
+
|
245
|
+
###############
|
246
|
+
module_function
|
247
|
+
###############
|
248
|
+
|
249
|
+
### Exit with the specified `exit_code` after printing the given `message`.
|
250
|
+
def exit_now!( message, exit_code=1 )
|
251
|
+
raise GLI::CustomExit.new( message, exit_code )
|
252
|
+
end
|
253
|
+
|
254
|
+
|
255
|
+
### Exit with a helpful `message` and display the usage.
|
256
|
+
def help_now!( message=nil )
|
257
|
+
exception = OptionParser::ParseError.new( message )
|
258
|
+
def exception.exit_code; 64; end
|
259
|
+
|
260
|
+
raise exception
|
261
|
+
end
|
262
|
+
|
263
|
+
|
264
|
+
### Get the prompt (a TTY::Prompt object)
|
265
|
+
def prompt
|
266
|
+
return Inversion::CLI.prompt
|
267
|
+
end
|
268
|
+
|
269
|
+
|
270
|
+
### Return the global Pastel object for convenient formatting, color, etc.
|
271
|
+
def hl
|
272
|
+
return Inversion::CLI.pastel
|
273
|
+
end
|
274
|
+
|
275
|
+
|
276
|
+
### Return the specified `string` in the 'headline' ANSI color.
|
277
|
+
def headline_string( string )
|
278
|
+
return hl.headline( string )
|
279
|
+
end
|
280
|
+
|
281
|
+
|
282
|
+
### Return the specified `string` in the 'highlight' ANSI color.
|
283
|
+
def highlight_string( string )
|
284
|
+
return hl.highlight( string )
|
285
|
+
end
|
286
|
+
|
287
|
+
|
288
|
+
### Return the specified `string` in the 'success' ANSI color.
|
289
|
+
def success_string( string )
|
290
|
+
return hl.success( string )
|
291
|
+
end
|
292
|
+
|
293
|
+
|
294
|
+
### Return the specified `string` in the 'error' ANSI color.
|
295
|
+
def error_string( string )
|
296
|
+
return hl.error( string )
|
297
|
+
end
|
298
|
+
|
299
|
+
|
300
|
+
### Output a table with the given `header` (an array) and `rows`
|
301
|
+
### (an array of arrays).
|
302
|
+
def display_table( header, rows )
|
303
|
+
table = TTY::Table.new( header, rows )
|
304
|
+
renderer = nil
|
305
|
+
|
306
|
+
if hl.enabled?
|
307
|
+
renderer = TTY::Table::Renderer::Unicode.new(
|
308
|
+
table,
|
309
|
+
multiline: true,
|
310
|
+
padding: [0,1,0,1]
|
311
|
+
)
|
312
|
+
renderer.border.style = :dim
|
313
|
+
|
314
|
+
else
|
315
|
+
renderer = TTY::Table::Renderer::ASCII.new(
|
316
|
+
table,
|
317
|
+
multiline: true,
|
318
|
+
padding: [0,1,0,1]
|
319
|
+
)
|
320
|
+
end
|
321
|
+
|
322
|
+
puts renderer.render
|
323
|
+
end
|
324
|
+
|
325
|
+
|
326
|
+
### Display the given list of `items`.
|
327
|
+
def display_list( items )
|
328
|
+
items.flatten.each do |item|
|
329
|
+
self.prompt.say( "- %s" % [ self.highlight_string(item) ] )
|
330
|
+
end
|
331
|
+
|
332
|
+
end
|
333
|
+
|
334
|
+
|
335
|
+
### Return the count of visible (i.e., non-control) characters in the given `string`.
|
336
|
+
def visible_chars( string )
|
337
|
+
return string.to_s.gsub(/\e\[.*?m/, '').scan( /\P{Cntrl}/ ).size
|
338
|
+
end
|
339
|
+
|
340
|
+
|
341
|
+
### In dry-run mode, output the description instead of running the provided block and
|
342
|
+
### return the `return_value`.
|
343
|
+
### If dry-run mode is not enabled, yield to the block.
|
344
|
+
def unless_dryrun( description, return_value=true )
|
345
|
+
if $DRYRUN
|
346
|
+
self.log.warn( "DRYRUN> #{description}" )
|
347
|
+
return return_value
|
348
|
+
else
|
349
|
+
return yield
|
350
|
+
end
|
351
|
+
end
|
352
|
+
alias_method :unless_dry_run, :unless_dryrun
|
353
|
+
|
354
|
+
|
355
|
+
|
356
|
+
### Load the Inversion::Template from the specified `tmplpath` and return it. If there
|
357
|
+
### is an error loading the template, output the error and return `nil`.
|
358
|
+
def load_template( tmplpath )
|
359
|
+
template = Inversion::Template.load( tmplpath )
|
360
|
+
return template
|
361
|
+
rescue Errno => err
|
362
|
+
self.prompt.say "Failed to load %s: %s" % [ tmplpath, err.message ]
|
363
|
+
return nil
|
364
|
+
rescue Inversion::ParseError => err
|
365
|
+
self.prompt.say "%s: Invalid template: %p: %s" %
|
366
|
+
[ tmplpath, err.class, err.message ]
|
367
|
+
self.prompt.say( err.backtrace.join("\n ") ) if $DEBUG
|
368
|
+
return nil
|
369
|
+
end
|
370
|
+
|
371
|
+
|
372
|
+
### Output a blank line
|
373
|
+
def output_blank_line
|
374
|
+
self.prompt.say( "\n" )
|
375
|
+
end
|
376
|
+
|
377
|
+
|
378
|
+
### Output a header between each template.
|
379
|
+
def output_template_header( template )
|
380
|
+
header_info = "%s (%0.2fK, %s)" %
|
381
|
+
[ template.source_file, template.source.bytesize/1024.0, template.source.encoding ]
|
382
|
+
header_line = "-- %s" % [ header_info ]
|
383
|
+
self.prompt.say( headline_string header_line )
|
384
|
+
end
|
385
|
+
|
386
|
+
|
387
|
+
### Output a subheader with the given `caption`.
|
388
|
+
def output_subheader( caption )
|
389
|
+
self.prompt.say( highlight_string caption )
|
390
|
+
end
|
391
|
+
|
392
|
+
end # module Subcommand
|
393
|
+
|
394
|
+
|
395
|
+
### Load commands from any files in the specified directory relative to LOAD_PATHs
|
396
|
+
def self::commands_from( subdir )
|
397
|
+
Gem.find_latest_files( File.join(subdir, '*.rb') ).each do |rbfile|
|
398
|
+
self.log.debug " loading %s..." % [ rbfile ]
|
399
|
+
require( rbfile )
|
400
|
+
end
|
401
|
+
end
|
402
|
+
|
403
|
+
|
404
|
+
commands_from 'inversion/cli'
|
405
|
+
|
406
|
+
end # class Inversion::CLI
|
data/lib/inversion/exceptions.rb
CHANGED
data/lib/inversion/mixins.rb
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
# -*- ruby -*-
|
2
|
-
# frozen_string_literal: true
|
3
2
|
# vim: set noet nosta sw=4 ts=4 :
|
4
3
|
|
5
4
|
require 'tempfile'
|
6
5
|
|
7
6
|
module Inversion
|
8
7
|
|
9
|
-
# Hides your class's ::new method and adds a
|
8
|
+
# Hides your class's ::new method and adds a `pure_virtual` method generator for
|
10
9
|
# defining API methods. If subclasses of your class don't provide implementations of
|
11
10
|
# "pure_virtual" methods, NotImplementedErrors will be raised if they are called.
|
12
11
|
#
|
@@ -67,7 +66,7 @@ module Inversion
|
|
67
66
|
module_function
|
68
67
|
###############
|
69
68
|
|
70
|
-
### Return a version of the given
|
69
|
+
### Return a version of the given `hash` with its keys transformed
|
71
70
|
### into Strings from whatever they were before.
|
72
71
|
###
|
73
72
|
### stringhash = stringify_keys( symbolhash )
|
@@ -87,7 +86,7 @@ module Inversion
|
|
87
86
|
end
|
88
87
|
|
89
88
|
|
90
|
-
### Return a duplicate of the given
|
89
|
+
### Return a duplicate of the given `hash` with its identifier-like keys
|
91
90
|
### transformed into symbols from whatever they were before.
|
92
91
|
###
|
93
92
|
### symbolhash = symbolify_keys( stringhash )
|
@@ -145,7 +144,7 @@ module Inversion
|
|
145
144
|
end
|
146
145
|
|
147
146
|
|
148
|
-
### Escape the
|
147
|
+
### Escape the `output` using the format specified by the given `render_state`'s config.
|
149
148
|
def escape( output, render_state )
|
150
149
|
format = render_state.options[:escape_format] || DEFAULT_ESCAPE_FORMAT
|
151
150
|
return output if format == :none
|
@@ -160,7 +159,7 @@ module Inversion
|
|
160
159
|
end
|
161
160
|
|
162
161
|
|
163
|
-
### Escape the given
|
162
|
+
### Escape the given `output` using HTML entity-encoding.
|
164
163
|
def escape_html( output )
|
165
164
|
return output.to_s.
|
166
165
|
gsub( /&/, '&' ).
|
@@ -169,7 +168,7 @@ module Inversion
|
|
169
168
|
end
|
170
169
|
|
171
170
|
|
172
|
-
### Escape the given
|
171
|
+
### Escape the given `output` using the encoding specified in RFC3986 (URIs)
|
173
172
|
def escape_uri( output )
|
174
173
|
return output.to_s.gsub( URI_ENCODED_CHARACTERS ) do |m|
|
175
174
|
bytes = m[ 0 ].each_byte
|
@@ -195,7 +194,7 @@ module Inversion
|
|
195
194
|
module MethodUtilities
|
196
195
|
|
197
196
|
### Creates instance variables and corresponding methods that return their
|
198
|
-
### values for each of the specified
|
197
|
+
### values for each of the specified `symbols` in the singleton of the
|
199
198
|
### declaring object (e.g., class instance variables and methods if declared
|
200
199
|
### in a Class).
|
201
200
|
def singleton_attr_reader( *symbols )
|
@@ -205,7 +204,7 @@ module Inversion
|
|
205
204
|
end
|
206
205
|
|
207
206
|
### Creates methods that allow assignment to the attributes of the singleton
|
208
|
-
### of the declaring object that correspond to the specified
|
207
|
+
### of the declaring object that correspond to the specified `symbols`.
|
209
208
|
def singleton_attr_writer( *symbols )
|
210
209
|
symbols.each do |sym|
|
211
210
|
singleton_class.__send__( :attr_writer, sym )
|
@@ -214,7 +213,7 @@ module Inversion
|
|
214
213
|
|
215
214
|
### Creates readers and writers that allow assignment to the attributes of
|
216
215
|
### the singleton of the declaring object that correspond to the specified
|
217
|
-
###
|
216
|
+
### `symbols`.
|
218
217
|
def singleton_attr_accessor( *symbols )
|
219
218
|
symbols.each do |sym|
|
220
219
|
singleton_class.__send__( :attr_accessor, sym )
|
@@ -231,7 +230,7 @@ module Inversion
|
|
231
230
|
module_function
|
232
231
|
###############
|
233
232
|
|
234
|
-
### Recursively copy the specified
|
233
|
+
### Recursively copy the specified `obj` and return the result.
|
235
234
|
def deep_copy( obj )
|
236
235
|
# self.log.debug "Deep copying: %p" % [ obj ]
|
237
236
|
|
data/lib/inversion/parser.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
# -*- ruby -*-
|
2
|
-
# frozen_string_literal: true
|
3
2
|
# vim: set noet nosta sw=4 ts=4 :
|
4
3
|
|
5
4
|
require 'loggability'
|
@@ -45,7 +44,7 @@ class Inversion::Parser
|
|
45
44
|
}
|
46
45
|
|
47
46
|
|
48
|
-
### Create a new Inversion::Parser with the specified config
|
47
|
+
### Create a new Inversion::Parser with the specified config `options`.
|
49
48
|
def initialize( template, options={} )
|
50
49
|
@template = template
|
51
50
|
@options = DEFAULT_OPTIONS.merge( options )
|
@@ -60,7 +59,7 @@ class Inversion::Parser
|
|
60
59
|
attr_reader :options
|
61
60
|
|
62
61
|
|
63
|
-
### Parse the given
|
62
|
+
### Parse the given `source` into one or more Inversion::Template::Nodes and return
|
64
63
|
### it as an Array.
|
65
64
|
def parse( source, inherited_state=nil )
|
66
65
|
state = nil
|
@@ -153,7 +152,7 @@ class Inversion::Parser
|
|
153
152
|
private
|
154
153
|
#######
|
155
154
|
|
156
|
-
### Return at most
|
155
|
+
### Return at most `length` characters long from the given `string`, appending `ellipsis`
|
157
156
|
### at the end if it was truncated.
|
158
157
|
def abbrevstring( string, length=30, ellipsis='…' )
|
159
158
|
return string if string.length < length
|
@@ -268,7 +267,7 @@ class Inversion::Parser
|
|
268
267
|
end
|
269
268
|
|
270
269
|
|
271
|
-
### Return the node that is currently being appended to, or
|
270
|
+
### Return the node that is currently being appended to, or `nil` if there aren't any
|
272
271
|
### opened container nodes.
|
273
272
|
def current_node
|
274
273
|
return self.node_stack.last
|
@@ -282,7 +281,7 @@ class Inversion::Parser
|
|
282
281
|
end
|
283
282
|
|
284
283
|
|
285
|
-
### Load a subtemplate from the specified
|
284
|
+
### Load a subtemplate from the specified `path`, checking for recursive-dependency.
|
286
285
|
def load_subtemplate( path )
|
287
286
|
if self.include_stack.include?( path )
|
288
287
|
stack_desc = ( self.include_stack + [path] ).join( ' --> ' )
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
# vim: set noet nosta sw=4 ts=4 :
|
3
|
+
|
4
|
+
require 'inversion' unless defined?( Inversion )
|
5
|
+
require 'ripper'
|
6
|
+
|
7
|
+
# Expose the 'tokens' instance variable of Ripper::TokenPattern::MatchData.
|
8
|
+
module Inversion::Refinements
|
9
|
+
|
10
|
+
refine Ripper::TokenPattern::MatchData do
|
11
|
+
|
12
|
+
# the array of token tuples
|
13
|
+
attr_reader :tokens
|
14
|
+
|
15
|
+
end # refine Ripper::TokenPattern::MatchData
|
16
|
+
|
17
|
+
end # module Inversion::Refinements
|
18
|
+
|