cmd.rb 0.3.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 1e81a52d995f13903b644a2dcc326b35b57d37bc9b0e1840509835791a7c3100
4
+ data.tar.gz: fb89b7ca7ba61d017141bebaeaa129589b812c7a7a742e5e0619cda3e4374b86
5
+ SHA512:
6
+ metadata.gz: 9131c3ffccbba0aef5cdcf3f19e7288ce8228b5095a9cac7e021c08202a09b4094a584e520a846c4be13e63f846f06a8b0583daf63dc3c01a8b7ef26185c2f0c
7
+ data.tar.gz: 3eaed61342560a42a56952e74f1723c9f35a08ae22b13c7bb403bb5dd3a8d3ca85cc046a7bda3dab6246a94d36fce301188c011e3f7789a89057e911d138ece8
@@ -0,0 +1,23 @@
1
+ name: cmd.rb
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ pull_request:
7
+ branches: [ main ]
8
+
9
+ jobs:
10
+ tests:
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ os: [ubuntu-latest]
15
+ ruby: [3.1, 3.2]
16
+ runs-on: ${{ matrix.os }}
17
+ steps:
18
+ - uses: actions/checkout@v2
19
+ - uses: ruby/setup-ruby@v1
20
+ with:
21
+ ruby-version: ${{ matrix.ruby }}
22
+ - run: bundle install
23
+ - run: bundle exec rake
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ *.lock
2
+ .yardoc/
3
+ doc/
4
+ .bundle/
5
+ .localgems/
6
+ .gems/
data/.projectile ADDED
@@ -0,0 +1,2 @@
1
+ -.localgems/
2
+ -doc/
data/.rubocop.yml ADDED
@@ -0,0 +1,36 @@
1
+ ##
2
+ # Plugins
3
+ require:
4
+ - standard
5
+
6
+ ##
7
+ # Defaults: standard-rb
8
+ inherit_gem:
9
+ standard: config/base.yml
10
+
11
+ ##
12
+ # All cops
13
+ AllCops:
14
+ TargetRubyVersion: 3.2
15
+ Include:
16
+ - lib/*.rb
17
+ - lib/**/*.rb
18
+ - test/*.rb
19
+
20
+ ##
21
+ # Enabled
22
+ Style/FrozenStringLiteralComment:
23
+ Enabled: true
24
+
25
+ ##
26
+ # Disabled
27
+ Layout/ArgumentAlignment:
28
+ Enabled: false
29
+ Layout/MultilineMethodCallIndentation:
30
+ Enabled: false
31
+ Layout/EmptyLineBetweenDefs:
32
+ Enabled: false
33
+ Style/TrivialAccessors:
34
+ Enabled: false
35
+ Style/CommandLiteral:
36
+ Enabled: false
@@ -0,0 +1,15 @@
1
+ #main #content #filecontents p, .discussion p {
2
+ max-width: 768px;
3
+ }
4
+
5
+ #toc {
6
+ position: fixed;
7
+ right: 25px;
8
+ display: none;
9
+ }
10
+
11
+ @media screen and (min-width: 1280px) {
12
+ #toc {
13
+ display: block;
14
+ }
15
+ }
@@ -0,0 +1,5 @@
1
+ def stylesheets
2
+ s = super
3
+ s << "css/0x1eef.css"
4
+ s
5
+ end
@@ -0,0 +1,7 @@
1
+ ##
2
+ # Sort methods in ascending order based
3
+ # on the line number where a method is
4
+ # defined.
5
+ def sort_listing(listing)
6
+ listing.sort_by { _1.files[1] }
7
+ end
data/.yardopts ADDED
@@ -0,0 +1,4 @@
1
+ -m markdown -M redcarpet --no-private -t default -p .yardoc-template --hide-void-return
2
+ -
3
+ README.md
4
+ LICENSE
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+ gemspec
3
+ gem "optparse", github: "ruby/optparse"
4
+ gem "ryo.rb", "~> 0.4", github: "0x1eef/ryo.rb", tag: "v0.4.2"
5
+ gem "test-cmd.rb", "~> 0.2", github: "0x1eef/test-cmd.rb"
6
+ gem "webrick"
data/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ Copyright (C) 2023 by 0x1eef <0x1eef@protonmail.com>
2
+
3
+ Permission to use, copy, modify, and/or distribute this
4
+ software for any purpose with or without fee is hereby
5
+ granted.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS
8
+ ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
9
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
10
+ EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
12
+ RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
14
+ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
15
+ OF THIS SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,90 @@
1
+ ## About
2
+
3
+ cmd.rb is a library for building command-line applications
4
+ in Ruby. The interface is centered around a class that implements
5
+ a command (or it could be a sub-command) that defines a banner,
6
+ a set of options, and a set of defaults for those options. The
7
+ option parsing implementation is delegated to
8
+ [ruby/optparse](https://github.com/ruby/optparse)
9
+ (with a few minor enhancements).
10
+
11
+ ## Example
12
+
13
+ The following example demonstrates a simple command that is
14
+ implemented with `Dir.entries`. The command accepts two options
15
+ that have fallback default values set:
16
+
17
+ **Definition**
18
+
19
+ ```ruby
20
+ #!/usr/bin/env ruby
21
+
22
+ require "cmd"
23
+ class Ls < Cmd
24
+ set_banner usage: "ls [OPTIONS]",
25
+ description: "Lists the contents of a directory"
26
+ set_option "-g PATTERN", "--grep PATTERN", "A regular expression", as: Regexp, default: /.+/
27
+ set_option "-d PATH", "--directory PATH", "A path to a directory", as: String, default: Dir.home
28
+
29
+ def run
30
+ options = parse_options(argv)
31
+ options.help ? show_help : run_command(options)
32
+ end
33
+
34
+ private
35
+
36
+ def run_command(options)
37
+ puts Dir.entries(options.directory)
38
+ .grep(options.grep)
39
+ .sort
40
+ .join("\n")
41
+ end
42
+ end
43
+
44
+ ##
45
+ # Run the command
46
+ Ls.new(ARGV).run
47
+ ```
48
+
49
+ **Command help (-h)**
50
+
51
+ ```
52
+ $ chmod u+x ls
53
+ $ ./ls --help
54
+ Usage: ls [OPTIONS]
55
+
56
+ Description:
57
+ Lists the contents of a directory
58
+
59
+ Options:
60
+ -g, --grep PATTERN A regular expression
61
+ -p, --path PATH A path to a directory
62
+ -h, --help Show help
63
+
64
+ ```
65
+
66
+ ## Sources
67
+
68
+ * [Source code (GitHub)](https://github.com/0x1eef/cmd.rb#readme)
69
+ * [Source code (GitLab)](https://gitlab.com/0x1eef/cmd.rb#about)
70
+
71
+ ## Install
72
+
73
+ cmd.rb is distributed as a RubyGem through its git repositories. <br>
74
+ [GitHub](https://github.com/0x1eef/cmd.rb),
75
+ and
76
+ [GitLab](https://gitlab.com/0x1eef/cmd.rb)
77
+ are available as sources.
78
+
79
+ **Gemfile**
80
+
81
+ ```ruby
82
+ gem "cmd.rb", github: "0x1eef/cmd.rb"
83
+ gem "ryo.rb", github: "0x1eef/ryo.rb"
84
+ ```
85
+
86
+ ## <a id="license"> License </a>
87
+
88
+ [BSD Zero Clause](https://choosealicense.com/licenses/0bsd/).
89
+ <br>
90
+ See [LICENSE](./LICENSE).
data/Rakefile.rb ADDED
@@ -0,0 +1,8 @@
1
+ require "rake/testtask"
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.test_files = FileList['test/*_test.rb']
5
+ t.verbose = true
6
+ t.warning = false
7
+ end
8
+ task default: :test
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ v0.3.2
data/cmd.rb.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ version = File.binread File.join(__dir__, "VERSION")
4
+ Gem::Specification.new do |gem|
5
+ gem.name = "cmd.rb"
6
+ gem.authors = ["0x1eef"]
7
+ gem.email = ["0x1eef@protonmail.com"]
8
+ gem.homepage = "https://github.com/0x1eef/cmd.rb#readme"
9
+ gem.version = version[/[\d.]+/]
10
+ gem.licenses = ["0BSD"]
11
+ gem.files = `git ls-files`.split($/)
12
+ gem.require_paths = ["lib"]
13
+ gem.summary = "A library for building command-line applications"
14
+ gem.description = gem.summary
15
+ gem.add_runtime_dependency "ryo.rb", "~> 0.4"
16
+ gem.add_runtime_dependency "optparse", "~> 0.3"
17
+ gem.add_development_dependency "test-unit", "~> 3.5.7"
18
+ gem.add_development_dependency "yard", "~> 0.9"
19
+ gem.add_development_dependency "redcarpet", "~> 3.5"
20
+ gem.add_development_dependency "standard", "~> 1.13"
21
+ gem.add_development_dependency "test-cmd.rb", "~> 0.2"
22
+ gem.add_development_dependency "rake", "~> 13.1"
23
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # The {Cmd::ARGV} module provides an initialize method, and an
5
+ # attribute reader for an array of strings (usually ARGV). Classes
6
+ # who include the {Cmd Cmd} module indirectly include this module as
7
+ # well.
8
+ module Cmd::ARGV
9
+ ##
10
+ # @return [Array<String>]
11
+ # Returns an array of strings.
12
+ attr_reader :argv
13
+
14
+ ##
15
+ # @param [Array<String>] argv
16
+ # An array of strings.
17
+ def initialize(argv)
18
+ @argv = argv.dup
19
+ end
20
+ end
@@ -0,0 +1,9 @@
1
+
2
+ module Cmd::Help
3
+ def show_help(io = $stdout)
4
+ banner = self.class.banner
5
+ io.puts "Usage: #{banner.usage}\n\n" \
6
+ "Description:\n #{banner.description}\n\n" \
7
+ "Options: #{option_parser.help}\n"
8
+ end
9
+ end
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "optparse"
4
+ require "ryo"
5
+
6
+ ##
7
+ # The {Cmd::OptionParser Cmd::OptionParser} module provides a light wrapper
8
+ # around Ruby's
9
+ # [OptionParser](https://docs.ruby-lang.org/en/3.2/OptionParser.html)
10
+ # class.
11
+ module Cmd::OptionParser
12
+ def self.included(klass)
13
+ klass.extend(ClassMethods)
14
+ end
15
+
16
+ module ClassMethods
17
+ ##
18
+ # Set command banner.
19
+ #
20
+ # @param [String] usage
21
+ # An example of how a command is used.
22
+ #
23
+ # @param [String] description
24
+ # The description of a command.
25
+ #
26
+ # @return [void]
27
+ def set_banner(usage:, description:)
28
+ banner.usage = usage
29
+ banner.description = description
30
+ end
31
+
32
+ ##
33
+ # Set a command option.
34
+ #
35
+ # @param [String] short
36
+ # Short option switch.
37
+ #
38
+ # @param [String] long
39
+ # Long option switch.
40
+ #
41
+ # @param [String] desc
42
+ # The description of an option.
43
+ #
44
+ # @param [Class] as
45
+ # The type (String, Integer, etc) of the option's value.
46
+ #
47
+ # @param [Object] default
48
+ # The default value for an option.
49
+ #
50
+ # @return [void]
51
+ def set_option(short, long, desc, as: String, default: nil)
52
+ option_parser.on(short, long, desc, as)
53
+ set_default({ short => default, long => default })
54
+ end
55
+
56
+ ##
57
+ # Set command option defaults.
58
+ #
59
+ # @param [{String => Object}] defaults
60
+ #
61
+ # @return [void]
62
+ def set_default(defaults)
63
+ @defaults = Ryo.from(defaults)
64
+ end
65
+
66
+ ##
67
+ # (see Cmd::OptionParser#option_parser)
68
+ def option_parser
69
+ @option_parser ||= ::OptionParser.new(nil, 26, " " * 2).tap do
70
+ _1.banner = ""
71
+ _1.on("-h", "--help", "Show help")
72
+ end
73
+ end
74
+
75
+ ##
76
+ # @private
77
+ def banner
78
+ @banner ||= Ryo({})
79
+ end
80
+
81
+ ##
82
+ # @private
83
+ def defaults
84
+ @defaults ||= Ryo({})
85
+ end
86
+ end
87
+
88
+ ##
89
+ # Parses an array of strings with
90
+ # [OptionParser#parse](https://docs.ruby-lang.org/en/3.2/OptionParser.html#method-i-parse).
91
+ #
92
+ # @param [Array<String>] argv
93
+ # An array of strings
94
+ #
95
+ # @return [Ryo::Object]
96
+ # Returns the parsed options as a Ryo object
97
+ def parse_options(argv)
98
+ options = Ryo.from(self.class.defaults)
99
+ option_parser.parse(argv, into: options)
100
+ options
101
+ end
102
+
103
+ ##
104
+ # Parses an array of strings with
105
+ # [OptionParser#parse!](https://docs.ruby-lang.org/en/3.2/OptionParser.html#method-i-parse-21).
106
+ #
107
+ # @param [Array<String>] argv
108
+ # An array of strings
109
+ #
110
+ # @return [Ryo::Object]
111
+ # Returns the parsed options as a Ryo object
112
+ def parse_options!(argv)
113
+ options = Ryo.from(self.class.defaults)
114
+ option_parser.parse!(argv, into: options)
115
+ options
116
+ end
117
+
118
+ ##
119
+ # @return [OptionParser]
120
+ # Returns an instance of
121
+ # [OptionParser](https://docs.ruby-lang.org/en/3.2/OptionParser.html)
122
+ def option_parser
123
+ self.class.option_parser
124
+ end
125
+ end
data/lib/cmd.rb ADDED
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Cmd
4
+ require_relative "cmd/mixins/argv"
5
+ require_relative "cmd/mixins/help"
6
+ require_relative "cmd/mixins/option_parser"
7
+
8
+ include ARGV
9
+ include Help
10
+
11
+ def self.inherited(klass)
12
+ klass.class_eval { include(OptionParser) }
13
+ end
14
+ end
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+ require_relative "setup"
4
+
5
+ require "cmd"
6
+ class Ls < Cmd
7
+ set_banner usage: "ls [OPTIONS]",
8
+ description: "Lists the contents of a directory"
9
+ set_option "-g PATTERN", "--grep PATTERN", "A regular expression", as: Regexp, default: /.+/
10
+ set_option "-d PATH", "--directory PATH", "A path to a directory", as: String, default: Dir.home
11
+
12
+ def run
13
+ options = parse_options(argv)
14
+ options.help ? show_help : run_command(options)
15
+ end
16
+
17
+ private
18
+
19
+ def run_command(options)
20
+ puts Dir.entries(options.directory)
21
+ .grep(options.grep)
22
+ .sort
23
+ .join("\n")
24
+ end
25
+ end
26
+
27
+ ##
28
+ # Run the command
29
+ Ls.new(ARGV).run
@@ -0,0 +1 @@
1
+ require "bundler/setup"
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "setup"
4
+
5
+ class READMETest < Test::Unit::TestCase
6
+ include Test::Cmd
7
+
8
+ def test_ls_command
9
+ assert_equal "dev\netc\nhome\n",
10
+ run_example("ls --directory test/fakefs/ --grep [^.gitkeep]").stdout
11
+ end
12
+
13
+ def test_ls_command_help
14
+ help = "Usage: ls [OPTIONS]\n\n" \
15
+ "Description:\n" \
16
+ " Lists the contents of a directory\n\n" \
17
+ "Options: \n" \
18
+ " -h, --help Show help\n" \
19
+ " -g, --grep PATTERN A regular expression\n" \
20
+ " -d, --directory PATH A path to a directory\n\n"
21
+ assert_equal help, run_example("ls --help").stdout
22
+ end
23
+
24
+ private
25
+
26
+ def run_example(command)
27
+ cmd File.join(__dir__, "..", "share", "examples", "cmd.rb", command)
28
+ end
29
+ end
data/test/setup.rb ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/setup"
4
+ require "test-unit"
5
+ require "test-cmd"
metadata ADDED
@@ -0,0 +1,181 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cmd.rb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.2
5
+ platform: ruby
6
+ authors:
7
+ - '0x1eef'
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-12-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ryo.rb
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.4'
27
+ - !ruby/object:Gem::Dependency
28
+ name: optparse
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.3'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: test-unit
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 3.5.7
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 3.5.7
55
+ - !ruby/object:Gem::Dependency
56
+ name: yard
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.9'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.9'
69
+ - !ruby/object:Gem::Dependency
70
+ name: redcarpet
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.5'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.5'
83
+ - !ruby/object:Gem::Dependency
84
+ name: standard
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.13'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.13'
97
+ - !ruby/object:Gem::Dependency
98
+ name: test-cmd.rb
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.2'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.2'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rake
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '13.1'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '13.1'
125
+ description: A library for building command-line applications
126
+ email:
127
+ - 0x1eef@protonmail.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - ".github/workflows/tests.yml"
133
+ - ".gitignore"
134
+ - ".projectile"
135
+ - ".rubocop.yml"
136
+ - ".yardoc-template/default/fulldoc/html/css/0x1eef.css"
137
+ - ".yardoc-template/default/layout/html/setup.rb"
138
+ - ".yardoc-template/default/module/setup.rb"
139
+ - ".yardopts"
140
+ - Gemfile
141
+ - LICENSE
142
+ - README.md
143
+ - Rakefile.rb
144
+ - VERSION
145
+ - cmd.rb.gemspec
146
+ - lib/cmd.rb
147
+ - lib/cmd/mixins/argv.rb
148
+ - lib/cmd/mixins/help.rb
149
+ - lib/cmd/mixins/option_parser.rb
150
+ - share/examples/cmd.rb/ls
151
+ - share/examples/cmd.rb/setup.rb
152
+ - test/fakefs/.gitkeep
153
+ - test/fakefs/dev/.gitkeep
154
+ - test/fakefs/etc/.gitkeep
155
+ - test/fakefs/home/.gitkeep
156
+ - test/readme_examples_test.rb
157
+ - test/setup.rb
158
+ homepage: https://github.com/0x1eef/cmd.rb#readme
159
+ licenses:
160
+ - 0BSD
161
+ metadata: {}
162
+ post_install_message:
163
+ rdoc_options: []
164
+ require_paths:
165
+ - lib
166
+ required_ruby_version: !ruby/object:Gem::Requirement
167
+ requirements:
168
+ - - ">="
169
+ - !ruby/object:Gem::Version
170
+ version: '0'
171
+ required_rubygems_version: !ruby/object:Gem::Requirement
172
+ requirements:
173
+ - - ">="
174
+ - !ruby/object:Gem::Version
175
+ version: '0'
176
+ requirements: []
177
+ rubygems_version: 3.4.10
178
+ signing_key:
179
+ specification_version: 4
180
+ summary: A library for building command-line applications
181
+ test_files: []