command_kit 0.1.0.pre1 → 0.1.0.pre2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +37 -140
- data/examples/colors.rb +30 -0
- data/examples/command.rb +65 -0
- data/examples/pager.rb +30 -0
- data/lib/command_kit/arguments.rb +49 -18
- data/lib/command_kit/arguments/argument.rb +14 -44
- data/lib/command_kit/arguments/argument_value.rb +1 -30
- data/lib/command_kit/command.rb +45 -3
- data/lib/command_kit/commands.rb +6 -0
- data/lib/command_kit/commands/auto_load/subcommand.rb +3 -0
- data/lib/command_kit/commands/subcommand.rb +3 -0
- data/lib/command_kit/description.rb +3 -1
- data/lib/command_kit/examples.rb +3 -1
- data/lib/command_kit/help.rb +3 -0
- data/lib/command_kit/help/man.rb +74 -39
- data/lib/command_kit/main.rb +2 -0
- data/lib/command_kit/options.rb +46 -9
- data/lib/command_kit/options/option.rb +35 -5
- data/lib/command_kit/options/option_value.rb +40 -3
- data/lib/command_kit/pager.rb +6 -0
- data/lib/command_kit/version.rb +1 -1
- data/lib/command_kit/xdg.rb +8 -1
- data/spec/arguments/argument_spec.rb +3 -39
- data/spec/arguments/argument_value_spec.rb +1 -61
- data/spec/arguments_spec.rb +7 -0
- data/spec/help/man_spec.rb +348 -0
- data/spec/options/option_spec.rb +45 -6
- data/spec/options/option_value_spec.rb +52 -3
- data/spec/pager_spec.rb +2 -4
- metadata +10 -8
- data/lib/command_kit/arguments/usage.rb +0 -6
- data/lib/command_kit/options/usage.rb +0 -6
data/lib/command_kit/main.rb
CHANGED
data/lib/command_kit/options.rb
CHANGED
@@ -9,24 +9,28 @@ module CommandKit
|
|
9
9
|
#
|
10
10
|
# include CommandKit::Options
|
11
11
|
#
|
12
|
-
# option :foo,
|
13
|
-
#
|
14
|
-
# desc:
|
12
|
+
# option :foo, short: '-f',
|
13
|
+
# value: {type: String},
|
14
|
+
# desc: "Foo option"
|
15
15
|
#
|
16
|
-
# option :bar,
|
17
|
-
#
|
18
|
-
#
|
16
|
+
# option :bar, short: '-b',
|
17
|
+
# value: {
|
18
|
+
# type: String,
|
19
|
+
# usage: 'STR:STR:...'
|
20
|
+
# },
|
19
21
|
# desc: "Bar option" do |arg|
|
20
22
|
# @bar = arg.split(':')
|
21
23
|
# end
|
24
|
+
#
|
25
|
+
# ### initialize and using ivars
|
22
26
|
#
|
23
|
-
# option :number, type: Integer,
|
27
|
+
# option :number, value: {type: Integer},
|
24
28
|
# desc: 'Numbers' do |num|
|
25
29
|
# @numbers << num
|
26
30
|
# end
|
27
31
|
#
|
28
|
-
# def initialize
|
29
|
-
# super
|
32
|
+
# def initialize(**kwargs)
|
33
|
+
# super(**kwargs)
|
30
34
|
#
|
31
35
|
# @numbers = []
|
32
36
|
# end
|
@@ -78,6 +82,31 @@ module CommandKit
|
|
78
82
|
# @param [Symbol] name
|
79
83
|
# The option name.
|
80
84
|
#
|
85
|
+
# @param [Hash{Symbol => Object}] kwargs
|
86
|
+
# Keyword arguments.
|
87
|
+
#
|
88
|
+
# @option kwargs [String, nil] short
|
89
|
+
# Optional short-flag for the option.
|
90
|
+
#
|
91
|
+
# @option kwargs [String, nil] long
|
92
|
+
# Optional explicit long-flag for the option.
|
93
|
+
#
|
94
|
+
# @option kwargs [Boolean] equals
|
95
|
+
# Specifies whether the option is of the form (`--opt=value`).
|
96
|
+
#
|
97
|
+
# @option kwargs [Hash{Symbol => Object}, true, false, nil] value
|
98
|
+
# Keyword arguments for {OptionValue#initialize}, or `nil` if the option
|
99
|
+
# has no additional value.
|
100
|
+
#
|
101
|
+
# @option value [Class, Hash, Array, Regexp] type
|
102
|
+
# The type of the option's value.
|
103
|
+
#
|
104
|
+
# @option value [String, nil] usage
|
105
|
+
# The usage string for the option's value.
|
106
|
+
#
|
107
|
+
# @option kwargs [String] desc
|
108
|
+
# The description for the option.
|
109
|
+
#
|
81
110
|
# @yield [(value)]
|
82
111
|
# If a block is given, it will be passed the parsed option value.
|
83
112
|
#
|
@@ -86,6 +115,10 @@ module CommandKit
|
|
86
115
|
#
|
87
116
|
# @return [Option]
|
88
117
|
#
|
118
|
+
# @raise [TypeError]
|
119
|
+
# The `value` keyword argument was not a `Hash`, `true`, `false`, or
|
120
|
+
# `nil`.
|
121
|
+
#
|
89
122
|
# @example Define an option:
|
90
123
|
# option :foo, desc: "Foo option"
|
91
124
|
#
|
@@ -156,6 +189,10 @@ module CommandKit
|
|
156
189
|
# @param [Hash{Symbol => Object}] options
|
157
190
|
# Optional pre-populated options hash.
|
158
191
|
#
|
192
|
+
# @note
|
193
|
+
# The {#option_parser} will populate {#options} and also call any
|
194
|
+
# {ClassMethods#option option} blocks with the parsed option values.
|
195
|
+
#
|
159
196
|
def initialize(options: {}, **kwargs)
|
160
197
|
@options = options
|
161
198
|
|
@@ -13,24 +13,33 @@ module CommandKit
|
|
13
13
|
#
|
14
14
|
class Option
|
15
15
|
|
16
|
+
# The option's name.
|
17
|
+
#
|
16
18
|
# @return [Symbol]
|
17
19
|
attr_reader :name
|
18
20
|
|
21
|
+
# The option's optional short-flag.
|
22
|
+
#
|
19
23
|
# @return [String, nil]
|
20
24
|
attr_reader :short
|
21
25
|
|
26
|
+
# The option's long-flag.
|
27
|
+
#
|
22
28
|
# @return [String]
|
23
29
|
attr_reader :long
|
24
30
|
|
25
|
-
#
|
26
|
-
|
27
|
-
|
31
|
+
# The option value's type.
|
32
|
+
#
|
28
33
|
# @return [OptionValue, nil]
|
29
34
|
attr_reader :value
|
30
35
|
|
36
|
+
# The option's description.
|
37
|
+
#
|
31
38
|
# @return [String]
|
32
39
|
attr_reader :desc
|
33
40
|
|
41
|
+
# The optional block that will receive the parsed option value.
|
42
|
+
#
|
34
43
|
# @return [Proc, nil]
|
35
44
|
attr_reader :block
|
36
45
|
|
@@ -38,26 +47,39 @@ module CommandKit
|
|
38
47
|
# Initializes the option.
|
39
48
|
#
|
40
49
|
# @param [Symbol] name
|
50
|
+
# The name of the option.
|
41
51
|
#
|
42
52
|
# @param [String, nil] short
|
53
|
+
# Optional short-flag for the option.
|
43
54
|
#
|
44
55
|
# @param [String, nil] long
|
56
|
+
# Optional explicit long-flag for the option.
|
45
57
|
#
|
46
58
|
# @param [Boolean] equals
|
59
|
+
# Specifies whether the option is of the form (`--opt=value`).
|
47
60
|
#
|
48
|
-
# @param [Hash{Symbol => Object}, nil] value
|
61
|
+
# @param [Hash{Symbol => Object}, true, false, nil] value
|
49
62
|
# Keyword arguments for {OptionValue#initialize}, or `nil` if the option
|
50
63
|
# has no additional value.
|
51
64
|
#
|
52
65
|
# @option value [Class, Hash, Array, Regexp] type
|
66
|
+
# The type of the option's value.
|
53
67
|
#
|
54
68
|
# @option value [String, nil] usage
|
69
|
+
# The usage string for the option's value.
|
55
70
|
#
|
56
71
|
# @param [String] desc
|
72
|
+
# The description for the option.
|
57
73
|
#
|
58
74
|
# @yield [(value)]
|
75
|
+
# If a block is given, it will be called when the option is parsed.
|
59
76
|
#
|
60
77
|
# @yieldparam [Object, nil] value
|
78
|
+
# The given block will be passed the parsed option's value.
|
79
|
+
#
|
80
|
+
# @raise [TypeError]
|
81
|
+
# The `value` keyword argument was not a `Hash`, `true`, `false`, or
|
82
|
+
# `nil`.
|
61
83
|
#
|
62
84
|
def initialize(name, short: nil,
|
63
85
|
long: self.class.default_long_opt(name),
|
@@ -69,7 +91,13 @@ module CommandKit
|
|
69
91
|
@short = short
|
70
92
|
@long = long
|
71
93
|
@equals = equals
|
72
|
-
@value =
|
94
|
+
@value = case value
|
95
|
+
when Hash then OptionValue.new(**value)
|
96
|
+
when true then OptionValue.new()
|
97
|
+
when false, nil then nil
|
98
|
+
else
|
99
|
+
raise(TypeError,"value: keyword must be Hash, true, false, or nil")
|
100
|
+
end
|
73
101
|
@desc = desc
|
74
102
|
@block = block
|
75
103
|
end
|
@@ -79,8 +107,10 @@ module CommandKit
|
|
79
107
|
# (ex: `:long_opt`).
|
80
108
|
#
|
81
109
|
# @param [Symbol] name
|
110
|
+
# The option name.
|
82
111
|
#
|
83
112
|
# @return [String]
|
113
|
+
# The long-flag for the option.
|
84
114
|
#
|
85
115
|
def self.default_long_opt(name)
|
86
116
|
"--#{Inflector.dasherize(name)}"
|
@@ -16,6 +16,7 @@ module CommandKit
|
|
16
16
|
#
|
17
17
|
class OptionValue < Arguments::ArgumentValue
|
18
18
|
|
19
|
+
# Maps OptionParser types to USAGE strings.
|
19
20
|
USAGES = {
|
20
21
|
# NOTE: NilClass and Object are intentionally omitted
|
21
22
|
Date => 'DATE',
|
@@ -36,27 +37,52 @@ module CommandKit
|
|
36
37
|
Regexp => '/REGEXP/'
|
37
38
|
}
|
38
39
|
|
40
|
+
# The desired type of the argument value.
|
41
|
+
#
|
42
|
+
# @return [Class, Hash, Array, Regexp, nil]
|
43
|
+
attr_reader :type
|
44
|
+
|
45
|
+
# The default parsed value for the argument value.
|
46
|
+
#
|
47
|
+
# @return [Object, Proc, nil]
|
48
|
+
attr_reader :default
|
49
|
+
|
39
50
|
#
|
40
51
|
# Initializes the option value.
|
41
52
|
#
|
42
53
|
# @param [Class, Hash, Array, Regexp] type
|
54
|
+
# The type of the option value.
|
55
|
+
#
|
56
|
+
# @param [Object, Proc, nil] default
|
57
|
+
# The default parsed value for the option value.
|
43
58
|
#
|
44
59
|
# @param [String, nil] usage
|
60
|
+
# The optional usage string for the option value.
|
45
61
|
#
|
46
62
|
# @param [Hash{Symbol => Object}] kwargs
|
63
|
+
# Additional keyword arguments.
|
64
|
+
#
|
65
|
+
# @option kwargs [Boolean] required
|
66
|
+
# Specifies whether the option value is required or optional.
|
47
67
|
#
|
48
|
-
def initialize(type:
|
49
|
-
|
68
|
+
def initialize(type: String,
|
69
|
+
default: nil,
|
70
|
+
usage: self.class.default_usage(type),
|
50
71
|
**kwargs)
|
51
|
-
super(
|
72
|
+
super(usage: usage, **kwargs)
|
73
|
+
|
74
|
+
@type = type
|
75
|
+
@default = default
|
52
76
|
end
|
53
77
|
|
54
78
|
#
|
55
79
|
# Returns the default option value usage for the given type.
|
56
80
|
#
|
57
81
|
# @param [Class, Hash, Array, Regexp] type
|
82
|
+
# The option value type.
|
58
83
|
#
|
59
84
|
# @return [String, nil]
|
85
|
+
# A default usage string based on the option value type.
|
60
86
|
#
|
61
87
|
# @raise [TypeError]
|
62
88
|
# The given type was not a Class, Hash, Array, or Regexp.
|
@@ -85,6 +111,17 @@ module CommandKit
|
|
85
111
|
string
|
86
112
|
end
|
87
113
|
|
114
|
+
#
|
115
|
+
# Returns a new default value.
|
116
|
+
#
|
117
|
+
# @return [Object]
|
118
|
+
#
|
119
|
+
def default_value
|
120
|
+
if @default.respond_to?(:call) then @default.call
|
121
|
+
else @default.dup
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
88
125
|
end
|
89
126
|
end
|
90
127
|
end
|
data/lib/command_kit/pager.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'command_kit/stdio'
|
4
|
+
require 'command_kit/console'
|
4
5
|
require 'command_kit/env'
|
5
6
|
require 'command_kit/env/path'
|
6
7
|
|
@@ -16,6 +17,7 @@ module CommandKit
|
|
16
17
|
#
|
17
18
|
# def run
|
18
19
|
# pager do |io|
|
20
|
+
# io.puts "This goes into the pager screen"
|
19
21
|
# end
|
20
22
|
# end
|
21
23
|
#
|
@@ -34,6 +36,7 @@ module CommandKit
|
|
34
36
|
#
|
35
37
|
module Pager
|
36
38
|
include Stdio
|
39
|
+
include Console
|
37
40
|
include Env
|
38
41
|
include Env::Path
|
39
42
|
|
@@ -43,6 +46,9 @@ module CommandKit
|
|
43
46
|
#
|
44
47
|
# Initializes the pager.
|
45
48
|
#
|
49
|
+
# @param [Hash{Symbol => Object}] kwargs
|
50
|
+
# Keyword arguments.
|
51
|
+
#
|
46
52
|
# @note
|
47
53
|
# Respects the `PAGER` env variable, or attemps to find `less` or
|
48
54
|
# `more` by searching the `PATH` env variable.
|
data/lib/command_kit/version.rb
CHANGED
data/lib/command_kit/xdg.rb
CHANGED
@@ -45,6 +45,9 @@ module CommandKit
|
|
45
45
|
|
46
46
|
extend ModuleMethods
|
47
47
|
|
48
|
+
#
|
49
|
+
# Class-level methods.
|
50
|
+
#
|
48
51
|
module ClassMethods
|
49
52
|
#
|
50
53
|
# Gets or sets the XDG sub-directory name used by the command.
|
@@ -62,7 +65,11 @@ module CommandKit
|
|
62
65
|
if new_namespace
|
63
66
|
@xdg_namespace = new_namespace.to_s
|
64
67
|
else
|
65
|
-
@xdg_namespace ||
|
68
|
+
@xdg_namespace || if superclass.kind_of?(ClassMethods)
|
69
|
+
superclass.xdg_namespace
|
70
|
+
else
|
71
|
+
command_name
|
72
|
+
end
|
66
73
|
end
|
67
74
|
end
|
68
75
|
end
|
@@ -3,39 +3,19 @@ require 'command_kit/arguments/argument'
|
|
3
3
|
|
4
4
|
describe Arguments::Argument do
|
5
5
|
let(:name) { :foo }
|
6
|
-
let(:type) { String }
|
7
6
|
let(:usage) { 'FOO' }
|
8
|
-
let(:default) { 'foo' }
|
9
7
|
let(:required) { true }
|
10
8
|
let(:repeats) { false }
|
11
9
|
let(:desc) { 'Foo argument' }
|
12
10
|
|
13
11
|
subject do
|
14
|
-
described_class.new name,
|
15
|
-
usage: usage,
|
16
|
-
default: default,
|
12
|
+
described_class.new name, usage: usage,
|
17
13
|
required: required,
|
18
14
|
repeats: repeats,
|
19
15
|
desc: desc
|
20
16
|
end
|
21
17
|
|
22
18
|
describe "#initialize" do
|
23
|
-
context "when the type: keyword is given" do
|
24
|
-
subject { described_class.new(name, type: type, desc: desc) }
|
25
|
-
|
26
|
-
it "must set #type" do
|
27
|
-
expect(subject.type).to eq(type)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
context "when the type: keyword is not given" do
|
32
|
-
subject { described_class.new(name, desc: desc) }
|
33
|
-
|
34
|
-
it "default #type to String" do
|
35
|
-
expect(subject.type).to eq(String)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
19
|
context "when the usage: keyword is given" do
|
40
20
|
subject { described_class.new(name, usage: usage, desc: desc) }
|
41
21
|
|
@@ -52,22 +32,6 @@ describe Arguments::Argument do
|
|
52
32
|
end
|
53
33
|
end
|
54
34
|
|
55
|
-
context "when the default: keyword is given" do
|
56
|
-
subject { described_class.new(name, default: default, desc: desc) }
|
57
|
-
|
58
|
-
it "must set #default" do
|
59
|
-
expect(subject.default).to eq(default)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
context "when the default: keyword is not given" do
|
64
|
-
subject { described_class.new(name, desc: desc) }
|
65
|
-
|
66
|
-
it "default #default to String" do
|
67
|
-
expect(subject.default).to eq(nil)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
35
|
context "when the required: keyword is given" do
|
72
36
|
subject { described_class.new(name, required: required, desc: desc) }
|
73
37
|
|
@@ -88,7 +52,7 @@ describe Arguments::Argument do
|
|
88
52
|
subject { described_class.new(name, repeats: repeats, desc: desc) }
|
89
53
|
|
90
54
|
it "must set #repeats" do
|
91
|
-
expect(subject.repeats).to eq(repeats)
|
55
|
+
expect(subject.repeats?).to eq(repeats)
|
92
56
|
end
|
93
57
|
end
|
94
58
|
|
@@ -96,7 +60,7 @@ describe Arguments::Argument do
|
|
96
60
|
subject { described_class.new(name, desc: desc) }
|
97
61
|
|
98
62
|
it "default #repeats to String" do
|
99
|
-
expect(subject.repeats).to eq(false)
|
63
|
+
expect(subject.repeats?).to eq(false)
|
100
64
|
end
|
101
65
|
end
|
102
66
|
|
@@ -2,16 +2,12 @@ require 'spec_helper'
|
|
2
2
|
require 'command_kit/arguments/argument_value'
|
3
3
|
|
4
4
|
describe CommandKit::Arguments::ArgumentValue do
|
5
|
-
let(:type) { String }
|
6
5
|
let(:required) { false }
|
7
|
-
let(:default) { "foo" }
|
8
6
|
let(:usage) { 'FOO' }
|
9
7
|
|
10
8
|
subject do
|
11
9
|
described_class.new(
|
12
|
-
type: type,
|
13
10
|
required: required,
|
14
|
-
default: default,
|
15
11
|
usage: usage
|
16
12
|
)
|
17
13
|
end
|
@@ -19,26 +15,10 @@ describe CommandKit::Arguments::ArgumentValue do
|
|
19
15
|
describe "#initialize" do
|
20
16
|
it "must require a usage: keyword"do
|
21
17
|
expect {
|
22
|
-
described_class.new(
|
18
|
+
described_class.new(required: required)
|
23
19
|
}.to raise_error(ArgumentError)
|
24
20
|
end
|
25
21
|
|
26
|
-
context "when type: is given" do
|
27
|
-
subject { described_class.new(type: type, usage: usage) }
|
28
|
-
|
29
|
-
it "must set #type" do
|
30
|
-
expect(subject.type).to eq(type)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
context "when type: is not given" do
|
35
|
-
subject { described_class.new(usage: usage) }
|
36
|
-
|
37
|
-
it "must default to nil" do
|
38
|
-
expect(subject.type).to be_nil
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
22
|
context "when required: is given" do
|
43
23
|
subject { described_class.new(required: required, usage: usage) }
|
44
24
|
|
@@ -54,22 +34,6 @@ describe CommandKit::Arguments::ArgumentValue do
|
|
54
34
|
expect(subject.required).to be(true)
|
55
35
|
end
|
56
36
|
end
|
57
|
-
|
58
|
-
context "when default: is given" do
|
59
|
-
subject { described_class.new(default: default, usage: usage) }
|
60
|
-
|
61
|
-
it "must set #default" do
|
62
|
-
expect(subject.default).to eq(default)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
context "when default: is not given" do
|
67
|
-
subject { described_class.new(usage: usage) }
|
68
|
-
|
69
|
-
it "must default to nil" do
|
70
|
-
expect(subject.default).to be_nil
|
71
|
-
end
|
72
|
-
end
|
73
37
|
end
|
74
38
|
|
75
39
|
describe "#required?" do
|
@@ -99,28 +63,4 @@ describe CommandKit::Arguments::ArgumentValue do
|
|
99
63
|
it { expect(subject.optional?).to be(true) }
|
100
64
|
end
|
101
65
|
end
|
102
|
-
|
103
|
-
describe "#default_value" do
|
104
|
-
context "when initialized with a default: that responded to #call" do
|
105
|
-
let(:default) do
|
106
|
-
->{ [] }
|
107
|
-
end
|
108
|
-
|
109
|
-
it "must call the default #call method" do
|
110
|
-
expect(subject.default_value).to eq(default.call)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
context "when initialized with a default: that it's an Object" do
|
115
|
-
let(:default) { "" }
|
116
|
-
|
117
|
-
it "must return the default: object" do
|
118
|
-
expect(subject.default_value).to eq(default)
|
119
|
-
end
|
120
|
-
|
121
|
-
it "must duplicate the default: object each time" do
|
122
|
-
expect(subject.default_value).to_not be(subject.default_value)
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
126
66
|
end
|