command_kit 0.1.0.pre1 → 0.1.0.pre2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|