Class: Samovar::Command

Inherits:
Object
  • Object
show all
Defined in:
lib/samovar/command.rb

Overview

Represents a command in the command-line interface.

Commands are the main building blocks of Samovar applications. Each command is a class that can parse command-line arguments, options, and sub-commands.

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(input = nil, name: File.basename($0), parent: nil, output: nil) ⇒ Command

Initialize a new command instance.



165
166
167
168
169
170
171
# File 'lib/samovar/command.rb', line 165

def initialize(input = nil, name: File.basename($0), parent: nil, output: nil)
	@name = name
	@parent = parent
	@output = output
	
	parse(input) if input
end

Class Attribute Details

.descriptionObject

A description of the command’s purpose.



67
68
69
# File 'lib/samovar/command.rb', line 67

def description
  @description
end

Instance Attribute Details

#nameObject (readonly)

The name of the command.



195
196
197
# File 'lib/samovar/command.rb', line 195

def name
  @name
end

#outputObject

The output stream for usage information, defaults to ‘$stdout`.



176
177
178
# File 'lib/samovar/command.rb', line 176

def output
  @output
end

#parentObject

The parent command, if this is a nested command.



200
201
202
# File 'lib/samovar/command.rb', line 200

def parent
  @parent
end

Class Method Details

.[](*input, **options) ⇒ Object

Create a new command instance with the given arguments.

This is a convenience method for creating command instances with explicit arguments.



59
60
61
# File 'lib/samovar/command.rb', line 59

def self.[](*input, **options)
	self.new(input, **options)
end

.append(row) ⇒ Object

Append a row to the parsing table.



80
81
82
83
84
85
86
87
88
# File 'lib/samovar/command.rb', line 80

def self.append(row)
	if method_defined?(row.key, false)
		raise ArgumentError, "Method for key #{row.key} is already defined!"
	end
	
	attr_accessor(row.key) if row.respond_to?(:key)
	
	self.table << row
end

.call(input = ARGV, output: $stderr) ⇒ Object

Parse and execute the command with the given input.

This is the high-level entry point for CLI applications. It handles errors gracefully by printing usage and returning nil.



30
31
32
33
34
35
36
37
38
# File 'lib/samovar/command.rb', line 30

def self.call(input = ARGV, output: $stderr)
	self.parse(input).call
rescue Error => error
	error.command.print_usage(output: output) do |formatter|
		formatter.map(error)
	end
	
	return nil
end

.command_line(name) ⇒ Object

Generate a command-line usage string.



153
154
155
156
157
# File 'lib/samovar/command.rb', line 153

def self.command_line(name)
	table = self.table.merged
	
	return "#{name} #{table.usage}"
end

.many(*arguments, **options) ⇒ Object

Define multiple positional arguments.



119
120
121
# File 'lib/samovar/command.rb', line 119

def self.many(*arguments, **options)
	append Many.new(*arguments, **options)
end

.nested(*arguments, **options) ⇒ Object

Define a nested sub-command.



103
104
105
# File 'lib/samovar/command.rb', line 103

def self.nested(*arguments, **options)
	append Nested.new(*arguments, **options)
end

.one(*arguments, **options) ⇒ Object

Define a single required positional argument.



111
112
113
# File 'lib/samovar/command.rb', line 111

def self.one(*arguments, **options)
	append One.new(*arguments, **options)
end

.options(*arguments, **options, &block) ⇒ Object

Define command-line options for this command.



95
96
97
# File 'lib/samovar/command.rb', line 95

def self.options(*arguments, **options, &block)
	append Options.parse(*arguments, **options, &block)
end

.parse(input) ⇒ Object

Parse the command-line input and create a command instance.

This is the low-level parsing primitive. It raises Error exceptions on parsing failures. For CLI applications, use call instead which handles errors gracefully.



48
49
50
# File 'lib/samovar/command.rb', line 48

def self.parse(input)
	self.new(input)
end

.split(*arguments, **options) ⇒ Object

Define a split point in the argument list (typically ‘–`).



127
128
129
# File 'lib/samovar/command.rb', line 127

def self.split(*arguments, **options)
	append Split.new(*arguments, **options)
end

.tableObject

The table of rows for parsing command-line arguments.



73
74
75
# File 'lib/samovar/command.rb', line 73

def self.table
	@table ||= Table.nested(self)
end

.usage(rows, name) ⇒ Object

Generate usage information for this command.



135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/samovar/command.rb', line 135

def self.usage(rows, name)
	rows.nested(name, self) do |rows|
		return unless table = self.table.merged
		
		table.each do |row|
			if row.respond_to?(:usage)
				row.usage(rows)
			else
				rows << row
			end
		end
	end
end

Instance Method Details

#[](*input) ⇒ Object

Duplicate the command with additional arguments.



206
207
208
# File 'lib/samovar/command.rb', line 206

def [](*input)
	self.dup.tap{|command| command.parse(input)}
end

#parse(input) ⇒ Object

Parse the command-line input.



214
215
216
217
218
219
220
221
222
# File 'lib/samovar/command.rb', line 214

def parse(input)
	self.class.table.merged.parse(input, self)
	
	if input.empty?
		return self
	else
		raise InvalidInputError.new(self, input)
	end
end

Print usage information for this command.



229
230
231
232
233
234
235
# File 'lib/samovar/command.rb', line 229

def print_usage(output: self.output, formatter: Output::UsageFormatter, &block)
	rows = Output::Rows.new
	
	self.class.usage(rows, @name)
	
	formatter.print(rows, output, &block)
end

#to_sObject

Generate a string representation of the command.



188
189
190
# File 'lib/samovar/command.rb', line 188

def to_s
	self.class.name
end