Class: KXI::CLI::Verb

Inherits:
Object
  • Object
show all
Defined in:
lib/kxi/cli/verb.rb

Overview

Represents a verb of console interface

Instance Method Summary collapse

Constructor Details

#initialize(nm, desc, ctx = nil) {|verb| ... } ⇒ Verb

Instantiates the KXI::CLI::Verb class

Parameters:

  • nm (String)

    Name of verb

  • desc (String)

    Description of verb

  • ctx (String) (defaults to: nil)

    Context of verb

Yields:

  • (verb)

    Initialization body of verb

Yield Parameters:

Raises:

  • (Exception)

    When name of verb is invalid



47
48
49
50
51
52
53
54
55
56
57
# File 'lib/kxi/cli/verb.rb', line 47

def initialize(nm, desc, ctx = nil)
	raise(Exception.new('Invalid name of verb!')) unless /^[A-Za-z0-9][A-Za-z0-9\-]*$/m =~ nm
	@name   = nm.downcase
	@desc   = desc
	@verbs  = KXI::Collections::ArrayCollection.new
	@args   = KXI::Collections::ArrayCollection.new
	@action = nil
	@ctx    = ctx
	@help   = false
	yield(self) if block_given?
end

Instance Method Details

#act(args = nil) ⇒ Object

Parses and executes action of verb

Parameters:

  • args (Array<String>) (defaults to: nil)

    Given arguments



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/kxi/cli/verb.rb', line 132

def act(args = nil)
	args = ARGV if args == nil
	hf   = (args.include?('-h') or args.include?('--help') or args.include?('-?'))
	if @verbs.count > 0
		v = args.shift
		if @help and (v == 'help' or hf)
			if v == 'help' or v == nil
				help
			else
				verb = @verbs.first { |i| i.name == v.downcase }
				if verb == nil
					help
				else
					verb.act(args)
				end
			end
		else
			raise(KXI::Exceptions::VerbExpectedException.new(@verbs.select { |i| i.name }.to_array)) if v == nil
			verb = @verbs.first { |i| i.name == v.downcase }
			raise(KXI::Exceptions::VerbExpectedException.new(@verbs.select { |i| i.name }.to_array)) if verb == nil
			verb.act(args)
		end
	else
		if @help and hf
			help
		else
			vals = KXI::CLI::ArgumentValues.new(@args.to_array)
			anon = @args.of_type(KXI::CLI::AnonymousArgument).order_by_descending { |a, b| a.order <=> b.order }
			
			ar = nil
			args.each do |val|
				if val.start_with?('-')
					raise(KXI::Exceptions::ArgumentException.new(ar.name, 'Expected value!')) if ar != nil
					raise(KXI::Exceptions::ArgumentException.new(val, 'Invalid syntax!')) if val.start_with?('---')
					if val.start_with?('--')
						raise(KXI::Exceptions::ArgumentException.new(val, 'Expected argument name!')) if val.length == 2
						nm  = val[2..val.length - 1].downcase
						arg = @args.first { |i| i.name == nm }
						raise(KXI::Exceptions::ArgumentException.new(nm, 'No such argument exists!')) if arg == nil
						if arg.is_a?(KXI::CLI::FlagArgument)
							vals.set(arg, true)
						elsif arg.is_a?(KXI::CLI::NamedArgument)
							ar = arg
						else
							raise(KXI::Exceptions::ArgumentException.new(nm, 'Argument cannot be assigned explicitly!'))
						end
					else
						raise(KXI::Exceptions::ArgumentException.new(val, 'Expected short argument name!')) if val.length == 1
						nm  = val[1]
						arg = @args.of_type(KXI::CLI::ExplicitArgument).first { |i| i.shortcut == nm }
						raise(KXI::Exceptions::ArgumentException.new(nm, 'No such argument exists!')) if arg == nil
						if arg.is_a?(KXI::CLI::FlagArgument)
							vals.set(arg, true)
						elsif arg.is_a?(KXI::CLI::NamedArgument)
							if val.length == 2
								ar = arg
							else
								vals.set(arg, val[2..val.length - 1])
							end
						end
					end
				else
					if ar != nil
						vals.set(ar, val)
						ar = nil
					else
						an = anon.first
						raise(KXI::Exceptions::NoArgumentException.new(val)) if an == nil
						vals.set(an, val)
						anon.remove_at(0) unless an.variadic?
					end
				end
			end
			vals.finish
			if @action == nil
				raise(KXI::Exceptions::NotImplementedException.new)
			else
				@action.call(vals)
			end
		end
	end
