mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-13 13:39:02 +00:00
More work towards autosuggesting completions
This commit is contained in:
parent
5ea78f55f2
commit
38e40862fe
14 changed files with 184 additions and 140 deletions
|
@ -261,7 +261,7 @@ static void builtin_print_help( parser_t &parser, const wchar_t *cmd, wcstring &
|
|||
|
||||
screen_height = common_get_height();
|
||||
lines = count_char( str, L'\n' );
|
||||
if( !is_interactive || (lines > 2*screen_height/3) )
|
||||
if( !get_is_interactive() || (lines > 2*screen_height/3) )
|
||||
{
|
||||
wchar_t *pos;
|
||||
int cut=0;
|
||||
|
@ -2569,7 +2569,7 @@ static int builtin_cd( parser_t &parser, wchar_t **argv )
|
|||
}
|
||||
|
||||
|
||||
if( !is_interactive )
|
||||
if( !get_is_interactive() )
|
||||
{
|
||||
stderr_buffer.append(parser.current_line());
|
||||
}
|
||||
|
@ -2599,7 +2599,7 @@ static int builtin_cd( parser_t &parser, wchar_t **argv )
|
|||
dir );
|
||||
}
|
||||
|
||||
if( !is_interactive )
|
||||
if( !get_is_interactive() )
|
||||
{
|
||||
stderr_buffer.append(parser.current_line());
|
||||
}
|
||||
|
|
|
@ -2062,6 +2062,7 @@ void assert_is_main_thread(const char *who)
|
|||
if (! is_main_thread()) {
|
||||
fprintf(stderr, "Warning: %s called off of main thread. Break on debug_thread_error to debug.\n", who);
|
||||
debug_thread_error();
|
||||
sleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
122
complete.cpp
122
complete.cpp
|
@ -143,7 +143,7 @@ typedef struct complete_entry_opt
|
|||
/** True if old style long options are used */
|
||||
int old_mode;
|
||||
/** Completion flags */
|
||||
int flags;
|
||||
complete_flags_t flags;
|
||||
|
||||
const wchar_t *localized_desc() const
|
||||
{
|
||||
|
@ -198,6 +198,9 @@ class completer_t {
|
|||
{
|
||||
}
|
||||
|
||||
bool empty() const { return completions.empty(); }
|
||||
const std::vector<completion_t> &get_completions(void) { return completions; }
|
||||
|
||||
bool try_complete_variable( const wcstring &str );
|
||||
bool try_complete_user( const wcstring &str );
|
||||
|
||||
|
@ -206,15 +209,14 @@ class completer_t {
|
|||
const wcstring &str,
|
||||
bool use_switches);
|
||||
|
||||
void complete_param_expand( const wcstring &str, bool do_file);
|
||||
void complete_param_expand(const wcstring &str, bool do_file);
|
||||
|
||||
void complete_cmd( const wcstring &str,
|
||||
bool use_function,
|
||||
bool use_builtin,
|
||||
bool use_command);
|
||||
bool use_function,
|
||||
bool use_builtin,
|
||||
bool use_command);
|
||||
|
||||
bool empty() const { return completions.empty(); }
|
||||
const std::vector<completion_t> &get_completions(void) { return completions; }
|
||||
bool complete_variable(const wcstring &str, int start_offset);
|
||||
|
||||
};
|
||||
|
||||
|
@ -244,7 +246,7 @@ void completion_autoload_t::command_removed(const wcstring &cmd) {
|
|||
Create a new completion entry
|
||||
|
||||
*/
|
||||
void completion_allocate(std::vector<completion_t> &completions, const wcstring &comp, const wcstring &desc, int flags)
|
||||
void completion_allocate(std::vector<completion_t> &completions, const wcstring &comp, const wcstring &desc, complete_flags_t flags)
|
||||
{
|
||||
completions.push_back(completion_t(comp, desc, flags));
|
||||
}
|
||||
|
@ -362,7 +364,7 @@ void complete_add( const wchar_t *cmd,
|
|||
const wchar_t *condition,
|
||||
const wchar_t *comp,
|
||||
const wchar_t *desc,
|
||||
int flags )
|
||||
complete_flags_t flags )
|
||||
{
|
||||
CHECK( cmd, );
|
||||
|
||||
|
@ -757,7 +759,7 @@ static void complete_strings( std::vector<completion_t> &comp_out,
|
|||
const wchar_t *desc,
|
||||
const wchar_t *(*desc_func)(const wcstring &),
|
||||
std::vector<completion_t> &possible_comp,
|
||||
int flags )
|
||||
complete_flags_t flags )
|
||||
{
|
||||
wcstring tmp = wc_escaped;
|
||||
if (! expand_one(tmp, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_WILDCARDS))
|
||||
|
@ -1090,21 +1092,24 @@ static void complete_from_args( const wcstring &str,
|
|||
const wcstring &args,
|
||||
const wcstring &desc,
|
||||
std::vector<completion_t> &comp_out,
|
||||
int flags )
|
||||
complete_type_t type,
|
||||
complete_flags_t flags )
|
||||
{
|
||||
/* If type is COMPLETE_AUTOSUGGEST, it means we're on a background thread, so don't call proc_push_interactive */
|
||||
|
||||
std::vector<completion_t> possible_comp;
|
||||
|
||||
parser_t parser(PARSER_TYPE_COMPLETIONS_ONLY);
|
||||
proc_push_interactive(0);
|
||||
|
||||
if (type != COMPLETE_AUTOSUGGEST)
|
||||
proc_push_interactive(0);
|
||||
|
||||
parser.eval_args( args.c_str(), possible_comp );
|
||||
|
||||
proc_pop_interactive();
|
||||
if (type != COMPLETE_AUTOSUGGEST)
|
||||
proc_pop_interactive();
|
||||
|
||||
complete_strings( comp_out, str.c_str(), desc.c_str(), 0, possible_comp, flags );
|
||||
|
||||
// al_foreach( &possible_comp, &free );
|
||||
// al_destroy( &possible_comp );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1249,7 +1254,7 @@ static int complete_param( const wchar_t *cmd_orig,
|
|||
{
|
||||
use_common &= ((o->result_mode & NO_COMMON )==0);
|
||||
use_files &= ((o->result_mode & NO_FILES )==0);
|
||||
complete_from_args( arg, o->comp, o->localized_desc(), comp_out, o->flags );
|
||||
complete_from_args( arg, o->comp, o->localized_desc(), comp_out, type, o->flags );
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1273,7 +1278,7 @@ static int complete_param( const wchar_t *cmd_orig,
|
|||
old_style_match = 1;
|
||||
use_common &= ((o->result_mode & NO_COMMON )==0);
|
||||
use_files &= ((o->result_mode & NO_FILES )==0);
|
||||
complete_from_args( str, o->comp, o->localized_desc(), comp_out, o->flags );
|
||||
complete_from_args( str, o->comp, o->localized_desc(), comp_out, type, o->flags );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1300,7 +1305,7 @@ static int complete_param( const wchar_t *cmd_orig,
|
|||
{
|
||||
use_common &= ((o->result_mode & NO_COMMON )==0);
|
||||
use_files &= ((o->result_mode & NO_FILES )==0);
|
||||
complete_from_args( str, o->comp.c_str(), o->localized_desc(), comp_out, o->flags );
|
||||
complete_from_args( str, o->comp.c_str(), o->localized_desc(), comp_out, type, o->flags );
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1326,7 +1331,7 @@ static int complete_param( const wchar_t *cmd_orig,
|
|||
if( (o->short_opt == L'\0' ) && (o->long_opt[0]==L'\0'))
|
||||
{
|
||||
use_files &= ((o->result_mode & NO_FILES )==0);
|
||||
complete_from_args( str, o->comp, o->localized_desc(), comp_out, o->flags );
|
||||
complete_from_args( str, o->comp, o->localized_desc(), comp_out, type, o->flags );
|
||||
}
|
||||
|
||||
if( wcslen(str) > 0 && use_switches )
|
||||
|
@ -1370,7 +1375,7 @@ static int complete_param( const wchar_t *cmd_orig,
|
|||
int req_arg=0; /* Does this switch _require_ an argument */
|
||||
|
||||
int offset = 0;
|
||||
int flags = 0;
|
||||
complete_flags_t flags = 0;
|
||||
|
||||
|
||||
if( match )
|
||||
|
@ -1426,7 +1431,6 @@ bool completer_t::complete_param( const wcstring &cmd_orig, const wcstring &popt
|
|||
static void complete_param_expand( const wchar_t *str, std::vector<completion_t> &comp_out, int do_file, complete_type_t type )
|
||||
{
|
||||
const wchar_t *comp_str;
|
||||
int flags;
|
||||
|
||||
if( (wcsncmp( str, L"--", 2 )) == 0 && (comp_str = wcschr(str, L'=' ) ) )
|
||||
{
|
||||
|
@ -1437,7 +1441,7 @@ static void complete_param_expand( const wchar_t *str, std::vector<completion_t>
|
|||
comp_str = str;
|
||||
}
|
||||
|
||||
flags = EXPAND_SKIP_CMDSUBST | ACCEPT_INCOMPLETE;
|
||||
expand_flags_t flags = EXPAND_SKIP_CMDSUBST | ACCEPT_INCOMPLETE;
|
||||
|
||||
if (! do_file)
|
||||
flags |= EXPAND_SKIP_WILDCARDS;
|
||||
|
@ -1464,11 +1468,13 @@ void completer_t::complete_param_expand( const wcstring &str, bool do_file)
|
|||
*/
|
||||
static int complete_variable( const wchar_t *whole_var,
|
||||
int start_offset,
|
||||
std::vector<completion_t> &comp_list )
|
||||
std::vector<completion_t> &comp_list,
|
||||
complete_type_t type)
|
||||
{
|
||||
const wchar_t *var = &whole_var[start_offset];
|
||||
int varlen = wcslen( var );
|
||||
int res = 0;
|
||||
bool wants_description = (type != COMPLETE_AUTOSUGGEST);
|
||||
|
||||
const wcstring_list_t names = env_get_names(0);
|
||||
for( size_t i=0; i<names.size(); i++ )
|
||||
|
@ -1489,34 +1495,39 @@ static int complete_variable( const wchar_t *whole_var,
|
|||
|
||||
if( match || match_no_case )
|
||||
{
|
||||
const env_var_t value_unescaped = env_get_string( env_name );
|
||||
if( !value_unescaped.missing() )
|
||||
{
|
||||
wcstring comp;
|
||||
int flags = 0;
|
||||
int offset = 0;
|
||||
wcstring comp;
|
||||
int flags = 0;
|
||||
int offset = 0;
|
||||
|
||||
if( match )
|
||||
{
|
||||
comp.append(env_name.c_str() + varlen);
|
||||
offset = varlen;
|
||||
}
|
||||
else
|
||||
{
|
||||
comp.append(whole_var, start_offset);
|
||||
comp.append(env_name);
|
||||
flags = COMPLETE_NO_CASE | COMPLETE_DONT_ESCAPE;
|
||||
}
|
||||
if( match )
|
||||
{
|
||||
comp.append(env_name.c_str() + varlen);
|
||||
offset = varlen;
|
||||
}
|
||||
else
|
||||
{
|
||||
comp.append(whole_var, start_offset);
|
||||
comp.append(env_name);
|
||||
flags = COMPLETE_NO_CASE | COMPLETE_DONT_ESCAPE;
|
||||
}
|
||||
|
||||
wcstring value = expand_escape_variable( value_unescaped );
|
||||
wcstring desc;
|
||||
if (wants_description)
|
||||
{
|
||||
env_var_t value_unescaped = env_get_string( env_name );
|
||||
if (value_unescaped.missing())
|
||||
continue;
|
||||
|
||||
wcstring desc = format_string(COMPLETE_VAR_DESC_VAL, value.c_str());
|
||||
completion_allocate( comp_list,
|
||||
comp.c_str(),
|
||||
desc.c_str(),
|
||||
flags );
|
||||
res =1;
|
||||
}
|
||||
wcstring value = expand_escape_variable( value_unescaped );
|
||||
if (type != COMPLETE_AUTOSUGGEST)
|
||||
desc = format_string(COMPLETE_VAR_DESC_VAL, value.c_str());
|
||||
}
|
||||
|
||||
completion_allocate( comp_list,
|
||||
comp.c_str(),
|
||||
desc.c_str(),
|
||||
flags );
|
||||
res =1;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1524,13 +1535,18 @@ static int complete_variable( const wchar_t *whole_var,
|
|||
return res;
|
||||
}
|
||||
|
||||
bool completer_t::complete_variable(const wcstring &str, int start_offset)
|
||||
{
|
||||
return ::complete_variable(str.c_str(), start_offset, this->completions, this->type);
|
||||
}
|
||||
|
||||
/**
|
||||
Search the specified string for the \$ sign. If found, try to
|
||||
complete as an environment variable.
|
||||
|
||||
\return 0 if unable to complete, 1 otherwise
|
||||
*/
|
||||
static int try_complete_variable( const wchar_t *cmd, std::vector<completion_t> &comp )
|
||||
static int try_complete_variable( const wchar_t *cmd, std::vector<completion_t> &comp, complete_type_t type )
|
||||
{
|
||||
int len = wcslen( cmd );
|
||||
int i;
|
||||
|
@ -1540,7 +1556,7 @@ static int try_complete_variable( const wchar_t *cmd, std::vector<completion_t>
|
|||
if( cmd[i] == L'$' )
|
||||
{
|
||||
/* wprintf( L"Var prefix \'%ls\'\n", &cmd[i+1] );*/
|
||||
return complete_variable( cmd, i+1, comp );
|
||||
return complete_variable( cmd, i+1, comp, type);
|
||||
}
|
||||
if( !isalnum(cmd[i]) && cmd[i]!=L'_' )
|
||||
{
|
||||
|
@ -1552,7 +1568,7 @@ static int try_complete_variable( const wchar_t *cmd, std::vector<completion_t>
|
|||
|
||||
bool completer_t::try_complete_variable( const wcstring &str )
|
||||
{
|
||||
return ::try_complete_variable(str.c_str(), this->completions) > 0;
|
||||
return ::try_complete_variable(str.c_str(), this->completions, this->type) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1910,7 +1926,7 @@ void complete( const wchar_t *cmd, std::vector<completion_t> &comp, complete_typ
|
|||
|
||||
if( !done )
|
||||
{
|
||||
if( try_complete_variable( tok_begin, comp ) || try_complete_user( tok_begin, comp ))
|
||||
if( try_complete_variable( tok_begin, comp, type ) || try_complete_user( tok_begin, comp ))
|
||||
{
|
||||
done=1;
|
||||
}
|
||||
|
|
58
complete.h
58
complete.h
|
@ -67,39 +67,41 @@
|
|||
*/
|
||||
#define PROG_COMPLETE_SEP L'\t'
|
||||
|
||||
/**
|
||||
Do not insert space afterwards if this is the only completion. (The
|
||||
default is to try insert a space)
|
||||
*/
|
||||
#define COMPLETE_NO_SPACE 1
|
||||
enum {
|
||||
/**
|
||||
Do not insert space afterwards if this is the only completion. (The
|
||||
default is to try insert a space)
|
||||
*/
|
||||
COMPLETE_NO_SPACE = 1 << 0,
|
||||
|
||||
/**
|
||||
This compeltion is case insensitive.
|
||||
/**
|
||||
This compeltion is case insensitive.
|
||||
|
||||
Warning: The contents of the completion_t structure is actually
|
||||
different if this flag is set! Specifically, the completion string
|
||||
contains the _entire_ completion token, not only the current
|
||||
*/
|
||||
#define COMPLETE_NO_CASE 2
|
||||
Warning: The contents of the completion_t structure is actually
|
||||
different if this flag is set! Specifically, the completion string
|
||||
contains the _entire_ completion token, not only the current
|
||||
*/
|
||||
COMPLETE_NO_CASE = 1 << 1,
|
||||
|
||||
/**
|
||||
This compeltion is the whole argument, not just the remainder. This
|
||||
flag must never be set on completions returned from the complete()
|
||||
function. It is strictly for internal use in the completion code.
|
||||
*/
|
||||
#define COMPLETE_WHOLE_ARGUMENT 4
|
||||
/**
|
||||
This compeltion is the whole argument, not just the remainder. This
|
||||
flag must never be set on completions returned from the complete()
|
||||
function. It is strictly for internal use in the completion code.
|
||||
*/
|
||||
COMPLETE_WHOLE_ARGUMENT = 1 << 2,
|
||||
|
||||
/**
|
||||
This completion may or may not want a space at the end - guess by
|
||||
checking the last character of the completion.
|
||||
*/
|
||||
#define COMPLETE_AUTO_SPACE 8
|
||||
|
||||
/**
|
||||
This completion should be inserted as-is, without escaping.
|
||||
*/
|
||||
#define COMPLETE_DONT_ESCAPE 16
|
||||
/**
|
||||
This completion may or may not want a space at the end - guess by
|
||||
checking the last character of the completion.
|
||||
*/
|
||||
COMPLETE_AUTO_SPACE = 1 << 3,
|
||||
|
||||
/**
|
||||
This completion should be inserted as-is, without escaping.
|
||||
*/
|
||||
COMPLETE_DONT_ESCAPE = 1 << 4
|
||||
};
|
||||
typedef int complete_flags_t;
|
||||
|
||||
|
||||
class completion_t
|
||||
|
|
17
env.cpp
17
env.cpp
|
@ -97,7 +97,7 @@ struct var_entry_t
|
|||
/**
|
||||
Struct representing one level in the function variable stack
|
||||
*/
|
||||
typedef struct env_node
|
||||
struct env_node_t
|
||||
{
|
||||
/**
|
||||
Variable table
|
||||
|
@ -118,12 +118,11 @@ typedef struct env_node
|
|||
/**
|
||||
Pointer to next level
|
||||
*/
|
||||
struct env_node *next;
|
||||
struct env_node_t *next;
|
||||
|
||||
|
||||
env_node() : new_scope(0), exportv(0), next(NULL) { }
|
||||
}
|
||||
env_node_t;
|
||||
env_node_t() : new_scope(0), exportv(0), next(NULL) { }
|
||||
};
|
||||
|
||||
class variable_entry_t {
|
||||
bool exportv; /**< Whether the variable should be exported */
|
||||
|
@ -337,7 +336,7 @@ static void handle_locale()
|
|||
|
||||
dcgettext( "fish", "Changing language to English", LC_MESSAGES );
|
||||
|
||||
if( is_interactive )
|
||||
if( get_is_interactive() )
|
||||
{
|
||||
debug( 0, _(L"Changing language to English") );
|
||||
}
|
||||
|
@ -1479,6 +1478,8 @@ static void add_key_to_string_set(const std::map<wcstring, var_entry_t*> &envs,
|
|||
|
||||
wcstring_list_t env_get_names( int flags )
|
||||
{
|
||||
scoped_lock lock(env_lock);
|
||||
|
||||
wcstring_list_t result;
|
||||
std::set<wcstring> names;
|
||||
int show_local = flags & ENV_LOCAL;
|
||||
|
@ -1489,9 +1490,9 @@ wcstring_list_t env_get_names( int flags )
|
|||
|
||||
|
||||
get_names_show_exported =
|
||||
flags & ENV_EXPORT|| (!(flags & ENV_UNEXPORT));
|
||||
(flags & ENV_EXPORT) || !(flags & ENV_UNEXPORT);
|
||||
get_names_show_unexported =
|
||||
flags & ENV_UNEXPORT|| (!(flags & ENV_EXPORT));
|
||||
(flags & ENV_UNEXPORT) || !(flags & ENV_EXPORT);
|
||||
|
||||
if( !show_local && !show_global && !show_universal )
|
||||
{
|
||||
|
|
4
env.h
4
env.h
|
@ -93,7 +93,7 @@ int env_set( const wchar_t *key,
|
|||
valid until the next call to env_get(), env_set(), env_push() or
|
||||
env_pop() takes place.
|
||||
*/
|
||||
const wchar_t *env_get( const wchar_t *key );
|
||||
//const wchar_t *env_get( const wchar_t *key );
|
||||
|
||||
class env_var_t : public wcstring {
|
||||
private:
|
||||
|
@ -153,7 +153,7 @@ void env_pop();
|
|||
char **env_export_arr( int recalc );
|
||||
|
||||
/**
|
||||
Insert all variable names into l. These are not copies of the strings and should not be freed after use.
|
||||
Returns all variable names.
|
||||
*/
|
||||
wcstring_list_t env_get_names( int flags );
|
||||
|
||||
|
|
13
expand.cpp
13
expand.cpp
|
@ -145,11 +145,11 @@ int expand_is_clean( const wchar_t *in )
|
|||
/**
|
||||
Return the environment variable value for the string starting at \c in.
|
||||
*/
|
||||
static const wchar_t* expand_var(const wchar_t *in)
|
||||
static env_var_t expand_var(const wchar_t *in)
|
||||
{
|
||||
if( !in )
|
||||
return 0;
|
||||
return env_get( in );
|
||||
return env_var_t::missing_var();
|
||||
return env_get_string( in );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -818,7 +818,6 @@ static int expand_variables_internal( parser_t &parser, wchar_t * const in, std:
|
|||
int start_pos = i+1;
|
||||
int stop_pos;
|
||||
int var_len;
|
||||
const wchar_t * var_val;
|
||||
int is_single = (c==VARIABLE_EXPAND_SINGLE);
|
||||
int var_name_stop_pos;
|
||||
|
||||
|
@ -849,9 +848,9 @@ static int expand_variables_internal( parser_t &parser, wchar_t * const in, std:
|
|||
}
|
||||
|
||||
var_tmp.append(in + start_pos, var_len);
|
||||
var_val = expand_var(var_tmp.c_str() );
|
||||
env_var_t var_val = expand_var(var_tmp.c_str() );
|
||||
|
||||
if( var_val )
|
||||
if( ! var_val.missing() )
|
||||
{
|
||||
int all_vars=1;
|
||||
wcstring_list_t var_item_list;
|
||||
|
@ -873,7 +872,7 @@ static int expand_variables_internal( parser_t &parser, wchar_t * const in, std:
|
|||
|
||||
if( is_ok )
|
||||
{
|
||||
tokenize_variable_array( var_val, var_item_list );
|
||||
tokenize_variable_array( var_val.c_str(), var_item_list );
|
||||
|
||||
if( !all_vars )
|
||||
{
|
||||
|
|
2
kill.cpp
2
kill.cpp
|
@ -266,7 +266,7 @@ const wchar_t *kill_yank()
|
|||
void kill_sanity_check()
|
||||
{
|
||||
int i;
|
||||
if( is_interactive )
|
||||
if( get_is_interactive() )
|
||||
{
|
||||
/* Test that the kill-ring is consistent */
|
||||
if( kill_current != 0 )
|
||||
|
|
46
parser.cpp
46
parser.cpp
|
@ -762,6 +762,8 @@ 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);
|
||||
|
||||
/*
|
||||
eval_args may be called while evaulating another command, so we
|
||||
save the previous tokenizer and restore it on exit
|
||||
|
@ -773,11 +775,14 @@ int parser_t::eval_args( const wchar_t *line, std::vector<completion_t> &args )
|
|||
CHECK( line, 1 );
|
||||
// CHECK( args, 1 );
|
||||
|
||||
proc_push_interactive(0);
|
||||
// PCA we need to suppress calling proc_push_interactive off of the main thread. I'm not sure exactly what it does.
|
||||
if (this->parser_type == PARSER_TYPE_GENERAL)
|
||||
proc_push_interactive(0);
|
||||
|
||||
current_tokenizer = &tok;
|
||||
current_tokenizer_pos = 0;
|
||||
|
||||
tok_init( &tok, line, 0 );
|
||||
tok_init( &tok, line, (show_errors ? 0 : TOK_SQUASH_ERRORS) );
|
||||
error_code=0;
|
||||
|
||||
for(;do_loop && tok_has_next( &tok) ; tok_next( &tok ) )
|
||||
|
@ -794,7 +799,7 @@ int parser_t::eval_args( const wchar_t *line, std::vector<completion_t> &args )
|
|||
DIE_MEM();
|
||||
}
|
||||
|
||||
if( expand_string( tmp, args, 0 ) == EXPAND_ERROR )
|
||||
if( expand_string( tmp, args, (show_errors ? 0 : EXPAND_NO_DESCRIPTIONS) ) == EXPAND_ERROR )
|
||||
{
|
||||
err_pos=tok_get_pos( &tok );
|
||||
do_loop=0;
|
||||
|
@ -809,10 +814,11 @@ int parser_t::eval_args( const wchar_t *line, std::vector<completion_t> &args )
|
|||
|
||||
case TOK_ERROR:
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( &tok ),
|
||||
TOK_ERR_MSG,
|
||||
tok_last(&tok) );
|
||||
if (show_errors)
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( &tok ),
|
||||
TOK_ERR_MSG,
|
||||
tok_last(&tok) );
|
||||
|
||||
do_loop=0;
|
||||
break;
|
||||
|
@ -820,10 +826,11 @@ int parser_t::eval_args( const wchar_t *line, std::vector<completion_t> &args )
|
|||
|
||||
default:
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( &tok ),
|
||||
UNEXPECTED_TOKEN_ERR_MSG,
|
||||
tok_get_desc( tok_last_type(&tok)) );
|
||||
if (show_errors)
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( &tok ),
|
||||
UNEXPECTED_TOKEN_ERR_MSG,
|
||||
tok_get_desc( tok_last_type(&tok)) );
|
||||
|
||||
do_loop=0;
|
||||
break;
|
||||
|
@ -831,13 +838,16 @@ int parser_t::eval_args( const wchar_t *line, std::vector<completion_t> &args )
|
|||
}
|
||||
}
|
||||
|
||||
this->print_errors_stderr();
|
||||
if (show_errors)
|
||||
this->print_errors_stderr();
|
||||
|
||||
tok_destroy( &tok );
|
||||
|
||||
current_tokenizer=previous_tokenizer;
|
||||
current_tokenizer_pos = previous_pos;
|
||||
proc_pop_interactive();
|
||||
|
||||
if (this->parser_type == PARSER_TYPE_GENERAL)
|
||||
proc_pop_interactive();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -1114,7 +1124,7 @@ const wchar_t *parser_t::current_line()
|
|||
/**
|
||||
If we are not going to print a stack trace, at least print the line number and filename
|
||||
*/
|
||||
if( !is_interactive || is_function() )
|
||||
if( !get_is_interactive() || is_function() )
|
||||
{
|
||||
int prev_width = my_wcswidth( lineinfo.c_str() );
|
||||
if( file )
|
||||
|
@ -1139,7 +1149,7 @@ const wchar_t *parser_t::current_line()
|
|||
Skip printing character position if we are in interactive mode
|
||||
and the error was on the first character of the line.
|
||||
*/
|
||||
if( !is_interactive || is_function() || (current_line_width!=0) )
|
||||
if( !get_is_interactive() || is_function() || (current_line_width!=0) )
|
||||
{
|
||||
// Workaround since it seems impossible to print 0 copies of a character using %*lc
|
||||
if( offset+current_line_width )
|
||||
|
@ -1559,7 +1569,7 @@ void parser_t::parse_job_argument_list( process_t *p,
|
|||
{
|
||||
job_set_flag( j, JOB_WILDCARD_ERROR, 1 );
|
||||
proc_set_last_status( STATUS_UNMATCHED_WILDCARD );
|
||||
if( is_interactive && !is_block )
|
||||
if( get_is_interactive() && !is_block )
|
||||
{
|
||||
int tmp;
|
||||
|
||||
|
@ -2210,11 +2220,11 @@ void parser_t::eval_job( tokenizer *tok )
|
|||
job_set_flag( j, JOB_SKIP_NOTIFICATION, is_subshell \
|
||||
|| is_block \
|
||||
|| is_event \
|
||||
|| (!is_interactive));
|
||||
|| (!get_is_interactive()));
|
||||
|
||||
current_block->job = j;
|
||||
|
||||
if( is_interactive )
|
||||
if( get_is_interactive() )
|
||||
{
|
||||
if( tcgetattr (0, &j->tmodes) )
|
||||
{
|
||||
|
|
9
proc.cpp
9
proc.cpp
|
@ -101,7 +101,6 @@ job_list_t &job_list(void) {
|
|||
return s_job_list;
|
||||
}
|
||||
|
||||
int is_interactive=-1;
|
||||
int is_interactive_session=0;
|
||||
int is_subshell=0;
|
||||
int is_block=0;
|
||||
|
@ -112,6 +111,12 @@ pid_t proc_last_bg_pid = 0;
|
|||
int job_control_mode = JOB_CONTROL_INTERACTIVE;
|
||||
int no_exec=0;
|
||||
|
||||
static int is_interactive = -1;
|
||||
|
||||
int get_is_interactive(void) {
|
||||
ASSERT_IS_MAIN_THREAD();
|
||||
return is_interactive;
|
||||
}
|
||||
|
||||
/**
|
||||
The event variable used to send all process event
|
||||
|
@ -1236,6 +1241,7 @@ void proc_sanity_check()
|
|||
|
||||
void proc_push_interactive( int value )
|
||||
{
|
||||
ASSERT_IS_MAIN_THREAD();
|
||||
int old = is_interactive;
|
||||
interactive_stack.push_back(is_interactive);
|
||||
is_interactive = value;
|
||||
|
@ -1245,6 +1251,7 @@ void proc_push_interactive( int value )
|
|||
|
||||
void proc_pop_interactive()
|
||||
{
|
||||
ASSERT_IS_MAIN_THREAD();
|
||||
int old = is_interactive;
|
||||
is_interactive= interactive_stack.back();
|
||||
interactive_stack.pop_back();
|
||||
|
|
2
proc.h
2
proc.h
|
@ -366,7 +366,7 @@ extern int is_block;
|
|||
/**
|
||||
Whether we are reading from the keyboard right now
|
||||
*/
|
||||
extern int is_interactive;
|
||||
int get_is_interactive(void);
|
||||
|
||||
/**
|
||||
Whether this shell is attached to the keyboard at all
|
||||
|
|
26
reader.cpp
26
reader.cpp
|
@ -1049,6 +1049,9 @@ static void completion_insert( const wchar_t *val, int flags )
|
|||
}
|
||||
insert_char( L' ' );
|
||||
}
|
||||
|
||||
/* Since we just inserted a completion, don't immediately do a new autosuggestion */
|
||||
data->suppress_autosuggestion = true;
|
||||
}
|
||||
|
||||
free(replaced);
|
||||
|
@ -1235,9 +1238,6 @@ struct autosuggestion_context_t {
|
|||
int threaded_autosuggest(void) {
|
||||
ASSERT_IS_BACKGROUND_THREAD();
|
||||
|
||||
std::vector<completion_t> completions;
|
||||
complete(search_string.c_str(), completions, COMPLETE_AUTOSUGGEST);
|
||||
|
||||
while (searcher.go_backwards()) {
|
||||
history_item_t item = searcher.current_item();
|
||||
bool item_ok = false;
|
||||
|
@ -1259,6 +1259,15 @@ struct autosuggestion_context_t {
|
|||
}
|
||||
}
|
||||
|
||||
/* Try normal completions */
|
||||
std::vector<completion_t> completions;
|
||||
complete2(search_string, completions, COMPLETE_AUTOSUGGEST);
|
||||
if (! completions.empty()) {
|
||||
this->autosuggestion = this->search_string;
|
||||
this->autosuggestion.append(completions.at(0).completion);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Since we didn't find a suggestion from history, try other means */
|
||||
wcstring special_suggestion;
|
||||
if (autosuggest_suggest_special(search_string, working_directory, special_suggestion)) {
|
||||
|
@ -1436,8 +1445,7 @@ static int handle_completions( std::vector<completion_t> &comp )
|
|||
*/
|
||||
if( !(c.flags & COMPLETE_NO_CASE) || reader_can_replace( tok, c.flags ) )
|
||||
{
|
||||
completion_insert( c.completion.c_str(),
|
||||
c.flags );
|
||||
completion_insert( c.completion.c_str(), c.flags );
|
||||
}
|
||||
done = 1;
|
||||
len = 1;
|
||||
|
@ -1732,7 +1740,7 @@ static void reader_interactive_destroy()
|
|||
|
||||
void reader_sanity_check()
|
||||
{
|
||||
if( is_interactive)
|
||||
if( get_is_interactive())
|
||||
{
|
||||
if( !data )
|
||||
sanity_lose();
|
||||
|
@ -2440,7 +2448,7 @@ static void reader_super_highlight_me_plenty( int match_highlight_pos )
|
|||
|
||||
/* Here's a hack. Check to see if our autosuggestion still applies; if so, don't recompute it. Since the autosuggestion computation is asynchronous, this avoids "flashing" as you type into the autosuggestion. */
|
||||
const wcstring &cmd = data->command_line, &suggest = data->autosuggestion;
|
||||
if (! suggest.empty() && ! cmd.empty() && string_prefixes_string(cmd, suggest)) {
|
||||
if (can_autosuggest() && ! suggest.empty() && string_prefixes_string(cmd, suggest)) {
|
||||
/* The autosuggestion is still reasonable, so do nothing */
|
||||
} else {
|
||||
update_autosuggestion();
|
||||
|
@ -2450,7 +2458,7 @@ static void reader_super_highlight_me_plenty( int match_highlight_pos )
|
|||
|
||||
int exit_status()
|
||||
{
|
||||
if( is_interactive )
|
||||
if( get_is_interactive() )
|
||||
return job_list().empty() && data->end_loop;
|
||||
else
|
||||
return end_loop;
|
||||
|
@ -3444,7 +3452,7 @@ int reader_read( int fd, io_data_t *io )
|
|||
int inter = ((fd == STDIN_FILENO) && isatty(STDIN_FILENO));
|
||||
proc_push_interactive( inter );
|
||||
|
||||
res= is_interactive?read_i():read_ni( fd, io );
|
||||
res= get_is_interactive() ? read_i():read_ni( fd, io );
|
||||
|
||||
/*
|
||||
If the exit command was called in a script, only exit the
|
||||
|
|
|
@ -41,7 +41,7 @@ void sanity_lose()
|
|||
int sanity_check()
|
||||
{
|
||||
if( !insane )
|
||||
if( is_interactive )
|
||||
if( get_is_interactive() )
|
||||
history_sanity_check();
|
||||
if( !insane )
|
||||
reader_sanity_check();
|
||||
|
|
|
@ -503,7 +503,7 @@ void signal_set_handlers()
|
|||
{
|
||||
struct sigaction act;
|
||||
|
||||
if( is_interactive == -1 )
|
||||
if( get_is_interactive() == -1 )
|
||||
return;
|
||||
|
||||
sigemptyset( & act.sa_mask );
|
||||
|
@ -527,7 +527,7 @@ void signal_set_handlers()
|
|||
*/
|
||||
sigaction( SIGPIPE, &act, 0);
|
||||
|
||||
if( is_interactive )
|
||||
if( get_is_interactive() )
|
||||
{
|
||||
/*
|
||||
Interactive mode. Ignore interactive signals. We are a
|
||||
|
|
Loading…
Reference in a new issue