shell: improve error behavior of parser and autocompletion

* Example on _e, but other commands are probably affected
* When completing, throw CompletionRequest("_error", <message>) to have
  a reasonable output and not mess up readline
* Avoid early returns (or if a command really cannot be completed,
  adjust the ShellCommand declaration to not run the command)
* Less CommandError in the parser, these would throw during
  autocompletion and annoy everyone
* Allow options with empty value so that we don't throw when
  autocompleting after typing eg. 'vspace='
This commit is contained in:
Lephenixnoir 2022-04-18 11:52:21 +01:00
parent e0783c2348
commit 0f5c1c2eba
Signed by untrusted user: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
5 changed files with 32 additions and 19 deletions

View File

@ -26,21 +26,21 @@ static _e_args parse_e(Session &session, Parser &parser)
parser.accept_options();
VirtualSpace *space;
if(!args.space_name.empty())
VirtualSpace *space = session.current_space;
if(!args.space_name.empty()) {
space = session.get_space(args.space_name);
else
space = session.current_space;
if(space)
while(!parser.at_end())
args.values.push_back(parser.expr(space));
else {
FxOS_log(ERR, "virtual space '%s' does not exist", args.space_name);
parser.exhaust();
if(!space) {
std::string msg =
format("virtual space '%s' does not exist", args.space_name);
if(parser.completing())
throw Parser::CompletionRequest("_error", msg);
else
FxOS_log(ERR, "%s", msg);
}
}
// TODO: Error message when session specified in _e does not exist
while(!parser.at_end())
args.values.push_back(parser.expr(space));
parser.end();
return args;

View File

@ -143,7 +143,7 @@ num_suffix [kMG]
num ({num_hex}|{num_dec}|{num_bin}){num_suffix}?
syscall [%][a-fA-F0-9]+
option [a-zA-Z]+=[^ ]+
option [a-zA-Z]+=[^ ]*
symbol [a-zA-Z_.][a-zA-Z0-9_.]*
space [ \t]+

View File

@ -129,6 +129,11 @@ char *autocomplete(char const *text, int state)
options = complete_region(text);
else if(r.category == "symbol" && r.space != nullptr)
options = complete_symbol(text, r.space);
else if(r.category == "_error") {
options.clear();
options.push_back("(ERROR) " + r.value);
options.push_back(".");
}
else
options.clear();
i = 0;

View File

@ -116,6 +116,11 @@ void Parser::exhaust()
feed();
}
bool Parser::completing() const
{
return m_complete;
}
void Parser::skip_separators()
{
while(m_la.type == T::SEPARATOR)
@ -319,13 +324,12 @@ long Parser::atom()
if(os && (int)opt->value < os->syscall_count())
val = os->syscall(opt->value);
}
else {
throw CommandError("symbol '{}' is undefined", t.value.STRING);
}
else if(!m_complete)
FxOS_log(ERR, "symbol '%s' is undefined", t.value.STRING);
}
else
throw CommandError(
"cannot query symbol '{}', no virtual space", t.value.STRING);
else if(!m_complete)
FxOS_log(ERR, "cannot query symbol '%s' (no virtual space)",
t.value.STRING);
return val;
}
else if(t.type == T::SYSCALL) {

View File

@ -117,6 +117,10 @@ public:
void end();
/* Exhaust all input (usually after encountering an error) */
void exhaust();
/* Whether we are parsing for autocompletion. This is only available to
allow appropriate decisions about printing vs. ignoring error messages.
Do not change parsing rules based on this information! */
bool completing() const;
/* Expect a token of this type, or of any of the listed types */
Token expect(T type, bool ignore_spaces=true);