end

#action {|args| ... } ⇒ Object

Assigns action to this verb

Yields:

  • (args)

    Action of verb

Yield Parameters:



22
23
24
# File 'lib/kxi/cli/verb.rb', line 22

def action(&block)
	@action = block
end

#add_argument(arg) ⇒ Object

Adds argument

Parameters:



249
250
251
252
253
254
255
256
257
258
259
260
261
# File 'lib/kxi/cli/verb.rb', line 249

def add_argument(arg)
	check_name(arg.name)
	if arg.is_a?(KXI::CLI::ExplicitArgument) and arg.shortcut != nil
		raise(Exception.new("Short name '#{arg.shortcut}' is already in use!")) if @args.of_type(KXI::CLI::ExplicitArgument).any { |i| i.shortcut == arg.shortcut }
	end
	if arg.is_a?(KXI::CLI::AnonymousArgument) and arg.variadic?
		raise(Exception.new("Verb can have only one variadic anonymous argument! (argument '#{arg.name}')")) if @args.of_type(KXI::CLI::AnonymousArgument).any { |i| i.variadic? }
		raise(Exception.new("Verb cannot contain both optional and variadic anonymous arguments! (argument '#{arg.name}')")) if @args.of_type(KXI::CLI::AnonymousArgument).any { |i| not i.required? }
	end
	@args.add(arg)
	@verbs.foreach { |i| i.add_argument(arg) }
	return arg
end

#add_verb(v) ⇒ Object

Adds child verb

Parameters:



265
266
267
268
269
270
# File 'lib/kxi/cli/verb.rb', line 265

def add_verb(v)
	@args.foreach { |a| v.add_argument(a) }
	@verbs.add(v)
	v.enable_help if @help
	return v
end

#anonymous(name, desc, df = nil, var = false) {|val| ... } ⇒ KXI::CLI::AnonymousArgument

Creates new optional anonymous argument

Parameters:

  • name (String)

    Name of argument

  • desc (String)

    Description of argument

  • df (Object, nil) (defaults to: nil)

    Default value of argument

  • var (Bool) (defaults to: false)

    Determines whether argument is variadic

Yields:

  • (val)

    Validator function for value of argument

Yield Parameters:

  • val (String, Array<String>)

    Value of argument

Returns:



76
77
78
# File 'lib/kxi/cli/verb.rb', line 76

def anonymous(name, desc, df = nil, var = false, &validator)
	add_argument(KXI::CLI::AnonymousArgument.new(name, desc, false, df, var, &validator))
end

#anonymous!(name, desc, var = false) {|val| ... } ⇒ KXI::CLI::AnonymousArgument

Creates new mandatory anonymous argument

Parameters:

  • name (String)

    Name of argument

  • desc (String)

    Description of argument

  • var (Bool) (defaults to: false)

    Determines whether argument is variadic

Yields:

  • (val)

    Validator function for value of argument

Yield Parameters:

  • val (String, Array<String>)

    Value of argument

Returns:



88
89
90
# File 'lib/kxi/cli/verb.rb', line 88

def anonymous!(name, desc, var = false, &validator)
	add_argument(KXI::CLI::AnonymousArgument.new(name, desc, true, nil, var, &validator))
end

#argumentsKXI::Collections::ProtectedCollection

Gets the arguments assigned to this verb

Returns:



28
29
30
# File 'lib/kxi/cli/verb.rb', line 28

def arguments
	KXI::Collections::ProtectedCollection.new(@args)
end

#descriptionString

Gets the description of verb

Returns:

  • (String)

    Description of verb



15
16
17
# File 'lib/kxi/cli/verb.rb', line 15

def description
	@desc
end

#enable_helpObject

Enables help for this verb and it’s children



