command_kit
Description
A Ruby toolkit for building clean, correct, and robust CLI commands as plain-old Ruby classes.
Features
- Supports defining commands as Classes.
- Supports defining options and arguments as attributes.
- Supports extending commands via inheritance.
- Supports subcommands (explicit or lazy-loaded) and command aliases.
- Correctly handles Ctrl^C and SIGINT interrupts (aka exit 130).
- Correctly handles broken pipes (aka
mycmd | head
). - Correctly handles when stdout or stdin is redirected to a file.
- Uses OptionParser for POSIX option parsing.
- Supports optionally displaying a man-page instead of
--help
(see CommandKit::Help::Man). - Supports optional ANSI coloring.
- Supports interactively prompting for user input.
- Supports easily detecting the terminal size.
- Supports paging output with
less
ormore
. - Supports XDG directories (
~/.config/
,~/.local/share/
,~/.cache/
). - Easy to test (ex:
MyCmd.main(arg1, arg2, options: {foo: foo}) # => 0
)
API
- CommandKit::Arguments
- CommandKit::Colors
- CommandKit::Command
- CommandKit::CommandName
- CommandKit::Commands
- CommandKit::Description
- CommandKit::Env
- CommandKit::Examples
- CommandKit::ExceptionHandler
- CommandKit::Help
- CommandKit::Interactive
- CommandKit::Main
- CommandKit::Options
- CommandKit::Pager
- CommandKit::Printing
- CommandKit::ProgramName
- CommandKit::Stdio
- CommandKit::Terminal
- CommandKit::Usage
- CommandKit::XDG
Anti-Features
- No additional runtime dependencies.
- Does not implement it's own option parser.
- Not named after a comic-book Superhero.
Examples
lib/foo/cli/my_cmd.rb
require 'command_kit'
module Foo
module CLI
class MyCmd < CommandKit::Command
usage '[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
end
argument :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
end
def run(file)
puts "count=#{[:count].inspect}"
puts "output=#{[:output].inspect}"
puts "file=#{file.inspect}"
puts "verbose=#{@verbose.inspect}"
end
end
end
end
bin/my_cmd
#!/usr/bin/env ruby
$LOAD_PATH.unshift(File.('../../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 information
Arguments:
FILE Input file
Examples:
my_cmd -o path/to/output.txt path/to/input.txt
my_cmd -v -c 2 -o path/to/output.txt path/to/input.txt
Example command
Requirements
- ruby >= 2.7.0
Install
$ gem install command_kit
Gemfile
gem 'command_kit', '~> 0.1'
Alternatives
Special Thanks
Special thanks to everyone who answered my questions and gave feedback on Twitter.
Copyright
Copyright (c) 2021 Hal Brodigan
See LICENSE for details.