command_kit 0.1.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +18 -3
  3. data/.rubocop.yml +141 -0
  4. data/ChangeLog.md +165 -0
  5. data/Gemfile +3 -0
  6. data/README.md +186 -118
  7. data/Rakefile +3 -2
  8. data/command_kit.gemspec +4 -4
  9. data/examples/command.rb +1 -1
  10. data/gemspec.yml +7 -0
  11. data/lib/command_kit/arguments/argument.rb +2 -2
  12. data/lib/command_kit/arguments.rb +36 -7
  13. data/lib/command_kit/colors.rb +702 -53
  14. data/lib/command_kit/command.rb +2 -3
  15. data/lib/command_kit/commands/auto_load.rb +8 -1
  16. data/lib/command_kit/commands/help.rb +3 -2
  17. data/lib/command_kit/commands/subcommand.rb +1 -1
  18. data/lib/command_kit/commands.rb +24 -9
  19. data/lib/command_kit/env/path.rb +1 -1
  20. data/lib/command_kit/file_utils.rb +46 -0
  21. data/lib/command_kit/help/man.rb +17 -33
  22. data/lib/command_kit/inflector.rb +47 -17
  23. data/lib/command_kit/interactive.rb +9 -0
  24. data/lib/command_kit/main.rb +7 -9
  25. data/lib/command_kit/man.rb +44 -0
  26. data/lib/command_kit/open_app.rb +69 -0
  27. data/lib/command_kit/options/option.rb +41 -27
  28. data/lib/command_kit/options/option_value.rb +3 -2
  29. data/lib/command_kit/options/parser.rb +17 -22
  30. data/lib/command_kit/options.rb +102 -14
  31. data/lib/command_kit/os/linux.rb +157 -0
  32. data/lib/command_kit/os.rb +159 -11
  33. data/lib/command_kit/package_manager.rb +200 -0
  34. data/lib/command_kit/pager.rb +46 -4
  35. data/lib/command_kit/printing/indent.rb +4 -4
  36. data/lib/command_kit/printing.rb +14 -3
  37. data/lib/command_kit/program_name.rb +9 -0
  38. data/lib/command_kit/sudo.rb +40 -0
  39. data/lib/command_kit/terminal.rb +5 -0
  40. data/lib/command_kit/version.rb +1 -1
  41. data/spec/arguments/argument_spec.rb +1 -1
  42. data/spec/arguments_spec.rb +84 -1
  43. data/spec/colors_spec.rb +357 -70
  44. data/spec/command_spec.rb +77 -6
  45. data/spec/commands/auto_load_spec.rb +33 -2
  46. data/spec/commands_spec.rb +101 -29
  47. data/spec/env/path_spec.rb +6 -0
  48. data/spec/exception_handler_spec.rb +1 -1
  49. data/spec/file_utils_spec.rb +59 -0
  50. data/spec/fixtures/template.erb +5 -0
  51. data/spec/help/man_spec.rb +54 -57
  52. data/spec/inflector_spec.rb +70 -8
  53. data/spec/man_spec.rb +46 -0
  54. data/spec/open_app_spec.rb +85 -0
  55. data/spec/options/option_spec.rb +38 -2
  56. data/spec/options/option_value_spec.rb +55 -0
  57. data/spec/options/parser_spec.rb +0 -10
  58. data/spec/options_spec.rb +328 -0
  59. data/spec/os/linux_spec.rb +164 -0
  60. data/spec/os_spec.rb +200 -13
  61. data/spec/package_manager_spec.rb +806 -0
  62. data/spec/pager_spec.rb +71 -6
  63. data/spec/printing/indent_spec.rb +7 -5
  64. data/spec/printing_spec.rb +23 -1
  65. data/spec/program_name_spec.rb +8 -0
  66. data/spec/sudo_spec.rb +51 -0
  67. data/spec/terminal_spec.rb +30 -0
  68. data/spec/usage_spec.rb +1 -1
  69. metadata +23 -4
data/README.md CHANGED
@@ -1,8 +1,12 @@
1
1
  # command_kit
2
2
 