33
34
35
36
37
38
# File 'lib/kxi/cli/verb.rb', line 33

def enable_help
	unless @help
		@help = true
		@verbs.foreach { |i| i.enable_help }
	end
end

#flag(name, desc, sh = nil) ⇒ KXI::CLI::FlagArgument

Creates new flag argument

Parameters:

  • name (String)

    Name of flag

  • desc (String)

    Description of flag

  • sh (String, nil) (defaults to: nil)

    Shortcut symbol

Returns:



126
127
128
# File 'lib/kxi/cli/verb.rb', line 126

def flag(name, desc, sh = nil)
	add_argument(KXI::CLI::FlagArgument.new(name, desc, sh))
end

#helpObject

Prints help message of verb



216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'lib/kxi/cli/verb.rb', line 216

def help
	puts(@name)
	puts("\t#{@desc}")
	puts
	puts('Usage:')
	if @verbs.count == 0
		print("\t")
		print("#{@ctx} ") if @ctx != nil
		print(@name)
		args = @args.order_by_descending { |a, b| a.order <=> b.order }
		args.where { |i| i.required? or i.is_a?(KXI::CLI::AnonymousArgument) }.foreach do |i|
			print(" #{i.syntax}")
		end
		puts
		if args.count > 0
			puts
			max = args.max { |a, b| a.headline.length <=> b.headline.length }.headline.length
			args.foreach do |a|
				puts("\t#{a.headline.ljust(max)}   #{a.description}")
			end
		end
	else
		max = @verbs.max { |a, b| a.name.length <=> b.name.length }.name.length
		@verbs.foreach do |v|
			print("\t")
			print("#{@ctx} ") if @ctx != nil
			puts("#{@name} #{v.name.ljust(max)}   #{v.description}")
		end
	end
end

#nameString

Gets the name of verb

Returns:

  • (String)

    Name of verb



9
10
11
# File 'lib/kxi/cli/verb.rb', line 9

def name
	@name
end

#named(name, val, desc, sh = nil, df = nil, var = false) {|val| ... } ⇒ KXI::CLI::NamedArgument

Creates new optional named argument

Parameters:

  • name (String)

    Name of argument

  • val (String)

    Name of value

  • desc (String)

    Description of argument

  • sh (String, nil) (defaults to: nil)

    Shortcut symbol

  • df (Object, nil) (defaults to: nil)

    Default value of argument

  • var (Bool) (defaults to: false)

    Determines whether argument is variadic

Yields:

  • (val)

    Validator function for value of argument

Yield Parameters:

  • val (String, Array<String>)

    Value of argument

Returns:



102
103
104
# File 'lib/kxi/cli/verb.rb', line 102

def named(name, val, desc, sh = nil, df = nil, var = false, &validator)
	add_argument(KXI::CLI::NamedArgument.new(name, val, desc, sh, false, df, var, &validator))
end

#named!(name, val, desc, sh = nil, var = false) {|val| ... } ⇒ KXI::CLI::NamedArgument

Creates new mandatory named argument

Parameters:

  • name (String)

    Name of argument

  • val (String)

    Name of value

  • desc (String)

    Description of argument

  • sh (String, nil) (defaults to: nil)

    Shortcut symbol

  • var (Bool) (defaults to: false)

    Determines whether argument is variadic

Yields:

  • (val)

    Validator function for value of argument

Yield Parameters:

  • val (String, Array<String>)

    Value of argument

Returns:



116
117
118
# File 'lib/kxi/cli/verb.rb', line 116

def named!(name, val, desc, sh = nil, var = false, &validator)
	add_argument(KXI::CLI::NamedArgument.new(name, val, desc, sh, true, nil, var, &validator))
end

#verb(name, desc) ⇒ KXI::CLI::Verb

Creates a new child verb

Parameters:

  • name (String)

    Name of verb

  • desc (String)

    Description of verb

Returns:



63
64
65
66
# File 'lib/kxi/cli/verb.rb', line 63

def verb(name, desc)
	check_name(name)
	add_verb(Verb.new(name, desc, @ctx == nil ? @name : "#{@ctx} #{@name}") { |v| yield(v) if block_given? })
end