First stab at directory transition. Test with care...

darcs-hash:20061019115023-ac50b-30c3fd51d8af8a616d63dfcac39370d7fe6d144e.gz
This commit is contained in:
axel 2006-10-19 21:50:23 +10:00
parent 52b2525b0e
commit ea998b03f2
22 changed files with 904 additions and 565 deletions

View file

@ -54,10 +54,6 @@ CFLAGS=@CFLAGS@ $(MACROS)
CPPFLAGS=@CPPFLAGS@ CPPFLAGS=@CPPFLAGS@
LDFLAGS= @LIBS@ @LDFLAGS@ LDFLAGS= @LIBS@ @LDFLAGS@
#etc files to install
ETC_DIR_INSTALL = etc/fish_interactive.fish
# Set to 1 if we have gettext # Set to 1 if we have gettext
HAVE_GETTEXT=@HAVE_GETTEXT@ HAVE_GETTEXT=@HAVE_GETTEXT@
@ -71,6 +67,7 @@ FISH_OBJS := function.o builtin.o complete.o env.o exec.o \
sanity.o tokenizer.o wildcard.o wgetopt.o wutil.o input.o \ sanity.o tokenizer.o wildcard.o wgetopt.o wutil.o input.o \
output.o intern.o env_universal.o env_universal_common.o \ output.o intern.o env_universal.o env_universal_common.o \
input_common.o event.o signal.o io.o parse_util.o common.o screen.o\ input_common.o event.o signal.o io.o parse_util.o common.o screen.o\
path.o
# Additional files used by builtin.o # Additional files used by builtin.o
BUILTIN_FILES := builtin_help.c builtin_set.c builtin_commandline.c \ BUILTIN_FILES := builtin_help.c builtin_set.c builtin_commandline.c \
@ -153,11 +150,11 @@ MAIN_DIR_FILES := Doxyfile Doxyfile.user Makefile.in configure \
main.c fish_pager.c fishd.c seq.in main.c fish_pager.c fishd.c seq.in
# Files in ./etc/ # Files in ./etc/
ETC_DIR_FILES :=etc/fish.in etc/fish_inputrc \ ETC_DIR_FILES :=etc/config.fish.in etc/fish_inputrc
etc/fish_interactive.fish.in
# Files in ./share/ # Files in ./share/
SHARE_DIR_FILES :=share/fish.in SHARE_DIR_FILES :=share/config.fish.in share/config_interactive.fish.in
# Files in ./tests/ # Files in ./tests/
TESTS_DIR_FILES := $(TEST_IN) $(TEST_IN:.in=.out) $(TEST_IN:.in=.err) \ TESTS_DIR_FILES := $(TEST_IN) $(TEST_IN:.in=.out) $(TEST_IN:.in=.err) \
@ -185,7 +182,7 @@ TRANSLATIONS_SRC := $(wildcard po/*.po)
TRANSLATIONS := $(TRANSLATIONS_SRC:.po=.gmo) TRANSLATIONS := $(TRANSLATIONS_SRC:.po=.gmo)
#Make everything needed for installing fish #Make everything needed for installing fish
all: $(PROGRAMS) user_doc etc/fish share/fish etc/fish_interactive.fish $(TRANSLATIONS) all: $(PROGRAMS) user_doc etc/config.fish share/config.fish share/config_interactive.fish $(TRANSLATIONS)
@echo fish has now been built. @echo fish has now been built.
@echo Use \'make install\' to install fish. @echo Use \'make install\' to install fish.
.PHONY: all .PHONY: all
@ -409,22 +406,20 @@ install-force: all install-translations
for i in $(PROGRAMS); do\ for i in $(PROGRAMS); do\
$(INSTALL) -m 755 $$i $(DESTDIR)$(bindir) ; \ $(INSTALL) -m 755 $$i $(DESTDIR)$(bindir) ; \
done; done;
$(INSTALL) -m 755 -d $(DESTDIR)$(sysconfdir)/fish.d $(INSTALL) -m 755 -d $(DESTDIR)$(sysconfdir)/fish
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish $(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/completions $(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/completions
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/functions $(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/functions
$(INSTALL) -m 644 etc/fish $(DESTDIR)$(sysconfdir)/fish $(INSTALL) -m 644 etc/config.fish $(DESTDIR)$(sysconfdir)/fish/
$(INSTALL) -m 644 share/fish $(DESTDIR)$(datadir)/fish $(INSTALL) -m 644 share/config.fish $(DESTDIR)$(datadir)/fish/
for i in $(ETC_DIR_INSTALL); do \ $(INSTALL) -m 644 share/config_interactive.fish $(DESTDIR)$(datadir)/fish/
$(INSTALL) -m 644 $$i $(DESTDIR)$(sysconfdir)/fish.d; \
done;
for i in $(COMPLETIONS_DIR_FILES); do \ for i in $(COMPLETIONS_DIR_FILES); do \
$(INSTALL) -m 644 $$i $(DESTDIR)$(datadir)/fish/completions/; \ $(INSTALL) -m 644 $$i $(DESTDIR)$(datadir)/fish/completions/; \
done; done;
for i in $(FUNCTIONS_DIR_FILES); do \ for i in $(FUNCTIONS_DIR_FILES); do \
$(INSTALL) -m 644 $$i $(DESTDIR)$(datadir)/fish/functions/; \ $(INSTALL) -m 644 $$i $(DESTDIR)$(datadir)/fish/functions/; \
done; done;
$(INSTALL) -m 644 etc/fish_inputrc $(DESTDIR)$(sysconfdir)/fish_inputrc; $(INSTALL) -m 644 etc/fish_inputrc $(DESTDIR)$(sysconfdir)/fish/fish_inputrc;
$(INSTALL) -m 755 -d $(DESTDIR)$(docdir) $(INSTALL) -m 755 -d $(DESTDIR)$(docdir)
for i in user_doc/html/* ChangeLog; do \ for i in user_doc/html/* ChangeLog; do \
if test -f $$i; then \ if test -f $$i; then \
@ -453,11 +448,9 @@ uninstall: uninstall-translations
rm -f $(DESTDIR)$(bindir)/$$i; \ rm -f $(DESTDIR)$(bindir)/$$i; \
done; done;
rm -f $(DESTDIR)$(bindir)/xsel rm -f $(DESTDIR)$(bindir)/xsel
rm -f $(DESTDIR)$(sysconfdir)/fish rm -f $(DESTDIR)$(sysconfdir)/fish/config.fish
rm -f $(DESTDIR)$(sysconfdir)/fish_inputrc rm -f $(DESTDIR)$(sysconfdir)/fish/fish_inputrc
if test -f $(DESTDIR)$(sysconfdir)/fish.d/fish_interactive.fish; then \ rmdir $(DESTDIR)$(sysconfdir)/fish; true
rm -f $(DESTDIR)$(sysconfdir)/fish.d/fish_interactive.fish; \
fi
if test -d $(DESTDIR)$(datadir)/fish; then \ if test -d $(DESTDIR)$(datadir)/fish; then \
rm -r $(DESTDIR)$(datadir)/fish; \ rm -r $(DESTDIR)$(datadir)/fish; \
fi fi
@ -533,7 +526,7 @@ count: count.o
$(CC) count.o -o $@ $(CC) count.o -o $@
set_color: set_color.o doc_src/set_color.o common.o set_color: set_color.o doc_src/set_color.o common.o
$(CC) set_color.o doc_src/set_color.o common.o $(LDFLAGS) -o $@ $(CC) set_color.o doc_src/set_color.o common.o wutil.o $(LDFLAGS) -o $@
# Test program for the tokenizer library # Test program for the tokenizer library
tokenizer_test: tokenizer.c tokenizer.h wutil.o common.o tokenizer_test: tokenizer.c tokenizer.h wutil.o common.o
@ -638,7 +631,7 @@ clean:
builtin.o: config.h fallback.h util.h wutil.h builtin.h function.h complete.h builtin.o: config.h fallback.h util.h wutil.h builtin.h function.h complete.h
builtin.o: proc.h io.h parser.h event.h reader.h env.h common.h wgetopt.h builtin.o: proc.h io.h parser.h event.h reader.h env.h common.h wgetopt.h
builtin.o: sanity.h tokenizer.h wildcard.h input_common.h input.h intern.h builtin.o: sanity.h tokenizer.h wildcard.h input_common.h input.h intern.h
builtin.o: signal.h halloc.h halloc_util.h parse_util.h expand.h builtin.o: signal.h halloc.h halloc_util.h parse_util.h expand.h path.h
builtin.o: builtin_help.c builtin_set.c builtin_commandline.c builtin.o: builtin_help.c builtin_set.c builtin_commandline.c
builtin.o: builtin_complete.c builtin_ulimit.c builtin_jobs.c builtin.o: builtin_complete.c builtin_ulimit.c builtin_jobs.c
builtin_commandline.o: config.h signal.h fallback.h util.h wutil.h builtin.h builtin_commandline.o: config.h signal.h fallback.h util.h wutil.h builtin.h
@ -660,7 +653,7 @@ common.o: fallback.c
complete.o: config.h signal.h fallback.h util.h tokenizer.h wildcard.h proc.h complete.o: config.h signal.h fallback.h util.h tokenizer.h wildcard.h proc.h
complete.o: io.h parser.h event.h function.h complete.h builtin.h env.h complete.o: io.h parser.h event.h function.h complete.h builtin.h env.h
complete.o: exec.h expand.h common.h reader.h history.h intern.h parse_util.h complete.o: exec.h expand.h common.h reader.h history.h intern.h parse_util.h
complete.o: halloc.h halloc_util.h wutil.h complete.o: halloc.h halloc_util.h wutil.h path.h
count.o: config.h count.o: config.h
env.o: config.h signal.h fallback.h util.h wutil.h proc.h io.h common.h env.h env.o: config.h signal.h fallback.h util.h wutil.h proc.h io.h common.h env.h
env.o: sanity.h expand.h history.h reader.h parser.h event.h env_universal.h env.o: sanity.h expand.h history.h reader.h parser.h event.h env_universal.h
@ -680,14 +673,13 @@ expand.o: io.h parser.h event.h expand.h wildcard.h exec.h tokenizer.h
expand.o: complete.h parse_util.h halloc.h halloc_util.h expand.o: complete.h parse_util.h halloc.h halloc_util.h
fallback.o: config.h fallback.h util.h fallback.o: config.h fallback.h util.h
fishd.o: config.h signal.h fallback.h util.h common.h wutil.h fishd.o: config.h signal.h fallback.h util.h common.h wutil.h
fishd.o: env_universal_common.h fishd.o: env_universal_common.h halloc.h halloc_util.h path.h
fish_pager.o: config.h signal.h fallback.h util.h wutil.h common.h complete.h fish_pager.o: config.h signal.h fallback.h util.h wutil.h common.h complete.h
fish_pager.o: output.h input_common.h env_universal.h env_universal_common.h fish_pager.o: output.h input_common.h env_universal.h env_universal_common.h
fish_pager.o: halloc.h halloc_util.h fish_pager.o: halloc.h halloc_util.h
fish_tests.o: config.h signal.h fallback.h util.h common.h proc.h io.h fish_tests.o: config.h signal.h fallback.h util.h common.h proc.h io.h
fish_tests.o: reader.h builtin.h function.h complete.h wutil.h env.h expand.h fish_tests.o: reader.h builtin.h function.h complete.h wutil.h env.h expand.h
fish_tests.o: parser.h event.h tokenizer.h output.h exec.h halloc_util.h fish_tests.o: parser.h event.h tokenizer.h output.h exec.h halloc_util.h
foo.o: config.h signal.h
function.o: config.h signal.h wutil.h fallback.h util.h function.h proc.h function.o: config.h signal.h wutil.h fallback.h util.h function.h proc.h
function.o: io.h parser.h event.h common.h intern.h reader.h parse_util.h function.o: io.h parser.h event.h common.h intern.h reader.h parse_util.h
function.o: env.h expand.h function.o: env.h expand.h
@ -696,9 +688,9 @@ halloc_util.o: config.h fallback.h util.h common.h halloc.h
highlight.o: config.h signal.h fallback.h util.h wutil.h highlight.h highlight.o: config.h signal.h fallback.h util.h wutil.h highlight.h
highlight.o: tokenizer.h proc.h io.h parser.h event.h parse_util.h builtin.h highlight.o: tokenizer.h proc.h io.h parser.h event.h parse_util.h builtin.h
highlight.o: function.h env.h expand.h sanity.h common.h complete.h output.h highlight.o: function.h env.h expand.h sanity.h common.h complete.h output.h
highlight.o: halloc.h halloc_util.h wildcard.h highlight.o: halloc.h halloc_util.h wildcard.h path.h
history.o: config.h fallback.h util.h wutil.h history.h common.h reader.h history.o: config.h fallback.h util.h wutil.h history.h common.h reader.h
history.o: env.h sanity.h signal.h halloc.h halloc_util.h history.o: env.h sanity.h signal.h halloc.h halloc_util.h path.h
input.o: config.h signal.h fallback.h util.h wutil.h reader.h proc.h io.h input.o: config.h signal.h fallback.h util.h wutil.h reader.h proc.h io.h
input.o: common.h sanity.h input_common.h input.h parser.h event.h env.h input.o: common.h sanity.h input_common.h input.h parser.h event.h env.h
input.o: expand.h output.h intern.h input.o: expand.h output.h intern.h
@ -708,10 +700,11 @@ intern.o: config.h fallback.h util.h wutil.h common.h intern.h
io.o: config.h fallback.h util.h wutil.h exec.h proc.h io.h common.h halloc.h io.o: config.h fallback.h util.h wutil.h exec.h proc.h io.h common.h halloc.h
key_reader.o: config.h fallback.h input_common.h key_reader.o: config.h fallback.h input_common.h
kill.o: config.h signal.h fallback.h util.h wutil.h kill.h proc.h io.h kill.o: config.h signal.h fallback.h util.h wutil.h kill.h proc.h io.h
kill.o: sanity.h common.h env.h exec.h parser.h event.h halloc.h kill.o: sanity.h common.h env.h exec.h halloc.h path.h
main.o: config.h signal.h fallback.h util.h common.h reader.h builtin.h main.o: config.h signal.h fallback.h util.h common.h reader.h builtin.h
main.o: function.h complete.h wutil.h env.h sanity.h proc.h io.h parser.h main.o: function.h complete.h wutil.h env.h sanity.h proc.h io.h parser.h
main.o: event.h expand.h intern.h exec.h output.h halloc_util.h history.h main.o: event.h expand.h intern.h exec.h output.h halloc.h halloc_util.h
main.o: history.h path.h
mimedb.o: config.h xdgmime.h fallback.h util.h mimedb.o: config.h xdgmime.h fallback.h util.h
output.o: config.h signal.h fallback.h util.h wutil.h expand.h common.h output.o: config.h signal.h fallback.h util.h wutil.h expand.h common.h
output.o: output.h halloc_util.h highlight.h output.o: output.h halloc_util.h highlight.h
@ -719,9 +712,12 @@ parser.o: config.h signal.h fallback.h util.h common.h wutil.h proc.h io.h
parser.o: parser.h event.h tokenizer.h exec.h wildcard.h function.h builtin.h parser.o: parser.h event.h tokenizer.h exec.h wildcard.h function.h builtin.h
parser.o: env.h expand.h reader.h sanity.h env_universal.h parser.o: env.h expand.h reader.h sanity.h env_universal.h
parser.o: env_universal_common.h intern.h parse_util.h halloc.h halloc_util.h parser.o: env_universal_common.h intern.h parse_util.h halloc.h halloc_util.h
parser.o: path.h
parse_util.o: config.h fallback.h util.h wutil.h common.h tokenizer.h parse_util.o: config.h fallback.h util.h wutil.h common.h tokenizer.h
parse_util.o: parse_util.h expand.h intern.h exec.h proc.h io.h env.h parse_util.o: parse_util.h expand.h intern.h exec.h proc.h io.h env.h
parse_util.o: wildcard.h halloc_util.h parse_util.o: wildcard.h halloc_util.h
path.o: config.h fallback.h util.h common.h env.h wutil.h halloc.h
path.o: halloc_util.h path.h expand.h
proc.o: config.h signal.h fallback.h util.h wutil.h proc.h io.h common.h proc.o: config.h signal.h fallback.h util.h wutil.h proc.h io.h common.h
proc.o: reader.h sanity.h env.h parser.h event.h halloc.h halloc_util.h proc.o: reader.h sanity.h env.h parser.h event.h halloc.h halloc_util.h
proc.o: output.h proc.o: output.h

View file

@ -65,6 +65,7 @@
#include "halloc_util.h" #include "halloc_util.h"
#include "parse_util.h" #include "parse_util.h"
#include "expand.h" #include "expand.h"
#include "path.h"
@ -2076,7 +2077,7 @@ static int builtin_cd( wchar_t **argv )
else else
dir_in = argv[1]; dir_in = argv[1];
dir = parser_cdpath_get( context, dir_in ); dir = path_get_cdpath( context, dir_in );
if( !dir ) if( !dir )
{ {

View file

@ -1557,3 +1557,42 @@ void tokenize_variable_array( const wchar_t *val, array_list_t *out )
} }
int create_directory( wchar_t *d )
{
int ok = 0;
struct stat buf;
int stat_res = 0;
while( (stat_res = wstat(d, &buf ) ) != 0 )
{
if( errno != EAGAIN )
break;
}
if( stat_res == 0 )
{
if( S_ISDIR( buf.st_mode ) )
{
ok = 1;
}
}
else
{
if( errno == ENOENT )
{
wchar_t *dir = wcsdup( d );
dir = wdirname( dir );
if( !create_directory( dir ) )
{
if( !wmkdir( d, 0700 ) )
{
ok = 1;
}
}
free(dir);
}
}
return ok?0:-1;
}

View file

@ -358,5 +358,12 @@ void write_screen( const wchar_t *msg, string_buffer_t *buff );
void tokenize_variable_array( const wchar_t *val, array_list_t *out ); void tokenize_variable_array( const wchar_t *val, array_list_t *out );
/**
Make sure the specified direcotry exists. If no, try to create it.
\return 0 if the directory exists, -1 otherwise.
*/
int create_directory( wchar_t *d );
#endif #endif

View file

@ -45,6 +45,7 @@
#include "halloc.h" #include "halloc.h"
#include "halloc_util.h" #include "halloc_util.h"
#include "wutil.h" #include "wutil.h"
#include "path.h"
/* /*
@ -407,7 +408,7 @@ void complete_add( const wchar_t *cmd,
complete_entry_opt *opt; complete_entry_opt *opt;
CHECK( cmd, ); CHECK( cmd, );
complete_init(); complete_init();
c = complete_find_exact_entry( cmd, cmd_type ); c = complete_find_exact_entry( cmd, cmd_type );
@ -581,7 +582,7 @@ static void parse_cmd_string( void *context,
wchar_t *cmd, *path; wchar_t *cmd, *path;
/* Get the path of the command */ /* Get the path of the command */
path = parser_get_filename( context, str ); path = path_get_path( context, str );
if( path == 0 ) if( path == 0 )
{ {
/** /**

View file

@ -279,8 +279,8 @@ automatically loaded when needed. A function definition file must have
a filename consisting of the name of the function plus the suffix a filename consisting of the name of the function plus the suffix
'.fish'. '.fish'.
The default value for \$fish_function_path is \c ~/.fish.d/functions The default value for \$fish_function_path is \c ~/.config/fish/functions
\c /etc/fish.d/functions \c /usr/share/fish/functions. The exact path \c /etc/fish/functions \c /usr/share/fish/functions. The exact path
to the last two of these may be slighly different depending on what to the last two of these may be slighly different depending on what
install path prefix was chosen at configuration time. The rationale install path prefix was chosen at configuration time. The rationale
behind having three different directories is that the first one is for behind having three different directories is that the first one is for
@ -404,8 +404,8 @@ searches through any directories in the array variable
loaded when needed. A completion file must have a filename consisting loaded when needed. A completion file must have a filename consisting
of the name of the command to complete and the suffix '.fish'. of the name of the command to complete and the suffix '.fish'.
The default value for \$fish_complete_path is ~/.fish.d/completions, The default value for \$fish_complete_path is ~/.config/fish/completions,
/etc/fish.d/completions and /usr/share/fish/completions. The exact /etc/fish/completions and /usr/share/fish/completions. The exact
path to the last two of these may be slighly different depending on path to the last two of these may be slighly different depending on
what install path prefix was chosen at configuration time. If a what install path prefix was chosen at configuration time. If a
suitable file is found in one of these directories, it will be suitable file is found in one of these directories, it will be
@ -972,8 +972,8 @@ Here are some of the commands available in the editor:
- Alt-p adds the string '| less;' to the end of the job under the cursor. The result is that the output of the command will be paged. - Alt-p adds the string '| less;' to the end of the job under the cursor. The result is that the output of the command will be paged.
You can change these key bindings by making an inputrc file. To do You can change these key bindings by making an inputrc file. To do
this, copy the file /etc/fish_inputrc to your home directory and this, copy the file /etc/fish/fish_inputrc to your home directory and
rename it to '.fish_inputrc'. Now you can edit the file .fish_inputrc, rename it to '.config/fish/fish_inputrc'. Now you can edit the file
to change your key bindings. The fileformat of this file is described to change your key bindings. The fileformat of this file is described
in the manual page for readline. Use the command <code>man readline</code> in the manual page for readline. Use the command <code>man readline</code>
to read up on this syntax. Please note that the list of key binding to read up on this syntax. Please note that the list of key binding
@ -1041,7 +1041,7 @@ cursor when the search began.
History searches can be aborted by pressing the escape key. History searches can be aborted by pressing the escape key.
The history is stored in the file '.fish_history'. It is automatically The history is stored in the file '~/.config/fish/fish_history'. It is automatically
read on startup and merged on program exit. read on startup and merged on program exit.
Example: Example:
@ -1065,20 +1065,23 @@ which the user can change <code>fish</code>'s behaviour.
\section initialization Initialization files \section initialization Initialization files
On startup, \c fish evaluates the files /usr/share/fish/fish, On startup, \c fish evaluates the files /usr/share/fish/config.fish
/etc/fish (Or ~/etc/fish if you installed fish in your home directory) (Or /usr/local/fish... if you installed fish in /usr/local),
and ~/.fish, in that order. The first file should not be directly /etc/fish/config.fish (Or ~/etc/fish/... if you installed fish in your
edited, the second one is meant for systemwide configuration and the home directory) and ~/.config/fish/config.fish (Or any other directory
last one is meant for user configuration. If you want to run a command specified by the \$XDG_CONFIG_HOME variable), in that order. The first
only on starting an interactive shell, use the exit status of the file should not be directly edited, the second one is meant for
command 'status --is-interactive' to determine if the shell is systemwide configuration and the last one is meant for user
interactive. If you want to run a command only when using a login configuration. If you want to run a command only on starting an
shell, use 'status --is-login' instead. interactive shell, use the exit status of the command 'status
--is-interactive' to determine if the shell is interactive. If you
want to run a command only when using a login shell, use 'status
--is-login' instead.
Examples: Examples:
If you want to add the directory ~/linux/bin to your PATH variable If you want to add the directory ~/linux/bin to your PATH variable
when using a login shell, add the following to your ~/.fish file: when using a login shell, add the following to your ~/.config/fish/config.fish file:
<pre>if status --is-login <pre>if status --is-login
set PATH $PATH ~/linux/bin set PATH $PATH ~/linux/bin
@ -1093,7 +1096,7 @@ shell:
end</pre> end</pre>
<a href="#variables-universal">Universal variables</a> are stored in <a href="#variables-universal">Universal variables</a> are stored in
the file .fishd.HOSTNAME, where HOSTNAME is the name of your the file .config/fish/fishd.HOSTNAME, where HOSTNAME is the name of your
computer. Do not edit this file directly, edit them through fish computer. Do not edit this file directly, edit them through fish
scripts or by using fish interactively instead. scripts or by using fish interactively instead.
@ -1302,7 +1305,7 @@ g++, javac, java, gcj, lpr, doxygen, whois, find)
- With a bit of tweakage, quite a few of the readline key-binding functions could be implemented in shellscript. - With a bit of tweakage, quite a few of the readline key-binding functions could be implemented in shellscript.
- Highlight beginning/end of block when moving over a block command - Highlight beginning/end of block when moving over a block command
- Inclusion guards for the init files to make them evaluate only once, even if the user has installed fish both in /etc and in $HOME - Inclusion guards for the init files to make them evaluate only once, even if the user has installed fish both in /etc and in $HOME
- Do not actually load/parse .fish_history, only mmap it and use some clever string handling. Should save ~150 kB of memory permanently, but is very hard to implement. - Do not actually load/parse fish_history, only mmap it and use some clever string handling. Should save ~150 kB of memory permanently, but is very hard to implement.
- command specific wildcarding (use case * instead of case '*', etc.) - command specific wildcarding (use case * instead of case '*', etc.)
- Map variables. (export only the values. When expanding with no key specified, expand to all values.) - Map variables. (export only the values. When expanding with no key specified, expand to all values.)
- Descriptions for variables using 'set -d'. - Descriptions for variables using 'set -d'.

View file

@ -59,6 +59,8 @@ end
# Load additional initialization files # Load additional initialization files
# #
for i in fish.d/*.fish if test -d include
. $i for i in include/*.fish
end . $i
end
end

View file

@ -1,103 +0,0 @@
#
# Initializations that should only be performed when in interactive mode
#
# @configure_input@
if not status --is-interactive
exit
end
#
# Set exit message
#
function fish_on_exit -d (_ "Commands to execute when fish exits") --on-process %self
printf (_ "Good bye\n")
end
#
# Set INPUTRC to something nice
#
# We override INPUTRC if already set, since it may be set by a shell
# other than fish, which may use a different file. The new value should
# be exported, since the fish inputrc file plays nice with other files
# by including them when found.
# Give priority to the default file installed with fish in
# @sysconfdir@/fish_inputrc.
#
for i in ~/.fish_inputrc @sysconfdir@/fish_inputrc ~/.inputrc /etc/inputrc
if test -f $i
set -xg INPUTRC $i
break
end
end
#
# Set various defaults using these throwaway functions
#
function set_default -d "Set an universal variable, unless it has already been set"
if not set -q $argv[1]
set -U -- $argv
end
if not set -q $argv[1]
set -g -- $argv
end
end
function set_exported_default -d "Set an exported universal variable, unless it has already been set"
if not set -q $argv[1]
set -Ux -- $argv
end
if not set -q $argv[1]
set -gx -- $argv
end
end
# Regular syntax highlighting colors
set_default fish_color_normal normal
set_default fish_color_command green
set_default fish_color_redirection normal
set_default fish_color_comment red
set_default fish_color_error red --bold
set_default fish_color_escape cyan
set_default fish_color_operator cyan
set_default fish_color_quote brown
set_default fish_color_valid_path --underline
set_default fish_color_cwd green
# Background color for matching quotes and parenthesis
set_default fish_color_match cyan
# Background color for search matches
set_default fish_color_search_match purple
# Pager colors
set_default fish_pager_color_prefix cyan
set_default fish_pager_color_completion normal
set_default fish_pager_color_description normal
set_default fish_pager_color_progress cyan
#
# Directory history colors
#
set_default fish_color_history_current cyan
#
# Setup the CDPATH variable
#
set_default CDPATH . ~
#
# Remove temporary functions for setting default variable values
#
functions -e set_exported_default
functions -e set_default

View file

@ -133,14 +133,14 @@ fi
%attr(0755,root,root) %_bindir/count %attr(0755,root,root) %_bindir/count
# Configuration files # Configuration files
%config %_sysconfdir/fish %config %_sysconfdir/fish/config.fish
%config %_sysconfdir/fish_inputrc %config %_sysconfdir/fish/fish_inputrc
%dir %_sysconfdir/fish.d %dir %_sysconfdir/fish
%config %_sysconfdir/fish.d/fish_*.fish
# Non-configuration initialization files # Non-configuration initialization files
%dir %_datadir/fish %dir %_datadir/fish
%_datadir/fish/fish %_datadir/fish/config.fish
%_datadir/fish/config_interactive.fish
# Program specific tab-completions # Program specific tab-completions
%dir %_datadir/fish/completions %dir %_datadir/fish/completions
@ -155,6 +155,9 @@ fi
%changelog %changelog
* Sat Oct 14 2006 Axel Liljencrantz<axel@liljencrantz.se> 1.22.0-0
- Update names of various configuration files
* Fri Aug 4 2006 Axel Liljencrantz<axel@liljencrantz.se> 1.21.10-4 * Fri Aug 4 2006 Axel Liljencrantz<axel@liljencrantz.se> 1.21.10-4
- Add better translation finding code from fedora spec to main spec. Thank you to Michael Schwendt. - Add better translation finding code from fedora spec to main spec. Thank you to Michael Schwendt.
- Add missing dependency libXext-devel. - Add missing dependency libXext-devel.

108
fishd.c
View file

@ -70,6 +70,9 @@ time the original barrier request was sent have been received.
#include "common.h" #include "common.h"
#include "wutil.h" #include "wutil.h"
#include "env_universal_common.h" #include "env_universal_common.h"
#include "halloc.h"
#include "halloc_util.h"
#include "path.h"
/** /**
Maximum length of socket filename Maximum length of socket filename
@ -100,7 +103,7 @@ time the original barrier request was sent have been received.
/** /**
The name of the save file. The hostname is appended to this. The name of the save file. The hostname is appended to this.
*/ */
#define FILE ".fishd." #define FILE "fishd."
/** /**
Maximum length of hostname. Longer hostnames are truncated Maximum length of hostname. Longer hostnames are truncated
@ -388,24 +391,108 @@ static void daemonize()
} }
/**
Get environment variable value. The resulting string needs to be free'd.
*/
static wchar_t *fishd_env_get( wchar_t *key )
{
char *nres, *nkey;
wchar_t *res;
nkey = wcs2str( key );
nres = getenv( nkey );
free( nkey );
if( nres )
{
return str2wcs( nres );
}
else
{
res = env_universal_common_get( key );
if( res )
res = wcsdup( res );
return env_universal_common_get( key );
}
}
/**
Get the configuration directory. The resulting string needs to be
free'd. This is mostly the same code as path_get_config(), but had
to be rewritten to avoid dragging in additional library
dependencies.
*/
static wchar_t *fishd_get_config()
{
wchar_t *xdg_dir, *home;
int done = 0;
wchar_t *res = 0;
xdg_dir = fishd_env_get( L"XDG_CONFIG_HOME" );
if( xdg_dir )
{
res = wcsdupcat( xdg_dir, L"/fish" );
if( !create_directory( res ) )
{
done = 1;
}
else
{
free( res );
}
free( xdg_dir );
}
else
{
home = fishd_env_get( L"HOME" );
if( home )
{
res = wcsdupcat( home, L"/.config/fish" );
if( !create_directory( res ) )
{
done = 1;
}
else
{
free( res );
}
free( home );
}
}
if( done )
{
return res;
}
else
{
debug( 0, _(L"Unable to create a configuration directory for fish. Your personal settings will not be saved. Please set the $XDG_CONFIG_HOME variable to a directory where the current user has write access." ));
return 0;
}
}
/** /**
Load or save all variables Load or save all variables
*/ */
static void load_or_save( int save) static void load_or_save( int save)
{ {
struct passwd *pw;
char *name; char *name;
char *dir = getenv( "HOME" ); wchar_t *wdir = fishd_get_config();
char *dir;
char hostname[HOSTNAME_LEN]; char hostname[HOSTNAME_LEN];
connection_t c; connection_t c;
int fd; int fd;
if( !dir ) if( !wdir )
{ {
pw = getpwuid( getuid() ); return;
dir = pw->pw_dir;
} }
dir = wcs2str( wdir );
free( wdir );
gethostname( hostname, HOSTNAME_LEN ); gethostname( hostname, HOSTNAME_LEN );
name = malloc( strlen(dir)+ strlen(FILE)+ strlen(hostname) + 2 ); name = malloc( strlen(dir)+ strlen(FILE)+ strlen(hostname) + 2 );
@ -413,6 +500,9 @@ static void load_or_save( int save)
strcat( name, "/" ); strcat( name, "/" );
strcat( name, FILE ); strcat( name, FILE );
strcat( name, hostname ); strcat( name, hostname );
free( dir );
debug( 4, L"Open file for %s: '%s'", debug( 4, L"Open file for %s: '%s'",
save?"saving":"loading", save?"saving":"loading",
@ -485,6 +575,8 @@ int main( int argc, char ** argv )
int update_count=0; int update_count=0;
fd_set read_fd, write_fd; fd_set read_fd, write_fd;
halloc_util_init();
program_name=L"fishd"; program_name=L"fishd";
wsetlocale( LC_ALL, L"" ); wsetlocale( LC_ALL, L"" );
@ -685,10 +777,10 @@ int main( int argc, char ** argv )
debug( 0, L"No more clients. Quitting" ); debug( 0, L"No more clients. Quitting" );
save(); save();
env_universal_common_destroy(); env_universal_common_destroy();
exit(0); break;
c=c->next;
} }
} }
halloc_util_destroy();
} }

View file

@ -33,6 +33,7 @@
#include "halloc.h" #include "halloc.h"
#include "halloc_util.h" #include "halloc_util.h"
#include "wildcard.h" #include "wildcard.h"
#include "path.h"
/** /**
Number of elements in the highlight_var array Number of elements in the highlight_var array
@ -588,7 +589,7 @@ void highlight_shell( wchar_t * buff,
EXPAND_SKIP_CMDSUBST ); EXPAND_SKIP_CMDSUBST );
if( dir ) if( dir )
{ {
if( !parser_cdpath_get( context, dir ) ) if( !path_get_cdpath( context, dir ) )
{ {
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_ERROR; color[ tok_get_pos( &tok ) ] = HIGHLIGHT_ERROR;
} }
@ -671,13 +672,13 @@ void highlight_shell( wchar_t * buff,
/* /*
Check if this is a regular command Check if this is a regular command
*/ */
is_cmd |= !!(tmp=parser_get_filename( context, cmd )); is_cmd |= !!(tmp=path_get_path( context, cmd ));
/* /*
Could not find the command. Maybe it is Could not find the command. Maybe it is
a path for a implicit cd command. a path for a implicit cd command.
*/ */
is_cmd |= !!(tmp=parser_cdpath_get( context, cmd )); is_cmd |= !!(tmp=path_get_cdpath( context, cmd ));
if( is_cmd ) if( is_cmd )
{ {

View file

@ -25,6 +25,7 @@
#include "signal.h" #include "signal.h"
#include "halloc.h" #include "halloc.h"
#include "halloc_util.h" #include "halloc_util.h"
#include "path.h"
/* /*
The history is implemented using a linked list. Searches are done The history is implemented using a linked list. Searches are done
@ -230,6 +231,19 @@ static wchar_t *history_unescape_newlines( wchar_t *in )
return (wchar_t *)out->buff; return (wchar_t *)out->buff;
} }
static wchar_t *history_file_name( void *context )
{
wchar_t *path = path_get_config( context );
wchar_t *res;
if( !path )
return 0;
res = wcsdupcat2( path, L"/", mode_name, L"_history", (void *)0 );
halloc_register_function( context, &free, res );
return res;
}
/** /**
Read a complete histor entry from the specified FILE. Read a complete histor entry from the specified FILE.
*/ */
@ -310,12 +324,15 @@ static int history_load()
FILE *in_stream; FILE *in_stream;
hash_table_t used; hash_table_t used;
int res = 0; int res = 0;
void *context;
if( !mode_name ) if( !mode_name )
{ {
return -1; return -1;
} }
context = halloc( 0, 0 );
is_loaded = 1; is_loaded = 1;
signal_block(); signal_block();
@ -324,8 +341,10 @@ static int history_load()
&hash_wcs_cmp, &hash_wcs_cmp,
4096 ); 4096 );
fn = wcsdupcat2( env_get(L"HOME"), L"/.", mode_name, L"_history", (void *)0 ); fn = history_file_name( context );
if( fn )
{
in_stream = wfopen( fn, "r" ); in_stream = wfopen( fn, "r" );
if( in_stream != 0 ) if( in_stream != 0 )
@ -374,15 +393,15 @@ static int history_load()
res = -1; res = -1;
} }
}
}
last_loaded = history_last;
}
hash_destroy( &used ); hash_destroy( &used );
free( fn );
last_loaded = history_last;
signal_unblock(); signal_unblock();
halloc_free( context );
return res; return res;
} }
@ -549,24 +568,29 @@ static void history_save()
/* Save the global history */ /* Save the global history */
{ {
fn = wcsdupcat2( env_get(L"HOME"), L"/.", mode_name, L"_history", (void *)0 ); void *context = halloc( 0, 0 );
fn = history_file_name( context );
out_stream = wfopen( fn, "w" ); if( fn )
if( out_stream )
{ {
history_save_node( history_last, out_stream ); out_stream = wfopen( fn, "w" );
if( fclose( out_stream ) )
if( out_stream )
{
history_save_node( history_last, out_stream );
if( fclose( out_stream ) )
{
debug( 1, L"The following non-fatal error occurred while saving command history to \'%ls\':", fn );
wperror( L"fopen" );
}
}
else
{ {
debug( 1, L"The following non-fatal error occurred while saving command history to \'%ls\':", fn ); debug( 1, L"The following non-fatal error occurred while saving command history to \'%ls\':", fn );
wperror( L"fopen" ); wperror( L"fopen" );
} }
} }
else
{ halloc_free( context );
debug( 1, L"The following non-fatal error occurred while saving command history to \'%ls\':", fn );
wperror( L"fopen" );
}
free( fn );
} }
} }

