mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-12 04:58:57 +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)
|
||||
{
|
||||
if( input[0] == L'~' )
|
||||
if( ! input.empty() && input.at(0) == L'~' )
|
||||
{
|
||||
input[0] = HOME_DIRECTORY;
|
||||
input.at(0) = HOME_DIRECTORY;
|
||||
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
|
||||
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
|
||||
*/
|
||||
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
|
||||
{
|
||||
int is_cmd = 0;
|
||||
bool is_cmd = false;
|
||||
int is_subcommand = 0;
|
||||
int mark = tok_get_pos( &tok );
|
||||
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
|
||||
any files for that
|
||||
*/
|
||||
if( use_builtin )
|
||||
is_cmd = is_cmd || builtin_exists( cmd );
|
||||
if (! is_cmd && use_builtin )
|
||||
is_cmd = builtin_exists( cmd );
|
||||
|
||||
if( use_function )
|
||||
is_cmd = is_cmd || function_exists_no_autoload( cmd, vars );
|
||||
if (! is_cmd && use_function )
|
||||
is_cmd = function_exists_no_autoload( cmd, vars );
|
||||
|
||||
/*
|
||||
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
|
||||
*/
|
||||
if( use_command )
|
||||
if (! is_cmd && use_command )
|
||||
{
|
||||
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 )
|
||||
|
@ -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 )
|
||||
{
|
||||
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() );
|
||||
err = errno;
|
||||
|
||||
/*
|
||||
Check if the specified command exists
|
||||
*/
|
||||
bool use_implicit_cd = false;
|
||||
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;
|
||||
|
|
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);
|
||||
bool result = (tmp != NULL);
|
||||
free(tmp);
|
||||
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)
|
||||
{
|
||||
|
|
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 );
|
||||
|
||||
/** 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;
|
||||
bool path_get_path_string(const wcstring &cmd, wcstring &output);
|
||||
bool path_get_path_string(const wcstring &cmd, wcstring &output, const env_vars &vars);
|
||||
|
|
Loading…
Reference in a new issue