mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 12:53:13 +00:00
Overhaul of the script autoloader. This should make sure that old scripts are unloaded and new scripts are loaded when the fish_function_path and fish_complete_path variables change
darcs-hash:20060712142242-ac50b-3966a0e96a32facc8bc1164d6d0837fc551e4733.gz
This commit is contained in:
parent
6d9631d0d0
commit
9e304fa734
7 changed files with 207 additions and 44 deletions
18
complete.c
18
complete.c
|
@ -233,7 +233,6 @@ static hash_table_t *condition_cache=0;
|
|||
*/
|
||||
static string_buffer_t *get_desc_buff=0;
|
||||
|
||||
|
||||
/**
|
||||
This command clears the cache of condition tests created by \c condition_test().
|
||||
*/
|
||||
|
@ -354,7 +353,7 @@ void complete_destroy()
|
|||
suffix_hash=0;
|
||||
}
|
||||
|
||||
parse_util_load_reset(L"fish_complete_path");
|
||||
parse_util_load_reset( L"fish_complete_path", 0 );
|
||||
|
||||
}
|
||||
|
||||
|
@ -1551,7 +1550,10 @@ static void complete_load_handler( const wchar_t *cmd )
|
|||
|
||||
void complete_load( const wchar_t *name, int reload )
|
||||
{
|
||||
parse_util_load( name, L"fish_complete_path", &complete_load_handler, reload );
|
||||
parse_util_load( name,
|
||||
L"fish_complete_path",
|
||||
&complete_load_handler,
|
||||
reload );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1955,20 +1957,18 @@ void complete( const wchar_t *cmd,
|
|||
wchar_t *buff;
|
||||
tokenizer tok;
|
||||
wchar_t *current_token=0, *current_command=0, *prev_token=0;
|
||||
|
||||
int on_command=0;
|
||||
int pos;
|
||||
|
||||
int done=0;
|
||||
|
||||
int cursor_pos = wcslen(cmd );
|
||||
int cursor_pos;
|
||||
|
||||
CHECK( cmd, );
|
||||
CHECK( comp, );
|
||||
|
||||
// debug( 1, L"Complete '%ls'", cmd );
|
||||
|
||||
|
||||
|
||||
cursor_pos = wcslen(cmd );
|
||||
|
||||
/**
|
||||
If we are completing a variable name or a tilde expansion user
|
||||
name, we do that and return. No need for any other competions.
|
||||
|
|
3
env.c
3
env.c
|
@ -317,9 +317,6 @@ static void handle_locale()
|
|||
|
||||
if( is_interactive )
|
||||
{
|
||||
complete_destroy();
|
||||
complete_init();
|
||||
|
||||
debug( 0, _(L"Changing language to English") );
|
||||
}
|
||||
}
|
||||
|
|
12
function.c
12
function.c
|
@ -225,7 +225,7 @@ void function_remove( const wchar_t *name )
|
|||
event_t ev;
|
||||
|
||||
CHECK( name, );
|
||||
|
||||
|
||||
hash_remove( &function,
|
||||
name,
|
||||
&key,
|
||||
|
@ -241,6 +241,16 @@ void function_remove( const wchar_t *name )
|
|||
event_remove( &ev );
|
||||
|
||||
clear_function_entry( key, d );
|
||||
|
||||
/*
|
||||
Notify the autoloader that the specified function is erased, but
|
||||
only if this call to fish_remove is not made by the autoloader
|
||||
itself.
|
||||
*/
|
||||
if( !is_autoload )
|
||||
{
|
||||
parse_util_unload( name, L"fish_function_path", 0 );
|
||||
}
|
||||
}
|
||||
|
||||
const wchar_t *function_get_definition( const wchar_t *argv )
|
||||
|
|
175
parse_util.c
175
parse_util.c
|
@ -29,9 +29,36 @@
|
|||
#include "intern.h"
|
||||
#include "exec.h"
|
||||
#include "env.h"
|
||||
#include "translate.h"
|
||||
#include "wildcard.h"
|
||||
#include "halloc_util.h"
|
||||
|
||||
/**
|
||||
A structure representing the autoload state for a specific variable, e.g. fish_complete_path
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/**
|
||||
A table containing the modification times of all loaded
|
||||
files. Failed loads (non-existing files) have modification time
|
||||
0.
|
||||
*/
|
||||
hash_table_t load_time;
|
||||
/**
|
||||
A string containg the path used to find any files to load. If
|
||||
this differs from the current environment variable, the
|
||||
autoloader needs to drop all loaded files and reload them.
|
||||
*/
|
||||
wchar_t *old_path;
|
||||
/**
|
||||
A table containing all the files that are currently being
|
||||
loaded. This is here to help prevent recursion.
|
||||
*/
|
||||
hash_table_t is_loading;
|
||||
}
|
||||
autoload_t;
|
||||
|
||||
|
||||
/**
|
||||
Set of files which have been autoloaded
|
||||
*/
|
||||
|
@ -448,20 +475,32 @@ void parse_util_token_extent( const wchar_t *buff,
|
|||
/**
|
||||
Free hash value, but not hash key
|
||||
*/
|
||||
static void clear_hash_value( void *key, void *data )
|
||||
static void clear_hash_value( void *key, void *data, void *aux )
|
||||
{
|
||||
if( aux )
|
||||
{
|
||||
wchar_t *name = (wchar_t *)key;
|
||||
void (*handler)(const wchar_t *)= (void (*)(const wchar_t *))aux;
|
||||
handler( name );
|
||||
}
|
||||
|
||||
free( (void *)data );
|
||||
}
|
||||
|
||||
/**
|
||||
Part of the autoloader cleanup
|
||||
*/
|
||||
static void clear_loaded_entry( void *key, void *data )
|
||||
static void clear_loaded_entry( void *key,
|
||||
void *data,
|
||||
void *handler )
|
||||
{
|
||||
hash_table_t *loaded = (hash_table_t *)data;
|
||||
hash_foreach( loaded,
|
||||
&clear_hash_value );
|
||||
hash_destroy( loaded );
|
||||
autoload_t *loaded = (autoload_t *)data;
|
||||
hash_foreach2( &loaded->load_time,
|
||||
&clear_hash_value,
|
||||
handler );
|
||||
hash_destroy( &loaded->load_time );
|
||||
|
||||
free( loaded->old_path );
|
||||
free( loaded );
|
||||
free( (void *)key );
|
||||
}
|
||||
|
@ -475,8 +514,9 @@ static void parse_util_destroy()
|
|||
{
|
||||
if( all_loaded )
|
||||
{
|
||||
hash_foreach( all_loaded,
|
||||
&clear_loaded_entry );
|
||||
hash_foreach2( all_loaded,
|
||||
&clear_loaded_entry,
|
||||
0 );
|
||||
|
||||
hash_destroy( all_loaded );
|
||||
free( all_loaded );
|
||||
|
@ -484,18 +524,61 @@ static void parse_util_destroy()
|
|||
}
|
||||
}
|
||||
|
||||
void parse_util_load_reset( const wchar_t *path_var )
|
||||
void parse_util_load_reset( const wchar_t *path_var_name,
|
||||
void (*on_load)(const wchar_t *cmd) )
|
||||
{
|
||||
wchar_t *path_var;
|
||||
|
||||
CHECK( path_var_name, );
|
||||
path_var = env_get( path_var_name );
|
||||
|
||||
if( !path_var )
|
||||
return;
|
||||
|
||||
if( all_loaded )
|
||||
{
|
||||
void *key, *data;
|
||||
hash_remove( all_loaded, path_var, &key, &data );
|
||||
hash_remove( all_loaded, path_var_name, &key, &data );
|
||||
if( key )
|
||||
clear_loaded_entry( key, data );
|
||||
clear_loaded_entry( key, data, (void *)on_load );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int parse_util_unload( const wchar_t *cmd,
|
||||
const wchar_t *path_var_name,
|
||||
void (*on_load)(const wchar_t *cmd) )
|
||||
{
|
||||
autoload_t *loaded;
|
||||
void *val;
|
||||
|
||||
CHECK( path_var_name, 0 );
|
||||
CHECK( cmd, 0 );
|
||||
|
||||
if( !all_loaded )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
loaded = (autoload_t *)hash_get( all_loaded, path_var_name );
|
||||
|
||||
if( !loaded )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
hash_remove( &loaded->load_time, cmd, 0, &val );
|
||||
if( val )
|
||||
{
|
||||
if( on_load )
|
||||
{
|
||||
on_load( (wchar_t *)val );
|
||||
}
|
||||
free( val );
|
||||
}
|
||||
|
||||
return !!val;
|
||||
}
|
||||
|
||||
int parse_util_load( const wchar_t *cmd,
|
||||
const wchar_t *path_var_name,
|
||||
|
@ -508,16 +591,22 @@ int parse_util_load( const wchar_t *cmd,
|
|||
int i;
|
||||
time_t *tm;
|
||||
int reloaded = 0;
|
||||
hash_table_t *loaded;
|
||||
autoload_t *loaded;
|
||||
|
||||
wchar_t *path_var = env_get( path_var_name );
|
||||
wchar_t *path_var;
|
||||
|
||||
CHECK( path_var_name, 0 );
|
||||
CHECK( cmd, 0 );
|
||||
|
||||
path_var = env_get( path_var_name );
|
||||
|
||||
/*
|
||||
Do we know where to look
|
||||
*/
|
||||
|
||||
if( !path_var )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( !all_loaded )
|
||||
{
|
||||
|
@ -530,23 +619,52 @@ int parse_util_load( const wchar_t *cmd,
|
|||
hash_init( all_loaded, &hash_wcs_func, &hash_wcs_cmp );
|
||||
}
|
||||
|
||||
loaded = (hash_table_t *)hash_get( all_loaded, path_var_name );
|
||||
|
||||
if( !loaded )
|
||||
loaded = (autoload_t *)hash_get( all_loaded, path_var_name );
|
||||
|
||||
if( loaded )
|
||||
{
|
||||
loaded = malloc( sizeof( hash_table_t ) );
|
||||
if( hash_get( &loaded->is_loading, cmd ) )
|
||||
{
|
||||
debug( 0, _(L"Could not autoload item %ls, it is already being autoloaded. This is a circular dependency in the autoloading scripts, please remove it."), cmd );
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Check if the lookup path has changed. If so, drop all loaded
|
||||
files and start from scratch.
|
||||
*/
|
||||
if( wcscmp( path_var, loaded->old_path ) != 0 )
|
||||
{
|
||||
parse_util_load_reset( path_var_name, on_load);
|
||||
reload = parse_util_load( cmd, path_var_name, on_load, reload );
|
||||
return reload;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
We have never tried to autoload using this name before, set up initial data
|
||||
*/
|
||||
loaded = malloc( sizeof( autoload_t ) );
|
||||
if( !loaded )
|
||||
{
|
||||
DIE_MEM();
|
||||
}
|
||||
hash_init( loaded, &hash_wcs_func, &hash_wcs_cmp );
|
||||
hash_init( &loaded->load_time, &hash_wcs_func, &hash_wcs_cmp );
|
||||
hash_put( all_loaded, wcsdup(path_var_name), loaded );
|
||||
|
||||
hash_init( &loaded->is_loading, &hash_wcs_func, &hash_wcs_cmp );
|
||||
|
||||
loaded->old_path = wcsdup( path_var );
|
||||
}
|
||||
|
||||
hash_put( &loaded->is_loading, cmd, cmd );
|
||||
|
||||
|
||||
/*
|
||||
Get modification time of file
|
||||
*/
|
||||
tm = (time_t *)hash_get( loaded, cmd );
|
||||
tm = (time_t *)hash_get( &loaded->load_time, cmd );
|
||||
|
||||
/*
|
||||
Did we just check this?
|
||||
|
@ -555,6 +673,7 @@ int parse_util_load( const wchar_t *cmd,
|
|||
{
|
||||
if(time(0)-tm[1]<=1)
|
||||
{
|
||||
hash_remove( &loaded->is_loading, cmd, 0, 0 );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -563,7 +682,10 @@ int parse_util_load( const wchar_t *cmd,
|
|||
Return if already loaded and we are skipping reloading
|
||||
*/
|
||||
if( !reload && tm )
|
||||
{
|
||||
hash_remove( &loaded->is_loading, cmd, 0, 0 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( !path_list )
|
||||
path_list = al_halloc( global_context);
|
||||
|
@ -601,7 +723,7 @@ int parse_util_load( const wchar_t *cmd,
|
|||
|
||||
tm[0] = buf.st_mtime;
|
||||
tm[1] = time(0);
|
||||
hash_put( loaded,
|
||||
hash_put( &loaded->load_time,
|
||||
intern( cmd ),
|
||||
tm );
|
||||
|
||||
|
@ -634,12 +756,13 @@ int parse_util_load( const wchar_t *cmd,
|
|||
|
||||
tm[0] = 0;
|
||||
tm[1] = time(0);
|
||||
hash_put( loaded, intern( cmd ), tm );
|
||||
hash_put( &loaded->load_time, intern( cmd ), tm );
|
||||
}
|
||||
|
||||
al_foreach( path_list, &free );
|
||||
al_truncate( path_list, 0 );
|
||||
|
||||
|
||||
hash_remove( &loaded->is_loading, cmd, 0, 0 );
|
||||
return reloaded;
|
||||
}
|
||||
|
||||
|
@ -670,7 +793,11 @@ void parse_util_set_argv( wchar_t **argv )
|
|||
wchar_t *parse_util_unescape_wildcards( const wchar_t *str )
|
||||
{
|
||||
wchar_t *in, *out;
|
||||
wchar_t *unescaped = wcsdup(str);
|
||||
wchar_t *unescaped;
|
||||
|
||||
CHECK( str, 0 );
|
||||
|
||||
unescaped = wcsdup(str);
|
||||
|
||||
if( !unescaped )
|
||||
DIE_MEM();
|
||||
|
|
28
parse_util.h
28
parse_util.h
|
@ -95,10 +95,11 @@ int parse_util_lineno( const wchar_t *str, int len );
|
|||
|
||||
/**
|
||||
Autoload the specified file, if it exists in the specified path. Do
|
||||
not load it multiple times unless it's timestamp changes.
|
||||
not load it multiple times unless it's timestamp changes or
|
||||
parse_util_unload is called.
|
||||
|
||||
\param cmd the filename to search for. The suffix '.fish' is always added to this name
|
||||
\param path_var_name the name of an environment variable containing a search path
|
||||
\param path_var_name the environment variable giving the search path
|
||||
\param on_load a callback function to run if a suitable file is found, which has not already been run
|
||||
\param reload wheter to recheck file timestamps on already loaded files
|
||||
*/
|
||||
|
@ -108,9 +109,28 @@ int parse_util_load( const wchar_t *cmd,
|
|||
int reload );
|
||||
|
||||
/**
|
||||
Reset the loader for the specified path variable
|
||||
Reset the loader for the specified path variable. This will cause
|
||||
all information on loaded files in the specified directory to be
|
||||
reset.
|
||||
|
||||
\param path_var_name the environment variable giving the search path
|
||||
\param on_load the callback function to use when a file is reloaded
|
||||
\param on_load the callback function to call if the file has been previously loaded
|
||||
*/
|
||||
void parse_util_load_reset( const wchar_t *path_var );
|
||||
void parse_util_load_reset( const wchar_t *path_var_name,
|
||||
void (*on_load)(const wchar_t *cmd) );
|
||||
|
||||
/**
|
||||
Tell the autoloader that the specified file, in the specified path,
|
||||
is no longer loaded.
|
||||
|
||||
\param cmd the filename to search for. The suffix '.fish' is always added to this name
|
||||
\param path_var_name the environment variable giving the search path
|
||||
\return non-zero if the file was removed, zero if the file had not yet been loaded
|
||||
*/
|
||||
int parse_util_unload( const wchar_t *cmd,
|
||||
const wchar_t *path_var_name,
|
||||
void (*on_load)(const wchar_t *cmd) );
|
||||
|
||||
/**
|
||||
Set the argv environment variable to the specified null-terminated
|
||||
|
|
13
parser.c
13
parser.c
|
@ -443,11 +443,19 @@ void parser_push_block( int type )
|
|||
blocks should always be skipped. Rather complicated... :-(
|
||||
*/
|
||||
new->skip=current_block?current_block->skip:0;
|
||||
|
||||
/*
|
||||
Type TOP and SUBST are never skipped
|
||||
*/
|
||||
if( type == TOP || type == SUBST )
|
||||
{
|
||||
new->skip = 0;
|
||||
}
|
||||
if( type == FAKE )
|
||||
|
||||
/*
|
||||
Fake blocks and function definition blocks are never executed
|
||||
*/
|
||||
if( type == FAKE || type == FUNCTION_DEF )
|
||||
{
|
||||
new->skip = 1;
|
||||
}
|
||||
|
@ -2065,11 +2073,12 @@ static int parse_job( process_t *p,
|
|||
|
||||
forbid = (wchar_t *)(al_get_count( forbidden_function)?al_peek( forbidden_function ):0);
|
||||
nxt_forbidden = forbid && (wcscmp( forbid, nxt) == 0 );
|
||||
|
||||
|
||||
/*
|
||||
Make feeble attempt to avoid infinite recursion. Will at
|
||||
least catch some accidental infinite recursion calls.
|
||||
*/
|
||||
|
||||
if( function_exists( nxt ) && !nxt_forbidden)
|
||||
{
|
||||
/*
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# Match colors for grep, if supported
|
||||
#
|
||||
|
||||
if grep --color=auto --help 1>/dev/null 2>/dev/null
|
||||
if command grep --color=auto --help 1>/dev/null 2>/dev/null
|
||||
if not set -q GREP_COLOR
|
||||
set -gx GREP_COLOR '97;45'
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue