forked from Lephenixnoir/fxos
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:
parent
e0783c2348
commit
0f5c1c2eba
24
shell/e.cpp
24
shell/e.cpp
|
@ -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;
|
||||
|
|
|
@ -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]+
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue