Implement basic CLI usage help
This commit is contained in:
parent
f38a5761be
commit
422a940eae
3
bin/uhwm
3
bin/uhwm
@ -2,4 +2,5 @@
|
|||||||
|
|
||||||
require 'uh/wm'
|
require 'uh/wm'
|
||||||
|
|
||||||
Uh::WM::CLI.run!(ARGV)
|
Uh::WM::CLI.run(ARGV)
|
||||||
|
sleep 8
|
||||||
|
11
features/cli/usage.feature
Normal file
11
features/cli/usage.feature
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
Feature: CLI usage
|
||||||
|
|
||||||
|
Scenario: prints the usage when unknown option switch is given
|
||||||
|
When I run uhwm with option --unknown-option
|
||||||
|
Then the exit status must be 64
|
||||||
|
And the output must contain exactly the usage
|
||||||
|
|
||||||
|
Scenario: prints the help when -h option is given
|
||||||
|
When I run uhwm with option -h
|
||||||
|
Then the exit status must be 0
|
||||||
|
And the output must contain exactly the usage
|
8
features/steps/output_steps.rb
Normal file
8
features/steps/output_steps.rb
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
Then /^the output must contain exactly the usage$/ do
|
||||||
|
assert_exact_output <<-eoh, all_output
|
||||||
|
Usage: uhwm [options]
|
||||||
|
|
||||||
|
options:
|
||||||
|
-h, --help print this message
|
||||||
|
eoh
|
||||||
|
end
|
@ -1,4 +1,17 @@
|
|||||||
When /^I start uhwm$/ do
|
def uhwm_run options = nil
|
||||||
@process = run 'uhwm'
|
command = %w[uhwm]
|
||||||
@interactive = @process
|
command << options if options
|
||||||
|
@interactive = @process = run command.join ' '
|
||||||
|
end
|
||||||
|
|
||||||
|
When /^I start uhwm$/ do
|
||||||
|
uhwm_run
|
||||||
|
end
|
||||||
|
|
||||||
|
When /^I run uhwm with options? (-.+)$/ do |options|
|
||||||
|
uhwm_run options
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^the exit status must be (\d+)$/ do |exit_status|
|
||||||
|
assert_exit_status exit_status.to_i
|
||||||
end
|
end
|
||||||
|
@ -1,13 +1,56 @@
|
|||||||
module Uh
|
module Uh
|
||||||
module WM
|
module WM
|
||||||
class CLI
|
class CLI
|
||||||
|
ArgumentError = Class.new(ArgumentError)
|
||||||
|
|
||||||
|
USAGE = "Usage: #{File.basename $0} [options]".freeze
|
||||||
|
|
||||||
|
EX_USAGE = 64
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
def run! arguments
|
def run arguments, **options
|
||||||
$stdout.sync = true
|
cli = new arguments, **options
|
||||||
|
cli.parse_arguments!
|
||||||
|
cli.run
|
||||||
|
rescue ArgumentError => e
|
||||||
|
$stderr.puts e
|
||||||
|
exit EX_USAGE
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize args, stdin: $stdin, stdout: $stdout, stderr: $stderr
|
||||||
|
@arguments = args
|
||||||
|
@stdin = stdin
|
||||||
|
@stdout = stdout
|
||||||
|
@stderr = stderr
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_arguments!
|
||||||
|
option_parser.parse! @arguments
|
||||||
|
rescue OptionParser::InvalidOption => e
|
||||||
|
fail ArgumentError, option_parser
|
||||||
|
end
|
||||||
|
|
||||||
|
def run
|
||||||
|
@stdout.sync = true
|
||||||
@display = Display.new
|
@display = Display.new
|
||||||
@display.open
|
@display.open
|
||||||
puts "Connected to X server on `#{display}'"
|
@stdout.puts "Connected to X server on `#{@display}'"
|
||||||
sleep 8
|
end
|
||||||
|
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def option_parser
|
||||||
|
OptionParser.new do |opts|
|
||||||
|
opts.banner = USAGE
|
||||||
|
opts.separator ''
|
||||||
|
opts.separator 'options:'
|
||||||
|
|
||||||
|
opts.on '-h', '--help', 'print this message' do
|
||||||
|
@stdout.print opts
|
||||||
|
exit
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
98
spec/uh/wm/cli_spec.rb
Normal file
98
spec/uh/wm/cli_spec.rb
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
require 'support/exit_helpers'
|
||||||
|
|
||||||
|
module Uh
|
||||||
|
module WM
|
||||||
|
RSpec.describe CLI do
|
||||||
|
include ExitHelpers
|
||||||
|
|
||||||
|
let(:stdout) { StringIO.new }
|
||||||
|
let(:stderr) { StringIO.new }
|
||||||
|
let(:arguments) { [] }
|
||||||
|
let(:options) { { stdout: stdout, stderr: stderr } }
|
||||||
|
|
||||||
|
subject(:cli) { described_class.new arguments, **options }
|
||||||
|
|
||||||
|
describe '.run' do
|
||||||
|
subject(:run) { described_class.run arguments, **options }
|
||||||
|
|
||||||
|
it 'builds a new CLI with given arguments' do
|
||||||
|
expect(described_class)
|
||||||
|
.to receive(:new).with(arguments, options).and_call_original
|
||||||
|
run
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'parses new CLI arguments' do
|
||||||
|
cli = instance_spy CLI
|
||||||
|
allow(described_class).to receive(:new) { cli }
|
||||||
|
expect(cli).to receive :parse_arguments!
|
||||||
|
run
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'runs new CLI' do
|
||||||
|
cli = instance_spy CLI
|
||||||
|
allow(described_class).to receive(:new) { cli }
|
||||||
|
expect(cli).to receive :run
|
||||||
|
run
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with invalid arguments' do
|
||||||
|
let(:arguments) { %w[--unknown-option] }
|
||||||
|
|
||||||
|
it 'prints the usage' do
|
||||||
|
expect { trap_exit { run } }.to output(/\AUsage: .+/).to_stderr
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'exits with a return status of 64' do
|
||||||
|
stderr_original = $stderr
|
||||||
|
$stderr = stderr
|
||||||
|
expect { run }.to raise_error(SystemExit) do |e|
|
||||||
|
expect(e.status).to eq 64
|
||||||
|
end
|
||||||
|
$stderr = stderr_original
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#run' do
|
||||||
|
let(:display) { instance_spy Display }
|
||||||
|
|
||||||
|
before { allow(Display).to receive(:new) { display } }
|
||||||
|
|
||||||
|
it 'opens a new X display' do
|
||||||
|
expect(display).to receive :open
|
||||||
|
cli.run
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'prints a message on standard output when connected' do
|
||||||
|
cli.run
|
||||||
|
expect(stdout.string).to match /connected/i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#parse_arguments!' do
|
||||||
|
context 'with help option' do
|
||||||
|
let(:arguments) { %w[-h] }
|
||||||
|
|
||||||
|
it 'prints the usage banner on standard output' do
|
||||||
|
trap_exit { cli.parse_arguments! }
|
||||||
|
expect(stdout.string).to match /\AUsage: .+/
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'prints options usage on standard output' do
|
||||||
|
trap_exit { cli.parse_arguments! }
|
||||||
|
expect(stdout.string).to match /\n^options:\n\s+-/
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with invalid option' do
|
||||||
|
let(:arguments) { %w[--unknown-option] }
|
||||||
|
|
||||||
|
it 'raises a CLI::ArgumentError' do
|
||||||
|
expect { cli.parse_arguments! }
|
||||||
|
.to raise_error CLI::ArgumentError
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
x
Reference in New Issue
Block a user