mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-12 13:08:49 +00:00
Changes to make autosuggestion even smarter by specially recognizing the cd command.
This commit is contained in:
parent
ed89df7e9d
commit
14b3a5be56
8 changed files with 296 additions and 131 deletions
|
@ -225,7 +225,7 @@
|
||||||
/* Begin PBXLegacyTarget section */
|
/* Begin PBXLegacyTarget section */
|
||||||
D0A084F713B3AC130099B651 /* FishsFish */ = {
|
D0A084F713B3AC130099B651 /* FishsFish */ = {
|
||||||
isa = PBXLegacyTarget;
|
isa = PBXLegacyTarget;
|
||||||
buildArgumentsString = "-k ${ACTION}";
|
buildArgumentsString = "-k ${ACTION} -j 3";
|
||||||
buildConfigurationList = D0A084FA13B3AC130099B651 /* Build configuration list for PBXLegacyTarget "FishsFish" */;
|
buildConfigurationList = D0A084FA13B3AC130099B651 /* Build configuration list for PBXLegacyTarget "FishsFish" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
);
|
);
|
||||||
|
|
|
@ -1826,12 +1826,14 @@ int create_directory( const wcstring &d )
|
||||||
return ok?0:-1;
|
return ok?0:-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__attribute__((noinline))
|
||||||
void bugreport()
|
void bugreport()
|
||||||
{
|
{
|
||||||
debug( 1,
|
debug( 1,
|
||||||
_( L"This is a bug. "
|
_( L"This is a bug. Break on bugreport to debug."
|
||||||
L"If you can reproduce it, please send a bug report to %s." ),
|
L"If you can reproduce it, please send a bug report to %s." ),
|
||||||
PACKAGE_BUGREPORT );
|
PACKAGE_BUGREPORT );
|
||||||
|
while (1) sleep(10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
146
highlight.cpp
146
highlight.cpp
|
@ -528,7 +528,150 @@ static int has_expand_reserved( const wchar_t *str )
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool autosuggest_handle_special(const wcstring &str, const env_vars &vars, const wcstring &working_directory, bool *outSuggestionOK) {
|
||||||
|
ASSERT_IS_BACKGROUND_THREAD();
|
||||||
|
assert(outSuggestionOK != NULL);
|
||||||
|
|
||||||
|
if (str.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
wcstring cmd;
|
||||||
|
bool had_cmd = false;
|
||||||
|
|
||||||
|
bool handled = false;
|
||||||
|
bool suggestionOK = true;
|
||||||
|
|
||||||
|
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 );
|
||||||
|
|
||||||
|
switch( last_type )
|
||||||
|
{
|
||||||
|
case TOK_STRING:
|
||||||
|
{
|
||||||
|
if( had_cmd )
|
||||||
|
{
|
||||||
|
if( cmd == L"cd" )
|
||||||
|
{
|
||||||
|
wcstring dir = tok_last( &tok );
|
||||||
|
if (expand_one(dir, EXPAND_SKIP_CMDSUBST))
|
||||||
|
{
|
||||||
|
/* We can specially handle the cd command */
|
||||||
|
handled = true;
|
||||||
|
bool is_help = string_prefixes_string(dir, L"--help") || string_prefixes_string(dir, L"-h");
|
||||||
|
if (! is_help && ! path_can_get_cdpath(dir, working_directory.c_str())) {
|
||||||
|
suggestionOK = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Command. First check that the command actually exists.
|
||||||
|
*/
|
||||||
|
cmd = tok_last( &tok );
|
||||||
|
bool expanded = expand_one(cmd, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_VARIABLES);
|
||||||
|
if (! expanded || has_expand_reserved(cmd.c_str()))
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int is_subcommand = 0;
|
||||||
|
int mark = tok_get_pos( &tok );
|
||||||
|
|
||||||
|
if( parser_keywords_is_subcommand( cmd ) )
|
||||||
|
{
|
||||||
|
|
||||||
|
int sw;
|
||||||
|
|
||||||
|
if( cmd == L"builtin")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else if( cmd == L"command")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
tok_next( &tok );
|
||||||
|
|
||||||
|
sw = parser_keywords_is_switch( tok_last( &tok ) );
|
||||||
|
|
||||||
|
if( !parser_keywords_is_block( cmd ) &&
|
||||||
|
sw == ARG_SWITCH )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( sw == ARG_SKIP )
|
||||||
|
{
|
||||||
|
mark = tok_get_pos( &tok );
|
||||||
|
}
|
||||||
|
|
||||||
|
is_subcommand = 1;
|
||||||
|
}
|
||||||
|
tok_set_pos( &tok, mark );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !is_subcommand )
|
||||||
|
{
|
||||||
|
had_cmd = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
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:
|
||||||
|
{
|
||||||
|
had_cmd = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TOK_END:
|
||||||
|
{
|
||||||
|
had_cmd = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TOK_COMMENT:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TOK_ERROR:
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tok_destroy( &tok );
|
||||||
|
|
||||||
|
*outSuggestionOK = suggestionOK;
|
||||||
|
return handled;
|
||||||
|
}
|
||||||
|
|
||||||
// This function does I/O
|
// This function does I/O
|
||||||
static void tokenize( const wchar_t * const buff, int * const color, const int pos, wcstring_list_t *error, const env_vars &vars) {
|
static void tokenize( const wchar_t * const buff, int * const color, const int pos, wcstring_list_t *error, const env_vars &vars) {
|
||||||
|
@ -563,7 +706,6 @@ static void tokenize( const wchar_t * const buff, int * const color, const int p
|
||||||
tok_next( &tok ) )
|
tok_next( &tok ) )
|
||||||
{
|
{
|
||||||
int last_type = tok_last_type( &tok );
|
int last_type = tok_last_type( &tok );
|
||||||
int prev_argc=0;
|
|
||||||
|
|
||||||
switch( last_type )
|
switch( last_type )
|
||||||
{
|
{
|
||||||
|
@ -620,8 +762,6 @@ static void tokenize( const wchar_t * const buff, int * const color, const int p
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
prev_argc=0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Command. First check that the command actually exists.
|
Command. First check that the command actually exists.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -106,4 +106,7 @@ void highlight_universal( const wchar_t *buff, int *color, int pos, wcstring_lis
|
||||||
*/
|
*/
|
||||||
rgb_color_t highlight_get_color( int highlight, bool is_background );
|
rgb_color_t highlight_get_color( int highlight, bool is_background );
|
||||||
|
|
||||||
|
bool autosuggest_handle_special(const wcstring &str, const env_vars &vars, const wcstring &working_directory, bool *outSuggestionOK);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
35
history.cpp
35
history.cpp
|
@ -695,26 +695,7 @@ int file_detection_context_t::perform_file_detection(bool test_all) {
|
||||||
valid_paths.clear();
|
valid_paths.clear();
|
||||||
int result = 1;
|
int result = 1;
|
||||||
for (path_list_t::const_iterator iter = potential_paths.begin(); iter != potential_paths.end(); iter++) {
|
for (path_list_t::const_iterator iter = potential_paths.begin(); iter != potential_paths.end(); iter++) {
|
||||||
wcstring path = *iter;
|
if (path_is_valid(*iter, working_directory)) {
|
||||||
|
|
||||||
bool path_is_valid;
|
|
||||||
/* Some special paths are always valid */
|
|
||||||
if (path.empty()) {
|
|
||||||
path_is_valid = false;
|
|
||||||
} else if (path == L"." || path == L"./") {
|
|
||||||
path_is_valid = true;
|
|
||||||
} else if (path == L".." || path == L"../") {
|
|
||||||
path_is_valid = (! working_directory.empty() && working_directory != L"/");
|
|
||||||
} else {
|
|
||||||
/* Maybe append the working directory. Note that we know path is not empty here. */
|
|
||||||
if (path.at(0) != '/') {
|
|
||||||
path.insert(0, working_directory);
|
|
||||||
}
|
|
||||||
path_is_valid = (0 == waccess(path, F_OK));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (path_is_valid) {
|
|
||||||
/* Push the original (possibly relative) path */
|
/* Push the original (possibly relative) path */
|
||||||
valid_paths.push_front(*iter);
|
valid_paths.push_front(*iter);
|
||||||
} else {
|
} else {
|
||||||
|
@ -736,17 +717,9 @@ bool file_detection_context_t::paths_are_valid(const path_list_t &paths) {
|
||||||
file_detection_context_t::file_detection_context_t(history_t *hist, const wcstring &cmd) :
|
file_detection_context_t::file_detection_context_t(history_t *hist, const wcstring &cmd) :
|
||||||
history(hist),
|
history(hist),
|
||||||
command(cmd),
|
command(cmd),
|
||||||
when(time(NULL)) {
|
when(time(NULL)),
|
||||||
/* Stash the working directory. TODO: We should be respecting CDPATH here*/
|
working_directory(get_working_directory())
|
||||||
wchar_t dir_path[4096];
|
{
|
||||||
const wchar_t *cwd = wgetcwd( dir_path, 4096 );
|
|
||||||
if (cwd) {
|
|
||||||
wcstring wd = cwd;
|
|
||||||
/* Make sure the working directory ends with a slash */
|
|
||||||
if (! wd.empty() && wd.at(wd.size() - 1) != L'/')
|
|
||||||
wd.push_back(L'/');
|
|
||||||
working_directory.swap(wd);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int threaded_perform_file_detection(file_detection_context_t *ctx) {
|
static int threaded_perform_file_detection(file_detection_context_t *ctx) {
|
||||||
|
|
109
path.cpp
109
path.cpp
|
@ -336,47 +336,46 @@ bool path_get_cdpath_string(const wcstring &dir_str, wcstring &result, const env
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
wchar_t *path_allocate_cdpath( const wchar_t *dir )
|
wchar_t *path_allocate_cdpath( const wchar_t *dir, const wchar_t *wd )
|
||||||
{
|
{
|
||||||
wchar_t *res = 0;
|
wchar_t *res = NULL;
|
||||||
int err = ENOENT;
|
int err = ENOENT;
|
||||||
if( !dir )
|
if( !dir )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (wd) {
|
||||||
if( dir[0] == L'/'|| (wcsncmp( dir, L"./", 2 )==0) )
|
size_t len = wcslen(wd);
|
||||||
{
|
assert(wd[len - 1] == L'/');
|
||||||
struct stat buf;
|
|
||||||
if( wstat( dir, &buf ) == 0 )
|
|
||||||
{
|
|
||||||
if( S_ISDIR(buf.st_mode) )
|
|
||||||
{
|
|
||||||
res = wcsdup(dir);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
err = ENOTDIR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
wcstring_list_t paths;
|
||||||
}
|
|
||||||
else
|
if (dir[0] == L'/') {
|
||||||
{
|
/* Absolute path */
|
||||||
|
paths.push_back(dir);
|
||||||
|
} else if (wcsncmp(dir, L"./", 2) == 0 ||
|
||||||
|
wcsncmp(dir, L"../", 3) == 0 ||
|
||||||
|
wcscmp(dir, L".") == 0 ||
|
||||||
|
wcscmp(dir, L"..") == 0) {
|
||||||
|
/* Path is relative to the working directory */
|
||||||
|
wcstring path;
|
||||||
|
if (wd)
|
||||||
|
path.append(wd);
|
||||||
|
path.append(dir);
|
||||||
|
paths.push_back(path);
|
||||||
|
} else {
|
||||||
wchar_t *path_cpy;
|
wchar_t *path_cpy;
|
||||||
const wchar_t *nxt_path;
|
const wchar_t *nxt_path;
|
||||||
wchar_t *state;
|
wchar_t *state;
|
||||||
wchar_t *whole_path;
|
wchar_t *whole_path;
|
||||||
|
|
||||||
env_var_t path = L".";
|
env_var_t path = env_get_string(L"CDPATH");
|
||||||
|
if (path.missing())
|
||||||
|
path = wd ? wd : L".";
|
||||||
|
|
||||||
nxt_path = path.c_str();
|
nxt_path = path.c_str();
|
||||||
path_cpy = wcsdup( path.c_str() );
|
path_cpy = wcsdup( path.c_str() );
|
||||||
|
|
||||||
if( !path_cpy )
|
|
||||||
{
|
|
||||||
DIE_MEM();
|
|
||||||
}
|
|
||||||
|
|
||||||
for( nxt_path = wcstok( path_cpy, ARRAY_SEP_STR, &state );
|
for( nxt_path = wcstok( path_cpy, ARRAY_SEP_STR, &state );
|
||||||
nxt_path != 0;
|
nxt_path != 0;
|
||||||
nxt_path = wcstok( 0, ARRAY_SEP_STR, &state) )
|
nxt_path = wcstok( 0, ARRAY_SEP_STR, &state) )
|
||||||
|
@ -398,13 +397,20 @@ wchar_t *path_allocate_cdpath( const wchar_t *dir )
|
||||||
dir );
|
dir );
|
||||||
|
|
||||||
free(expanded_path );
|
free(expanded_path );
|
||||||
|
paths.push_back(whole_path);
|
||||||
|
free( whole_path );
|
||||||
|
}
|
||||||
|
free( path_cpy );
|
||||||
|
}
|
||||||
|
|
||||||
|
for (wcstring_list_t::const_iterator iter = paths.begin(); iter != paths.end(); iter++) {
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
if( wstat( whole_path, &buf ) == 0 )
|
const wchar_t *dir = iter->c_str();
|
||||||
|
if( wstat( dir, &buf ) == 0 )
|
||||||
{
|
{
|
||||||
if( S_ISDIR(buf.st_mode) )
|
if( S_ISDIR(buf.st_mode) )
|
||||||
{
|
{
|
||||||
res = whole_path;
|
res = wcsdup(dir);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -412,17 +418,6 @@ wchar_t *path_allocate_cdpath( const wchar_t *dir )
|
||||||
err = ENOTDIR;
|
err = ENOTDIR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
if( lwstat( whole_path, &buf ) == 0 )
|
|
||||||
{
|
|
||||||
err = EROTTEN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free( whole_path );
|
|
||||||
}
|
|
||||||
free( path_cpy );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !res )
|
if( !res )
|
||||||
|
@ -434,8 +429,8 @@ wchar_t *path_allocate_cdpath( const wchar_t *dir )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool path_can_get_cdpath(const wcstring &in) {
|
bool path_can_get_cdpath(const wcstring &in, const wchar_t *wd) {
|
||||||
wchar_t *tmp = path_allocate_cdpath(in.c_str());
|
wchar_t *tmp = path_allocate_cdpath(in.c_str(), wd);
|
||||||
bool result = (tmp != NULL);
|
bool result = (tmp != NULL);
|
||||||
free(tmp);
|
free(tmp);
|
||||||
return result;
|
return result;
|
||||||
|
@ -512,3 +507,37 @@ void path_make_canonical( wcstring &path )
|
||||||
path.resize(size+1);
|
path.resize(size+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool path_is_valid(const wcstring &path, const wcstring &working_directory)
|
||||||
|
{
|
||||||
|
bool path_is_valid;
|
||||||
|
/* Some special paths are always valid */
|
||||||
|
if (path.empty()) {
|
||||||
|
path_is_valid = false;
|
||||||
|
} else if (path == L"." || path == L"./") {
|
||||||
|
path_is_valid = true;
|
||||||
|
} else if (path == L".." || path == L"../") {
|
||||||
|
path_is_valid = (! working_directory.empty() && working_directory != L"/");
|
||||||
|
} else if (path.at(0) != '/') {
|
||||||
|
/* Prepend the working directory. Note that we know path is not empty here. */
|
||||||
|
wcstring tmp = working_directory;
|
||||||
|
tmp.append(path);
|
||||||
|
path_is_valid = (0 == waccess(tmp.c_str(), F_OK));
|
||||||
|
} else {
|
||||||
|
/* Simple check */
|
||||||
|
path_is_valid = (0 == waccess(path.c_str(), F_OK));
|
||||||
|
}
|
||||||
|
return path_is_valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
wcstring get_working_directory(void) {
|
||||||
|
wcstring wd = L"./";
|
||||||
|
wchar_t dir_path[4096];
|
||||||
|
const wchar_t *cwd = wgetcwd( dir_path, 4096 );
|
||||||
|
if (cwd) {
|
||||||
|
wd = cwd;
|
||||||
|
/* Make sure the working directory ends with a slash */
|
||||||
|
if (! wd.empty() && wd.at(wd.size() - 1) != L'/')
|
||||||
|
wd.push_back(L'/');
|
||||||
|
}
|
||||||
|
return wd;
|
||||||
|
}
|
||||||
|
|
8
path.h
8
path.h
|
@ -49,11 +49,12 @@ bool path_get_path_string(const wcstring &cmd, wcstring &output, const env_vars
|
||||||
will be returned.
|
will be returned.
|
||||||
|
|
||||||
\param in The name of the directory.
|
\param in The name of the directory.
|
||||||
|
\param wd The working directory, or NULL to use the default. The working directory should have a slash appended at the end.
|
||||||
\return 0 if the command can not be found, the path of the command otherwise. The path should be free'd with free().
|
\return 0 if the command can not be found, the path of the command otherwise. The path should be free'd with free().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
wchar_t *path_allocate_cdpath( const wchar_t *in );
|
wchar_t *path_allocate_cdpath( const wchar_t *in, const wchar_t *wd = NULL);
|
||||||
bool path_can_get_cdpath(const wcstring &in);
|
bool path_can_get_cdpath(const wcstring &in, const wchar_t *wd = NULL);
|
||||||
bool path_get_cdpath_string(const wcstring &in, wcstring &out, const env_vars &vars);
|
bool path_get_cdpath_string(const wcstring &in, wcstring &out, const env_vars &vars);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -62,5 +63,8 @@ bool path_get_cdpath_string(const wcstring &in, wcstring &out, const env_vars &v
|
||||||
*/
|
*/
|
||||||
void path_make_canonical( wcstring &path );
|
void path_make_canonical( wcstring &path );
|
||||||
|
|
||||||
|
bool path_is_valid(const wcstring &path, const wcstring &working_directory);
|
||||||
|
|
||||||
|
wcstring get_working_directory(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
30
reader.cpp
30
reader.cpp
|
@ -103,6 +103,7 @@ commence.
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
#include "iothread.h"
|
#include "iothread.h"
|
||||||
#include "intern.h"
|
#include "intern.h"
|
||||||
|
#include "path.h"
|
||||||
|
|
||||||
#include "parse_util.h"
|
#include "parse_util.h"
|
||||||
|
|
||||||
|
@ -1270,31 +1271,43 @@ static void run_pager( wchar_t *prefix, int is_quoted, const std::vector<complet
|
||||||
struct autosuggestion_context_t {
|
struct autosuggestion_context_t {
|
||||||
history_search_t searcher;
|
history_search_t searcher;
|
||||||
file_detection_context_t detector;
|
file_detection_context_t detector;
|
||||||
|
const wcstring working_directory;
|
||||||
|
const env_vars vars;
|
||||||
|
|
||||||
autosuggestion_context_t(history_t *history, const wcstring &term) :
|
autosuggestion_context_t(history_t *history, const wcstring &term) :
|
||||||
searcher(*history, term, HISTORY_SEARCH_TYPE_PREFIX),
|
searcher(*history, term, HISTORY_SEARCH_TYPE_PREFIX),
|
||||||
detector(history, term)
|
detector(history, term),
|
||||||
|
working_directory(get_working_directory()),
|
||||||
|
vars(env_vars::highlighting_keys)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
static int threaded_autosuggest(autosuggestion_context_t *ctx) {
|
int threaded_autosuggest(void) {
|
||||||
ASSERT_IS_BACKGROUND_THREAD();
|
ASSERT_IS_BACKGROUND_THREAD();
|
||||||
while (ctx->searcher.go_backwards()) {
|
while (searcher.go_backwards()) {
|
||||||
history_item_t item = ctx->searcher.current_item();
|
history_item_t item = searcher.current_item();
|
||||||
|
bool item_ok = false;
|
||||||
|
if (autosuggest_handle_special(item.str(), vars, working_directory, &item_ok)) {
|
||||||
|
/* The command autosuggestion was handled specially, so we're done */
|
||||||
|
} else {
|
||||||
/* See if the item has any required paths */
|
/* See if the item has any required paths */
|
||||||
bool item_ok;
|
|
||||||
const path_list_t &paths = item.get_required_paths();
|
const path_list_t &paths = item.get_required_paths();
|
||||||
if (paths.empty()) {
|
if (paths.empty()) {
|
||||||
item_ok = true;
|
item_ok = true;
|
||||||
} else {
|
} else {
|
||||||
ctx->detector.potential_paths = paths;
|
detector.potential_paths = paths;
|
||||||
item_ok = ctx->detector.paths_are_valid(paths);
|
item_ok = detector.paths_are_valid(paths);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (item_ok)
|
if (item_ok)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static int threaded_autosuggest(autosuggestion_context_t *ctx) {
|
||||||
|
return ctx->threaded_autosuggest();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool can_autosuggest(void) {
|
static bool can_autosuggest(void) {
|
||||||
|
@ -2587,6 +2600,7 @@ static int read_i()
|
||||||
|
|
||||||
data->buff_pos=0;
|
data->buff_pos=0;
|
||||||
data->command_line.clear();
|
data->command_line.clear();
|
||||||
|
data->check_size();
|
||||||
reader_run_command( parser, tmp );
|
reader_run_command( parser, tmp );
|
||||||
free( (void *)tmp );
|
free( (void *)tmp );
|
||||||
if( data->end_loop)
|
if( data->end_loop)
|
||||||
|
|
Loading…
Reference in a new issue