diff --git a/complete.cpp b/complete.cpp index be06ab310..ea83af2bd 100644 --- a/complete.cpp +++ b/complete.cpp @@ -1163,7 +1163,8 @@ void completer_t::complete_from_args( const wcstring &str, std::vector 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) diff --git a/expand.cpp b/expand.cpp index 905f7f984..c6e851912 100644 --- a/expand.cpp +++ b/expand.cpp @@ -1419,7 +1419,7 @@ static void remove_internal_separator2( wcstring &s, int conv ) int expand_string( const wcstring &input, std::vector &output, expand_flags_t flags ) { - parser_t parser(PARSER_TYPE_ERRORS_ONLY); + parser_t parser(PARSER_TYPE_ERRORS_ONLY, true /* show errors */); std::vector list1, list2; std::vector *in, *out; diff --git a/parser.cpp b/parser.cpp index 513bf316c..3b4beb0ff 100644 --- a/parser.cpp +++ b/parser.cpp @@ -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 &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; /* diff --git a/parser.h b/parser.h index 5ce832921..ca97fc733 100644 --- a/parser.h +++ b/parser.h @@ -269,9 +269,12 @@ class parser_t { enum parser_type_t parser_type; std::vector blocks; + /** Whether or not we output errors */ + const bool show_errors; + /** Last error code */ int error_code; - + /** Position of last error */ int err_pos; @@ -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; diff --git a/reader.cpp b/reader.cpp index 18ecfdca3..0beefbd06 100644 --- a/reader.cpp +++ b/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; }