Lots of modernization changed

Removed wcsdupcat
This commit is contained in:
ridiculousfish 2012-05-09 02:33:42 -07:00
parent 4bd63020ca
commit 9bcc7df96f
15 changed files with 177 additions and 348 deletions

View file

@ -231,7 +231,7 @@
/* Begin PBXLegacyTarget section */ /* Begin PBXLegacyTarget section */
D0A084F713B3AC130099B651 /* FishsFish */ = { D0A084F713B3AC130099B651 /* FishsFish */ = {
isa = PBXLegacyTarget; isa = PBXLegacyTarget;
buildArgumentsString = "-k ${ACTION} -j 3"; buildArgumentsString = "-k ${ACTION}";
buildConfigurationList = D0A084FA13B3AC130099B651 /* Build configuration list for PBXLegacyTarget "FishsFish" */; buildConfigurationList = D0A084FA13B3AC130099B651 /* Build configuration list for PBXLegacyTarget "FishsFish" */;
buildPhases = ( buildPhases = (
); );

View file

@ -2569,7 +2569,7 @@ static int builtin_exit( parser_t &parser, wchar_t **argv )
static int builtin_cd( parser_t &parser, wchar_t **argv ) static int builtin_cd( parser_t &parser, wchar_t **argv )
{ {
env_var_t dir_in; env_var_t dir_in;
wchar_t *dir; wchar_t *dir = NULL;
int res=STATUS_BUILTIN_OK; int res=STATUS_BUILTIN_OK;
@ -2583,10 +2583,13 @@ static int builtin_cd( parser_t &parser, wchar_t **argv )
argv[0] ); argv[0] );
} }
} }
else else {
dir_in = argv[1]; dir_in = argv[1];
}
dir = path_allocate_cdpath( dir_in.missing() ? NULL : dir_in.c_str() ); if (! dir_in.missing()) {
dir = path_allocate_cdpath(dir_in);
}
if( !dir ) if( !dir )
{ {

View file

@ -401,61 +401,6 @@ char **wcsv2strv( const wchar_t * const *in )
} }
wchar_t *wcsdupcat_internal( const wchar_t *a, ... )
{
int len=wcslen(a);
int pos;
va_list va, va2;
wchar_t *arg;
va_start( va, a );
va_copy( va2, va );
while( (arg=va_arg(va, wchar_t *) )!= 0 )
{
len += wcslen( arg );
}
va_end( va );
wchar_t *res = (wchar_t *)malloc( sizeof(wchar_t)*(len +1 ));
if( res == 0 )
{
DIE_MEM();
}
wcscpy( res, a );
pos = wcslen(a);
while( (arg=va_arg(va2, wchar_t *) )!= 0 )
{
wcscpy( res+pos, arg );
pos += wcslen(arg);
}
va_end( va2 );
return res;
}
wchar_t **strv2wcsv( const char **in )
{
int count =0;
int i;
while( in[count] != 0 )
count++;
wchar_t **res = (wchar_t **)malloc( sizeof( wchar_t *)*(count+1));
if( res == 0 )
{
DIE_MEM();
}
for( i=0; i<count; i++ )
{
res[i]=str2wcs(in[i]);
}
res[count]=0;
return res;
}
wcstring format_string(const wchar_t *format, ...) wcstring format_string(const wchar_t *format, ...)
{ {
va_list va; va_list va;
@ -1723,6 +1668,13 @@ void tokenize_variable_array( const wcstring &val, std::vector<wcstring> &out)
out.push_back(val.substr(pos, end - pos)); out.push_back(val.substr(pos, end - pos));
} }
bool string_prefixes_string(const wchar_t *proposed_prefix, const wcstring &value)
{
size_t prefix_size = wcslen(proposed_prefix);
return prefix_size <= value.size() && value.compare(0, prefix_size, proposed_prefix) == 0;
}
bool string_prefixes_string(const wcstring &proposed_prefix, const wcstring &value) bool string_prefixes_string(const wcstring &proposed_prefix, const wcstring &value)
{ {
size_t prefix_size = proposed_prefix.size(); size_t prefix_size = proposed_prefix.size();
@ -1948,14 +1900,19 @@ null_terminated_array_t<char> convert_wide_array_to_narrow(const null_terminated
void append_path_component(wcstring &path, const wcstring &component) void append_path_component(wcstring &path, const wcstring &component)
{ {
size_t len = path.size(); if (path.empty() || component.empty()) {
if (len == 0) path.append(component);
{ } else {
path = component; size_t path_len = path.size();
} bool path_slash = path.at(path_len-1) == L'/';
else bool comp_slash = component.at(0) == L'/';
{ if (! path_slash && ! comp_slash) {
if (path[len-1] != L'/') path.push_back(L'/'); // Need a slash
path.push_back(L'/');
} else if (path_slash && comp_slash) {
// Too many slashes
path.erase(path_len - 1, 1);
}
path.append(component); path.append(component);
} }
} }

View file

@ -180,10 +180,6 @@ extern const wchar_t *program_name;
Check if the specified stringelement is a part of the specified string list Check if the specified stringelement is a part of the specified string list
*/ */
#define contains( str,... ) contains_internal( str, __VA_ARGS__, NULL ) #define contains( str,... ) contains_internal( str, __VA_ARGS__, NULL )
/**
Concatenate all the specified strings into a single newly allocated one
*/
#define wcsdupcat( str,... ) wcsdupcat_internal( str, __VA_ARGS__, NULL )
/** /**
Print a stack trace to stderr Print a stack trace to stderr
@ -251,6 +247,7 @@ std::string wcs2string(const wcstring &input);
/** Test if a string prefixes another. Returns true if a is a prefix of b */ /** Test if a string prefixes another. Returns true if a is a prefix of b */
bool string_prefixes_string(const wcstring &proposed_prefix, const wcstring &value); bool string_prefixes_string(const wcstring &proposed_prefix, const wcstring &value);
bool string_prefixes_string(const wchar_t *proposed_prefix, const wcstring &value);
/** Test if a string prefixes another without regard to case. Returns true if a is a prefix of b */ /** Test if a string prefixes another without regard to case. Returns true if a is a prefix of b */
bool string_prefixes_string_case_insensitive(const wcstring &proposed_prefix, const wcstring &value); bool string_prefixes_string_case_insensitive(const wcstring &proposed_prefix, const wcstring &value);
@ -520,23 +517,6 @@ void append_format(wcstring &str, const wchar_t *format, ...);
*/ */
char **wcsv2strv( const wchar_t * const *in ); char **wcsv2strv( const wchar_t * const *in );
/**
Returns a newly allocated multibyte character string array equivalent of the specified wide character string array
*/
wchar_t **strv2wcsv( const char **in );
/**
Returns a newly allocated concatenation of the specified wide
character strings. The last argument must be a null pointer.
*/
__sentinel wchar_t *wcsdupcat_internal( const wchar_t *a, ... );
/**
Test if the given string is a valid variable name
*/
/** /**
Test if the given string is a valid variable name. Test if the given string is a valid variable name.

View file

@ -828,7 +828,7 @@ int complete_is_valid_argument( const wchar_t *str,
*/ */
static void complete_strings( std::vector<completion_t> &comp_out, static void complete_strings( std::vector<completion_t> &comp_out,
const wchar_t *wc_escaped, const wcstring &wc_escaped,
const wchar_t *desc, const wchar_t *desc,
const wchar_t *(*desc_func)(const wcstring &), const wchar_t *(*desc_func)(const wcstring &),
std::vector<completion_t> &possible_comp, std::vector<completion_t> &possible_comp,
@ -1001,9 +1001,12 @@ static const wchar_t *complete_function_desc( const wcstring &fn )
\param comp the list to add all completions to \param comp the list to add all completions to
*/ */
void completer_t::complete_cmd( const wcstring &str, bool use_function, bool use_builtin, bool use_command) void completer_t::complete_cmd( const wcstring &str_cmd, bool use_function, bool use_builtin, bool use_command)
{ {
const wchar_t * const cmd = str.c_str(); /* Paranoia */
if (str_cmd.empty())
return;
wchar_t *path_cpy; wchar_t *path_cpy;
wchar_t *nxt_path; wchar_t *nxt_path;
wchar_t *state; wchar_t *state;
@ -1013,20 +1016,19 @@ void completer_t::complete_cmd( const wcstring &str, bool use_function, bool use
env_var_t cdpath = env_get_string(L"CDPATH"); env_var_t cdpath = env_get_string(L"CDPATH");
if (cdpath.missing_or_empty()) if (cdpath.missing_or_empty())
cdpath = L"."; cdpath = L".";
wchar_t *cdpath_cpy = wcsdup(cdpath.c_str());
const bool wants_description = (type == COMPLETE_DEFAULT); const bool wants_description = (type == COMPLETE_DEFAULT);
if( (wcschr( cmd, L'/') != 0) || (cmd[0] == L'~' ) ) if (str_cmd.find(L'/') != wcstring::npos || str_cmd.at(0) == L'~')
{ {
if( use_command ) if( use_command )
{ {
if( expand_string(str, this->completions, ACCEPT_INCOMPLETE | EXECUTABLES_ONLY | this->expand_flags() ) != EXPAND_ERROR ) if( expand_string(str_cmd, this->completions, ACCEPT_INCOMPLETE | EXECUTABLES_ONLY | this->expand_flags() ) != EXPAND_ERROR )
{ {
if (wants_description) { if (wants_description) {
this->complete_cmd_desc( str ); this->complete_cmd_desc( str_cmd );
} }
} }
} }
@ -1046,43 +1048,37 @@ void completer_t::complete_cmd( const wcstring &str, bool use_function, bool use
nxt_path != 0; nxt_path != 0;
nxt_path = wcstok( 0, ARRAY_SEP_STR, &state) ) nxt_path = wcstok( 0, ARRAY_SEP_STR, &state) )
{ {
size_t prev_count; wcstring base_path = nxt_path;
int path_len = wcslen(nxt_path); if (base_path.empty())
int add_slash; continue;
if( !path_len ) /* Make sure the base path ends with a slash */
{ if (base_path.at(base_path.size() - 1) != L'/')
continue; base_path.push_back(L'/');
}
add_slash = nxt_path[path_len-1]!=L'/'; wcstring nxt_completion = base_path;
wchar_t *nxt_completion = wcsdupcat( nxt_path, nxt_completion.append(str_cmd);
add_slash?L"/":L"",
cmd ); size_t prev_count = this->completions.size();
if( ! nxt_completion )
continue;
prev_count = this->completions.size() ;
if( expand_string( nxt_completion, if( expand_string( nxt_completion,
this->completions, this->completions,
ACCEPT_INCOMPLETE | EXECUTABLES_ONLY | this->expand_flags() ) != EXPAND_ERROR ) ACCEPT_INCOMPLETE | EXECUTABLES_ONLY | this->expand_flags() ) != EXPAND_ERROR )
{ {
/* For all new completions, if COMPLETE_NO_CASE is set, then use only the last path component */
for( size_t i=prev_count; i< this->completions.size(); i++ ) for( size_t i=prev_count; i< this->completions.size(); i++ )
{ {
completion_t &c = this->completions.at( i ); completion_t &c = this->completions.at( i );
if(c.flags & COMPLETE_NO_CASE ) if(c.flags & COMPLETE_NO_CASE )
{ {
c.completion += add_slash ;
c.completion.erase(0, base_path.size());
} }
} }
} }
free(nxt_completion);
} }
free( path_cpy ); free( path_cpy );
if (wants_description) if (wants_description)
this->complete_cmd_desc( str ); this->complete_cmd_desc( str_cmd );
} }
} }
@ -1093,12 +1089,12 @@ void completer_t::complete_cmd( const wcstring &str, bool use_function, bool use
if( use_function ) if( use_function )
{ {
//function_get_names( &possible_comp, cmd[0] == L'_' ); //function_get_names( &possible_comp, cmd[0] == L'_' );
wcstring_list_t names = function_get_names(cmd[0] == L'_' ); wcstring_list_t names = function_get_names(str_cmd.at(0) == L'_' );
for (size_t i=0; i < names.size(); i++) { for (size_t i=0; i < names.size(); i++) {
possible_comp.push_back(completion_t(names.at(i))); possible_comp.push_back(completion_t(names.at(i)));
} }
complete_strings( this->completions, cmd, 0, &complete_function_desc, possible_comp, 0 ); complete_strings( this->completions, str_cmd, 0, &complete_function_desc, possible_comp, 0 );
} }
possible_comp.clear(); possible_comp.clear();
@ -1106,43 +1102,10 @@ void completer_t::complete_cmd( const wcstring &str, bool use_function, bool use
if( use_builtin ) if( use_builtin )
{ {
builtin_get_names( possible_comp ); builtin_get_names( possible_comp );
complete_strings( this->completions, cmd, 0, &builtin_get_desc, possible_comp, 0 ); complete_strings( this->completions, str_cmd, 0, &builtin_get_desc, possible_comp, 0 );
} }
// al_destroy( &possible_comp );
} }
if( use_builtin || (use_function && function_exists( L"cd") ) )
{
/*
Tab complete implicit cd for directories in CDPATH
*/
if( cmd[0] != L'/' && ( wcsncmp( cmd, L"./", 2 )!=0) )
{
for( nxt_path = wcstok( cdpath_cpy, ARRAY_SEP_STR, &state );
nxt_path != 0;
nxt_path = wcstok( 0, ARRAY_SEP_STR, &state) )
{
wchar_t *nxt_completion=
wcsdupcat( nxt_path,
(nxt_path[wcslen(nxt_path)-1]==L'/'?L"":L"/"),
cmd );
if( ! nxt_completion )
{
continue;
}
if( expand_string( nxt_completion,
this->completions,
ACCEPT_INCOMPLETE | DIRECTORIES_ONLY | this->expand_flags() ) != EXPAND_ERROR )
{
}
free(nxt_completion);
}
}
}
free( cdpath_cpy );
} }
@ -1178,7 +1141,7 @@ void completer_t::complete_from_args( const wcstring &str,
if (! is_autosuggest) if (! is_autosuggest)
proc_pop_interactive(); proc_pop_interactive();
complete_strings( this->completions, str.c_str(), desc.c_str(), 0, possible_comp, flags ); complete_strings( this->completions, str, desc.c_str(), 0, possible_comp, flags );
} }
/** /**
@ -1507,7 +1470,7 @@ void completer_t::complete_param_expand( const wcstring &sstr, bool do_file)
const wchar_t * const str = sstr.c_str(); const wchar_t * const str = sstr.c_str();
const wchar_t *comp_str; const wchar_t *comp_str;
if( (wcsncmp( str, L"--", 2 )) == 0 && (comp_str = wcschr(str, L'=' ) ) ) if (string_prefixes_string( L"--", sstr) && (comp_str = wcschr(str, L'=' ) ) )
{ {
comp_str++; comp_str++;
} }

View file

@ -105,8 +105,7 @@ enum
EXPAND_WILDCARD_NO_MATCH, EXPAND_WILDCARD_NO_MATCH,
/* Ok, a wildcard in the string matched a file */ /* Ok, a wildcard in the string matched a file */
EXPAND_WILDCARD_MATCH EXPAND_WILDCARD_MATCH
} };
;
/** Character for separating two array elements. We use 30, i.e. the ascii record separator since that seems logical. */ /** Character for separating two array elements. We use 30, i.e. the ascii record separator since that seems logical. */
#define ARRAY_SEP 0x1e #define ARRAY_SEP 0x1e
@ -129,8 +128,7 @@ class parser_t;
into the list out. into the list out.
If the parameter does not need expansion, it is copied into the list If the parameter does not need expansion, it is copied into the list
out. If expansion is performed, the original parameter is freed and out.
newly allocated strings are inserted into the list out.
\param input The parameter to expand \param input The parameter to expand
\param output The list to which the result will be appended. \param output The list to which the result will be appended.