3
+ [![Build Status](https://github.com/postmodern/command_kit.rb/workflows/CI/badge.svg?branch=main)](https://github.com/postmodern/command_kit.rb/actions)
4
+ [![Code Climate](https://codeclimate.com/github/postmodern/command_kit.rb.svg)](https://codeclimate.com/github/postmodern/command_kit.rb)
5
+ [![Gem Version](https://badge.fury.io/rb/command_kit.svg)](https://badge.fury.io/rb/command_kit)
6
+
3
7
  * [Homepage](https://github.com/postmodern/command_kit.rb#readme)
4
- * [Forum](https://github.com/postmodern/command_kit.rb/discussions)
5
- * [Issues](https://github.com/postmodern/command_kit.rb/issues)
8
+ * [Forum](https://github.com/postmodern/command_kit.rb/discussions) |
9
+ [Issues](https://github.com/postmodern/command_kit.rb/issues)
6
10
  * [Documentation](http://rubydoc.info/gems/command_kit/frames)
7
11
 
8
12
  ## Description
@@ -12,53 +16,26 @@ plain-old Ruby classes.
12
16
 
13
17
  ## Features
14
18
 
15
- * Supports defining commands as Classes.
16
- * Supports defining options and arguments as attributes.
17
- * Supports extending commands via inheritance.
18
- * Supports subcommands (explicit or lazy-loaded) and command aliases.
19
- * Correctly handles Ctrl^C and SIGINT interrupts (aka exit 130).
20
- * Correctly handles broken pipes (aka `mycmd | head`).
21
- * Correctly handles when stdout or stdin is redirected to a file.
22
- * Uses [OptionParser][optparse] for POSIX option parsing.
23
- * Supports optionally displaying a man-page instead of `--help`
24
- (see {CommandKit::Help::Man}).
25
- * Supports optional ANSI coloring.
26
- * Supports interactively prompting for user input.
27
- * Supports easily detecting the terminal size.
28
- * Supports paging output with `less` or `more`.
29
- * Supports XDG directories (`~/.config/`, `~/.local/share/`, `~/.cache/`).
30
- * Easy to test (ex: `MyCmd.main(arg1, arg2, options: {foo: foo}) # => 0`)
31
-
32
- ### API
33
-
34
- * [CommandKit::Arguments](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Arguments)
35
- * [CommandKit::Colors](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Colors)
36
- * [CommandKit::Command](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Command)
37
- * [CommandKit::CommandName](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/CommandName)
38
- * [CommandKit::Commands](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Commands)
39
- * [CommandKit::Commands::AutoLoad](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Commands/AutoLoad)
40
- * [CommandKit::Commands::AutoRequire](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Commands/AutoRequire)
41
- * [CommandKit::Description](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Description)
42
- * [CommandKit::Env](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Env)
43
- * [CommandKit::Env::Home](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Env/Home)
44
- * [CommandKit::Env::Path](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Env/Path)
45
- * [CommandKit::Examples](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Examples)
46
- * [CommandKit::ExceptionHandler](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/ExceptionHandler)
47
- * [CommandKit::Help](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Help)
48
- * [CommandKit::Help::Man](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Help/Man)
49
- * [CommandKit::Interactive](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Interactive)
50
- * [CommandKit::Main](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Main)
51
- * [CommandKit::Options](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Options)
52
- * [CommandKit::Options::Quiet](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Options/Quiet)
53
- * [CommandKit::Options::Verbose](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Options/Verbose)
54
- * [CommandKit::Pager](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Pager)
55
- * [CommandKit::Printing](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Printing)
56
- * [CommandKit::Printing::Indent](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Printing/Indent)
57
- * [CommandKit::ProgramName](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/ProgramName)
58
- * [CommandKit::Stdio](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Stdio)
59
- * [CommandKit::Terminal](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Terminal)
60
- * [CommandKit::Usage](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Usage)
61
- * [CommandKit::XDG](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/XDG)
19
+ * **Simple** - Commands are plain-old ruby classes, with options and
20
+ arguments declared as attributes. All features are ruby modules that can be
21
+ included into command classes.
22
+ * **Correct** - CommandKit behaves like a standard UNIX command.
23
+ * Safely handles Ctrl^C / SIGINT interrupts and [exits with 130](https://tldp.org/LDP/abs/html/exitcodes.html).
24
+ * Safely handles broken pipes (aka `mycmd | head`).
25
+ * Respects common environment variables (ex: `TERM=dumb`).
26
+ * Uses [OptionParser][optparse] for POSIX option parsing.
27
+ * Disables ANSI color when output is redirected to a file.
28
+ * **Complete** - Provides many additional CLI features.
29
+ * OS detection.
30
+ * Terminal size detection.
31
+ * ANSI coloring support.
32
+ * Interactive input.
33
+ * Subcommands (explicit or lazy-loaded) and command aliases.
34
+ * Displaying man pages for `--help`/`help`.
35
+ * Using the pager (aka `less`).
36
+ * [XDG directories](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html) (aka `~/.config/`, `~/.local/share/`, `~/.cache/`).
37
+ * **Testable** - Since commands are plain-old ruby classes, it's easy to
38
+ initialize them and call `#main` or `#run`.
62
39
 
63
40
  ## Anti-Features
64
41
 
@@ -66,103 +43,194 @@ plain-old Ruby classes.
66
43
  * Does not implement it's own option parser.
67
44
  * Not named after a comic-book Superhero.
68
45
 
46
+ ## Requirements
47
+
48
+ * [ruby] >= 2.7.0
49
+
50
+ ## Install
51
+
52
+ ```sh
53
+ $ gem install command_kit
54
+ ```
55
+
56
+ ### gemspec
57
+
58
+ ```ruby
59
+ gem.add_dependency 'command_kit', '~> 0.2'
60
+ ```
61
+
62
+ ### Gemfile
63
+
64
+ ```ruby
65
+ gem 'command_kit', '~> 0.2'
66
+ ```
67
+
69
68
  ## Examples
70
69
 
71
70
  ### lib/foo/cli/my_cmd.rb
72
71
 
73
- require 'command_kit'
74
-
75
- module Foo
76
- module CLI
77
- class MyCmd < CommandKit::Command
78
-
79
- usage '[OPTIONS] [-o OUTPUT] FILE'
80
-
81
- option :count, short: '-c',
82
- value: {
83
- type: Integer,
84
- default: 1
85
- },
86
- desc: "Number of times"
87
-
88
- option :output, short: '-o',
89
- value: {
90
- type: String,
91
- usage: 'FILE'
92
- },
93
- desc: "Optional output file"
94
-
95
- option :verbose, short: '-v', desc: "Increase verbose level" do
96
- @verbose += 1
97
- end
98
-
99
- argument :file, required: true,
100
- usage: 'FILE',
101
- desc: "Input file"
102
-
103
- examples [
104
- '-o path/to/output.txt path/to/input.txt',
105
- '-v -c 2 -o path/to/output.txt path/to/input.txt',
106
- ]
107
-
108
- description 'Example command'
109
-
110
- def initialize(**kwargs)
111
- super(**kwargs)
112
-
113
- @verbose = 0
114
- end
115
-
116
- def run(file)
117
- puts "count=#{options[:count].inspect}"
118
- puts "output=#{options[:output].inspect}"
119
- puts "file=#{file.inspect}"
120
- puts "verbose=#{@verbose.inspect}"
121
- end
122
-
123
- end
72
+ ```ruby
73
+ require 'command_kit'
74
+
75
+ module Foo
76
+ module CLI
77
+ class MyCmd < CommandKit::Command
78
+
79
+ usage '[OPTIONS] [-o OUTPUT] FILE'
80
+
81
+ option :count, short: '-c',
82
+ value: {
83
+ type: Integer,
84
+ default: 1
85
+ },
86
+ desc: "Number of times"
87
+
88
+ option :output, short: '-o',
89
+ value: {
90
+ type: String,
91
+ usage: 'FILE'
92
+ },
93
+ desc: "Optional output file"
94
+
95
+ option :verbose, short: '-v', desc: "Increase verbose level" do
96
+ @verbose += 1
124
97
  end
98
+
99
+ argument :file, required: true,
100
+ usage: 'FILE',
101
+ desc: "Input file"
102
+
103
+ examples [
104
+ '-o path/to/output.txt path/to/input.txt',
105
+ '-v -c 2 -o path/to/output.txt path/to/input.txt',
106
+ ]
107
+
108
+ description 'Example command'
109
+
110
+ def initialize(**kwargs)
111
+ super(**kwargs)
112
+
113
+ @verbose = 0
114
+ end
115
+
116
+ def run(file)
117
+ puts "count=#{options[:count].inspect}"
118
+ puts "output=#{options[:output].inspect}"
119
+ puts "file=#{file.inspect}"
120
+ puts "verbose=#{@verbose.inspect}"
121
+ end
122
+
125
123
  end
124
+ end
125
+ end
126
+ ```
126
127
 
127
128
  ### bin/my_cmd
128
129
 
129
- #!/usr/bin/env ruby
130
-
131
- $LOAD_PATH.unshift(File.expand_path('../../lib',__FILE__))
132
- require 'foo/cli/my_cmd'
133
-
134
- Foo::CLI::MyCmd.start
130
+ ```ruby
131
+ #!/usr/bin/env ruby
132
+
133
+ $LOAD_PATH.unshift(File.expand_path('../../lib',__FILE__))
134
+ require 'foo/cli/my_cmd'
135
+
136
+ Foo::CLI::MyCmd.start
137
+ ```
135
138
 
136
139
  ### --help
137
140
 
138
141
  Usage: my_cmd [OPTIONS] [-o OUTPUT] FILE
139
-
142
+
140
143
  Options:
141
144
  -c, --count INT Number of times (Default: 1)
142
145
  -o, --output FILE Optional output file
143
146
  -v, --verbose Increase verbose level
144
147
  -h, --help Print help information
145
-
148
+
146
149
  Arguments:
147
150
  FILE Input file
148
-
151
+
149
152
  Examples:
150
153
  my_cmd -o path/to/output.txt path/to/input.txt
151
154
  my_cmd -v -c 2 -o path/to/output.txt path/to/input.txt
152
-
153
- Example command
154
155
 
155
- ## Requirements
156
-
157
- * [ruby] >= 2.7.0
156
+ Example command
158
157
 
159
- ## Install
158
+ ## Testing
159
+
160
+ ### RSpec
161
+
162
+ ```ruby
163
+ require 'spec_helper'
164
+ require 'stringio'
165
+ require 'foo/cli/my_cmd'
166
+
167
+ describe Foo::CLI::MyCmd do
168
+ let(:stdin) { StringIO.new }
169
+ let(:stdout) { StringIO.new }
170
+ let(:stderr) { StringIO.new }
171
+ let(:env) { ENV }
172
+
173
+ subject do
174
+ described_class.new(
175
+ stdin: stdin,
176
+ stdout: stdout,
177
+ stderr: stderr,
178
+ env: env
179
+ )
180
+ end
181
+
182
+ # testing with raw options/arguments
183
+ describe "#main" do
184
+ context "when executed with no arguments" do
185
+ it "must exit with -1" do
186
+ expect(subject.main([])).to eq(-1)
187
+ end
188
+ end
160
189
 
161
- $ gem install command_kit
190
+ context "when executed with -o OUTPUT" do
191
+ let(:file) { ... }
192
+ let(:output) { ... }
162
193
 
163
- ### Gemfile
194
+ before { subject.main(["-o", output, file]) }
164
195
 
165
- gem 'command_kit', '~> 0.1'
196
+ it "must create the output file" do
197
+ ...
198
+ end
199
+ end
200
+ end
201
+ end
202
+ ```
203
+
204
+ ### Reference
205
+
206
+ * [CommandKit::Arguments](https://rubydoc.info/gems/command_kit/CommandKit/Arguments)
207
+ * [CommandKit::Colors](https://rubydoc.info/gems/command_kit/CommandKit/Colors)
208
+ * [CommandKit::Command](https://rubydoc.info/gems/command_kit/CommandKit/Command)
209
+ * [CommandKit::CommandName](https://rubydoc.info/gems/command_kit/CommandKit/CommandName)
210
+ * [CommandKit::Commands](https://rubydoc.info/gems/command_kit/CommandKit/Commands)
211
+ * [CommandKit::Commands::AutoLoad](https://rubydoc.info/gems/command_kit/CommandKit/Commands/AutoLoad)
212
+ * [CommandKit::Commands::AutoRequire](https://rubydoc.info/gems/command_kit/CommandKit/Commands/AutoRequire)
213
+ * [CommandKit::Description](https://rubydoc.info/gems/command_kit/CommandKit/Description)
214
+ * [CommandKit::Env](https://rubydoc.info/gems/command_kit/CommandKit/Env)
215
+ * [CommandKit::Env::Home](https://rubydoc.info/gems/command_kit/CommandKit/Env/Home)
216
+ * [CommandKit::Env::Path](https://rubydoc.info/gems/command_kit/CommandKit/Env/Path)
217
+ * [CommandKit::Examples](https://rubydoc.info/gems/command_kit/CommandKit/Examples)
218
+ * [CommandKit::ExceptionHandler](https://rubydoc.info/gems/command_kit/CommandKit/ExceptionHandler)
219
+ * [CommandKit::Help](https://rubydoc.info/gems/command_kit/CommandKit/Help)
220
+ * [CommandKit::Help::Man](https://rubydoc.info/gems/command_kit/CommandKit/Help/Man)
221
+ * [CommandKit::Interactive](https://rubydoc.info/gems/command_kit/CommandKit/Interactive)
222
+ * [CommandKit::Main](https://rubydoc.info/gems/command_kit/CommandKit/Main)
223
+ * [CommandKit::Options](https://rubydoc.info/gems/command_kit/CommandKit/Options)
224
+ * [CommandKit::Options::Quiet](https://rubydoc.info/gems/command_kit/CommandKit/Options/Quiet)
225
+ * [CommandKit::Options::Verbose](https://rubydoc.info/gems/command_kit/CommandKit/Options/Verbose)
226
+ * [CommandKit::Pager](https://rubydoc.info/gems/command_kit/CommandKit/Pager)
227
+ * [CommandKit::Printing](https://rubydoc.info/gems/command_kit/CommandKit/Printing)
228
+ * [CommandKit::Printing::Indent](https://rubydoc.info/gems/command_kit/CommandKit/Printing/Indent)
229
+ * [CommandKit::ProgramName](https://rubydoc.info/gems/command_kit/CommandKit/ProgramName)
230
+ * [CommandKit::Stdio](https://rubydoc.info/gems/command_kit/CommandKit/Stdio)
231
+ * [CommandKit::Terminal](https://rubydoc.info/gems/command_kit/CommandKit/Terminal)
232
+ * [CommandKit::Usage](https://rubydoc.info/gems/command_kit/CommandKit/Usage)
233
+ * [CommandKit::XDG](https://rubydoc.info/gems/command_kit/CommandKit/XDG)
166
234
 
167
235
  ## Alternatives
168
236
 
data/Rakefile CHANGED
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  require 'rubygems'
4
2
 
5
3
  begin
@@ -21,3 +19,6 @@ task :default => :spec
21
19
  require 'yard'
22
20
  YARD::Rake::YardocTask.new
23
21
  task :doc => :yard
22
+
23
+ require 'rubocop/rake_task'
24
+ RuboCop::RakeTask.new
data/command_kit.gemspec CHANGED
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  require 'yaml'
4
2
 
5
3
  Gem::Specification.new do |gem|
@@ -20,11 +18,13 @@ Gem::Specification.new do |gem|
20
18
  gem.authors = Array(gemspec['authors'])
21
19
  gem.email = gemspec['email']
22
20
  gem.homepage = gemspec['homepage']
21
+ gem.metadata = gemspec['metadata'] if gemspec['metadata']
23
22
 
24
23
  glob = lambda { |patterns| gem.files & Dir[*patterns] }
25
24
 
26
- gem.files = `git ls-files`.split($/)
27
- gem.files = glob[gemspec['files']] if gemspec['files']
25
+ gem.files = if gemspec['files'] then glob[gemspec['files']]
26
+ else `git ls-files`.split($/)
27
+ end
28
28
 
29
29
  gem.executables = gemspec.fetch('executables') do
30
30
  glob['bin/*'].map { |path| File.basename(path) }
data/examples/command.rb CHANGED
@@ -16,7 +16,7 @@ class Command < CommandKit::Command
16
16
 
17
17
  option :output, value: {
18
18
  type: String,
19
- usage: 'FILE',
19
+ usage: 'FILE'
20
20
  },
21
21
  short: '-o',
22
22
  desc: "Optional output file"
data/gemspec.yml CHANGED
@@ -9,6 +9,13 @@ authors: Postmodern
9
9
  email: postmodern.mod3@gmail.com
10
10
  homepage: https://github.com/postmodern/command_kit.rb#readme
11
11
 
12
+ metadata:
13
+ documentation_uri: https://rubydoc.info/gems/command_kit
14
+ source_code_uri: https://github.com/postmodern/command_kit.rb
15
+ bug_tracker_uri: https://github.com/postmodern/command_kit.rb/issues
16
+ changelog_uri: https://github.com/postmodern/command_kit.rb/blob/main/ChangeLog.md
17
+ rubygems_mfa_required: 'true'
18
+
12
19
  required_ruby_version: ">= 2.7.0"
13
20
 
14
21
  development_dependencies:
@@ -16,7 +16,7 @@ module CommandKit
16
16
 
17
17
  # The argument's description.
18
18
  #
19
- # @return [String]
19
+ # @return [String, Array<String>]
20
20
  attr_reader :desc
21
21
 
22
22
  #
@@ -34,7 +34,7 @@ module CommandKit
34
34
  # @param [Boolean] repeats
35
35
  # Specifies whether the argument can be repeated multiple times.
36
36
  #
37
- # @param [String] desc
37
+ # @param [String, Array<String>] desc
38
38
  # The description for the argument.
39
39
  #
40
40
  # @yield [(value)]
@@ -1,8 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'command_kit/arguments/argument'
4
+ require 'command_kit/usage'
3
5
  require 'command_kit/main'
4
6
  require 'command_kit/help'
5
- require 'command_kit/arguments/argument'
7
+ require 'command_kit/printing'
6
8
 
7
9
  module CommandKit
8
10
  #
@@ -44,9 +46,19 @@ module CommandKit
44
46
  # def run(*files)
45
47
  # end
46
48
  #
49
+ # ### Multi-line descriptions
50
+ #
51
+ # argument :arg, desc: [
52
+ # 'line1',
53
+ # 'line2',
54
+ # '...'
55
+ # ]
56
+ #
47
57
  module Arguments
58
+ include Usage
48
59
  include Main
49
60
  include Help
61
+ include Printing
50
62
 
51
63
  #
52
64
  # @api private
@@ -110,7 +122,7 @@ module CommandKit
110
122
  # @option kwargs [Boolean] repeats
111
123
  # Specifies whether the argument can be repeated multiple times.
112
124
  #
113
- # @option kwargs [String] desc
125
+ # @option kwargs [String, Array<String>] desc
114
126
  # The description for the argument.
115
127
  #
116
128
  # @return [Argument]
@@ -119,9 +131,15 @@ module CommandKit
119
131
  # @example Define an argument:
120
132
  # argument :bar, desc: "Bar argument"
121
133
  #
134
+ # @example Defines an argument with a multi-line description:
135
+ # argument :bar, desc: [
136
+ # "Line 1 ...",
137
+ # "Line 2 ..."
138
+ # ]
139
+ #
122
140
  # @example With a custom usage string:
123
- # option :bar, usage: 'BAR',
124
- # desc: "Bar argument"
141
+ # argument :bar, usage: 'BAR',
142
+ # desc: "Bar argument"
125
143
  #
126
144
  # @example With a custom type:
127
145
  # argument :bar, desc: "Bar argument"
@@ -168,7 +186,7 @@ module CommandKit
168
186
  help_usage
169
187
  return 1
170
188
  elsif argv.length > (required_args + optional_args) && !has_repeats_arg
171
- print_error("too many arguments given")
189
+ print_error("too many arguments given.")
172
190
  help_usage
173
191
  return 1
174
192
  end
@@ -186,8 +204,19 @@ module CommandKit
186
204
  puts
187
205
  puts 'Arguments:'
188
206
 
189
- self.class.arguments.each_value do |arg|
190
- puts " #{arg.usage.ljust(33)}#{arg.desc}"
207
+ arguments.each_value do |arg|
208
+ case arg.desc
209
+ when Array
210
+ arg.desc.each_with_index do |line,index|
211
+ if index == 0
212
+ puts " #{arg.usage.ljust(33)}#{line}"
213
+ else
214
+ puts " #{' '.ljust(33)}#{line}"
215
+ end
216
+ end
217
+ else
218
+ puts " #{arg.usage.ljust(33)}#{arg.desc}"
219
+ end
191
220
  end
192
221
  end
193
222
  end