command_kit 0.4.1 → 0.5.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.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog.md +6 -0
  3. data/README.md +3 -0
  4. data/command_kit.gemspec +7 -2
  5. data/lib/command_kit/completion/install.rb +276 -0
  6. data/lib/command_kit/env/prefix.rb +41 -0
  7. data/lib/command_kit/env/shell.rb +58 -0
  8. data/lib/command_kit/version.rb +1 -1
  9. metadata +4 -64
  10. data/spec/arguments/argument_spec.rb +0 -133
  11. data/spec/arguments/argument_value_spec.rb +0 -66
  12. data/spec/arguments_spec.rb +0 -279
  13. data/spec/bug_report_spec.rb +0 -266
  14. data/spec/colors_spec.rb +0 -771
  15. data/spec/command_kit_spec.rb +0 -8
  16. data/spec/command_name_spec.rb +0 -130
  17. data/spec/command_spec.rb +0 -123
  18. data/spec/commands/auto_load/subcommand_spec.rb +0 -82
  19. data/spec/commands/auto_load_spec.rb +0 -159
  20. data/spec/commands/auto_require_spec.rb +0 -142
  21. data/spec/commands/fixtures/test_auto_load/cli/commands/test1.rb +0 -10
  22. data/spec/commands/fixtures/test_auto_load/cli/commands/test2.rb +0 -10
  23. data/spec/commands/fixtures/test_auto_require/lib/test_auto_require/cli/commands/test1.rb +0 -10
  24. data/spec/commands/help_spec.rb +0 -66
  25. data/spec/commands/parent_command_spec.rb +0 -40
  26. data/spec/commands/subcommand_spec.rb +0 -99
  27. data/spec/commands_spec.rb +0 -865
  28. data/spec/description_spec.rb +0 -179
  29. data/spec/edit_spec.rb +0 -72
  30. data/spec/env/home_spec.rb +0 -46
  31. data/spec/env/path_spec.rb +0 -84
  32. data/spec/env_spec.rb +0 -123
  33. data/spec/examples_spec.rb +0 -211
  34. data/spec/exception_handler_spec.rb +0 -103
  35. data/spec/file_utils_spec.rb +0 -59
  36. data/spec/fixtures/template.erb +0 -5
  37. data/spec/help/man_spec.rb +0 -345
  38. data/spec/help_spec.rb +0 -94
  39. data/spec/inflector_spec.rb +0 -166
  40. data/spec/interactive_spec.rb +0 -415
  41. data/spec/main_spec.rb +0 -179
  42. data/spec/man_spec.rb +0 -46
  43. data/spec/open_app_spec.rb +0 -85
  44. data/spec/options/option_spec.rb +0 -343
  45. data/spec/options/option_value_spec.rb +0 -171
  46. data/spec/options/parser_spec.rb +0 -274
  47. data/spec/options/quiet_spec.rb +0 -51
  48. data/spec/options/verbose_spec.rb +0 -51
  49. data/spec/options/version_spec.rb +0 -146
  50. data/spec/options_spec.rb +0 -465
  51. data/spec/os/linux_spec.rb +0 -164
  52. data/spec/os_spec.rb +0 -233
  53. data/spec/package_manager_spec.rb +0 -806
  54. data/spec/pager_spec.rb +0 -217
  55. data/spec/printing/fields_spec.rb +0 -167
  56. data/spec/printing/indent_spec.rb +0 -132
  57. data/spec/printing/lists_spec.rb +0 -99
  58. data/spec/printing/tables/border_style.rb +0 -43
  59. data/spec/printing/tables/cell_builer_spec.rb +0 -135
  60. data/spec/printing/tables/row_builder_spec.rb +0 -165
  61. data/spec/printing/tables/style_spec.rb +0 -377
  62. data/spec/printing/tables/table_builder_spec.rb +0 -252
  63. data/spec/printing/tables/table_formatter_spec.rb +0 -1190
  64. data/spec/printing/tables_spec.rb +0 -1069
  65. data/spec/printing_spec.rb +0 -106
  66. data/spec/program_name_spec.rb +0 -70
  67. data/spec/spec_helper.rb +0 -3
  68. data/spec/stdio_spec.rb +0 -264
  69. data/spec/sudo_spec.rb +0 -51
  70. data/spec/terminal_spec.rb +0 -231
  71. data/spec/usage_spec.rb +0 -237
  72. data/spec/xdg_spec.rb +0 -191
