cl 0.1.12 → 0.1.13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -3
- data/Gemfile.lock +2 -2
- data/NOTES.md +12 -8
- data/README.md +897 -13
- data/examples/readme/alias +22 -0
- data/examples/readme/arg +16 -0
- data/examples/readme/arg_array +16 -0
- data/examples/readme/arg_type +18 -0
- data/examples/readme/args_splat +43 -0
- data/examples/readme/array +18 -0
- data/examples/readme/default +18 -0
- data/examples/readme/deprecated +21 -0
- data/examples/readme/deprecated_alias +20 -0
- data/examples/readme/downcase +18 -0
- data/examples/readme/enum +26 -0
- data/examples/readme/example +17 -0
- data/examples/readme/format +29 -0
- data/examples/readme/internal +18 -0
- data/examples/readme/opts +29 -0
- data/examples/readme/opts_block +26 -0
- data/examples/readme/range +29 -0
- data/examples/readme/required +29 -0
- data/examples/readme/requireds +36 -0
- data/examples/readme/requires +32 -0
- data/examples/readme/see +21 -0
- data/examples/readme/type +22 -0
- data/lib/cl.rb +26 -66
- data/lib/cl/arg.rb +9 -5
- data/lib/cl/cast.rb +5 -1
- data/lib/cl/cmd.rb +11 -49
- data/lib/cl/ctx.rb +3 -5
- data/lib/cl/dsl.rb +176 -0
- data/lib/cl/errors.rb +73 -0
- data/lib/cl/help/cmd.rb +8 -3
- data/lib/cl/helper.rb +8 -0
- data/lib/cl/opt.rb +13 -0
- data/lib/cl/opts.rb +27 -8
- data/lib/cl/runner.rb +10 -0
- data/lib/cl/runner/default.rb +22 -2
- data/lib/cl/runner/multi.rb +6 -4
- data/lib/cl/ui.rb +11 -2
- data/lib/cl/version.rb +1 -1
- metadata +27 -2
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$: << File.expand_path('lib')
|
3
|
+
|
4
|
+
require 'cl'
|
5
|
+
|
6
|
+
class Add < Cl::Cmd
|
7
|
+
opt '--to GROUP'
|
8
|
+
opt '--retries INT', requires: :to
|
9
|
+
|
10
|
+
def run
|
11
|
+
p to, retries
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Cl.new('owners').run(%w(add --to one --retries 1))
|
16
|
+
|
17
|
+
# Output:
|
18
|
+
#
|
19
|
+
# "one"
|
20
|
+
# 1
|
21
|
+
|
22
|
+
Cl.new('owners').run(%w(add --retries 1))
|
23
|
+
|
24
|
+
# Missing option: to (required by retries)
|
25
|
+
#
|
26
|
+
# Usage: requires add [options]
|
27
|
+
#
|
28
|
+
# Options:
|
29
|
+
#
|
30
|
+
# --to GROUP type: string
|
31
|
+
# --retries INT type: string, requires: to
|
32
|
+
# --help Get help on this command
|
data/examples/readme/see
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$: << File.expand_path('lib')
|
3
|
+
|
4
|
+
require 'cl'
|
5
|
+
|
6
|
+
class Add < Cl::Cmd
|
7
|
+
opt '--to GROUP', see: 'https://docs.io/cli/owners/add'
|
8
|
+
|
9
|
+
def run
|
10
|
+
p retries
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
Cl.new('owners').run(%w(add --help))
|
15
|
+
|
16
|
+
# Usage: see add [options]
|
17
|
+
#
|
18
|
+
# Options:
|
19
|
+
#
|
20
|
+
# --to GROUP type: string, see: https://docs.io/cli/owners/add
|
21
|
+
# --help Get help on this command
|
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$: << File.expand_path('lib')
|
3
|
+
|
4
|
+
require 'cl'
|
5
|
+
|
6
|
+
class Add < Cl::Cmd
|
7
|
+
opt '--active BOOL', type: :boolean
|
8
|
+
opt '--retries INT', type: :integer
|
9
|
+
opt '--sleep FLOAT', type: :float
|
10
|
+
|
11
|
+
def run
|
12
|
+
p active.class, retries.class, sleep.class
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
Cl.new('owners').run(%w(add --active yes --retries 1 --sleep 0.1))
|
17
|
+
|
18
|
+
# Output:
|
19
|
+
#
|
20
|
+
# TrueClass
|
21
|
+
# Integer
|
22
|
+
# Float
|
data/lib/cl.rb
CHANGED
@@ -1,70 +1,17 @@
|
|
1
1
|
require 'cl/cmd'
|
2
2
|
require 'cl/help'
|
3
|
-
require 'cl/runner
|
4
|
-
require 'cl/
|
3
|
+
require 'cl/runner'
|
4
|
+
require 'cl/errors'
|
5
5
|
|
6
6
|
class Cl
|
7
|
-
class Error < StandardError
|
8
|
-
MSGS = {
|
9
|
-
missing_args: 'Missing arguments (given: %s, required: %s)',
|
10
|
-
too_many_args: 'Too many arguments (given: %s, allowed: %s)',
|
11
|
-
wrong_type: 'Wrong argument type (given: %s, expected: %s)',
|
12
|
-
exceeding_max: 'Exceeds max value: %s',
|
13
|
-
invalid_format: 'Invalid format: %s',
|
14
|
-
unknown_values: 'Unknown value: %s',
|
15
|
-
required_opt: 'Missing required option: %s',
|
16
|
-
required_opts: 'Missing required options: %s',
|
17
|
-
requires_opt: 'Missing option: %s',
|
18
|
-
requires_opts: 'Missing options: %s',
|
19
|
-
}
|
20
|
-
|
21
|
-
def initialize(msg, *args)
|
22
|
-
super(MSGS[msg] ? MSGS[msg] % args : msg)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
ArgumentError = Class.new(Error)
|
27
|
-
OptionError = Class.new(Error)
|
28
|
-
RequiredOpts = Class.new(OptionError)
|
29
|
-
|
30
|
-
class RequiredsOpts < OptionError
|
31
|
-
def initialize(opts)
|
32
|
-
opts = opts.map { |alts| alts.map { |alt| Array(alt).join(' and ') }.join(', or ' ) }
|
33
|
-
super(:requires_opts, opts.join('; '))
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
class RequiresOpts < OptionError
|
38
|
-
def initialize(opts)
|
39
|
-
msg = opts.size == 1 ? :requires_opt : :requires_opts
|
40
|
-
opts = opts.map { |one, other| "#{one} (required by #{other})" }.join(', ')
|
41
|
-
super(msg, opts)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
class ExceedingMax < OptionError
|
46
|
-
def initialize(opts)
|
47
|
-
opts = opts.map { |opt, max| "#{opt} (max: #{max})" }.join(', ')
|
48
|
-
super(:exceeding_max, opts)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
class InvalidFormat < OptionError
|
53
|
-
def initialize(opts)
|
54
|
-
opts = opts.map { |opt, format| "#{opt} (format: #{format})" }.join(', ')
|
55
|
-
super(:invalid_format, opts)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
class UnknownValues < OptionError
|
60
|
-
def initialize(opts)
|
61
|
-
opts = opts.map { |(key, value, known)| "#{key}=#{value} (known values: #{known.join(', ')})" }.join(', ')
|
62
|
-
super(:unknown_values, opts)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
7
|
attr_reader :ctx, :name, :opts
|
67
8
|
|
9
|
+
# @overload initialize(ctx, name, opts)
|
10
|
+
# @param ctx [Cl::Ctx] the current execution context (optional)
|
11
|
+
# @param name [String] the program (executable) name (optional, defaults to $0)
|
12
|
+
# @param opts [Hash] options (optional)
|
13
|
+
# @option opts [Cl::Runner] :runner registry key for a runner (optional, defaults to :default)
|
14
|
+
# @option opts [Cl::Ui] :ui the ui for handling user interaction
|
68
15
|
def initialize(*args)
|
69
16
|
ctx = args.shift if args.first.is_a?(Ctx)
|
70
17
|
@opts = args.last.is_a?(Hash) ? args.pop : {}
|
@@ -72,19 +19,32 @@ class Cl
|
|
72
19
|
@ctx = ctx || Ctx.new(name, opts)
|
73
20
|
end
|
74
21
|
|
22
|
+
# Runs the command.
|
23
|
+
#
|
24
|
+
# Instantiates a runner with the given arguments, and runs it.
|
25
|
+
#
|
26
|
+
# If the command fails (raises a Cl::Error) then the exception is caught, and
|
27
|
+
# the process aborted with the error message and help output for the given
|
28
|
+
# command.
|
29
|
+
#
|
30
|
+
# @param args [Array<String>] arguments (usually ARGV)
|
75
31
|
def run(args)
|
76
32
|
runner(args.map(&:dup)).run
|
33
|
+
rescue UnknownCmd => e
|
34
|
+
ctx.abort e
|
77
35
|
rescue Error => e
|
78
|
-
abort
|
36
|
+
ctx.abort e, help(args.first)
|
79
37
|
end
|
80
38
|
|
39
|
+
# Returns a runner instance for the given arguments.
|
81
40
|
def runner(args)
|
82
41
|
runner = :default if args.first.to_s == 'help'
|
83
42
|
runner ||= opts[:runner] || :default
|
84
|
-
Runner
|
43
|
+
Runner[runner].new(ctx, args)
|
85
44
|
end
|
86
45
|
|
87
|
-
#
|
88
|
-
|
89
|
-
|
46
|
+
# Returns help output for the given command
|
47
|
+
def help(*args)
|
48
|
+
runner(['help', *args]).cmd.help
|
49
|
+
end
|
90
50
|
end
|
data/lib/cl/arg.rb
CHANGED
@@ -20,20 +20,24 @@ class Cl
|
|
20
20
|
opts[:description]
|
21
21
|
end
|
22
22
|
|
23
|
-
def splat?
|
24
|
-
type == :array
|
25
|
-
end
|
26
|
-
|
27
23
|
def required?
|
28
24
|
!!opts[:required]
|
29
25
|
end
|
30
26
|
|
27
|
+
def separator
|
28
|
+
opts[:sep]
|
29
|
+
end
|
30
|
+
|
31
|
+
def splat?
|
32
|
+
opts[:splat] && type == :array
|
33
|
+
end
|
34
|
+
|
31
35
|
def to_s
|
32
36
|
str = name
|
33
37
|
case type
|
34
38
|
when :array then str = "#{str}.."
|
35
|
-
when :integer, :int then str = "#{str}:int"
|
36
39
|
when :boolean, :bool then str = "#{str}:bool"
|
40
|
+
when :integer, :int then str = "#{str}:int"
|
37
41
|
when :float then str = "#{str}:float"
|
38
42
|
end
|
39
43
|
required? ? str : "[#{str}]"
|
data/lib/cl/cast.rb
CHANGED
@@ -8,7 +8,7 @@ class Cl
|
|
8
8
|
when nil
|
9
9
|
value
|
10
10
|
when :array
|
11
|
-
Array(value).compact.flatten.map { |value|
|
11
|
+
Array(value).compact.flatten.map { |value| split(value) }.flatten
|
12
12
|
when :string, :str
|
13
13
|
value.to_s unless value.to_s.empty?
|
14
14
|
when :flag, :boolean, :bool
|
@@ -25,5 +25,9 @@ class Cl
|
|
25
25
|
rescue ::ArgumentError => e
|
26
26
|
raise ArgumentError.new(:wrong_type, value.inspect, type)
|
27
27
|
end
|
28
|
+
|
29
|
+
def split(value)
|
30
|
+
separator ? value.to_s.split(separator) : value
|
31
|
+
end
|
28
32
|
end
|
29
33
|
end
|
data/lib/cl/cmd.rb
CHANGED
@@ -1,21 +1,28 @@
|
|
1
1
|
require 'registry'
|
2
2
|
require 'cl/args'
|
3
|
-
require 'cl/
|
3
|
+
require 'cl/dsl'
|
4
4
|
require 'cl/opts'
|
5
5
|
require 'cl/parser'
|
6
6
|
|
7
7
|
class Cl
|
8
|
+
# Base class for all command classes that can be run.
|
9
|
+
#
|
10
|
+
# Inherit your command classes from this class, use the {Cl::Cmd::Dsl} to
|
11
|
+
# declare arguments, options, summary, description, examples etc., and
|
12
|
+
# implement the method #run.
|
13
|
+
#
|
14
|
+
# See {Cl::Cmd::Dsl} for details on the DSL methods.
|
8
15
|
class Cmd
|
9
16
|
include Registry
|
17
|
+
extend Dsl
|
10
18
|
|
11
19
|
class << self
|
12
|
-
include Merge
|
20
|
+
include Merge, Underscore
|
13
21
|
|
14
22
|
inherited = ->(const) do
|
15
23
|
const.register [registry_key, underscore(const.name.split('::').last)].compact.join(':') if const.name
|
16
24
|
const.define_singleton_method(:inherited, &inherited)
|
17
25
|
end
|
18
|
-
|
19
26
|
define_method(:inherited, &inherited)
|
20
27
|
|
21
28
|
def cmds
|
@@ -27,51 +34,6 @@ class Cl
|
|
27
34
|
opts = merge(ctx.config[registry_key], opts) if ctx.config[registry_key]
|
28
35
|
[args, opts || {}]
|
29
36
|
end
|
30
|
-
|
31
|
-
def abstract
|
32
|
-
unregister
|
33
|
-
end
|
34
|
-
|
35
|
-
def args(*args)
|
36
|
-
return @args ||= Args.new unless args.any?
|
37
|
-
opts = args.last.is_a?(Hash) ? args.pop : {}
|
38
|
-
args.each { |arg| arg(arg, opts) }
|
39
|
-
end
|
40
|
-
|
41
|
-
def arg(*args)
|
42
|
-
self.args.define(self, *args)
|
43
|
-
end
|
44
|
-
|
45
|
-
def opt(*args, &block)
|
46
|
-
self.opts.define(self, *args, &block)
|
47
|
-
end
|
48
|
-
|
49
|
-
def opts
|
50
|
-
@opts ||= self == Cmd ? Opts.new : superclass.opts.dup
|
51
|
-
end
|
52
|
-
|
53
|
-
def description(description = nil)
|
54
|
-
description ? @description = description : @description
|
55
|
-
end
|
56
|
-
|
57
|
-
def required?
|
58
|
-
!!@required
|
59
|
-
end
|
60
|
-
|
61
|
-
def required(*required)
|
62
|
-
required.any? ? self.required << required : @required ||= []
|
63
|
-
end
|
64
|
-
|
65
|
-
def summary(summary = nil)
|
66
|
-
summary ? @summary = summary : @summary
|
67
|
-
end
|
68
|
-
alias purpose summary
|
69
|
-
|
70
|
-
def underscore(string)
|
71
|
-
string.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
72
|
-
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
73
|
-
downcase
|
74
|
-
end
|
75
37
|
end
|
76
38
|
|
77
39
|
opt '--help', 'Get help on this command'
|
@@ -92,7 +54,7 @@ class Cl
|
|
92
54
|
def deprecated_opts
|
93
55
|
opts = self.class.opts.select(&:deprecated?)
|
94
56
|
opts = opts.select { |opt| self.opts.key?(opt.deprecated[0]) }
|
95
|
-
opts.map(&:deprecated)
|
57
|
+
opts.map(&:deprecated).to_h
|
96
58
|
end
|
97
59
|
end
|
98
60
|
end
|
data/lib/cl/ctx.rb
CHANGED
@@ -13,13 +13,11 @@ class Cl
|
|
13
13
|
|
14
14
|
def initialize(name, opts = {})
|
15
15
|
@config = Config.new(name).to_h
|
16
|
-
@ui = Ui.new(self, opts)
|
16
|
+
@ui = opts[:ui] || Ui.new(self, opts)
|
17
17
|
end
|
18
18
|
|
19
|
-
def abort(
|
20
|
-
|
21
|
-
ui.error(str)
|
22
|
-
exit 1
|
19
|
+
def abort(error, *strs)
|
20
|
+
ui.abort(error, *strs)
|
23
21
|
end
|
24
22
|
|
25
23
|
def test?
|
data/lib/cl/dsl.rb
ADDED
@@ -0,0 +1,176 @@
|
|
1
|
+
require 'cl/helper'
|
2
|
+
|
3
|
+
class Cl
|
4
|
+
class Cmd
|
5
|
+
module Dsl
|
6
|
+
include Merge, Underscore
|
7
|
+
|
8
|
+
def abstract
|
9
|
+
unregister
|
10
|
+
end
|
11
|
+
|
12
|
+
# Declare multiple arguments at once
|
13
|
+
#
|
14
|
+
# See {Cl::Cmd::Dsl#arg} for more details.
|
15
|
+
def args(*args)
|
16
|
+
return @args ||= Args.new unless args.any?
|
17
|
+
opts = args.last.is_a?(Hash) ? args.pop : {}
|
18
|
+
args.each { |arg| arg(arg, opts) }
|
19
|
+
end
|
20
|
+
|
21
|
+
# Declares an argument
|
22
|
+
#
|
23
|
+
# Use this method to declare arguments the command accepts.
|
24
|
+
#
|
25
|
+
# For example:
|
26
|
+
#
|
27
|
+
# ```ruby
|
28
|
+
# class GitPush < Cl::Cmd
|
29
|
+
# arg remote, 'The Git remote to push to.', type: :string
|
30
|
+
# end
|
31
|
+
# ```
|
32
|
+
#
|
33
|
+
# Arguments do not need to be declared, in order to be passed to the Cmd
|
34
|
+
# instance, but it is useful to do so for more explicit help output, and
|
35
|
+
# in order to define extra properties on the arguments (e.g. their type).
|
36
|
+
#
|
37
|
+
# @overload arg(name, description, opts)
|
38
|
+
# @param name [String] the argument name
|
39
|
+
# @param description [String] description for the argument, shown in the help output
|
40
|
+
# @param opts [Hash] argument options
|
41
|
+
# @option opts [Symbol] :type the argument type (`:array`, `:string`, `:integer`, `:float`, `:boolean`)
|
42
|
+
# @option opts [Boolean] :required whether the argument is required
|
43
|
+
# @option opts [String] :sep separator to split strings by, if the argument is an array
|
44
|
+
# @option opts [Boolean] :splat whether to splat the argument, if the argument is an array
|
45
|
+
def arg(*args)
|
46
|
+
self.args.define(self, *args)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Declare a description for this command
|
50
|
+
#
|
51
|
+
# This is the description that will be shown in the command details help output.
|
52
|
+
#
|
53
|
+
# For example:
|
54
|
+
#
|
55
|
+
# ```ruby
|
56
|
+
# class Api::Login < Cl::Cmd
|
57
|
+
# description <<~str
|
58
|
+
# Use this command to login to our API.
|
59
|
+
# [...]
|
60
|
+
# str
|
61
|
+
# end
|
62
|
+
# ```
|
63
|
+
#
|
64
|
+
# @return [String] the description if no argument was given
|
65
|
+
def description(description = nil)
|
66
|
+
description ? @description = description : @description
|
67
|
+
end
|
68
|
+
|
69
|
+
# Declare an example text for this command
|
70
|
+
#
|
71
|
+
# This is the example text that will be shown in the command details help output.
|
72
|
+
#
|
73
|
+
# For example:
|
74
|
+
#
|
75
|
+
# ```ruby
|
76
|
+
# class Api::Login < Cl::Cmd
|
77
|
+
# example <<~str
|
78
|
+
# For example, in order to login to our API with your username and
|
79
|
+
# password, you can use:
|
80
|
+
#
|
81
|
+
# ./api --username [username] --password [password]
|
82
|
+
# str
|
83
|
+
# end
|
84
|
+
# ```
|
85
|
+
#
|
86
|
+
# @return [String] the description if no argument was given
|
87
|
+
def examples(examples = nil)
|
88
|
+
examples ? @examples = examples : @examples
|
89
|
+
end
|
90
|
+
|
91
|
+
# Declares an option
|
92
|
+
#
|
93
|
+
# Use this method to declare options a command accepts.
|
94
|
+
#
|
95
|
+
# See [this section](/#Options) for a full explanation on each feature supported by command options.
|
96
|
+
#
|
97
|
+
# @overload opt(name, description, opts)
|
98
|
+
# @param name [String] the option name
|
99
|
+
# @param description [String] description for the option, shown in the help output
|
100
|
+
# @param opts [Hash] option options
|
101
|
+
# @option opts [Symbol or Array<Symbol>] :alias alias name(s) for the option
|
102
|
+
# @option opts [Object] :default default value for the option
|
103
|
+
# @option opts [String or Symbol] :deprecated deprecation message for the option, or if given a Symbol, deprecated alias name
|
104
|
+
# @option opts [Boolean] :downcase whether to downcase the option value
|
105
|
+
# @option opts [Array<Object>] :enum list of acceptable option values
|
106
|
+
# @option opts [String] :example example(s) for the option, shown in help output
|
107
|
+
# @option opts [Regexp] :format acceptable option value format
|
108
|
+
# @option opts [Boolean] :internal whether to hide the option from help output
|
109
|
+
# @option opts [Numeric] :min minimum acceptable value
|
110
|
+
# @option opts [Numeric] :max maximum acceptable value
|
111
|
+
# @option opts [String] :see see also reference (e.g. documentation URL)
|
112
|
+
# @option opts [Symbol] :type the option value type (`:array`, `:string`, `:integer`, `:float`, `:boolean`)
|
113
|
+
# @option opts [Boolean] :required whether the option is required
|
114
|
+
# @option opts [Array<Symbol> or Symbol] :requires (an)other options required this option depends on
|
115
|
+
def opt(*args, &block)
|
116
|
+
self.opts.define(self, *args, &block)
|
117
|
+
end
|
118
|
+
|
119
|
+
# Collection of options supported by this command
|
120
|
+
#
|
121
|
+
# This collection is being inherited from super classes.
|
122
|
+
def opts
|
123
|
+
@opts ||= self == Cmd ? Opts.new : superclass.opts.dup
|
124
|
+
end
|
125
|
+
|
126
|
+
# Whether any alternative option requirements have been declared.
|
127
|
+
#
|
128
|
+
# See [this section](/#Required_Options) for a full explanation of how
|
129
|
+
# alternative option requirements can be used.
|
130
|
+
def required?
|
131
|
+
!!@required
|
132
|
+
end
|
133
|
+
|
134
|
+
# Declare alternative option requirements.
|
135
|
+
#
|
136
|
+
# Alternative (combinations of) options can be required. These need to be declared on the class body.
|
137
|
+
#
|
138
|
+
# For example,
|
139
|
+
#
|
140
|
+
# ```ruby
|
141
|
+
# class Api::Login < Cl::Cmd
|
142
|
+
# # DNF, read as: api_key OR username AND password
|
143
|
+
# required :api_key, [:username, :password]
|
144
|
+
#
|
145
|
+
# opt '--api_key KEY'
|
146
|
+
# opt '--username NAME'
|
147
|
+
# opt '--password PASS'
|
148
|
+
# end
|
149
|
+
# ```
|
150
|
+
# Will require either the option `api_key`, or both the options `username` and `password`.
|
151
|
+
#
|
152
|
+
# See [this section](/#Required_Options) for a full explanation of how
|
153
|
+
# alternative option requirements can be used.
|
154
|
+
def required(*required)
|
155
|
+
required.any? ? self.required << required : @required ||= []
|
156
|
+
end
|
157
|
+
|
158
|
+
# Declare a summary for this command
|
159
|
+
#
|
160
|
+
# This is the summary that will be shown in both the command list, and command details help output.
|
161
|
+
#
|
162
|
+
# For example:
|
163
|
+
#
|
164
|
+
# ```ruby
|
165
|
+
# class Api::Login < Cl::Cmd
|
166
|
+
# summary 'Login to the API'
|
167
|
+
# end
|
168
|
+
# ```
|
169
|
+
#
|
170
|
+
# @return [String] the summary if no argument was given
|
171
|
+
def summary(summary = nil)
|
172
|
+
summary ? @summary = summary : @summary
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|