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.



180
181
182
183
184
185
186
# File 'lib/samovar/command.rb', line 180

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.



82
83
84
# File 'lib/samovar/command.rb', line 82

def description
  @description
end

Instance Attribute Details

#nameObject (readonly)

The name of the command.



210
211
212
# File 'lib/samovar/command.rb', line 210

def name
  @name
end

#outputObject

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



191
192
193
# File 'lib/samovar/command.rb', line 191

def output
  @output
end

#parentObject

The parent command, if this is a nested command.



215
216
217
# File 'lib/samovar/command.rb', line 215

def parent
  @parent
end

Class Method Details

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

Create a new command instance with the given arguments.

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



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

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

.append(row) ⇒ Object

Append a row to the parsing table.



95
96
97
98
99
100
101
102
103
# File 'lib/samovar/command.rb', line 95

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(arguments = 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. The given arguments are passed to the parser, which consumes them as mutable input.



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

def self.call(arguments = ARGV, output: $stderr)
	self.parse(arguments).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.



168
169
170
171
172
# File 'lib/samovar/command.rb', line 168

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

.complete(arguments = ARGV, environment: ENV, output: $stdout) ⇒ Object

Complete the command-line input without executing the command. The given arguments are treated as the stable command-line boundary; completion internals consume derived input arrays.



49
50
51
52
53
# File 'lib/samovar/command.rb', line 49

def self.complete(arguments = ARGV, environment: ENV, output: $stdout)
	Completion.complete(self, arguments, environment: environment).tap do |result|
		result.print(output)
	end
end

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

Define multiple positional arguments.



134
135
136
# File 'lib/samovar/command.rb', line 134

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

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

Define a nested sub-command.



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

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

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

Define a single required positional argument.



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

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

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

Define command-line options for this command.



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

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

.parse(arguments) ⇒ 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.



63
64
65
# File 'lib/samovar/command.rb', line 63

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

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

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



142
143
144
# File 'lib/samovar/command.rb', line 142

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

.tableObject

The table of rows for parsing command-line arguments.



88
89
90
# File 'lib/samovar/command.rb', line 88

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

.usage(rows, name) ⇒ Object

Generate usage information for this command.



150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/samovar/command.rb', line 150

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.



221
222
223
# File 'lib/samovar/command.rb', line 221

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

#parse(input) ⇒ Object

Parse the command-line input.



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

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.



244
245
246
247
248
249
250
# File 'lib/samovar/command.rb', line 244

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.



203
204
205
# File 'lib/samovar/command.rb', line 203

def to_s
	self.class.name
end