Class: CommandMapper::Command
- Inherits:
-
Object
- Object
- CommandMapper::Command
- Includes:
- Types
- Defined in:
- lib/command_mapper/command.rb
Overview
Base class for all mapped commands.
Direct Known Subclasses
Instance Attribute Summary collapse
-
#command_env ⇒ Hash{String => String}
readonly
The environment variables to execute the command with.
-
#command_name ⇒ String
readonly
The command name.
-
#command_path ⇒ String?
readonly
The optional path to the command.
-
#command_subcommand ⇒ Command?
readonly
The subcommand's options and arguments.
Class Method Summary collapse
-
.argument(name, required: true, type: Str.new, repeats: false) ⇒ Object
Defines an option for the command.
-
.arguments ⇒ Hash{Symbol => Argument}
All defined options.
-
.capture(params = {}, **kwargs) {|command| ... } ⇒ String
Initializes and runs the command in a shell and captures all stdout output.
- .command(new_command_name) {|self| ... } ⇒ Object
-
.command_name ⇒ String
Gets or sets the command name.
-
.has_argument?(name) ⇒ Boolean
Determines if an argument with the given name has been defined.
-
.has_option?(name) ⇒ Boolean
Determines if an option with the given name has been defined.
-
.has_subcommand?(name) ⇒ Boolean
Determines if a subcommand with the given name has been defined.
-
.option(flag, name: nil, value: nil, repeats: false, equals: nil, value_in_flag: nil, &block) ⇒ Object
Defines an option for the command.
-
.options ⇒ Hash{Symbol => Option}
All defined options.
-
.popen(params = {}, mode: 'r', **kwargs) {|command| ... } ⇒ IO
Initializes and executes the command and returns an IO object to it.
-
.run(params = {}, **kwargs) {|command| ... } ⇒ Boolean?
Initializes and runs the command.
-
.spawn(params = {}, **kwargs) {|command| ... } ⇒ Integer
Initializes and spawns the command as a separate process, returning the PID of the process.
-
.subcommand(name) {|subcommand| ... } ⇒ Object
Defines a subcommand.
-
.subcommands ⇒ Hash{Symbol => Command.class}
All defined subcommands.
-
.sudo(params = {}, sudo: {}, **kwargs) {|command| ... } ⇒ Boolean?
Initializes and runs the command through
sudo
.
Instance Method Summary collapse
-
#[](name) ⇒ Object
Gets the value of an option or an argument.
-
#[]=(name, value) ⇒ Object
Sets an option or an argument with the given name.
-
#capture_command ⇒ String
Runs the command in a shell and captures all stdout output.
-
#command_argv ⇒ Array<String>
Returns an Array of command-line arguments for the command.
-
#command_string ⇒ String
Escapes any shell control-characters so that it can be ran in a shell.
-
#initialize(params = {}, command_name: self.class.command_name, command_path: nil, command_env: {}, **kwargs) {|self| ... } ⇒ Command
constructor
Initializes the command.
-
#popen_command(mode = nil) ⇒ IO
Executes the command and returns an IO object to it.
-
#run_command ⇒ Boolean?
Runs the command.
-
#spawn_command ⇒ Integer
Spawns the command as a separate process, returning the PID of the process.
-
#sudo_command(**sudo_kwargs, &block) ⇒ Boolean?
Runs the command through
sudo
. - #to_a ⇒ Object
- #to_s ⇒ Object
Methods included from Types
Constructor Details
#initialize(params = {}, command_name: self.class.command_name, command_path: nil, command_env: {}, **kwargs) {|self| ... } ⇒ Command
Initializes the command.
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/command_mapper/command.rb', line 71 def initialize(params={}, command_name: self.class.command_name, command_path: nil, command_env: {}, **kwargs) @command_name = command_name @command_path = command_path @command_env = command_env params = params.merge(kwargs) params.each do |name,value| self[name] = value end yield self if block_given? end |
Instance Attribute Details
#command_env ⇒ Hash{String => String} (readonly)
The environment variables to execute the command with.
30 31 32 |
# File 'lib/command_mapper/command.rb', line 30 def command_env @command_env end |
#command_name ⇒ String (readonly)
The command name.
20 21 22 |
# File 'lib/command_mapper/command.rb', line 20 def command_name @command_name end |
#command_path ⇒ String? (readonly)
The optional path to the command.
25 26 27 |
# File 'lib/command_mapper/command.rb', line 25 def command_path @command_path end |
#command_subcommand ⇒ Command? (readonly)
The subcommand's options and arguments.
35 36 37 |
# File 'lib/command_mapper/command.rb', line 35 def command_subcommand @command_subcommand end |
Class Method Details
.argument(name, required: true, type: Str.new, repeats: false) ⇒ Object
Defines an option for the command.
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 |
# File 'lib/command_mapper/command.rb', line 435 def self.argument(name, required: true, type: Str.new, repeats: false) name = name.to_sym argument = Argument.new(name, required: required, type: type, repeats: repeats) if is_internal_method?(argument.name) raise(ArgumentError,"argument #{name.inspect} cannot override internal method with same name: ##{argument.name}") elsif has_option?(argument.name) raise(ArgumentError,"argument #{name.inspect} conflicts with another option with the same name") elsif has_subcommand?(argument.name) raise(ArgumentError,"argument #{name.inspect} conflicts with another subcommand with the same name") end self.arguments[argument.name] = argument attr_accessor name end |
.arguments ⇒ Hash{Symbol => Argument}
All defined options.
381 382 383 384 385 386 387 |
# File 'lib/command_mapper/command.rb', line 381 def self.arguments @arguments ||= if superclass < Command superclass.arguments.dup else {} end end |
.capture(params = {}, **kwargs) {|command| ... } ⇒ String
Initializes and runs the command in a shell and captures all stdout output.
158 159 160 161 |
# File 'lib/command_mapper/command.rb', line 158 def self.capture(params={},**kwargs,&block) command = new(params,**kwargs,&block) command.capture_command end |
.command(new_command_name) {|self| ... } ⇒ Object
248 249 250 251 |
# File 'lib/command_mapper/command.rb', line 248 def self.command(new_command_name,&block) @command_name = new_command_name.to_s.freeze yield self if block_given? end |
.command_name ⇒ String
Gets or sets the command name.
223 224 225 226 227 228 229 |
# File 'lib/command_mapper/command.rb', line 223 def self.command_name @command_name || if superclass < Command superclass.command_name else raise(NotImplementedError,"#{self} did not call command(...)") end end |
.has_argument?(name) ⇒ Boolean
Determines if an argument with the given name has been defined.
402 403 404 |
# File 'lib/command_mapper/command.rb', line 402 def self.has_argument?(name) arguments.has_key?(name) end |
.has_option?(name) ⇒ Boolean
Determines if an option with the given name has been defined.
281 282 283 |
# File 'lib/command_mapper/command.rb', line 281 def self.has_option?(name) .has_key?(name) end |
.has_subcommand?(name) ⇒ Boolean
Determines if a subcommand with the given name has been defined.
482 483 484 |
# File 'lib/command_mapper/command.rb', line 482 def self.has_subcommand?(name) subcommands.has_key?(name) end |
.option(flag, name: nil, value: nil, repeats: false, equals: nil, value_in_flag: nil, &block) ⇒ Object
Defines an option for the command.
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 |
# File 'lib/command_mapper/command.rb', line 344 def self.option(flag, name: nil, value: nil, repeats: false, # formatting options equals: nil, value_in_flag: nil, &block) option = Option.new(flag, name: name, value: value, repeats: repeats, # formatting options equals: equals, value_in_flag: value_in_flag, &block) if is_internal_method?(option.name) if name raise(ArgumentError,"option #{flag.inspect} with name #{name.inspect} cannot override the internal method with same name: ##{option.name}") else raise(ArgumentError,"option #{flag.inspect} maps to method name ##{option.name} and cannot override the internal method with same name: ##{option.name}") end elsif has_argument?(option.name) raise(ArgumentError,"option #{flag.inspect} with name #{option.name.inspect} conflicts with another argument with the same name") elsif has_subcommand?(option.name) raise(ArgumentError,"option #{flag.inspect} with name #{option.name.inspect} conflicts with another subcommand with the same name") end self.[option.name] = option attr_accessor option.name end |
.options ⇒ Hash{Symbol => Option}
All defined options.
260 261 262 263 264 265 266 |
# File 'lib/command_mapper/command.rb', line 260 def self. @options ||= if superclass < Command superclass..dup else {} end end |
.popen(params = {}, mode: 'r', **kwargs) {|command| ... } ⇒ IO
Initializes and executes the command and returns an IO object to it.
183 184 185 186 |
# File 'lib/command_mapper/command.rb', line 183 def self.popen(params={}, mode: 'r', **kwargs,&block) command = new(params,**kwargs,&block) command.popen_command end |
.run(params = {}, **kwargs) {|command| ... } ⇒ Boolean?
Initializes and runs the command.
105 106 107 108 |
# File 'lib/command_mapper/command.rb', line 105 def self.run(params={},**kwargs,&block) command = new(params,**kwargs,&block) command.run_command end |
.spawn(params = {}, **kwargs) {|command| ... } ⇒ Integer
Initializes and spawns the command as a separate process, returning the PID of the process.
134 135 136 137 |
# File 'lib/command_mapper/command.rb', line 134 def self.spawn(params={},**kwargs,&block) command = new(params,**kwargs,&block) command.spawn_command end |
.subcommand(name) {|subcommand| ... } ⇒ Object
Also defines a class within the command class using the subcommand's name.
Defines a subcommand.
516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 |
# File 'lib/command_mapper/command.rb', line 516 def self.subcommand(name,&block) name = name.to_s method_name = name.tr('-','_') class_name = name.split(/[_-]+/).map(&:capitalize).join subcommand_name = method_name.to_sym if is_internal_method?(method_name) raise(ArgumentError,"subcommand #{name.inspect} maps to method name ##{method_name} and cannot override the internal method with same name: ##{method_name}") elsif has_option?(subcommand_name) raise(ArgumentError,"subcommand #{name.inspect} conflicts with another option with the same name") elsif has_argument?(subcommand_name) raise(ArgumentError,"subcommand #{name.inspect} conflicts with another argument with the same name") end subcommand_class = Class.new(Command) subcommand_class.command(name) subcommand_class.class_eval(&block) self.subcommands[subcommand_name] = subcommand_class const_set(class_name,subcommand_class) define_method(method_name) do |&block| if block then @command_subcommand = subcommand_class.new(&block) else @command_subcommand end end define_method(:"#{method_name}=") do || @command_subcommand = if subcommand_class.new() end end end |
.subcommands ⇒ Hash{Symbol => Command.class}
All defined subcommands.
461 462 463 464 465 466 467 |
# File 'lib/command_mapper/command.rb', line 461 def self.subcommands @subcommands ||= if superclass < Command superclass.subcommands.dup else {} end end |
.sudo(params = {}, sudo: {}, **kwargs) {|command| ... } ⇒ Boolean?
Initializes and runs the command through sudo
.
204 205 206 207 |
# File 'lib/command_mapper/command.rb', line 204 def self.sudo(params={}, sudo: {}, **kwargs,&block) command = new(params,**kwargs,&block) command.sudo_command(**sudo) end |
Instance Method Details
#[](name) ⇒ Object
Gets the value of an option or an argument.
562 563 564 565 566 567 568 569 570 |
# File 'lib/command_mapper/command.rb', line 562 def [](name) name = name.to_s if respond_to?(name) send(name) else raise(ArgumentError,"#{self.class} does not define ##{name}") end end |
#[]=(name, value) ⇒ Object
Sets an option or an argument with the given name.
587 588 589 590 591 592 593 |
# File 'lib/command_mapper/command.rb', line 587 def []=(name,value) if respond_to?("#{name}=") send("#{name}=",value) else raise(ArgumentError,"#{self.class} does not define ##{name}=") end end |
#capture_command ⇒ String
Runs the command in a shell and captures all stdout output.
695 696 697 |
# File 'lib/command_mapper/command.rb', line 695 def capture_command `#{command_string}` end |
#command_argv ⇒ Array<String>
Returns an Array of command-line arguments for the command.
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 |
# File 'lib/command_mapper/command.rb', line 604 def command_argv argv = [@command_path || @command_name] self.class..each do |name,option| unless (value = self[name]).nil? option.argv(argv,value) end end if @command_subcommand # a subcommand takes precedence over any command arguments argv.concat(@command_subcommand.command_argv) else additional_args = [] self.class.arguments.each do |name,argument| value = self[name] if value.nil? if argument.required? raise(ArgumentRequired,"argument #{name} is required") end else argument.argv(additional_args,value) end end if additional_args.any? { |arg| arg.start_with?('-') } # append a '--' separator if any of the arguments start with a '-' argv << '--' end argv.concat(additional_args) end return argv end |
#command_string ⇒ String
Escapes any shell control-characters so that it can be ran in a shell.
648 649 650 651 652 653 654 655 656 657 658 659 660 |
# File 'lib/command_mapper/command.rb', line 648 def command_string escaped_command = Shellwords.shelljoin(command_argv) unless @command_env.empty? escaped_env = @command_env.map { |name,value| "#{Shellwords.shellescape(name)}=#{Shellwords.shellescape(value)}" }.join(' ') escaped_command = "#{escaped_env} #{escaped_command}" end return escaped_command end |
#popen_command(mode = nil) ⇒ IO
Executes the command and returns an IO object to it.
705 706 707 708 709 |
# File 'lib/command_mapper/command.rb', line 705 def popen_command(mode=nil) if mode then IO.popen(@command_env,command_argv,mode) else IO.popen(@command_env,command_argv) end end |
#run_command ⇒ Boolean?
Runs the command.
669 670 671 |
# File 'lib/command_mapper/command.rb', line 669 def run_command Kernel.system(@command_env,*command_argv) end |
#spawn_command ⇒ Integer
Spawns the command as a separate process, returning the PID of the process.
685 686 687 |
# File 'lib/command_mapper/command.rb', line 685 def spawn_command Process.spawn(@command_env,*command_argv) end |
#sudo_command(**sudo_kwargs, &block) ⇒ Boolean?
Runs the command through sudo
.
721 722 723 724 725 |
# File 'lib/command_mapper/command.rb', line 721 def sudo_command(**sudo_kwargs,&block) sudo_params = sudo_kwargs.merge(command: command_argv) Sudo.run(sudo_params, command_env: @command_env, &block) end |
#to_a ⇒ Object
730 731 732 |
# File 'lib/command_mapper/command.rb', line 730 def to_a command_argv end |
#to_s ⇒ Object
737 738 739 |
# File 'lib/command_mapper/command.rb', line 737 def to_s command_string end |