Class: Inversion::Command
- Inherits:
-
Object
- Object
- Inversion::Command
- Extended by:
- Sysexits
- Defined in:
- lib/inversion/command.rb
Overview
Command class for the ‘inversion’ command-line tool.
Constant Summary collapse
- SUBCOMMANDS =
The list of valid subcommands
%w[api tagtokens tree]
Instance Attribute Summary collapse
-
#opts ⇒ Object
readonly
The command-line options.
-
#prompt ⇒ Object
readonly
The command’s prompt object (HighLine).
Class Method Summary collapse
-
.create_option_parser ⇒ Object
Create an option parser for the command and return it.
-
.parse_options(args) ⇒ Object
Parse the given command line
args
, returning a populated options struct and any remaining arguments. -
.prompt ⇒ Object
Fetch the HighLine instance for the command, creating it if necessary.
-
.run(args) ⇒ Object
Run the command.
Instance Method Summary collapse
-
#describe_publications(template) ⇒ Object
Output a list of sections the template publishes.
-
#describe_subscriptions(template) ⇒ Object
Output a list of sections the template subscribes to.
-
#describe_template_api(template) ⇒ Object
Output a description of the
template
‘s attributes, subscriptions, etc. -
#describe_templates(templates) ⇒ Object
Output a description of the templates.
-
#dump_node_trees(templates) ⇒ Object
Dump the node tree of the given
templates
. -
#dump_tokens(args) ⇒ Object
Attempt to parse the given
code
and dump its tokens as a tagpattern. -
#initialize(opts) ⇒ Command
constructor
Create a new instance of the command that will use the specified
opts
to parse and dump info about the giventemplates
. -
#load_template(tmplpath) ⇒ Object
Load the Inversion::Template from the specified
tmplpath
and return it. -
#output_blank_line ⇒ Object
Output a blank line.
-
#output_error(message) ⇒ Object
Display an error message.
-
#output_list(columns) ⇒ Object
Display a columnar list.
-
#output_subheader(caption) ⇒ Object
Output a subheader with the given
caption
. -
#output_template_header(template) ⇒ Object
Output a header between each template.
-
#output_template_nodes(tree, indent = 0) ⇒ Object
Output the given
tree
of nodes at the specifiedindent
level. -
#run(subcommand, args) ⇒ Object
Run the given
subcommand
with the specifiedargs
.
Constructor Details
#initialize(opts) ⇒ Command
Create a new instance of the command that will use the specified opts
to parse and dump info about the given templates
.
108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/inversion/command.rb', line 108 def initialize( opts ) @opts = opts @prompt = self.class.prompt # Configure logging Loggability.level = opts.debug ? :debug : :error Loggability.format_with( :color ) if $stdin.tty? # Configure Inversion's strictness Inversion::Template.configure( :ignore_unknown_tags => opts., :template_paths => opts.path, ) end |
Instance Attribute Details
#opts ⇒ Object (readonly)
The command-line options
129 130 131 |
# File 'lib/inversion/command.rb', line 129 def opts @opts end |
#prompt ⇒ Object (readonly)
The command’s prompt object (HighLine)
132 133 134 |
# File 'lib/inversion/command.rb', line 132 def prompt @prompt end |
Class Method Details
.create_option_parser ⇒ Object
Create an option parser for the command and return it
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/inversion/command.rb', line 51 def self::create_option_parser pr = self.prompt progname = pr.color( File.basename($0), :bold, :yellow ) return Trollop::Parser.new do version Inversion.version_string( true ) (" \#{progname} OPTIONS SUBCOMMAND ARGS\n\n Run the specified SUBCOMMAND with the given ARGS.\n END_BANNER\n text ''\n\n stop_on( *SUBCOMMANDS )\n text pr.color('Subcommands', :bold, :white)\n text pr.list( SUBCOMMANDS, :columns_across )\n text ''\n\n text pr.color('Inversion Config', :bold, :white)\n opt :ignore_unknown_tags, \"Ignore unknown tags instead of displaying an error\"\n opt :path, \"Add one or more directories to the template search path\",\n :type => :string, :multi => true\n text ''\n\n\n text pr.color('Other Options', :bold, :white)\n opt :debug, \"Enable debugging output\"\n end\nend\n").gsub(/^\t+/, '') |
.parse_options(args) ⇒ Object
Parse the given command line args
, returning a populated options struct and any remaining arguments.
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/inversion/command.rb', line 85 def self::( args ) oparser = self.create_option_parser opts = oparser.parse( args ) if oparser.leftovers.empty? $stderr.puts "No subcommand given.\nUsage: " oparser.educate( $stderr ) exit :usage end args.replace( oparser.leftovers ) return opts, args rescue Trollop::HelpNeeded oparser.educate( $stderr ) exit :ok rescue Trollop::VersionNeeded $stderr.puts( oparser.version ) exit :ok end |
.prompt ⇒ Object
Fetch the HighLine instance for the command, creating it if necessary.
39 40 41 42 43 44 45 46 47 |
# File 'lib/inversion/command.rb', line 39 def self::prompt unless @prompt @prompt = HighLine.new @prompt.page_at = @prompt.output_rows - 5 @prompt.wrap_at = @prompt.output_cols - 2 end @prompt end |
.run(args) ⇒ Object
Run the command
26 27 28 29 30 31 32 33 34 35 |
# File 'lib/inversion/command.rb', line 26 def self::run( args ) opts, args = self.( args ) subcommand = args.shift command = self.new( opts ) command.run( subcommand, args ) rescue => err $stderr.puts "%p: %s" % [ err.class, err. ] $stderr.puts( err.backtrace.join("\n ") ) if opts && opts.debug end |
Instance Method Details
#describe_publications(template) ⇒ Object
Output a list of sections the template publishes.
219 220 221 222 223 224 225 226 227 |
# File 'lib/inversion/command.rb', line 219 def describe_publications( template ) = template.node_tree.find_all {|node| node.is_a?(Inversion::Template::PublishTag) } return if .empty? pubnames = .map( &:key ).map( &:to_s ).uniq.sort self.output_subheader "%d Publication/s" % [ pubnames.length ] self.output_list( pubnames ) self.output_blank_line end |
#describe_subscriptions(template) ⇒ Object
Output a list of sections the template subscribes to.
231 232 233 234 235 236 237 238 239 |
# File 'lib/inversion/command.rb', line 231 def describe_subscriptions( template ) = template.node_tree.find_all {|node| node.is_a?(Inversion::Template::SubscribeTag) } return if .empty? subnames = .map( &:key ).map( &:to_s ).uniq.sort self.output_subheader "%d Subscription/s" % [ subnames.length ] self.output_list( subnames ) self.output_blank_line end |
#describe_template_api(template) ⇒ Object
Output a description of the template
‘s attributes, subscriptions, etc.
208 209 210 211 212 213 214 215 |
# File 'lib/inversion/command.rb', line 208 def describe_template_api( template ) attrs = template.attributes.keys.map( &:to_s ) return if attrs.empty? self.output_subheader "%d Attribute/s" % [ attrs.length ] self.output_list( attrs.sort ) self.output_blank_line end |
#describe_templates(templates) ⇒ Object
Output a description of the templates.
186 187 188 189 190 191 192 193 194 195 |
# File 'lib/inversion/command.rb', line 186 def describe_templates( templates ) templates.each do |path| template = self.load_template( path ) self.output_blank_line self.output_template_header( template ) self.describe_template_api( template ) self.describe_publications( template ) self.describe_subscriptions( template ) end end |
#dump_node_trees(templates) ⇒ Object
Dump the node tree of the given templates
.
165 166 167 168 169 170 171 172 |
# File 'lib/inversion/command.rb', line 165 def dump_node_trees( templates ) templates.each do |path| template = self.load_template( path ) self.output_blank_line self.output_template_header( template ) self.output_template_nodes( template.node_tree ) end end |
#dump_tokens(args) ⇒ Object
Attempt to parse the given code
and dump its tokens as a tagpattern.
243 244 245 246 247 248 249 250 251 252 |
# File 'lib/inversion/command.rb', line 243 def dump_tokens( args ) code = args.join(' ') require 'ripper' tokens = Ripper.lex( code ).collect do |(pos, tok, text)| "%s<%p>" % [ tok.to_s.sub(/^on_/,''), text ] end.join(' ') self.prompt.say( tokens ) end |
#load_template(tmplpath) ⇒ Object
Load the Inversion::Template from the specified tmplpath
and return it. If there is an error loading the template, output the error and return nil
.
152 153 154 155 156 157 158 159 160 161 |
# File 'lib/inversion/command.rb', line 152 def load_template( tmplpath ) template = Inversion::Template.load( tmplpath ) return template rescue Errno => err self.prompt.say "Failed to load %s: %s" % [ tmplpath, err. ] rescue Inversion::ParseError => err self.prompt.say "%s: Invalid template: %p: %s" % [ tmplpath, err.class, err. ] self.prompt.say( err.backtrace.join("\n ") ) if self.opts.debug end |
#output_blank_line ⇒ Object
Output a blank line
274 275 276 |
# File 'lib/inversion/command.rb', line 274 def output_blank_line self.prompt.say( "\n" ) end |
#output_error(message) ⇒ Object
Display an error message.
262 263 264 |
# File 'lib/inversion/command.rb', line 262 def output_error( ) self.prompt.say( self.prompt.color(, :red) ) end |
#output_list(columns) ⇒ Object
Display a columnar list.
256 257 258 |
# File 'lib/inversion/command.rb', line 256 def output_list( columns ) self.prompt.say( self.prompt.list(columns, :columns_down) ) end |
#output_subheader(caption) ⇒ Object
Output a subheader with the given caption
.
268 269 270 |
# File 'lib/inversion/command.rb', line 268 def output_subheader( caption ) self.prompt.say( self.prompt.color(caption, :cyan) ) end |
#output_template_header(template) ⇒ Object
Output a header between each template.
199 200 201 202 203 204 |
# File 'lib/inversion/command.rb', line 199 def output_template_header( template ) header_info = "%s (%0.2fK, %s)" % [ template.source_file, template.source.bytesize/1024.0, template.source.encoding ] header_line = "-- %s" % [ header_info ] self.prompt.say( self.prompt.color(header_line, :bold, :white) ) end |
#output_template_nodes(tree, indent = 0) ⇒ Object
Output the given tree
of nodes at the specified indent
level.
176 177 178 179 180 181 182 |
# File 'lib/inversion/command.rb', line 176 def output_template_nodes( tree, indent=0 ) indenttxt = ' ' * indent tree.each do |node| self.prompt.say( indenttxt + node.as_comment_body ) self.output_template_nodes( node.subnodes, indent+4 ) if node.is_container? end end |
#run(subcommand, args) ⇒ Object
Run the given subcommand
with the specified args
.
136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/inversion/command.rb', line 136 def run( subcommand, args ) case subcommand.to_sym when :tree self.dump_node_trees( args ) when :api self.describe_templates( args ) when :tagtokens self.dump_tokens( args ) else self.output_error( "No such command #{subcommand.dump}" ) end end |