aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar axel <axel@liljencrantz.se>2006-02-08 19:20:05 +1000
committerGravatar axel <axel@liljencrantz.se>2006-02-08 19:20:05 +1000
commit73a9c8bcb8d3d8db967fcc5cc9dd5e8db645400f (patch)
tree13862f394dca16b0c9bae427f86fbbecdfc9ac03
parent47b652c76e240e16875734f7ca251bab97ae6309 (diff)
Autoloaded functions
darcs-hash:20060208092005-ac50b-8e784f79a4e158c8c15b553fad85002dccc7bd03.gz
-rw-r--r--Makefile.in12
-rw-r--r--common.c1
-rw-r--r--complete.c137
-rw-r--r--complete.h2
-rw-r--r--fish.spec.in2
-rw-r--r--function.c62
-rw-r--r--init/fish.in2
-rw-r--r--init/fish_complete.fish.in232
-rw-r--r--init/fish_function.fish851
-rw-r--r--init/functions/__fish_complete_directory.fish22
-rw-r--r--init/functions/__fish_complete_subcommand.fish36
-rw-r--r--init/functions/__fish_complete_suffix.fish26
-rw-r--r--init/functions/__fish_contains_opt.fish53
-rw-r--r--init/functions/__fish_gnu_complete.fish29
-rw-r--r--init/functions/__fish_move_last.fish27
-rw-r--r--init/functions/__fish_print_packages.fish55
-rw-r--r--init/functions/dirh.fish26
-rw-r--r--init/functions/help.fish94
-rw-r--r--init/functions/ls.fish18
-rw-r--r--init/functions/nextd.fish50
-rw-r--r--init/functions/open.fish12
-rw-r--r--init/functions/prevd.fish51
-rw-r--r--init/functions/psub.fish54
-rw-r--r--init/functions/trap.fish136
-rw-r--r--init/functions/type.fish134
-rw-r--r--init/functions/umask.fish206
-rw-r--r--init/functions/vared.fish47
-rw-r--r--main.c2
-rw-r--r--parse_util.c156
-rw-r--r--parse_util.h11
-rw-r--r--parser.c2
31 files changed, 1319 insertions, 1229 deletions
diff --git a/Makefile.in b/Makefile.in
index 255f016e..fd1f72f5 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -171,6 +171,8 @@ TESTS_DIR_FILES := $(TEST_IN) $(TEST_IN:.in=.out) $(TEST_IN:.in=.err) \
COMPLETIONS_DIR_FILES := $(wildcard init/completions/*.fish)
+FUNCTIONS_DIR_FILES := $(wildcard init/functions/*.fish)
+
# Programs to build
PROGRAMS:=fish set_color @XSEL@ @SEQ_FALLBACK@ mimedb count fish_pager fishd
@@ -262,7 +264,7 @@ doc.h:$(BUILTIN_DOC_SRC) $(CMD_DOC_SRC) doc_src/doc.hdr
fi
# Create a template translation object
-messages.pot: *.c *.h init/*.in init/*.fish init/completions/*.fish seq
+messages.pot: *.c *.h init/*.in init/*.fish init/completions/*.fish init/functions/*.fish seq
if test $(HAVE_GETTEXT) = 1;then \
xgettext -k_ -kN_ -kcomplete_desc *.c *.h -o messages.pot; \
if ! xgettext -j -k_ -LShell init/*.in init/*.fish init/completions/*.fish seq -o messages.pot; then \
@@ -346,6 +348,7 @@ install: all install-translations
done;
$(INSTALL) -m 755 -d $(DESTDIR)$(sysconfdir)$(fishdir)
$(INSTALL) -m 755 -d $(DESTDIR)$(sysconfdir)$(fishdir)/completions
+ $(INSTALL) -m 755 -d $(DESTDIR)$(sysconfdir)$(fishdir)/functions
$(INSTALL) -m 644 init/fish $(DESTDIR)$(sysconfdir)$(fishfile)
for i in $(INIT_DIR_INSTALL); do \
$(INSTALL) -m 644 $$i $(DESTDIR)$(sysconfdir)$(fishdir); \
@@ -353,6 +356,9 @@ install: all install-translations
for i in $(COMPLETIONS_DIR_FILES); do \
$(INSTALL) -m 644 $$i $(DESTDIR)$(sysconfdir)$(fishdir)/completions/; \
done;
+ for i in $(FUNCTIONS_DIR_FILES); do \
+ $(INSTALL) -m 644 $$i $(DESTDIR)$(sysconfdir)$(fishdir)/functions/; \
+ done;
$(INSTALL) -m 644 init/fish_inputrc $(DESTDIR)$(sysconfdir)$(fishinputfile);
$(INSTALL) -m 755 -d $(DESTDIR)$(docdir)
for i in user_doc/html/* ChangeLog; do \
@@ -450,18 +456,20 @@ depend:
#
# Uses install instead of mkdir so build won't fail if the directory
# exists
-fish-@PACKAGE_VERSION@.tar: $(DOC_SRC_DIR_FILES) $(MAIN_DIR_FILES) $(INIT_DIR_FILES) $(TEST_DIR_FILES) $(COMPLETIONS_DIR_FILES) ChangeLog
+fish-@PACKAGE_VERSION@.tar: $(DOC_SRC_DIR_FILES) $(MAIN_DIR_FILES) $(INIT_DIR_FILES) $(TEST_DIR_FILES) $(FUNCTIONS_DIR_FILES) $(COMPLETIONS_DIR_FILES) ChangeLog
rm -rf fish-@PACKAGE_VERSION@
$(INSTALL) -d fish-@PACKAGE_VERSION@
$(INSTALL) -d fish-@PACKAGE_VERSION@/doc_src
$(INSTALL) -d fish-@PACKAGE_VERSION@/init
$(INSTALL) -d fish-@PACKAGE_VERSION@/init/completions
+ $(INSTALL) -d fish-@PACKAGE_VERSION@/init/functions
$(INSTALL) -d fish-@PACKAGE_VERSION@/tests
$(INSTALL) -d fish-@PACKAGE_VERSION@/po
cp -f $(DOC_SRC_DIR_FILES) fish-@PACKAGE_VERSION@/doc_src
cp -f $(MAIN_DIR_FILES) fish-@PACKAGE_VERSION@/
cp -f $(INIT_DIR_FILES) fish-@PACKAGE_VERSION@/init/
cp -f $(COMPLETIONS_DIR_FILES) fish-@PACKAGE_VERSION@/init/completions/
+ cp -f $(FUNCTIONS_DIR_FILES) fish-@PACKAGE_VERSION@/init/functions/
cp -f $(TESTS_DIR_FILES) fish-@PACKAGE_VERSION@/tests/
cp -f $(TRANSLATIONS_SRC) fish-@PACKAGE_VERSION@/po/
tar -c fish-@PACKAGE_VERSION@ >fish-@PACKAGE_VERSION@.tar
diff --git a/common.c b/common.c
index 25f0b544..103c5bea 100644
--- a/common.c
+++ b/common.c
@@ -287,6 +287,7 @@ wchar_t *str2wcs( const char *in )
{
return out;
}
+
default:
{
in_pos += res;
diff --git a/complete.c b/complete.c
index 4c2d0680..00dc6dd6 100644
--- a/complete.c
+++ b/complete.c
@@ -216,11 +216,6 @@ static hash_table_t *suffix_hash=0;
static hash_table_t *condition_cache=0;
/**
- Set of commands for which completions have already been loaded
-*/
-static hash_table_t *loaded_completions=0;
-
-/**
String buffer used by complete_get_desc
*/
static string_buffer_t *get_desc_buff=0;
@@ -326,15 +321,6 @@ static void clear_hash_entry( const void *key, const void *data )
free( (void *)data );
}
-/**
- Free hash value, but not hash key
-*/
-static void clear_hash_value( const void *key, const void *data )
-{
- free( (void *)data );
-}
-
-
void complete_destroy()
{
complete_entry *i=first_entry, *prev;
@@ -355,15 +341,6 @@ void complete_destroy()
suffix_hash=0;
}
- if( loaded_completions )
- {
- hash_foreach( loaded_completions,
- &clear_hash_value );
- hash_destroy( loaded_completions );
- free( loaded_completions );
- loaded_completions = 0;
- }
-
if( get_desc_buff )
{
sb_destroy( get_desc_buff );
@@ -1464,117 +1441,15 @@ static int short_ok( wchar_t *arg,
return 1;
}
-void complete_load( wchar_t *cmd,
- int reload )
+static void complete_load_handler( const wchar_t *cmd )
{
- const wchar_t *path_var;
- array_list_t path_list;
- int i;
- string_buffer_t path;
- time_t *tm;
-
- /*
- First check that the specified completion hasn't already been loaded
- */
- if( !loaded_completions )
- {
- loaded_completions = malloc( sizeof( hash_table_t ) );
- if( !loaded_completions )
- {
- die_mem();
- }
- hash_init( loaded_completions, &hash_wcs_func, &hash_wcs_cmp );
- }
-
- /*
- Get modification time of file
- */
- tm = (time_t *)hash_get( loaded_completions, cmd );
-
- /*
- Return if already loaded and we are skipping reloading
- */
- if( !reload && tm )
- return;
-
- /*
- Do we know where to look for completions?
- */
- path_var = env_get( L"fish_complete_path" );
- if( !path_var )
- return;
-
- 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));
- if( !tm )
- die_mem();
- }
-
- *tm = buf.st_mtime;
- hash_put( loaded_completions,
- intern( cmd ),
- tm );
-
- free( esc );
-
- complete_remove( cmd, COMMAND, 0, 0 );
-
- /*
- Source the completion file for the specified completion
- */
- exec_subshell( src_cmd, 0 );
- free(src_cmd);
-
- break;
- }
- }
- }
-
- /*
- If no file was found we insert a last modified time of Jan 1, 1970.
- This way, the completions_path wont be searched over and over again
- when reload is set to 0.
- */
- if( !tm )
- {
- tm = malloc(sizeof(time_t));
- if( !tm )
- die_mem();
-
- *tm = 0;
- hash_put( loaded_completions, intern( cmd ), tm );
- }
-
- sb_destroy( &path );
- al_foreach( &path_list, (void (*)(const void *))&free );
-
- al_destroy( &path_list );
+ complete_remove( cmd, COMMAND, 0, 0 );
}
+void complete_load( const wchar_t *name, int reload )
+{
+ parse_util_load( name, env_get( L"fish_complete_path" ), &complete_load_handler, reload );
+}
/**
Find completion for the argument str of command cmd_orig with
diff --git a/complete.h b/complete.h
index 5f339e5c..c02d5375 100644
--- a/complete.h
+++ b/complete.h
@@ -162,6 +162,6 @@ int complete_is_valid_argument( const wchar_t *str,
\param cmd the command for which to load command-specific completions
\param reload should the commands completions be reloaded, even if they where previously loaded. (This is set to true on actual completions, so that changed completion are updated in running shells)
*/
-void complete_load( wchar_t *cmd, int reload );
+void complete_load( const wchar_t *cmd, int reload );
#endif
diff --git a/fish.spec.in b/fish.spec.in
index 42358aba..3ce51b7e 100644
--- a/fish.spec.in
+++ b/fish.spec.in
@@ -67,6 +67,8 @@ fi
%config %_sysconfdir/fish.d/fish_*.fish
%dir %_sysconfdir/fish.d/completions
%config %_sysconfdir/fish.d/completions/*.fish
+%dir %_sysconfdir/fish.d/functions
+%config %_sysconfdir/fish.d/functions/*.fish
%_datadir/locale/*/LC_MESSAGES/fish.mo
%changelog
diff --git a/function.c b/function.c
index 260df870..47633026 100644
--- a/function.c
+++ b/function.c
@@ -19,6 +19,7 @@
#include "event.h"
#include "reader.h"
#include "parse_util.h"
+#include "env.h"
/**
@@ -33,6 +34,7 @@ typedef struct
const wchar_t *definition_file;
int definition_offset;
int is_binding;
+ int is_autoload;
}
function_data_t;
@@ -40,6 +42,31 @@ typedef struct
Table containing all functions
*/
static hash_table_t function;
+static int is_autoload = 0;
+
+
+static int load( const wchar_t *name )
+{
+ int was_autoload = is_autoload;
+ int res;
+ function_data_t *data;
+ data = (function_data_t *)hash_get( &function, name );
+ if( data && !data->is_autoload )
+ return 0;
+
+ is_autoload = 1;
+ res = parse_util_load( name,
+ env_get( L"fish_function_path" ),
+ &function_remove,
+ 1 );
+ is_autoload = was_autoload;
+ return res;
+}
+
+static void load_all()
+{
+}
+
/**
Free all contents of an entry to the function hash table
@@ -92,7 +119,8 @@ void function_add( const wchar_t *name,
d->desc = desc?wcsdup( desc ):0;
d->is_binding = is_binding;
d->definition_file = intern(reader_current_filename());
-
+ d->is_autoload = is_autoload;
+
hash_put( &function, intern(name), d );
for( i=0; i<al_get_count( events ); i++ )
@@ -104,6 +132,11 @@ void function_add( const wchar_t *name,
int function_exists( const wchar_t *cmd )
{
+ function_data_t *data;
+ if( parser_is_reserved(cmd) )
+ return 0;
+
+ load( cmd );
return (hash_get(&function, cmd) != 0 );
}
@@ -130,8 +163,9 @@ void function_remove( const wchar_t *name )
const wchar_t *function_get_definition( const wchar_t *argv )
{
- function_data_t *data =
- (function_data_t *)hash_get( &function, argv );
+ function_data_t *data;
+ load( argv );
+ data = (function_data_t *)hash_get( &function, argv );
if( data == 0 )
return 0;
return data->cmd;
@@ -139,8 +173,9 @@ const wchar_t *function_get_definition( const wchar_t *argv )
const wchar_t *function_get_desc( const wchar_t *argv )
{
- function_data_t *data =
- (function_data_t *)hash_get( &function, argv );
+ function_data_t *data;
+ load( argv );
+ data = (function_data_t *)hash_get( &function, argv );
if( data == 0 )
return 0;
@@ -149,8 +184,9 @@ const wchar_t *function_get_desc( const wchar_t *argv )
void function_set_desc( const wchar_t *name, const wchar_t *desc )
{
- function_data_t *data =
- (function_data_t *)hash_get( &function, name );
+ function_data_t *data;
+ load( name );
+ data = (function_data_t *)hash_get( &function, name );
if( data == 0 )
return;
@@ -173,6 +209,8 @@ static void get_names_internal( const void *key,
void function_get_names( array_list_t *list, int get_hidden )
{
+ load_all();
+
if( get_hidden )
hash_get_keys( &function, list );
else
@@ -182,8 +220,9 @@ void function_get_names( array_list_t *list, int get_hidden )
const wchar_t *function_get_definition_file( const wchar_t *argv )
{
- function_data_t *data =
- (function_data_t *)hash_get( &function, argv );
+ function_data_t *data;
+ load( argv );
+ data = (function_data_t *)hash_get( &function, argv );
if( data == 0 )
return 0;
@@ -193,8 +232,9 @@ const wchar_t *function_get_definition_file( const wchar_t *argv )
int function_get_definition_offset( const wchar_t *argv )
{
- function_data_t *data =
- (function_data_t *)hash_get( &function, argv );
+ function_data_t *data;
+ load( argv );
+ data = (function_data_t *)hash_get( &function, argv );
if( data == 0 )
return -1;
diff --git a/init/fish.in b/init/fish.in
index c67a4a5f..344484c7 100644
--- a/init/fish.in
+++ b/init/fish.in
@@ -87,6 +87,8 @@ if test 1 = "@HAVE_GETTEXT@"
end
end
+set -g fish_function_path $PWD/fish.d/functions
+
#
# Load additional initialization files
#
diff --git a/init/fish_complete.fish.in b/init/fish_complete.fish.in
index ac8b4056..42619251 100644
--- a/init/fish_complete.fish.in
+++ b/init/fish_complete.fish.in
@@ -14,16 +14,6 @@ end
set -g fish_complete_path @SYSCONFDIR@/fish.d/completions ~/.fish.d/completions
-# Knowing the location of the whatis database speeds up command
-# description lookup.
-
-for i in /var/cache/man/{whatis,windex} /usr{,/local}{,/share}/man/{whatis,windex}
- if test -f $i
- set -g __fish_whatis_path $i
- break
- end
-end
-
#
# Convenience functions
#
@@ -32,55 +22,6 @@ end
# without the description
#
-#
-# Find files that complete $argv[1], has the suffix $argv[2], and
-# output them as completions with description $argv[3]
-#
-
-function __fish_complete_suffix -d "Complete using files"
-
- set -- comp $argv[1]
- set -- suff $argv[2]
- set -- desc $argv[3]
-
- set -- base (echo $comp |sed -e 's/\.[a-zA-Z0-9]*$//')
- eval "set -- files $base*$suff"
-
- if test $files[1]
- printf "%s\t$desc\n" $files
- end
-
- #
- # Also do directory completion, since there might be files
- # with the correct suffix in a subdirectory
- #
-
- __fish_complete_directory $comp
-
-end
-
-#
-# Find directories that complete $argv[1], output them as completions
-# with description $argv[2] if defined, otherwise use 'Directory'
-#
-
-function __fish_complete_directory -d "Complete using directories"
-
- set -- comp $argv[1]
- set -- desc (_ Directory)
-
- if test (count $argv) -gt 1
- set desc $argv[2]
- end
-
- eval "set -- dirs "$comp"*/"
-
- if test $dirs[1]
- printf "%s\t$desc\n" $dirs
- end
-
-end
-
function __fish_complete_users -d "Print a list of local users, with the real user name as a description"
cat /etc/passwd | sed -e "s/^\([^:]*\):[^:]*:[^:]*:[^:]*:\([^:]*\):.*/\1\t\2/"
end
@@ -101,42 +42,6 @@ function __fish_complete_command -d "Complete using all available commands"
printf "%s\n" (commandline -ct)(complete -C (commandline -ct))
end
-function __fish_complete_subcommand -d "Complete subcommand"
- set -l res ""
- set -l had_cmd 0
- set -l cmd (commandline -cop) (commandline -ct)
- set -l skip_next 1
-
- for i in $cmd
-
- if test "$skip_next" = 1
- set skip_next 0
- continue
- end
-
- if test "$had_cmd" = 1
- set res "$res $i"
- else
-
- if contains -- $i $argv
- set skip_next 1
- continue
- end
-
- switch $i
- case '-*'
-
- case '*'
- set had_cmd 1
- set res $i
- end
- end
- end
-
- printf "%s\n" (commandline -ct)(complete -C $res)
-
-end
-
function __fish_print_hostnames -d "Print a list of known hostnames"
@@ -166,59 +71,6 @@ function __fish_print_users -d "Print a list of local users"
cat /etc/passwd | cut -d : -f 1
end
-
-function __fish_contains_opt -d "Checks if a specific option has been given in the current commandline"
- set -l next_short
-
- set -l short_opt
- set -l long_opt
-
- for i in $argv
- if test $next_short
- set next_short
- set -- short_opt $short_opt $i
- else
- switch $i
- case -s
- set next_short 1
- case '-*'
- echo __fish_contains_opt: Unknown option $i
- return 1
-
- case '**'
- set -- long_opt $long_opt $i
- end
- end
- end
-
- for i in $short_opt
-
- if test -z $i
- continue
- end
-
- if commandline -cpo | grep -- "^-"$i"\|^-[^-]*"$i >/dev/null
- return 0
- end
-
- if commandline -ct | grep -- "^-"$i"\|^-[^-]*"$i >/dev/null
- return 0
- end
- end
-
- for i in $long_opt
- if test -z $i
- continue
- end
-
- if contains -- --$i (commandline -cpo)
- return 0
- end
- end
-
- return 1
-end
-
#
# Completions for the shell and it's builtin commands and functions
#
@@ -231,61 +83,6 @@ end
-function __fish_print_packages
-
- # apt-cache is much, much faster than rpm, and can do this in real
- # time. We use it if available.
-
- switch (commandline -tc)
- case '-**'
- return
- end
-
- #Get the word 'Package' in the current language
- set -l package (_ Package)
-
- if which apt-cache >/dev/null ^/dev/null
- # Apply the following filters to output of apt-cache:
- # 1) Remove package names with parentesis in them, since these seem to not correspond to actual packages as reported by rpm
- # 2) Remove package names that are .so files, since these seem to not correspond to actual packages as reported by rpm
- # 3) Remove path information such as /usr/bin/, as rpm packages do not have paths
-
- apt-cache --no-generate pkgnames (commandline -tc)|grep -v \( |grep -v '\.so\(\.[0-9]\)*$'|sed -e 's/\/.*\///'|sed -e 's/$/\t'$package'/'
- return
- end
-
- # Rpm is too slow for this job, so we set it up to do completions
- # as a background job and cache the results.
-
- if which rpm >/dev/null ^/dev/null
-
- # If the cache is less than five minutes old, we do not recalculate it
-
- set cache_file /tmp/.rpm-cache.$USER
- if test -f $cache_file
- cat $cache_file
- set age (echo (date +%s) - (stat -c '%Y' $cache_file) | bc)
- set max_age 250
- if test $age -lt $max_age
- return
- end
- end
-
- # Remove package version information from output and pipe into cache file
- rpm -qa >$cache_file |sed -e 's/-[^-]*-[^-]*$//' | sed -e 's/$/\t'$package'/' &
- end
-
- # This completes the package name from the portage tree.
- # True for installing new packages. Function for printing
- # installed on the system packages is in completions/emerge.fish
- if which emerge >/dev/null ^/dev/null
- emerge -s \^(commandline -tc) |grep "^*" |cut -d\ -f3 |cut -d/ -f2
- return
- end
-
-end
-
-
function __fish_append -d "Internal completion function for appending string to the commandline"
set separator $argv[1]
set -e argv[1]
@@ -293,35 +90,6 @@ function __fish_append -d "Internal completion function for appending string to
printf "%s\n" "$str"$argv "$str"(printf "%s\n" $argv|sed -e "s/\(\t\|\$\)/,\1/")
end
-function __fish_gnu_complete -d "Wrapper for the complete builtin. Skips the long completions on non-GNU systems"
- set is_gnu 0
-
- # Check if we are using a gnu system
- for i in (seq (count $argv))
- switch $argv[$i]
-
- case -g --is-gnu
- set -e argv[$i]
- set is_gnu 1
- break
- end
- end
-
- # Remove long option if not on a gnu system
- if test $is_gnu = 0
- for i in (seq (count $argv))
- if test $argv[$i] = -l
- set -e argv[$i]
- set -e argv[$i]
- break
- end
- end
- end
-
- complete $argv
-
-end
-
function __fish_is_first_token -d 'Test if no non-switch argument has been specified yet'
set -- cmd (commandline -poc)
set -e -- cmd[1]
diff --git a/init/fish_function.fish b/init/fish_function.fish
index 47fa0e88..4ddadc35 100644
--- a/init/fish_function.fish
+++ b/init/fish_function.fish
@@ -47,117 +47,6 @@ function contains -d "Test if a key is contained in a set of values"
end
-#
-# help should use 'open' to find a suitable browser, but only
-# if there is a mime database _and_ DISPLAY is set, since the
-# browser will most likely be graphical. Since most systems which
-# have a mime databe also have the htmlview program, this is mostly a
-# theoretical problem.
-#
-
-function help -d "Show help for the fish shell"
-
- # Declare variables to set correct scope
- set -l fish_browser
- set -l fish_browser_bg
-
- set -l h syntax completion editor job-control todo bugs history killring help
- set h $h color prompt title variables builtin-overview changes expand
- set h $h expand-variable expand-home expand-brace expand-wildcard
- set -l help_topics $h expand-command-substitution expand-process
-
- #
- # Find a suitable browser for viewing the help pages. This is needed
- # by the help function defined below.
- #
- set -l graphical_browsers htmlview x-www-browser firefox galeon mozilla konqueror epiphany opera netscape
- set -l text_browsers htmlview www-browser links elinks lynx w3m
-
- if test $BROWSER
- # User has manualy set a preferred browser, so we respect that
- set fish_browser $BROWSER
-
- # If browser is known to be graphical, put into background
- if contains -- $BROWSER $graphical_browsers
- set fish_browser_bg 1
- end
- else
- # Check for a text-based browser.
- for i in $text_browsers
- if which $i 2>/dev/null >/dev/null
- set fish_browser $i
- break
- end
- end
-
- # If we are in a graphical environment, check if there is a graphical
- # browser to use instead.
- if test "$DISPLAY" -a \( "$XAUTHORITY" = "$HOME/.Xauthority" -o "$XAUTHORITY" = "" \)
- for i in $graphical_browsers
- if which $i 2>/dev/null >/dev/null
- set fish_browser $i
- set fish_browser_bg 1
- break
- end
- end
- end
- end
-
- if test -z $fish_browser
- printf (_ '%s: Could not find a web browser.\n') help
- printf (_ 'Please set the variable $BROWSER to a suitable browser and try again\n\n')
- return 1
- end
-
- set fish_help_item $argv[1]
-
- switch "$fish_help_item"
- case ""
- set fish_help_page index.html
- case "."
- set fish_help_page "builtins.html\#source"
- case difference
- set fish_help_page difference.html
- case globbing
- set fish_help_page "index.html\#expand"
- case (builtin -n)
- set fish_help_page "builtins.html\#$fish_help_item"
- case contains count dirh dirs help mimedb nextd open popd prevd pushd set_color tokenize psub umask type vared
- set fish_help_page "commands.html\#$fish_help_item"
- case $help_topics
- set fish_help_page "index.html\#$fish_help_item"
- case "*"
- if which $fish_help_item >/dev/null ^/dev/null
- man $fish_help_item
- return
- end
- set fish_help_page "index.html"
- end
-
- if test $fish_browser_bg
- eval $fish_browser file://$__fish_help_dir/$fish_help_page \&
- else
- eval $fish_browser file://$__fish_help_dir/$fish_help_page
- end
-end
-
-#
-# Make ls use colors if we are on a system that supports this
-#
-
-if ls --version 1>/dev/null 2>/dev/null
- # This is GNU ls
- function ls -d "List contents of directory"
- command ls --color=auto --indicator-style=classify $argv
- end
-else
- # BSD, OS X and a few more support colors through the -G switch instead
- if ls / -G 1>/dev/null 2>/dev/null
- function ls -d "List contents of directory"
- command ls -G $argv
- end
- end
-end
#
# These are very common and useful
@@ -170,16 +59,6 @@ function la -d "List contents of directory using long format, showing hidden fil
ls -lha $argv
end
-#
-# This allows us to use 'open FILENAME' to open a given file in the default
-# application for the file.
-#
-
-if not test (uname) = Darwin
- function open -d "Open file in default application"
- mimedb -l -- $argv
- end
-end
#
# Print the current working directory in a shortened form.This
@@ -215,52 +94,6 @@ function pwd -d "Print working directory"
end
#
-# This is a neat function, stolen from zsh. It allows you to edit the
-# value of a variable interactively.
-#
-
-function vared -d "Edit variable value"
- if test (count $argv) = 1
- switch $argv
-
- case '-h' '--h' '--he' '--hel' '--help'
- help vared
-
- case '-*'
- printf (_ "%s: Unknown option %s\n") vared $argv
-
- case '*'
- if test (count $$argv ) -lt 2
- set init ''
- if test $$argv
- set -- init $$argv
- end
- set prompt 'set_color green; echo '$argv'; set_color normal; echo "> "'
- read -p $prompt -c $init tmp
-
- # If variable already exists, do not add any
- # switches, so we don't change export rules. But
- # if it does not exist, we make the variable
- # global, so that it will not die when this
- # function dies
-
- if test $$argv
- set -- $argv $tmp
- else
- set -g -- $argv $tmp
- end
-
- else
-
- printf (_ '%s: %s is an array variable. Use %svared%s %s[n] to edit the n:th element of %s\n') $argv (set_color $fish_color_command) (set_color $fish_color_normal) vared $argv $argv
- end
- end
- else
- printf (_ '%s: Expected exactly one argument, got %s.\n\nSynopsis:\n\t%svared%s VARIABLE\n') vared (count $argv) (set_color $fish_color_command) (set_color $fish_color_normal)
- end
-end
-
-#
# This function is used internally by the fish command completion code
#
@@ -360,160 +193,6 @@ function cd -d "Change directory"
end
-function __fish_move_last -d "Move the last element of a directory history from src to dest"
- set -l src $argv[1]
- set -l dest $argv[2]
-
- set -l size_src (count $$src)
-
- if test $size_src = 0
- # Cannot make this step
- printf (_ "Hit end of history...\n")
- return 1
- end
-
- # Append current dir to the end of the destination
- set -g (echo $dest) $$dest (command pwd)
-
- set ssrc $$src
-
- # Change dir to the last entry in the source dir-hist
- builtin cd $ssrc[$size_src]
-
- # Keep all but the last from the source dir-hist
- set -e (echo $src)[$size_src]
-
- # All ok, return success
- return 0
-end
-
-
-function prevd -d "Move back in the directory history"
- # Parse arguments
- set -l show_hist 0
- set -l times 1
- for i in (seq (count $argv))
- switch $argv[$i]
- case '-l' --l --li --lis --list
- set show_hist 1
- continue
- case '-*'
- printf (_ "%s: Unknown option %s\n" ) prevd $argv[$i]
- return 1
- case '*'
- if test $argv[$i] -ge 0 ^/dev/null
- set times $argv[$i]
- else
- printf (_ "The number of positions to skip must be a non-negative integer\n")
- return 1
- end
- continue
- end
- end
-
- # Traverse history
- set -l code 1
- for i in (seq $times)
- # Try one step backward
- if __fish_move_last dirprev dirnext;
- # We consider it a success if we were able to do at least 1 step
- # (low expectations are the key to happiness ;)
- set code 0
- else
- break
- end
- end
-
- # Show history if needed
- if test $show_hist = 1
- dirh
- end
-
- # Set direction for 'cd -'
- if test $code = 0 ^/dev/null
- set -g __fish_cd_direction next
- end
-
- # All done
- return $code
-end
-
-
-function nextd -d "Move forward in the directory history"
- # Parse arguments
- set -l show_hist 0
- set -l times 1
- for i in (seq (count $argv))
- switch $argv[$i]
- case '-l' --l --li --lis --list
- set show_hist 1
- continue
- case '-*'
- printf (_ "%s: Unknown option %s\n" ) nextd $argv[$i]
- return 1
- case '*'
- if test $argv[$i] -ge 0 ^/dev/null
- set times $argv[$i]
- else
- printf (_ "%s: The number of positions to skip must be a non-negative integer\n" ) nextd
- return 1
- end
- continue
- end
- end
-
- # Traverse history
- set -l code 1
- for i in (seq $times)
- # Try one step backward
- if __fish_move_last dirnext dirprev;
- # We consider it a success if we were able to do at least 1 step
- # (low expectations are the key to happiness ;)
- set code 0
- else
- break
- end
- end
-
- # Show history if needed
- if test $show_hist = 1
- dirh
- end
-
- # Set direction for 'cd -'
- if test $code = 0 ^/dev/null
- set -g __fish_cd_direction prev
- end
-
- # All done
- return $code
-end
-
-
-function dirh -d "Print the current directory history (the back- and fwd- lists)"
- # Avoid set comment
- set -l current (command pwd)
- set -l separator " "
- set -l line_len (echo (count $dirprev) + (echo $dirprev $current $dirnext | wc -m) | bc)
- if test $line_len -gt $COLUMNS
- # Print one entry per line if history is long
- set separator "\n"
- end
-
- for i in $dirprev
- echo -n -e $i$separator
- end
-
- set_color $fish_color_history_current
- echo -n -e $current$separator
- set_color normal
-
- for i in (seq (echo (count $dirnext)) -1 1)
- echo -n -e $dirnext[$i]$separator
- end
-
- echo
-end
function __bold -d "Print argument in bold"
set_color --bold
@@ -522,536 +201,6 @@ function __bold -d "Print argument in bold"
end
-function __trap_translate_signal
- set upper (echo $argv[1]|tr a-z A-Z)
- if expr $upper : 'SIG.*' >/dev/null
- echo $upper | cut -c 4-
- else
- echo $upper
- end
-end
-
-function __trap_switch
-
- switch $argv[1]
- case EXIT
- echo --on-exit %self
-
- case '*'
- echo --on-signal $argv[1]
- end
-
-end
-
-function trap -d 'Perform an action when the shell recives a signal'
-
- set -l mode
- set -l cmd
- set -l sig
- set -l shortopt
- set -l longopt
-
- set -l shortopt -o lph
- set -l longopt
- if not getopt -T >/dev/null
- set longopt -l print,help,list-signals
- end
-
- if not getopt -n type -Q $shortopt $longopt -- $argv
- return 1
- end
-
- set -l tmp (getopt $shortopt $longopt -- $argv)
-
- eval set opt $tmp
-
- while count $opt >/dev/null
- switch $opt[1]
- case -h --help
- help trap
- return 0
-
- case -p --print
- set mode print
-
- case -l --list-signals
- set mode list
-
- case --
- set -e opt[1]
- break
-
- end
- set -e opt[1]
- end
-
- if not count $mode >/dev/null
-
- switch (count $opt)
-
- case 0
- set mode print
-
- case 1
- set mode clear
-
- case '*'
- if test opt[1] = -
- set -e opt[1]
- set mode clear
- else
- set mode set
- end
- end
- end
-
- switch $mode
- case clear
- for i in $opt
- set -- sig (__trap_translate_signal $i)
- if test $sig
- functions -e __trap_handler_$sig
- end
- end
-
- case set
- set -l cmd $opt[1]
- set -e opt[1]
-
- for i in $opt
-
- set -l -- sig (__trap_translate_signal $i)
- set -- sw (__trap_switch $sig)
-
- if test $sig
- eval "function __trap_handler_$sig $sw; $cmd; end"
- else
- return 1
- end
- end
-
- case print
- set -l names
-
- if count $opt >/dev/null
- set -- names $opt
- else
- set -- names (functions -na|grep "^__trap_handler_"|sed -e 's/__trap_handler_//' )
- end
-
- for i in $names
-
- set -- sig (__trap_translate_signal $i)
-
- if test sig
- functions __trap_handler_$i
- else
- return 1
- end
-
- end
-
- case list
- kill -l
-
- end
-
-end
-
-
-function type -d "Print the type of a command"
-
- # Initialize
- set -l status 1
- set -l mode normal
- set -l selection all
-
- #
- # Get options
- #
- set -l shortopt -o tpPafh
- set -l longopt
- if not getopt -T >/dev/null
- set longopt -l type,path,force-path,all,no-functions,help
- end
-
- if not getopt -n type -Q $shortopt $longopt -- $argv
- return 1
- end
-
- set -l tmp (getopt $shortopt $longopt -- $argv)
-
- set -l opt
- eval set opt $tmp
-
- for i in $opt
- switch $i
- case -t --type
- set mode type
-
- case -p --path
- set mode path
-
- case -P --force-path
- set mode path
- set selection files
-
- case -a --all
- set selection multi
-
- case -f --no-functions
- set selection files
-
- case -h --help
- help type
- return 0
-
- case --
- break
-
- end
- end
-
- # Check all possible types for the remaining arguments
- for i in $argv
-
- switch $i
- case '-*'
- continue
- end
-
- # Found will be set to 1 if a match is found
- set found 0
-
- if test $selection != files
-
- if contains -- $i (functions -na)
- set status 0
- set found 1
- switch $mode
- case normal
- printf (_ '%s is a function with definition\n') $i
- functions $i
-
- case type
- printf (_ 'function\n')
-
- case path
- echo
-
- end
- if test $selection != multi
- continue
- end
- end
-
- if contains -- $i (builtin -n)
- set status 0
- set found 1
- switch $mode
- case normal
- printf (_ '%s is a builtin\n') $i
-
- case type
- printf (_ 'builtin\n')
-
- case path
- echo
- end
- if test $selection != multi
- continue
- end
- end
-
- end
-
- if which $i ^/dev/null >/dev/null
- set status 0
- set found 1
- switch $mode
- case normal
- printf (_ '%s is %s\n') $i (which $i)
-
- case type
- printf (_ 'file\n')
-
- case path
- which $i
- end
- if test $selection != multi
- continue
- end
- end
-
- if test $found = 0
- printf (_ "%s: Could not find '%s'") type $i
- end
-
- end
-
- return $status
-end
-
-function __fish_umask_parse -d "Parses a file permission specification as into an octal version"
- # Test if already a valid octal mask, and pad it with zeros
- if echo $argv | grep -E '^(0|)[0-7]{1,3}$' >/dev/null
- for i in (seq (echo 5-(echo $argv|wc -c)|bc)); set argv 0$argv; end
- echo $argv
- else
- # Test if argument really is a valid symbolic mask
- if not echo $argv | grep -E '^(((u|g|o|a|)(=|\+|-)|)(r|w|x)*)(,(((u|g|o|a|)(=|\+|-)|)(r|w|x)*))*$' >/dev/null
- printf (_ "%s: Invalid mask '%s'\n") umask $argv >&2
- return 1
- end
-
- set -l implicit_all
-
- # Insert inverted umask into res variable
-
- set -l mode
- set -l val
- set -l tmp $umask
- set -l res
-
- for i in 1 2 3
- set tmp (echo $tmp|cut -c 2-)
- set res[$i] (echo 7-(echo $tmp|cut -c 1)|bc)
- end
-
- set -l el (echo $argv|tr , \n)
- for i in $el
- switch $i
- case 'u*'
- set idx 1
- set i (echo $i| cut -c 2-)
-
- case 'g*'
- set idx 2
- set i (echo $i| cut -c 2-)
-
- case 'o*'
- set idx 3
- set i (echo $i| cut -c 2-)
-
- case 'a*'
- set idx 1 2 3
- set i (echo $i| cut -c 2-)
-
- case '*'
- set implicit_all 1
- set idx 1 2 3
- end
-
- switch $i
- case '=*'
- set mode set
- set i (echo $i| cut -c 2-)
-
- case '+*'
- set mode add
- set i (echo $i| cut -c 2-)
-
- case '-*'
- set mode remove
- set i (echo $i| cut -c 2-)
-
- case '*'
- if not count $implicit_all >/dev/null
- printf (_ "%s: Invalid mask %s\n") umask $argv >&2
- return
- end
- set mode set
- end
-
- if not echo $perm|grep -E '^(r|w|x)*$' >/dev/null
- printf (_ "%s: Invalid mask %s\n") umask $argv >&2
- return
- end
-
- set val 0
- if echo $i |grep 'r' >/dev/null
- set val 4
- end
- if echo $i |grep 'w' >/dev/null
- set val (echo $val + 2|bc)
- end
- if echo $i |grep 'x' >/dev/null
- set val (echo $val + 1|bc)
- end
-
- for j in $idx
- switch $mode
- case set
- set res[$j] $val
-
- case add
- set res[$j] (perl -e 'print( ( '$res[$j]'|'$val[$j]' )."\n" )')
-
- case remove
- set res[$j] (perl -e 'print( ( (7-'$res[$j]')&'$val[$j]' )."\n" )')
- end
- end
- end
-
- for i in 1 2 3
- set res[$i] (echo 7-$res[$i]|bc)
- end
- echo 0$res[1]$res[2]$res[3]
- end
-end
-
-function __fish_umask_print_symbolic
- set -l res ""
- set -l letter a u g o
-
- for i in 2 3 4
- set res $res,$letter[$i]=
- set val (echo $umask|cut -c $i)
-
- if contains $val 0 1 2 3
- set res {$res}r
- end
-
- if contains $val 0 1 4 5
- set res {$res}w
- end
-
- if contains $val 0 2 4 6
- set res {$res}x
- end
-
- end
-
- echo $res|cut -c 2-
-end
-
-function umask -d "Set default file permission mask"
-
- set -l as_command 0
- set -l symbolic 0
-
- set -l shortopt -o pSh
- set -l longopt
- if not getopt -T >/dev/null
- set longopt -l as-command,symbolic,help
- end
-
- if not getopt -n umask -Q $shortopt $longopt -- $argv
- return 1
- end
-
- set -l tmp (getopt $shortopt $longopt -- $argv)
-
- eval set opt $tmp
-
- while count $opt >/dev/null
-
- switch $opt[1]
- case -h --help
- help umask
- return 0
-
- case -p --as-command
- set as_command 1
-
- case -S --symbolic
- set symbolic 1
-
- case --
- set -e opt[1]
- break
-
- end
-
- set -e opt[1]
-
- end
-
- switch (count $opt)
-
- case 0
- if not set -q umask
- set -g umask 113
- end
- if test $as_command -eq 1
- echo umask $umask
- else
- if test $symbolic -eq 1
- __fish_umask_print_symbolic $umask
- else
- echo $umask
- end
- end
-
- case 1
- set -l parsed (__fish_umask_parse $opt)
- if test (count $parsed) -eq 1
- set -g umask $parsed
- return 0
- end
- return 1
-
- case '*'
- printf (_ '%s: Too many arguments\n') umask >&2
-
- end
-
-end
-
-
-function psub -d "Read from stdin into a file and output the filename. Remove the file when the command that calles psub exits."
-
- set -l filename
- set -l funcname
-
- if count $argv >/dev/null
- switch $argv[1]
- case '-h*' --h --he --hel --help
-
- help psub
- return 0
-
- case '*'
- printf (_ "%s: Unknown argument '%s'\n") psub $argv[1]
- return 1
- end
- end
-
- if not status --is-command-substitution
- echo psub: Not inside of command substitution >&2
- return
- end
-
- # Find unique file name for writing output to
- while true
- set filename /tmp/.psub.(echo %self).(random);
- if not test -e $filename
- break;
- end
- end
-
- # Write output to pipe. This needs to be done in the background so
- # that the command substitution exits without needing to wait for
- # all the commands to exit
- mkfifo $filename
- cat >$filename &
-
- # Write filename to stdout
- echo $filename
-
- # Find unique function name
- while true
- set funcname __fish_psub_(random);
- if not functions $funcname >/dev/null ^/dev/null
- break;
- end
- end
-
- # Make sure we erase file when caller exits
- eval function $funcname --on-job-exit caller\; rm $filename\; functions -e $funcname\; end
-
-end
-
function prevd-or-backward-word --key-binding
if test -z (commandline)
prevd
diff --git a/init/functions/__fish_complete_directory.fish b/init/functions/__fish_complete_directory.fish
new file mode 100644
index 00000000..af3844d5
--- /dev/null
+++ b/init/functions/__fish_complete_directory.fish
@@ -0,0 +1,22 @@
+#
+# Find directories that complete $argv[1], output them as completions
+# with description $argv[2] if defined, otherwise use 'Directory'
+#
+
+function __fish_complete_directory -d "Complete using directories"
+
+ set -- comp $argv[1]
+ set -- desc (_ Directory)
+
+ if test (count $argv) -gt 1
+ set desc $argv[2]
+ end
+
+ eval "set -- dirs "$comp"*/"
+
+ if test $dirs[1]
+ printf "%s\t$desc\n" $dirs
+ end
+
+end
+
diff --git a/init/functions/__fish_complete_subcommand.fish b/init/functions/__fish_complete_subcommand.fish
new file mode 100644
index 00000000..60ecc35a
--- /dev/null
+++ b/init/functions/__fish_complete_subcommand.fish
@@ -0,0 +1,36 @@
+function __fish_complete_subcommand -d "Complete subcommand"
+ set -l res ""
+ set -l had_cmd 0
+ set -l cmd (commandline -cop) (commandline -ct)
+ set -l skip_next 1
+
+ for i in $cmd
+
+ if test "$skip_next" = 1
+ set skip_next 0
+ continue
+ end
+
+ if test "$had_cmd" = 1
+ set res "$res $i"
+ else
+
+ if contains -- $i $argv
+ set skip_next 1
+ continue
+ end
+
+ switch $i
+ case '-*'
+
+ case '*'
+ set had_cmd 1
+ set res $i
+ end
+ end
+ end
+
+ printf "%s\n" (commandline -ct)(complete -C $res)
+
+end
+
diff --git a/init/functions/__fish_complete_suffix.fish b/init/functions/__fish_complete_suffix.fish
new file mode 100644
index 00000000..78c5d2e0
--- /dev/null
+++ b/init/functions/__fish_complete_suffix.fish
@@ -0,0 +1,26 @@
+#
+# Find files that complete $argv[1], has the suffix $argv[2], and
+# output them as completions with description $argv[3]
+#
+
+function __fish_complete_suffix -d "Complete using files"
+
+ set -- comp $argv[1]
+ set -- suff $argv[2]
+ set -- desc $argv[3]
+
+ set -- base (echo $comp |sed -e 's/\.[a-zA-Z0-9]*$//')
+ eval "set -- files $base*$suff"
+
+ if test $files[1]
+ printf "%s\t$desc\n" $files
+ end
+
+ #
+ # Also do directory completion, since there might be files
+ # with the correct suffix in a subdirectory
+ #
+
+ __fish_complete_directory $comp
+
+end
diff --git a/init/functions/__fish_contains_opt.fish b/init/functions/__fish_contains_opt.fish
new file mode 100644
index 00000000..5b06007e
--- /dev/null
+++ b/init/functions/__fish_contains_opt.fish
@@ -0,0 +1,53 @@
+
+function __fish_contains_opt -d "Checks if a specific option has been given in the current commandline"
+ set -l next_short
+
+ set -l short_opt
+ set -l long_opt
+
+ for i in $argv
+ if test $next_short
+ set next_short
+ set -- short_opt $short_opt $i
+ else
+ switch $i
+ case -s
+ set next_short 1
+ case '-*'
+ echo __fish_contains_opt: Unknown option $i
+ return 1
+
+ case '**'
+ set -- long_opt $long_opt $i
+ end
+ end
+ end
+
+ for i in $short_opt
+
+ if test -z $i
+ continue
+ end
+
+ if commandline -cpo | grep -- "^-"$i"\|^-[^-]*"$i >/dev/null
+ return 0
+ end
+
+ if commandline -ct | grep -- "^-"$i"\|^-[^-]*"$i >/dev/null
+ return 0
+ end
+ end
+
+ for i in $long_opt
+ if test -z $i
+ continue
+ end
+
+ if contains -- --$i (commandline -cpo)
+ return 0
+ end
+ end
+
+ return 1
+end
+
diff --git a/init/functions/__fish_gnu_complete.fish b/init/functions/__fish_gnu_complete.fish
new file mode 100644
index 00000000..9aeb0ba8
--- /dev/null
+++ b/init/functions/__fish_gnu_complete.fish
@@ -0,0 +1,29 @@
+function __fish_gnu_complete -d "Wrapper for the complete builtin. Skips the long completions on non-GNU systems"
+ set is_gnu 0
+
+ # Check if we are using a gnu system
+ for i in (seq (count $argv))
+ switch $argv[$i]
+
+ case -g --is-gnu
+ set -e argv[$i]
+ set is_gnu 1
+ break
+ end
+ end
+
+ # Remove long option if not on a gnu system
+ if test $is_gnu = 0
+ for i in (seq (count $argv))
+ if test $argv[$i] = -l
+ set -e argv[$i]
+ set -e argv[$i]
+ break
+ end
+ end
+ end
+
+ complete $argv
+
+end
+
diff --git a/init/functions/__fish_move_last.fish b/init/functions/__fish_move_last.fish
new file mode 100644
index 00000000..965072cd
--- /dev/null
+++ b/init/functions/__fish_move_last.fish
@@ -0,0 +1,27 @@
+function __fish_move_last -d "Move the last element of a directory history from src to dest"
+ set -l src $argv[1]
+ set -l dest $argv[2]
+
+ set -l size_src (count $$src)
+
+ if test $size_src = 0
+ # Cannot make this step
+ printf (_ "Hit end of history...\n")
+ return 1
+ end
+
+ # Append current dir to the end of the destination
+ set -g (echo $dest) $$dest (command pwd)
+
+ set ssrc $$src
+
+ # Change dir to the last entry in the source dir-hist
+ builtin cd $ssrc[$size_src]
+
+ # Keep all but the last from the source dir-hist
+ set -e (echo $src)[$size_src]
+
+ # All ok, return success
+ return 0
+end
+
diff --git a/init/functions/__fish_print_packages.fish b/init/functions/__fish_print_packages.fish
new file mode 100644
index 00000000..03e52314
--- /dev/null
+++ b/init/functions/__fish_print_packages.fish
@@ -0,0 +1,55 @@
+
+function __fish_print_packages
+
+ # apt-cache is much, much faster than rpm, and can do this in real
+ # time. We use it if available.
+
+ switch (commandline -tc)
+ case '-**'
+ return
+ end
+
+ #Get the word 'Package' in the current language
+ set -l package (_ Package)
+
+ if which apt-cache >/dev/null ^/dev/null
+ # Apply the following filters to output of apt-cache:
+ # 1) Remove package names with parentesis in them, since these seem to not correspond to actual packages as reported by rpm
+ # 2) Remove package names that are .so files, since these seem to not correspond to actual packages as reported by rpm
+ # 3) Remove path information such as /usr/bin/, as rpm packages do not have paths
+
+ apt-cache --no-generate pkgnames (commandline -tc)|grep -v \( |grep -v '\.so\(\.[0-9]\)*$'|sed -e 's/\/.*\///'|sed -e 's/$/\t'$package'/'
+ return
+ end
+
+ # Rpm is too slow for this job, so we set it up to do completions
+ # as a background job and cache the results.
+
+ if which rpm >/dev/null ^/dev/null
+
+ # If the cache is less than five minutes old, we do not recalculate it
+
+ set cache_file /tmp/.rpm-cache.$USER
+ if test -f $cache_file
+ cat $cache_file
+ set age (echo (date +%s) - (stat -c '%Y' $cache_file) | bc)
+ set max_age 250
+ if test $age -lt $max_age
+ return
+ end
+ end
+
+ # Remove package version information from output and pipe into cache file
+ rpm -qa >$cache_file |sed -e 's/-[^-]*-[^-]*$//' | sed -e 's/$/\t'$package'/' &
+ end
+
+ # This completes the package name from the portage tree.
+ # True for installing new packages. Function for printing
+ # installed on the system packages is in completions/emerge.fish
+ if which emerge >/dev/null ^/dev/null
+ emerge -s \^(commandline -tc) |grep "^*" |cut -d\ -f3 |cut -d/ -f2
+ return
+ end
+
+end
+
diff --git a/init/functions/dirh.fish b/init/functions/dirh.fish
new file mode 100644
index 00000000..82eb5a29
--- /dev/null
+++ b/init/functions/dirh.fish
@@ -0,0 +1,26 @@
+
+function dirh -d "Print the current directory history (the back- and fwd- lists)"
+ # Avoid set comment
+ set -l current (command pwd)
+ set -l separator " "
+ set -l line_len (echo (count $dirprev) + (echo $dirprev $current $dirnext | wc -m) | bc)
+ if test $line_len -gt $COLUMNS
+ # Print one entry per line if history is long
+ set separator "\n"
+ end
+
+ for i in $dirprev
+ echo -n -e $i$separator
+ end
+
+ set_color $fish_color_history_current
+ echo -n -e $current$separator
+ set_color normal
+
+ for i in (seq (echo (count $dirnext)) -1 1)
+ echo -n -e $dirnext[$i]$separator
+ end
+
+ echo
+end
+
diff --git a/init/functions/help.fish b/init/functions/help.fish
new file mode 100644
index 00000000..1dff5f91
--- /dev/null
+++ b/init/functions/help.fish
@@ -0,0 +1,94 @@
+
+#
+# help should use 'open' to find a suitable browser, but only
+# if there is a mime database _and_ DISPLAY is set, since the
+# browser will most likely be graphical. Since most systems which
+# have a mime databe also have the htmlview program, this is mostly a
+# theoretical problem.
+#
+
+function help -d "Show help for the fish shell"
+
+ # Declare variables to set correct scope
+ set -l fish_browser
+ set -l fish_browser_bg
+
+ set -l h syntax completion editor job-control todo bugs history killring help
+ set h $h color prompt title variables builtin-overview changes expand
+ set h $h expand-variable expand-home expand-brace expand-wildcard
+ set -l help_topics $h expand-command-substitution expand-process
+
+ #
+ # Find a suitable browser for viewing the help pages. This is needed
+ # by the help function defined below.
+ #
+ set -l graphical_browsers htmlview x-www-browser firefox galeon mozilla konqueror epiphany opera netscape
+ set -l text_browsers htmlview www-browser links elinks lynx w3m
+
+ if test $BROWSER
+ # User has manualy set a preferred browser, so we respect that
+ set fish_browser $BROWSER
+
+ # If browser is known to be graphical, put into background
+ if contains -- $BROWSER $graphical_browsers
+ set fish_browser_bg 1
+ end
+ else
+ # Check for a text-based browser.
+ for i in $text_browsers
+ if which $i 2>/dev/null >/dev/null
+ set fish_browser $i
+ break
+ end
+ end
+
+ # If we are in a graphical environment, check if there is a graphical
+ # browser to use instead.
+ if test "$DISPLAY" -a \( "$XAUTHORITY" = "$HOME/.Xauthority" -o "$XAUTHORITY" = "" \)
+ for i in $graphical_browsers
+ if which $i 2>/dev/null >/dev/null
+ set fish_browser $i
+ set fish_browser_bg 1
+ break
+ end
+ end
+ end
+ end
+
+ if test -z $fish_browser
+ printf (_ '%s: Could not find a web browser.\n') help
+ printf (_ 'Please set the variable $BROWSER to a suitable browser and try again\n\n')
+ return 1
+ end
+
+ set fish_help_item $argv[1]
+
+ switch "$fish_help_item"
+ case ""
+ set fish_help_page index.html
+ case "."
+ set fish_help_page "builtins.html\#source"
+ case difference
+ set fish_help_page difference.html
+ case globbing
+ set fish_help_page "index.html\#expand"
+ case (builtin -n)
+ set fish_help_page "builtins.html\#$fish_help_item"
+ case contains count dirh dirs help mimedb nextd open popd prevd pushd set_color tokenize psub umask type vared
+ set fish_help_page "commands.html\#$fish_help_item"
+ case $help_topics
+ set fish_help_page "index.html\#$fish_help_item"
+ case "*"
+ if which $fish_help_item >/dev/null ^/dev/null
+ man $fish_help_item
+ return
+ end
+ set fish_help_page "index.html"
+ end
+
+ if test $fish_browser_bg
+ eval $fish_browser file://$__fish_help_dir/$fish_help_page \&
+ else
+ eval $fish_browser file://$__fish_help_dir/$fish_help_page
+ end
+end
diff --git a/init/functions/ls.fish b/init/functions/ls.fish
new file mode 100644
index 00000000..3f96812a
--- /dev/null
+++ b/init/functions/ls.fish
@@ -0,0 +1,18 @@
+#
+# Make ls use colors if we are on a system that supports this
+#
+
+if ls --version 1>/dev/null 2>/dev/null
+ # This is GNU ls
+ function ls -d "List contents of directory"
+ command ls --color=auto --indicator-style=classify $argv
+ end
+else
+ # BSD, OS X and a few more support colors through the -G switch instead
+ if ls / -G 1>/dev/null 2>/dev/null
+ function ls -d "List contents of directory"
+ command ls -G $argv
+ end
+ end
+end
+
diff --git a/init/functions/nextd.fish b/init/functions/nextd.fish
new file mode 100644
index 00000000..293e7fd9
--- /dev/null
+++ b/init/functions/nextd.fish
@@ -0,0 +1,50 @@
+
+function nextd -d "Move forward in the directory history"
+ # Parse arguments
+ set -l show_hist 0
+ set -l times 1
+ for i in (seq (count $argv))
+ switch $argv[$i]
+ case '-l' --l --li --lis --list
+ set show_hist 1
+ continue
+ case '-*'
+ printf (_ "%s: Unknown option %s\n" ) nextd $argv[$i]
+ return 1
+ case '*'
+ if test $argv[$i] -ge 0 ^/dev/null
+ set times $argv[$i]
+ else
+ printf (_ "%s: The number of positions to skip must be a non-negative integer\n" ) nextd
+ return 1
+ end
+ continue
+ end
+ end
+
+ # Traverse history
+ set -l code 1
+ for i in (seq $times)
+ # Try one step backward
+ if __fish_move_last dirnext dirprev;
+ # We consider it a success if we were able to do at least 1 step
+ # (low expectations are the key to happiness ;)
+ set code 0
+ else
+ break
+ end
+ end
+
+ # Show history if needed
+ if test $show_hist = 1
+ dirh
+ end
+
+ # Set direction for 'cd -'
+ if test $code = 0 ^/dev/null
+ set -g __fish_cd_direction prev
+ end
+
+ # All done
+ return $code
+end
diff --git a/init/functions/open.fish b/init/functions/open.fish
new file mode 100644
index 00000000..bfe0f99e
--- /dev/null
+++ b/init/functions/open.fish
@@ -0,0 +1,12 @@
+
+#
+# This allows us to use 'open FILENAME' to open a given file in the default
+# application for the file.
+#
+
+if not test (uname) = Darwin
+ function open -d "Open file in default application"
+ mimedb -l -- $argv
+ end
+end
+
diff --git a/init/functions/prevd.fish b/init/functions/prevd.fish
new file mode 100644
index 00000000..e71fb2e0
--- /dev/null
+++ b/init/functions/prevd.fish
@@ -0,0 +1,51 @@
+
+function prevd -d "Move back in the directory history"
+ # Parse arguments
+ set -l show_hist 0
+ set -l times 1
+ for i in (seq (count $argv))
+ switch $argv[$i]
+ case '-l' --l --li --lis --list
+ set show_hist 1
+ continue
+ case '-*'
+ printf (_ "%s: Unknown option %s\n" ) prevd $argv[$i]
+ return 1
+ case '*'
+ if test $argv[$i] -ge 0 ^/dev/null
+ set times $argv[$i]
+ else
+ printf (_ "The number of positions to skip must be a non-negative integer\n")
+ return 1
+ end
+ continue
+ end
+ end
+
+ # Traverse history
+ set -l code 1
+ for i in (seq $times)
+ # Try one step backward
+ if __fish_move_last dirprev dirnext;
+ # We consider it a success if we were able to do at least 1 step
+ # (low expectations are the key to happiness ;)
+ set code 0
+ else
+ break
+ end
+ end
+
+ # Show history if needed
+ if test $show_hist = 1
+ dirh
+ end
+
+ # Set direction for 'cd -'
+ if test $code = 0 ^/dev/null
+ set -g __fish_cd_direction next
+ end
+
+ # All done
+ return $code
+end
+
diff --git a/init/functions/psub.fish b/init/functions/psub.fish
new file mode 100644
index 00000000..974833f2
--- /dev/null
+++ b/init/functions/psub.fish
@@ -0,0 +1,54 @@
+
+
+function psub -d "Read from stdin into a file and output the filename. Remove the file when the command that calles psub exits."
+
+ set -l filename
+ set -l funcname
+
+ if count $argv >/dev/null
+ switch $argv[1]
+ case '-h*' --h --he --hel --help
+
+ help psub
+ return 0
+
+ case '*'
+ printf (_ "%s: Unknown argument '%s'\n") psub $argv[1]
+ return 1
+ end
+ end
+
+ if not status --is-command-substitution
+ echo psub: Not inside of command substitution >&2
+ return
+ end
+
+ # Find unique file name for writing output to
+ while true
+ set filename /tmp/.psub.(echo %self).(random);
+ if not test -e $filename
+ break;
+ end
+ end
+
+ # Write output to pipe. This needs to be done in the background so
+ # that the command substitution exits without needing to wait for
+ # all the commands to exit
+ mkfifo $filename
+ cat >$filename &
+
+ # Write filename to stdout
+ echo $filename
+
+ # Find unique function name
+ while true
+ set funcname __fish_psub_(random);
+ if not functions $funcname >/dev/null ^/dev/null
+ break;
+ end
+ end
+
+ # Make sure we erase file when caller exits
+ eval function $funcname --on-job-exit caller\; rm $filename\; functions -e $funcname\; end
+
+end
diff --git a/init/functions/trap.fish b/init/functions/trap.fish
new file mode 100644
index 00000000..74940dbe
--- /dev/null
+++ b/init/functions/trap.fish
@@ -0,0 +1,136 @@
+
+function __trap_translate_signal
+ set upper (echo $argv[1]|tr a-z A-Z)
+ if expr $upper : 'SIG.*' >/dev/null
+ echo $upper | cut -c 4-
+ else
+ echo $upper
+ end
+end
+
+function __trap_switch
+
+ switch $argv[1]
+ case EXIT
+ echo --on-exit %self
+
+ case '*'
+ echo --on-signal $argv[1]
+ end
+
+end
+
+function trap -d 'Perform an action when the shell recives a signal'
+
+ set -l mode
+ set -l cmd
+ set -l sig
+ set -l shortopt
+ set -l longopt
+
+ set -l shortopt -o lph
+ set -l longopt
+ if not getopt -T >/dev/null
+ set longopt -l print,help,list-signals
+ end
+
+ if not getopt -n type -Q $shortopt $longopt -- $argv
+ return 1
+ end
+
+ set -l tmp (getopt $shortopt $longopt -- $argv)
+
+ eval set opt $tmp
+
+ while count $opt >/dev/null
+ switch $opt[1]
+ case -h --help
+ help trap
+ return 0
+
+ case -p --print
+ set mode print
+
+ case -l --list-signals
+ set mode list
+
+ case --
+ set -e opt[1]
+ break
+
+ end
+ set -e opt[1]
+ end
+
+ if not count $mode >/dev/null
+
+ switch (count $opt)
+
+ case 0
+ set mode print
+
+ case 1
+ set mode clear
+
+ case '*'
+ if test opt[1] = -
+ set -e opt[1]
+ set mode clear
+ else
+ set mode set
+ end
+ end
+ end
+
+ switch $mode
+ case clear
+ for i in $opt
+ set -- sig (__trap_translate_signal $i)
+ if test $sig
+ functions -e __trap_handler_$sig
+ end
+ end
+
+ case set
+ set -l cmd $opt[1]
+ set -e opt[1]
+
+ for i in $opt
+
+ set -l -- sig (__trap_translate_signal $i)
+ set -- sw (__trap_switch $sig)
+
+ if test $sig
+ eval "function __trap_handler_$sig $sw; $cmd; end"
+ else
+ return 1
+ end
+ end
+
+ case print
+ set -l names
+
+ if count $opt >/dev/null
+ set -- names $opt
+ else
+ set -- names (functions -na|grep "^__trap_handler_"|sed -e 's/__trap_handler_//' )
+ end
+
+ for i in $names
+
+ set -- sig (__trap_translate_signal $i)
+
+ if test sig
+ functions __trap_handler_$i
+ else
+ return 1
+ end
+
+ end
+
+ case list
+ kill -l
+
+ end
+
+end
diff --git a/init/functions/type.fish b/init/functions/type.fish
new file mode 100644
index 00000000..af7e0faa
--- /dev/null
+++ b/init/functions/type.fish
@@ -0,0 +1,134 @@
+
+function type -d "Print the type of a command"
+
+ # Initialize
+ set -l status 1
+ set -l mode normal
+ set -l selection all
+
+ #
+ # Get options
+ #
+ set -l shortopt -o tpPafh
+ set -l longopt
+ if not getopt -T >/dev/null
+ set longopt -l type,path,force-path,all,no-functions,help
+ end
+
+ if not getopt -n type -Q $shortopt $longopt -- $argv
+ return 1
+ end
+
+ set -l tmp (getopt $shortopt $longopt -- $argv)
+
+ set -l opt
+ eval set opt $tmp
+
+ for i in $opt
+ switch $i
+ case -t --type
+ set mode type
+
+ case -p --path
+ set mode path
+
+ case -P --force-path
+ set mode path
+ set selection files
+
+ case -a --all
+ set selection multi
+
+ case -f --no-functions
+ set selection files
+
+ case -h --help
+ help type
+ return 0
+
+ case --
+ break
+
+ end
+ end
+
+ # Check all possible types for the remaining arguments
+ for i in $argv
+
+ switch $i
+ case '-*'
+ continue
+ end
+
+ # Found will be set to 1 if a match is found
+ set found 0
+
+ if test $selection != files
+
+ if contains -- $i (functions -na)
+ set status 0
+ set found 1
+ switch $mode
+ case normal
+ printf (_ '%s is a function with definition\n') $i
+ functions $i
+
+ case type
+ printf (_ 'function\n')
+
+ case path
+ echo
+
+ end
+ if test $selection != multi
+ continue
+ end
+ end
+
+ if contains -- $i (builtin -n)
+ set status 0
+ set found 1
+ switch $mode
+ case normal
+ printf (_ '%s is a builtin\n') $i
+
+ case type
+ printf (_ 'builtin\n')
+
+ case path
+ echo
+ end
+ if test $selection != multi
+ continue
+ end
+ end
+
+ end
+
+ if which $i ^/dev/null >/dev/null
+ set status 0
+ set found 1
+ switch $mode
+ case normal
+ printf (_ '%s is %s\n') $i (which $i)
+
+ case type
+ printf (_ 'file\n')
+
+ case path
+ which $i
+ end
+ if test $selection != multi
+ continue
+ end
+ end
+
+ if test $found = 0
+ printf (_ "%s: Could not find '%s'") type $i
+ end
+
+ end
+
+ return $status
+end
+
diff --git a/init/functions/umask.fish b/init/functions/umask.fish
new file mode 100644
index 00000000..5392a390
--- /dev/null
+++ b/init/functions/umask.fish
@@ -0,0 +1,206 @@
+
+function __fish_umask_parse -d "Parses a file permission specification as into an octal version"
+ # Test if already a valid octal mask, and pad it with zeros
+ if echo $argv | grep -E '^(0|)[0-7]{1,3}$' >/dev/null
+ for i in (seq (echo 5-(echo $argv|wc -c)|bc)); set argv 0$argv; end
+ echo $argv
+ else
+ # Test if argument really is a valid symbolic mask
+ if not echo $argv | grep -E '^(((u|g|o|a|)(=|\+|-)|)(r|w|x)*)(,(((u|g|o|a|)(=|\+|-)|)(r|w|x)*))*$' >/dev/null
+ printf (_ "%s: Invalid mask '%s'\n") umask $argv >&2
+ return 1
+ end
+
+ set -l implicit_all
+
+ # Insert inverted umask into res variable
+
+ set -l mode
+ set -l val
+ set -l tmp $umask
+ set -l res
+
+ for i in 1 2 3
+ set tmp (echo $tmp|cut -c 2-)
+ set res[$i] (echo 7-(echo $tmp|cut -c 1)|bc)
+ end
+
+ set -l el (echo $argv|tr , \n)
+ for i in $el
+ switch $i
+ case 'u*'
+ set idx 1
+ set i (echo $i| cut -c 2-)
+
+ case 'g*'
+ set idx 2
+ set i (echo $i| cut -c 2-)
+
+ case 'o*'
+ set idx 3
+ set i (echo $i| cut -c 2-)
+
+ case 'a*'
+ set idx 1 2 3
+ set i (echo $i| cut -c 2-)
+
+ case '*'
+ set implicit_all 1
+ set idx 1 2 3
+ end
+
+ switch $i
+ case '=*'
+ set mode set
+ set i (echo $i| cut -c 2-)
+
+ case '+*'
+ set mode add
+ set i (echo $i| cut -c 2-)
+
+ case '-*'
+ set mode remove
+ set i (echo $i| cut -c 2-)
+
+ case '*'
+ if not count $implicit_all >/dev/null
+ printf (_ "%s: Invalid mask '%s'\n") umask $argv >&2
+ return
+ end
+ set mode set
+ end
+
+ if not echo $perm|grep -E '^(r|w|x)*$' >/dev/null
+ printf (_ "%s: Invalid mask '%s'\n") umask $argv >&2
+ return
+ end
+
+ set val 0
+ if echo $i |grep 'r' >/dev/null
+ set val 4
+ end
+ if echo $i |grep 'w' >/dev/null
+ set val (echo $val + 2|bc)
+ end
+ if echo $i |grep 'x' >/dev/null
+ set val (echo $val + 1|bc)
+ end
+
+ for j in $idx
+ switch $mode
+ case set
+ set res[$j] $val
+
+ case add
+ set res[$j] (perl -e 'print( ( '$res[$j]'|'$val[$j]' )."\n" )')
+
+ case remove
+ set res[$j] (perl -e 'print( ( (7-'$res[$j]')&'$val[$j]' )."\n" )')
+ end
+ end
+ end
+
+ for i in 1 2 3
+ set res[$i] (echo 7-$res[$i]|bc)
+ end
+ echo 0$res[1]$res[2]$res[3]
+ end
+end
+
+function __fish_umask_print_symbolic
+ set -l res ""
+ set -l letter a u g o
+
+ for i in 2 3 4
+ set res $res,$letter[$i]=
+ set val (echo $umask|cut -c $i)
+
+ if contains $val 0 1 2 3
+ set res {$res}r
+ end
+
+ if contains $val 0 1 4 5
+ set res {$res}w
+ end
+
+ if contains $val 0 2 4 6
+ set res {$res}x
+ end
+
+ end
+
+ echo $res|cut -c 2-
+end
+
+function umask -d "Set default file permission mask"
+
+ set -l as_command 0
+ set -l symbolic 0
+
+ set -l shortopt -o pSh
+ set -l longopt
+ if not getopt -T >/dev/null
+ set longopt -l as-command,symbolic,help
+ end
+
+ if not getopt -n umask -Q $shortopt $longopt -- $argv
+ return 1
+ end
+
+ set -l tmp (getopt $shortopt $longopt -- $argv)
+
+ eval set opt $tmp
+
+ while count $opt >/dev/null
+
+ switch $opt[1]
+ case -h --help
+ help umask
+ return 0
+
+ case -p --as-command
+ set as_command 1
+
+ case -S --symbolic
+ set symbolic 1
+
+ case --
+ set -e opt[1]
+ break
+
+ end
+
+ set -e opt[1]
+
+ end
+
+ switch (count $opt)
+
+ case 0
+ if not set -q umask
+ set -g umask 113
+ end
+ if test $as_command -eq 1
+ echo umask $umask
+ else
+ if test $symbolic -eq 1
+ __fish_umask_print_symbolic $umask
+ else
+ echo $umask
+ end
+ end
+
+ case 1
+ set -l parsed (__fish_umask_parse $opt)
+ if test (count $parsed) -eq 1
+ set -g umask $parsed
+ return 0
+ end
+ return 1
+
+ case '*'
+ printf (_ '%s: Too many arguments\n') umask >&2
+
+ end
+
+end
diff --git a/init/functions/vared.fish b/init/functions/vared.fish
new file mode 100644
index 00000000..f6b442b5
--- /dev/null
+++ b/init/functions/vared.fish
@@ -0,0 +1,47 @@
+
+#
+# This is a neat function, stolen from zsh. It allows you to edit the
+# value of a variable interactively.
+#
+
+function vared -d "Edit variable value"
+ if test (count $argv) = 1
+ switch $argv
+
+ case '-h' '--h' '--he' '--hel' '--help'
+ help vared
+
+ case '-*'
+ printf (_ "%s: Unknown option %s\n") vared $argv
+
+ case '*'
+ if test (count $$argv ) -lt 2
+ set init ''
+ if test $$argv
+ set -- init $$argv
+ end
+ set prompt 'set_color green; echo '$argv'; set_color normal; echo "> "'
+ read -p $prompt -c $init tmp
+
+ # If variable already exists, do not add any
+ # switches, so we don't change export rules. But
+ # if it does not exist, we make the variable
+ # global, so that it will not die when this
+ # function dies
+
+ if test $$argv
+ set -- $argv $tmp
+ else
+ set -g -- $argv $tmp
+ end
+
+ else
+
+ printf (_ '%s: %s is an array variable. Use %svared%s %s[n] to edit the n:th element of %s\n') $argv (set_color $fish_color_command) (set_color $fish_color_normal) vared $argv $argv
+ end
+ end
+ else
+ printf (_ '%s: Expected exactly one argument, got %s.\n\nSynopsis:\n\t%svared%s VARIABLE\n') vared (count $argv) (set_color $fish_color_command) (set_color $fish_color_normal)
+ end
+end
+
diff --git a/main.c b/main.c
index b277ba0a..1744451a 100644
--- a/main.c
+++ b/main.c
@@ -220,6 +220,7 @@ int main( int argc, char **argv )
builtin_init();
function_init();
env_init();
+ parse_util_init();
complete_init();
reader_init();
@@ -303,6 +304,7 @@ int main( int argc, char **argv )
wutil_destroy();
common_destroy();
exec_destroy();
+ parse_util_destroy();
event_destroy();
output_destroy();
translate_destroy();
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;
+ }
+}
diff --git a/parse_util.h b/parse_util.h
index 3b21e09b..53940f63 100644
--- a/parse_util.h
+++ b/parse_util.h
@@ -49,5 +49,16 @@ void parse_util_token_extent( const wchar_t *buff,
int parse_util_lineno( const wchar_t *str, int len );
+int parse_util_load( const wchar_t *cmd,
+ const wchar_t *path_var,
+ void (*on_load)(const wchar_t *cmd),
+ int reload );
+
+void parse_util_init();
+
+
+void parse_util_destroy();
+
+
#endif
diff --git a/parser.c b/parser.c
index 714067b6..1c13cfc1 100644
--- a/parser.c
+++ b/parser.c
@@ -1856,7 +1856,7 @@ static int parse_job( process_t *p,
continue;
}
- if( use_function)
+ if( use_function && !current_block->skip )
{
int nxt_forbidden;
wchar_t *forbid;