command_kit 0.1.0.rc1 → 0.2.2
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 +17 -3
- data/.rubocop.yml +141 -0
- data/ChangeLog.md +102 -1
- data/Gemfile +3 -0
- data/README.md +187 -116
- data/Rakefile +3 -2
- data/command_kit.gemspec +4 -4
- data/examples/command.rb +1 -1
- data/gemspec.yml +8 -1
- data/lib/command_kit/arguments/argument.rb +2 -0
- data/lib/command_kit/arguments/argument_value.rb +2 -0
- data/lib/command_kit/arguments.rb +25 -6
- data/lib/command_kit/colors.rb +253 -45
- data/lib/command_kit/command.rb +6 -1
- data/lib/command_kit/command_name.rb +9 -0
- data/lib/command_kit/commands/auto_load.rb +24 -1
- data/lib/command_kit/commands/auto_require.rb +16 -0
- data/lib/command_kit/commands/command.rb +3 -0
- data/lib/command_kit/commands/help.rb +5 -2
- data/lib/command_kit/commands/parent_command.rb +7 -0
- data/lib/command_kit/commands/subcommand.rb +13 -1
- data/lib/command_kit/commands.rb +54 -9
- data/lib/command_kit/description.rb +12 -1
- data/lib/command_kit/env/home.rb +9 -0
- data/lib/command_kit/env/path.rb +16 -1
- data/lib/command_kit/env.rb +4 -0
- data/lib/command_kit/examples.rb +12 -1
- data/lib/command_kit/exception_handler.rb +4 -0
- data/lib/command_kit/help/man.rb +28 -31
- data/lib/command_kit/help.rb +7 -1
- data/lib/command_kit/inflector.rb +49 -17
- data/lib/command_kit/interactive.rb +71 -1
- data/lib/command_kit/main.rb +18 -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 +3 -6
- data/lib/command_kit/options/option_value.rb +5 -2
- data/lib/command_kit/options/parser.rb +46 -19
- data/lib/command_kit/options/quiet.rb +3 -0
- data/lib/command_kit/options/verbose.rb +5 -0
- data/lib/command_kit/options/version.rb +6 -0
- data/lib/command_kit/options.rb +32 -7
- data/lib/command_kit/os/linux.rb +157 -0
- data/lib/command_kit/os.rb +165 -11
- data/lib/command_kit/package_manager.rb +200 -0
- data/lib/command_kit/pager.rb +73 -4
- data/lib/command_kit/printing/indent.rb +27 -4
- data/lib/command_kit/printing.rb +35 -1
- data/lib/command_kit/program_name.rb +7 -0
- data/lib/command_kit/stdio.rb +24 -0
- data/lib/command_kit/sudo.rb +40 -0
- data/lib/command_kit/terminal.rb +17 -0
- data/lib/command_kit/usage.rb +14 -0
- data/lib/command_kit/version.rb +1 -1
- data/lib/command_kit/xdg.rb +13 -0
- data/lib/command_kit.rb +1 -0
- data/spec/arguments/argument_spec.rb +2 -2
- data/spec/arguments_spec.rb +54 -28
- data/spec/colors_spec.rb +277 -13
- data/spec/command_name_spec.rb +1 -1
- data/spec/command_spec.rb +79 -5
- data/spec/commands/auto_load/subcommand_spec.rb +1 -1
- data/spec/commands/auto_load_spec.rb +34 -3
- data/spec/commands/auto_require_spec.rb +2 -2
- data/spec/commands/help_spec.rb +1 -1
- data/spec/commands/parent_command_spec.rb +1 -1
- data/spec/commands/subcommand_spec.rb +1 -1
- data/spec/commands_spec.rb +102 -30
- data/spec/description_spec.rb +1 -25
- data/spec/env/home_spec.rb +1 -1
- data/spec/env/path_spec.rb +7 -1
- data/spec/examples_spec.rb +1 -25
- data/spec/exception_handler_spec.rb +1 -1
- data/spec/help/man_spec.rb +55 -58
- data/spec/help_spec.rb +0 -25
- data/spec/inflector_spec.rb +71 -9
- data/spec/main_spec.rb +7 -7
- data/spec/man_spec.rb +46 -0
- data/spec/open_app_spec.rb +85 -0
- data/spec/options/option_spec.rb +5 -5
- data/spec/options/option_value_spec.rb +56 -1
- data/spec/options_spec.rb +283 -1
- data/spec/os/linux_spec.rb +164 -0
- data/spec/os_spec.rb +201 -14
- data/spec/package_manager_spec.rb +806 -0
- data/spec/pager_spec.rb +72 -7
- data/spec/printing/indent_spec.rb +8 -6
- data/spec/printing_spec.rb +33 -3
- data/spec/program_name_spec.rb +1 -1
- data/spec/spec_helper.rb +0 -3
- data/spec/sudo_spec.rb +51 -0
- data/spec/terminal_spec.rb +31 -1
- data/spec/usage_spec.rb +2 -2
- data/spec/xdg_spec.rb +1 -1
- metadata +21 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d04119403fa9585e0258d2b20bb7c307d124aafb70c88e03749395c7b4eedb97
|
4
|
+
data.tar.gz: 3ec992adf12bbc98313bb6ff8f3038091b50b31abbf8950765a71edd771378fb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: faeeaa08921ab315a825d4b1ff69f6b254c53b6675dd4278478b77200d6d2afb688d110757685ed33d74b90a6b1e9394c12135c3ab5f08e2ca3ca5834ead248d
|
7
|
+
data.tar.gz: 6b4ba3da0434c9fbd93d92a4c9d91e8eb53f1185df15edb21283c09b2ddf9ec4dc9fcb3708bdf83a1158cef92c988ccb5133ec5664ac9dcb213bdcde45aacf3d
|
data/.github/workflows/ruby.yml
CHANGED
@@ -3,19 +3,19 @@ name: CI
|
|
3
3
|
on: [ push, pull_request ]
|
4
4
|
|
5
5
|
jobs:
|
6
|
+
# run tests
|
6
7
|
tests:
|
7
8
|
runs-on: ubuntu-latest
|
8
9
|
strategy:
|
9
10
|
fail-fast: false
|
10
11
|
matrix:
|
11
12
|
ruby:
|
12
|
-
# - 2.4
|
13
|
-
# - 2.5
|
14
|
-
# - 2.6
|
15
13
|
- 2.7
|
16
14
|
- 3.0
|
17
15
|
# TODO: uncomment when jruby supports ruby >= 2.7
|
18
16
|
# - jruby
|
17
|
+
# TODO: uncomment when truffleruby supports splatting empty kwargs
|
18
|
+
# - truffleruby
|
19
19
|
name: Ruby ${{ matrix.ruby }}
|
20
20
|
steps:
|
21
21
|
- uses: actions/checkout@v2
|
@@ -27,3 +27,17 @@ jobs:
|
|
27
27
|
run: bundle install --jobs 4 --retry 3
|
28
28
|
- name: Run tests
|
29
29
|
run: bundle exec rake test
|
30
|
+
|
31
|
+
# rubocop linting
|
32
|
+
rubocop:
|
33
|
+
runs-on: ubuntu-latest
|
34
|
+
steps:
|
35
|
+
- uses: actions/checkout@v2
|
36
|
+
- name: Set up Ruby
|
37
|
+
uses: ruby/setup-ruby@v1
|
38
|
+
with:
|
39
|
+
ruby-version: 2.7
|
40
|
+
- name: Install dependencies
|
41
|
+
run: bundle install --jobs 4 --retry 3
|
42
|
+
- name: Run rubocop
|
43
|
+
run: bundle exec rubocop --parallel
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
AllCops:
|
2
|
+
NewCops: enable
|
3
|
+
SuggestExtensions: false
|
4
|
+
TargetRubyVersion: 2.7
|
5
|
+
|
6
|
+
#
|
7
|
+
# our rules
|
8
|
+
#
|
9
|
+
|
10
|
+
Layout/FirstArrayElementIndentation: { EnforcedStyle: consistent }
|
11
|
+
Layout/LineLength: { Enabled: false }
|
12
|
+
Layout/SpaceAroundEqualsInParameterDefault: { EnforcedStyle: no_space }
|
13
|
+
Lint/ConstantDefinitionInBlock: { Exclude: ['spec/**/*'] }
|
14
|
+
Metrics: { Enabled: false }
|
15
|
+
Style/SymbolArray: { EnforcedStyle: brackets }
|
16
|
+
Style/IfInsideElse: { Enabled: false } # Offense count: 1
|
17
|
+
Style/PercentLiteralDelimiters:
|
18
|
+
Enabled: true
|
19
|
+
PreferredDelimiters:
|
20
|
+
default: '{}'
|
21
|
+
'%i': '[]'
|
22
|
+
'%I': '[]'
|
23
|
+
'%w': '[]'
|
24
|
+
'%W': '[]'
|
25
|
+
|
26
|
+
#
|
27
|
+
# rules that are in flux
|
28
|
+
#
|
29
|
+
|
30
|
+
# consider enabling these and autocorrecting?
|
31
|
+
# Layout/SpaceAfterComma
|
32
|
+
# Layout/SpaceAroundKeyword
|
33
|
+
# Layout/SpaceBeforeComma
|
34
|
+
# Layout/SpaceInsideHashLiteralBraces
|
35
|
+
# Layout/SpaceInsideParens
|
36
|
+
# Layout/TrailingWhitespace
|
37
|
+
# Lint/UnreachableLoop
|
38
|
+
# Lint/UnusedBlockArgument
|
39
|
+
# Style/ClassCheck
|
40
|
+
# Style/Documentation
|
41
|
+
# Style/ExpandPathArguments
|
42
|
+
# Style/GlobalStdStream
|
43
|
+
# Style/HashSyntax
|
44
|
+
# Style/KeywordParametersOrder
|
45
|
+
# Style/MethodCallWithoutArgsParentheses
|
46
|
+
# Style/MutableConstant
|
47
|
+
# Style/QuotedSymbols: { EnforcedStyle: double_quotes }
|
48
|
+
# Style/RedundantReturn
|
49
|
+
# Style/SafeNavigation
|
50
|
+
# Style/SpecialGlobalVars
|
51
|
+
# Style/StringLiterals: { EnforcedStyle: double_quotes }
|
52
|
+
# Style/WordArray
|
53
|
+
|
54
|
+
# these have been fixed
|
55
|
+
# Gemspec/DuplicatedAssignment: { Enabled: false } # Offense count: 1
|
56
|
+
# Layout/ElseAlignment: { Enabled: false } # Offense count: 1
|
57
|
+
# Layout/EndAlignment: { Enabled: false } # Offense count: 1
|
58
|
+
# Lint/DuplicateMethods: { Enabled: false } # Offense count: 1
|
59
|
+
# Lint/UselessAssignment: { Enabled: false } # Offense count: 1
|
60
|
+
# Style/Encoding: { Enabled: false } # Offense count: 2
|
61
|
+
# Style/RedundantBegin: { Enabled: false } # Offense count: 2
|
62
|
+
# Style/RedundantInterpolation: { Enabled: false } # Offense count: 1
|
63
|
+
# Style/TrailingCommaInArrayLiteral: { Enabled: false } # Offense count: 1
|
64
|
+
|
65
|
+
#
|
66
|
+
# This list was generated with:
|
67
|
+
# bundle exec rubocop --auto-gen-config --exclude-limit 1
|
68
|
+
#
|
69
|
+
|
70
|
+
# > 10 violations
|
71
|
+
Layout/AssignmentIndentation: { Enabled: false } # Offense count: 11
|
72
|
+
Layout/EmptyLinesAroundClassBody: { Enabled: false } # Offense count: 76
|
73
|
+
Layout/HashAlignment: { Enabled: false } # Offense count: 28
|
74
|
+
Layout/SpaceAfterComma: { Enabled: false } # Offense count: 141
|
75
|
+
Layout/SpaceInsideHashLiteralBraces: { Enabled: false } # Offense count: 57
|
76
|
+
Layout/TrailingWhitespace: { Enabled: false } # Offense count: 50
|
77
|
+
Naming/RescuedExceptionsVariableName: { Enabled: false } # Offense count: 11
|
78
|
+
Style/BlockDelimiters: { Enabled: false } # Offense count: 17
|
79
|
+
Style/ClassCheck: { Enabled: false } # Offense count: 10
|
80
|
+
Style/ClassEqualityComparison: { Enabled: false } # Offense count: 16
|
81
|
+
Style/FrozenStringLiteralComment: { Enabled: false } # Offense count: 77
|
82
|
+
Style/GlobalStdStream: { Enabled: false } # Offense count: 13
|
83
|
+
Style/GuardClause: { Enabled: false } # Offense count: 10
|
84
|
+
Style/IfUnlessModifier: { Enabled: false } # Offense count: 13
|
85
|
+
Style/MethodCallWithoutArgsParentheses: { Enabled: false } # Offense count: 10
|
86
|
+
Style/SpecialGlobalVars: { Enabled: false } # Offense count: 28
|
87
|
+
Style/StringLiterals: { Enabled: false } # Offense count: 774
|
88
|
+
Lint/ElseLayout: { Enabled: false } # Offense count: 22
|
89
|
+
|
90
|
+
# < 10 violations
|
91
|
+
Layout/EmptyLinesAroundModuleBody: { Enabled: false } # Offense count: 5
|
92
|
+
Layout/ExtraSpacing: { Enabled: false } # Offense count: 6
|
93
|
+
Layout/FirstHashElementIndentation: { Enabled: false } # Offense count: 4
|
94
|
+
Layout/ParameterAlignment: { Enabled: false } # Offense count: 9
|
95
|
+
Layout/SpaceAroundKeyword: { Enabled: false } # Offense count: 7
|
96
|
+
Layout/SpaceBeforeComma: { Enabled: false } # Offense count: 4
|
97
|
+
Layout/SpaceInsideParens: { Enabled: false } # Offense count: 4
|
98
|
+
Lint/EmptyClass: { Enabled: false } # Offense count: 3
|
99
|
+
Lint/SuppressedException: { Enabled: false } # Offense count: 4
|
100
|
+
Lint/UnusedMethodArgument: { Enabled: false } # Offense count: 5
|
101
|
+
Style/AccessorGrouping: { Enabled: false } # Offense count: 7
|
102
|
+
Style/Documentation: { Enabled: false } # Offense count: 3
|
103
|
+
Style/ExpandPathArguments: { Enabled: false } # Offense count: 8
|
104
|
+
Style/HashSyntax: { Exclude: ['Rakefile'] } # Offense count: 3
|
105
|
+
Style/KeywordParametersOrder: { Enabled: false } # Offense count: 8
|
106
|
+
Style/Lambda: { Enabled: false } # Offense count: 3
|
107
|
+
Style/MutableConstant: { Enabled: false } # Offense count: 4
|
108
|
+
Style/RaiseArgs: { Enabled: false } # Offense count: 4
|
109
|
+
Style/RedundantReturn: { Enabled: false } # Offense count: 7
|
110
|
+
Style/SafeNavigation: { Enabled: false } # Offense count: 5
|
111
|
+
Style/StringConcatenation: { Enabled: false } # Offense count: 8
|
112
|
+
Style/WordArray: { Enabled: false } # Offense count: 4
|
113
|
+
|
114
|
+
# 1 or 2 violations
|
115
|
+
Layout/ArgumentAlignment: { Enabled: false } # Offense count: 1
|
116
|
+
Layout/BlockAlignment: { Enabled: false } # Offense count: 1
|
117
|
+
Layout/IndentationWidth: { Enabled: false } # Offense count: 2
|
118
|
+
Layout/SpaceAroundOperators: { Enabled: false } # Offense count: 1
|
119
|
+
Layout/SpaceBeforeBlockBraces: { Enabled: false } # Offense count: 1
|
120
|
+
Lint/MissingSuper: { Enabled: false } # Offense count: 2
|
121
|
+
Lint/RescueException: { Enabled: false } # Offense count: 1
|
122
|
+
Lint/UnreachableLoop: { Enabled: false } # Offense count: 1
|
123
|
+
Lint/UnusedBlockArgument: { Enabled: false } # Offense count: 1
|
124
|
+
Naming/MethodParameterName: { Enabled: false } # Offense count: 1
|
125
|
+
Style/EmptyMethod: { Enabled: false } # Offense count: 2
|
126
|
+
Style/HashConversion: { Enabled: false } # Offense count: 1
|
127
|
+
Style/MultilineMemoization: { Enabled: false } # Offense count: 1
|
128
|
+
Style/NumericPredicate: { Enabled: false } # Offense count: 1
|
129
|
+
Style/OptionalArguments: { Enabled: false } # Offense count: 1
|
130
|
+
Style/ParenthesesAroundCondition: { Enabled: false } # Offense count: 1
|
131
|
+
Style/PreferredHashMethods: { Enabled: false } # Offense count: 1
|
132
|
+
Style/QuotedSymbols: { Enabled: false } # Offense count: 1
|
133
|
+
Style/RedundantException: { Enabled: false } # Offense count: 1
|
134
|
+
Style/RedundantRegexpEscape: { Enabled: false } # Offense count: 1
|
135
|
+
Style/RegexpLiteral: { Enabled: false } # Offense count: 1
|
136
|
+
Style/RescueStandardError: { Enabled: false } # Offense count: 1
|
137
|
+
Style/SoleNestedConditional: { Enabled: false } # Offense count: 1
|
138
|
+
Style/TrailingCommaInHashLiteral: { Enabled: false } # Offense count: 2
|
139
|
+
|
140
|
+
# rubocop cannot tell that rubygems_mfa_required is enabled in gemspec.yml
|
141
|
+
Gemspec/RequireMFA: { Enabled: false }
|
data/ChangeLog.md
CHANGED
@@ -1,4 +1,104 @@
|
|
1
|
-
### 0.
|
1
|
+
### 0.2.2 / 2021-12-26
|
2
|
+
|
3
|
+
#### CommandKit::Help::Man
|
4
|
+
|
5
|
+
* Raise a `NotImplementedError` exception in {CommandKit::Help::Man#help_man
|
6
|
+
#help_man} if {CommandKit::Help::Man::ClassMethods#man_dir .man_dir} was not
|
7
|
+
set.
|
8
|
+
|
9
|
+
### 0.2.1 / 2021-11-16
|
10
|
+
|
11
|
+
* Ensure that all error messages end with a period.
|
12
|
+
* Documentation fixes.
|
13
|
+
* Opt-in to [rubygem.org MFA requirement](https://guides.rubygems.org/mfa-requirement-opt-in/).
|
14
|
+
|
15
|
+
#### CommandKit::Printing
|
16
|
+
|
17
|
+
* Auto-detect whether {CommandKit::CommandName#command_name #command_name} is
|
18
|
+
available, and if so, prepend the command name to all error messages.
|
19
|
+
|
20
|
+
#### CommandKit::Help::Man
|
21
|
+
|
22
|
+
* Expand the path given to
|
23
|
+
{CommandKit::Help::Man::ClassMethods#man_dir man_dir}.
|
24
|
+
* If {CommandKit::Help::Man::ClassMethods#man_dir man_dir} is not set, fallback
|
25
|
+
to regular `--help` output.
|
26
|
+
|
27
|
+
#### CommandKit::Arguments
|
28
|
+
|
29
|
+
* Include {CommandKit::Usage} and {CommandKit::Printing} into
|
30
|
+
{CommandKit::Arguments}.
|
31
|
+
|
32
|
+
#### CommandKit::Options
|
33
|
+
|
34
|
+
* Include {CommandKit::Arguments} into {CommandKit::Options}.
|
35
|
+
* Ensure that {CommandKit::Options::Parser#main} runs before
|
36
|
+
{CommandKit::Arguments#main}.
|
37
|
+
* Ensure that {CommandKit::Options#help} also calls
|
38
|
+
{CommandKit::Arguments#help_arguments}.
|
39
|
+
* Always prepopulate {CommandKit::Options#options #options} with option's
|
40
|
+
default values.
|
41
|
+
* Note: if an option has a default value but the option's value is not
|
42
|
+
required (ex: `value: {required: false, default: "foo"}`), and the option's
|
43
|
+
flag is given but no value is given (ex: `--option-flag --some-other-flag`),
|
44
|
+
the option's value in {CommandKit::Options#options #options} will be `nil`
|
45
|
+
_not_ the option's default value (`"foo"`). This helps indicate that the
|
46
|
+
option's flag was given but no value was given with it.
|
47
|
+
|
48
|
+
#### CommandKit::Options::OptionValue
|
49
|
+
|
50
|
+
* When a `Class` is passed to {CommandKit::Options::OptionValue.default_usage},
|
51
|
+
demodularize the class name before converting it to underscored/uppercase.
|
52
|
+
|
53
|
+
#### CommandKit::Command
|
54
|
+
|
55
|
+
* Fixed the inclusion order of {CommandKit::Options} and
|
56
|
+
{CommandKit::Arguments}.
|
57
|
+
|
58
|
+
#### CommandKit::Commands
|
59
|
+
|
60
|
+
* Define the `COMMAND` and `ARGS` arguments.
|
61
|
+
* Correctly duplicate the {CommandKit::Env#env env} (which can be either `ENV`
|
62
|
+
or a `Hash`) to work on ruby-3.1.0-preview1.
|
63
|
+
* Print command aliases that were set explicitly
|
64
|
+
(ex: `command_aliases['rm'] = 'remove'`) in {CommandKit::Commands#help}.
|
65
|
+
* Print help and exit with status `1` if no command is given. This matches the
|
66
|
+
behavior of the `git` command.
|
67
|
+
|
68
|
+
#### CommandKit::Commands::AutoLoad
|
69
|
+
|
70
|
+
* Ensure that any explicit command aliases are added to the command's
|
71
|
+
{CommandKit::Commands::ClassMethods#command_aliases command_aliases}.
|
72
|
+
|
73
|
+
### 0.2.0 / 2021-08-31
|
74
|
+
|
75
|
+
* Added {CommandKit::Colors::ANSI#on_black}.
|
76
|
+
* Added {CommandKit::Colors::ANSI#on_red}.
|
77
|
+
* Added {CommandKit::Colors::ANSI#on_green}.
|
78
|
+
* Added {CommandKit::Colors::ANSI#on_yellow}.
|
79
|
+
* Added {CommandKit::Colors::ANSI#on_blue}.
|
80
|
+
* Added {CommandKit::Colors::ANSI#on_magenta}.
|
81
|
+
* Added {CommandKit::Colors::ANSI#on_cyan}.
|
82
|
+
* Added {CommandKit::Colors::ANSI#on_white}.
|
83
|
+
* Added {CommandKit::Man}.
|
84
|
+
* Added {CommandKit::OS#bsd?}.
|
85
|
+
* Added {CommandKit::OS#freebsd?}.
|
86
|
+
* Added {CommandKit::OS#netbsd?}.
|
87
|
+
* Added {CommandKit::OS#openbsd?}.
|
88
|
+
* Added {CommandKit::OS#os}.
|
89
|
+
* Added {CommandKit::OS#unix?}.
|
90
|
+
* Added {CommandKit::OS::Linux}.
|
91
|
+
* Added {CommandKit::OpenApp}.
|
92
|
+
* Added {CommandKit::PackageManager}.
|
93
|
+
* Added {CommandKit::Pager#pipe_to_pager}.
|
94
|
+
* Added {CommandKit::Sudo}.
|
95
|
+
* Added {CommandKit::Terminal#tty?}.
|
96
|
+
* Refactor {CommandKit::Inflector.camelize} and
|
97
|
+
{CommandKit::Inflector.underscore} to use StringScanner.
|
98
|
+
* Allow {CommandKit::OS#initialize} to accept an `os:` keyword to override the
|
99
|
+
detected OS.
|
100
|
+
|
101
|
+
### 0.1.0 / 2021-07-16
|
2
102
|
|
3
103
|
* Initial release:
|
4
104
|
* {CommandKit::Arguments}
|
@@ -21,6 +121,7 @@
|
|
21
121
|
* {CommandKit::Options}
|
22
122
|
* {CommandKit::Options::Quiet}
|
23
123
|
* {CommandKit::Options::Verbose}
|
124
|
+
* {CommandKit::OS}
|
24
125
|
* {CommandKit::Pager}
|
25
126
|
* {CommandKit::Printing}
|
26
127
|
* {CommandKit::Printing::Indent}
|
data/Gemfile
CHANGED
@@ -6,9 +6,12 @@ group :development do
|
|
6
6
|
gem 'rake'
|
7
7
|
gem 'rubygems-tasks', '~> 0.2'
|
8
8
|
|
9
|
+
gem 'rubocop', '~> 1.18'
|
10
|
+
|
9
11
|
gem 'rspec', '~> 3.0'
|
10
12
|
gem 'simplecov', '~> 0.20', require: false
|
11
13
|
|
12
14
|
gem 'kramdown'
|
13
15
|
gem 'yard', '~> 0.9'
|
16
|
+
gem 'yard-spellcheck', require: false
|
14
17
|
end
|
data/README.md
CHANGED
@@ -1,9 +1,13 @@
|
|
1
1
|
# command_kit
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
[](https://github.com/postmodern/command_kit.rb/actions)
|
4
|
+
[](https://codeclimate.com/github/postmodern/command_kit.rb)
|
5
|
+
[](https://badge.fury.io/rb/command_kit)
|
6
|
+
|
7
|
+
* [Homepage](https://github.com/postmodern/command_kit.rb#readme)
|
8
|
+
* [Forum](https://github.com/postmodern/command_kit.rb/discussions) |
|
9
|
+
[Issues](https://github.com/postmodern/command_kit.rb/issues)
|
5
10
|
* [Documentation](http://rubydoc.info/gems/command_kit/frames)
|
6
|
-
* [Email](mailto:postmodern.mod3 at gmail.com)
|
7
11
|
|
8
12
|
## Description
|
9
13
|
|
@@ -12,50 +16,26 @@ plain-old Ruby classes.
|
|
12
16
|
|
13
17
|
## Features
|
14
18
|
|
15
|
-
*
|
16
|
-
|
17
|
-
|
18
|
-
*
|
19
|
-
*
|
20
|
-
*
|
21
|
-
*
|
22
|
-
* Uses [OptionParser][optparse] for POSIX option parsing.
|
23
|
-
*
|
24
|
-
*
|
25
|
-
|
26
|
-
*
|
27
|
-
*
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
*
|
32
|
-
* [
|
33
|
-
*
|
34
|
-
|
35
|
-
* [CommandKit::Commands](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Commands)
|
36
|
-
* [CommandKit::Commands::AutoLoad](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Commands/AutoLoad)
|
37
|
-
* [CommandKit::Commands::AutoRequire](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Commands/AutoRequire)
|
38
|
-
* [CommandKit::Description](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Description)
|
39
|
-
* [CommandKit::Env](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Env)
|
40
|
-
* [CommandKit::Env::Home](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Env/Home)
|
41
|
-
* [CommandKit::Env::Path](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Env/Path)
|
42
|
-
* [CommandKit::Examples](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Examples)
|
43
|
-
* [CommandKit::ExceptionHandler](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/ExceptionHandler)
|
44
|
-
* [CommandKit::Help](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Help)
|
45
|
-
* [CommandKit::Help::Man](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Help/Man)
|
46
|
-
* [CommandKit::Interactive](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Interactive)
|
47
|
-
* [CommandKit::Main](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Main)
|
48
|
-
* [CommandKit::Options](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Options)
|
49
|
-
* [CommandKit::Options::Quiet](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Options/Quiet)
|
50
|
-
* [CommandKit::Options::Verbose](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Options/Verbose)
|
51
|
-
* [CommandKit::Pager](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Pager)
|
52
|
-
* [CommandKit::Printing](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Printing)
|
53
|
-
* [CommandKit::Printing::Indent](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Printing/Indent)
|
54
|
-
* [CommandKit::ProgramName](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/ProgramName)
|
55
|
-
* [CommandKit::Stdio](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Stdio)
|
56
|
-
* [CommandKit::Terminal](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Terminal)
|
57
|
-
* [CommandKit::Usage](https://rubydoc.info/github/postmodern/command_kit/main/CommandKit/Usage)
|
58
|
-
* [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`.
|
59
39
|
|
60
40
|
## Anti-Features
|
61
41
|
|
@@ -63,103 +43,194 @@ plain-old Ruby classes.
|
|
63
43
|
* Does not implement it's own option parser.
|
64
44
|
* Not named after a comic-book Superhero.
|
65
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
|
+
|
66
68
|
## Examples
|
67
69
|
|
68
70
|
### lib/foo/cli/my_cmd.rb
|
69
71
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
argument :file, required: true,
|
97
|
-
usage: 'FILE',
|
98
|
-
desc: "Input file"
|
99
|
-
|
100
|
-
examples [
|
101
|
-
'-o path/to/output.txt path/to/input.txt',
|
102
|
-
'-v -c 2 -o path/to/output.txt path/to/input.txt',
|
103
|
-
]
|
104
|
-
|
105
|
-
description 'Example command'
|
106
|
-
|
107
|
-
def initialize(**kwargs)
|
108
|
-
super(**kwargs)
|
109
|
-
|
110
|
-
@verbose = 0
|
111
|
-
end
|
112
|
-
|
113
|
-
def run(file)
|
114
|
-
puts "count=#{options[:count].inspect}"
|
115
|
-
puts "output=#{options[:output].inspect}"
|
116
|
-
puts "file=#{file.inspect}"
|
117
|
-
puts "verbose=#{@verbose.inspect}"
|
118
|
-
end
|
119
|
-
|
120
|
-
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
|
121
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
|
+
|
122
123
|
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
```
|
123
127
|
|
124
128
|
### bin/my_cmd
|
125
129
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
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
|
+
```
|
132
138
|
|
133
139
|
### --help
|
134
140
|
|
135
141
|
Usage: my_cmd [OPTIONS] [-o OUTPUT] FILE
|
136
|
-
|
142
|
+
|
137
143
|
Options:
|
138
144
|
-c, --count INT Number of times (Default: 1)
|
139
145
|
-o, --output FILE Optional output file
|
140
146
|
-v, --verbose Increase verbose level
|
141
147
|
-h, --help Print help information
|
142
|
-
|
148
|
+
|
143
149
|
Arguments:
|
144
150
|
FILE Input file
|
145
|
-
|
151
|
+
|
146
152
|
Examples:
|
147
153
|
my_cmd -o path/to/output.txt path/to/input.txt
|
148
154
|
my_cmd -v -c 2 -o path/to/output.txt path/to/input.txt
|
149
|
-
|
150
|
-
Example command
|
151
155
|
|
152
|
-
|
153
|
-
|
154
|
-
* [ruby] >= 2.7.0
|
156
|
+
Example command
|
155
157
|
|
156
|
-
##
|
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
|
157
189
|
|
158
|
-
|
190
|
+
context "when executed with -o OUTPUT" do
|
191
|
+
let(:file) { ... }
|
192
|
+
let(:output) { ... }
|
159
193
|
|
160
|
-
|
194
|
+
before { subject.main(["-o", output, file]) }
|
161
195
|
|
162
|
-
|
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)
|
163
234
|
|
164
235
|
## Alternatives
|
165
236
|
|