4
kill.c
View file

@ -29,8 +29,8 @@
#include "common.h" #include "common.h"
#include "env.h" #include "env.h"
#include "exec.h" #include "exec.h"
#include "parser.h"
#include "halloc.h" #include "halloc.h"
#include "path.h"
/** /**
Maximum entries in killring Maximum entries in killring
@ -50,7 +50,7 @@ static wchar_t *cut_buffer=0;
static int has_xsel() static int has_xsel()
{ {
void *context = halloc(0, 0); void *context = halloc(0, 0);
wchar_t *path = parser_get_filename( context, L"xsel" ); wchar_t *path = path_get_path( context, L"xsel" );
int res = !!path; int res = !!path;
halloc_free( context ); halloc_free( context );
return res; return res;

33
main.c
View file

@ -58,9 +58,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "exec.h" #include "exec.h"
#include "event.h" #include "event.h"
#include "output.h" #include "output.h"
#include "halloc.h"
#include "halloc_util.h" #include "halloc_util.h"
#include "history.h" #include "history.h"
#include "path.h"
/** /**
The string describing the single-character options accepted by the main fish binary The string describing the single-character options accepted by the main fish binary
@ -75,23 +76,42 @@ static int read_init()
char cwd[4096]; char cwd[4096];
wchar_t *wcwd; wchar_t *wcwd;
wchar_t *config_dir;
wchar_t *config_dir_escaped;
void *context;
string_buffer_t *eval_buff;
if( !getcwd( cwd, 4096 ) ) if( !getcwd( cwd, 4096 ) )
{ {
wperror( L"getcwd" ); wperror( L"getcwd" );
return 0; return 0;
} }
eval( L"builtin cd " DATADIR L"/fish 2>/dev/null; and builtin . fish 2>/dev/null", 0, TOP ); eval( L"builtin cd " DATADIR L"/fish 2>/dev/null; and builtin . config.fish 2>/dev/null", 0, TOP );
eval( L"builtin cd " SYSCONFDIR L" 2>/dev/null; and builtin . fish 2>/dev/null", 0, TOP ); eval( L"builtin cd " SYSCONFDIR L"/fish 2>/dev/null; and builtin . config.fish 2>/dev/null", 0, TOP );
eval( L"builtin cd 2>/dev/null; and builtin . .fish 2>/dev/null", 0, TOP );
/*
We need to get the configuration directory before we can source the user configuration file
*/
context = halloc( 0, 0 );
eval_buff = sb_halloc( context );
config_dir = path_get_config( context );
config_dir_escaped = escape( config_dir, 1 );
sb_printf( eval_buff, L"builtin cd %ls 2>/dev/null; and builtin . config.fish 2>/dev/null", config_dir_escaped );
eval( (wchar_t *)eval_buff->buff, 0, TOP );
halloc_free( context );
free( config_dir_escaped );
if( chdir( cwd ) == -1 ) if( chdir( cwd ) == -1 )
{ {
/* /*
If we can't change back to previos directory, we'll stay in If we can't change back to previos directory, we go to
~. Should be a sane default behavior. ~. Should be a sane default behavior.
*/ */
eval( L"builtin cd", 0, TOP );
} }
wcwd = str2wcs( cwd ); wcwd = str2wcs( cwd );
if( wcwd ) if( wcwd )
{ {
@ -281,6 +301,7 @@ int main( int argc, char **argv )
reader_init(); reader_init();
history_init(); history_init();
if( read_init() ) if( read_init() )
{ {
if( cmd != 0 ) if( cmd != 0 )

201
parser.c
View file

@ -37,11 +37,11 @@ The fish parser. Contains functions for parsing code.
#include "sanity.h" #include "sanity.h"
#include "env_universal.h" #include "env_universal.h"
#include "event.h" #include "event.h"
#include "intern.h" #include "intern.h"
#include "parse_util.h" #include "parse_util.h"
#include "halloc.h" #include "halloc.h"
#include "halloc_util.h" #include "halloc_util.h"
#include "path.h"
/** /**
Maximum number of block levels in code. This is not the same as Maximum number of block levels in code. This is not the same as
@ -173,18 +173,11 @@ The fish parser. Contains functions for parsing code.
*/ */
#define UNEXPECTED_TOKEN_ERR_MSG _( L"Unexpected token of type '%ls'") #define UNEXPECTED_TOKEN_ERR_MSG _( L"Unexpected token of type '%ls'")
/**
Unexpected error in parser_get_filename()
*/
#define MISSING_COMMAND_ERR_MSG _( L"Error while searching for command '%ls'" )
/** /**
While block description While block description
*/ */
#define WHILE_BLOCK N_( L"'while' block" ) #define WHILE_BLOCK N_( L"'while' block" )
/** /**
For block description For block description
*/ */
@ -652,87 +645,6 @@ static const wchar_t *parser_find_end( const wchar_t * buff )
} }
wchar_t *parser_cdpath_get( void *context, wchar_t *dir )
{
wchar_t *res = 0;
if( !dir )
return 0;
if( dir[0] == L'/'|| (wcsncmp( dir, L"./", 2 )==0) )
{
struct stat buf;
if( wstat( dir, &buf ) == 0 )
{
if( S_ISDIR(buf.st_mode) )
{
res = halloc_wcsdup( context, dir );
}
}
}
else
{
wchar_t *path;
wchar_t *path_cpy;
wchar_t *nxt_path;
wchar_t *state;
wchar_t *whole_path;
path = env_get(L"CDPATH");
if( !path || !wcslen(path) )
{
path = L".";
}
nxt_path = path;
path_cpy = wcsdup( path );
if( !path_cpy )
{
DIE_MEM();
}
for( nxt_path = wcstok( path_cpy, ARRAY_SEP_STR, &state );
nxt_path != 0;
nxt_path = wcstok( 0, ARRAY_SEP_STR, &state) )
{
wchar_t *expanded_path = expand_tilde( wcsdup(nxt_path) );
// debug( 2, L"woot %ls\n", expanded_path );
int path_len = wcslen( expanded_path );
if( path_len == 0 )
{
free(expanded_path );
continue;
}
whole_path =
wcsdupcat2( expanded_path,
( expanded_path[path_len-1] != L'/' )?L"/":L"",
dir, (void *)0 );
free(expanded_path );
struct stat buf;
if( wstat( whole_path, &buf ) == 0 )
{
if( S_ISDIR(buf.st_mode) )
{
res = whole_path;
halloc_register( context, whole_path );
break;
}
}
free( whole_path );
}
free( path_cpy );
}
return res;
}
void parser_forbid_function( wchar_t *function ) void parser_forbid_function( wchar_t *function )
{ {
@ -771,111 +683,6 @@ void error( int ec, int p, const wchar_t *str, ... )
} }
wchar_t *parser_get_filename( void *context, const wchar_t *cmd )
{
wchar_t *path;
CHECK( cmd, 0 );
debug( 3, L"parser_get_filename( '%ls' )", cmd );
if(wcschr( cmd, L'/' ) != 0 )
{
if( waccess( cmd, X_OK )==0 )
{
struct stat buff;
wstat( cmd, &buff );
if( S_ISREG(buff.st_mode) )
return halloc_wcsdup( context, cmd );
else
return 0;
}
}
else
{
path = env_get(L"PATH");
if( path == 0 )
{
if( contains_str( PREFIX L"/bin", L"/bin", L"/usr/bin", (void *)0 ) )
{
path = L"/bin" ARRAY_SEP_STR L"/usr/bin";
}
else
{
path = L"/bin" ARRAY_SEP_STR L"/usr/bin" ARRAY_SEP_STR PREFIX L"/bin";
}
}
/*
Allocate string long enough to hold the whole command
*/
wchar_t *new_cmd = halloc( context, sizeof(wchar_t)*(wcslen(cmd)+wcslen(path)+2) );
/*
We tokenize a copy of the path, since strtok modifies
its arguments
*/
wchar_t *path_cpy = wcsdup( path );
wchar_t *nxt_path = path;
wchar_t *state;
if( (new_cmd==0) || (path_cpy==0) )
{
DIE_MEM();
}
for( nxt_path = wcstok( path_cpy, ARRAY_SEP_STR, &state );
nxt_path != 0;
nxt_path = wcstok( 0, ARRAY_SEP_STR, &state) )
{
int path_len = wcslen( nxt_path );
wcscpy( new_cmd, nxt_path );
if( new_cmd[path_len-1] != L'/' )
{
new_cmd[path_len++]=L'/';
}
wcscpy( &new_cmd[path_len], cmd );
if( waccess( new_cmd, X_OK )==0 )
{
struct stat buff;
if( wstat( new_cmd, &buff )==-1 )
{
if( errno != EACCES )
{
wperror( L"stat" );
}
continue;
}
if( S_ISREG(buff.st_mode) )
{
free( path_cpy );
return new_cmd;
}
}
else
{
switch( errno )
{
case ENOENT:
case ENAMETOOLONG:
case EACCES:
case ENOTDIR:
break;
default:
{
debug( 1,
MISSING_COMMAND_ERR_MSG,
new_cmd );
wperror( L"access" );
}
}
}
}
free( path_cpy );
}
return 0;
}
void parser_init() void parser_init()
{ {
if( profile ) if( profile )
@ -2141,7 +1948,7 @@ static int parse_job( process_t *p,
} }
else else
{ {
p->actual_cmd = parser_get_filename( j, (wchar_t *)al_get( args, 0 ) ); p->actual_cmd = path_get_path( j, (wchar_t *)al_get( args, 0 ) );
/* /*
Check if the specified command exists Check if the specified command exists
@ -2155,7 +1962,7 @@ static int parse_job( process_t *p,
implicit command. implicit command.
*/ */
wchar_t *pp = wchar_t *pp =
parser_cdpath_get( j, (wchar_t *)al_get( args, 0 ) ); path_get_cdpath( j, (wchar_t *)al_get( args, 0 ) );
if( pp ) if( pp )
{ {
wchar_t *tmp; wchar_t *tmp;

View file

@ -188,15 +188,6 @@ extern event_block_t *global_event_block;
*/ */
extern io_data_t *block_io; extern io_data_t *block_io;
/**
Finds the full path of an executable in a newly allocated string.
\param cmd The name of the executable.
\param context the halloc context to use for memory allocations
\return 0 if the command can not be found, the path of the command otherwise.
*/
wchar_t *parser_get_filename( void *context, const wchar_t *cmd );
/** /**
Evaluate the expressions contained in cmd. Evaluate the expressions contained in cmd.
@ -325,15 +316,6 @@ int parser_test( const wchar_t * buff, int *block_level, string_buffer_t *out, c
*/ */
int parser_test_args( const wchar_t * buff, string_buffer_t *out, const wchar_t *prefix ); int parser_test_args( const wchar_t * buff, string_buffer_t *out, const wchar_t *prefix );
/**
Returns the full path of the specified directory. If the \c in is a
full path to an existing directory, a copy of the string is
returned. If \c in is a directory relative to one of the
directories i the CDPATH, the full path is returned. If no
directory can be found, 0 is returned.
*/
wchar_t *parser_cdpath_get( void *context, wchar_t *in );
/** /**
Tell the parser that the specified function may not be run if not Tell the parser that the specified function may not be run if not
inside of a conditional block. This is to remove some possibilities inside of a conditional block. This is to remove some possibilities

267
path.c Normal file
View file

@ -0,0 +1,267 @@
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <wchar.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <libgen.h>
#include "fallback.h"
#include "util.h"
#include "common.h"
#include "env.h"
#include "wutil.h"
#include "halloc.h"
#include "halloc_util.h"
#include "path.h"
#include "expand.h"
/**
Unexpected error in path_get_path()
*/
#define MISSING_COMMAND_ERR_MSG _( L"Error while searching for command '%ls'" )
wchar_t *path_get_path( void *context, const wchar_t *cmd )
{
wchar_t *path;
CHECK( cmd, 0 );
debug( 3, L"path_get_path( '%ls' )", cmd );
if(wcschr( cmd, L'/' ) != 0 )
{
if( waccess( cmd, X_OK )==0 )
{
struct stat buff;
wstat( cmd, &buff );
if( S_ISREG(buff.st_mode) )
return halloc_wcsdup( context, cmd );
else
return 0;
}
}
else
{
path = env_get(L"PATH");
if( path == 0 )
{
if( contains_str( PREFIX L"/bin", L"/bin", L"/usr/bin", (void *)0 ) )
{
path = L"/bin" ARRAY_SEP_STR L"/usr/bin";
}
else
{
path = L"/bin" ARRAY_SEP_STR L"/usr/bin" ARRAY_SEP_STR PREFIX L"/bin";
}
}
/*
Allocate string long enough to hold the whole command
*/
wchar_t *new_cmd = halloc( context, sizeof(wchar_t)*(wcslen(cmd)+wcslen(path)+2) );
/*
We tokenize a copy of the path, since strtok modifies
its arguments
*/
wchar_t *path_cpy = wcsdup( path );
wchar_t *nxt_path = path;
wchar_t *state;
if( (new_cmd==0) || (path_cpy==0) )
{
DIE_MEM();
}
for( nxt_path = wcstok( path_cpy, ARRAY_SEP_STR, &state );
nxt_path != 0;
nxt_path = wcstok( 0, ARRAY_SEP_STR, &state) )
{
int path_len = wcslen( nxt_path );
wcscpy( new_cmd, nxt_path );
if( new_cmd[path_len-1] != L'/' )
{
new_cmd[path_len++]=L'/';
}
wcscpy( &new_cmd[path_len], cmd );
if( waccess( new_cmd, X_OK )==0 )
{
struct stat buff;
if( wstat( new_cmd, &buff )==-1 )
{
if( errno != EACCES )
{
wperror( L"stat" );
}
continue;
}
if( S_ISREG(buff.st_mode) )
{
free( path_cpy );
return new_cmd;
}
}
else
{
switch( errno )
{
case ENOENT:
case ENAMETOOLONG:
case EACCES:
case ENOTDIR:
break;
default:
{
debug( 1,
MISSING_COMMAND_ERR_MSG,
new_cmd );
wperror( L"access" );
}
}
}
}
free( path_cpy );
}
return 0;
}
wchar_t *path_get_cdpath( void *context, wchar_t *dir )
{
wchar_t *res = 0;
if( !dir )
return 0;
if( dir[0] == L'/'|| (wcsncmp( dir, L"./", 2 )==0) )
{
struct stat buf;
if( wstat( dir, &buf ) == 0 )
{
if( S_ISDIR(buf.st_mode) )
{
res = halloc_wcsdup( context, dir );
}
}
}
else
{
wchar_t *path;
wchar_t *path_cpy;
wchar_t *nxt_path;
wchar_t *state;
wchar_t *whole_path;
path = env_get(L"CDPATH");
if( !path || !wcslen(path) )
{
path = L".";
}
nxt_path = path;
path_cpy = wcsdup( path );
if( !path_cpy )
{
DIE_MEM();
}
for( nxt_path = wcstok( path_cpy, ARRAY_SEP_STR, &state );
nxt_path != 0;
nxt_path = wcstok( 0, ARRAY_SEP_STR, &state) )
{
wchar_t *expanded_path = expand_tilde( wcsdup(nxt_path) );
// debug( 2, L"woot %ls\n", expanded_path );
int path_len = wcslen( expanded_path );
if( path_len == 0 )
{
free(expanded_path );
continue;
}
whole_path =
wcsdupcat2( expanded_path,
( expanded_path[path_len-1] != L'/' )?L"/":L"",
dir, (void *)0 );
free(expanded_path );
struct stat buf;
if( wstat( whole_path, &buf ) == 0 )
{
if( S_ISDIR(buf.st_mode) )
{
res = whole_path;
halloc_register( context, whole_path );
break;
}
}
free( whole_path );
}
free( path_cpy );
}
return res;
}
wchar_t *path_get_config( void *context)
{
wchar_t *xdg_dir, *home;
int done = 0;
wchar_t *res = 0;
xdg_dir = env_get( L"XDG_CONFIG_HOME" );
if( xdg_dir )
{
res = wcsdupcat( xdg_dir, L"/fish" );
if( !create_directory( res ) )
{
done = 1;
}
else
{
free( res );
}
}
else
{
home = env_get( L"HOME" );
if( home )
{
res = wcsdupcat( home, L"/.config/fish" );
if( !create_directory( res ) )
{
done = 1;
}
else
{
free( res );
}
}
}
if( done )
{
halloc_register_function( context, &free, res );
return res;
}
else
{
debug( 0, _(L"Unable to create a configuration directory for fish. Your personal settings will not be saved. Please set the $XDG_CONFIG_HOME variable to a directory where the current user has write access." ));
return 0;
}
}

43
path.h Normal file
View file

@ -0,0 +1,43 @@
/** \file path.h
Directory utilities. This library contains functions for locating
configuration directories, for testing if a command with a given
name can be found in the PATH, and various other path-related
issues.
*/
#ifndef FISH_PATH_H
#define FISH_PATH_H
/**
Returns the user configuration directory for fish. If the directory
or one of it's parents doesn't exist, they are first created.
\param context the halloc context to use for memory allocations
\return 0 if the no configuration directory can be located or created, the directory path otherwise.
*/
wchar_t *path_get_config( void *context);
/**
Finds the full path of an executable in a newly allocated string.
\param cmd The name of the executable.
\param context the halloc context to use for memory allocations
\return 0 if the command can not be found, the path of the command otherwise.
*/
wchar_t *path_get_path( void *context, const wchar_t *cmd );
/**
Returns the full path of the specified directory. If the \c in is a
full path to an existing directory, a copy of the string is
returned. If \c in is a directory relative to one of the
directories i the CDPATH, the full path is returned. If no
directory can be found, 0 is returned.
\param in The name of the directory.
\param context the halloc context to use for memory allocations
\return 0 if the command can not be found, the path of the command otherwise.
*/
wchar_t *path_get_cdpath( void *context, wchar_t *in );
#endif

86
share/config.fish.in Normal file
View file

@ -0,0 +1,86 @@
#
# Main file for fish command completions. This file contains various
# common helper functions for the command completions. All actual
# completions are located in the completions subdirectory.
#
# @configure_input@
#
# Set default search paths for completions and shellscript functions
# unless they already exist
#
set -l configdir ~/.config
if set -q XDG_CONFIG_HOME
set configdir $XDG_CONFIG_HOME
end
if not set -q fish_function_path
set -U fish_function_path $configdir/fish/functions @sysconfdir@/fish/functions @datadir@/fish/functions
end
if not set -q fish_complete_path
set -U fish_complete_path $configdir/fish/completions @sysconfdir@/fish/completions @datadir@/fish/completions
end
set __fish_help_dir @docdir@
# This is a Solaris-specific test to modify the PATH so that
# Posix-conformant tools are used by default.
if test -d /usr/xpg4/bin
if not contains /usr/xpg4/bin $PATH
set PATH /usr/xpg4/bin $PATH
end
end
#
# Make sure there are no invalid entries in the PATH
#
if status --is-interactive
set -l erase_idx
for idx in (seq (count $PATH))
set i $PATH[$idx]
if not test -d $i
set erase_idx $erase_idx $idx
printf (_ '%s: Warning: The directory %s has been removed from your PATH because it does not exist\n') fish $i
end
end
if count $erase_idx >/dev/null
set -e PATH[(echo $erase_idx)]
end
end
#
# Add a few common directories to path, if they exists. Note that pure
# console programs like makedep sometimes live in /usr/X11R6/bin, so we
# want this even for text-only terminals.
#
set -l path_list /bin /usr/bin /usr/X11R6/bin @prefix@/bin @optbindirs@
# Root should also have the sbin directories in the path
if test "$USER" = root
set path_list $path_list /sbin /usr/sbin /usr/local/sbin
end
# Make a regular expression that matches any component in the PATH. A
# trailing slash is ok. The sed call is to remove the last '|'.
set -l tmp (printf "%s" \^$PATH'/?$|')
set -l path_regexp \((echo $tmp | sed -e "s/.\$//")\)
for i in (printf "%s\n" $path_list|grep -E -v $path_regexp)
if test -d $i
set PATH $PATH $i
end
end
if status --is-interactive
. config_interactive.fish
end

View file

@ -0,0 +1,213 @@
#
# Initializations that should only be performed when in interactive mode.
#
#
# @configure_input@
#
set -l configdir ~/.config
if set -q XDG_CONFIG_HOME
set configdir $XDG_CONFIG_HOME
end
if not set -q __fish_init_1_22_0
if test -f ~/.fish_history -o -f ~/.fish -o -d ~/.fish.d -a ! -d $configdir/fish
# Perform upgrade of configuration file hierarchy
if not test -d $configdir
builtin mkdir $configdir >/dev/null
end
if test -d $configdir
if builtin mkdir $configdir/fish
# These files are sometimes overwritten to by fish, so
# we want backups of them in case something goes wrong
cp ~/.fishd.(hostname) $configdir/fish/fishh.(hostname).backup
cp ~/.fish_history $configdir/fish/fish_history.backup
# Move the files
mv ~/.fish_history $configdir/fish/fish_history
mv ~/.fish $configdir/fish/config.fish
mv ~/.fish_inputrc $configdir/fish/fish_inputrc
mv ~/.fish.d/functions $configdir/fish/functions
mv ~/.fish.d/completions $configdir/fish/completions
#
# Move the fishd stuff from another shell to avoid concurrency problems
#
/bin/sh -c mv\ \~/.fishd.(hostname)\ $configdir/fish/fishd.(hostname)\;kill\ -9\ (echo %fishd)
# Update paths to point to new configuration locations
set fish_function_path (printf "%s\n" $fish_function_path|sed -e "s|@sysconfdir@/fish.d/|@sysconfdir@/fish/|")
set fish_complete_path (printf "%s\n" $fish_complete_path|sed -e "s|@sysconfdir@/fish.d/|@sysconfdir@/fish/|")
set fish_function_path (printf "%s\n" $fish_function_path|sed -e "s|$HOME/.fish.d/|$configdir/fish/|")
set fish_complete_path (printf "%s\n" $fish_complete_path|sed -e "s|$HOME/.fish.d/|$configdir/fish/|")
printf (_ "\nWARNING\n\nThe location for fish configuration files has changed to %s.\nYour old files have been moved to this location.\n You can change to a different location by changing the value of the variable \$XDG_CONFIG_HOME.\n\n") $configdir
end ^/dev/null
end
end
# Make sure this is only done once
set -U __fish_init_1_22_0
end
#
# Print a greeting
#
if not set -q fish_greeting
set -l line1 (printf (_ 'Welcome to fish, the friendly interactive shell') )
set -l line2 (printf (_ 'Type %shelp%s for instructions on how to use fish') (set_color green) (set_color normal))
set -U fish_greeting $line1\n$line2
end
echo $fish_greeting
#
# Set exit message
#
function fish_on_exit -d (_ "Commands to execute when fish exits") --on-process %self
printf (_ "Good bye\n")
end
#
# Set INPUTRC to something nice
#
# We override INPUTRC if already set, since it may be set by a shell
# other than fish, which may use a different file. The new value should
# be exported, since the fish inputrc file plays nice with other files
# by including them when found.
#
for i in ~/$config_dir/fish/fish_inputrc @sysconfdir@/fish/fish_inputrc ~/.inputrc /etc/inputrc
if test -f $i
set -xg INPUTRC $i
break
end
end
#
# Set various defaults using these throwaway functions
#
function set_default -d "Set an universal variable, unless it has already been set"
if not set -q $argv[1]
set -U -- $argv
end
if not set -q $argv[1]
set -g -- $argv
end
end
# Regular syntax highlighting colors
set_default fish_color_normal normal
set_default fish_color_command green
set_default fish_color_redirection normal
set_default fish_color_comment red
set_default fish_color_error red --bold
set_default fish_color_escape cyan
set_default fish_color_operator cyan
set_default fish_color_quote brown
set_default fish_color_valid_path --underline
set_default fish_color_cwd green
# Background color for matching quotes and parenthesis
set_default fish_color_match cyan
# Background color for search matches
set_default fish_color_search_match purple
# Pager colors
set_default fish_pager_color_prefix cyan
set_default fish_pager_color_completion normal
set_default fish_pager_color_description normal
set_default fish_pager_color_progress cyan
#
# Directory history colors
#
set_default fish_color_history_current cyan
#
# Setup the CDPATH variable
#
set_default CDPATH . ~
#
# Remove temporary functions for setting default variable values
#
functions -e set_default
#
# A few minor convenience functions
#
# The naming heuristic is that __fish_complete_* prints completions
# and descriptions, while __fish_print_* only prints the completions
# and no descriptions
#
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
function __fish_complete_groups -d "Print a list of local groups, with group members as the description"
cat /etc/group | sed -e "s/^\([^:]*\):[^:]*:[^:]*:\(.*\)/\1\tMembers: \2/"
end
function __fish_complete_command -d "Complete using all available commands"
printf "%s\n" (commandline -ct)(complete -C (commandline -ct))
end
function __fish_print_interfaces -d "Print a list of known network interfaces"
netstat -i -n -a | awk 'NR>2'|awk '{print $1}'
end
function __fish_print_addresses -d "Print a list of known network addresses"
/sbin/ifconfig |grep 'inet addr'|cut -d : -f 2|cut -d ' ' -f 1
end
function __fish_print_users -d "Print a list of local users"
cat /etc/passwd | cut -d : -f 1
end
#
# Completions for the shell and it's builtin commands and functions
#
for i in (builtin -n|grep -E -v '(while|for|if|function|switch)' )
complete -c $i -s h -l help -d "Display help and exit"
end
#
# Completions for SysV startup scripts
#
complete -x -p "/etc/init.d/*" -a start\t(_ 'Start service')
complete -x -p "/etc/init.d/*" -a stop\t(_ 'Stop service')
complete -x -p "/etc/init.d/*" -a status\t(_ 'Print service status')
complete -x -p "/etc/init.d/*" -a restart\t(_ 'Stop and then start service')
complete -x -p "/etc/init.d/*" -a reload\t(_ 'Reload service configuration')

View file

@ -1,148 +0,0 @@
#
# Main file for fish command completions. This file contains various
# common helper functions for the command completions. All actual
# completions are located in the completions subdirectory.
#
# @configure_input@
#
# Set default search paths for completions and shellscript functions
# unless they already exist
#
if not set -q fish_function_path
set -U fish_function_path ~/.fish.d/functions @sysconfdir@/fish.d/functions @datadir@/fish/functions
end
if not set -q fish_complete_path
set -U fish_complete_path ~/.fish.d/completions @sysconfdir@/fish.d/completions @datadir@/fish/completions
end
set __fish_help_dir @docdir@
# This is a Solaris-specific test to modify the PATH so that
# Posix-conformant tools are used by default.
if test -d /usr/xpg4/bin
if not contains /usr/xpg4/bin $PATH
set PATH /usr/xpg4/bin $PATH
end
end
#
# Make sure there are no invalid entries in the PATH
#
if status --is-interactive
set -l erase_idx
for idx in (seq (count $PATH))
set i $PATH[$idx]
if not test -d $i
set erase_idx $erase_idx $idx
printf (_ '%s: Warning: The directory %s has been removed from your PATH because it does not exist\n') fish $i
end
end
if count $erase_idx >/dev/null
set -e PATH[(echo $erase_idx)]
end
end
#
# Add a few common directories to path, if they exists. Note that pure
# console programs like makedep sometimes live in /usr/X11R6/bin, so we
# want this even for text-only terminals.
#
set -l path_list /bin /usr/bin /usr/X11R6/bin @prefix@/bin @optbindirs@
# Root should also have the sbin directories in the path
if test "$USER" = root
set path_list $path_list /sbin /usr/sbin /usr/local/sbin
end
# Make a regular expression that matches any component in the PATH. A
# trailing slash is ok. The sed call is to remove the last '|'.
set -l tmp (printf "%s" \^$PATH'/?$|')
set -l path_regexp \((echo $tmp | sed -e "s/.\$//")\)
for i in (printf "%s\n" $path_list|grep -E -v $path_regexp)
if test -d $i
set PATH $PATH $i
end
end
#
# Print a greeting
#
if not set -q fish_greeting
set -l line1 (printf (_ 'Welcome to fish, the friendly interactive shell') )
set -l line2 (printf (_ 'Type %shelp%s for instructions on how to use fish') (set_color green) (set_color normal))
set -U fish_greeting $line1\n$line2
end
if status --is-interactive
echo $fish_greeting
end
#
# Don't need completions in non-interactive mode
#
if not status --is-interactive
exit
end
#
# Convenience functions
#
# The naming heuristic is that __fish_complete_* prints completions
# and descriptions, while __fish_print_* only prints the completions
# and no descriptions
#
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
function __fish_complete_groups -d "Print a list of local groups, with group members as the description"
cat /etc/group | sed -e "s/^\([^:]*\):[^:]*:[^:]*:\(.*\)/\1\tMembers: \2/"
end
function __fish_complete_command -d "Complete using all available commands"
printf "%s\n" (commandline -ct)(complete -C (commandline -ct))
end
function __fish_print_interfaces -d "Print a list of known network interfaces"
netstat -i -n -a | awk 'NR>2'|awk '{print $1}'
end
function __fish_print_addresses -d "Print a list of known network addresses"
/sbin/ifconfig |grep 'inet addr'|cut -d : -f 2|cut -d ' ' -f 1
end
function __fish_print_users -d "Print a list of local users"
cat /etc/passwd | cut -d : -f 1
end
#
# Completions for the shell and it's builtin commands and functions
#
for i in (builtin -n|grep -E -v '(while|for|if|function|switch)' )
complete -c $i -s h -l help -d "Display help and exit"
end
#
# Completions for SysV startup scripts
#
complete -x -p "/etc/init.d/*" -a start\t(_ 'Start service')
complete -x -p "/etc/init.d/*" -a stop\t(_ 'Stop service')
complete -x -p "/etc/init.d/*" -a status\t(_ 'Print service status')
complete -x -p "/etc/init.d/*" -a restart\t(_ 'Stop and then start service')
complete -x -p "/etc/init.d/*" -a reload\t(_ 'Reload service configuration')

4
util.h
View file

@ -307,7 +307,9 @@ int hash_str_cmp( void *a,
void *b ); void *b );
/** /**
Hash function suitable for wide character strings. Hash function suitable for wide character strings. Uses a version
of the sha cryptographic function which is simplified in order to
returns a 32-bit number.
*/ */
int hash_wcs_func( void *data ); int hash_wcs_func( void *data );