aboutsummaryrefslogtreecommitdiffhomepage
path: root/parse_util.c
diff options
context:
space:
mode:
Diffstat (limited to 'parse_util.c')
-rw-r--r--parse_util.c156
1 files changed, 156 insertions, 0 deletions
diff --git a/parse_util.c b/parse_util.c
index b0c559cb..62024189 100644
--- a/parse_util.c
+++ b/parse_util.c
@@ -13,6 +13,7 @@
#include <wchar.h>
+#include <time.h>
#include <assert.h>
#include "util.h"
@@ -20,6 +21,14 @@
#include "common.h"
#include "tokenizer.h"
#include "parse_util.h"
+#include "expand.h"
+#include "intern.h"
+#include "exec.h"
+
+/**
+ Set of files which have been autoloaded
+*/
+static hash_table_t *loaded=0;
int parse_util_lineno( const wchar_t *str, int len )
{
@@ -419,4 +428,151 @@ void parse_util_token_extent( const wchar_t *buff,
}
+int parse_util_load( const wchar_t *cmd,
+ const wchar_t *path_var,
+ void (*on_load)(const wchar_t *cmd),
+ int reload )
+{
+ array_list_t path_list;
+ int i;
+ string_buffer_t path;
+ time_t *tm;
+ int reloaded = 0;
+
+ /*
+ Do we know where to look
+ */
+
+ if( !path_var )
+ return 0;
+
+ if( !loaded )
+ {
+ loaded = malloc( sizeof( hash_table_t ) );
+ if( !loaded )
+ {
+ die_mem();
+ }
+ hash_init( loaded, &hash_wcs_func, &hash_wcs_cmp );
+ }
+
+
+ /*
+ Get modification time of file
+ */
+ tm = (time_t *)hash_get( loaded, cmd );
+
+ /*
+ Did we just check this?
+ */
+ if( tm )
+ if(tm[1]-time(0)<=1)
+ return 0;
+
+ /*
+ Return if already loaded and we are skipping reloading
+ */
+ if( !reload && tm )
+ return 0;
+ debug( 1, L"WOO %ls", cmd );
+
+ al_init( &path_list );
+
+ sb_init( &path );
+
+ expand_variable_array( path_var, &path_list );
+
+ /*
+ Iterate over path searching for suitable completion files
+ */
+ for( i=0; i<al_get_count( &path_list ); i++ )
+ {
+ struct stat buf;
+ wchar_t *next = (wchar_t *)al_get( &path_list, i );
+ sb_clear( &path );
+ sb_append2( &path, next, L"/", cmd, L".fish", (void *)0 );
+ if( (wstat( (wchar_t *)path.buff, &buf )== 0) &&
+ (waccess( (wchar_t *)path.buff, R_OK ) == 0) )
+ {
+ if( !tm || (*tm != buf.st_mtime ) )
+ {
+ wchar_t *esc = escape( (wchar_t *)path.buff, 1 );
+ wchar_t *src_cmd = wcsdupcat( L". ", esc );
+
+ if( !tm )
+ {
+ tm = malloc(sizeof(time_t)*2);
+ if( !tm )
+ die_mem();
+ }
+
+ tm[0] = buf.st_mtime;
+ tm[1] = time(0);
+ hash_put( loaded,
+ intern( cmd ),
+ tm );
+
+ free( esc );
+
+ on_load(cmd );
+
+ /*
+ Source the completion file for the specified completion
+ */
+ exec_subshell( src_cmd, 0 );
+ free(src_cmd);
+ reloaded = 1;
+ break;
+ }
+ }
+ }
+
+ /*
+ If no file was found we insert the current time. Later we only
+ research if the current time is at least five seconds later.
+ This way, the files won't be searched over and over again.
+ */
+ if( !tm )
+ {
+ tm = malloc(sizeof(time_t)*2);
+ if( !tm )
+ die_mem();
+
+ tm[0] = 0;
+ tm[1] = time(0);
+ hash_put( loaded, intern( cmd ), tm );
+ }
+
+ sb_destroy( &path );
+ al_foreach( &path_list, (void (*)(const void *))&free );
+
+ al_destroy( &path_list );
+
+ return reloaded;
+}
+
+void parse_util_init()
+{
+}
+
+/**
+ Free hash value, but not hash key
+*/
+static void clear_hash_value( const void *key, const void *data )
+{
+ free( (void *)data );
+}
+
+
+void parse_util_destroy()
+{
+ if( loaded )
+ {
+ hash_foreach( loaded,
+ &clear_hash_value );
+ hash_destroy( loaded );
+ free( loaded );
+ loaded = 0;
+ }
+}