command_kit 0.4.0 → 0.4.1
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/.github/workflows/ruby.yml +2 -0
- data/.rubocop.yml +3 -0
- data/ChangeLog.md +12 -0
- data/LICENSE.txt +1 -1
- data/README.md +1 -1
- data/examples/subcommands/cli/config/get.rb +47 -0
- data/examples/subcommands/cli/config/set.rb +44 -0
- data/examples/subcommands/cli/config.rb +23 -0
- data/examples/subcommands/cli/list.rb +35 -0
- data/examples/subcommands/cli/update.rb +47 -0
- data/examples/subcommands/cli.rb +55 -0
- data/lib/command_kit/env/home.rb +1 -1
- data/lib/command_kit/inflector.rb +1 -1
- data/lib/command_kit/options/parser.rb +1 -1
- data/lib/command_kit/os/linux.rb +1 -1
- data/lib/command_kit/os.rb +1 -1
- data/lib/command_kit/printing/tables/table_formatter.rb +2 -2
- data/lib/command_kit/version.rb +1 -1
- data/lib/command_kit/xdg.rb +1 -1
- data/spec/commands_spec.rb +26 -0
- data/spec/options/parser_spec.rb +19 -0
- data/spec/printing/tables/table_formatter_spec.rb +10 -0
- metadata +9 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3a35e836c936c91aa916f33e691260a591d2e363de6a0fd3d9259150b86add15
|
4
|
+
data.tar.gz: fe2e2cc87a8a0fe889cba23b5567b307bb088fdf3ee4eff7d681694a981b5143
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: da2676ab635edc9898457b1c532af6ac4c478c6f3a0ab19dfc42f0abc4ddd73ef4f473fe7699f8bed3ac5abec3381a7a9ca9c50736c4cc3697612ef36f3d6fea
|
7
|
+
data.tar.gz: d30a04ab5274f489ef3e534950301669d47112ee56d43b59e51c5e816f7de21fba72197d43f3362331c40f3e75a70e0c316d53fe12bf8960daf79efec270a372
|
data/.github/workflows/ruby.yml
CHANGED
data/.rubocop.yml
CHANGED
@@ -152,3 +152,6 @@ Bundler/OrderedGems: { Enabled: false }
|
|
152
152
|
Layout/SpaceInsideArrayLiteralBrackets: { Enabled: false }
|
153
153
|
|
154
154
|
Naming/HeredocDelimiterNaming: { Enabled: false }
|
155
|
+
|
156
|
+
# I prefer to use explicit parenthesis for compound logical statements
|
157
|
+
Style/RedundantParentheses: { Enabled: false }
|
data/ChangeLog.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
### 0.4.1 / 2024-01-03
|
2
|
+
|
3
|
+
* Added more examples of how to define sub-commands and sub-sub-commands.
|
4
|
+
|
5
|
+
#### CommandKit::Options::Parser
|
6
|
+
|
7
|
+
* Do not override the command's `usage` if it's already been set.
|
8
|
+
|
9
|
+
#### CommandKit::Printing::Tables
|
10
|
+
|
11
|
+
* Format the table output as UTF-8 to allow UTF-8 data in the formatted table.
|
12
|
+
|
1
13
|
### 0.4.0 / 2022-11-11
|
2
14
|
|
3
15
|
* Added {CommandKit::BugReport}.
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'command_kit/command'
|
2
|
+
|
3
|
+
module Foo
|
4
|
+
class CLI
|
5
|
+
class Config < CommandKit::Command
|
6
|
+
#
|
7
|
+
# The `config get` sub-command.
|
8
|
+
#
|
9
|
+
class Get < CommandKit::Command
|
10
|
+
|
11
|
+
usage '[options] NAME'
|
12
|
+
|
13
|
+
argument :name, required: false,
|
14
|
+
desc: 'Configuration variable name'
|
15
|
+
|
16
|
+
description 'Gets a configuration variable'
|
17
|
+
|
18
|
+
CONFIG = {
|
19
|
+
'name' => 'John Smith',
|
20
|
+
'email' => 'john.smith@example.com'
|
21
|
+
}
|
22
|
+
|
23
|
+
#
|
24
|
+
# Runs the `config get` sub-command.
|
25
|
+
#
|
26
|
+
# @param [String, nil] name
|
27
|
+
# The optional name argument.
|
28
|
+
#
|
29
|
+
def run(name=nil)
|
30
|
+
if name
|
31
|
+
unless CONFIG.has_key?(name)
|
32
|
+
print_error "unknown config variable: #{name}"
|
33
|
+
exit(1)
|
34
|
+
end
|
35
|
+
|
36
|
+
puts CONFIG.fetch(name)
|
37
|
+
else
|
38
|
+
CONFIG.each do |name,value|
|
39
|
+
puts "#{name}:\t#{value}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'command_kit/command'
|
2
|
+
|
3
|
+
module Foo
|
4
|
+
class CLI
|
5
|
+
class Config < CommandKit::Command
|
6
|
+
#
|
7
|
+
# The `config set` sub-command.
|
8
|
+
#
|
9
|
+
class Set < CommandKit::Command
|
10
|
+
|
11
|
+
usage '[options] NAME'
|
12
|
+
|
13
|
+
argument :name, required: true,
|
14
|
+
desc: 'Configuration variable name to set'
|
15
|
+
|
16
|
+
argument :value, required: true,
|
17
|
+
desc: 'Configuration variable value to set'
|
18
|
+
|
19
|
+
description 'Sets a configuration variable'
|
20
|
+
|
21
|
+
CONFIG = {
|
22
|
+
'name' => 'John Smith',
|
23
|
+
'email' => 'john.smith@example.com'
|
24
|
+
}
|
25
|
+
|
26
|
+
#
|
27
|
+
# Runs the `config get` sub-command.
|
28
|
+
#
|
29
|
+
# @param [String] name
|
30
|
+
# The name argument.
|
31
|
+
#
|
32
|
+
def run(name,value)
|
33
|
+
unless CONFIG.has_key?(name)
|
34
|
+
print_error "unknown config variable: #{name}"
|
35
|
+
exit(1)
|
36
|
+
end
|
37
|
+
|
38
|
+
puts "Configuration variable #{name} was #{CONFIG.fetch(name)}, but is now #{value}"
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'command_kit/command'
|
2
|
+
require 'command_kit/commands'
|
3
|
+
|
4
|
+
require_relative 'config/get'
|
5
|
+
require_relative 'config/set'
|
6
|
+
|
7
|
+
module Foo
|
8
|
+
class CLI
|
9
|
+
#
|
10
|
+
# The `config` sub-command.
|
11
|
+
#
|
12
|
+
class Config < CommandKit::Command
|
13
|
+
|
14
|
+
include CommandKit::Commands
|
15
|
+
|
16
|
+
command Get
|
17
|
+
command Set
|
18
|
+
|
19
|
+
description 'Get or set the configuration'
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'command_kit/command'
|
2
|
+
|
3
|
+
module Foo
|
4
|
+
class CLI
|
5
|
+
#
|
6
|
+
# The `list` sub-command.
|
7
|
+
#
|
8
|
+
class List < CommandKit::Command
|
9
|
+
|
10
|
+
usage '[options] [NAME]'
|
11
|
+
|
12
|
+
argument :name, required: false,
|
13
|
+
desc: 'Optional name to list'
|
14
|
+
|
15
|
+
description 'Lists the contents'
|
16
|
+
|
17
|
+
ITEMS = %w[foo bar baz]
|
18
|
+
|
19
|
+
#
|
20
|
+
# Runs the `list` sub-command.
|
21
|
+
#
|
22
|
+
# @param [String, nil] name
|
23
|
+
# The optional name argument.
|
24
|
+
#
|
25
|
+
def run(name=nil)
|
26
|
+
if name
|
27
|
+
puts ITEMS.grep(name)
|
28
|
+
else
|
29
|
+
puts ITEMS
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'command_kit/command'
|
2
|
+
|
3
|
+
module Foo
|
4
|
+
class CLI
|
5
|
+
#
|
6
|
+
# The `update` sub-command.
|
7
|
+
#
|
8
|
+
class Update < CommandKit::Command
|
9
|
+
|
10
|
+
usage '[options] [NAME]'
|
11
|
+
|
12
|
+
option :quiet, short: '-q',
|
13
|
+
desc: 'Suppresses logging messages'
|
14
|
+
|
15
|
+
argument :name, required: false,
|
16
|
+
desc: 'Optional name to update'
|
17
|
+
|
18
|
+
description 'Updates an item or all items'
|
19
|
+
|
20
|
+
ITEMS = %w[foo bar baz]
|
21
|
+
|
22
|
+
#
|
23
|
+
# Runs the `update` sub-command.
|
24
|
+
#
|
25
|
+
# @param [String, nil] name
|
26
|
+
# The optional name argument.
|
27
|
+
#
|
28
|
+
def run(name=nil)
|
29
|
+
if name
|
30
|
+
unless ITEMS.include?(name)
|
31
|
+
print_error "unknown item: #{name}"
|
32
|
+
exit(1)
|
33
|
+
end
|
34
|
+
|
35
|
+
puts "Updating #{name} ..." unless options[:quiet]
|
36
|
+
sleep 1
|
37
|
+
puts "Item #{name} updated." unless options[:quiet]
|
38
|
+
else
|
39
|
+
puts "Updating ..." unless options[:quiet]
|
40
|
+
sleep 2
|
41
|
+
puts "All items updated." unless options[:quiet]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift(File.expand_path('../../../lib',__FILE__))
|
4
|
+
|
5
|
+
require 'command_kit/commands'
|
6
|
+
|
7
|
+
require_relative 'cli/config'
|
8
|
+
require_relative 'cli/list'
|
9
|
+
require_relative 'cli/update'
|
10
|
+
|
11
|
+
module Foo
|
12
|
+
#
|
13
|
+
# The main CLI command.
|
14
|
+
#
|
15
|
+
class CLI
|
16
|
+
|
17
|
+
include CommandKit::Commands
|
18
|
+
|
19
|
+
class << self
|
20
|
+
# The global configuration file setting.
|
21
|
+
#
|
22
|
+
# @return [String, nil]
|
23
|
+
attr_accessor :config_file
|
24
|
+
end
|
25
|
+
|
26
|
+
command_name 'foo'
|
27
|
+
|
28
|
+
# Commands must be explicitly registered, unless
|
29
|
+
# CommandKit::Commands::AutoLoad.new(...) is included.
|
30
|
+
command Config
|
31
|
+
command List
|
32
|
+
command Update
|
33
|
+
|
34
|
+
# Commands may have aliases
|
35
|
+
command_aliases['ls'] = 'list'
|
36
|
+
command_aliases['up'] = 'update'
|
37
|
+
|
38
|
+
# Global options may be defined which are parsed before the sub-command's
|
39
|
+
# options are parsed and the sub-command is executed.
|
40
|
+
option :config_file, short: '-C',
|
41
|
+
value: {
|
42
|
+
type: String,
|
43
|
+
usage: 'FILE'
|
44
|
+
},
|
45
|
+
desc: 'Global option to set the config file' do |file|
|
46
|
+
CLI.config_file = file
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
if $0 == __FILE__
|
53
|
+
# Normally you would invoke Foo::CLI.start from a bin/ script.
|
54
|
+
Foo::CLI.start
|
55
|
+
end
|
data/lib/command_kit/env/home.rb
CHANGED
@@ -20,7 +20,7 @@ module CommandKit
|
|
20
20
|
module ModuleMethods
|
21
21
|
#
|
22
22
|
# Extends {ClassMethods} or {ModuleMethods}, depending on whether
|
23
|
-
# {Env::Home} is being included into a class or a module
|
23
|
+
# {Env::Home} is being included into a class or a module.
|
24
24
|
#
|
25
25
|
# @param [Class, Module] context
|
26
26
|
# The class or module which is including {Home}.
|
@@ -103,7 +103,7 @@ module CommandKit
|
|
103
103
|
new_string << word
|
104
104
|
elsif scanner.scan(/[_-]+/)
|
105
105
|
# skip
|
106
|
-
elsif scanner.scan(
|
106
|
+
elsif scanner.scan(%r{/})
|
107
107
|
new_string << '::'
|
108
108
|
else
|
109
109
|
raise(ArgumentError,"cannot convert string to CamelCase: #{scanner.string.inspect}")
|
data/lib/command_kit/os/linux.rb
CHANGED
@@ -36,7 +36,7 @@ module CommandKit
|
|
36
36
|
module ModuleMethods
|
37
37
|
#
|
38
38
|
# Extends {ClassMethods} or {ModuleMethods}, depending on whether
|
39
|
-
# {OS} is being included into a class or a module
|
39
|
+
# {OS} is being included into a class or a module.
|
40
40
|
#
|
41
41
|
# @param [Class, Module] context
|
42
42
|
# The class or module which is including {OS}.
|
data/lib/command_kit/os.rb
CHANGED
@@ -32,7 +32,7 @@ module CommandKit
|
|
32
32
|
module ModuleMethods
|
33
33
|
#
|
34
34
|
# Extends {ClassMethods} or {ModuleMethods}, depending on whether
|
35
|
-
# {OS} is being included into a class or a module
|
35
|
+
# {OS} is being included into a class or a module.
|
36
36
|
#
|
37
37
|
# @param [Class, Module] context
|
38
38
|
# The class or module which is including {OS}.
|
@@ -87,7 +87,7 @@ module CommandKit
|
|
87
87
|
column_border: ,
|
88
88
|
joined_border: ,
|
89
89
|
right_border: )
|
90
|
-
line = String.new
|
90
|
+
line = String.new(encoding: Encoding::UTF_8)
|
91
91
|
line << left_border
|
92
92
|
|
93
93
|
@table.max_columns.times do |column_index|
|
@@ -191,7 +191,7 @@ module CommandKit
|
|
191
191
|
# The formatted row line.
|
192
192
|
#
|
193
193
|
def format_row_line(row,line_index, justify: @style.justify)
|
194
|
-
line = String.new
|
194
|
+
line = String.new(encoding: Encoding::UTF_8)
|
195
195
|
line << @style.border.left_border if @style.border
|
196
196
|
|
197
197
|
@table.max_columns.times do |column_index|
|
data/lib/command_kit/version.rb
CHANGED
data/lib/command_kit/xdg.rb
CHANGED
@@ -30,7 +30,7 @@ module CommandKit
|
|
30
30
|
module ModuleMethods
|
31
31
|
#
|
32
32
|
# Extends {ClassMethods} or {ModuleMethods}, depending on whether {XDG} is
|
33
|
-
# being included into a class or a module
|
33
|
+
# being included into a class or a module.
|
34
34
|
#
|
35
35
|
# @param [Class, Module] context
|
36
36
|
# The class or module which is including {XDG}.
|
data/spec/commands_spec.rb
CHANGED
@@ -155,6 +155,32 @@ describe CommandKit::Commands do
|
|
155
155
|
|
156
156
|
let(:command_class) { TestCommands::TestCommands }
|
157
157
|
|
158
|
+
describe ".included" do
|
159
|
+
subject { command_class }
|
160
|
+
|
161
|
+
it "must set .usage to '[options] [COMMAND [ARGS...]]'" do
|
162
|
+
expect(subject.usage).to eq('[options] [COMMAND [ARGS...]]')
|
163
|
+
end
|
164
|
+
|
165
|
+
it "must add a 'command' argument" do
|
166
|
+
expect(subject.arguments[:command]).to_not be_nil
|
167
|
+
expect(subject.arguments[:command].required?).to be(false)
|
168
|
+
expect(subject.arguments[:command].desc).to eq('The command name to run')
|
169
|
+
end
|
170
|
+
|
171
|
+
it "must add a 'args' argument" do
|
172
|
+
expect(subject.arguments[:args]).to_not be_nil
|
173
|
+
expect(subject.arguments[:args].required?).to be(false)
|
174
|
+
expect(subject.arguments[:args].repeats?).to be(true)
|
175
|
+
expect(subject.arguments[:args].desc).to eq('Additional arguments for the command')
|
176
|
+
end
|
177
|
+
|
178
|
+
it "must add a 'help' command" do
|
179
|
+
expect(subject.commands['help']).to_not be(nil)
|
180
|
+
expect(subject.commands['help'].command).to be(described_class::Help)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
158
184
|
describe ".commands" do
|
159
185
|
subject { command_class }
|
160
186
|
|
data/spec/options/parser_spec.rb
CHANGED
@@ -19,6 +19,25 @@ describe CommandKit::Options::Parser do
|
|
19
19
|
it { expect(subject).to include(CommandKit::Main) }
|
20
20
|
it { expect(subject).to include(CommandKit::Usage) }
|
21
21
|
it { expect(subject.usage).to eq('[options]') }
|
22
|
+
|
23
|
+
context "when the command class already defines a usage string" do
|
24
|
+
module TestOptionParser
|
25
|
+
class TestCommandWithUsage
|
26
|
+
include CommandKit::Usage
|
27
|
+
|
28
|
+
usage '[options] ARGS...'
|
29
|
+
|
30
|
+
include CommandKit::Options::Parser
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
let(:command_class) { TestOptionParser::TestCommandWithUsage }
|
35
|
+
subject { command_class }
|
36
|
+
|
37
|
+
it "must not override the usage" do
|
38
|
+
expect(subject.usage).to eq('[options] ARGS...')
|
39
|
+
end
|
40
|
+
end
|
22
41
|
end
|
23
42
|
|
24
43
|
subject { command_class.new }
|
@@ -57,6 +57,16 @@ describe CommandKit::Printing::Tables::TableFormatter do
|
|
57
57
|
)
|
58
58
|
end
|
59
59
|
|
60
|
+
it "must encode the Strings as UTF-8" do
|
61
|
+
yielded_lines = []
|
62
|
+
|
63
|
+
subject.format do |line|
|
64
|
+
yielded_lines << line
|
65
|
+
end
|
66
|
+
|
67
|
+
expect(yielded_lines.map(&:encoding)).to all(be(Encoding::UTF_8))
|
68
|
+
end
|
69
|
+
|
60
70
|
context "but when the table contains multi-line cells" do
|
61
71
|
let(:rows) { multiline_rows }
|
62
72
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: command_kit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Postmodern
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-01-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -50,6 +50,12 @@ files:
|
|
50
50
|
- examples/command.rb
|
51
51
|
- examples/pager.rb
|
52
52
|
- examples/printing/tables.rb
|
53
|
+
- examples/subcommands/cli.rb
|
54
|
+
- examples/subcommands/cli/config.rb
|
55
|
+
- examples/subcommands/cli/config/get.rb
|
56
|
+
- examples/subcommands/cli/config/set.rb
|
57
|
+
- examples/subcommands/cli/list.rb
|
58
|
+
- examples/subcommands/cli/update.rb
|
53
59
|
- gemspec.yml
|
54
60
|
- lib/command_kit.rb
|
55
61
|
- lib/command_kit/arguments.rb
|
@@ -198,7 +204,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
198
204
|
- !ruby/object:Gem::Version
|
199
205
|
version: '0'
|
200
206
|
requirements: []
|
201
|
-
rubygems_version: 3.
|
207
|
+
rubygems_version: 3.4.10
|
202
208
|
signing_key:
|
203
209
|
specification_version: 4
|
204
210
|
summary: An all-in-one modular Ruby CLI toolkit
|