data/spec/pager_spec.rb DELETED
@@ -1,217 +0,0 @@
1
- require 'spec_helper'
2
- require 'command_kit/pager'
3
-
4
- require 'stringio'
5
-
6
- describe CommandKit::Pager do
7
- module TestPager
8
- class TestCommand
9
- include CommandKit::Pager
10
- end
11
- end
12
-
13
- let(:command_class) { TestPager::TestCommand }
14
- subject { command_class.new }
15
-
16
- describe "#initialize" do
17
- context "when the PAGER env variable is set" do
18
- let(:pager) { 'foo' }
19
-
20
- subject { command_class.new(env: {'PAGER' => pager}) }
21
-
22
- it "must set @pager_command to the PAGER env variable" do
23
- expect(subject.instance_variable_get('@pager_command')).to eq(pager)
24
- end
25
- end
26
-
27
- context "when the PAGER env variable is not set" do
28
- context "but the PATH env variable is" do
29
- subject { command_class.new(env: {'PATH' => ENV.fetch('PATH')}) }
30
-
31
- it "must search PATH for one of the pagers" do
32
- expect(subject.instance_variable_get('@pager_command')).to eq("less -r")
33
- end
34
- end
35
- end
36
- end
37
-
38
- describe "#pager" do
39
- context "when stdout is not a TTY" do
40
- subject { command_class.new(stdout: StringIO.new) }
41
-
42
- it "must yield stdout" do
43
- expect { |b|
44
- subject.pager(&b)
45
- }.to yield_with_args(subject.stdout)
46
- end
47
- end
48
-
49
- context "when @pager_command isn't initialized" do
50
- before do
51
- subject.instance_variable_set('@pager_command',nil)
52
- end
53
-
54
- it "must yield stdout" do
55
- expect { |b|
56
- subject.pager(&b)
57
- }.to yield_with_args(subject.stdout)
58
- end
59
- end
60
-
61
- context "when stdout is a TTY and @pager_command is initialized" do
62
- let(:pager) { 'less -r' }
63
-
64
- subject { command_class.new(env: {'PAGER' => pager}) }
65
-
66
- let(:pager_io) { double('less') }
67
- let(:pager_pid) { double('pid') }
68
-
69
- before do
70
- expect(subject.stdout).to receive(:tty?).and_return(true)
71
-
72
- expect(IO).to receive(:popen).with(pager,'w').and_return(pager_io)
73
- expect(pager_io).to receive(:pid).and_return(pager_pid)
74
-
75
- expect(pager_io).to receive(:close)
76
- expect(Process).to receive(:waitpid).with(pager_pid)
77
- end
78
-
79
- it "must spawn a new process and yield an IO object" do
80
- expect { |b|
81
- subject.pager(&b)
82
- }.to yield_with_args(pager_io)
83
- end
84
-
85
- context "when Errno::EPIPE is raised" do
86
- it "must return gracefully" do
87
- expect {
88
- subject.pager do
89
- raise(Errno::EPIPE,"pipe broken")
90
- end
91
- }.to_not raise_error
92
- end
93
- end
94
- end
95
- end
96
-
97
- describe "#print_or_page" do
98
- let(:terminal_height) { 10 }
99
-
100
- before do
101
- expect(subject).to receive(:terminal_height).and_return(terminal_height)
102
- end
103
-
104
- context "when given a String" do
105
- context "and the number of lines is less than the console's height" do
106
- let(:string) { "foo#{$/}bar#{$/}" }
107
-
108
- it "must puts the String to stdout" do
109
- expect(subject.stdout).to receive(:puts).with(string)
110
-
111
- subject.print_or_page(string)
112
- end
113
- end
114
-
115
- context "and the number of lines is greater than the console's height" do
116
- let(:string) { "foo#{$/}bar#{$/}" * terminal_height }
117
-
118
- it "must spawn a pager and puts the String to the pager" do
119
- pager = double('pager')
120
- expect(subject).to receive(:pager).and_yield(pager)
121
- expect(pager).to receive(:puts).with(string)
122
-
123
- subject.print_or_page(string)
124
- end
125
- end
126
- end
127
-
128
- context "when given an Array" do
129
- context "and the number of lines is less than the console's height" do
130
- let(:array) { ['foo', 'bar'] }
131
-
132
- it "must puts the Array of Strings to stdout" do
133
- expect(subject.stdout).to receive(:puts).with(array)
134
-
135
- subject.print_or_page(array)
136
- end
137
- end
138
-
139
- context "and the number of lines is greater than the console's height" do
140
- let(:array) { ['foo', 'bar'] * terminal_height }
141
-
142
- it "must spawn a pager and puts the Array of Strings to the pager" do
143
- pager = double('pager')
144
- expect(subject).to receive(:pager).and_yield(pager)
145
- expect(pager).to receive(:puts).with(array)
146
-
147
- subject.print_or_page(array)
148
- end
149
- end
150
- end
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
217
- end
@@ -1,167 +0,0 @@
1
- require 'spec_helper'
2
- require 'command_kit/printing/fields'
3
-
4
- describe CommandKit::Printing::Fields do
5
- module TestPrintingFields
6
- class TestCmd
7
-
8
- include CommandKit::Printing::Fields
9
-
10
- end
11
- end
12
-
13
- let(:command_class) { TestPrintingFields::TestCmd }
14
- subject { command_class.new }
15
-
16
- let(:nl) { $/ }
17
-
18
- describe "#print_fields" do
19
- context "when given a Hash" do
20
- context "and all key values are the same length" do
21
- let(:name1) { 'A' }
22
- let(:value1) { 'foo' }
23
- let(:name2) { 'B' }
24
- let(:value2) { 'bar' }
25
-
26
- let(:hash) do
27
- {
28
- name1 => value1,
29
- name2 => value2
30
- }
31
- end
32
-
33
- it "must not left-justify the Hash keys" do
34
- expect {
35
- subject.print_fields(hash)
36
- }.to output("#{name1}: #{value1}#{nl}#{name2}: #{value2}#{nl}").to_stdout
37
- end
38
- end
39
-
40
- context "but key values have different lengths" do
41
- let(:name1) { 'A' }
42
- let(:value1) { 'foo' }
43
- let(:name2) { 'Bar' }
44
- let(:value2) { 'bar' }
45
-
46
- let(:hash) do
47
- {
48
- name1 => value1,
49
- name2 => value2
50
- }
51
- end
52
-
53
- it "must left-justify the Hash keys" do
54
- expect {
55
- subject.print_fields(hash)
56
- }.to output("#{name1}: #{value1}#{nl}#{name2}: #{value2}#{nl}").to_stdout
57
- end
58
- end
59
-
60
- context "but the key values are not Strings" do
61
- let(:name1) { 1 }
62
- let(:value1) { 'foo' }
63
- let(:name2) { 100 }
64
- let(:value2) { 'bar' }
65
-
66
- let(:hash) do
67
- {
68
- name1 => value1,
69
- name2 => value2
70
- }
71
- end
72
-
73
- it "must convert them to Strings before calculating justification" do
74
- expect {
75
- subject.print_fields(hash)
76
- }.to output("#{name1}: #{value1}#{nl}#{name2}: #{value2}#{nl}").to_stdout
77
- end
78
- end
79
- end
80
-
81
- context "when given an Array of tuples" do
82
- context "and all first tuple values are the same length" do
83
- let(:name1) { 'A' }
84
- let(:value1) { 'foo' }
85
- let(:name2) { 'B' }
86
- let(:value2) { 'bar' }
87
-
88
- let(:array) do
89
- [
90
- [name1, value1],
91
- [name2, value2]
92
- ]
93
- end
94
-
95
- it "must not left-justify the tuples" do
96
- expect {
97
- subject.print_fields(array)
98
- }.to output("#{name1}: #{value1}#{nl}#{name2}: #{value2}#{nl}").to_stdout
99
- end
100
- end
101
-
102
- context "but first tuple values have different lengths" do
103
- let(:name1) { 'A' }
104
- let(:value1) { 'foo' }
105
- let(:name2) { 'Bar' }
106
- let(:value2) { 'bar' }
107
-
108
- let(:array) do
109
- [
110
- [name1, value1],
111
- [name2, value2]
112
- ]
113
- end
114
-
115
- it "must left-justify the tuples" do
116
- expect {
117
- subject.print_fields(array)
118
- }.to output("#{name1}: #{value1}#{nl}#{name2}: #{value2}#{nl}").to_stdout
119
- end
120
- end
121
-
122
- context "but the first tuple values are not Strings" do
123
- let(:name1) { 1 }
124
- let(:value1) { 'foo' }
125
- let(:name2) { 100 }
126
- let(:value2) { 'bar' }
127
-
128
- let(:array) do
129
- [
130
- [name1, value1],
131
- [name2, value2]
132
- ]
133
- end
134
-
135
- it "must convert them to Strings before calculating justification" do
136
- expect {
137
- subject.print_fields(array)
138
- }.to output("#{name1}: #{value1}#{nl}#{name2}: #{value2}#{nl}").to_stdout
139
- end
140
- end
141
- end
142
-
143
- context "but the values contain multiple lines" do
144
- let(:name1) { 'A' }
145
- let(:value1) { 'foo' }
146
- let(:name2) { 'Bar' }
147
- let(:line1) { 'bar' }
148
- let(:line2) { 'baz' }
149
- let(:value2) do
150
- [line1, line2].join($/)
151
- end
152
-
153
- let(:hash) do
154
- {
155
- name1 => value1,
156
- name2 => value2
157
- }
158
- end
159
-
160
- it "must print the header with the first line and then indent the other lines" do
161
- expect {
162
- subject.print_fields(hash)
163
- }.to output("#{name1}: #{value1}#{nl}#{name2}: #{line1}#{nl} #{line2}#{nl}").to_stdout
164
- end
165
- end
166
- end
167
- end
@@ -1,132 +0,0 @@
1
- require 'spec_helper'
2
- require 'command_kit/printing/indent'
3
-
4
- describe CommandKit::Printing::Indent do
5
- module TestIndent
6
- class TestCommand
7
- include CommandKit::Printing::Indent
8
- end
9
- end
10
-
11
- let(:command_class) { TestIndent::TestCommand }
12
- subject { command_class.new }
13
-
14
- describe "#initialize" do
15
- it "must initialize #indent to 0" do
16
- expect(subject.indent).to eq(0)
17
- end
18
-
19
- context "when the class has a superclass" do
20
- module TestIndent
21
- class TestSuperCommand
22
-
23
- attr_reader :var
24
-
25
- def initialize(var: 'default')
26
- @var = var
27
- end
28
-
29
- end
30
-
31
- class TestSubCommand < TestSuperCommand
32
-
33
- include CommandKit::Printing::Indent
34
-
35
- end
36
- end
37
-
38
- let(:command_class) { TestIndent::TestSubCommand }
39
-
40
- it "must initialize @indent to 0" do
41
- expect(subject.indent).to eq(0)
42
- end
43
-
44
- it "must call super()" do
45
- expect(subject.var).to eq('default')
46
- end
47
-
48
- context "and additional keyword arguments are given" do
49
- let(:var) { 'foo' }
50
-
51
- subject { command_class.new(var: var) }
52
-
53
- it "must call super() with the additional keyword arguments" do
54
- expect(subject.var).to eq(var)
55
- end
56
- end
57
- end
58
- end
59
-
60
- describe "#indent" do
61
- context "when no block is given" do
62
- it "must return the indentation level" do
63
- expect(subject.indent).to eq(0)
64
- end
65
- end
66
-
67
- context "when a block is given" do
68
- it do
69
- expect { |b| subject.indent(&b) }.to yield_control
70
- end
71
-
72
- it "must increase the indent level by 2 then yield" do
73
- expect(subject.indent).to eq(0)
74
-
75
- subject.indent do
76
- expect(subject.indent).to eq(2)
77
- end
78
- end
79
-
80
- it "must restore the indententation level to it's original value" do
81
- subject.indent do
82
- expect(subject.indent).to eq(2)
83
- end
84
-
85
- expect(subject.indent).to eq(0)
86
- end
87
-
88
- context "when an exception occurrs within the given block" do
89
- it "must not rescue the exception" do
90
- expect {
91
- subject.indent do
92
- raise("error")
93
- end
94
- }.to raise_error(RuntimeError,"error")
95
- end
96
-
97
- it "must restore the indententation level to it's original value" do
98
- begin
99
- subject.indent do
100
- expect(subject.indent).to eq(2)
101
- raise("error")
102
- end
103
- rescue
104
- end
105
-
106
- expect(subject.indent).to eq(0)
107
- end
108
- end
109
- end
110
- end
111
-
112
- describe "#puts" do
113
- let(:nl) { $/ }
114
- let(:text) { 'hello world' }
115
-
116
- context "when the indententation level is 0" do
117
- it "must not add leading indentation" do
118
- expect { subject.puts(text) }.to output("#{text}#{nl}").to_stdout
119
- end
120
- end
121
-
122
- context "when the indententation level is > 0" do
123
- it "must add a number of spaces to the text" do
124
- expect {
125
- subject.indent do
126
- subject.puts(text)
127
- end
128
- }.to output(" #{text}#{nl}").to_stdout
129
- end
130
- end
131
- end
132
- end
@@ -1,99 +0,0 @@
1
- require 'spec_helper'
2
- require 'command_kit/printing/lists'
3
-
4
- describe CommandKit::Printing::Lists do
5
- module TestPrintingLists
6
- class TestCmd
7
-
8
- include CommandKit::Printing::Lists
9
-
10
- end
11
- end
12
-
13
- let(:command_class) { TestPrintingLists::TestCmd }
14
- subject { command_class.new }
15
-
16
- describe "#print_list" do
17
- let(:list) { %w[foo bar baz] }
18
-
19
- it "must print each item in the list with a '*' bullet" do
20
- expect {
21
- subject.print_list(list)
22
- }.to output(
23
- list.map { |item| "* #{item}" }.join($/) + $/
24
- ).to_stdout
25
- end
26
-
27
- context "when the list contins multi-line Strings" do
28
- let(:item1) { "foo" }
29
- let(:item2) do
30
- [
31
- "line 1",
32
- "line 2",
33
- "line 3"
34
- ].join($/)
35
- end
36
- let(:item3) { "bar" }
37
- let(:list) { [item1, item2, item3] }
38
-
39
- it "must print the bullet with the first line and then indent the other lines" do
40
- expect {
41
- subject.print_list(list)
42
- }.to output(
43
- [
44
- "* #{item1}",
45
- "* #{item2.lines[0].chomp}",
46
- " #{item2.lines[1].chomp}",
47
- " #{item2.lines[2].chomp}",
48
- "* #{item3}",
49
- ''
50
- ].join($/)
51
- ).to_stdout
52
- end
53
- end
54
-
55
- context "when the list contains nested-lists" do
56
- let(:item1) { 'item 1' }
57
- let(:sub_item1) { 'sub-item 1' }
58
- let(:sub_item2) { 'sub-item 2' }
59
- let(:item2) { 'item 2' }
60
-
61
- let(:list) do
62
- [
63
- 'item 1',
64
- [
65
- 'sub-item 1',
66
- 'sub-item 2'
67
- ],
68
- 'item 2'
69
- ]
70
- end
71
-
72
- it "must indent and print each sub-list" do
73
- expect {
74
- subject.print_list(list)
75
- }.to output(
76
- [
77
- "* #{item1}",
78
- " * #{sub_item1}",
79
- " * #{sub_item2}",
80
- "* #{item2}",
81
- ''
82
- ].join($/)
83
- ).to_stdout
84
- end
85
- end
86
-
87
- context "when the bullet: keyowrd argument is given" do
88
- let(:bullet) { '-' }
89
-
90
- it "must print each item in the list with the bullet character" do
91
- expect {
92
- subject.print_list(list, bullet: bullet)
93
- }.to output(
94
- list.map { |item| "#{bullet} #{item}" }.join($/) + $/
95
- ).to_stdout
96
- end
97
- end
98
- end
99
- end
@@ -1,43 +0,0 @@
1
- require 'spec_helper'
2
- require 'command_kit/printing/tables/border_style'
3
-
4
- describe CommandKit::Printing::Tables::BorderStyle do
5
- describe "#initialize" do
6
- [
7
- :top_left_corner,
8
- :top_border,
9
- :top_joined_border,
10
- :top_right_corner,
11
- :left_border,
12
- :left_joined_border,
13
- :horizontal_separator,
14
- :vertical_separator,
15
- :inner_joined_border,
16
- :right_border,
17
- :right_joined_border,
18
- :bottom_border,
19
- :bottom_left_corner,
20
- :bottom_joined_border,
21
- :bottom_right_corner
22
- ].each do |keyword|
23
- context "when #{keyword}: keyword is given" do
24
- let(:keyword) { keyword }
25
- let(:value) { 'x' }
26
-
27
- subject { described_class.new(**{keyword => value}) }
28
-
29
- it "must set ##{keyword}" do
30
- expect(subject.send(keyword)).to eq(value)
31
- end
32
- end
33
-
34
- context "when #{keyword}: keyword is not given" do
35
- let(:keyword) { keyword }
36
-
37
- it "must default ##{keyword} to ' '" do
38
- expect(subject.send(keyword)).to eq(' ')
39
- end
40
- end
41
- end
42
- end
43
- end