mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-27 05:13:10 +00:00
Teach parser_t how to parse an argument list that contains newlines, for
complete -a support. Fixes #1369
This commit is contained in:
parent
31bf50b2d4
commit
62b3ed17ba
5 changed files with 39 additions and 7 deletions
|
@ -44,6 +44,10 @@ enum parse_token_type_t
|
||||||
|
|
||||||
symbol_argument_list,
|
symbol_argument_list,
|
||||||
|
|
||||||
|
// "freestanding" argument lists are parsed from the argument list supplied to 'complete -a'
|
||||||
|
// They are not generated by parse trees rooted in symbol_job_list
|
||||||
|
symbol_freestanding_argument_list,
|
||||||
|
|
||||||
symbol_argument,
|
symbol_argument,
|
||||||
symbol_redirection,
|
symbol_redirection,
|
||||||
|
|
||||||
|
|
|
@ -276,6 +276,26 @@ RESOLVE(argument_list)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PRODUCTIONS(freestanding_argument_list) =
|
||||||
|
{
|
||||||
|
{},
|
||||||
|
{symbol_argument, symbol_freestanding_argument_list},
|
||||||
|
{parse_token_type_end, symbol_freestanding_argument_list},
|
||||||
|
};
|
||||||
|
RESOLVE(freestanding_argument_list)
|
||||||
|
{
|
||||||
|
switch (token1.type)
|
||||||
|
{
|
||||||
|
case parse_token_type_string:
|
||||||
|
return 1;
|
||||||
|
case parse_token_type_end:
|
||||||
|
return 2;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PRODUCTIONS(block_statement) =
|
PRODUCTIONS(block_statement) =
|
||||||
{
|
{
|
||||||
{symbol_block_header, parse_token_type_end, symbol_job_list, symbol_end_command, symbol_arguments_or_redirections_list}
|
{symbol_block_header, parse_token_type_end, symbol_job_list, symbol_end_command, symbol_arguments_or_redirections_list}
|
||||||
|
@ -485,6 +505,7 @@ const production_t *parse_productions::production_for_token(parse_token_type_t n
|
||||||
TEST(case_item_list)
|
TEST(case_item_list)
|
||||||
TEST(case_item)
|
TEST(case_item)
|
||||||
TEST(argument_list)
|
TEST(argument_list)
|
||||||
|
TEST(freestanding_argument_list)
|
||||||
TEST(block_header)
|
TEST(block_header)
|
||||||
TEST(for_header)
|
TEST(for_header)
|
||||||
TEST(while_header)
|
TEST(while_header)
|
||||||
|
|
|
@ -186,6 +186,8 @@ wcstring token_type_description(parse_token_type_t type)
|
||||||
|
|
||||||
case symbol_argument_list:
|
case symbol_argument_list:
|
||||||
return L"argument_list";
|
return L"argument_list";
|
||||||
|
case symbol_freestanding_argument_list:
|
||||||
|
return L"freestanding_argument_list";
|
||||||
|
|
||||||
case symbol_boolean_statement:
|
case symbol_boolean_statement:
|
||||||
return L"boolean_statement";
|
return L"boolean_statement";
|
||||||
|
|
|
@ -255,6 +255,11 @@ bool parse_tree_from_string(const wcstring &str, parse_tree_flags_t flags, parse
|
||||||
|
|
||||||
end_command = END
|
end_command = END
|
||||||
|
|
||||||
|
# A freestanding_argument_list is equivalent to a normal argument list, except it may contain TOK_END (newlines, and even semicolons, for historical reasons:
|
||||||
|
|
||||||
|
freestanding_argument_list = <empty> |
|
||||||
|
argument freestanding_argument_list |
|
||||||
|
<TOK_END> freestanding_argument_list
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -493,7 +493,7 @@ void parser_t::expand_argument_list(const wcstring &arg_list_src, std::vector<co
|
||||||
|
|
||||||
/* Parse the string as an argument list */
|
/* Parse the string as an argument list */
|
||||||
parse_node_tree_t tree;
|
parse_node_tree_t tree;
|
||||||
if (! parse_tree_from_string(arg_list_src, parse_flag_none, &tree, NULL /* errors */, symbol_argument_list))
|
if (! parse_tree_from_string(arg_list_src, parse_flag_none, &tree, NULL /* errors */, symbol_freestanding_argument_list))
|
||||||
{
|
{
|
||||||
/* Failed to parse. Here we expect to have reported any errors in test_args */
|
/* Failed to parse. Here we expect to have reported any errors in test_args */
|
||||||
return;
|
return;
|
||||||
|
@ -502,7 +502,7 @@ void parser_t::expand_argument_list(const wcstring &arg_list_src, std::vector<co
|
||||||
/* Get the root argument list */
|
/* Get the root argument list */
|
||||||
assert(! tree.empty());
|
assert(! tree.empty());
|
||||||
const parse_node_t *arg_list = &tree.at(0);
|
const parse_node_t *arg_list = &tree.at(0);
|
||||||
assert(arg_list->type == symbol_argument_list);
|
assert(arg_list->type == symbol_freestanding_argument_list);
|
||||||
|
|
||||||
/* Extract arguments from it */
|
/* Extract arguments from it */
|
||||||
while (arg_list != NULL)
|
while (arg_list != NULL)
|
||||||
|
@ -968,7 +968,7 @@ bool parser_t::detect_errors_in_argument_list(const wcstring &arg_list_src, wcst
|
||||||
|
|
||||||
/* Parse the string as an argument list */
|
/* Parse the string as an argument list */
|
||||||
parse_node_tree_t tree;
|
parse_node_tree_t tree;
|
||||||
if (! parse_tree_from_string(arg_list_src, parse_flag_none, &tree, &errors, symbol_argument_list))
|
if (! parse_tree_from_string(arg_list_src, parse_flag_none, &tree, &errors, symbol_freestanding_argument_list))
|
||||||
{
|
{
|
||||||
/* Failed to parse. */
|
/* Failed to parse. */
|
||||||
errored = true;
|
errored = true;
|
||||||
|
@ -979,7 +979,7 @@ bool parser_t::detect_errors_in_argument_list(const wcstring &arg_list_src, wcst
|
||||||
/* Get the root argument list */
|
/* Get the root argument list */
|
||||||
assert(! tree.empty());
|
assert(! tree.empty());
|
||||||
const parse_node_t *arg_list = &tree.at(0);
|
const parse_node_t *arg_list = &tree.at(0);
|
||||||
assert(arg_list->type == symbol_argument_list);
|
assert(arg_list->type == symbol_freestanding_argument_list);
|
||||||
|
|
||||||
/* Extract arguments from it */
|
/* Extract arguments from it */
|
||||||
while (arg_list != NULL && ! errored)
|
while (arg_list != NULL && ! errored)
|
||||||
|
|
Loading…
Reference in a new issue