mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 04:43:10 +00:00
Some work to allow completions to be evaluated off of the main thread
This commit is contained in:
parent
90e979d0d9
commit
a515db4aea
12 changed files with 144 additions and 129 deletions
|
@ -547,7 +547,7 @@ static int builtin_complete( parser_t &parser, wchar_t **argv )
|
|||
{
|
||||
recursion_level++;
|
||||
|
||||
complete( do_complete, comp );
|
||||
complete( do_complete, comp, COMPLETE_DEFAULT );
|
||||
|
||||
for( size_t i=0; i< comp.size() ; i++ )
|
||||
{
|
||||
|
|
12
common.cpp
12
common.cpp
|
@ -2070,5 +2070,15 @@ void assert_is_background_thread(const char *who)
|
|||
if (is_main_thread()) {
|
||||
fprintf(stderr, "Warning: %s called on the main thread (may block!). Break on debug_thread_error to debug.\n", who);
|
||||
debug_thread_error();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void assert_is_locked(void *vmutex, const char *who)
|
||||
{
|
||||
pthread_mutex_t *mutex = static_cast<pthread_mutex_t*>(vmutex);
|
||||
if (0 == pthread_mutex_trylock(mutex)) {
|
||||
fprintf(stderr, "Warning: %s is not locked when it should be. Break on debug_thread_error to debug.\n", who);
|
||||
debug_thread_error();
|
||||
pthread_mutex_unlock(mutex);
|
||||
}
|
||||
}
|
||||
|
|
3
common.h
3
common.h
|
@ -258,6 +258,9 @@ void assert_is_background_thread(const char *who);
|
|||
#define ASSERT_IS_BACKGROUND_THREAD_TRAMPOLINE(x) assert_is_background_thread(x)
|
||||
#define ASSERT_IS_BACKGROUND_THREAD() ASSERT_IS_BACKGROUND_THREAD_TRAMPOLINE(__FUNCTION__)
|
||||
|
||||
/* Useful macro for asserting that a lock is locked. This doesn't check whether this thread locked it, which it would be nice if it did, but here it is anyways. */
|
||||
void assert_is_locked(void *mutex, const char *who);
|
||||
#define ASSERT_IS_LOCKED(x) assert_is_locked((void *)(&x), #x)
|
||||
|
||||
/**
|
||||
Converts the wide character string \c in into it's narrow
|
||||
|
|
83
complete.cpp
83
complete.cpp
|
@ -20,7 +20,7 @@
|
|||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "fallback.h"
|
||||
#include "util.h"
|
||||
|
@ -176,6 +176,7 @@ struct completion_entry_t
|
|||
/** Linked list of all completion entries */
|
||||
typedef std::list<completion_entry_t *> completion_entry_list_t;
|
||||
static completion_entry_list_t completion_entries;
|
||||
static pthread_mutex_t completion_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
/**
|
||||
Table of completions conditions that have already been tested and
|
||||
|
@ -259,12 +260,10 @@ static int condition_test( const wcstring &condition )
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
Search for an exactly matching completion entry
|
||||
*/
|
||||
static completion_entry_t *complete_find_exact_entry( const wchar_t *cmd,
|
||||
const int cmd_type )
|
||||
/** Search for an exactly matching completion entry. Must be called while locked. */
|
||||
static completion_entry_t *complete_find_exact_entry( const wchar_t *cmd, const int cmd_type )
|
||||
{
|
||||
ASSERT_IS_LOCKED(completion_lock);
|
||||
for (completion_entry_list_t::iterator iter = completion_entries.begin(); iter != completion_entries.end(); iter++)
|
||||
{
|
||||
completion_entry_t *entry = *iter;
|
||||
|
@ -274,16 +273,14 @@ static completion_entry_t *complete_find_exact_entry( const wchar_t *cmd,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
Locate the specified entry. Create it if it doesn't exist.
|
||||
*/
|
||||
static completion_entry_t *complete_get_exact_entry( const wchar_t *cmd,
|
||||
int cmd_type )
|
||||
/** Locate the specified entry. Create it if it doesn't exist. Must be called while locked. */
|
||||
static completion_entry_t *complete_get_exact_entry( const wchar_t *cmd, int cmd_type )
|
||||
{
|
||||
ASSERT_IS_LOCKED(completion_lock);
|
||||
completion_entry_t *c;
|
||||
|
||||
complete_init();
|
||||
|
||||
|
||||
c = complete_find_exact_entry( cmd, cmd_type );
|
||||
|
||||
if( c == NULL )
|
||||
|
@ -307,6 +304,7 @@ void complete_set_authoritative( const wchar_t *cmd,
|
|||
completion_entry_t *c;
|
||||
|
||||
CHECK( cmd, );
|
||||
scoped_lock lock(completion_lock);
|
||||
c = complete_get_exact_entry( cmd, cmd_type );
|
||||
c->authoritative = authoritative;
|
||||
}
|
||||
|
@ -324,7 +322,8 @@ void complete_add( const wchar_t *cmd,
|
|||
int flags )
|
||||
{
|
||||
CHECK( cmd, );
|
||||
|
||||
|
||||
scoped_lock lock(completion_lock);
|
||||
completion_entry_t *c;
|
||||
c = complete_get_exact_entry( cmd, cmd_type );
|
||||
|
||||
|
@ -356,11 +355,11 @@ void complete_add( const wchar_t *cmd,
|
|||
/**
|
||||
Remove all completion options in the specified entry that match the
|
||||
specified short / long option strings. Returns true if it is now
|
||||
empty and should be deleted, false if it's not empty.
|
||||
empty and should be deleted, false if it's not empty. Must be called while locked.
|
||||
*/
|
||||
static bool complete_remove_entry( completion_entry_t *e, wchar_t short_opt, const wchar_t *long_opt )
|
||||
{
|
||||
|
||||
ASSERT_IS_LOCKED(completion_lock);
|
||||
if(( short_opt == 0 ) && (long_opt == 0 ) )
|
||||
{
|
||||
e->options.clear();
|
||||
|
@ -410,6 +409,7 @@ void complete_remove( const wchar_t *cmd,
|
|||
const wchar_t *long_opt )
|
||||
{
|
||||
CHECK( cmd, );
|
||||
scoped_lock lock(completion_lock);
|
||||
for (completion_entry_list_t::iterator iter = completion_entries.begin(); iter != completion_entries.end(); ) {
|
||||
completion_entry_t *e = *iter;
|
||||
bool delete_it = false;
|
||||
|
@ -529,7 +529,8 @@ int complete_is_valid_option( const wchar_t *str,
|
|||
Make sure completions are loaded for the specified command
|
||||
*/
|
||||
if (allow_autoload) complete_load( cmd, false );
|
||||
|
||||
|
||||
scoped_lock lock(completion_lock);
|
||||
for (completion_entry_list_t::iterator iter = completion_entries.begin(); iter != completion_entries.end(); iter++)
|
||||
{
|
||||
const completion_entry_t *i = *iter;
|
||||
|
@ -741,6 +742,8 @@ static void complete_strings( std::vector<completion_t> &comp_out,
|
|||
*/
|
||||
static void complete_cmd_desc( const wchar_t *cmd, std::vector<completion_t> &comp )
|
||||
{
|
||||
ASSERT_IS_MAIN_THREAD();
|
||||
|
||||
const wchar_t *cmd_start;
|
||||
int cmd_len;
|
||||
int skip;
|
||||
|
@ -886,7 +889,8 @@ static void complete_cmd( const wchar_t *cmd,
|
|||
std::vector<completion_t> &comp,
|
||||
int use_function,
|
||||
int use_builtin,
|
||||
int use_command )
|
||||
int use_command,
|
||||
complete_type_t type )
|
||||
{
|
||||
wchar_t *path_cpy;
|
||||
wchar_t *nxt_path;
|
||||
|
@ -896,10 +900,12 @@ static void complete_cmd( const wchar_t *cmd,
|
|||
|
||||
wchar_t *cdpath_cpy = wcsdup(L".");
|
||||
|
||||
const bool wants_description = (type == COMPLETE_DEFAULT);
|
||||
|
||||
if( (wcschr( cmd, L'/') != 0) || (cmd[0] == L'~' ) )
|
||||
{
|
||||
|
||||
if( use_command )
|
||||
if( use_command && wants_description )
|
||||
{
|
||||
|
||||
if( expand_string(cmd, comp, ACCEPT_INCOMPLETE | EXECUTABLES_ONLY ) != EXPAND_ERROR )
|
||||
|
@ -941,8 +947,7 @@ static void complete_cmd( const wchar_t *cmd,
|
|||
|
||||
prev_count = comp.size() ;
|
||||
|
||||
if( expand_string(
|
||||
nxt_completion,
|
||||
if( expand_string( nxt_completion,
|
||||
comp,
|
||||
ACCEPT_INCOMPLETE |
|
||||
EXECUTABLES_ONLY ) != EXPAND_ERROR )
|
||||
|
@ -958,7 +963,8 @@ static void complete_cmd( const wchar_t *cmd,
|
|||
}
|
||||
}
|
||||
free( path_cpy );
|
||||
complete_cmd_desc( cmd, comp );
|
||||
if (wants_description)
|
||||
complete_cmd_desc( cmd, comp );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1157,7 +1163,8 @@ static int complete_param( const wchar_t *cmd_orig,
|
|||
const wchar_t *popt,
|
||||
const wchar_t *str,
|
||||
int use_switches,
|
||||
std::vector<completion_t> &comp_out )
|
||||
complete_type_t type,
|
||||
std::vector<completion_t> &comp_out)
|
||||
{
|
||||
|
||||
int use_common=1, use_files=1;
|
||||
|
@ -1165,7 +1172,8 @@ static int complete_param( const wchar_t *cmd_orig,
|
|||
wcstring cmd, path;
|
||||
parse_cmd_string(cmd_orig, path, cmd);
|
||||
|
||||
complete_load( cmd, true );
|
||||
if (type == COMPLETE_DEFAULT)
|
||||
complete_load( cmd, true );
|
||||
|
||||
for (completion_entry_list_t::iterator iter = completion_entries.begin(); iter != completion_entries.end(); iter++)
|
||||
{
|
||||
|
@ -1362,9 +1370,7 @@ static int complete_param( const wchar_t *cmd_orig,
|
|||
/**
|
||||
Perform file completion on the specified string
|
||||
*/
|
||||
static void complete_param_expand( const wchar_t *str,
|
||||
std::vector<completion_t> &comp_out,
|
||||
int do_file )
|
||||
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;
|
||||
|
@ -1377,10 +1383,14 @@ static void complete_param_expand( const wchar_t *str,
|
|||
{
|
||||
comp_str = str;
|
||||
}
|
||||
|
||||
flags = EXPAND_SKIP_CMDSUBST |
|
||||
ACCEPT_INCOMPLETE |
|
||||
(do_file?0:EXPAND_SKIP_WILDCARDS);
|
||||
|
||||
flags = EXPAND_SKIP_CMDSUBST | ACCEPT_INCOMPLETE;
|
||||
|
||||
if (! do_file)
|
||||
flags |= EXPAND_SKIP_WILDCARDS;
|
||||
|
||||
if (type == COMPLETE_AUTOSUGGEST)
|
||||
flags |= EXPAND_NO_DESCRIPTIONS;
|
||||
|
||||
if( expand_string( comp_str,
|
||||
comp_out,
|
||||
|
@ -1553,8 +1563,7 @@ static int try_complete_user( const wchar_t *cmd,
|
|||
return res;
|
||||
}
|
||||
|
||||
void complete( const wchar_t *cmd,
|
||||
std::vector<completion_t> &comp )
|
||||
void complete( const wchar_t *cmd, std::vector<completion_t> &comp, complete_type_t type )
|
||||
{
|
||||
|
||||
const wchar_t *tok_begin, *tok_end, *cmdsubst_begin, *cmdsubst_end, *prev_begin, *prev_end;
|
||||
|
@ -1610,7 +1619,7 @@ void complete( const wchar_t *cmd,
|
|||
int had_cmd=0;
|
||||
int end_loop=0;
|
||||
|
||||
tok_init( &tok, buff.c_str(), TOK_ACCEPT_UNFINISHED );
|
||||
tok_init( &tok, buff.c_str(), TOK_ACCEPT_UNFINISHED | TOK_SQUASH_ERRORS );
|
||||
|
||||
while( tok_has_next( &tok) && !end_loop )
|
||||
{
|
||||
|
@ -1765,8 +1774,7 @@ void complete( const wchar_t *cmd,
|
|||
if( on_command )
|
||||
{
|
||||
/* Complete command filename */
|
||||
complete_cmd( current_token,
|
||||
comp, use_function, use_builtin, use_command );
|
||||
complete_cmd( current_token, comp, use_function, use_builtin, use_command, type );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1781,7 +1789,8 @@ void complete( const wchar_t *cmd,
|
|||
do_file = complete_param( current_command_unescape,
|
||||
prev_token_unescape,
|
||||
current_token_unescape,
|
||||
!had_ddash,
|
||||
!had_ddash,
|
||||
type,
|
||||
comp );
|
||||
}
|
||||
|
||||
|
@ -1799,7 +1808,7 @@ void complete( const wchar_t *cmd,
|
|||
/*
|
||||
This function wants the unescaped string
|
||||
*/
|
||||
complete_param_expand( current_token, comp, do_file );
|
||||
complete_param_expand( current_token, comp, do_file, type );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
11
complete.h
11
complete.h
|
@ -148,6 +148,10 @@ public:
|
|||
bool operator != (const completion_t& rhs) const { return ! (*this == rhs); }
|
||||
};
|
||||
|
||||
enum complete_type_t {
|
||||
COMPLETE_DEFAULT,
|
||||
COMPLETE_AUTOSUGGEST
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
|
@ -218,10 +222,9 @@ void complete_remove( const wchar_t *cmd,
|
|||
wchar_t short_opt,
|
||||
const wchar_t *long_opt );
|
||||
|
||||
/**
|
||||
Find all completions of the command cmd, insert them into out.
|
||||
*/
|
||||
void complete( const wchar_t* cmd, std::vector<completion_t> &out);
|
||||
|
||||
/** Find all completions of the command cmd, insert them into out. */
|
||||
void complete( const wchar_t* cmd, std::vector<completion_t> &out, complete_type_t type);
|
||||
|
||||
/**
|
||||
Print a list of all current completions into the string_buffer_t.
|
||||
|
|
|
@ -1429,7 +1429,7 @@ static void remove_internal_separator2( wcstring &s, int conv )
|
|||
}
|
||||
|
||||
|
||||
int expand_string( const wcstring &input, std::vector<completion_t> &output, int flags )
|
||||
int expand_string( const wcstring &input, std::vector<completion_t> &output, expand_flags_t flags )
|
||||
{
|
||||
parser_t parser(PARSER_TYPE_ERRORS_ONLY);
|
||||
std::vector<completion_t> list1, list2;
|
||||
|
@ -1639,7 +1639,7 @@ int expand_string( const wcstring &input, std::vector<completion_t> &output, int
|
|||
return res;
|
||||
}
|
||||
|
||||
bool expand_one(wcstring &string, int flags) {
|
||||
bool expand_one(wcstring &string, expand_flags_t flags) {
|
||||
std::vector<completion_t> completions;
|
||||
bool result = false;
|
||||
|
||||
|
|
62
expand.h
62
expand.h
|
@ -21,40 +21,34 @@
|
|||
#include "common.h"
|
||||
#include <list>
|
||||
|
||||
/**
|
||||
Flag specifying that cmdsubst expansion should be skipped
|
||||
*/
|
||||
#define EXPAND_SKIP_CMDSUBST 1
|
||||
enum {
|
||||
/** Flag specifying that cmdsubst expansion should be skipped */
|
||||
EXPAND_SKIP_CMDSUBST = 1 << 0,
|
||||
|
||||
/** Flag specifying that variable expansion should be skipped */
|
||||
EXPAND_SKIP_VARIABLES = 1 << 1,
|
||||
|
||||
/** Flag specifying that wildcard expansion should be skipped */
|
||||
EXPAND_SKIP_WILDCARDS = 1 << 2,
|
||||
|
||||
/**
|
||||
Flag specifying that variable expansion should be skipped
|
||||
*/
|
||||
#define EXPAND_SKIP_VARIABLES 2
|
||||
/**
|
||||
Incomplete matches in the last segment are ok (for tab
|
||||
completion). An incomplete match is a wildcard that matches a
|
||||
prefix of the filename. If accept_incomplete is true, only the
|
||||
remainder of the string is returned.
|
||||
*/
|
||||
ACCEPT_INCOMPLETE = 1 << 3,
|
||||
|
||||
/**
|
||||
Flag specifying that wildcard expansion should be skipped
|
||||
*/
|
||||
#define EXPAND_SKIP_WILDCARDS 4
|
||||
|
||||
/**
|
||||
Incomplete matches in the last segment are ok (for tab
|
||||
completion). An incomplete match is a wildcard that matches a
|
||||
prefix of the filename. If accept_incomplete is true, only the
|
||||
remainder of the string is returned.
|
||||
*/
|
||||
#define ACCEPT_INCOMPLETE 8
|
||||
|
||||
/**
|
||||
Only match files that are executable by the current user. Only applicable together with ACCEPT_INCOMPLETE.
|
||||
*/
|
||||
|
||||
#define EXECUTABLES_ONLY 16
|
||||
|
||||
/**
|
||||
Only match directories. Only applicable together with ACCEPT_INCOMPLETE.
|
||||
*/
|
||||
|
||||
#define DIRECTORIES_ONLY 32
|
||||
/** Only match files that are executable by the current user. Only applicable together with ACCEPT_INCOMPLETE. */
|
||||
EXECUTABLES_ONLY = 1 << 4,
|
||||
|
||||
/** Only match directories. Only applicable together with ACCEPT_INCOMPLETE. */
|
||||
DIRECTORIES_ONLY = 1 << 5,
|
||||
|
||||
/** Don't generate descriptions */
|
||||
EXPAND_NO_DESCRIPTIONS = 1 << 6
|
||||
};
|
||||
typedef int expand_flags_t;
|
||||
|
||||
/**
|
||||
Use unencoded private-use keycodes for internal characters
|
||||
|
@ -143,7 +137,7 @@ class parser_t;
|
|||
\param flag Specifies if any expansion pass should be skipped. Legal values are any combination of EXPAND_SKIP_CMDSUBST EXPAND_SKIP_VARIABLES and EXPAND_SKIP_WILDCARDS
|
||||
\return One of EXPAND_OK, EXPAND_ERROR, EXPAND_WILDCARD_MATCH and EXPAND_WILDCARD_NO_MATCH. EXPAND_WILDCARD_NO_MATCH and EXPAND_WILDCARD_MATCH are normal exit conditions used only on strings containing wildcards to tell if the wildcard produced any matches.
|
||||
*/
|
||||
__warn_unused int expand_string( const wcstring &input, std::vector<completion_t> &output, int flag );
|
||||
__warn_unused int expand_string( const wcstring &input, std::vector<completion_t> &output, expand_flags_t flags );
|
||||
|
||||
|
||||
/**
|
||||
|
@ -155,7 +149,7 @@ __warn_unused int expand_string( const wcstring &input, std::vector<completion_t
|
|||
\param flag Specifies if any expansion pass should be skipped. Legal values are any combination of EXPAND_SKIP_CMDSUBST EXPAND_SKIP_VARIABLES and EXPAND_SKIP_WILDCARDS
|
||||
\return Whether expansion succeded
|
||||
*/
|
||||
bool expand_one( wcstring &inout_str, int flag );
|
||||
bool expand_one( wcstring &inout_str, expand_flags_t flags );
|
||||
|
||||
/**
|
||||
Convert the variable value to a human readable form, i.e. escape things, handle arrays, etc. Suitable for pretty-printing. The result must be free'd!
|
||||
|
|
12
reader.cpp
12
reader.cpp
|
@ -258,8 +258,7 @@ class reader_data_t
|
|||
/**
|
||||
Function for tab completion
|
||||
*/
|
||||
void (*complete_func)( const wchar_t *,
|
||||
std::vector<completion_t>& );
|
||||
complete_function_t complete_func;
|
||||
|
||||
/**
|
||||
Function for syntax highlighting
|
||||
|
@ -1235,6 +1234,10 @@ 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;
|
||||
|
@ -2299,8 +2302,7 @@ void reader_set_prompt( const wchar_t *new_prompt )
|
|||
data->prompt = new_prompt;
|
||||
}
|
||||
|
||||
void reader_set_complete_function( void (*f)( const wchar_t *,
|
||||
std::vector<completion_t>& ) )
|
||||
void reader_set_complete_function( complete_function_t f )
|
||||
{
|
||||
data->complete_func = f;
|
||||
}
|
||||
|
@ -2828,7 +2830,7 @@ const wchar_t *reader_readline()
|
|||
buffcpy = wcsndup( begin, len );
|
||||
|
||||
// comp = al_halloc( 0 );
|
||||
data->complete_func( buffcpy, comp );
|
||||
data->complete_func( buffcpy, comp, COMPLETE_DEFAULT );
|
||||
|
||||
sort_completion_list( comp );
|
||||
remove_duplicates( comp );
|
||||
|
|
4
reader.h
4
reader.h
|
@ -15,6 +15,7 @@
|
|||
#include "util.h"
|
||||
#include "io.h"
|
||||
#include "common.h"
|
||||
#include "complete.h"
|
||||
|
||||
class parser_t;
|
||||
class completion_t;
|
||||
|
@ -132,7 +133,8 @@ void reader_pop();
|
|||
- The command to be completed as a null terminated array of wchar_t
|
||||
- An array_list_t in which completions will be inserted.
|
||||
*/
|
||||
void reader_set_complete_function( void (*f)( const wchar_t *, std::vector<completion_t> & ) );
|
||||
typedef void (*complete_function_t)( const wchar_t *, std::vector<completion_t> &, complete_type_t );
|
||||
void reader_set_complete_function( complete_function_t );
|
||||
|
||||
/**
|
||||
The type of a highlight function.
|
||||
|
|
42
wildcard.cpp
42
wildcard.cpp
|
@ -573,7 +573,7 @@ static void wildcard_completion_allocate( std::vector<completion_t> &list,
|
|||
const wcstring &fullname,
|
||||
const wchar_t *completion,
|
||||
const wchar_t *wc,
|
||||
int is_cmd )
|
||||
expand_flags_t expand_flags)
|
||||
{
|
||||
struct stat buf, lbuf;
|
||||
wcstring sb;
|
||||
|
@ -625,8 +625,10 @@ static void wildcard_completion_allocate( std::vector<completion_t> &list,
|
|||
}
|
||||
}
|
||||
|
||||
wcstring desc = file_get_desc( fullname.c_str(), lstat_res, lbuf, stat_res, buf, stat_errno );
|
||||
|
||||
wcstring desc;
|
||||
if (! (expand_flags & EXPAND_NO_DESCRIPTIONS))
|
||||
desc = file_get_desc( fullname.c_str(), lstat_res, lbuf, stat_res, buf, stat_errno );
|
||||
|
||||
if( sz >= 0 && S_ISDIR(buf.st_mode) )
|
||||
{
|
||||
free_completion = 1;
|
||||
|
@ -688,7 +690,7 @@ static int test_flags( const wchar_t *filename,
|
|||
*/
|
||||
static int wildcard_expand_internal( const wchar_t *wc,
|
||||
const wchar_t *base_dir,
|
||||
int flags,
|
||||
expand_flags_t flags,
|
||||
std::vector<completion_t> &out )
|
||||
{
|
||||
|
||||
|
@ -797,7 +799,7 @@ static int wildcard_expand_internal( const wchar_t *wc,
|
|||
long_name,
|
||||
next.c_str(),
|
||||
L"",
|
||||
flags & EXECUTABLES_ONLY );
|
||||
flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -842,7 +844,7 @@ static int wildcard_expand_internal( const wchar_t *wc,
|
|||
long_name,
|
||||
name,
|
||||
wc,
|
||||
flags & EXECUTABLES_ONLY );
|
||||
flags);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1058,7 +1060,7 @@ static int wildcard_expand_internal( const wchar_t *wc,
|
|||
|
||||
int wildcard_expand( const wchar_t *wc,
|
||||
const wchar_t *base_dir,
|
||||
int flags,
|
||||
expand_flags_t flags,
|
||||
std::vector<completion_t> &out )
|
||||
{
|
||||
size_t c = out.size();
|
||||
|
@ -1066,17 +1068,12 @@ int wildcard_expand( const wchar_t *wc,
|
|||
|
||||
if( flags & ACCEPT_INCOMPLETE )
|
||||
{
|
||||
const wchar_t *wc_base=L"";
|
||||
wcstring wc_base;
|
||||
const wchar_t *wc_base_ptr = wcsrchr( wc, L'/' );
|
||||
string_buffer_t sb;
|
||||
|
||||
|
||||
if( wc_base_ptr )
|
||||
{
|
||||
wc_base = wcsndup( wc, (wc_base_ptr-wc)+1 );
|
||||
wc_base = wcstring(wc, (wc_base_ptr-wc)+1);
|
||||
}
|
||||
|
||||
sb_init( &sb );
|
||||
|
||||
for( size_t i=c; i<out.size(); i++ )
|
||||
{
|
||||
|
@ -1084,25 +1081,14 @@ int wildcard_expand( const wchar_t *wc,
|
|||
|
||||
if( c.flags & COMPLETE_NO_CASE )
|
||||
{
|
||||
sb_clear( &sb );
|
||||
sb_printf( &sb, L"%ls%ls%ls", base_dir, wc_base, c.completion.c_str() );
|
||||
|
||||
c.completion = (wchar_t *)sb.buff;
|
||||
c.completion = format_string(L"%ls%ls%ls", base_dir, wc_base.c_str(), c.completion.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
sb_destroy( &sb );
|
||||
|
||||
if( wc_base_ptr )
|
||||
{
|
||||
free( (void *)wc_base );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int wildcard_expand_string(const wcstring &wc, const wcstring &base_dir, int flags, std::vector<completion_t> &outputs )
|
||||
int wildcard_expand_string(const wcstring &wc, const wcstring &base_dir, expand_flags_t flags, std::vector<completion_t> &outputs )
|
||||
{
|
||||
std::vector<completion_t> lst;
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "util.h"
|
||||
#include "common.h"
|
||||
#include "expand.h"
|
||||
|
||||
/*
|
||||
Use unencoded private-use keycodes for internal characters
|
||||
|
@ -66,7 +67,7 @@ enum
|
|||
\return 1 if matches where found, 0 otherwise. Return -1 on abort (I.e. ^C was pressed).
|
||||
|
||||
*/
|
||||
int wildcard_expand_string(const wcstring &wc, const wcstring &base_dir, int flags, std::vector<completion_t> &out );
|
||||
int wildcard_expand_string(const wcstring &wc, const wcstring &base_dir, expand_flags_t flags, std::vector<completion_t> &out );
|
||||
/**
|
||||
Test whether the given wildcard matches the string
|
||||
|
||||
|
@ -90,6 +91,6 @@ int wildcard_complete( const wchar_t *str,
|
|||
const wchar_t *desc,
|
||||
const wchar_t *(*desc_func)(const wcstring &),
|
||||
std::vector<completion_t> &out,
|
||||
int flags );
|
||||
expand_flags_t flags );
|
||||
|
||||
#endif
|
||||
|
|
33
wutil.cpp
33
wutil.cpp
|
@ -20,6 +20,7 @@
|
|||
#include <libgen.h>
|
||||
#include <pthread.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
|
||||
#if HAVE_LIBINTL_H
|
||||
|
@ -73,6 +74,12 @@ static char *wcs2str_buff=0;
|
|||
*/
|
||||
static size_t wcs2str_buff_count=0;
|
||||
|
||||
/* Lock to protect wgettext */
|
||||
static pthread_mutex_t wgettext_lock;
|
||||
|
||||
/* Maps string keys to (immortal) pointers to string values */
|
||||
typedef std::map<wcstring, wcstring *> wgettext_map_t;
|
||||
static std::map<wcstring, wcstring *> wgettext_map;
|
||||
|
||||
void wutil_init()
|
||||
{
|
||||
|
@ -312,6 +319,7 @@ static void wgettext_really_init() {
|
|||
{
|
||||
sb_init( &buff[i] );
|
||||
}
|
||||
pthread_mutex_init(&wgettext_lock, NULL);
|
||||
bindtextdomain( PACKAGE_NAME, LOCALEDIR );
|
||||
textdomain( PACKAGE_NAME );
|
||||
}
|
||||
|
@ -347,24 +355,21 @@ static char *wgettext_wcs2str( const wchar_t *in )
|
|||
|
||||
const wchar_t *wgettext( const wchar_t *in )
|
||||
{
|
||||
ASSERT_IS_MAIN_THREAD();
|
||||
|
||||
if( !in )
|
||||
return in;
|
||||
|
||||
wgettext_init_if_necessary();
|
||||
|
||||
char *mbs_in = wgettext_wcs2str( in );
|
||||
char *out = gettext( mbs_in );
|
||||
wchar_t *wres=0;
|
||||
|
||||
sb_clear( &buff[curr_buff] );
|
||||
|
||||
sb_printf( &buff[curr_buff], L"%s", out );
|
||||
wres = (wchar_t *)buff[curr_buff].buff;
|
||||
curr_buff = (curr_buff+1)%BUFF_COUNT;
|
||||
|
||||
return wres;
|
||||
|
||||
wcstring key = in;
|
||||
scoped_lock lock(wgettext_lock);
|
||||
|
||||
wcstring *& val = wgettext_map[key];
|
||||
if (val == NULL) {
|
||||
cstring mbs_in = wcs2string(key);
|
||||
char *out = gettext(mbs_in.c_str());
|
||||
val = new wcstring(format_string(L"%s", out));
|
||||
}
|
||||
return val->c_str();
|
||||
}
|
||||
|
||||
wcstring wgettext2(const wcstring &in) {
|
||||
|
|
Loading…
Reference in a new issue