mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-12 13:08:49 +00:00
Restore implicit cd for paths starting with ., .., or ~
This commit is contained in:
parent
ae12e1b537
commit
b7ba252965
6 changed files with 68 additions and 25 deletions
13
expand.cpp
13
expand.cpp
|
@ -1351,22 +1351,13 @@ static wchar_t * expand_tilde_internal_compat( wchar_t *in )
|
||||||
|
|
||||||
void expand_tilde( wcstring &input)
|
void expand_tilde( wcstring &input)
|
||||||
{
|
{
|
||||||
if( input[0] == L'~' )
|
if( ! input.empty() && input.at(0) == L'~' )
|
||||||
{
|
{
|
||||||
input[0] = HOME_DIRECTORY;
|
input.at(0) = HOME_DIRECTORY;
|
||||||
expand_tilde_internal( input );
|
expand_tilde_internal( input );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wchar_t * expand_tilde_compat( wchar_t *input )
|
|
||||||
{
|
|
||||||
if (input[0] == L'~') {
|
|
||||||
input[0] = HOME_DIRECTORY;
|
|
||||||
return expand_tilde_internal_compat(input);
|
|
||||||
}
|
|
||||||
return input;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Remove any internal separators. Also optionally convert wildcard characters to
|
Remove any internal separators. Also optionally convert wildcard characters to
|
||||||
regular equivalents. This is done to support EXPAND_SKIP_WILDCARDS.
|
regular equivalents. This is done to support EXPAND_SKIP_WILDCARDS.
|
||||||
|
|
1
expand.h
1
expand.h
|
@ -162,7 +162,6 @@ wcstring expand_escape_variable( const wcstring &in );
|
||||||
\param input the string to tilde expand
|
\param input the string to tilde expand
|
||||||
*/
|
*/
|
||||||
void expand_tilde(wcstring &input);
|
void expand_tilde(wcstring &input);
|
||||||
wchar_t * expand_tilde_compat( wchar_t *input );
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -916,7 +916,7 @@ static void tokenize( const wchar_t * const buff, std::vector<int> &color, const
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int is_cmd = 0;
|
bool is_cmd = false;
|
||||||
int is_subcommand = 0;
|
int is_subcommand = 0;
|
||||||
int mark = tok_get_pos( &tok );
|
int mark = tok_get_pos( &tok );
|
||||||
color.at(tok_get_pos( &tok )) = HIGHLIGHT_COMMAND;
|
color.at(tok_get_pos( &tok )) = HIGHLIGHT_COMMAND;
|
||||||
|
@ -984,11 +984,11 @@ static void tokenize( const wchar_t * const buff, std::vector<int> &color, const
|
||||||
function, since we don't have to stat
|
function, since we don't have to stat
|
||||||
any files for that
|
any files for that
|
||||||
*/
|
*/
|
||||||
if( use_builtin )
|
if (! is_cmd && use_builtin )
|
||||||
is_cmd = is_cmd || builtin_exists( cmd );
|
is_cmd = builtin_exists( cmd );
|
||||||
|
|
||||||
if( use_function )
|
if (! is_cmd && use_function )
|
||||||
is_cmd = is_cmd || function_exists_no_autoload( cmd, vars );
|
is_cmd = function_exists_no_autoload( cmd, vars );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Moving on to expensive tests
|
Moving on to expensive tests
|
||||||
|
@ -997,10 +997,17 @@ static void tokenize( const wchar_t * const buff, std::vector<int> &color, const
|
||||||
/*
|
/*
|
||||||
Check if this is a regular command
|
Check if this is a regular command
|
||||||
*/
|
*/
|
||||||
if( use_command )
|
if (! is_cmd && use_command )
|
||||||
{
|
{
|
||||||
wcstring tmp;
|
wcstring tmp;
|
||||||
is_cmd = is_cmd || path_get_path_string( cmd, tmp, vars );
|
is_cmd = path_get_path_string( cmd, tmp, vars );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Maybe it is a path for a implicit cd command. */
|
||||||
|
if (! is_cmd)
|
||||||
|
{
|
||||||
|
if (use_builtin || (use_function && function_exists_no_autoload( L"cd", vars)))
|
||||||
|
is_cmd = path_can_be_implicit_cd(cmd, NULL, working_directory.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if( is_cmd )
|
if( is_cmd )
|
||||||
|
@ -1181,7 +1188,7 @@ static void tokenize( const wchar_t * const buff, std::vector<int> &color, const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// PCA DOES_IO (calls is_potential_path, path_get_path, maybe others)
|
// PCA This function does I/O, (calls is_potential_path, path_get_path, maybe others) and so ought to only run on a background thread
|
||||||
void highlight_shell( const wcstring &buff, std::vector<int> &color, int pos, wcstring_list_t *error, const env_vars &vars )
|
void highlight_shell( const wcstring &buff, std::vector<int> &color, int pos, wcstring_list_t *error, const env_vars &vars )
|
||||||
{
|
{
|
||||||
ASSERT_IS_BACKGROUND_THREAD();
|
ASSERT_IS_BACKGROUND_THREAD();
|
||||||
|
|
24
parser.cpp
24
parser.cpp
|
@ -1956,10 +1956,28 @@ int parser_t::parse_job( process_t *p,
|
||||||
p->actual_cmd = path_get_path( args.at(0).completion.c_str() );
|
p->actual_cmd = path_get_path( args.at(0).completion.c_str() );
|
||||||
err = errno;
|
err = errno;
|
||||||
|
|
||||||
/*
|
bool use_implicit_cd = false;
|
||||||
Check if the specified command exists
|
|
||||||
*/
|
|
||||||
if (p->actual_cmd == NULL)
|
if (p->actual_cmd == NULL)
|
||||||
|
{
|
||||||
|
/* If the specified command does not exist, try using an implicit cd. */
|
||||||
|
wcstring implicit_cd_path;
|
||||||
|
use_implicit_cd = path_can_be_implicit_cd(args.at(0).completion, &implicit_cd_path);
|
||||||
|
if (use_implicit_cd)
|
||||||
|
{
|
||||||
|
args.clear();
|
||||||
|
args.push_back(completion_t(L"cd"));
|
||||||
|
args.push_back(completion_t(implicit_cd_path));
|
||||||
|
|
||||||
|
/* If we have defined a wrapper around cd, use it, otherwise use the cd builtin */
|
||||||
|
if (use_function && function_exists(L"cd"))
|
||||||
|
p->type = INTERNAL_FUNCTION;
|
||||||
|
else
|
||||||
|
p->type = INTERNAL_BUILTIN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the specified command exists */
|
||||||
|
if( p->actual_cmd == NULL && ! use_implicit_cd )
|
||||||
{
|
{
|
||||||
|
|
||||||
int tmp;
|
int tmp;
|
||||||
|
|
27
path.cpp
27
path.cpp
|
@ -431,13 +431,38 @@ wchar_t *path_allocate_cdpath( const wcstring &dir, const wchar_t *wd )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool path_can_get_cdpath(const wcstring &in, const wchar_t *wd) {
|
bool path_can_get_cdpath(const wcstring &in, const wchar_t *wd)
|
||||||
|
{
|
||||||
wchar_t *tmp = path_allocate_cdpath(in, wd);
|
wchar_t *tmp = path_allocate_cdpath(in, wd);
|
||||||
bool result = (tmp != NULL);
|
bool result = (tmp != NULL);
|
||||||
free(tmp);
|
free(tmp);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool path_can_be_implicit_cd(const wcstring &path, wcstring *out_path, const wchar_t *wd)
|
||||||
|
{
|
||||||
|
wcstring exp_path = path;
|
||||||
|
expand_tilde(exp_path);
|
||||||
|
|
||||||
|
bool result = false;
|
||||||
|
if (string_prefixes_string(L"/", exp_path) ||
|
||||||
|
string_prefixes_string(L"./", exp_path) ||
|
||||||
|
string_prefixes_string(L"../", exp_path) ||
|
||||||
|
exp_path == L"..")
|
||||||
|
{
|
||||||
|
/* These paths can be implicit cd. Note that a single period cannot (that's used for sourcing files anyways) */
|
||||||
|
wchar_t *cd_path = path_allocate_cdpath(exp_path, wd);
|
||||||
|
if (cd_path)
|
||||||
|
{
|
||||||
|
/* It worked. Return the path if desired */
|
||||||
|
if (out_path)
|
||||||
|
out_path->assign(cd_path);
|
||||||
|
free(cd_path);
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
bool path_get_config(wcstring &path)
|
bool path_get_config(wcstring &path)
|
||||||
{
|
{
|
||||||
|
|
3
path.h
3
path.h
|
@ -31,6 +31,9 @@ bool path_get_config(wcstring &path);
|
||||||
*/
|
*/
|
||||||
wchar_t *path_get_path( const wchar_t *cmd );
|
wchar_t *path_get_path( const wchar_t *cmd );
|
||||||
|
|
||||||
|
/** Returns whether the path can be used for an implicit cd command; if so, also returns the path by reference (if desired). This requires it to start with one of the allowed prefixes (., .., ~) and resolve to a directory. */
|
||||||
|
bool path_can_be_implicit_cd(const wcstring &path, wcstring *out_path = NULL, const wchar_t *wd = NULL);
|
||||||
|
|
||||||
class env_vars;
|
class env_vars;
|
||||||
bool path_get_path_string(const wcstring &cmd, wcstring &output);
|
bool path_get_path_string(const wcstring &cmd, wcstring &output);
|
||||||
bool path_get_path_string(const wcstring &cmd, wcstring &output, const env_vars &vars);
|
bool path_get_path_string(const wcstring &cmd, wcstring &output, const env_vars &vars);
|
||||||
|
|
Loading…
Reference in a new issue