mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-13 13:39:02 +00:00
Eliminate the silly autosuggest_parsed_command_t class; make it just a function
This commit is contained in:
parent
0c79bb6e7c
commit
4df6b599b8
1 changed files with 112 additions and 113 deletions
225
highlight.cpp
225
highlight.cpp
|
@ -601,131 +601,122 @@ static int has_expand_reserved( const wchar_t *str )
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A class representing the result of parsing a command line, containing both the last command and its arguments. This is used by autosuggestions */
|
/* Parse a command line. Return by reference the last command, its arguments, and the offset in the string of the beginning of the last argument. This is used by autosuggestions */
|
||||||
class autosuggest_parsed_command_t {
|
static bool autosuggest_parse_command(const wcstring &str, wcstring *out_command, wcstring_list_t *out_arguments, int *out_last_arg_pos)
|
||||||
public:
|
{
|
||||||
/* The command, like "cd" */
|
if (str.empty())
|
||||||
wcstring command;
|
return false;
|
||||||
|
|
||||||
/* Arguments to the command */
|
wcstring cmd;
|
||||||
wcstring_list_t arguments;
|
wcstring_list_t args;
|
||||||
|
int arg_pos = -1;
|
||||||
|
|
||||||
/* Position in the string of the start of the last argument */
|
bool had_cmd = false;
|
||||||
int last_arg_pos;
|
tokenizer tok;
|
||||||
|
for (tok_init( &tok, str.c_str(), TOK_SQUASH_ERRORS); tok_has_next(&tok); tok_next(&tok))
|
||||||
autosuggest_parsed_command_t(const wcstring &str) {
|
{
|
||||||
if (str.empty())
|
int last_type = tok_last_type(&tok);
|
||||||
return;
|
|
||||||
|
|
||||||
wcstring cmd;
|
switch( last_type )
|
||||||
wcstring_list_t args;
|
|
||||||
int arg_pos = -1;
|
|
||||||
|
|
||||||
bool had_cmd = false;
|
|
||||||
tokenizer tok;
|
|
||||||
for (tok_init( &tok, str.c_str(), TOK_SQUASH_ERRORS); tok_has_next(&tok); tok_next(&tok))
|
|
||||||
{
|
{
|
||||||
int last_type = tok_last_type(&tok);
|
case TOK_STRING:
|
||||||
|
|
||||||
switch( last_type )
|
|
||||||
{
|
{
|
||||||
case TOK_STRING:
|
if( had_cmd )
|
||||||
{
|
{
|
||||||
if( had_cmd )
|
/* Parameter to the command */
|
||||||
|
args.push_back(tok_last(&tok));
|
||||||
|
arg_pos = tok_get_pos(&tok);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Command. First check that the command actually exists. */
|
||||||
|
wcstring local_cmd = tok_last( &tok );
|
||||||
|
bool expanded = expand_one(cmd, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_VARIABLES);
|
||||||
|
if (! expanded || has_expand_reserved(cmd.c_str()))
|
||||||
{
|
{
|
||||||
/* Parameter to the command */
|
/* We can't expand this cmd, ignore it */
|
||||||
args.push_back(tok_last(&tok));
|
|
||||||
arg_pos = tok_get_pos(&tok);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Command. First check that the command actually exists. */
|
bool is_subcommand = false;
|
||||||
wcstring local_cmd = tok_last( &tok );
|
int mark = tok_get_pos(&tok);
|
||||||
bool expanded = expand_one(cmd, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_VARIABLES);
|
|
||||||
if (! expanded || has_expand_reserved(cmd.c_str()))
|
if (parser_keywords_is_subcommand(cmd))
|
||||||
{
|
{
|
||||||
/* We can't expand this cmd, ignore it */
|
int sw;
|
||||||
}
|
tok_next( &tok );
|
||||||
else
|
|
||||||
{
|
|
||||||
bool is_subcommand = false;
|
|
||||||
int mark = tok_get_pos(&tok);
|
|
||||||
|
|
||||||
if (parser_keywords_is_subcommand(cmd))
|
sw = parser_keywords_is_switch( tok_last( &tok ) );
|
||||||
|
if( !parser_keywords_is_block( cmd ) &&
|
||||||
|
sw == ARG_SWITCH )
|
||||||
{
|
{
|
||||||
int sw;
|
/* It's an argument to the subcommand itself */
|
||||||
tok_next( &tok );
|
|
||||||
|
|
||||||
sw = parser_keywords_is_switch( tok_last( &tok ) );
|
|
||||||
if( !parser_keywords_is_block( cmd ) &&
|
|
||||||
sw == ARG_SWITCH )
|
|
||||||
{
|
|
||||||
/* It's an argument to the subcommand itself */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if( sw == ARG_SKIP )
|
|
||||||
mark = tok_get_pos( &tok );
|
|
||||||
is_subcommand = true;
|
|
||||||
}
|
|
||||||
tok_set_pos( &tok, mark );
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (!is_subcommand)
|
|
||||||
{
|
{
|
||||||
/* It's really a command */
|
if( sw == ARG_SKIP )
|
||||||
had_cmd = true;
|
mark = tok_get_pos( &tok );
|
||||||
cmd = local_cmd;
|
is_subcommand = true;
|
||||||
}
|
}
|
||||||
|
tok_set_pos( &tok, mark );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!is_subcommand)
|
||||||
|
{
|
||||||
|
/* It's really a command */
|
||||||
|
had_cmd = true;
|
||||||
|
cmd = local_cmd;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case TOK_REDIRECT_NOCLOB:
|
|
||||||
case TOK_REDIRECT_OUT:
|
|
||||||
case TOK_REDIRECT_IN:
|
|
||||||
case TOK_REDIRECT_APPEND:
|
|
||||||
case TOK_REDIRECT_FD:
|
|
||||||
{
|
|
||||||
if( !had_cmd )
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tok_next( &tok );
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
case TOK_PIPE:
|
|
||||||
case TOK_BACKGROUND:
|
|
||||||
case TOK_END:
|
|
||||||
{
|
|
||||||
had_cmd = false;
|
|
||||||
cmd.empty();
|
|
||||||
args.empty();
|
|
||||||
arg_pos = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case TOK_COMMENT:
|
|
||||||
case TOK_ERROR:
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case TOK_REDIRECT_NOCLOB:
|
||||||
|
case TOK_REDIRECT_OUT:
|
||||||
|
case TOK_REDIRECT_IN:
|
||||||
|
case TOK_REDIRECT_APPEND:
|
||||||
|
case TOK_REDIRECT_FD:
|
||||||
|
{
|
||||||
|
if( !had_cmd )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tok_next( &tok );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TOK_PIPE:
|
||||||
|
case TOK_BACKGROUND:
|
||||||
|
case TOK_END:
|
||||||
|
{
|
||||||
|
had_cmd = false;
|
||||||
|
cmd.empty();
|
||||||
|
args.empty();
|
||||||
|
arg_pos = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TOK_COMMENT:
|
||||||
|
case TOK_ERROR:
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tok_destroy( &tok );
|
}
|
||||||
|
tok_destroy( &tok );
|
||||||
/* Remember our command if we have one */
|
|
||||||
if (had_cmd) {
|
/* Remember our command if we have one */
|
||||||
this->command.swap(cmd);
|
if (had_cmd) {
|
||||||
this->arguments.swap(args);
|
if (out_command) out_command->swap(cmd);
|
||||||
this->last_arg_pos = arg_pos;
|
if (out_arguments) out_arguments->swap(args);
|
||||||
}
|
if (out_last_arg_pos) *out_last_arg_pos = arg_pos;
|
||||||
}
|
}
|
||||||
};
|
return had_cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool autosuggest_suggest_special(const wcstring &str, const wcstring &working_directory, wcstring &outSuggestion) {
|
bool autosuggest_suggest_special(const wcstring &str, const wcstring &working_directory, wcstring &outSuggestion) {
|
||||||
if (str.empty())
|
if (str.empty())
|
||||||
|
@ -735,12 +726,16 @@ bool autosuggest_suggest_special(const wcstring &str, const wcstring &working_di
|
||||||
|
|
||||||
|
|
||||||
/* Parse the string */
|
/* Parse the string */
|
||||||
const autosuggest_parsed_command_t parsed(str);
|
wcstring parsed_command;
|
||||||
|
wcstring_list_t parsed_arguments;
|
||||||
|
int parsed_last_arg_pos = -1;
|
||||||
|
if (! autosuggest_parse_command(str, &parsed_command, &parsed_arguments, &parsed_last_arg_pos))
|
||||||
|
return false;
|
||||||
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
if (parsed.command == L"cd" && ! parsed.arguments.empty()) {
|
if (parsed_command == L"cd" && ! parsed_arguments.empty()) {
|
||||||
/* We can possibly handle this specially */
|
/* We can possibly handle this specially */
|
||||||
wcstring dir = parsed.arguments.back();
|
wcstring dir = parsed_arguments.back();
|
||||||
wcstring suggested_path;
|
wcstring suggested_path;
|
||||||
|
|
||||||
/* We always return true because we recognized the command. This prevents us from falling back to dumber algorithms; for example we won't suggest a non-directory for the cd command. */
|
/* We always return true because we recognized the command. This prevents us from falling back to dumber algorithms; for example we won't suggest a non-directory for the cd command. */
|
||||||
|
@ -780,7 +775,7 @@ bool autosuggest_suggest_special(const wcstring &str, const wcstring &working_di
|
||||||
|
|
||||||
/* Success */
|
/* Success */
|
||||||
outSuggestion = str;
|
outSuggestion = str;
|
||||||
outSuggestion.erase(parsed.last_arg_pos);
|
outSuggestion.erase(parsed_last_arg_pos);
|
||||||
outSuggestion.append(suggested_path);
|
outSuggestion.append(suggested_path);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -794,13 +789,17 @@ bool autosuggest_special_validate_from_history(const wcstring &str, const wcstri
|
||||||
assert(outSuggestionOK != NULL);
|
assert(outSuggestionOK != NULL);
|
||||||
|
|
||||||
bool handled = false, suggestionOK = false;
|
bool handled = false, suggestionOK = false;
|
||||||
|
|
||||||
/* Parse the string */
|
/* Parse the string */
|
||||||
autosuggest_parsed_command_t parsed(str);
|
wcstring parsed_command;
|
||||||
|
wcstring_list_t parsed_arguments;
|
||||||
if (parsed.command == L"cd" && ! parsed.arguments.empty()) {
|
int parsed_last_arg_pos = -1;
|
||||||
|
if (! autosuggest_parse_command(str, &parsed_command, &parsed_arguments, &parsed_last_arg_pos))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (parsed_command == L"cd" && ! parsed_arguments.empty()) {
|
||||||
/* We can possibly handle this specially */
|
/* We can possibly handle this specially */
|
||||||
wcstring dir = parsed.arguments.back();
|
wcstring dir = parsed_arguments.back();
|
||||||
if (expand_one(dir, EXPAND_SKIP_CMDSUBST))
|
if (expand_one(dir, EXPAND_SKIP_CMDSUBST))
|
||||||
{
|
{
|
||||||
handled = true;
|
handled = true;
|
||||||
|
|
Loading…
Reference in a new issue