Skip to content

Commit b72eacf

Browse files
authored
Fix --help option (#665)
Restores the behavior where `--help` would always skip the command to be invoked, while still allowing to pass the `--help` to external subcommands: The following commands print the help message and exit: - `shards --help` - `shards --local --help` - `shards update --help` While the following tries to call `shards-unknown --help` then falls back to print the help message and exit: - `shards unknown --help` Relies on a fixed list of the builtin command names to avoid having each `when` case starting with `display_help_and_exit(opts) if display_help`.
1 parent 74fb685 commit b72eacf

File tree

2 files changed

+92
-47
lines changed

2 files changed

+92
-47
lines changed

spec/integration/help_spec.cr

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
require "./spec_helper"
2+
3+
describe "--help" do
4+
it "prints help and doesn't invoke the command" do
5+
metadata = {
6+
version: "1.0.0",
7+
dependencies: {
8+
mock: {git: git_path("mock")},
9+
},
10+
}
11+
12+
[
13+
"shards --help",
14+
"shards --local --help",
15+
"shards update --help",
16+
].each do |command|
17+
with_shard(metadata) do
18+
output = run command
19+
20+
# it printed the help message
21+
output.should contain("Commands:")
22+
output.should contain("General options:")
23+
24+
# it didn't run the command (or default command)
25+
output.should_not contain("Resolving dependencies")
26+
end
27+
end
28+
end
29+
end

src/cli.cr

Lines changed: 63 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@ require "option_parser"
22
require "./commands/*"
33

44
module Shards
5+
BUILTIN_COMMANDS = %w[
6+
build
7+
run
8+
check
9+
init
10+
install
11+
list
12+
lock
13+
outdated
14+
prune
15+
update
16+
version
17+
]
18+
519
def self.display_help_and_exit(opts)
620
puts <<-HELP
721
shards [<options>...] [<command>]
@@ -58,61 +72,63 @@ module Shards
5872
opts.on("-h", "--help", "Print usage synopsis.") { display_help = true }
5973

6074
opts.unknown_args do |args, options|
61-
case args[0]? || DEFAULT_COMMAND
62-
when "build"
63-
targets, build_options = parse_args(args[1..-1])
64-
check_and_install_dependencies(path)
65-
66-
Commands::Build.run(path, targets, build_options)
67-
when "run"
68-
targets, run_options = parse_args(args[1..-1])
69-
check_and_install_dependencies(path)
70-
71-
Commands::Run.run(path, targets, run_options, options)
72-
when "check"
73-
Commands::Check.run(path)
74-
when "init"
75-
Commands::Init.run(path)
76-
when "install"
77-
Commands::Install.run(
78-
path
79-
)
80-
when "list"
81-
Commands::List.run(path, tree: args.includes?("--tree"))
82-
when "lock"
83-
Commands::Lock.run(
84-
path,
85-
args[1..-1].reject(&.starts_with?("--")),
86-
print: args.includes?("--print"),
87-
update: args.includes?("--update")
88-
)
89-
when "outdated"
90-
Commands::Outdated.run(
91-
path,
92-
prereleases: args.includes?("--pre")
93-
)
94-
when "prune"
95-
Commands::Prune.run(path)
96-
when "update"
97-
Commands::Update.run(
98-
path,
99-
args[1..-1].reject(&.starts_with?("--"))
100-
)
101-
when "version"
102-
Commands::Version.run(args[1]? || path)
75+
command = args[0]? || DEFAULT_COMMAND
76+
77+
if BUILTIN_COMMANDS.includes?(command)
78+
if display_help
79+
display_help_and_exit(opts)
80+
end
81+
82+
case command
83+
when "build"
84+
targets, build_options = parse_args(args[1..-1])
85+
check_and_install_dependencies(path)
86+
Commands::Build.run(path, targets, build_options)
87+
when "run"
88+
targets, run_options = parse_args(args[1..-1])
89+
check_and_install_dependencies(path)
90+
Commands::Run.run(path, targets, run_options, options)
91+
when "check"
92+
Commands::Check.run(path)
93+
when "init"
94+
Commands::Init.run(path)
95+
when "install"
96+
Commands::Install.run(path)
97+
when "list"
98+
Commands::List.run(path, tree: args.includes?("--tree"))
99+
when "lock"
100+
Commands::Lock.run(
101+
path,
102+
args[1..-1].reject(&.starts_with?("--")),
103+
print: args.includes?("--print"),
104+
update: args.includes?("--update")
105+
)
106+
when "outdated"
107+
Commands::Outdated.run(
108+
path,
109+
prereleases: args.includes?("--pre")
110+
)
111+
when "prune"
112+
Commands::Prune.run(path)
113+
when "update"
114+
Commands::Update.run(
115+
path,
116+
args[1..-1].reject(&.starts_with?("--"))
117+
)
118+
when "version"
119+
Commands::Version.run(args[1]? || path)
120+
else
121+
raise "BUG: unknown command #{command}"
122+
end
103123
else
104-
program_name = "shards-#{args[0]}"
124+
program_name = "shards-#{command}"
105125
if program_path = Process.find_executable(program_name)
106126
run_shards_subcommand(program_path, cli_options)
107127
else
108128
display_help_and_exit(opts)
109129
end
110130
end
111131

112-
if display_help
113-
display_help_and_exit(opts)
114-
end
115-
116132
exit
117133
end
118134
end

0 commit comments

Comments
 (0)