command_kit 0.1.0 → 0.3.0
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 +18 -3
- data/.rubocop.yml +141 -0
- data/ChangeLog.md +165 -0
- data/Gemfile +3 -0
- data/README.md +186 -118
- data/Rakefile +3 -2
- data/command_kit.gemspec +4 -4
- data/examples/command.rb +1 -1
- data/gemspec.yml +7 -0
- data/lib/command_kit/arguments/argument.rb +2 -2
- data/lib/command_kit/arguments.rb +36 -7
- data/lib/command_kit/colors.rb +702 -53
- data/lib/command_kit/command.rb +2 -3
- data/lib/command_kit/commands/auto_load.rb +8 -1
- data/lib/command_kit/commands/help.rb +3 -2
- data/lib/command_kit/commands/subcommand.rb +1 -1
- data/lib/command_kit/commands.rb +24 -9
- data/lib/command_kit/env/path.rb +1 -1
- data/lib/command_kit/file_utils.rb +46 -0
- data/lib/command_kit/help/man.rb +17 -33
- data/lib/command_kit/inflector.rb +47 -17
- data/lib/command_kit/interactive.rb +9 -0
- data/lib/command_kit/main.rb +7 -9
- data/lib/command_kit/man.rb +44 -0
- data/lib/command_kit/open_app.rb +69 -0
- data/lib/command_kit/options/option.rb +41 -27
- data/lib/command_kit/options/option_value.rb +3 -2
- data/lib/command_kit/options/parser.rb +17 -22
- data/lib/command_kit/options.rb +102 -14
- data/lib/command_kit/os/linux.rb +157 -0
- data/lib/command_kit/os.rb +159 -11
- data/lib/command_kit/package_manager.rb +200 -0
- data/lib/command_kit/pager.rb +46 -4
- data/lib/command_kit/printing/indent.rb +4 -4
- data/lib/command_kit/printing.rb +14 -3
- data/lib/command_kit/program_name.rb +9 -0
- data/lib/command_kit/sudo.rb +40 -0
- data/lib/command_kit/terminal.rb +5 -0
- data/lib/command_kit/version.rb +1 -1
- data/spec/arguments/argument_spec.rb +1 -1
- data/spec/arguments_spec.rb +84 -1
- data/spec/colors_spec.rb +357 -70
- data/spec/command_spec.rb +77 -6
- data/spec/commands/auto_load_spec.rb +33 -2
- data/spec/commands_spec.rb +101 -29
- data/spec/env/path_spec.rb +6 -0
- data/spec/exception_handler_spec.rb +1 -1
- data/spec/file_utils_spec.rb +59 -0
- data/spec/fixtures/template.erb +5 -0
- data/spec/help/man_spec.rb +54 -57
- data/spec/inflector_spec.rb +70 -8
- data/spec/man_spec.rb +46 -0
- data/spec/open_app_spec.rb +85 -0
- data/spec/options/option_spec.rb +38 -2
- data/spec/options/option_value_spec.rb +55 -0
- data/spec/options/parser_spec.rb +0 -10
- data/spec/options_spec.rb +328 -0
- data/spec/os/linux_spec.rb +164 -0
- data/spec/os_spec.rb +200 -13
- data/spec/package_manager_spec.rb +806 -0
- data/spec/pager_spec.rb +71 -6
- data/spec/printing/indent_spec.rb +7 -5
- data/spec/printing_spec.rb +23 -1
- data/spec/program_name_spec.rb +8 -0
- data/spec/sudo_spec.rb +51 -0
- data/spec/terminal_spec.rb +30 -0
- data/spec/usage_spec.rb +1 -1
- metadata +23 -4
data/spec/pager_spec.rb
CHANGED
@@ -19,8 +19,8 @@ describe CommandKit::Pager do
|
|
19
19
|
|
20
20
|
subject { command_class.new(env: {'PAGER' => pager}) }
|
21
21
|
|
22
|
-
it "must set @
|
23
|
-
expect(subject.instance_variable_get('@
|
22
|
+
it "must set @pager_command to the PAGER env variable" do
|
23
|
+
expect(subject.instance_variable_get('@pager_command')).to eq(pager)
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
@@ -29,7 +29,7 @@ describe CommandKit::Pager do
|
|
29
29
|
subject { command_class.new(env: {'PATH' => ENV['PATH']}) }
|
30
30
|
|
31
31
|
it "must search PATH for one of the pagers" do
|
32
|
-
expect(subject.instance_variable_get('@
|
32
|
+
expect(subject.instance_variable_get('@pager_command')).to eq("less -r")
|
33
33
|
end
|
34
34
|
end
|
35
35
|
end
|
@@ -46,9 +46,9 @@ describe CommandKit::Pager do
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
-
context "when @
|
49
|
+
context "when @pager_command isn't initialized" do
|
50
50
|
before do
|
51
|
-
subject.instance_variable_set('@
|
51
|
+
subject.instance_variable_set('@pager_command',nil)
|
52
52
|
end
|
53
53
|
|
54
54
|
it "must yield stdout" do
|
@@ -58,7 +58,7 @@ describe CommandKit::Pager do
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
-
context "when stdout is a TTY and @
|
61
|
+
context "when stdout is a TTY and @pager_command is initialized" do
|
62
62
|
let(:pager) { 'less -r' }
|
63
63
|
|
64
64
|
subject { command_class.new(env: {'PAGER' => pager}) }
|
@@ -149,4 +149,69 @@ describe CommandKit::Pager do
|
|
149
149
|
end
|
150
150
|
end
|
151
151
|
end
|
152
|
+
|
153
|
+
describe "#pipe_to_pager" do
|
154
|
+
context "when @pager_command is initialized" do
|
155
|
+
let(:pager) { 'less' }
|
156
|
+
|
157
|
+
subject do
|
158
|
+
command_class.new(env: {'PAGER' => pager})
|
159
|
+
end
|
160
|
+
|
161
|
+
context "and when given a single String" do
|
162
|
+
let(:command) { "find ." }
|
163
|
+
|
164
|
+
it "must run the command but piped into the pager" do
|
165
|
+
expect(subject).to receive(:system).with("#{command} | #{pager}")
|
166
|
+
|
167
|
+
subject.pipe_to_pager(command)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
context "and when given a String and additional arguments" do
|
172
|
+
let(:command) { 'find' }
|
173
|
+
let(:arguments) { %w[. -name *.md] }
|
174
|
+
|
175
|
+
let(:escaped_command) do
|
176
|
+
Shellwords.shelljoin([command,*arguments])
|
177
|
+
end
|
178
|
+
|
179
|
+
it "must shell escape the command and arguments" do
|
180
|
+
expect(subject).to receive(:system).with(
|
181
|
+
"#{escaped_command} | #{pager}"
|
182
|
+
)
|
183
|
+
|
184
|
+
subject.pipe_to_pager(command,*arguments)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
context "when @pager_command is not initialized" do
|
190
|
+
before do
|
191
|
+
subject.instance_variable_set('@pager_command',nil)
|
192
|
+
end
|
193
|
+
|
194
|
+
let(:command) { 'find' }
|
195
|
+
let(:arguments) { %w[. -name *.md] }
|
196
|
+
|
197
|
+
it "must pass the command and any additional arguments to #system" do
|
198
|
+
expect(subject).to receive(:system).with(command,*arguments)
|
199
|
+
|
200
|
+
subject.pipe_to_pager(command,*arguments)
|
201
|
+
end
|
202
|
+
|
203
|
+
context "when one of the arguments is not a String" do
|
204
|
+
let(:command) { :find }
|
205
|
+
let(:arguments) { ['.', :"-name", "*.md"] }
|
206
|
+
|
207
|
+
it "must convert the command to a String before calling #system" do
|
208
|
+
expect(subject).to receive(:system).with(
|
209
|
+
command.to_s, *arguments.map(&:to_s)
|
210
|
+
)
|
211
|
+
|
212
|
+
subject.pipe_to_pager(command,*arguments)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
152
217
|
end
|
@@ -12,14 +12,16 @@ describe CommandKit::Printing::Indent do
|
|
12
12
|
subject { command_class.new }
|
13
13
|
|
14
14
|
describe "#initialize" do
|
15
|
-
it "must initialize
|
16
|
-
expect(subject.
|
15
|
+
it "must initialize #indent to 0" do
|
16
|
+
expect(subject.indent).to eq(0)
|
17
17
|
end
|
18
18
|
|
19
19
|
context "when the class has a superclass" do
|
20
20
|
module TestIndent
|
21
21
|
class TestSuperCommand
|
22
22
|
|
23
|
+
attr_reader :var
|
24
|
+
|
23
25
|
def initialize(var: 'default')
|
24
26
|
@var = var
|
25
27
|
end
|
@@ -36,11 +38,11 @@ describe CommandKit::Printing::Indent do
|
|
36
38
|
let(:command_class) { TestIndent::TestSubCommand }
|
37
39
|
|
38
40
|
it "must initialize @indent to 0" do
|
39
|
-
expect(subject.
|
41
|
+
expect(subject.indent).to eq(0)
|
40
42
|
end
|
41
43
|
|
42
44
|
it "must call super()" do
|
43
|
-
expect(subject.
|
45
|
+
expect(subject.var).to eq('default')
|
44
46
|
end
|
45
47
|
|
46
48
|
context "and additional keyword arguments are given" do
|
@@ -49,7 +51,7 @@ describe CommandKit::Printing::Indent do
|
|
49
51
|
subject { command_class.new(var: var) }
|
50
52
|
|
51
53
|
it "must call super() with the additional keyword arguments" do
|
52
|
-
expect(subject.
|
54
|
+
expect(subject.var).to eq(var)
|
53
55
|
end
|
54
56
|
end
|
55
57
|
end
|
data/spec/printing_spec.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'command_kit/printing'
|
3
|
+
require 'command_kit/command_name'
|
3
4
|
|
4
5
|
require 'stringio'
|
5
6
|
|
@@ -34,11 +35,32 @@ describe CommandKit::Printing do
|
|
34
35
|
describe "#print_error" do
|
35
36
|
let(:message) { "oh no!" }
|
36
37
|
|
37
|
-
it "must print
|
38
|
+
it "must print the error message to stderr" do
|
38
39
|
expect {
|
39
40
|
subject.print_error(message)
|
40
41
|
}.to output("#{message}#{nl}").to_stderr
|
41
42
|
end
|
43
|
+
|
44
|
+
context "and when CommandKit::CommandName is included" do
|
45
|
+
module TestPrinting
|
46
|
+
class TestCmdWithCommandName
|
47
|
+
|
48
|
+
include CommandKit::CommandName
|
49
|
+
include CommandKit::Printing
|
50
|
+
|
51
|
+
command_name 'foo'
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
let(:command_class) { TestPrinting::TestCmdWithCommandName }
|
57
|
+
|
58
|
+
it "must print the command_name and the error message" do
|
59
|
+
expect {
|
60
|
+
subject.print_error(message)
|
61
|
+
}.to output("#{subject.command_name}: #{message}#{nl}").to_stderr
|
62
|
+
end
|
63
|
+
end
|
42
64
|
end
|
43
65
|
|
44
66
|
describe "#print_exception" do
|
data/spec/program_name_spec.rb
CHANGED
@@ -56,6 +56,14 @@ describe CommandKit::ProgramName do
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
+
describe "#command_name" do
|
60
|
+
subject { command_class.new }
|
61
|
+
|
62
|
+
it "should be the same as #program_name" do
|
63
|
+
expect(subject.command_name).to eq(subject.program_name)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
59
67
|
after do
|
60
68
|
$PROGRAM_NAME = @original_program_name
|
61
69
|
end
|
data/spec/sudo_spec.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'command_kit/sudo'
|
3
|
+
|
4
|
+
describe CommandKit::Sudo do
|
5
|
+
module TestSudo
|
6
|
+
class TestCommand
|
7
|
+
include CommandKit::Sudo
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:command_class) { TestSudo::TestCommand }
|
12
|
+
subject { command_class.new }
|
13
|
+
|
14
|
+
describe "#sudo" do
|
15
|
+
let(:command) { "ls" }
|
16
|
+
let(:arguments) { ["-la", "~root"] }
|
17
|
+
let(:status) { double(:status) }
|
18
|
+
|
19
|
+
context "on UNIX" do
|
20
|
+
context "when the UID is 0" do
|
21
|
+
before { allow(Process).to receive(:uid).and_return(0) }
|
22
|
+
|
23
|
+
it "must execute the command without sudo" do
|
24
|
+
expect(subject).to receive(:system).with(command,*arguments).and_return(status)
|
25
|
+
|
26
|
+
expect(subject.sudo(command,*arguments)).to be(status)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "when the UID is not 0" do
|
31
|
+
before { allow(Process).to receive(:uid).and_return(1000) }
|
32
|
+
|
33
|
+
it "must execute the command with 'sudo ...'" do
|
34
|
+
expect(subject).to receive(:system).with('sudo',command,*arguments).and_return(status)
|
35
|
+
|
36
|
+
expect(subject.sudo(command,*arguments)).to be(status)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "on Windows" do
|
42
|
+
subject { command_class.new(os: :windows) }
|
43
|
+
|
44
|
+
it "must execute the command with 'runas /user:administrator ...'" do
|
45
|
+
expect(subject).to receive(:system).with('runas','/user:administrator',command,*arguments).and_return(status)
|
46
|
+
|
47
|
+
expect(subject.sudo(command,*arguments)).to be(status)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/spec/terminal_spec.rb
CHANGED
@@ -43,6 +43,36 @@ describe CommandKit::Terminal do
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
+
describe "#tty?" do
|
47
|
+
context "when stdout is connected to a TTY" do
|
48
|
+
subject { command_class.new(stdout: STDOUT) }
|
49
|
+
|
50
|
+
it do
|
51
|
+
skip "STDOUT is not a TTY" unless STDOUT.tty?
|
52
|
+
|
53
|
+
expect(subject.tty?).to be(true)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context "when stdout is not connected to a TTY" do
|
58
|
+
subject { command_class.new(stdout: StringIO.new) }
|
59
|
+
|
60
|
+
it do
|
61
|
+
expect(subject.tty?).to be(false)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "when IO.console is missing" do
|
66
|
+
before do
|
67
|
+
expect(IO).to receive(:respond_to?).with(:console).and_return(false)
|
68
|
+
end
|
69
|
+
|
70
|
+
it do
|
71
|
+
expect(subject.tty?).to be(false)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
46
76
|
describe "#terminal" do
|
47
77
|
context "when stdout is connected to a TTY" do
|
48
78
|
subject { command_class.new(stdout: STDOUT) }
|
data/spec/usage_spec.rb
CHANGED
@@ -182,7 +182,7 @@ describe CommandKit::Usage do
|
|
182
182
|
[
|
183
183
|
"#{subject.command_name} #{command_class.usage[0]}",
|
184
184
|
"#{subject.command_name} #{command_class.usage[1]}",
|
185
|
-
"#{subject.command_name} #{command_class.usage[2]}"
|
185
|
+
"#{subject.command_name} #{command_class.usage[2]}"
|
186
186
|
]
|
187
187
|
)
|
188
188
|
end
|
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
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Postmodern
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-12-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -38,6 +38,7 @@ files:
|
|
38
38
|
- ".github/workflows/ruby.yml"
|
39
39
|
- ".gitignore"
|
40
40
|
- ".rspec"
|
41
|
+
- ".rubocop.yml"
|
41
42
|
- ".yardopts"
|
42
43
|
- ChangeLog.md
|
43
44
|
- Gemfile
|
@@ -70,11 +71,14 @@ files:
|
|
70
71
|
- lib/command_kit/env/path.rb
|
71
72
|
- lib/command_kit/examples.rb
|
72
73
|
- lib/command_kit/exception_handler.rb
|
74
|
+
- lib/command_kit/file_utils.rb
|
73
75
|
- lib/command_kit/help.rb
|
74
76
|
- lib/command_kit/help/man.rb
|
75
77
|
- lib/command_kit/inflector.rb
|
76
78
|
- lib/command_kit/interactive.rb
|
77
79
|
- lib/command_kit/main.rb
|
80
|
+
- lib/command_kit/man.rb
|
81
|
+
- lib/command_kit/open_app.rb
|
78
82
|
- lib/command_kit/options.rb
|
79
83
|
- lib/command_kit/options/option.rb
|
80
84
|
- lib/command_kit/options/option_value.rb
|
@@ -83,11 +87,14 @@ files:
|
|
83
87
|
- lib/command_kit/options/verbose.rb
|
84
88
|
- lib/command_kit/options/version.rb
|
85
89
|
- lib/command_kit/os.rb
|
90
|
+
- lib/command_kit/os/linux.rb
|
91
|
+
- lib/command_kit/package_manager.rb
|
86
92
|
- lib/command_kit/pager.rb
|
87
93
|
- lib/command_kit/printing.rb
|
88
94
|
- lib/command_kit/printing/indent.rb
|
89
95
|
- lib/command_kit/program_name.rb
|
90
96
|
- lib/command_kit/stdio.rb
|
97
|
+
- lib/command_kit/sudo.rb
|
91
98
|
- lib/command_kit/terminal.rb
|
92
99
|
- lib/command_kit/usage.rb
|
93
100
|
- lib/command_kit/version.rb
|
@@ -115,29 +122,41 @@ files:
|
|
115
122
|
- spec/env_spec.rb
|
116
123
|
- spec/examples_spec.rb
|
117
124
|
- spec/exception_handler_spec.rb
|
125
|
+
- spec/file_utils_spec.rb
|
126
|
+
- spec/fixtures/template.erb
|
118
127
|
- spec/help/man_spec.rb
|
119
128
|
- spec/help_spec.rb
|
120
129
|
- spec/inflector_spec.rb
|
121
130
|
- spec/interactive_spec.rb
|
122
131
|
- spec/main_spec.rb
|
132
|
+
- spec/man_spec.rb
|
133
|
+
- spec/open_app_spec.rb
|
123
134
|
- spec/options/option_spec.rb
|
124
135
|
- spec/options/option_value_spec.rb
|
125
136
|
- spec/options/parser_spec.rb
|
126
137
|
- spec/options_spec.rb
|
138
|
+
- spec/os/linux_spec.rb
|
127
139
|
- spec/os_spec.rb
|
140
|
+
- spec/package_manager_spec.rb
|
128
141
|
- spec/pager_spec.rb
|
129
142
|
- spec/printing/indent_spec.rb
|
130
143
|
- spec/printing_spec.rb
|
131
144
|
- spec/program_name_spec.rb
|
132
145
|
- spec/spec_helper.rb
|
133
146
|
- spec/stdio_spec.rb
|
147
|
+
- spec/sudo_spec.rb
|
134
148
|
- spec/terminal_spec.rb
|
135
149
|
- spec/usage_spec.rb
|
136
150
|
- spec/xdg_spec.rb
|
137
151
|
homepage: https://github.com/postmodern/command_kit.rb#readme
|
138
152
|
licenses:
|
139
153
|
- MIT
|
140
|
-
metadata:
|
154
|
+
metadata:
|
155
|
+
documentation_uri: https://rubydoc.info/gems/command_kit
|
156
|
+
source_code_uri: https://github.com/postmodern/command_kit.rb
|
157
|
+
bug_tracker_uri: https://github.com/postmodern/command_kit.rb/issues
|
158
|
+
changelog_uri: https://github.com/postmodern/command_kit.rb/blob/main/ChangeLog.md
|
159
|
+
rubygems_mfa_required: 'true'
|
141
160
|
post_install_message:
|
142
161
|
rdoc_options: []
|
143
162
|
require_paths:
|
@@ -153,7 +172,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
153
172
|
- !ruby/object:Gem::Version
|
154
173
|
version: '0'
|
155
174
|
requirements: []
|
156
|
-
rubygems_version: 3.2.
|
175
|
+
rubygems_version: 3.2.22
|
157
176
|
signing_key:
|
158
177
|
specification_version: 4
|
159
178
|
summary: A toolkit for building Ruby CLI commands
|