Skip to content

Commit 2e6a149

Browse files
committed
refactor(command, executor): return exit code from command
1 parent ab076ee commit 2e6a149

File tree

2 files changed

+31
-20
lines changed

2 files changed

+31
-20
lines changed

src/cling/command.cr

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -169,12 +169,22 @@ module Cling
169169
@options[long] = Option.new(long, short, description, required, hidden, type, default)
170170
end
171171

172-
# Executes the command with the given input and parser (see `Parser`).
173-
def execute(input : String | Array(String), *, parser : Parser? = nil) : Nil
174-
parser ||= Parser.new input
175-
results = parser.parse
176-
Executor.handle self, results
177-
end
172+
{% begin %}
173+
# Executes the command with the given input and parser (see `Parser`). Returns the program exit
174+
# status code, by default it is `0`.
175+
{% if @top_level.has_constant?("Spec") %}
176+
def execute(input : String | Array(String), *, parser : Parser? = nil, terminate : Bool = false) : Int32
177+
{% else %}
178+
def execute(input : String | Array(String), *, parser : Parser? = nil, terminate : Bool = true) : Int32
179+
{% end %}
180+
parser ||= Parser.new input
181+
results = parser.parse
182+
code = Executor.handle self, results
183+
exit code if terminate
184+
185+
code
186+
end
187+
{% end %}
178188

179189
# A hook method to run once the command/subcommands, arguments and options have been parsed.
180190
# This has access to the parsed arguments and options from the command line. This is useful if

src/cling/executor.cr

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ module Cling::Executor
1717
end
1818
end
1919

20-
# Handles the execution of a command using the given results from the parser.
20+
# Handles the execution of a command using the given results from the parser. Returns the program
21+
# exit code from the command, by default it is `0`.
2122
#
2223
# ### Process
2324
#
@@ -27,26 +28,28 @@ module Cling::Executor
2728
# 2. The results are evaluated with the command arguments and options to set their values and
2829
# move the missing, unknown and invalid arguments/options into place.
2930
#
30-
# 3. The `Command#pre_run` hook is executed with the resolved arguments and options, and the
31-
# response is checked for continuation.
31+
# 3. The `Command#pre_run` hook is executed with the resolved arguments and options.
3232
#
3333
# 4. The evaluated arguments and options are finalized: missing, unknown and invalid arguments/
3434
# options trigger the necessary missing/unknown/invalid command hooks.
3535
#
36-
# 5. The main `Command#run` and `Command#post_run` methods are executed with the evaluated
37-
# arguments and options.
38-
def self.handle(command : Command, results : Array(Parser::Result)) : Nil
36+
# 5. The `Command#run` and `Command#post_run` methods are executed with the evaluated arguments
37+
# and options.
38+
#
39+
# 6. The program exit code is returned from the command, or `0` if no `ExitProgram` exception was
40+
# raised during the command's execution.
41+
def self.handle(command : Command, results : Array(Parser::Result)) : Int32
3942
resolved_command = resolve_command command, results
4043
unless resolved_command
4144
command.on_error CommandError.new("Command '#{results.first.value}' not found")
42-
return
45+
return 1
4346
end
4447

4548
begin
4649
executed = get_in_position resolved_command, results
4750
rescue ex : ExecutionError
4851
resolved_command.on_invalid_option ex.to_s
49-
return
52+
return 1
5053
end
5154

5255
begin
@@ -55,7 +58,7 @@ module Cling::Executor
5558
resolved_command.pre_run(executed.parsed_arguments, executed.parsed_options)
5659
)
5760
rescue ex : ExitProgram
58-
return handle_exit ex
61+
return ex.code
5962
rescue ex
6063
resolved_command.on_error ex
6164
end
@@ -66,10 +69,12 @@ module Cling::Executor
6669
resolved_command.run executed.parsed_arguments, executed.parsed_options
6770
resolved_command.post_run executed.parsed_arguments, executed.parsed_options
6871
rescue ex : ExitProgram
69-
handle_exit ex
72+
return ex.code
7073
rescue ex
7174
resolved_command.on_error ex
7275
end
76+
77+
0
7378
end
7479

7580
private def self.deprecation_helper(type : T, value : Bool?) : Nil forall T
@@ -231,8 +236,4 @@ module Cling::Executor
231236
command.on_missing_arguments(res.missing_arguments) unless res.missing_arguments.empty?
232237
command.on_unknown_arguments(res.unknown_arguments) unless res.unknown_arguments.empty?
233238
end
234-
235-
private def self.handle_exit(ex : ExitProgram) : NoReturn
236-
exit ex.code
237-
end
238239
end

0 commit comments

Comments
 (0)