Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/postmodern/command_kit.rb
A Ruby toolkit for building complete and robust CLI commands.
https://github.com/postmodern/command_kit.rb
Last synced: about 1 month ago
JSON representation
A Ruby toolkit for building complete and robust CLI commands.
- Host: GitHub
- URL: https://github.com/postmodern/command_kit.rb
- Owner: postmodern
- License: mit
- Created: 2021-01-27T03:42:37.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2024-06-27T04:46:33.000Z (3 months ago)
- Last Synced: 2024-07-27T11:01:32.708Z (about 2 months ago)
- Language: Ruby
- Size: 542 KB
- Stars: 158
- Watchers: 3
- Forks: 2
- Open Issues: 18
-
Metadata Files:
- Readme: README.md
- Changelog: ChangeLog.md
- License: LICENSE.txt
Awesome Lists containing this project
README
# command_kit
[![Build Status](https://github.com/postmodern/command_kit.rb/workflows/CI/badge.svg?branch=main)](https://github.com/postmodern/command_kit.rb/actions)
[![Code Climate](https://codeclimate.com/github/postmodern/command_kit.rb.svg)](https://codeclimate.com/github/postmodern/command_kit.rb)
[![Gem Version](https://badge.fury.io/rb/command_kit.svg)](https://badge.fury.io/rb/command_kit)* [Homepage](https://github.com/postmodern/command_kit.rb#readme)
* [Forum](https://github.com/postmodern/command_kit.rb/discussions) |
[Issues](https://github.com/postmodern/command_kit.rb/issues)
* [Documentation](http://rubydoc.info/gems/command_kit/frames)## Description
A modular Ruby toolkit for building clean, correct, and robust CLI commands as
plain-old Ruby classes.## Features
* **Simple** - Commands are plain-old ruby classes, with options and
arguments declared as attributes. All features are Ruby modules that can be
included into command classes.
* **Correct** - CommandKit behaves like a standard UNIX command.
* Safely handles Ctrl^C / SIGINT interrupts and [exits with 130](https://tldp.org/LDP/abs/html/exitcodes.html).
* Safely handles broken pipes (aka `mycmd | head`).
* Respects common environment variables (ex: `TERM=dumb` and `NO_COLOR`).
* Uses [OptionParser][optparse] for POSIX option parsing.
* Disables ANSI color when output is redirected to a file or when `NO_COLOR`
is set.
* **Complete** - Provides many additional CLI features.
* OS detection.
* Terminal size detection.
* ANSI coloring support.
* Interactive input.
* Rich text printing support (fields, lists, and tables).
* Subcommands (explicit or lazy-loaded) and command aliases.
* Displaying man pages for `--help`/`help`.
* Using the pager (aka `less`).
* [XDG directories](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html) (aka `~/.config/`, `~/.local/share/`, `~/.cache/`).
* Exception handling / Bug reporting.
* **Testable** - Since commands are plain-old Ruby classes, it's easy to
initialize them and call `#main` or `#run`.## Anti-Features
* No additional runtime dependencies.
* Does not implement it's own option parser.
* Not named after a comic-book Superhero.## Requirements
* [ruby] >= 3.0.0
## Install
```sh
$ gem install command_kit
```### gemspec
```ruby
gem.add_dependency 'command_kit', '~> 0.3'
```### Gemfile
```ruby
gem 'command_kit', '~> 0.3'
```## Examples
### lib/foo/cli/my_cmd.rb
```ruby
require 'command_kit'module Foo
module CLI
class MyCmd < CommandKit::Commandusage '[OPTIONS] [-o OUTPUT] FILE'
option :count, short: '-c',
value: {
type: Integer,
default: 1
},
desc: "Number of times"option :output, short: '-o',
value: {
type: String,
usage: 'FILE'
},
desc: "Optional output file"option :verbose, short: '-v', desc: "Increase verbose level" do
@verbose += 1
endargument :file, required: true,
usage: 'FILE',
desc: "Input file"examples [
'-o path/to/output.txt path/to/input.txt',
'-v -c 2 -o path/to/output.txt path/to/input.txt',
]description 'Example command'
def initialize(**kwargs)
super(**kwargs)@verbose = 0
enddef run(file)
puts "count=#{options[:count].inspect}"
puts "output=#{options[:output].inspect}"
puts "file=#{file.inspect}"
puts "verbose=#{@verbose.inspect}"
endend
end
end
```### bin/my_cmd
```ruby
#!/usr/bin/env ruby$LOAD_PATH.unshift(File.expand_path('../../lib',__FILE__))
require 'foo/cli/my_cmd'Foo::CLI::MyCmd.start
```### --help
Usage: my_cmd [OPTIONS] [-o OUTPUT] FILE
Options:
-c, --count INT Number of times (Default: 1)
-o, --output FILE Optional output file
-v, --verbose Increase verbose level
-h, --help Print help informationArguments:
FILE Input fileExamples:
my_cmd -o path/to/output.txt path/to/input.txt
my_cmd -v -c 2 -o path/to/output.txt path/to/input.txtExample command
## Testing
### RSpec
```ruby
require 'spec_helper'
require 'stringio'
require 'foo/cli/my_cmd'describe Foo::CLI::MyCmd do
let(:stdin) { StringIO.new }
let(:stdout) { StringIO.new }
let(:stderr) { StringIO.new }
let(:env) { ENV }subject do
described_class.new(
stdin: stdin,
stdout: stdout,
stderr: stderr,
env: env
)
end# testing with raw options/arguments
describe "#main" do
context "when executed with no arguments" do
it "must exit with -1" do
expect(subject.main([])).to eq(-1)
end
endcontext "when executed with -o OUTPUT" do
let(:file) { ... }
let(:output) { ... }before { subject.main(["-o", output, file]) }
it "must create the output file" do
...
end
end
end
end
```### Reference
* [CommandKit::Arguments](https://rubydoc.info/gems/command_kit/CommandKit/Arguments)
* [CommandKit::BugReport](https://rubydoc.info/gems/command_kit/CommandKit/BugReport)
* [CommandKit::Colors](https://rubydoc.info/gems/command_kit/CommandKit/Colors)
* [CommandKit::Command](https://rubydoc.info/gems/command_kit/CommandKit/Command)
* [CommandKit::CommandName](https://rubydoc.info/gems/command_kit/CommandKit/CommandName)
* [CommandKit::Commands](https://rubydoc.info/gems/command_kit/CommandKit/Commands)
* [CommandKit::Commands::AutoLoad](https://rubydoc.info/gems/command_kit/CommandKit/Commands/AutoLoad)
* [CommandKit::Commands::AutoRequire](https://rubydoc.info/gems/command_kit/CommandKit/Commands/AutoRequire)
* [CommandKit::Completion::Install](https://rubydoc.info/gems/command_kit/CommandKit/Completion/Install)
* [CommandKit::Description](https://rubydoc.info/gems/command_kit/CommandKit/Description)
* [CommandKit::Edit](https://rubydoc.info/gems/command_kit/CommandKit/Edit)
* [CommandKit::Env](https://rubydoc.info/gems/command_kit/CommandKit/Env)
* [CommandKit::Env::Home](https://rubydoc.info/gems/command_kit/CommandKit/Env/Home)
* [CommandKit::Env::Path](https://rubydoc.info/gems/command_kit/CommandKit/Env/Path)
* [CommandKit::Env::Prefix](https://rubydoc.info/gems/command_kit/CommandKit/Env/Prefix)
* [CommandKit::Env::Shell](https://rubydoc.info/gems/command_kit/CommandKit/Env/Shell)
* [CommandKit::Examples](https://rubydoc.info/gems/command_kit/CommandKit/Examples)
* [CommandKit::ExceptionHandler](https://rubydoc.info/gems/command_kit/CommandKit/ExceptionHandler)
* [CommandKit::FileUtils](https://rubydoc.info/gems/command_kit/CommandKit/FileUtils)
* [CommandKit::Help](https://rubydoc.info/gems/command_kit/CommandKit/Help)
* [CommandKit::Help::Man](https://rubydoc.info/gems/command_kit/CommandKit/Help/Man)
* [CommandKit::Interactive](https://rubydoc.info/gems/command_kit/CommandKit/Interactive)
* [CommandKit::Main](https://rubydoc.info/gems/command_kit/CommandKit/Main)
* [CommandKit::Open](https://rubydoc.info/gems/command_kit/CommandKit/Open)
* [CommandKit::Options](https://rubydoc.info/gems/command_kit/CommandKit/Options)
* [CommandKit::Options::Quiet](https://rubydoc.info/gems/command_kit/CommandKit/Options/Quiet)
* [CommandKit::Options::Verbose](https://rubydoc.info/gems/command_kit/CommandKit/Options/Verbose)
* [CommandKit::Pager](https://rubydoc.info/gems/command_kit/CommandKit/Pager)
* [CommandKit::Printing](https://rubydoc.info/gems/command_kit/CommandKit/Printing)
* [CommandKit::Printing::Fields](https://rubydoc.info/gems/command_kit/CommandKit/Printing/Fields)
* [CommandKit::Printing::Indent](https://rubydoc.info/gems/command_kit/CommandKit/Printing/Indent)
* [CommandKit::Printing::Lists](https://rubydoc.info/gems/command_kit/CommandKit/Printing/Lists)
* [CommandKit::Printing::Tables](https://rubydoc.info/gems/command_kit/CommandKit/Printing/Tables)
* [CommandKit::ProgramName](https://rubydoc.info/gems/command_kit/CommandKit/ProgramName)
* [CommandKit::Stdio](https://rubydoc.info/gems/command_kit/CommandKit/Stdio)
* [CommandKit::Terminal](https://rubydoc.info/gems/command_kit/CommandKit/Terminal)
* [CommandKit::Usage](https://rubydoc.info/gems/command_kit/CommandKit/Usage)
* [CommandKit::XDG](https://rubydoc.info/gems/command_kit/CommandKit/XDG)## Real-World Examples
* [configure_trusted_publisher](https://github.com/rubygems/configure_trusted_publisher#usage)
* [ronin](https://github.com/ronin-rb/ronin#readme)## Alternatives
* [dry-cli](https://dry-rb.org/gems/dry-cli/0.6/)
* [cmdparse](https://cmdparse.gettalong.org/)## Special Thanks
Special thanks to everyone who answered my questions and gave feedback on
Twitter.## Copyright
Copyright (c) 2021-2024 Hal Brodigan
See {file:LICENSE.txt} for details.
[ruby]: https://www.ruby-lang.org/
[optparse]: https://rubydoc.info/stdlib/optparse/OptionParser