mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-23 03:03:57 +08:00
Improvements to error messages with new parser. In particular, "naked
builtins" now print their help (e.g. just 'while')
This commit is contained in:
parent
40e223c12d
commit
ec469782c8
40
builtin.cpp
40
builtin.cpp
|
@ -1038,20 +1038,22 @@ static int builtin_emit(parser_t &parser, wchar_t **argv)
|
|||
static int builtin_generic(parser_t &parser, wchar_t **argv)
|
||||
{
|
||||
int argc=builtin_count_args(argv);
|
||||
|
||||
/* Hackish - if we have no arguments other than the command, we are a "naked invocation" and we just print help */
|
||||
if (argc == 1)
|
||||
{
|
||||
builtin_print_help(parser, argv[0], stdout_buffer);
|
||||
return STATUS_BUILTIN_ERROR;
|
||||
}
|
||||
|
||||
woptind=0;
|
||||
|
||||
static const struct woption
|
||||
long_options[] =
|
||||
{
|
||||
{
|
||||
L"help", no_argument, 0, 'h'
|
||||
}
|
||||
,
|
||||
{
|
||||
0, 0, 0, 0
|
||||
}
|
||||
}
|
||||
;
|
||||
{ L"help", no_argument, 0, 'h' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
@ -2060,6 +2062,13 @@ int define_function(parser_t &parser, const wcstring_list_t &c_args, const wcstr
|
|||
*/
|
||||
static int builtin_function(parser_t &parser, wchar_t **argv)
|
||||
{
|
||||
/* Hack hack hack - with the new parser, this is only invoked for help */
|
||||
if (parser_use_ast())
|
||||
{
|
||||
builtin_print_help(parser, argv[0], stdout_buffer);
|
||||
return STATUS_BUILTIN_OK;
|
||||
}
|
||||
|
||||
int argc = builtin_count_args(argv);
|
||||
int res=STATUS_BUILTIN_OK;
|
||||
wchar_t *desc=0;
|
||||
|
@ -3662,6 +3671,12 @@ static int builtin_for(parser_t &parser, wchar_t **argv)
|
|||
int argc = builtin_count_args(argv);
|
||||
int res=STATUS_BUILTIN_ERROR;
|
||||
|
||||
/* Hackish - if we have no arguments other than the command, we are a "naked invocation" and we just print help */
|
||||
if (argc == 1)
|
||||
{
|
||||
builtin_print_help(parser, argv[0], stdout_buffer);
|
||||
return STATUS_BUILTIN_ERROR;
|
||||
}
|
||||
|
||||
if (argc < 3)
|
||||
{
|
||||
|
@ -4048,6 +4063,13 @@ static int builtin_switch(parser_t &parser, wchar_t **argv)
|
|||
{
|
||||
int res=STATUS_BUILTIN_OK;
|
||||
int argc = builtin_count_args(argv);
|
||||
|
||||
/* Hackish - if we have no arguments other than the command, we are a "naked invocation" and we just print help */
|
||||
if (argc == 1)
|
||||
{
|
||||
builtin_print_help(parser, argv[0], stdout_buffer);
|
||||
return STATUS_BUILTIN_ERROR;
|
||||
}
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
|
|
|
@ -240,6 +240,39 @@ wcstring keyword_description(parse_keyword_t k)
|
|||
return format_string(L"Unknown keyword type %ld", static_cast<long>(k));
|
||||
}
|
||||
|
||||
static wcstring token_type_user_presentable_description(parse_token_type_t type, parse_keyword_t keyword)
|
||||
{
|
||||
if (keyword != parse_keyword_none)
|
||||
{
|
||||
return format_string(L"keyword '%ls'", keyword_description(keyword).c_str());
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
/* Hackish. We only support the following types. */
|
||||
case symbol_statement:
|
||||
return L"a command";
|
||||
|
||||
case parse_token_type_string:
|
||||
return L"a string";
|
||||
|
||||
case parse_token_type_pipe:
|
||||
return L"a pipe";
|
||||
|
||||
case parse_token_type_redirection:
|
||||
return L"a redirection";
|
||||
|
||||
case parse_token_type_background:
|
||||
return L"a '&'";
|
||||
|
||||
case parse_token_type_end:
|
||||
return L"end of the statement";
|
||||
|
||||
default:
|
||||
return format_string(L"a %ls", token_type_description(type).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns a string description of the given parse node */
|
||||
wcstring parse_node_t::describe(void) const
|
||||
{
|
||||
|
@ -263,32 +296,7 @@ wcstring parse_token_t::describe() const
|
|||
/** A string description appropriate for presentation to the user */
|
||||
wcstring parse_token_t::user_presentable_description() const
|
||||
{
|
||||
if (keyword != parse_keyword_none)
|
||||
{
|
||||
return format_string(L"keyword %ls", keyword_description(keyword).c_str());
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
/* Hackish. We only support the */
|
||||
case parse_token_type_string:
|
||||
return L"a string";
|
||||
|
||||
case parse_token_type_pipe:
|
||||
return L"a pipe";
|
||||
|
||||
case parse_token_type_redirection:
|
||||
return L"a redirection";
|
||||
|
||||
case parse_token_type_background:
|
||||
return L"a '&'";
|
||||
|
||||
case parse_token_type_end:
|
||||
return L"statement terminator";
|
||||
|
||||
default:
|
||||
return format_string(L"a %ls", this->describe().c_str());
|
||||
}
|
||||
return token_type_user_presentable_description(type, keyword);
|
||||
}
|
||||
|
||||
/* Convert from tokenizer_t's token type to a parse_token_t type */
|
||||
|
@ -443,20 +451,7 @@ struct parse_stack_element_t
|
|||
/* Returns a name that we can show to the user, e.g. "a command" */
|
||||
wcstring user_presentable_description(void) const
|
||||
{
|
||||
if (keyword != parse_keyword_none)
|
||||
{
|
||||
return format_string(L"keyword %ls", keyword_description(keyword).c_str());
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
/* Hackish, the only one we support now */
|
||||
case symbol_statement:
|
||||
return L"a command";
|
||||
|
||||
default:
|
||||
return format_string(L"a %ls", this->describe().c_str());
|
||||
}
|
||||
return token_type_user_presentable_description(type, keyword);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -751,7 +746,8 @@ void parse_ll_t::parse_error_unbalancing_token(parse_token_t token)
|
|||
// This is a 'generic' parse error when we can't match the top of the stack element
|
||||
void parse_ll_t::parse_error_failed_production(struct parse_stack_element_t &stack_elem, parse_token_t token)
|
||||
{
|
||||
this->parse_error(token, parse_error_generic, L"Expected %ls, but instead found %ls", stack_elem.user_presentable_description().c_str(), token.user_presentable_description().c_str());
|
||||
const wcstring expected = stack_elem.user_presentable_description();
|
||||
this->parse_error(expected.c_str(), token);
|
||||
}
|
||||
|
||||
void parse_ll_t::report_tokenizer_error(parse_token_t token, const wchar_t *tok_error)
|
||||
|
@ -765,8 +761,7 @@ void parse_ll_t::parse_error(const wchar_t *expected, parse_token_t token)
|
|||
fatal_errored = true;
|
||||
if (this->should_generate_error_messages)
|
||||
{
|
||||
wcstring desc = token.user_presentable_description();
|
||||
this->parse_error(token, parse_error_generic, L"Expected a %ls, instead got a token of type %ls", expected, desc.c_str());
|
||||
this->parse_error(token, parse_error_generic, L"Expected %ls, but instead found %ls", expected, token.user_presentable_description().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user