Class: DenCli::CMD

Inherits:
Object
  • Object
show all
Defined in:
lib/dencli/cmd.rb

Defined Under Namespace

Classes: Opt

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(parent, name, description, exe, defined_in) ⇒ CMD

Returns a new instance of CMD.



7
8
9
10
11
12
13
14
15
16
17
18
# File 'lib/dencli/cmd.rb', line 7

def initialize parent, name, description, exe, defined_in
	raise "Proc expected, instead of: #{exe.inspect}"  unless Proc === exe
	@parent, @name, @description, @exe, @defined_in = parent, name, description, lambda( &exe), defined_in
	@parameters = @exe.parameters
	@arguments_required = @exe.parameters.select {|e| :req == e[0] }.map {|e| e[1] }
	@arguments_additional = @exe.parameters.select {|e| :opt == e[0] }.map {|e| e[1] }
	@arguments = @exe.parameters.select {|e| :req == e[0] or :opt == e[0] }.map {|e| e[1] }
	@options_required = @exe.parameters.select {|e| :keyreq == e[0] }.map {|e| e[1] }
	@options_additional = @exe.parameters.select {|e| :key == e[0] }.map {|e| e[1] }
	@options = {}
	completion {|*a| [] }
end

Instance Attribute Details

#argumentsObject (readonly)

Returns the value of attribute arguments.



23
24
25
# File 'lib/dencli/cmd.rb', line 23

def arguments
  @arguments
end

#arguments_additionalObject (readonly) Also known as: additional

Returns the value of attribute arguments_additional.



23
24
25
# File 'lib/dencli/cmd.rb', line 23

def arguments_additional
  @arguments_additional
end

#arguments_requiredObject (readonly) Also known as: required

Returns the value of attribute arguments_required.



23
24
25
# File 'lib/dencli/cmd.rb', line 23

def arguments_required
  @arguments_required
end

#completion(&exe) ⇒ Object (readonly)

Returns the value of attribute completion.



5
6
7
# File 'lib/dencli/cmd.rb', line 5

def completion
  @completion
end

#defined_inObject (readonly)

Returns the value of attribute defined_in.



5
6
7
# File 'lib/dencli/cmd.rb', line 5

def defined_in
  @defined_in
end

#descriptionObject (readonly)

Returns the value of attribute description.



5
6
7
# File 'lib/dencli/cmd.rb', line 5

def description
  @description
end

#exeObject (readonly)

Returns the value of attribute exe.



5
6
7
# File 'lib/dencli/cmd.rb', line 5

def exe
  @exe
end

#nameObject (readonly)

Returns the value of attribute name.



5
6
7
# File 'lib/dencli/cmd.rb', line 5

def name
  @name
end

#optionsObject (readonly)

Returns the value of attribute options.



5
6
7
# File 'lib/dencli/cmd.rb', line 5

def options
  @options
end

#options_additionalObject (readonly)

Returns the value of attribute options_additional.



23
24
25
# File 'lib/dencli/cmd.rb', line 23

def options_additional
  @options_additional
end

#options_requiredObject (readonly)

Returns the value of attribute options_required.



23
24
25
# File 'lib/dencli/cmd.rb', line 23

def options_required
  @options_required
end

#parametersObject (readonly)

Returns the value of attribute parameters.



23
24
25
# File 'lib/dencli/cmd.rb', line 23

def parameters
  @parameters
end

#parentObject (readonly)

Returns the value of attribute parent.



5
6
7
# File 'lib/dencli/cmd.rb', line 5

def parent
  @parent
end

Instance Method Details

#_full_cmd(post) ⇒ Object



20
# File 'lib/dencli/cmd.rb', line 20

def _full_cmd( post) parent._full_cmd [@name]+post end

#_help(output) ⇒ Object



112
113
114
115
# File 'lib/dencli/cmd.rb', line 112

def _help output
	output << "Usage: #{usage}\n#{description}\n"
	_help_options output
end

#_help_options(output) ⇒ Object



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/dencli/cmd.rb', line 123

def _help_options output
	sc, lc, dc = 0, 0, 0
	@options.each do |_, o|
		s = o.short&.length || 0
		l = o.long&.length || 0
		v = o.val&.length || 0
		d = o.desc&.to_s&.length || 0
		d += 3 + o.default.to_s.length  if o.default?
		if 0 == l
			x = s + (0==v ? 0 : 1+v)
			sc = x  if sc < x
		else
			sc = s  if sc < s
			x = l + (0==v ? 0 : 1+v)
			lc = x  if lc < x
		end
		dc = d  if dc < d
	end
	format = "  %-#{sc}s%s %-#{lc}s %s\n"
	@options.map do |_, o|
		s, l, v, y = o.short, o.long, o.val, ','
		if l.nil?
			s += "#{v}"  if v
			y = ' '
		elsif s.nil?
			l += "=#{v}"  if v
			y = ' '
		end
		d = o.desc || ''
		d += " (#{o.default})"  if o.default?
		output << format % [ s, y, l, d ]
	end
end

#_usage(output) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/dencli/cmd.rb', line 76

def _usage output
	output << full_cmd.join( ' ')
	@options.each do |_, o|
		s = "#{o.short||o.long}#{(!o.short && o.val) ? ?= : ''}#{o.val}"
		output << (o.required? ? " #{s}" : " [#{s}]")
	end
	if @exe.lambda?
		parameters.each do |(type, name)|
			case type
			when :req
				output << " <#{name}>"
			when :opt
				output << " [<#{name}>]"
			when :rest
				output << " [<#{name}> ...]"
			end
		end
	else
		output << ' [...]'
	end
end

#call(*as) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/dencli/cmd.rb', line 33

def call *as
	os = {}
	unless @options.empty?
		# options like --abc | -x will be provided in os
		options = OptionParser.new
		options.banner = "#{full_cmd.join ' '}"
		# see also @options-array
		@options.each {|_, opt| opt.on options, os }
		as = options.parse! as
	end
	if @exe.lambda?
		# The difference between a lambda and a Proc is, that Proc has anytime arity=-1.
		# There will be no check if all arguments are given or some were missing or more than expected.
		# lambda checks these arguments and has a arity.
		# We will check it to provide useful errors.
		pars = required
		if as.length < pars.length
			raise DenCli::UsageError, "Missing parameter(s): #{pars[as.length..-1].join " "}"
		end
		if parameters.select {|e| :rest == e[0] }.empty?
			pars = pars + additional
			if as.length > pars.length
				raise DenCli::UsageError, "Unused parameter(s): #{as[-pars.length..-1].shelljoin}"
			end
		end
		kr = @options.select {|_, o| o.required? and not os.has_key? o.name }
		unless kr.empty?
			raise DenCli::UsageError, "Missing argument(s): #{kr.map {|_, o| o.long || o.short }.join ', '}"
		end
	end
	if os.empty?
		@exe.call *as
	else
		@exe.call *as, **os
	end
end

#commands(*args) {|name, _self| ... } ⇒ Object

Yields:

Yield Parameters:

  • _self (DenCli::CMD)

    the object that the method was called on



98
99
100
# File 'lib/dencli/cmd.rb', line 98

def commands *args
	yield name, self
end

#complete(*pre, str) ⇒ Object



29
30
31
# File 'lib/dencli/cmd.rb', line 29

def complete *pre, str
	@completion.call *pre, str
end

#full_cmdObject



21
# File 'lib/dencli/cmd.rb', line 21

def full_cmd() _full_cmd [] end

#goto(*args) ⇒ Object



102
103
104
# File 'lib/dencli/cmd.rb', line 102

def goto *args
	self
end

#help(output: nil) ⇒ Object



106
107
108
109
110
# File 'lib/dencli/cmd.rb', line 106

def help output: nil
	output ||= ''
	_help output
	output
end

#help_options(output: nil) ⇒ Object



117
118
119
120
121
# File 'lib/dencli/cmd.rb', line 117

def help_options output: nil
	output ||= ''
	_help_options output
	output
end

#inspectObject



226
227
228
229
230
231
232
# File 'lib/dencli/cmd.rb', line 226

def inspect
	"#<%s:0x%x %s @name=%p @description=%p @options=%p @parent=<%s:0x%x %s> @exe=<arity=%d>>" % [
		self.class.name, self.object_id, self.full_cmd,
		@name, @description, @options.values, @parent.class.name, @parent.class.object_id, @parent.full_cmd,
		@exe.arity
	]
end

#opt(name, opt, *args, desc, default: NilClass, &conv) ⇒ Object



220
221
222
223
224
# File 'lib/dencli/cmd.rb', line 220

def opt name, opt, *args, desc, default: NilClass, &conv
	r = Opt.new( self, name, opt, *args, desc, default: default, &conv)
	@options[r.name] = r
	self
end

#usage(output: nil) ⇒ Object



70
71
72
73
74
# File 'lib/dencli/cmd.rb', line 70

def usage output: nil
	output ||= ''
	_usage output
	output
end