Summary
Follow-up to #561. The CommandNotFoundHandler is now called with the unknown command name and available commands for top-level command-not-found errors. However, it is not called when a nested subcommand is not found (e.g., alias ad instead of alias add).
Problem
When a group command receives an invalid subcommand, the parser generates a CommandLineParserException (not CommandNotFoundException):
// AeshCommandLineParser.java:576-578
processedCommand.addParserException(new CommandLineParserException(
"'" + command + " " + iterator.peekWord()
+ "' is not part of the " + command + " commands. See '" + command + " --help'."));
The CommandNotFoundHandler is only invoked for CommandNotFoundException, so nested subcommand typos bypass the handler entirely.
Use case
$ jbang alis add myalias test.java
jbang: 'alis' is not a jbang command. Did you mean 'alias'? <-- works (#561)
$ jbang alias ad myalias test.java
'alias ad' is not part of the alias commands. <-- no "did you mean?" suggestion
The second case should suggest add since the child parser knows its available subcommands (add, list, remove).
Proposed approach
At the parser level (AeshCommandLineParser.parse() line 576-578), the unknown subcommand name and the available child parser names are both accessible:
- Unknown name:
iterator.peekWord()
- Available children:
getAllChildParsers() -> each child's getProcessedCommand().name()
Options:
- Throw
CommandNotFoundException instead of CommandLineParserException for invalid subcommands -- this would route through the existing handler. But it changes exception semantics and may break catch blocks that distinguish these types.
- Store the unknown subcommand + available names on the
ProcessedCommand and check for it in the runtime/runner error handling paths.
- Call the handler directly from the parser exception path -- add handler invocation to the
CommandLineParserException catch block in ReadlineConsole, AeshCommandRuntime, and AeshRuntimeRunner.
- Include available subcommand names in the parser exception message -- less flexible but simpler.
Depends on
Environment
Summary
Follow-up to #561. The
CommandNotFoundHandleris now called with the unknown command name and available commands for top-level command-not-found errors. However, it is not called when a nested subcommand is not found (e.g.,alias adinstead ofalias add).Problem
When a group command receives an invalid subcommand, the parser generates a
CommandLineParserException(notCommandNotFoundException):The
CommandNotFoundHandleris only invoked forCommandNotFoundException, so nested subcommand typos bypass the handler entirely.Use case
The second case should suggest
addsince the child parser knows its available subcommands (add,list,remove).Proposed approach
At the parser level (
AeshCommandLineParser.parse()line 576-578), the unknown subcommand name and the available child parser names are both accessible:iterator.peekWord()getAllChildParsers()-> each child'sgetProcessedCommand().name()Options:
CommandNotFoundExceptioninstead ofCommandLineParserExceptionfor invalid subcommands -- this would route through the existing handler. But it changes exception semantics and may break catch blocks that distinguish these types.ProcessedCommandand check for it in the runtime/runner error handling paths.CommandLineParserExceptioncatch block inReadlineConsole,AeshCommandRuntime, andAeshRuntimeRunner.Depends on
Environment