View file

@ -670,54 +670,45 @@ static wchar_t *fishd_env_get( const wchar_t *key )
to be rewritten to avoid dragging in additional library to be rewritten to avoid dragging in additional library
dependencies. dependencies.
*/ */
static wchar_t *fishd_get_config() static wcstring fishd_get_config()
{ {
wchar_t *xdg_dir, *home; wchar_t *xdg_dir, *home;
int done = 0; bool done = false;
wchar_t *res = 0; wcstring result;
xdg_dir = fishd_env_get( L"XDG_CONFIG_HOME" ); xdg_dir = fishd_env_get( L"XDG_CONFIG_HOME" );
if( xdg_dir ) if (xdg_dir)
{ {
res = wcsdupcat( xdg_dir, L"/fish" ); result = xdg_dir;
if( !create_directory( res ) ) append_path_component(result, L"/fish");
if (!create_directory(result))
{ {
done = 1; done = true;
} }
else free(xdg_dir);
{
free( res );
}
free( xdg_dir );
} }
else else
{ {
home = fishd_env_get( L"HOME" ); home = fishd_env_get( L"HOME" );
if( home ) if( home )
{ {
res = wcsdupcat( home, L"/.config/fish" ); result = home;
if( !create_directory( res ) ) append_path_component(result, L"/.config/fish");
if (!create_directory(result))
{ {
done = 1; done = 1;
} }
else
{
free( res );
}
free( home ); free( home );
} }
} }
if( done ) if (! done) {
{ /* Bad juju */
return res;
}
else
{
debug( 0, _(L"Unable to create a configuration directory for fish. Your personal settings will not be saved. Please set the $XDG_CONFIG_HOME variable to a directory where the current user has write access." )); debug( 0, _(L"Unable to create a configuration directory for fish. Your personal settings will not be saved. Please set the $XDG_CONFIG_HOME variable to a directory where the current user has write access." ));
return 0; result.clear();
} }
return result;
} }
/** /**
@ -725,41 +716,30 @@ static wchar_t *fishd_get_config()
*/ */
static void load_or_save( int save) static void load_or_save( int save)
{ {
char *name; const wcstring wdir = fishd_get_config();
wchar_t *wdir = fishd_get_config();
char *dir;
char hostname[HOSTNAME_LEN]; char hostname[HOSTNAME_LEN];
connection_t c; connection_t c;
int fd; int fd;
if( !wdir ) if (wdir.empty())
{
return; return;
}
dir = wcs2str( wdir ); std::string dir = wcs2string( wdir );
free( wdir );
gethostname( hostname, HOSTNAME_LEN ); gethostname( hostname, HOSTNAME_LEN );
name = (char *)malloc( strlen(dir)+ strlen(FILE)+ strlen(hostname) + 2 ); std::string name;
strcpy( name, dir ); name.append(dir);
strcat( name, "/" ); name.append("/");
strcat( name, FILE ); name.append(FILE);
strcat( name, hostname ); name.append(hostname);
free( dir );
debug( 4, L"Open file for %s: '%s'", debug( 4, L"Open file for %s: '%s'",
save?"saving":"loading", save?"saving":"loading",
name ); name.c_str() );
/* OK to not use CLO_EXEC here because fishd is single threaded */ /* OK to not use CLO_EXEC here because fishd is single threaded */
fd = open( name, save?(O_CREAT | O_TRUNC | O_WRONLY):O_RDONLY, 0600); fd = open(name.c_str(), save?(O_CREAT | O_TRUNC | O_WRONLY):O_RDONLY, 0600);
free( name );
if( fd == -1 ) if( fd == -1 )
{ {

View file

@ -807,7 +807,7 @@ bool autosuggest_special_validate_from_history(const wcstring &str, const wcstri
if (is_help) { if (is_help) {
suggestionOK = false; suggestionOK = false;
} else { } else {
wchar_t *path = path_allocate_cdpath(dir.c_str(), working_directory.c_str()); wchar_t *path = path_allocate_cdpath(dir, working_directory.c_str());
if (path == NULL) { if (path == NULL) {
suggestionOK = false; suggestionOK = false;
} else if (paths_are_same_file(working_directory, path)) { } else if (paths_are_same_file(working_directory, path)) {
@ -1237,8 +1237,7 @@ void highlight_shell( const wcstring &buff, std::vector<int> &color, int pos, wc
//our subcolors start at color + (begin-subbuff)+1 //our subcolors start at color + (begin-subbuff)+1
size_t start = begin - subbuff + 1, len = wcslen(begin + 1); size_t start = begin - subbuff + 1, len = wcslen(begin + 1);
std::vector<int> subcolors; std::vector<int> subcolors(len, -1);
subcolors.resize(len, -1);
highlight_shell( begin+1, subcolors, -1, error, vars ); highlight_shell( begin+1, subcolors, -1, error, vars );

View file

@ -76,8 +76,8 @@ void kill_add( const wcstring &str )
if (str.empty()) if (str.empty())
return; return;
wchar_t *cmd = NULL; wcstring cmd;
wchar_t *escaped_str; wchar_t *escaped_str = NULL;
kill_list.push_front(str); kill_list.push_front(str);
/* /*
@ -92,7 +92,9 @@ void kill_add( const wcstring &str )
if( !clipboard_wstr.missing() ) if( !clipboard_wstr.missing() )
{ {
escaped_str = escape( str.c_str(), 1 ); escaped_str = escape( str.c_str(), 1 );
cmd = wcsdupcat(L"echo -n ", escaped_str, clipboard_wstr.c_str()); cmd.assign(L"echo -n ");
cmd.append(escaped_str);
cmd.append(clipboard_wstr);
} }
else else
{ {
@ -105,13 +107,15 @@ void kill_add( const wcstring &str )
if( !disp_wstr.missing() ) if( !disp_wstr.missing() )
{ {
escaped_str = escape( str.c_str(), 1 ); escaped_str = escape( str.c_str(), 1 );
cmd = wcsdupcat(L"echo ", escaped_str, L"|xsel -b" ); cmd.assign(L"echo ");
cmd.append(escaped_str);
cmd.append(L"|xsel -b" );
} }
} }
if (cmd != NULL) if (! cmd.empty())
{ {
if( exec_subshell( cmd) == -1 ) if( exec_subshell(cmd) == -1 )
{ {
/* /*
Do nothing on failiure Do nothing on failiure
@ -119,7 +123,6 @@ void kill_add( const wcstring &str )
} }
free( cut_buffer ); free( cut_buffer );
free( cmd );
cut_buffer = escaped_str; cut_buffer = escaped_str;
} }

View file

@ -798,14 +798,8 @@ int parser_t::eval_args( const wchar_t *line, std::vector<completion_t> &args )
{ {
case TOK_STRING: case TOK_STRING:
{ {
wchar_t *tmp = wcsdup(tok_last( &tok )); const wcstring tmp = tok_last(&tok);
if( expand_string(tmp, args, eflags) == EXPAND_ERROR )
if( !tmp )
{
DIE_MEM();
}
if( expand_string( tmp, args, eflags ) == EXPAND_ERROR )
{ {
err_pos=tok_get_pos( &tok ); err_pos=tok_get_pos( &tok );
do_loop=0; do_loop=0;

View file

@ -343,12 +343,12 @@ bool path_get_cdpath_string(const wcstring &dir_str, wcstring &result, const env
} }
wchar_t *path_allocate_cdpath( const wchar_t *dir, const wchar_t *wd ) wchar_t *path_allocate_cdpath( const wcstring &dir, const wchar_t *wd )
{ {
wchar_t *res = NULL; wchar_t *res = NULL;
int err = ENOENT; int err = ENOENT;
if( !dir ) if (dir.empty())
return 0; return NULL;
if (wd) { if (wd) {
size_t len = wcslen(wd); size_t len = wcslen(wd);
@ -357,13 +357,12 @@ wchar_t *path_allocate_cdpath( const wchar_t *dir, const wchar_t *wd )
wcstring_list_t paths; wcstring_list_t paths;
if (dir[0] == L'/') { if (dir.at(0) == L'/') {
/* Absolute path */ /* Absolute path */
paths.push_back(dir); paths.push_back(dir);
} else if (wcsncmp(dir, L"./", 2) == 0 || } else if (string_prefixes_string(L"./", dir) ||
wcsncmp(dir, L"../", 3) == 0 || string_prefixes_string(L"../", dir) ||
wcscmp(dir, L".") == 0 || dir == L"." || dir == L"..") {
wcscmp(dir, L"..") == 0) {
/* Path is relative to the working directory */ /* Path is relative to the working directory */
wcstring path; wcstring path;
if (wd) if (wd)
@ -373,7 +372,6 @@ wchar_t *path_allocate_cdpath( const wchar_t *dir, const wchar_t *wd )
} else { } else {
wchar_t *path_cpy; wchar_t *path_cpy;
wchar_t *state; wchar_t *state;
wchar_t *whole_path;
// Respect CDPATH // Respect CDPATH
env_var_t path = env_get_string(L"CDPATH"); env_var_t path = env_get_string(L"CDPATH");
@ -392,25 +390,17 @@ wchar_t *path_allocate_cdpath( const wchar_t *dir, const wchar_t *wd )
nxt_path = wd; nxt_path = wd;
} }
wchar_t *expanded_path = expand_tilde_compat( wcsdup(nxt_path) ); wcstring expanded_path = nxt_path;
expand_tilde(expanded_path);
// debug( 2, L"woot %ls\n", expanded_path ); // debug( 2, L"woot %ls\n", expanded_path.c_str() );
int path_len = wcslen( expanded_path ); if (expanded_path.empty())
if( path_len == 0 )
{
free(expanded_path );
continue; continue;
}
wcstring whole_path = expanded_path;
whole_path = append_path_component(whole_path, dir);
wcsdupcat( expanded_path,
( expanded_path[path_len-1] != L'/' )?L"/":L"",
dir );
free(expanded_path );
paths.push_back(whole_path); paths.push_back(whole_path);
free( whole_path );
} }
free( path_cpy ); free( path_cpy );
} }
@ -442,7 +432,7 @@ wchar_t *path_allocate_cdpath( const wchar_t *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.c_str(), 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;

2
path.h
View file

@ -53,7 +53,7 @@ bool path_get_path_string(const wcstring &cmd, wcstring &output, const env_vars
\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, const wchar_t *wd = NULL); wchar_t *path_allocate_cdpath( const wcstring &in, const wchar_t *wd = NULL);
bool path_can_get_cdpath(const wcstring &in, const wchar_t *wd = NULL); 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);

View file

@ -938,7 +938,6 @@ static void get_param( const wchar_t *cmd,
*/ */
static wcstring completion_apply_to_command_line(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(); const wchar_t *val = val_str.c_str();
bool add_space = !(flags & COMPLETE_NO_SPACE); bool add_space = !(flags & COMPLETE_NO_SPACE);
bool do_replace = !!(flags & COMPLETE_NO_CASE); bool do_replace = !!(flags & COMPLETE_NO_CASE);
@ -988,25 +987,20 @@ static wcstring completion_apply_to_command_line(const wcstring &val_str, int fl
else else
{ {
wchar_t quote = L'\0'; wchar_t quote = L'\0';
wcstring replaced;
if( do_escape ) if( do_escape )
{ {
get_param(command_line.c_str(), cursor_pos, &quote, 0, 0, 0); get_param(command_line.c_str(), cursor_pos, &quote, 0, 0, 0);
if( quote == L'\0' ) if( quote == L'\0' )
{ {
replaced = escape( val, ESCAPE_ALL | ESCAPE_NO_QUOTED ); replaced = escape_string( val, ESCAPE_ALL | ESCAPE_NO_QUOTED );
} }
else else
{ {
bool unescapable = false; bool unescapable = false;
for (const wchar_t *pin = val; *pin; pin++)
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 ) switch (*pin )
{ {
case L'\n': case L'\n':
case L'\t': case L'\t':
@ -1015,31 +1009,26 @@ static wcstring completion_apply_to_command_line(const wcstring &val_str, int fl
unescapable = true; unescapable = true;
break; break;
default: default:
*pout++ = *pin; replaced.push_back(*pin);
break; break;
} }
} }
if (unescapable) if (unescapable)
{ {
free( replaced ); replaced = escape_string(val, ESCAPE_ALL | ESCAPE_NO_QUOTED);
wchar_t *tmp = escape( val, ESCAPE_ALL | ESCAPE_NO_QUOTED ); replaced.insert(0, &quote, 1);
replaced = wcsdupcat( L" ", tmp );
free( tmp);
replaced[0]=quote;
} }
else
*pout = 0;
} }
} }
else else
{ {
replaced = wcsdup(val); replaced = val;
} }
wcstring result = command_line; wcstring result = command_line;
result.insert(cursor_pos, replaced); result.insert(cursor_pos, replaced);
size_t new_cursor_pos = cursor_pos + wcslen(replaced); size_t new_cursor_pos = cursor_pos + replaced.size();
if (add_space) if (add_space)
{ {
if (quote && (command_line.c_str()[cursor_pos] != quote)) if (quote && (command_line.c_str()[cursor_pos] != quote))
@ -1049,7 +1038,6 @@ static wcstring completion_apply_to_command_line(const wcstring &val_str, int fl
} }
result.insert(new_cursor_pos++, L" "); result.insert(new_cursor_pos++, L" ");
} }
free(replaced);
*inout_cursor_pos = new_cursor_pos; *inout_cursor_pos = new_cursor_pos;
return result; return result;
} }
@ -1084,31 +1072,29 @@ static void completion_insert( const wchar_t *val, int flags )
\param comp the list of completions to display \param comp the list of completions to display
*/ */
static void run_pager( wchar_t *prefix, int is_quoted, const std::vector<completion_t> &comp ) static void run_pager( const wcstring &prefix, int is_quoted, const std::vector<completion_t> &comp )
{ {
wcstring msg; wcstring msg;
wchar_t * prefix_esc; wcstring prefix_esc;
char *foo; char *foo;
io_data_t *in; io_data_t *in;
wchar_t *escaped_separator; wchar_t *escaped_separator;
int has_case_sensitive=0; int has_case_sensitive=0;
if( !prefix || (wcslen(prefix)==0)) if (prefix.empty())
{ {
prefix_esc = wcsdup(L"\"\""); prefix_esc = L"\"\"";
} }
else else
{ {
prefix_esc = escape( prefix,1); prefix_esc = escape_string(prefix, 1);
} }
wcstring cmd = format_string(L"fish_pager -c 3 -r 4 %ls -p %ls", wcstring cmd = format_string(L"fish_pager -c 3 -r 4 %ls -p %ls",
// L"valgrind --track-fds=yes --log-file=pager.txt --leak-check=full ./fish_pager %d %ls", // L"valgrind --track-fds=yes --log-file=pager.txt --leak-check=full ./fish_pager %d %ls",
is_quoted?L"-q":L"", is_quoted?L"-q":L"",
prefix_esc ); prefix_esc.c_str() );
free(prefix_esc);
in= io_buffer_create( 1 ); in= io_buffer_create( 1 );
in->fd = 3; in->fd = 3;
@ -1611,7 +1597,7 @@ static int handle_completions( const std::vector<completion_t> &comp )
is true, so we print the list is true, so we print the list
*/ */
int len; int len;
wchar_t * prefix; wcstring prefix;
const wchar_t * prefix_start; const wchar_t * prefix_start;
const wchar_t *buff = data->command_line.c_str(); const wchar_t *buff = data->command_line.c_str();
get_param( buff, get_param( buff,
@ -1625,23 +1611,12 @@ static int handle_completions( const std::vector<completion_t> &comp )
if( len <= PREFIX_MAX_LEN ) if( len <= PREFIX_MAX_LEN )
{ {
prefix = (wchar_t *)malloc( sizeof(wchar_t)*(len+1) ); prefix.append(prefix_start, len);
wcslcpy( prefix, prefix_start, len );
prefix[len]=L'\0';
} }
else else
{ {
wchar_t tmp[2]= prefix = wcstring(&ellipsis_char, 1);
{ prefix.append(prefix_start + (len - PREFIX_MAX_LEN));
ellipsis_char,
0
}
;
prefix = wcsdupcat( tmp,
prefix_start + (len - PREFIX_MAX_LEN) );
prefix[PREFIX_MAX_LEN] = 0;
} }
{ {
@ -1656,8 +1631,6 @@ static int handle_completions( const std::vector<completion_t> &comp )
run_pager( prefix, is_quoted, comp ); run_pager( prefix, is_quoted, comp );
} }
free( prefix );
s_reset( &data->screen, true); s_reset( &data->screen, true);
reader_repaint(); reader_repaint();

View file

@ -199,54 +199,49 @@ static int wildcard_match2( const wcstring &str_str,
possible completion of the string, the remainder of the string is possible completion of the string, the remainder of the string is
inserted into the out vector. inserted into the out vector.
*/ */
static int wildcard_complete_internal( const wchar_t *orig, static bool wildcard_complete_internal(const wcstring &orig,
const wchar_t *str, const wchar_t *str,
const wchar_t *wc, const wchar_t *wc,
int is_first, bool is_first,
const wchar_t *desc, const wchar_t *desc,
const wchar_t *(*desc_func)(const wcstring &), const wchar_t *(*desc_func)(const wcstring &),
std::vector<completion_t> &out, std::vector<completion_t> &out,
int flags ) int flags )
{ {
if( !wc || !str || !orig) if( !wc || ! str || orig.empty())
{ {
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ ); debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
return 0; return 0;
} }
if( *wc == 0 && if( *wc == 0 &&
( ( *str != L'.') || (!is_first)) ) ( (str[0] != L'.') || (!is_first)) )
{ {
wchar_t *out_completion = 0; wcstring out_completion;
const wchar_t *out_desc = desc; wcstring out_desc = (desc ? desc : L"");
if( flags & COMPLETE_NO_CASE ) if( flags & COMPLETE_NO_CASE )
{ {
out_completion = wcsdup( orig ); out_completion = orig;
} }
else else
{ {
out_completion = wcsdup( str ); out_completion = str;
} }
if( wcschr( str, PROG_COMPLETE_SEP ) ) size_t complete_sep_loc = out_completion.find(PROG_COMPLETE_SEP);
if (complete_sep_loc != wcstring::npos)
{ {
/* /* This completion has an embedded description, do not use the generic description */
This completion has an embedded description, du not use the generic description out_desc.assign(out_completion, complete_sep_loc + 1, out_completion.size() - complete_sep_loc - 1);
*/ out_completion.resize(complete_sep_loc);
wchar_t *sep;
sep = wcschr(out_completion, PROG_COMPLETE_SEP );
*sep = 0;
out_desc = sep + 1;
} }
else else
{ {
if( desc_func ) if( desc_func )
{ {
/* /*
A descripton generating function is specified, call A description generating function is specified, call
it. If it returns something, use that as the it. If it returns something, use that as the
description. description.
*/ */
@ -257,36 +252,33 @@ static int wildcard_complete_internal( const wchar_t *orig,
} }
if(out_completion) if (! out_completion.empty())
{ {
completion_allocate( out, completion_allocate( out,
out_completion, out_completion,
out_desc ? out_desc : L"", out_desc,
flags ); flags );
} }
return true;
free ( out_completion );
return 1;
} }
if( *wc == ANY_STRING ) if( *wc == ANY_STRING )
{ {
int res=0; bool res=false;
/* Ignore hidden file */ /* Ignore hidden file */
if( is_first && str[0] == L'.' ) if( is_first && str[0] == L'.' )
return 0; return false;
/* Try all submatches */ /* Try all submatches */
do do
{ {
res |= wildcard_complete_internal( orig, str, wc+1, 0, desc, desc_func, out, flags ); res = wildcard_complete_internal( orig, str, wc+1, 0, desc, desc_func, out, flags );
if( res ) if (res)
break; break;
} }
while( *str++ != 0 ); while (*str++ != 0);
return res; return res;
} }
@ -302,20 +294,18 @@ static int wildcard_complete_internal( const wchar_t *orig,
{ {
return wildcard_complete_internal( orig, str+1, wc+1, 0, desc, desc_func, out, flags | COMPLETE_NO_CASE ); return wildcard_complete_internal( orig, str+1, wc+1, 0, desc, desc_func, out, flags | COMPLETE_NO_CASE );
} }
return 0; return false;
} }
int wildcard_complete( const wchar_t *str, bool wildcard_complete(const wcstring &str,
const wchar_t *wc, const wchar_t *wc,
const wchar_t *desc, const wchar_t *desc,
const wchar_t *(*desc_func)(const wcstring &), const wchar_t *(*desc_func)(const wcstring &),
std::vector<completion_t> &out, std::vector<completion_t> &out,
int flags ) int flags )
{ {
int res; bool res;
res = wildcard_complete_internal( str, str.c_str(), wc, true, desc, desc_func, out, flags );
res = wildcard_complete_internal( str, str, wc, 1, desc, desc_func, out, flags );
return res; return res;
} }
@ -570,15 +560,14 @@ static wcstring file_get_desc( const wchar_t *filename,
*/ */
static void wildcard_completion_allocate( std::vector<completion_t> &list, static void wildcard_completion_allocate( std::vector<completion_t> &list,
const wcstring &fullname, const wcstring &fullname,
const wchar_t *completion, const wcstring &completion,
const wchar_t *wc, const wchar_t *wc,
expand_flags_t expand_flags) expand_flags_t expand_flags)
{ {
struct stat buf, lbuf; struct stat buf, lbuf;
wcstring sb; wcstring sb;
wcstring munged_completion;
int free_completion = 0;
int flags = 0; int flags = 0;
int stat_res, lstat_res; int stat_res, lstat_res;
int stat_errno=0; int stat_errno=0;
@ -593,12 +582,13 @@ static void wildcard_completion_allocate( std::vector<completion_t> &list,
*/ */
if( ( lstat_res = lwstat( fullname, &lbuf ) ) ) if( ( lstat_res = lwstat( fullname, &lbuf ) ) )
{ {
/* lstat failed! */
sz=-1; sz=-1;
stat_res = lstat_res; stat_res = lstat_res;
} }
else else
{ {
if( S_ISLNK(lbuf.st_mode)) if (S_ISLNK(lbuf.st_mode))
{ {
if( ( stat_res = wstat( fullname, &buf ) ) ) if( ( stat_res = wstat( fullname, &buf ) ) )
@ -630,9 +620,9 @@ static void wildcard_completion_allocate( std::vector<completion_t> &list,
if( sz >= 0 && S_ISDIR(buf.st_mode) ) if( sz >= 0 && S_ISDIR(buf.st_mode) )
{ {
free_completion = 1;
flags = flags | COMPLETE_NO_SPACE; flags = flags | COMPLETE_NO_SPACE;
completion = wcsdupcat( completion, L"/" ); munged_completion = completion;
munged_completion.push_back(L'/');
sb.append(desc); sb.append(desc);
} }
else else
@ -641,10 +631,9 @@ static void wildcard_completion_allocate( std::vector<completion_t> &list,
sb.append(L", "); sb.append(L", ");
sb.append(format_size(sz)); sb.append(format_size(sz));
} }
wildcard_complete( completion, wc, sb.c_str(), NULL, list, flags ); const wcstring &completion_to_use = munged_completion.empty() ? completion : munged_completion;
if( free_completion ) wildcard_complete(completion_to_use, wc, sb.c_str(), NULL, list, flags);
free( (void *)completion );
} }
/** /**
@ -790,7 +779,7 @@ static int wildcard_expand_internal( const wchar_t *wc,
{ {
wildcard_completion_allocate( out, wildcard_completion_allocate( out,
long_name, long_name,
next.c_str(), next,
L"", L"",
flags); flags);
} }
@ -812,7 +801,7 @@ static int wildcard_expand_internal( const wchar_t *wc,
This is the last wildcard segment, and it is not empty. Match files/directories. This is the last wildcard segment, and it is not empty. Match files/directories.
*/ */
wcstring next; wcstring next;
while(wreaddir(dir, next)) while (wreaddir(dir, next))
{ {
const wchar_t * const name = next.c_str(); const wchar_t * const name = next.c_str();
if( flags & ACCEPT_INCOMPLETE ) if( flags & ACCEPT_INCOMPLETE )

View file

@ -86,7 +86,7 @@ int wildcard_has( const wchar_t *str, int internal );
/** /**
Test wildcard completion Test wildcard completion
*/ */
int wildcard_complete( const wchar_t *str, bool wildcard_complete(const wcstring &str,
const wchar_t *wc, const wchar_t *wc,
const wchar_t *desc, const wchar_t *desc,
const wchar_t *(*desc_func)(const wcstring &), const wchar_t *(*desc_func)(const wcstring &),