Skip to content

Commit

Permalink
Improve output when using a namespace as a command (athena-framework/…
Browse files Browse the repository at this point in the history
  • Loading branch information
Blacksmoke16 authored Jun 22, 2024
1 parent 10e5e98 commit 59527e6
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 16 deletions.
32 changes: 32 additions & 0 deletions spec/application_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,38 @@ struct ApplicationTest < ASPEC::TestCase
output.should contain "Do you want to run 'foo' instead? (yes/no) [no]:"
end

def test_run_namespace : Nil
ENV["COLUMNS"] = "120"
app = ACON::Application.new "foo"
app.auto_exit = false
app.add FooCommand.new
app.add Foo1Command.new
app.add Foo2Command.new

tester = ACON::Spec::ApplicationTester.new app
tester.run(command: "foo", decorated: false) # .should eq ACON::Command::Status::FAILURE

output = tester.display true
output.should contain "Available commands for the 'foo' namespace:"
output.should contain "The foo:bar command"
output.should contain "The foo:bar1 command"
end

def test_run_with_find_error : Nil
app = ACON::Application.new "foo"
app.auto_exit = false
app.catch_exceptions = false
app.command_loader = MockCommandLoader.new(
command_or_exception: FooCommand.new,
has: false,
names: ::Exception.new("Oh noes")
)

expect_raises ::Exception, "Oh noes" do
ACON::Spec::ApplicationTester.new(app).run command: "blah"
end
end

def test_find_alternative_exception_message_multiple : Nil
ENV["COLUMNS"] = "120"
app = ACON::Application.new "foo"
Expand Down
2 changes: 1 addition & 1 deletion spec/fixtures/text/application_filtered_namespace.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ My Athena application <info>1.0.0</info>
<info>-n, --no-interaction</info> Do not ask any interactive question
<info>-v|vv|vvv, --verbose</info> Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

<comment>Available commands for the "command4" namespace:</comment>
<comment>Available commands for the 'command4' namespace:</comment>
<info>command4:descriptor</info>
31 changes: 31 additions & 0 deletions spec/spec_helper.cr
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,35 @@ require "./fixtures/**"
# Override that given there are specs based on ansi output.
Colorize.enabled = true

struct MockCommandLoader
include Athena::Console::Loader::Interface

def initialize(
*,
@command_or_exception : ACON::Command | ::Exception? = nil,
@has : Bool = true,
@names : Array(String) | ::Exception = [] of String
)
end

def get(name : String) : ACON::Command
case v = @command_or_exception
in ::Exception then raise v
in ACON::Command then v
in Nil then raise "BUG: no command or exception was set"
end
end

def has?(name : String) : Bool
@has
end

def names : Array(String)
case v = @names
in ::Exception then raise v
in Array(String) then v
end
end
end

ASPEC.run_all
47 changes: 33 additions & 14 deletions src/application.cr
Original file line number Diff line number Diff line change
Expand Up @@ -599,27 +599,46 @@ class Athena::Console::Application

command = self.find command_name
rescue ex : Exception
if !(ex.is_a?(ACON::Exceptions::CommandNotFound) && !ex.is_a?(ACON::Exceptions::NamespaceNotFound)) ||
1 != (alternatives = ex.alternatives).size ||
!input.interactive?
# TODO: Handle dispatching

raise ex
end
if (ex.is_a?(ACON::Exceptions::CommandNotFound) && !ex.is_a?(ACON::Exceptions::NamespaceNotFound)) &&
1 == (alternatives = ex.alternatives).size &&
input.interactive?
alternative = alternatives.not_nil!.first

alternative = alternatives.not_nil!.first
style = ACON::Style::Athena.new input, output
output.puts ""
output.puts ACON::Helper::Formatter.new.format_block "Command '#{command_name}' is not defined.", "error", true

style = ACON::Style::Athena.new input, output
unless style.confirm "Do you want to run '#{alternative}' instead?", false
# TODO: Handle dispatching

style.block "\nCommand '#{command_name}' is not defined.\n", style: "error"
return ACON::Command::Status::FAILURE
end

unless style.confirm "Do you want to run '#{alternative}' instead?", false
command = self.find alternative
else
# TODO: Handle dispatching

return ACON::Command::Status::FAILURE
end
begin
if ex.is_a?(ACON::Exceptions::CommandNotFound) && (namespace = self.find_namespace command_name)
ACON::Helper::Descriptor.new.describe(
output.is_a?(ACON::Output::ConsoleOutputInterface) ? output.error_output : output,
self,
ACON::Descriptor::Context.new(
format: "txt",
raw_text: false,
namespace: namespace,
short: false
)
)

return ACON::Command::Status::SUCCESS
end

command = self.find alternative
raise ex
rescue ACON::Exceptions::NamespaceNotFound
raise ex
end
end
end

@running_command = command
Expand Down
2 changes: 1 addition & 1 deletion src/descriptor/text.cr
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class Athena::Console::Descriptor::Text < Athena::Console::Descriptor
)

if described_namespace
self.write_text %(<comment>Available commands for the "#{described_namespace}" namespace:</comment>), context
self.write_text %(<comment>Available commands for the '#{described_namespace}' namespace:</comment>), context
else
self.write_text "<comment>Available commands:</comment>", context
end
Expand Down

0 comments on commit 59527e6

Please sign in to comment.