mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 12:53:13 +00:00
Fix to restore completions that use command substitution (like cd)
Fix to adopt the same escaping code for both completions and autosuggestions
This commit is contained in:
parent
90826e4031
commit
71a8d39372
5 changed files with 18 additions and 165 deletions
|
@ -1163,7 +1163,8 @@ void completer_t::complete_from_args( const wcstring &str,
|
|||
std::vector<completion_t> possible_comp;
|
||||
|
||||
bool is_autosuggest = (this->type == COMPLETE_AUTOSUGGEST);
|
||||
parser_t parser(is_autosuggest ? PARSER_TYPE_COMPLETIONS_ONLY : PARSER_TYPE_GENERAL);
|
||||
bool show_errors = ! is_autosuggest;
|
||||
parser_t parser(PARSER_TYPE_COMPLETIONS_ONLY, show_errors);
|
||||
|
||||
/* If type is COMPLETE_AUTOSUGGEST, it means we're on a background thread, so don't call proc_push_interactive */
|
||||
if (! is_autosuggest)
|
||||
|
|
|
@ -1419,7 +1419,7 @@ static void remove_internal_separator2( wcstring &s, int conv )
|
|||
|
||||
int expand_string( const wcstring &input, std::vector<completion_t> &output, expand_flags_t flags )
|
||||
{
|
||||
parser_t parser(PARSER_TYPE_ERRORS_ONLY);
|
||||
parser_t parser(PARSER_TYPE_ERRORS_ONLY, true /* show errors */);
|
||||
std::vector<completion_t> list1, list2;
|
||||
std::vector<completion_t> *in, *out;
|
||||
|
||||
|
|
|
@ -356,8 +356,9 @@ static const struct block_lookup_entry block_lookup[]=
|
|||
};
|
||||
|
||||
|
||||
parser_t::parser_t(enum parser_type_t type) :
|
||||
parser_t::parser_t(enum parser_type_t type, bool errors) :
|
||||
parser_type(type),
|
||||
show_errors(errors),
|
||||
error_code(0),
|
||||
err_pos(0),
|
||||
current_tokenizer(NULL),
|
||||
|
@ -374,7 +375,7 @@ parser_t &parser_t::principal_parser(void)
|
|||
{
|
||||
ASSERT_IS_NOT_FORKED_CHILD();
|
||||
ASSERT_IS_MAIN_THREAD();
|
||||
static parser_t parser(PARSER_TYPE_GENERAL);
|
||||
static parser_t parser(PARSER_TYPE_GENERAL, true);
|
||||
return parser;
|
||||
}
|
||||
|
||||
|
@ -762,12 +763,12 @@ void parser_t::print_errors_stderr()
|
|||
int parser_t::eval_args( const wchar_t *line, std::vector<completion_t> &args )
|
||||
{
|
||||
tokenizer tok;
|
||||
const bool show_errors = (this->parser_type == PARSER_TYPE_GENERAL || this->parser_type == PARSER_TYPE_ERRORS_ONLY);
|
||||
|
||||
expand_flags_t eflags = 0;
|
||||
if (! show_errors)
|
||||
eflags |= EXPAND_NO_DESCRIPTIONS;
|
||||
if (this->parser_type != PARSER_TYPE_GENERAL)
|
||||
// Completions need command substitution (for example, the cd completion uses this)
|
||||
if (this->parser_type != PARSER_TYPE_GENERAL && this->parser_type != PARSER_TYPE_COMPLETIONS_ONLY)
|
||||
eflags |= EXPAND_SKIP_CMDSUBST;
|
||||
|
||||
/*
|
||||
|
|
5
parser.h
5
parser.h
|
@ -269,6 +269,9 @@ class parser_t {
|
|||
enum parser_type_t parser_type;
|
||||
std::vector<block_t> blocks;
|
||||
|
||||
/** Whether or not we output errors */
|
||||
const bool show_errors;
|
||||
|
||||
/** Last error code */
|
||||
int error_code;
|
||||
|
||||
|
@ -330,7 +333,7 @@ class parser_t {
|
|||
static parser_t &principal_parser();
|
||||
|
||||
/** Create a parser of the given type */
|
||||
parser_t(enum parser_type_t type);
|
||||
parser_t(enum parser_type_t type, bool show_errors);
|
||||
|
||||
/** The current innermost block, allocated with new */
|
||||
block_t *current_block;
|
||||
|
|
162
reader.cpp
162
reader.cpp
|
@ -866,7 +866,7 @@ static void get_param( const wchar_t *cmd,
|
|||
int unfinished;
|
||||
|
||||
tokenizer tok;
|
||||
tok_init( &tok, cmd, TOK_ACCEPT_UNFINISHED );
|
||||
tok_init( &tok, cmd, TOK_ACCEPT_UNFINISHED | TOK_SQUASH_ERRORS );
|
||||
|
||||
for( ; tok_has_next( &tok ); tok_next( &tok ) )
|
||||
{
|
||||
|
@ -936,7 +936,7 @@ static void get_param( const wchar_t *cmd,
|
|||
\param inout_cursor_pos On input, the location of the cursor within the command line. On output, the new desired position.
|
||||
\return The completed string
|
||||
*/
|
||||
static wcstring completion_insert_helper(const wcstring &val_str, int flags, const wcstring &command_line, size_t *inout_cursor_pos)
|
||||
static wcstring completion_apply_to_command_line(const wcstring &val_str, int flags, const wcstring &command_line, size_t *inout_cursor_pos)
|
||||
{
|
||||
wchar_t *replaced;
|
||||
const wchar_t *val = val_str.c_str();
|
||||
|
@ -1067,151 +1067,13 @@ static wcstring completion_insert_helper(const wcstring &val_str, int flags, con
|
|||
static void completion_insert( const wchar_t *val, int flags )
|
||||
{
|
||||
size_t cursor = data->buff_pos;
|
||||
wcstring new_command_line = completion_insert_helper(val, flags, data->command_line, &cursor);
|
||||
wcstring new_command_line = completion_apply_to_command_line(val, flags, data->command_line, &cursor);
|
||||
reader_set_buffer(new_command_line, cursor);
|
||||
|
||||
/* Since we just inserted a completion, don't immediately do a new autosuggestion */
|
||||
data->suppress_autosuggestion = true;
|
||||
}
|
||||
|
||||
static void completion_insert_old( const wchar_t *val, int flags )
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
wchar_t *replaced;
|
||||
|
||||
wchar_t quote;
|
||||
bool add_space = !(flags & COMPLETE_NO_SPACE);
|
||||
bool do_replace = !!(flags & COMPLETE_NO_CASE);
|
||||
bool do_escape = !(flags & COMPLETE_DONT_ESCAPE);
|
||||
|
||||
// debug( 0, L"Insert completion %ls with flags %d", val, flags);
|
||||
|
||||
if( do_replace )
|
||||
{
|
||||
|
||||
int move_cursor;
|
||||
const wchar_t *begin, *end;
|
||||
wchar_t *escaped;
|
||||
|
||||
const wchar_t *buff = data->command_line.c_str();
|
||||
parse_util_token_extent( buff, data->buff_pos, &begin, 0, 0, 0 );
|
||||
end = buff + data->buff_pos;
|
||||
|
||||
wcstring sb(buff, begin - buff);
|
||||
|
||||
if( do_escape )
|
||||
{
|
||||
escaped = escape( val, ESCAPE_ALL | ESCAPE_NO_QUOTED );
|
||||
sb.append( escaped );
|
||||
move_cursor = wcslen(escaped);
|
||||
free( escaped );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( val );
|
||||
move_cursor = wcslen(val);
|
||||
}
|
||||
|
||||
|
||||
if( add_space )
|
||||
{
|
||||
sb.append( L" " );
|
||||
move_cursor += 1;
|
||||
}
|
||||
|
||||
sb.append( end );
|
||||
|
||||
reader_set_buffer( sb, (begin-buff)+move_cursor );
|
||||
|
||||
reader_super_highlight_me_plenty( data->buff_pos );
|
||||
reader_repaint();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if( do_escape )
|
||||
{
|
||||
get_param( data->command_line.c_str(),
|
||||
data->buff_pos,
|
||||
"e,
|
||||
0, 0, 0 );
|
||||
|
||||
if( quote == L'\0' )
|
||||
{
|
||||
replaced = escape( val, ESCAPE_ALL | ESCAPE_NO_QUOTED );
|
||||
}
|
||||
else
|
||||
{
|
||||
int unescapable=0;
|
||||
|
||||
const wchar_t *pin;
|
||||
wchar_t *pout;
|
||||
|
||||
replaced = pout =
|
||||
(wchar_t *)malloc( sizeof(wchar_t)*(wcslen(val) + 1) );
|
||||
|
||||
for( pin=val; *pin; pin++ )
|
||||
{
|
||||
switch( *pin )
|
||||
{
|
||||
case L'\n':
|
||||
case L'\t':
|
||||
case L'\b':
|
||||
case L'\r':
|
||||
unescapable=1;
|
||||
break;
|
||||
default:
|
||||
*pout++ = *pin;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( unescapable )
|
||||
{
|
||||
free( replaced );
|
||||
wchar_t *tmp = escape( val, ESCAPE_ALL | ESCAPE_NO_QUOTED );
|
||||
replaced = wcsdupcat( L" ", tmp );
|
||||
free( tmp);
|
||||
replaced[0]=quote;
|
||||
}
|
||||
else
|
||||
*pout = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
replaced = wcsdup(val);
|
||||
}
|
||||
|
||||
if( insert_string( replaced ) )
|
||||
{
|
||||
/*
|
||||
Print trailing space since this is the only completion
|
||||
*/
|
||||
if( add_space )
|
||||
{
|
||||
|
||||
if( quote &&
|
||||
(data->command_line.c_str()[data->buff_pos] != quote ) )
|
||||
{
|
||||
/*
|
||||
This is a quoted parameter, first print a quote
|
||||
*/
|
||||
insert_char( quote );
|
||||
}
|
||||
insert_char( L' ' );
|
||||
}
|
||||
|
||||
/* Since we just inserted a completion, don't immediately do a new autosuggestion */
|
||||
data->suppress_autosuggestion = true;
|
||||
}
|
||||
|
||||
free(replaced);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Run the fish_pager command to display the completion list. If the
|
||||
fish_pager outputs any text, it is inserted into the input
|
||||
|
@ -1446,22 +1308,8 @@ struct autosuggestion_context_t {
|
|||
complete(search_string, completions, COMPLETE_AUTOSUGGEST, &this->commands_to_load);
|
||||
if (! completions.empty()) {
|
||||
const completion_t &comp = completions.at(0);
|
||||
this->autosuggestion = this->search_string;
|
||||
|
||||
if (comp.flags & COMPLETE_NO_CASE) {
|
||||
/* The completion contains the whole current token, not merely a suffix */
|
||||
|
||||
const wchar_t *begin;
|
||||
const wchar_t *buff = data->command_line.c_str();
|
||||
parse_util_token_extent( buff, data->buff_pos, &begin, 0, 0, 0 );
|
||||
|
||||
size_t start = begin - buff;
|
||||
assert(data->buff_pos >= start);
|
||||
this->autosuggestion.replace(start, data->buff_pos - start, comp.completion);
|
||||
} else {
|
||||
/* The completion contains only a suffix */
|
||||
this->autosuggestion.append(comp.completion);
|
||||
}
|
||||
size_t cursor = this->cursor_pos;
|
||||
this->autosuggestion = completion_apply_to_command_line(comp.completion.c_str(), comp.flags, this->search_string, &cursor);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue