mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-05-12 03:41:14 -03:00
Compare commits
102 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6d0b6e5de5 | ||
|
|
fd6bf06f15 | ||
|
|
d2e11ea61d | ||
|
|
dad2b93d1e | ||
|
|
1075ca69b0 | ||
|
|
e29f5c5474 | ||
|
|
22bfa6638a | ||
|
|
1a48941f6b | ||
|
|
68e0c94dbb | ||
|
|
ca04fc745d | ||
|
|
3afead1827 | ||
|
|
0ea69dab7b | ||
|
|
a4a025b786 | ||
|
|
328c3a39a1 | ||
|
|
5aa019a0b5 | ||
|
|
92aa99104a | ||
|
|
6b544bc3c2 | ||
|
|
ea0005e16d | ||
|
|
6901ad361d | ||
|
|
b21cccf5f0 | ||
|
|
7740035d14 | ||
|
|
7dc3934997 | ||
|
|
845e15876c | ||
|
|
c4e7a7992f | ||
|
|
43ab84397b | ||
|
|
0840c9248f | ||
|
|
dd79d75504 | ||
|
|
7073f0b58b | ||
|
|
15916bfbdc | ||
|
|
228fdbef5a | ||
|
|
7f7f8fb156 | ||
|
|
2ae9735858 | ||
|
|
8ac1688c89 | ||
|
|
9cd2dbc9e7 | ||
|
|
a74055bc33 | ||
|
|
e1d0b9370e | ||
|
|
5dfa28059e | ||
|
|
7ead45d899 | ||
|
|
5c9ac72c19 | ||
|
|
343cafef34 | ||
|
|
95a01f3c8f | ||
|
|
cfa367f14c | ||
|
|
94cae410f3 | ||
|
|
cc69afc4fe | ||
|
|
777a559e12 | ||
|
|
0427ccbb55 | ||
|
|
f9a4699147 | ||
|
|
e6e287ae1f | ||
|
|
143602e5f6 | ||
|
|
1c2d3583e7 | ||
|
|
e58110da2c | ||
|
|
0d1683edc8 | ||
|
|
c94b9e504d | ||
|
|
8be3bf3e5d | ||
|
|
3e165297ce | ||
|
|
7ac922def6 | ||
|
|
f12127c775 | ||
|
|
73d84fe136 | ||
|
|
c595448f9c | ||
|
|
5a2aeb1511 | ||
|
|
5fb9d9aa38 | ||
|
|
8258961c29 | ||
|
|
0dab94a54c | ||
|
|
3097f71abd | ||
|
|
ea5e1b70db | ||
|
|
6b393d35a9 | ||
|
|
a5dde6021c | ||
|
|
a015472739 | ||
|
|
6affa4452b | ||
|
|
7ebfa380dd | ||
|
|
370336e7c7 | ||
|
|
bad4269dc9 | ||
|
|
effe6f47a3 | ||
|
|
7eb3a5a17d | ||
|
|
b6cd723eb7 | ||
|
|
a2cd8c8a8d | ||
|
|
3b03bd6a10 | ||
|
|
6caff2d85d | ||
|
|
eeaa241be8 | ||
|
|
8fdb4d2a17 | ||
|
|
7c7f744b4c | ||
|
|
5718ea41df | ||
|
|
20c83ba605 | ||
|
|
e9e32f980b | ||
|
|
4b2cc49aaa | ||
|
|
28f65c07b0 | ||
|
|
18279c3867 | ||
|
|
d1c9bca2e9 | ||
|
|
49973b85da | ||
|
|
47373c4f68 | ||
|
|
cbf1dbaa2e | ||
|
|
fdaa79416a | ||
|
|
7c3700c190 | ||
|
|
a0e1f9113e | ||
|
|
133b682793 | ||
|
|
824f4ee566 | ||
|
|
1cb9b65744 | ||
|
|
35dde5de15 | ||
|
|
4d9bb19467 | ||
|
|
2555353161 | ||
|
|
73a9c8bcb8 | ||
|
|
47b652c76e |
256
Makefile.in
256
Makefile.in
@@ -48,25 +48,25 @@ datadir = @datadir@
|
||||
bindir = @bindir@
|
||||
mandir = @mandir@
|
||||
sysconfdir = @sysconfdir@
|
||||
fishdir = @fishdir@
|
||||
fishfile = @fishfile@
|
||||
fishinputfile = @fishinputfile@
|
||||
docdir = @docdir@
|
||||
|
||||
#Init files to install
|
||||
INIT_DIR_INSTALL = init/fish_interactive.fish init/fish_function.fish init/fish_complete.fish
|
||||
#etc files to install
|
||||
ETC_DIR_INSTALL = etc/fish_interactive.fish
|
||||
|
||||
# Set to 1 if we have gettext
|
||||
HAVE_GETTEXT=@HAVE_GETTEXT@
|
||||
|
||||
CORE_OBJS := util.o common.o halloc.o halloc_util.o
|
||||
|
||||
# All objects used by fish, that are compiled from an ordinary .c file
|
||||
# using an ordinary .h file.
|
||||
COMMON_OBJS := function.o builtin.o common.o complete.o env.o exec.o \
|
||||
COMMON_OBJS := function.o builtin.o complete.o env.o exec.o \
|
||||
expand.o highlight.o history.o kill.o parser.o proc.o reader.o \
|
||||
sanity.o tokenizer.o util.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 \
|
||||
input_common.o event.o signal.o io.o translate.o parse_util.o \
|
||||
halloc.o
|
||||
$(CORE_OBJS)
|
||||
|
||||
# builtin_help.h exists, but builtin_help.c is autogenerated
|
||||
COMMON_OBJS_WITH_HEADER := builtin_help.o
|
||||
@@ -80,21 +80,21 @@ FISH_OBJS := $(COMMON_OBJS) $(COMMON_OBJS_WITH_CODE) \
|
||||
$(COMMON_OBJS_WITH_HEADER) main.o
|
||||
|
||||
# All objects that the system needs to build fish_pager
|
||||
FISH_PAGER_OBJS := fish_pager.o common.o output.o util.o wutil.o \
|
||||
FISH_PAGER_OBJS := fish_pager.o output.o wutil.o \
|
||||
tokenizer.o input_common.o env_universal.o env_universal_common.o \
|
||||
translate.o halloc.o
|
||||
translate.o $(CORE_OBJS)
|
||||
|
||||
# All objects that the system needs to build fish_tests
|
||||
FISH_TESTS_OBJS := $(COMMON_OBJS) $(COMMON_OBJS_WITH_CODE) \
|
||||
$(COMMON_OBJS_WITH_HEADER) fish_tests.o
|
||||
|
||||
# All objects that the system needs to build fishd
|
||||
FISHD_OBJS := fishd.o env_universal_common.o common.o util.o wutil.o \
|
||||
doc_src/fishd.o halloc.o
|
||||
FISHD_OBJS := fishd.o env_universal_common.o wutil.o \
|
||||
doc_src/fishd.o $(CORE_OBJS)
|
||||
|
||||
# All objects needed to build mimedb
|
||||
MIME_OBJS := mimedb.o xdgmimealias.o xdgmime.o xdgmimeglob.o \
|
||||
xdgmimeint.o xdgmimemagic.o xdgmimeparent.o wutil.o halloc.o
|
||||
MIME_OBJS := mimedb.o xdgmimealias.o xdgmime.o xdgmimeglob.o \
|
||||
xdgmimeint.o xdgmimemagic.o xdgmimeparent.o wutil.o
|
||||
|
||||
#
|
||||
# Files containing documentation for builtins. Should be listed
|
||||
@@ -160,16 +160,20 @@ MAIN_DIR_FILES := Doxyfile Doxyfile.user Makefile.in configure \
|
||||
user_doc.head.html xsel-0.9.6.tar ChangeLog config.sub \
|
||||
config.guess fish_tests.c main.c fish_pager.c fishd.c seq.in
|
||||
|
||||
# Files in ./init/
|
||||
INIT_DIR_FILES :=init/fish.in init/fish_complete.fish.in \
|
||||
init/fish_function.fish init/fish_inputrc \
|
||||
init/fish_interactive.fish.in
|
||||
# Files in ./etc/
|
||||
ETC_DIR_FILES :=etc/fish.in etc/fish_inputrc \
|
||||
etc/fish_interactive.fish.in
|
||||
|
||||
# Files in ./share/
|
||||
SHARE_DIR_FILES :=share/fish
|
||||
|
||||
# Files in ./tests/
|
||||
TESTS_DIR_FILES := $(TEST_IN) $(TEST_IN:.in=.out) $(TEST_IN:.in=.err) \
|
||||
$(TEST_IN:.in=.status) tests/test.fish tests/gen_output.fish
|
||||
|
||||
COMPLETIONS_DIR_FILES := $(wildcard init/completions/*.fish)
|
||||
COMPLETIONS_DIR_FILES := $(wildcard share/completions/*.fish)
|
||||
|
||||
FUNCTIONS_DIR_FILES := $(wildcard share/functions/*.fish)
|
||||
|
||||
# Programs to build
|
||||
PROGRAMS:=fish set_color @XSEL@ @SEQ_FALLBACK@ mimedb count fish_pager fishd
|
||||
@@ -262,10 +266,10 @@ 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 etc/*.in share/fish share/completions/*.fish share/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 \
|
||||
if ! xgettext -j -k_ -LShell etc/*.in share/fish share/completions/*.fish share/functions/*.fish seq -o messages.pot; then \
|
||||
echo "Your xgettext version is too old to build the messages.pot file"\
|
||||
rm messages.pot\
|
||||
false;\
|
||||
@@ -336,24 +340,54 @@ builtin_help.c: $(BUILTIN_DOC_HDR) doc_src/count.doxygen gen_hdr2 gen_hdr.sh bui
|
||||
#man -- doc_src/builtin_doc/man/man1/`basename $@ .c`.1 | cat -s | ./gen_hdr2 >>$@
|
||||
|
||||
#
|
||||
# The build rules for installing/uninstalling
|
||||
# The build rules for installing/uninstalling fish
|
||||
#
|
||||
|
||||
install: all install-translations
|
||||
# Check for an incompatible installed fish version, and fail with an
|
||||
# error if found
|
||||
|
||||
check-uninstall:
|
||||
if test -f $(DESTDIR)$(sysconfdir)/fish.d/fish_function.fish -o -f $(DESTDIR)$(sysconfdir)/fish.d/fish_complete.fish; then \
|
||||
echo;\
|
||||
echo ERROR;\
|
||||
echo;\
|
||||
echo An older fish installation using an incompatible filesystem hierarchy was detected;\
|
||||
echo You must uninstall this fish version before installing proceeding;\
|
||||
echo type \'make uninstall-legacy\' to uninstall these files,;\
|
||||
echo or type \'make force-install\' to force installation.;\
|
||||
echo The latter may result in a broken installation.;\
|
||||
echo;\
|
||||
false;\
|
||||
fi;
|
||||
.PHONY: check-uninstall
|
||||
|
||||
# Try to install after checking for incompatible installed versions
|
||||
install: all check-uninstall install-force
|
||||
.PHONY: install
|
||||
|
||||
# Force installation, even in presense of incompatible previous
|
||||
# version
|
||||
install-force: all install-translations
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(bindir)
|
||||
for i in $(PROGRAMS); do\
|
||||
$(INSTALL) -m 755 $$i $(DESTDIR)$(bindir) ; \
|
||||
done;
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(sysconfdir)$(fishdir)
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(sysconfdir)$(fishdir)/completions
|
||||
$(INSTALL) -m 644 init/fish $(DESTDIR)$(sysconfdir)$(fishfile)
|
||||
for i in $(INIT_DIR_INSTALL); do \
|
||||
$(INSTALL) -m 644 $$i $(DESTDIR)$(sysconfdir)$(fishdir); \
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(sysconfdir)/fish.d
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/completions
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/functions
|
||||
$(INSTALL) -m 644 etc/fish $(DESTDIR)$(sysconfdir)/fish
|
||||
$(INSTALL) -m 644 share/fish $(DESTDIR)$(datadir)/fish
|
||||
for i in $(ETC_DIR_INSTALL); do \
|
||||
$(INSTALL) -m 644 $$i $(DESTDIR)$(sysconfdir)/fish.d; \
|
||||
done;
|
||||
for i in $(COMPLETIONS_DIR_FILES); do \
|
||||
$(INSTALL) -m 644 $$i $(DESTDIR)$(sysconfdir)$(fishdir)/completions/; \
|
||||
$(INSTALL) -m 644 $$i $(DESTDIR)$(datadir)/fish/completions/; \
|
||||
done;
|
||||
$(INSTALL) -m 644 init/fish_inputrc $(DESTDIR)$(sysconfdir)$(fishinputfile);
|
||||
for i in $(FUNCTIONS_DIR_FILES); do \
|
||||
$(INSTALL) -m 644 $$i $(DESTDIR)$(datadir)/fish/functions/; \
|
||||
done;
|
||||
$(INSTALL) -m 644 etc/fish_inputrc $(DESTDIR)$(sysconfdir)/fish_inputrc;
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(docdir)
|
||||
for i in user_doc/html/* ChangeLog; do \
|
||||
if test -f $$i; then \
|
||||
@@ -372,22 +406,48 @@ install: all install-translations
|
||||
@echo \* use the command \'chsh -s $(DESTDIR)$(bindir)/fish\'.
|
||||
@echo
|
||||
@echo Have fun!
|
||||
.PHONY: install
|
||||
.PHONY: force-install
|
||||
|
||||
|
||||
# Uninstall this fish version
|
||||
|
||||
uninstall: uninstall-translations
|
||||
for i in $(PROGRAMS); do \
|
||||
rm -f $(DESTDIR)$(bindir)/$$i; \
|
||||
done;
|
||||
rm -f $(DESTDIR)$(bindir)/xsel
|
||||
rm -f $(DESTDIR)$(sysconfdir)$(fishfile)
|
||||
rm -f $(DESTDIR)$(sysconfdir)$(fishinputfile)
|
||||
rm -r $(DESTDIR)$(sysconfdir)$(fishdir)
|
||||
rm -r $(DESTDIR)$(docdir)
|
||||
for i in fish.1* @XSEL_MAN@ mimedb.1* fishd.1* set_color.1* count.1*; do \
|
||||
rm $(DESTDIR)$(mandir)/man1/$$i; \
|
||||
rm -f $(DESTDIR)$(sysconfdir)/fish
|
||||
rm -f $(DESTDIR)$(sysconfdir)/fish_inputrc
|
||||
if test -d $(DESTDIR)$(datadir)/fish; then \
|
||||
rm -r $(DESTDIR)$(datadir)/fish; \
|
||||
fi
|
||||
if test -d $(DESTDIR)$(docdir); then \
|
||||
rm -r $(DESTDIR)$(docdir);\
|
||||
fi
|
||||
for i in fish.1 @XSEL_MAN@ mimedb.1 fishd.1 set_color.1 count.1; do \
|
||||
rm -f $(DESTDIR)$(mandir)/man1/$$i*; \
|
||||
done;
|
||||
.PHONY: uninstall
|
||||
|
||||
# Uninstall older fish release. This is not the default uninstall
|
||||
# since there is a slight chance that it removes a file put in place by
|
||||
# the sysadmin.
|
||||
|
||||
uninstall-legacy: uninstall
|
||||
rm -f $(DESTDIR)$(sysconfdir)/fish.d/fish_interactive.fish
|
||||
rm -f $(DESTDIR)$(sysconfdir)/fish.d/fish_complete.fish
|
||||
rm -f $(DESTDIR)$(sysconfdir)/fish.d/fish_function.fish
|
||||
if test -d $(DESTDIR)$(sysconfdir)/fish.d/completions; then \
|
||||
for i in $(COMPLETIONS_DIR_FILES); do \
|
||||
basename=`basename $$i`; \
|
||||
if test -f $(DESTDIR)$(sysconfdir)/fish.d/completions/$$basename; then \
|
||||
rm $(DESTDIR)$(sysconfdir)/fish.d/completions/$$basename; \
|
||||
fi; \
|
||||
done; \
|
||||
fi;
|
||||
rmdir $(DESTDIR)$(sysconfdir)/fish.d/completions; true
|
||||
rmdir $(DESTDIR)$(sysconfdir)/fish.d; true
|
||||
|
||||
install-translations: $(TRANSLATIONS)
|
||||
if test $(HAVE_GETTEXT) = 1; then \
|
||||
for i in $(TRANSLATIONS); do \
|
||||
@@ -395,13 +455,13 @@ install-translations: $(TRANSLATIONS)
|
||||
$(INSTALL) -m 644 $$i $(DESTDIR)$(datadir)/locale/`basename $$i .gmo`/LC_MESSAGES/fish.mo; \
|
||||
echo $(DESTDIR)$(datadir)/locale/`basename $$i .gmo`/LC_MESSAGES/fish.mo;\
|
||||
done; \
|
||||
fi
|
||||
fi;
|
||||
.PHONY: install-translations
|
||||
|
||||
uninstall-translations:
|
||||
if test $(HAVE_GETTEXT) = 1; then \
|
||||
for i in $(TRANSLATIONS_SRC); do \
|
||||
rm -f $(DESTDIR)$(datadir)/locale/`basename $$i .po`/LC_MESSAGES/fish.mo; \
|
||||
rm -f $(DESTDIR)$(datadir)/locale/*/LC_MESSAGES/fish.mo; \
|
||||
done; \
|
||||
fi
|
||||
.PHONY: uninstall-translations
|
||||
@@ -450,18 +510,22 @@ 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) $(ETC_DIR_FILES) $(TEST_DIR_FILES) $(SHARE_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@/etc
|
||||
$(INSTALL) -d fish-@PACKAGE_VERSION@/share
|
||||
$(INSTALL) -d fish-@PACKAGE_VERSION@/share/completions
|
||||
$(INSTALL) -d fish-@PACKAGE_VERSION@/share/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 $(ETC_DIR_FILES) fish-@PACKAGE_VERSION@/etc/
|
||||
cp -f $(SHARE_DIR_FILES) fish-@PACKAGE_VERSION@/share/
|
||||
cp -f $(COMPLETIONS_DIR_FILES) fish-@PACKAGE_VERSION@/share/completions/
|
||||
cp -f $(FUNCTIONS_DIR_FILES) fish-@PACKAGE_VERSION@/share/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
|
||||
@@ -489,7 +553,7 @@ rpm: fish-@PACKAGE_VERSION@.tar.bz2
|
||||
|
||||
distclean: clean
|
||||
rm -f fish.spec doc_src/fish.1 doc_src/Doxyfile
|
||||
rm -f init/fish init/fish_interactive.fish init/fish_complete.fish
|
||||
rm -f etc/fish etc/fish_interactive.fish share/fish
|
||||
rm -f config.status config.log config.h Makefile
|
||||
.PHONY: distclean
|
||||
|
||||
@@ -512,83 +576,101 @@ clean:
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
builtin.o: config.h util.h wutil.h builtin.h function.h complete.h proc.h
|
||||
builtin.o: io.h parser.h reader.h env.h expand.h common.h wgetopt.h sanity.h
|
||||
builtin.o: io.h parser.h event.h reader.h env.h common.h wgetopt.h sanity.h
|
||||
builtin.o: tokenizer.h builtin_help.h wildcard.h input_common.h input.h
|
||||
builtin.o: intern.h event.h signal.h translate.h
|
||||
builtin_commandline.o: signal.h config.h util.h builtin.h common.h wgetopt.h
|
||||
builtin_commandline.o: reader.h proc.h io.h parser.h tokenizer.h
|
||||
builtin_commandline.o: input_common.h input.h translate.h
|
||||
builtin.o: intern.h signal.h translate.h halloc.h halloc_util.h parse_util.h
|
||||
builtin.o: expand.h
|
||||
builtin_commandline.o: signal.h config.h util.h wutil.h builtin.h common.h
|
||||
builtin_commandline.o: wgetopt.h reader.h proc.h io.h parser.h event.h
|
||||
builtin_commandline.o: tokenizer.h input_common.h input.h translate.h
|
||||
builtin_commandline.o: parse_util.h
|
||||
builtin_complete.o: signal.h config.h util.h wutil.h builtin.h common.h
|
||||
builtin_complete.o: complete.h wgetopt.h parser.h proc.h io.h event.h
|
||||
builtin_complete.o: reader.h translate.h
|
||||
builtin_help.o: config.h util.h common.h builtin_help.h
|
||||
builtin_set.o: signal.h config.h util.h builtin.h env.h expand.h common.h
|
||||
builtin_set.o: wgetopt.h proc.h io.h parser.h translate.h
|
||||
builtin_set.o: signal.h config.h util.h wutil.h builtin.h env.h expand.h
|
||||
builtin_set.o: common.h wgetopt.h proc.h io.h parser.h event.h translate.h
|
||||
builtin_ulimit.o: config.h util.h builtin.h common.h wgetopt.h translate.h
|
||||
common.o: config.h signal.h util.h wutil.h common.h expand.h proc.h io.h
|
||||
common.o: wildcard.h parser.h
|
||||
common.o: config.h util.h wutil.h common.h expand.h proc.h io.h wildcard.h
|
||||
common.o: parser.h event.h
|
||||
complete.o: signal.h config.h util.h tokenizer.h wildcard.h proc.h io.h
|
||||
complete.o: parser.h function.h complete.h builtin.h env.h exec.h expand.h
|
||||
complete.o: common.h reader.h history.h intern.h translate.h wutil.h
|
||||
complete.o: parser.h event.h function.h complete.h builtin.h env.h exec.h
|
||||
complete.o: expand.h common.h reader.h history.h intern.h translate.h
|
||||
complete.o: parse_util.h halloc_util.h wutil.h
|
||||
env.o: config.h signal.h util.h wutil.h proc.h io.h common.h env.h sanity.h
|
||||
env.o: expand.h history.h reader.h parser.h env_universal.h
|
||||
env.o: env_universal_common.h input_common.h event.h translate.h
|
||||
env.o: expand.h history.h reader.h parser.h event.h env_universal.h
|
||||
env.o: env_universal_common.h input_common.h translate.h complete.h
|
||||
env_universal.o: config.h signal.h util.h common.h wutil.h
|
||||
env_universal.o: env_universal_common.h env_universal.h
|
||||
env_universal_common.o: signal.h util.h common.h wutil.h
|
||||
env_universal_common.o: config.h signal.h util.h common.h wutil.h
|
||||
env_universal_common.o: env_universal_common.h
|
||||
event.o: signal.h config.h util.h function.h proc.h io.h parser.h common.h
|
||||
event.o: event.h translate.h
|
||||
event.o: signal.h config.h util.h wutil.h function.h proc.h io.h parser.h
|
||||
event.o: event.h common.h translate.h halloc_util.h
|
||||
exec.o: signal.h config.h util.h common.h wutil.h proc.h io.h exec.h parser.h
|
||||
exec.o: builtin.h function.h env.h wildcard.h sanity.h expand.h
|
||||
exec.o: env_universal.h env_universal_common.h translate.h
|
||||
exec.o: event.h builtin.h function.h env.h wildcard.h sanity.h expand.h
|
||||
exec.o: env_universal.h env_universal_common.h translate.h halloc.h
|
||||
exec.o: halloc_util.h parse_util.h
|
||||
expand.o: signal.h config.h util.h common.h wutil.h env.h proc.h io.h
|
||||
expand.o: parser.h expand.h wildcard.h exec.h tokenizer.h complete.h
|
||||
fishd.o: signal.h util.h common.h wutil.h env_universal_common.h
|
||||
expand.o: parser.h event.h expand.h wildcard.h exec.h tokenizer.h complete.h
|
||||
expand.o: translate.h parse_util.h halloc_util.h
|
||||
fishd.o: config.h signal.h util.h common.h wutil.h env_universal_common.h
|
||||
fish_pager.o: config.h signal.h util.h wutil.h common.h complete.h output.h
|
||||
fish_pager.o: input_common.h env_universal.h env_universal_common.h
|
||||
fish_pager.o: input_common.h env_universal.h env_universal_common.h halloc.h
|
||||
fish_pager.o: halloc_util.h
|
||||
fish_tests.o: config.h signal.h util.h common.h proc.h io.h reader.h
|
||||
fish_tests.o: builtin.h function.h complete.h wutil.h env.h expand.h parser.h
|
||||
fish_tests.o: tokenizer.h output.h exec.h event.h
|
||||
function.o: signal.h config.h util.h function.h proc.h io.h parser.h common.h
|
||||
function.o: intern.h event.h
|
||||
fish_tests.o: event.h tokenizer.h output.h exec.h halloc_util.h
|
||||
function.o: signal.h config.h wutil.h util.h function.h proc.h io.h parser.h
|
||||
function.o: event.h common.h intern.h reader.h parse_util.h env.h expand.h
|
||||
halloc.o: config.h util.h common.h halloc.h
|
||||
halloc_util.o: config.h util.h common.h halloc.h
|
||||
highlight.o: signal.h config.h util.h wutil.h highlight.h tokenizer.h proc.h
|
||||
highlight.o: io.h parser.h builtin.h function.h env.h expand.h sanity.h
|
||||
highlight.o: common.h complete.h output.h
|
||||
highlight.o: io.h parser.h event.h parse_util.h builtin.h function.h env.h
|
||||
highlight.o: expand.h sanity.h common.h complete.h output.h
|
||||
history.o: config.h util.h wutil.h history.h common.h reader.h env.h sanity.h
|
||||
history.o: signal.h
|
||||
input.o: config.h signal.h util.h wutil.h reader.h proc.h io.h common.h
|
||||
input.o: sanity.h input_common.h input.h parser.h env.h expand.h event.h
|
||||
input.o: translate.h
|
||||
input.o: sanity.h input_common.h input.h parser.h event.h env.h expand.h
|
||||
input.o: translate.h output.h
|
||||
input_common.o: config.h util.h common.h wutil.h input_common.h
|
||||
input_common.o: env_universal.h env_universal_common.h
|
||||
intern.o: config.h util.h common.h intern.h
|
||||
intern.o: config.h util.h wutil.h common.h intern.h
|
||||
io.o: config.h util.h wutil.h exec.h proc.h io.h common.h translate.h
|
||||
io.o: halloc.h
|
||||
key_reader.o: input_common.h
|
||||
kill.o: signal.h config.h util.h wutil.h kill.h proc.h io.h sanity.h common.h
|
||||
kill.o: env.h expand.h exec.h parser.h
|
||||
kill.o: env.h exec.h parser.h event.h
|
||||
main.o: config.h signal.h util.h common.h reader.h builtin.h function.h
|
||||
main.o: complete.h wutil.h env.h sanity.h proc.h io.h parser.h expand.h
|
||||
main.o: intern.h exec.h event.h output.h translate.h
|
||||
main.o: complete.h wutil.h env.h sanity.h proc.h io.h parser.h event.h
|
||||
main.o: expand.h intern.h exec.h output.h translate.h halloc_util.h
|
||||
mimedb.o: config.h xdgmime.h util.h
|
||||
output.o: config.h signal.h util.h wutil.h expand.h common.h output.h
|
||||
output.o: highlight.h
|
||||
output.o: halloc_util.h highlight.h
|
||||
parser.o: signal.h config.h util.h common.h wutil.h proc.h io.h parser.h
|
||||
parser.o: tokenizer.h exec.h wildcard.h function.h builtin.h builtin_help.h
|
||||
parser.o: env.h expand.h reader.h sanity.h env_universal.h
|
||||
parser.o: env_universal_common.h event.h translate.h
|
||||
parser.o: event.h tokenizer.h exec.h wildcard.h function.h builtin.h
|
||||
parser.o: builtin_help.h env.h expand.h reader.h sanity.h env_universal.h
|
||||
parser.o: env_universal_common.h translate.h intern.h parse_util.h halloc.h
|
||||
parser.o: halloc_util.h
|
||||
parse_util.o: config.h util.h wutil.h common.h tokenizer.h parse_util.h
|
||||
parse_util.o: expand.h intern.h exec.h proc.h io.h env.h halloc_util.h
|
||||
proc.o: config.h signal.h util.h wutil.h proc.h io.h common.h reader.h
|
||||
proc.o: sanity.h env.h parser.h event.h translate.h
|
||||
proc.o: sanity.h env.h parser.h event.h translate.h halloc.h halloc_util.h
|
||||
proc.o: output.h
|
||||
reader.o: config.h signal.h util.h wutil.h highlight.h reader.h proc.h io.h
|
||||
reader.o: parser.h complete.h history.h common.h sanity.h env.h exec.h
|
||||
reader.o: expand.h tokenizer.h kill.h input_common.h input.h function.h
|
||||
reader.o: output.h translate.h
|
||||
reader.o: parser.h event.h complete.h history.h common.h sanity.h env.h
|
||||
reader.o: exec.h expand.h tokenizer.h kill.h input_common.h input.h
|
||||
reader.o: function.h output.h translate.h parse_util.h
|
||||
refcount.o: config.h util.h wutil.h common.h refcount.h
|
||||
sanity.o: signal.h config.h util.h common.h sanity.h proc.h io.h history.h
|
||||
sanity.o: reader.h kill.h wutil.h
|
||||
sanity.o: reader.h kill.h wutil.h translate.h
|
||||
set_color.o: config.h
|
||||
signal.o: config.h signal.h common.h util.h wutil.h event.h reader.h proc.h
|
||||
signal.o: io.h translate.h
|
||||
tokenizer.o: config.h util.h wutil.h tokenizer.h common.h wildcard.h
|
||||
tokenizer.o: translate.h
|
||||
translate.o: config.h common.h util.h
|
||||
translate.o: config.h common.h util.h halloc_util.h
|
||||
util.o: config.h util.h common.h wutil.h
|
||||
wgetopt.o: config.h wgetopt.h wutil.h
|
||||
wgetopt.o: config.h wgetopt.h wutil.h translate.h
|
||||
wildcard.o: config.h util.h wutil.h complete.h common.h wildcard.h reader.h
|
||||
wildcard.o: expand.h translate.h
|
||||
wutil.o: config.h util.h common.h wutil.h
|
||||
|
||||
92
builtin.c
92
builtin.c
@@ -60,6 +60,9 @@
|
||||
#include "signal.h"
|
||||
#include "translate.h"
|
||||
#include "halloc.h"
|
||||
#include "halloc_util.h"
|
||||
#include "parse_util.h"
|
||||
#include "expand.h"
|
||||
|
||||
/**
|
||||
The default prompt for the read command
|
||||
@@ -496,7 +499,7 @@ static int builtin_builtin( wchar_t **argv )
|
||||
|
||||
al_init( &names );
|
||||
builtin_get_names( &names );
|
||||
names_arr = list_to_char_arr( 0, &names );
|
||||
names_arr = list_to_char_arr( &names );
|
||||
qsort( names_arr,
|
||||
al_get_count( &names ),
|
||||
sizeof(wchar_t *),
|
||||
@@ -511,7 +514,7 @@ static int builtin_builtin( wchar_t **argv )
|
||||
L"\n",
|
||||
(void *)0 );
|
||||
}
|
||||
halloc_free( names_arr );
|
||||
free( names_arr );
|
||||
al_destroy( &names );
|
||||
}
|
||||
return 0;
|
||||
@@ -813,7 +816,7 @@ static int builtin_functions( wchar_t **argv )
|
||||
|
||||
al_init( &names );
|
||||
function_get_names( &names, show_hidden );
|
||||
names_arr = list_to_char_arr( 0, &names );
|
||||
names_arr = list_to_char_arr( &names );
|
||||
qsort( names_arr,
|
||||
al_get_count( &names ),
|
||||
sizeof(wchar_t *),
|
||||
@@ -845,7 +848,7 @@ static int builtin_functions( wchar_t **argv )
|
||||
}
|
||||
}
|
||||
|
||||
halloc_free( names_arr );
|
||||
free( names_arr );
|
||||
al_destroy( &names );
|
||||
return 0;
|
||||
}
|
||||
@@ -858,7 +861,7 @@ static int builtin_functions( wchar_t **argv )
|
||||
sb_append( sb_out, _( L"Current function definitions are:\n\n" ) );
|
||||
al_init( &names );
|
||||
function_get_names( &names, show_hidden );
|
||||
names_arr = list_to_char_arr( 0, &names );
|
||||
names_arr = list_to_char_arr( &names );
|
||||
qsort( names_arr,
|
||||
al_get_count( &names ),
|
||||
sizeof(wchar_t *),
|
||||
@@ -867,7 +870,7 @@ static int builtin_functions( wchar_t **argv )
|
||||
{
|
||||
functions_def( names_arr[i] );
|
||||
}
|
||||
halloc_free( names_arr );
|
||||
free( names_arr );
|
||||
al_destroy( &names );
|
||||
break;
|
||||
}
|
||||
@@ -924,8 +927,7 @@ static int builtin_function( wchar_t **argv )
|
||||
woptind=0;
|
||||
|
||||
parser_push_block( FUNCTION_DEF );
|
||||
events=halloc( current_block, sizeof(array_list_t ) );
|
||||
al_init( events );
|
||||
events=al_halloc( current_block );
|
||||
|
||||
const static struct woption
|
||||
long_options[] =
|
||||
@@ -1037,7 +1039,7 @@ static int builtin_function( wchar_t **argv )
|
||||
if( !e )
|
||||
die_mem();
|
||||
e->type = EVENT_VARIABLE;
|
||||
e->param1.variable = halloc_register( current_block, wcsdup( woptarg ));
|
||||
e->param1.variable = halloc_wcsdup( current_block, woptarg );
|
||||
e->function_name=0;
|
||||
al_push( events, e );
|
||||
break;
|
||||
@@ -1160,8 +1162,6 @@ static int builtin_function( wchar_t **argv )
|
||||
}
|
||||
}
|
||||
|
||||
halloc_register( current_block, events->arr );
|
||||
|
||||
if( res )
|
||||
{
|
||||
int i;
|
||||
@@ -1176,7 +1176,7 @@ static int builtin_function( wchar_t **argv )
|
||||
|
||||
al_init( &names );
|
||||
function_get_names( &names, 0 );
|
||||
names_arr = list_to_char_arr( 0, &names );
|
||||
names_arr = list_to_char_arr( &names );
|
||||
qsort( names_arr,
|
||||
al_get_count( &names ),
|
||||
sizeof(wchar_t *),
|
||||
@@ -1194,7 +1194,7 @@ static int builtin_function( wchar_t **argv )
|
||||
sb_append2( sb_err,
|
||||
nxt, L" ", (void *)0 );
|
||||
}
|
||||
halloc_free( names_arr );
|
||||
free( names_arr );
|
||||
al_destroy( &names );
|
||||
sb_append( sb_err, L"\n" );
|
||||
|
||||
@@ -1203,11 +1203,11 @@ static int builtin_function( wchar_t **argv )
|
||||
}
|
||||
else
|
||||
{
|
||||
current_block->param1.function_name=halloc_register( current_block, wcsdup(argv[woptind]));
|
||||
current_block->param2.function_description=desc?halloc_register( current_block, wcsdup(desc)):0;
|
||||
current_block->param1.function_name=halloc_wcsdup( current_block, argv[woptind]);
|
||||
current_block->param2.function_description=desc?halloc_wcsdup( current_block, desc):0;
|
||||
current_block->param3.function_is_binding = is_binding;
|
||||
current_block->param4.function_events = events;
|
||||
|
||||
|
||||
for( i=0; i<al_get_count( events ); i++ )
|
||||
{
|
||||
event_t *e = (event_t *)al_get( events, i );
|
||||
@@ -1613,6 +1613,8 @@ static int builtin_status( wchar_t **argv )
|
||||
IS_NO_JOB_CONTROL,
|
||||
STACK_TRACE,
|
||||
DONE,
|
||||
CURRENT_FILENAME,
|
||||
CURRENT_LINE_NUMBER
|
||||
}
|
||||
;
|
||||
|
||||
@@ -1658,6 +1660,14 @@ static int builtin_status( wchar_t **argv )
|
||||
L"is-no-job-control", no_argument, &mode, IS_NO_JOB_CONTROL
|
||||
}
|
||||
,
|
||||
{
|
||||
L"current-filename", no_argument, &mode, CURRENT_FILENAME
|
||||
}
|
||||
,
|
||||
{
|
||||
L"current-line-number", no_argument, &mode, CURRENT_LINE_NUMBER
|
||||
}
|
||||
,
|
||||
{
|
||||
L"job-control", required_argument, 0, 'j'
|
||||
}
|
||||
@@ -1732,6 +1742,24 @@ static int builtin_status( wchar_t **argv )
|
||||
|
||||
switch( mode )
|
||||
{
|
||||
case CURRENT_FILENAME:
|
||||
{
|
||||
const wchar_t *fn = parser_current_filename();
|
||||
|
||||
if( !fn )
|
||||
fn = _(L"Standard input");
|
||||
|
||||
sb_printf( sb_out, L"%ls\n", fn );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CURRENT_LINE_NUMBER:
|
||||
{
|
||||
sb_printf( sb_out, L"%d\n", parser_get_lineno() );
|
||||
break;
|
||||
}
|
||||
|
||||
case IS_INTERACTIVE:
|
||||
return !is_interactive_session;
|
||||
|
||||
@@ -1766,9 +1794,9 @@ static int builtin_status( wchar_t **argv )
|
||||
else
|
||||
sb_printf( sb_out, _( L"This is not a login shell\n" ) );
|
||||
|
||||
sb_printf( sb_out, _(L"Job control: %ls\n"),
|
||||
job_control_mode==JOB_CONTROL_INTERACTIVE?_(L"Only on interactive jobs"):
|
||||
(job_control_mode==JOB_CONTROL_NONE?_(L"Never"):_(L"Always")) );
|
||||
sb_printf( sb_out, _( L"Job control: %ls\n" ),
|
||||
job_control_mode==JOB_CONTROL_INTERACTIVE?_( L"Only on interactive jobs" ):
|
||||
(job_control_mode==JOB_CONTROL_NONE ? _( L"Never" ) : _( L"Always" ) ) );
|
||||
|
||||
parser_stack_trace( current_block, sb_out );
|
||||
break;
|
||||
@@ -1943,9 +1971,9 @@ static int builtin_source( wchar_t ** argv )
|
||||
|
||||
argc = builtin_count_args( argv );
|
||||
|
||||
if( argc != 2 )
|
||||
if( argc < 2 )
|
||||
{
|
||||
sb_printf( sb_err, _( L"%ls: Expected exactly one argument, got %d\n" ), argv[0], argc );
|
||||
sb_printf( sb_err, _( L"%ls: Expected at least one argument, got %d\n" ), argv[0], argc );
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
return 1;
|
||||
}
|
||||
@@ -1972,7 +2000,7 @@ static int builtin_source( wchar_t ** argv )
|
||||
{
|
||||
wchar_t *fn = wrealpath( argv[1], 0 );
|
||||
const wchar_t *fn_intern;
|
||||
|
||||
|
||||
if( !fn )
|
||||
{
|
||||
fn_intern = intern( argv[1] );
|
||||
@@ -1985,10 +2013,13 @@ static int builtin_source( wchar_t ** argv )
|
||||
|
||||
parser_push_block( SOURCE );
|
||||
reader_push_current_filename( fn_intern );
|
||||
|
||||
|
||||
|
||||
current_block->param1.source_dest = fn_intern;
|
||||
|
||||
parse_util_set_argv( argv+2);
|
||||
res = reader_read( fd );
|
||||
|
||||
parser_pop_block();
|
||||
if( res )
|
||||
{
|
||||
@@ -2010,7 +2041,6 @@ static int builtin_source( wchar_t ** argv )
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Make the specified job the first job of the job list. Moving jobs
|
||||
around in the list makes the list reflect the order in which the
|
||||
@@ -2545,7 +2575,8 @@ static int builtin_for( wchar_t **argv )
|
||||
if( argc < 3)
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
_( L"%ls: Expected at least two arguments\n" ),
|
||||
_( L"%ls: Expected at least two arguments, got %d\n"),
|
||||
argc ,
|
||||
argv[0] );
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
}
|
||||
@@ -2581,11 +2612,11 @@ static int builtin_for( wchar_t **argv )
|
||||
|
||||
int i;
|
||||
current_block->tok_pos = parser_get_pos();
|
||||
current_block->param1.for_variable = halloc_register( current_block, wcsdup( argv[1] ));
|
||||
current_block->param1.for_variable = halloc_wcsdup( current_block, argv[1] );
|
||||
|
||||
for( i=argc-1; i>3; i-- )
|
||||
{
|
||||
al_push( ¤t_block->param2.for_vars, halloc_register( current_block, wcsdup(argv[ i ] ) ) );
|
||||
al_push( ¤t_block->param2.for_vars, halloc_wcsdup( current_block, argv[ i ] ) );
|
||||
}
|
||||
halloc_register( current_block, current_block->param2.for_vars.arr );
|
||||
|
||||
@@ -2901,7 +2932,7 @@ static int builtin_switch( wchar_t **argv )
|
||||
else
|
||||
{
|
||||
parser_push_block( SWITCH );
|
||||
current_block->param1.switch_value = halloc_register( current_block, wcsdup( argv[1]));
|
||||
current_block->param1.switch_value = halloc_wcsdup( current_block, argv[1]);
|
||||
current_block->skip=1;
|
||||
current_block->param2.switch_taken=0;
|
||||
}
|
||||
@@ -2937,8 +2968,10 @@ static int builtin_case( wchar_t **argv )
|
||||
for( i=1; i<argc; i++ )
|
||||
{
|
||||
free( unescaped );
|
||||
unescaped = unescape( argv[i], 1);
|
||||
|
||||
unescaped = parse_util_unescape_wildcards( argv[i] );
|
||||
|
||||
|
||||
if( wildcard_match( current_block->param1.switch_value, unescaped ) )
|
||||
{
|
||||
current_block->skip = 0;
|
||||
@@ -3145,6 +3178,7 @@ void builtin_destroy()
|
||||
{
|
||||
hash_destroy( desc );
|
||||
free( desc );
|
||||
desc=0;
|
||||
}
|
||||
|
||||
al_destroy( &io_stack );
|
||||
|
||||
@@ -27,7 +27,7 @@ const static wchar_t *temporary_buffer;
|
||||
/*
|
||||
builtin_complete_* are a set of rather silly looping functions that
|
||||
make sure that all the proper combinations of complete_add or
|
||||
complete_remove get called.
|
||||
complete_remove get called.
|
||||
*/
|
||||
|
||||
static void builtin_complete_add2( const wchar_t *cmd,
|
||||
@@ -253,7 +253,7 @@ int builtin_complete( wchar_t **argv )
|
||||
|
||||
string_buffer_t short_opt;
|
||||
array_list_t gnu_opt, old_opt;
|
||||
wchar_t *comp=L"", *desc=L"", *condition=L"", *load=0;
|
||||
wchar_t *comp=L"", *desc=L"", *condition=L"";
|
||||
|
||||
wchar_t *do_complete = 0;
|
||||
|
||||
@@ -307,7 +307,8 @@ int builtin_complete( wchar_t **argv )
|
||||
}
|
||||
,
|
||||
{
|
||||
L"long-option", required_argument, 0, 'l' }
|
||||
L"long-option", required_argument, 0, 'l'
|
||||
}
|
||||
,
|
||||
{
|
||||
L"old-option", required_argument, 0, 'o'
|
||||
@@ -333,10 +334,6 @@ int builtin_complete( wchar_t **argv )
|
||||
L"condition", required_argument, 0, 'n'
|
||||
}
|
||||
,
|
||||
{
|
||||
L"load", required_argument, 0, 'y'
|
||||
}
|
||||
,
|
||||
{
|
||||
L"do-complete", required_argument, 0, 'C'
|
||||
}
|
||||
@@ -351,7 +348,7 @@ int builtin_complete( wchar_t **argv )
|
||||
|
||||
int opt = wgetopt_long( argc,
|
||||
argv,
|
||||
L"a:c:p:s:l:o:d:frxeun:y:C:",
|
||||
L"a:c:p:s:l:o:d:frxeun:C:",
|
||||
long_options,
|
||||
&opt_index );
|
||||
if( opt == -1 )
|
||||
@@ -368,6 +365,7 @@ int builtin_complete( wchar_t **argv )
|
||||
long_options[opt_index].name );
|
||||
sb_append( sb_err,
|
||||
parser_current_line() );
|
||||
|
||||
// builtin_print_help( argv[0], sb_err );
|
||||
|
||||
|
||||
@@ -418,25 +416,21 @@ int builtin_complete( wchar_t **argv )
|
||||
comp = woptarg;
|
||||
break;
|
||||
|
||||
|
||||
case 'e':
|
||||
remove = 1;
|
||||
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
condition = woptarg;
|
||||
break;
|
||||
|
||||
case 'y':
|
||||
load = woptarg;
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
do_complete = woptarg?woptarg:reader_get_buffer();
|
||||
break;
|
||||
|
||||
case '?':
|
||||
sb_append( sb_err,
|
||||
parser_current_line() );
|
||||
// builtin_print_help( argv[0], sb_err );
|
||||
|
||||
res = 1;
|
||||
@@ -446,90 +440,85 @@ int builtin_complete( wchar_t **argv )
|
||||
|
||||
}
|
||||
|
||||
if( res != 0 )
|
||||
if( !res )
|
||||
{
|
||||
}
|
||||
else if( do_complete )
|
||||
{
|
||||
array_list_t comp;
|
||||
int i;
|
||||
|
||||
const wchar_t *prev_temporary_buffer = temporary_buffer;
|
||||
temporary_buffer = do_complete;
|
||||
|
||||
if( recursion_level < 1 )
|
||||
if( do_complete )
|
||||
{
|
||||
recursion_level++;
|
||||
array_list_t comp;
|
||||
int i;
|
||||
|
||||
const wchar_t *prev_temporary_buffer = temporary_buffer;
|
||||
temporary_buffer = do_complete;
|
||||
|
||||
if( recursion_level < 1 )
|
||||
{
|
||||
recursion_level++;
|
||||
|
||||
al_init( &comp );
|
||||
|
||||
complete( do_complete, &comp );
|
||||
|
||||
for( i=0; i<al_get_count( &comp ); i++ )
|
||||
{
|
||||
wchar_t *next = (wchar_t *)al_get( &comp, i );
|
||||
wchar_t *sep = wcschr( next, COMPLETE_SEP );
|
||||
if( sep )
|
||||
*sep = L'\t';
|
||||
sb_printf( sb_out, L"%ls\n", next );
|
||||
}
|
||||
|
||||
al_foreach( &comp, (void (*)(const void *))&free );
|
||||
al_destroy( &comp );
|
||||
recursion_level--;
|
||||
}
|
||||
|
||||
temporary_buffer = prev_temporary_buffer;
|
||||
|
||||
al_init( &comp );
|
||||
|
||||
complete( do_complete, &comp );
|
||||
|
||||
for( i=0; i<al_get_count( &comp ); i++ )
|
||||
{
|
||||
wchar_t *next = (wchar_t *)al_get( &comp, i );
|
||||
wchar_t *sep = wcschr( next, COMPLETE_SEP );
|
||||
if( sep )
|
||||
*sep = L'\t';
|
||||
sb_printf( sb_out, L"%ls\n", next );
|
||||
}
|
||||
|
||||
al_foreach( &comp, (void (*)(const void *))&free );
|
||||
al_destroy( &comp );
|
||||
recursion_level--;
|
||||
}
|
||||
|
||||
temporary_buffer = prev_temporary_buffer;
|
||||
|
||||
}
|
||||
else if( woptind != argc )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
_( L"%ls: Too many arguments\n" ),
|
||||
argv[0] );
|
||||
sb_append( sb_err,
|
||||
parser_current_line() );
|
||||
// builtin_print_help( argv[0], sb_err );
|
||||
|
||||
res = 1;
|
||||
}
|
||||
else if( load )
|
||||
{
|
||||
complete_load( load, 1 );
|
||||
}
|
||||
else if( (al_get_count( &cmd) == 0 ) && (al_get_count( &path) == 0 ) )
|
||||
{
|
||||
/* No arguments specified, meaning we print the definitions of
|
||||
* all specified completions to stdout.*/
|
||||
complete_print( sb_out );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( remove )
|
||||
else if( woptind != argc )
|
||||
{
|
||||
builtin_complete_remove( &cmd,
|
||||
&path,
|
||||
(wchar_t *)short_opt.buff,
|
||||
&gnu_opt,
|
||||
&old_opt );
|
||||
sb_printf( sb_err,
|
||||
_( L"%ls: Too many arguments\n" ),
|
||||
argv[0] );
|
||||
sb_append( sb_err,
|
||||
parser_current_line() );
|
||||
// builtin_print_help( argv[0], sb_err );
|
||||
|
||||
res = 1;
|
||||
}
|
||||
else if( (al_get_count( &cmd) == 0 ) && (al_get_count( &path) == 0 ) )
|
||||
{
|
||||
/* No arguments specified, meaning we print the definitions of
|
||||
* all specified completions to stdout.*/
|
||||
complete_print( sb_out );
|
||||
}
|
||||
else
|
||||
{
|
||||
builtin_complete_add( &cmd,
|
||||
&path,
|
||||
(wchar_t *)short_opt.buff,
|
||||
&gnu_opt,
|
||||
&old_opt,
|
||||
result_mode,
|
||||
authorative,
|
||||
condition,
|
||||
comp,
|
||||
desc );
|
||||
}
|
||||
|
||||
}
|
||||
if( remove )
|
||||
{
|
||||
builtin_complete_remove( &cmd,
|
||||
&path,
|
||||
(wchar_t *)short_opt.buff,
|
||||
&gnu_opt,
|
||||
&old_opt );
|
||||
}
|
||||
else
|
||||
{
|
||||
builtin_complete_add( &cmd,
|
||||
&path,
|
||||
(wchar_t *)short_opt.buff,
|
||||
&gnu_opt,
|
||||
&old_opt,
|
||||
result_mode,
|
||||
authorative,
|
||||
condition,
|
||||
comp,
|
||||
desc );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
al_foreach( &cmd, (void (*)(const void *))&free );
|
||||
al_foreach( &path, (void (*)(const void *))&free );
|
||||
|
||||
|
||||
211
common.c
211
common.c
@@ -20,7 +20,6 @@ parts of fish.
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <signal.h>
|
||||
#include <locale.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
@@ -58,7 +57,6 @@ parts of fish.
|
||||
#include "proc.h"
|
||||
#include "wildcard.h"
|
||||
#include "parser.h"
|
||||
#include "halloc.h"
|
||||
|
||||
/**
|
||||
The maximum number of minor errors to report. Further errors will be omitted.
|
||||
@@ -73,13 +71,6 @@ parts of fish.
|
||||
|
||||
struct termios shell_modes;
|
||||
|
||||
/**
|
||||
Number of error encountered. This is reset after each command, and
|
||||
used to limit the number of error messages on commands with many
|
||||
string convertion problems.
|
||||
*/
|
||||
static int error_count=0;
|
||||
|
||||
int error_max=1;
|
||||
|
||||
wchar_t ellipsis_char;
|
||||
@@ -95,20 +86,14 @@ int debug_level=1;
|
||||
*/
|
||||
static struct winsize termsize;
|
||||
|
||||
|
||||
/**
|
||||
Number of nested calls to the block function. Unblock when this reaches 0.
|
||||
*/
|
||||
static int block_count=0;
|
||||
|
||||
/**
|
||||
String buffer used by the wsetlocale function
|
||||
*/
|
||||
static string_buffer_t *setlocale_buff=0;
|
||||
|
||||
|
||||
void common_destroy()
|
||||
{
|
||||
|
||||
if( setlocale_buff )
|
||||
{
|
||||
sb_destroy( setlocale_buff );
|
||||
@@ -116,9 +101,13 @@ void common_destroy()
|
||||
}
|
||||
}
|
||||
|
||||
wchar_t **list_to_char_arr( void *context, array_list_t *l )
|
||||
void common_init()
|
||||
{
|
||||
wchar_t ** res = halloc( context, sizeof(wchar_t *)*(al_get_count( l )+1) );
|
||||
}
|
||||
|
||||
wchar_t **list_to_char_arr( array_list_t *l )
|
||||
{
|
||||
wchar_t ** res = malloc( sizeof(wchar_t *)*(al_get_count( l )+1) );
|
||||
int i;
|
||||
if( res == 0 )
|
||||
{
|
||||
@@ -127,40 +116,11 @@ wchar_t **list_to_char_arr( void *context, array_list_t *l )
|
||||
for( i=0; i<al_get_count( l ); i++ )
|
||||
{
|
||||
res[i] = (wchar_t *)al_get(l,i);
|
||||
if( context )
|
||||
halloc_register( context, res[i] );
|
||||
}
|
||||
res[i]='\0';
|
||||
return res;
|
||||
}
|
||||
|
||||
void block()
|
||||
{
|
||||
block_count++;
|
||||
if( block_count == 1 )
|
||||
{
|
||||
sigset_t chldset;
|
||||
sigemptyset( &chldset );
|
||||
sigaddset( &chldset, SIGCHLD );
|
||||
sigprocmask(SIG_BLOCK, &chldset, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void unblock()
|
||||
{
|
||||
block_count--;
|
||||
if( block_count == 0 )
|
||||
{
|
||||
sigset_t chldset;
|
||||
sigemptyset( &chldset );
|
||||
sigaddset( &chldset, SIGCHLD );
|
||||
sigprocmask(SIG_UNBLOCK, &chldset, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int fgetws2( wchar_t **b, int *len, FILE *f )
|
||||
{
|
||||
int i=0;
|
||||
@@ -174,8 +134,6 @@ int fgetws2( wchar_t **b, int *len, FILE *f )
|
||||
watching for EINTR errors, bytes are lost.
|
||||
*/
|
||||
|
||||
block();
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
/* Reallocate the buffer if necessary */
|
||||
@@ -214,8 +172,6 @@ int fgetws2( wchar_t **b, int *len, FILE *f )
|
||||
case L'\n':
|
||||
case L'\0':
|
||||
buff[i]=L'\0';
|
||||
unblock();
|
||||
|
||||
return i;
|
||||
/* Ignore carriage returns */
|
||||
case L'\r':
|
||||
@@ -228,7 +184,6 @@ int fgetws2( wchar_t **b, int *len, FILE *f )
|
||||
|
||||
|
||||
}
|
||||
unblock();
|
||||
|
||||
}
|
||||
|
||||
@@ -254,20 +209,28 @@ void sort_list( array_list_t *comp )
|
||||
wchar_t *str2wcs( const char *in )
|
||||
{
|
||||
wchar_t *out;
|
||||
size_t res=0;
|
||||
int in_pos=0;
|
||||
int out_pos = 0;
|
||||
size_t len = strlen(in);
|
||||
mbstate_t state;
|
||||
|
||||
out = malloc( sizeof(wchar_t)*(len+1) );
|
||||
memset( &state, 0, sizeof(state) );
|
||||
|
||||
|
||||
if( !out )
|
||||
{
|
||||
die_mem();
|
||||
}
|
||||
|
||||
return str2wcs_internal( in, out );
|
||||
}
|
||||
|
||||
wchar_t *str2wcs_internal( const char *in, wchar_t *out )
|
||||
{
|
||||
size_t res=0;
|
||||
int in_pos=0;
|
||||
int out_pos = 0;
|
||||
mbstate_t state;
|
||||
size_t len = strlen(in);
|
||||
|
||||
memset( &state, 0, sizeof(state) );
|
||||
|
||||
while( in[in_pos] )
|
||||
{
|
||||
res = mbrtowc( &out[out_pos], &in[in_pos], len-in_pos, &state );
|
||||
@@ -287,6 +250,7 @@ wchar_t *str2wcs( const char *in )
|
||||
{
|
||||
return out;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
in_pos += res;
|
||||
@@ -300,27 +264,28 @@ wchar_t *str2wcs( const char *in )
|
||||
return out;
|
||||
}
|
||||
|
||||
void error_reset()
|
||||
{
|
||||
error_count=0;
|
||||
}
|
||||
|
||||
char *wcs2str( const wchar_t *in )
|
||||
{
|
||||
char *out;
|
||||
size_t res=0;
|
||||
int in_pos=0;
|
||||
int out_pos = 0;
|
||||
mbstate_t state;
|
||||
|
||||
out = malloc( MAX_UTF8_BYTES*wcslen(in)+1 );
|
||||
memset( &state, 0, sizeof(state) );
|
||||
|
||||
if( !out )
|
||||
{
|
||||
die_mem();
|
||||
}
|
||||
|
||||
return wcs2str_internal( in, out );
|
||||
}
|
||||
|
||||
char *wcs2str_internal( const wchar_t *in, char *out )
|
||||
{
|
||||
size_t res=0;
|
||||
int in_pos=0;
|
||||
int out_pos = 0;
|
||||
mbstate_t state;
|
||||
memset( &state, 0, sizeof(state) );
|
||||
|
||||
while( in[in_pos] )
|
||||
{
|
||||
if( ( in[in_pos] >= ENCODE_DIRECT_BASE) &&
|
||||
@@ -550,8 +515,6 @@ int wcsvarname( wchar_t *str )
|
||||
str++;
|
||||
}
|
||||
return 1;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -574,12 +537,34 @@ int my_wcswidth( const wchar_t *c )
|
||||
return res;
|
||||
}
|
||||
|
||||
wchar_t *quote_end( const wchar_t *in )
|
||||
const wchar_t *quote_end( const wchar_t *pos )
|
||||
{
|
||||
return wcschr( in+1, *in );
|
||||
wchar_t c = *pos;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
pos++;
|
||||
|
||||
if( !*pos )
|
||||
return 0;
|
||||
|
||||
if( *pos == L'\\')
|
||||
{
|
||||
pos++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( *pos == c )
|
||||
{
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
const wchar_t *wsetlocale(int category, const wchar_t *locale)
|
||||
{
|
||||
|
||||
@@ -642,12 +627,6 @@ int read_blocked(int fd, void *buf, size_t count)
|
||||
return res;
|
||||
}
|
||||
|
||||
int writeb( tputs_arg_t b )
|
||||
{
|
||||
write( 1, &b, 1 );
|
||||
// putc( b, stdout );
|
||||
return 0;
|
||||
}
|
||||
|
||||
void die_mem()
|
||||
{
|
||||
@@ -938,74 +917,87 @@ wchar_t *unescape( const wchar_t * orig, int unescape_special )
|
||||
break;
|
||||
}
|
||||
|
||||
case L'X':
|
||||
case L'u':
|
||||
case L'U':
|
||||
case L'x':
|
||||
case L'o':
|
||||
case L'X':
|
||||
case L'0':
|
||||
case L'1':
|
||||
case L'2':
|
||||
case L'3':
|
||||
case L'4':
|
||||
case L'5':
|
||||
case L'6':
|
||||
case L'7':
|
||||
{
|
||||
int i;
|
||||
wchar_t res=0;
|
||||
long long res=0;
|
||||
int chars=2;
|
||||
int base=16;
|
||||
|
||||
int byte = 0;
|
||||
int max_val = 127;
|
||||
|
||||
switch( in[in_pos] )
|
||||
{
|
||||
case L'u':
|
||||
{
|
||||
base=16;
|
||||
chars=4;
|
||||
max_val = 35535;
|
||||
break;
|
||||
}
|
||||
|
||||
case L'U':
|
||||
{
|
||||
base=16;
|
||||
chars=8;
|
||||
max_val = WCHAR_MAX;
|
||||
break;
|
||||
}
|
||||
|
||||
case L'x':
|
||||
{
|
||||
base=16;
|
||||
chars=2;
|
||||
break;
|
||||
}
|
||||
|
||||
case L'X':
|
||||
{
|
||||
byte=1;
|
||||
base=16;
|
||||
chars=2;
|
||||
max_val = 255;
|
||||
break;
|
||||
}
|
||||
|
||||
case L'o':
|
||||
default:
|
||||
{
|
||||
base=8;
|
||||
chars=3;
|
||||
in_pos--;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
for( i=0; i<chars; i++ )
|
||||
{
|
||||
int d = convert_digit( in[++in_pos],base);
|
||||
|
||||
if( d < 0 )
|
||||
{
|
||||
in_pos--;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
res=(res*base)|d;
|
||||
|
||||
}
|
||||
|
||||
in[out_pos] = (byte?ENCODE_DIRECT_BASE:0)+res;
|
||||
|
||||
|
||||
if( (res > 0) && (res <= max_val) )
|
||||
{
|
||||
in[out_pos] = (byte?ENCODE_DIRECT_BASE:0)+res;
|
||||
}
|
||||
else
|
||||
{
|
||||
free(in);
|
||||
return 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1160,6 +1152,30 @@ wchar_t *unescape( const wchar_t * orig, int unescape_special )
|
||||
*/
|
||||
case 1:
|
||||
{
|
||||
if( c == L'\\' )
|
||||
{
|
||||
switch( in[++in_pos] )
|
||||
{
|
||||
case L'\'':
|
||||
{
|
||||
in[out_pos]=in[in_pos];
|
||||
break;
|
||||
}
|
||||
|
||||
case 0:
|
||||
{
|
||||
free(in);
|
||||
return 0;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
in[out_pos++] = L'\\';
|
||||
in[out_pos]= in[in_pos];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if( c == L'\'' )
|
||||
{
|
||||
in[out_pos] = INTERNAL_SEPARATOR;
|
||||
@@ -1198,11 +1214,12 @@ wchar_t *unescape( const wchar_t * orig, int unescape_special )
|
||||
}
|
||||
|
||||
case L'$':
|
||||
case '"':
|
||||
{
|
||||
in[out_pos]=in[in_pos];
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
{
|
||||
in[out_pos++] = L'\\';
|
||||
|
||||
36
common.h
36
common.h
@@ -47,7 +47,7 @@ typedef char tputs_arg_t;
|
||||
/**
|
||||
This is in the unicode private use area.
|
||||
*/
|
||||
#define ENCODE_DIRECT_BASE 0xf000
|
||||
#define ENCODE_DIRECT_BASE 0xf100
|
||||
|
||||
/**
|
||||
Save the shell mode on startup so we can restore them on exit
|
||||
@@ -88,7 +88,7 @@ extern wchar_t *program_name;
|
||||
is not noll, all elements of the \c array_list_t are also
|
||||
registered to \c context using \c halloc_register().
|
||||
*/
|
||||
wchar_t **list_to_char_arr( void *context, array_list_t *l );
|
||||
wchar_t **list_to_char_arr( array_list_t *l );
|
||||
|
||||
/**
|
||||
Read a line from the stream f into the buffer buff of length len. If
|
||||
@@ -114,6 +114,7 @@ void sort_list( array_list_t *comp );
|
||||
specified multibyte character string
|
||||
*/
|
||||
wchar_t *str2wcs( const char *in );
|
||||
wchar_t *str2wcs_internal( const char *in, wchar_t *out );
|
||||
|
||||
/**
|
||||
Returns a newly allocated multibyte character string equivalent of
|
||||
@@ -121,6 +122,8 @@ wchar_t *str2wcs( const char *in );
|
||||
*/
|
||||
char *wcs2str( const wchar_t *in );
|
||||
|
||||
char *wcs2str_internal( const wchar_t *in, char *out );
|
||||
|
||||
/**
|
||||
Returns a newly allocated wide character string array equivalent of
|
||||
the specified multibyte character string array
|
||||
@@ -187,7 +190,7 @@ int my_wcswidth( const wchar_t *c );
|
||||
|
||||
\param in the position of the opening quote
|
||||
*/
|
||||
wchar_t *quote_end( const wchar_t *in );
|
||||
const wchar_t *quote_end( const wchar_t *in );
|
||||
|
||||
/**
|
||||
A call to this function will reset the error counter. Some
|
||||
@@ -220,20 +223,18 @@ int contains_str( const wchar_t *needle, ... );
|
||||
*/
|
||||
int read_blocked(int fd, void *buf, size_t count);
|
||||
|
||||
/**
|
||||
This is for writing process notification messages. Has to write to
|
||||
stdout, so clr_eol and such functions will work correctly. Not an
|
||||
issue since this function is only used in interactive mode anyway.
|
||||
*/
|
||||
int writeb( tputs_arg_t b );
|
||||
|
||||
/**
|
||||
Exit program at once, leaving an error message about running out of memory
|
||||
*/
|
||||
void die_mem();
|
||||
|
||||
/**
|
||||
Clean up
|
||||
Create global_context using halloc
|
||||
*/
|
||||
void common_init();
|
||||
|
||||
/**
|
||||
Free global_context using halloc_free
|
||||
*/
|
||||
void common_destroy();
|
||||
|
||||
@@ -262,8 +263,7 @@ void debug( int level, const wchar_t *msg, ... );
|
||||
\return The escaped string, or 0 if there is not enough memory
|
||||
*/
|
||||
|
||||
wchar_t *escape( const wchar_t *in,
|
||||
int escape_all );
|
||||
wchar_t *escape( const wchar_t *in, int escape_all );
|
||||
|
||||
/**
|
||||
Expand backslashed escapes and substitute them with their unescaped
|
||||
@@ -279,16 +279,6 @@ wchar_t *escape( const wchar_t *in,
|
||||
wchar_t *unescape( const wchar_t * in,
|
||||
int escape_special );
|
||||
|
||||
/**
|
||||
Block SIGCHLD. Calls to block/unblock may be nested, and only once the nest count reaches zero wiull the block be removed.
|
||||
*/
|
||||
void block();
|
||||
|
||||
/**
|
||||
undo call to block().
|
||||
*/
|
||||
void unblock();
|
||||
|
||||
/**
|
||||
Attempt to acquire a lock based on a lockfile, waiting LOCKPOLLINTERVAL
|
||||
milliseconds between polls and timing out after timeout seconds,
|
||||
|
||||
512
complete.c
512
complete.c
File diff suppressed because it is too large
Load Diff
@@ -33,6 +33,8 @@
|
||||
/** Separateor between completion and description*/
|
||||
#define COMPLETE_SEP_STR L"\004"
|
||||
|
||||
#define COMPLETE_ITEM_SEP L'\uf500'
|
||||
|
||||
/**
|
||||
Character that separates the completion and description on programmable completions
|
||||
*/
|
||||
@@ -162,6 +164,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
|
||||
|
||||
12
configure.ac
12
configure.ac
@@ -1,5 +1,5 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
AC_INIT(fish,1.20.2,fish-users@lists.sf.net)
|
||||
AC_INIT(fish,1.21.0,fish-users@lists.sf.net)
|
||||
|
||||
for i in /usr/pkg /sw /opt /opt/local; do
|
||||
|
||||
@@ -104,10 +104,6 @@ else
|
||||
AC_SUBST( PREFIX, [$prefix])
|
||||
fi
|
||||
|
||||
AC_SUBST(fishdir,[/fish.d])
|
||||
AC_SUBST(fishfile,[/fish])
|
||||
AC_SUBST(fishinputfile,[/fish_inputrc])
|
||||
|
||||
AC_ARG_VAR( [docdir], [Documentation direcotry] )
|
||||
|
||||
if test -z $docdir; then
|
||||
@@ -116,7 +112,9 @@ fi
|
||||
|
||||
AC_DEFINE_UNQUOTED( DOCDIR, [L"$(eval echo $docdir)"], [Documentation directory] )
|
||||
AC_DEFINE_UNQUOTED( SYSCONFDIR, [L"$(eval echo $sysconfdir)"], [System configuration directory] )
|
||||
AC_DEFINE_UNQUOTED( DATADIR, [L"$(eval echo $datadir)"], [System configuration directory] )
|
||||
AC_SUBST( SYSCONFDIR, ["$(eval echo $sysconfdir)"] )
|
||||
AC_SUBST( DATADIR, ["$(eval echo $datadir)"] )
|
||||
|
||||
# Set up locale directory
|
||||
AC_DEFINE_UNQUOTED( [LOCALEDIR], "$(eval echo $datadir)/locale", [Locale directory])
|
||||
@@ -199,7 +197,7 @@ AC_CHECK_LIB(rt, nanosleep)
|
||||
AC_CHECK_LIB(intl, gettext)
|
||||
|
||||
# Check for various header files
|
||||
AC_CHECK_HEADERS([getopt.h termio.h sys/resource.h term.h ncurses/term.h libintl.h])
|
||||
AC_CHECK_HEADERS([getopt.h termio.h sys/resource.h term.h ncurses/term.h libintl.h ncurses.h curses.h])
|
||||
|
||||
AC_CHECK_HEADER([regex.h],
|
||||
[AC_DEFINE([HAVE_REGEX_H], [1], [Define to 1 if you have the <regex.h> header file.])],
|
||||
@@ -235,7 +233,7 @@ fi
|
||||
# Check if we have ncurses, and use it rather than curses if possible.
|
||||
AC_SEARCH_LIBS( setupterm, [ncurses curses], [ AC_MSG_NOTICE([Found curses implementation])], [AC_MSG_ERROR([Could not find a curses implementation, needed to build fish])] )
|
||||
|
||||
AC_CONFIG_FILES([Makefile fish.spec doc_src/fish.1 doc_src/Doxyfile init/fish init/fish_interactive.fish init/fish_complete.fish seq])
|
||||
AC_CONFIG_FILES([Makefile fish.spec doc_src/fish.1 doc_src/Doxyfile etc/fish etc/fish_interactive.fish seq])
|
||||
AC_OUTPUT
|
||||
|
||||
echo "Now run 'make' and 'make install' to built and install fish."
|
||||
|
||||
@@ -3,10 +3,9 @@
|
||||
\subsection cd-synopsis Synopsis
|
||||
<tt>cd [DIRECTORY]</tt>
|
||||
|
||||
\subsection cd-description Description
|
||||
Changes the current directory. If <tt>DIRECTORY</tt> is supplied it
|
||||
will become the new directory. If \c DIRECTORY is a relative path, the
|
||||
CDPATH environment variable will be separated using the : as
|
||||
separator, and the resulting list will be searched for a suitable new
|
||||
current directory. If CDPATH is not set, it is assumed to be '.'. If
|
||||
\c DIRECTORY is not specified, \$HOME will be the new directory.
|
||||
\subsection cd-description Description Changes the current
|
||||
directory. If <tt>DIRECTORY</tt> is supplied it will become the new
|
||||
directory. If \c DIRECTORY is a relative path, the paths found in the
|
||||
CDPATH environment variable array will be tried as prefixes for the
|
||||
specified path. If CDPATH is not set, it is assumed to be '.'. If \c
|
||||
DIRECTORY is not specified, \$HOME will be the new directory.
|
||||
|
||||
1012
doc_src/doc.hdr
1012
doc_src/doc.hdr
File diff suppressed because it is too large
Load Diff
9
doc_src/fish_pager.txt
Normal file
9
doc_src/fish_pager.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
\section fish_pager fish_pager - Internal command used by fish
|
||||
|
||||
\subsection fish_pager-description Description
|
||||
|
||||
This command is used internally by fish to display a list of
|
||||
completions. It should not be used by other commands, as it's
|
||||
interface is liable to change in the future.
|
||||
|
||||
@@ -214,7 +214,7 @@ void env_universal_init( wchar_t * p,
|
||||
void (*sf)(),
|
||||
void (*cb)( int type, const wchar_t *name, const wchar_t *val ))
|
||||
{
|
||||
debug( 2, L"env_universal_init()" );
|
||||
debug( 3, L"env_universal_init()" );
|
||||
path=p;
|
||||
user=u;
|
||||
start_fishd=sf;
|
||||
@@ -233,7 +233,7 @@ void env_universal_init( wchar_t * p,
|
||||
{
|
||||
env_universal_barrier();
|
||||
}
|
||||
debug( 2, L"end env_universal_init()" );
|
||||
debug( 3, L"end env_universal_init()" );
|
||||
}
|
||||
|
||||
void env_universal_destroy()
|
||||
|
||||
@@ -105,7 +105,7 @@ static int get_names_show_unexported;
|
||||
|
||||
void env_universal_common_init( void (*cb)(int type, const wchar_t *key, const wchar_t *val ) )
|
||||
{
|
||||
debug( 2, L"Init env_universal_common" );
|
||||
debug( 3, L"Init env_universal_common" );
|
||||
callback = cb;
|
||||
hash_init( &env_universal_var, &hash_wcs_func, &hash_wcs_cmp );
|
||||
}
|
||||
@@ -229,7 +229,7 @@ static int match( const wchar_t *msg, const wchar_t *cmd )
|
||||
static void parse_message( wchar_t *msg,
|
||||
connection_t *src )
|
||||
{
|
||||
debug( 2, L"parse_message( %ls );", msg );
|
||||
debug( 3, L"parse_message( %ls );", msg );
|
||||
|
||||
if( msg[0] == L'#' )
|
||||
return;
|
||||
|
||||
@@ -3,6 +3,13 @@
|
||||
#
|
||||
# @configure_input@
|
||||
|
||||
#
|
||||
# Set default search paths
|
||||
#
|
||||
|
||||
set -g fish_function_path ~/.fish.d/functions @SYSCONFDIR@/fish.d/functions @DATADIR@/functions
|
||||
set -g fish_complete_path ~/.fish.d/completions @SYSCONFDIR@/fish.d/completions @DATADIR@/completions
|
||||
|
||||
#
|
||||
# Set default field separators
|
||||
#
|
||||
@@ -31,28 +38,12 @@ for i in $path_list
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Set some value for LANG if nothing was set before, and this is a
|
||||
# login shell. Also check for i18n information in /etc/sysconfig/i18n
|
||||
#
|
||||
|
||||
if status --is-login
|
||||
if not set -q LANG >/dev/null
|
||||
set -gx LANG en_US.UTF-8
|
||||
end
|
||||
|
||||
if test -f /etc/sysconfig/i18n
|
||||
eval (cat /etc/sysconfig/i18n |sed -ne 's/^\([a-zA-Z]*\)=\(.*\)$/set -gx \1 \2;/p')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Put linux console in unicode mode. Should this be done in any other
|
||||
# situation as well?
|
||||
#
|
||||
|
||||
if expr "$LANG" : ".*UTF" >/dev/null
|
||||
if expr "$LANG" : ".*[Uu][Tt][Ff]" >/dev/null
|
||||
if test linux = "$TERM"
|
||||
unicode_start ^/dev/null
|
||||
end
|
||||
@@ -70,23 +61,6 @@ for i in DISPLAY
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Alias for gettext (or a fallback if gettext isn't installed) This
|
||||
# needs to be defined here and not in fish_function.fish, since it is
|
||||
# used by other init files.
|
||||
#
|
||||
|
||||
function _ -d "Alias for the gettext command"
|
||||
printf "%s" $argv
|
||||
end
|
||||
if test 1 = "@HAVE_GETTEXT@"
|
||||
if which gettext ^/dev/null >/dev/null
|
||||
function _ -d "Alias for the gettext command"
|
||||
gettext fish $argv
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Load additional initialization files
|
||||
#
|
||||
@@ -22,26 +22,6 @@ function fish_on_exit -d (_ "Commands to execute when fish exits") --on-process
|
||||
printf (_ "Good bye\n")
|
||||
end
|
||||
|
||||
# Set the default prompt command. Make sure that every terminal escape
|
||||
# string has a newline before and after, so that fish will know how
|
||||
# long it is.
|
||||
|
||||
function fish_prompt -d (_ "Write out the prompt")
|
||||
|
||||
# Just calculate these once, to save a few cycles when displaying the prompt
|
||||
if not set -q __fish_prompt_hostname
|
||||
set -g __fish_prompt_hostname (hostname|cut -d . -f 1)
|
||||
end
|
||||
|
||||
if not set -q __fish_prompt_normal
|
||||
set -g __fish_prompt_normal (set_color normal)
|
||||
end
|
||||
|
||||
set -l prompt_color (set_color $fish_color_cwd)
|
||||
|
||||
printf '%s@%s %s%s%s> \n' $USER $__fish_prompt_hostname "$prompt_color" (prompt_pwd) "$__fish_prompt_normal"
|
||||
end
|
||||
|
||||
#
|
||||
# Set INPUTRC to something nice
|
||||
#
|
||||
@@ -109,63 +89,6 @@ set_default fish_color_history_current cyan
|
||||
|
||||
set_default CDPATH . ~
|
||||
|
||||
#
|
||||
# Match colors for grep, if supported
|
||||
#
|
||||
|
||||
if grep --color=auto --help 1>/dev/null 2>/dev/null
|
||||
set_exported_default GREP_COLOR '97;45'
|
||||
set_exported_default GREP_OPTIONS '--color=auto'
|
||||
end
|
||||
|
||||
#
|
||||
# Color definitions for ls, if supported
|
||||
#
|
||||
|
||||
if command ls --color=auto --help 1>/dev/null 2>/dev/null
|
||||
|
||||
set -l color_document 35
|
||||
set -l color_image '01;35'
|
||||
set -l color_sound '01;35'
|
||||
set -l color_video '01;35'
|
||||
set -l color_archive '01;31'
|
||||
set -l color_command '01;32'
|
||||
set -l color_backup 37
|
||||
|
||||
set -l default no=00 fi=00 'di=01;34' 'ln=01;36' 'pi=40;33' 'so=01;35' 'bd=40;33;01' 'cd=40;33;01' 'or=01;05;37;41' 'mi=01;05;37;41' ex=$color_command
|
||||
|
||||
for i in .cmd .exe .com .btm .bat .sh .csh .fish
|
||||
set default $default "*$i=$color_command"
|
||||
end
|
||||
|
||||
for i in .tar .tgz .arj .taz .lhz .zip .z .Z .gz .bz2 .bz .tz .rpm .cpio .jar .deb .rar .bin .hqx
|
||||
set default $default "*$i=$color_archive"
|
||||
end
|
||||
|
||||
for i in .jpg .jpeg .gif .bmp .xbm .xpm .png .tif
|
||||
set default $default "*$i=$color_image"
|
||||
end
|
||||
|
||||
for i in .mp3 .au .wav .aiff .ogg .wma
|
||||
set default $default "*$i=$color_sound"
|
||||
end
|
||||
|
||||
for i in .avi .mpeg .mpg .divx .mov .qt .wmv .rm
|
||||
set default $default "*$i=$color_video"
|
||||
end
|
||||
|
||||
for i in .htm .html .rtf .wpd .doc .pdf .ps .xls .swf .txt .tex .sxw .dvi INSTALL README ChangeLog
|
||||
set default $default "*$i=$color_document"
|
||||
end
|
||||
|
||||
for i in '~' .bak
|
||||
set default $default "*$i=$color_backup"
|
||||
end
|
||||
|
||||
set -gx LS_COLORS $default
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Remove temporary functions
|
||||
#
|
||||
28
event.c
28
event.c
@@ -21,6 +21,7 @@
|
||||
#include "event.h"
|
||||
#include "signal.h"
|
||||
#include "translate.h"
|
||||
#include "halloc_util.h"
|
||||
|
||||
/**
|
||||
Number of signals that can be queued before an overflow occurs
|
||||
@@ -194,10 +195,7 @@ const wchar_t *event_get_desc( event_t *e )
|
||||
{
|
||||
if( !get_desc_buff )
|
||||
{
|
||||
get_desc_buff=malloc(sizeof(string_buffer_t) );
|
||||
if( !get_desc_buff )
|
||||
die_mem();
|
||||
sb_init( get_desc_buff );
|
||||
get_desc_buff=sb_halloc( global_context );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -255,7 +253,7 @@ void event_add_handler( event_t *event )
|
||||
e = event_copy( event, 0 );
|
||||
|
||||
if( !events )
|
||||
events = al_new();
|
||||
events = al_new();
|
||||
|
||||
if( e->type == EVENT_SIGNAL )
|
||||
{
|
||||
@@ -387,8 +385,6 @@ static void event_fire_internal( event_t *event )
|
||||
int i, j;
|
||||
string_buffer_t *b=0;
|
||||
array_list_t *fire=0;
|
||||
|
||||
int was_interactive = is_interactive;
|
||||
|
||||
/*
|
||||
First we free all events that have been removed
|
||||
@@ -452,7 +448,7 @@ static void event_fire_internal( event_t *event )
|
||||
|
||||
for( j=0; j<al_get_count(&event->arguments); j++ )
|
||||
{
|
||||
wchar_t *arg_esc = escape( (wchar_t *)al_get( &event->arguments, j), 0 );
|
||||
wchar_t *arg_esc = escape( (wchar_t *)al_get( &event->arguments, j), 1 );
|
||||
sb_append( b, L" " );
|
||||
sb_append( b, arg_esc );
|
||||
free( arg_esc );
|
||||
@@ -464,19 +460,14 @@ static void event_fire_internal( event_t *event )
|
||||
Event handlers are not part of the main flow of code, so
|
||||
they are marked as non-interactive and as a subshell
|
||||
*/
|
||||
is_interactive=0;
|
||||
proc_push_interactive(0);
|
||||
parser_push_block( EVENT );
|
||||
current_block->param1.event = event;
|
||||
eval( (wchar_t *)b->buff, 0, TOP );
|
||||
parser_pop_block();
|
||||
|
||||
proc_pop_interactive();
|
||||
}
|
||||
|
||||
/*
|
||||
Restore interactivity flags
|
||||
*/
|
||||
is_interactive = was_interactive;
|
||||
|
||||
if( b )
|
||||
{
|
||||
sb_destroy( b );
|
||||
@@ -644,13 +635,6 @@ void event_destroy()
|
||||
free( killme );
|
||||
killme=0;
|
||||
}
|
||||
|
||||
if( get_desc_buff )
|
||||
{
|
||||
sb_destroy( get_desc_buff );
|
||||
free( get_desc_buff );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void event_free( event_t *e )
|
||||
|
||||
49
exec.c
49
exec.c
@@ -38,6 +38,8 @@
|
||||
#include "env_universal.h"
|
||||
#include "translate.h"
|
||||
#include "halloc.h"
|
||||
#include "halloc_util.h"
|
||||
#include "parse_util.h"
|
||||
|
||||
/**
|
||||
Prototype for the getpgid library function. The prototype for this
|
||||
@@ -260,7 +262,7 @@ static int handle_child_io( io_data_t *io, int exit_on_error )
|
||||
if( io->fd > 2 )
|
||||
{
|
||||
/*
|
||||
Make sure the fd used by this redirection is not used by i.e. a pipe.
|
||||
Make sure the fd used by this redirection is not used by e.g. a pipe.
|
||||
*/
|
||||
free_fd( io, io->fd );
|
||||
}
|
||||
@@ -403,7 +405,7 @@ static int setup_child_process( job_t *j, process_t *p )
|
||||
|
||||
if( !res )
|
||||
{
|
||||
res = handle_child_io( j->io, (p==0) );
|
||||
res = handle_child_io( j->io, (p!=0) );
|
||||
}
|
||||
|
||||
/* Set the handling for job control signals back to the default. */
|
||||
@@ -788,9 +790,6 @@ void exec( job_t *j )
|
||||
{
|
||||
case INTERNAL_FUNCTION:
|
||||
{
|
||||
wchar_t **arg;
|
||||
int i;
|
||||
string_buffer_t sb;
|
||||
|
||||
wchar_t * def = halloc_register( j, wcsdup( function_get_definition( p->argv[0] )));
|
||||
//fwprintf( stderr, L"run function %ls\n", argv[0] );
|
||||
@@ -804,26 +803,9 @@ void exec( job_t *j )
|
||||
|
||||
current_block->param2.function_call_process = p;
|
||||
current_block->param1.function_name = halloc_register( current_block, wcsdup( p->argv[0] ) );
|
||||
|
||||
if( builtin_count_args(p->argv)>1 )
|
||||
{
|
||||
sb_init( &sb );
|
||||
|
||||
for( i=1, arg=p->argv+1; *arg; i++, arg++ )
|
||||
{
|
||||
if( i != 1 )
|
||||
sb_append( &sb, ARRAY_SEP_STR );
|
||||
sb_append( &sb, *arg );
|
||||
}
|
||||
|
||||
env_set( L"argv", (wchar_t *)sb.buff, ENV_LOCAL );
|
||||
sb_destroy( &sb );
|
||||
}
|
||||
else
|
||||
{
|
||||
env_set( L"argv", 0, ENV_LOCAL );
|
||||
}
|
||||
|
||||
|
||||
parse_util_set_argv( p->argv+1 );
|
||||
|
||||
parser_forbid_function( p->argv[0] );
|
||||
|
||||
if( p->next )
|
||||
@@ -1278,10 +1260,16 @@ int exec_subshell( const wchar_t *cmd,
|
||||
{
|
||||
wchar_t *el = str2wcs( begin );
|
||||
if( el )
|
||||
{
|
||||
al_push( l, el );
|
||||
}
|
||||
else
|
||||
{
|
||||
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
|
||||
}
|
||||
}
|
||||
io_buffer_destroy( io_buffer );
|
||||
|
||||
|
||||
return status;
|
||||
|
||||
case '\n':
|
||||
@@ -1289,7 +1277,14 @@ int exec_subshell( const wchar_t *cmd,
|
||||
wchar_t *el;
|
||||
*end=0;
|
||||
el = str2wcs( begin );
|
||||
al_push( l, el );
|
||||
if( el )
|
||||
{
|
||||
al_push( l, el );
|
||||
}
|
||||
else
|
||||
{
|
||||
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
|
||||
}
|
||||
begin = end+1;
|
||||
break;
|
||||
}
|
||||
|
||||
296
expand.c
296
expand.c
@@ -1,7 +1,7 @@
|
||||
/**\file expand.c
|
||||
|
||||
String expansion functions. These functions perform several kinds of
|
||||
parameter expansion.
|
||||
parameter expansion.
|
||||
|
||||
*/
|
||||
|
||||
@@ -36,10 +36,12 @@ parameter expansion.
|
||||
#include "expand.h"
|
||||
#include "wildcard.h"
|
||||
#include "exec.h"
|
||||
#include "signal.h"
|
||||
#include "tokenizer.h"
|
||||
#include "complete.h"
|
||||
#include "translate.h"
|
||||
#include "parse_util.h"
|
||||
#include "halloc_util.h"
|
||||
|
||||
/**
|
||||
Description for child process
|
||||
@@ -388,8 +390,6 @@ static int find_process( const wchar_t *proc,
|
||||
This is a numeric job string, like '%2'
|
||||
*/
|
||||
|
||||
// fwprintf( stderr, L"Numeric\n\n\n" );
|
||||
|
||||
if( flags & ACCEPT_INCOMPLETE )
|
||||
{
|
||||
for( j=first_job; j != 0; j=j->next )
|
||||
@@ -399,7 +399,6 @@ static int find_process( const wchar_t *proc,
|
||||
continue;
|
||||
|
||||
swprintf( jid, 16, L"%d", j->job_id );
|
||||
// fwprintf( stderr, L"Jid %ls\n", jid );
|
||||
|
||||
if( wcsncmp( proc, jid, wcslen(proc ) )==0 )
|
||||
{
|
||||
@@ -557,8 +556,10 @@ static int find_process( const wchar_t *proc,
|
||||
continue;
|
||||
}
|
||||
|
||||
signal_block();
|
||||
fgetws2( &cmd, &sz, cmdfile );
|
||||
|
||||
signal_unblock();
|
||||
|
||||
fclose( cmdfile );
|
||||
}
|
||||
else
|
||||
@@ -710,7 +711,6 @@ static int expand_pid( wchar_t *in,
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Expand all environment variables in the string *ptr.
|
||||
|
||||
@@ -725,7 +725,7 @@ static int expand_pid( wchar_t *in,
|
||||
happens, don't edit it unless you know exactly what you are doing,
|
||||
and do proper testing afterwards.
|
||||
*/
|
||||
static int expand_variables( wchar_t *in, array_list_t *out )
|
||||
static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
|
||||
{
|
||||
wchar_t c;
|
||||
wchar_t prev_char=0;
|
||||
@@ -733,7 +733,32 @@ static int expand_variables( wchar_t *in, array_list_t *out )
|
||||
int is_ok= 1;
|
||||
int empty=0;
|
||||
|
||||
for( i=wcslen(in)-1; (i>=0) && is_ok && !empty; i-- )
|
||||
static string_buffer_t *var_tmp = 0;
|
||||
static array_list_t *var_idx_list = 0;
|
||||
|
||||
if( !var_tmp )
|
||||
{
|
||||
var_tmp = sb_halloc( global_context );
|
||||
if( !var_tmp )
|
||||
die_mem();
|
||||
}
|
||||
else
|
||||
{
|
||||
sb_clear(var_tmp );
|
||||
}
|
||||
|
||||
if( !var_idx_list )
|
||||
{
|
||||
var_idx_list = al_halloc( global_context );
|
||||
if( !var_idx_list )
|
||||
die_mem();
|
||||
}
|
||||
else
|
||||
{
|
||||
al_truncate( var_idx_list, 0 );
|
||||
}
|
||||
|
||||
for( i=last_idx; (i>=0) && is_ok && !empty; i-- )
|
||||
{
|
||||
c = in[i];
|
||||
if( ( c == VARIABLE_EXPAND ) || (c == VARIABLE_EXPAND_SINGLE ) )
|
||||
@@ -741,12 +766,11 @@ static int expand_variables( wchar_t *in, array_list_t *out )
|
||||
int start_pos = i+1;
|
||||
int stop_pos;
|
||||
int var_len, new_len;
|
||||
wchar_t *var_name;
|
||||
wchar_t * var_val;
|
||||
wchar_t * new_in;
|
||||
array_list_t l;
|
||||
int is_single = (c==VARIABLE_EXPAND_SINGLE);
|
||||
|
||||
int var_name_stop_pos;
|
||||
|
||||
stop_pos = start_pos;
|
||||
|
||||
while( 1 )
|
||||
@@ -759,7 +783,8 @@ static int expand_variables( wchar_t *in, array_list_t *out )
|
||||
|
||||
stop_pos++;
|
||||
}
|
||||
|
||||
var_name_stop_pos = stop_pos;
|
||||
|
||||
/* printf( "Stop for '%c'\n", in[stop_pos]);*/
|
||||
|
||||
var_len = stop_pos - start_pos;
|
||||
@@ -808,23 +833,16 @@ static int expand_variables( wchar_t *in, array_list_t *out )
|
||||
break;
|
||||
}
|
||||
|
||||
sb_append_substring( var_tmp, &in[start_pos], var_len );
|
||||
|
||||
if( !(var_name = malloc( sizeof(wchar_t)*(var_len+1) )))
|
||||
{
|
||||
die_mem();
|
||||
}
|
||||
wcsncpy( var_name, &in[start_pos], var_len );
|
||||
var_name[var_len]='\0';
|
||||
/* printf( "Variable name is %s, len is %d\n", var_name, var_len );*/
|
||||
wchar_t *var_val_orig = expand_var( var_name );
|
||||
var_val = expand_var( (wchar_t *)var_tmp->buff );
|
||||
|
||||
if( var_val_orig && (var_val = wcsdup( var_val_orig) ) )
|
||||
if( var_val )
|
||||
{
|
||||
int all_vars=1;
|
||||
array_list_t idx;
|
||||
al_init( &idx );
|
||||
al_init( &l );
|
||||
|
||||
array_list_t var_item_list;
|
||||
al_init( &var_item_list );
|
||||
|
||||
if( in[stop_pos] == L'[' )
|
||||
{
|
||||
wchar_t *end;
|
||||
@@ -857,43 +875,42 @@ static int expand_variables( wchar_t *in, array_list_t *out )
|
||||
is_ok = 0;
|
||||
break;
|
||||
}
|
||||
al_push( &idx, (void *)tmp );
|
||||
al_push( var_idx_list, (void *)tmp );
|
||||
stop_pos = end-in;
|
||||
}
|
||||
}
|
||||
|
||||
if( is_ok )
|
||||
{
|
||||
expand_variable_array( var_val, &l );
|
||||
expand_variable_array( var_val, &var_item_list );
|
||||
if( !all_vars )
|
||||
{
|
||||
int j;
|
||||
for( j=0; j<al_get_count( &idx ); j++)
|
||||
for( j=0; j<al_get_count( var_idx_list ); j++)
|
||||
{
|
||||
int tmp = (int)al_get( &idx, j );
|
||||
if( tmp < 1 || tmp > al_get_count( &l ) )
|
||||
int tmp = (int)al_get( var_idx_list, j );
|
||||
if( tmp < 1 || tmp > al_get_count( &var_item_list ) )
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
-1,
|
||||
L"Array index out of bounds" );
|
||||
is_ok=0;
|
||||
al_truncate( &idx, j );
|
||||
al_truncate( var_idx_list, j );
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Move string from list l to list idx */
|
||||
al_set( &idx, j, al_get( &l, tmp-1 ) );
|
||||
al_set( &l, tmp-1, 0 );
|
||||
al_set( var_idx_list, j, al_get( &var_item_list, tmp-1 ) );
|
||||
al_set( &var_item_list, tmp-1, 0 );
|
||||
}
|
||||
}
|
||||
/* Free remaining strings in list l and truncate it */
|
||||
al_foreach( &l, (void (*)(const void *))&free );
|
||||
al_truncate( &l, 0 );
|
||||
al_foreach( &var_item_list, (void (*)(const void *))&free );
|
||||
al_truncate( &var_item_list, 0 );
|
||||
/* Add items from list idx back to list l */
|
||||
al_push_all( &l, &idx );
|
||||
al_push_all( &var_item_list, var_idx_list );
|
||||
}
|
||||
free( var_val );
|
||||
}
|
||||
|
||||
if( is_ok )
|
||||
@@ -902,16 +919,15 @@ static int expand_variables( wchar_t *in, array_list_t *out )
|
||||
if( is_single )
|
||||
{
|
||||
string_buffer_t res;
|
||||
sb_init( &res );
|
||||
|
||||
in[i]=0;
|
||||
|
||||
|
||||
sb_init( &res );
|
||||
sb_append( &res, in );
|
||||
sb_append_char( &res, INTERNAL_SEPARATOR );
|
||||
|
||||
for( j=0; j<al_get_count( &l); j++ )
|
||||
for( j=0; j<al_get_count( &var_item_list); j++ )
|
||||
{
|
||||
wchar_t *next = (wchar_t *)al_get( &l, j );
|
||||
wchar_t *next = (wchar_t *)al_get( &var_item_list, j );
|
||||
|
||||
if( is_ok )
|
||||
{
|
||||
@@ -922,52 +938,58 @@ static int expand_variables( wchar_t *in, array_list_t *out )
|
||||
free( next );
|
||||
}
|
||||
sb_append( &res, &in[stop_pos] );
|
||||
is_ok &= expand_variables( (wchar_t *)res.buff, out );
|
||||
is_ok &= expand_variables( (wchar_t *)res.buff, out, i );
|
||||
}
|
||||
else
|
||||
{
|
||||
for( j=0; j<al_get_count( &l); j++ )
|
||||
for( j=0; j<al_get_count( &var_item_list); j++ )
|
||||
{
|
||||
wchar_t *next = (wchar_t *)al_get( &l, j );
|
||||
|
||||
if( is_ok )
|
||||
wchar_t *next = (wchar_t *)al_get( &var_item_list, j );
|
||||
if( is_ok && (i == 0) && (!in[stop_pos]) )
|
||||
{
|
||||
|
||||
new_len = wcslen(in) - (stop_pos-start_pos+1) + wcslen( next) +2;
|
||||
|
||||
if( !(new_in = malloc( sizeof(wchar_t)*new_len )))
|
||||
al_push( out, next );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if( is_ok )
|
||||
{
|
||||
die_mem();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
wcsncpy( new_in, in, start_pos-1 );
|
||||
|
||||
if(start_pos>1 && new_in[start_pos-2]!=VARIABLE_EXPAND)
|
||||
new_len = wcslen(in) - (stop_pos-start_pos+1);
|
||||
new_len += wcslen( next) +2;
|
||||
|
||||
if( !(new_in = malloc( sizeof(wchar_t)*new_len )))
|
||||
{
|
||||
new_in[start_pos-1]=INTERNAL_SEPARATOR;
|
||||
new_in[start_pos]=L'\0';
|
||||
die_mem();
|
||||
}
|
||||
else
|
||||
new_in[start_pos-1]=L'\0';
|
||||
|
||||
wcscat( new_in, next );
|
||||
wcscat( new_in, &in[stop_pos] );
|
||||
{
|
||||
|
||||
wcsncpy( new_in, in, start_pos-1 );
|
||||
|
||||
if(start_pos>1 && new_in[start_pos-2]!=VARIABLE_EXPAND)
|
||||
{
|
||||
new_in[start_pos-1]=INTERNAL_SEPARATOR;
|
||||
new_in[start_pos]=L'\0';
|
||||
}
|
||||
else
|
||||
new_in[start_pos-1]=L'\0';
|
||||
|
||||
wcscat( new_in, next );
|
||||
wcscat( new_in, &in[stop_pos] );
|
||||
|
||||
// fwprintf( stderr, L"New value %ls\n", new_in );
|
||||
is_ok &= expand_variables( new_in, out );
|
||||
is_ok &= expand_variables( new_in, out, i );
|
||||
}
|
||||
}
|
||||
free( next );
|
||||
}
|
||||
free( next );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
al_destroy( &l );
|
||||
al_destroy( &idx );
|
||||
free(in);
|
||||
free(var_name );
|
||||
al_destroy( &var_item_list );
|
||||
return is_ok;
|
||||
}
|
||||
else
|
||||
@@ -993,19 +1015,14 @@ static int expand_variables( wchar_t *in, array_list_t *out )
|
||||
in[i]=0;
|
||||
|
||||
sb_append( &res, in );
|
||||
|
||||
sb_append( &res, &in[stop_pos] );
|
||||
is_ok &= expand_variables( wcsdup((wchar_t *)res.buff), out );
|
||||
|
||||
sb_destroy( &res );
|
||||
is_ok &= expand_variables( (wchar_t *)res.buff, out, i );
|
||||
free(in);
|
||||
free(var_name );
|
||||
return is_ok;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
free(var_name );
|
||||
|
||||
}
|
||||
|
||||
@@ -1109,7 +1126,7 @@ static int expand_brackets( wchar_t *in, int flags, array_list_t *out )
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
-1,
|
||||
L"Mismatched brackets" );
|
||||
_(L"Mismatched brackets") );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1172,6 +1189,18 @@ static int expand_subshell( wchar_t *in, array_list_t *out )
|
||||
int i, j;
|
||||
const wchar_t *item_begin;
|
||||
|
||||
if( !in )
|
||||
{
|
||||
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( !out )
|
||||
{
|
||||
debug( 2, L"Got null pointer on line %d of file %s", __LINE__, __FILE__ );
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch( parse_util_locate_cmdsubst(in,
|
||||
¶n_begin,
|
||||
¶n_end,
|
||||
@@ -1188,7 +1217,6 @@ static int expand_subshell( wchar_t *in, array_list_t *out )
|
||||
case 1:
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
len1 = (paran_begin-in);
|
||||
@@ -1237,10 +1265,10 @@ static int expand_subshell( wchar_t *in, array_list_t *out )
|
||||
sb_append_substring( &whole_item, sub_item2, item_len );
|
||||
sb_append_char( &whole_item, INTERNAL_SEPARATOR );
|
||||
sb_append( &whole_item, tail_item );
|
||||
|
||||
al_push( out, whole_item.buff );
|
||||
|
||||
al_push( out, whole_item.buff );
|
||||
}
|
||||
|
||||
|
||||
free( sub_item2 );
|
||||
}
|
||||
free(in);
|
||||
@@ -1371,7 +1399,7 @@ static void remove_internal_separator( const void *s, int conv )
|
||||
case INTERNAL_SEPARATOR:
|
||||
in++;
|
||||
break;
|
||||
|
||||
|
||||
case ANY_CHAR:
|
||||
in++;
|
||||
*out++ = conv?L'?':ANY_CHAR;
|
||||
@@ -1393,7 +1421,8 @@ static void remove_internal_separator( const void *s, int conv )
|
||||
/**
|
||||
The real expansion function. expand_one is just a wrapper around this one.
|
||||
*/
|
||||
int expand_string( wchar_t *str,
|
||||
int expand_string( void *context,
|
||||
wchar_t *str,
|
||||
array_list_t *end_out,
|
||||
int flags )
|
||||
{
|
||||
@@ -1403,12 +1432,14 @@ int expand_string( wchar_t *str,
|
||||
int i;
|
||||
int subshell_ok = 1;
|
||||
int res = EXPAND_OK;
|
||||
int start_count = al_get_count( end_out );
|
||||
|
||||
// debug( 1, L"Expand %ls", str );
|
||||
|
||||
|
||||
if( (!(flags & ACCEPT_INCOMPLETE)) && is_clean( str ) )
|
||||
{
|
||||
halloc_register( context, str );
|
||||
al_push( end_out, str );
|
||||
return EXPAND_OK;
|
||||
}
|
||||
@@ -1418,23 +1449,18 @@ int expand_string( wchar_t *str,
|
||||
|
||||
if( EXPAND_SKIP_SUBSHELL & flags )
|
||||
{
|
||||
wchar_t *pos = str;
|
||||
|
||||
while( 1 )
|
||||
const wchar_t *begin, *end;
|
||||
|
||||
if( parse_util_locate_cmdsubst( str,
|
||||
&begin,
|
||||
&end,
|
||||
1 ) != 0 )
|
||||
{
|
||||
pos = wcschr( pos, L'(' );
|
||||
if( pos == 0 )
|
||||
break;
|
||||
|
||||
if( (pos == str) || ( *(pos-1) != L'\\' ) )
|
||||
{
|
||||
error( SUBSHELL_ERROR, -1, L"Subshells not allowed" );
|
||||
free( str );
|
||||
al_destroy( &list1 );
|
||||
al_destroy( &list2 );
|
||||
return EXPAND_ERROR;
|
||||
}
|
||||
pos++;
|
||||
error( SUBSHELL_ERROR, -1, L"Subshells not allowed" );
|
||||
free( str );
|
||||
al_destroy( &list1 );
|
||||
al_destroy( &list2 );
|
||||
return EXPAND_ERROR;
|
||||
}
|
||||
al_push( &list1, str );
|
||||
}
|
||||
@@ -1463,7 +1489,10 @@ int expand_string( wchar_t *str,
|
||||
free( (void *)al_get( in, i ) );
|
||||
|
||||
if( !next )
|
||||
continue;
|
||||
{
|
||||
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( EXPAND_SKIP_VARIABLES & flags )
|
||||
{
|
||||
@@ -1472,11 +1501,10 @@ int expand_string( wchar_t *str,
|
||||
if( *tmp == VARIABLE_EXPAND )
|
||||
*tmp = L'$';
|
||||
al_push( out, next );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!expand_variables( next, out ))
|
||||
if(!expand_variables( next, out, wcslen(next)-1 ))
|
||||
{
|
||||
al_destroy( in );
|
||||
al_destroy( out );
|
||||
@@ -1493,6 +1521,13 @@ int expand_string( wchar_t *str,
|
||||
for( i=0; i<al_get_count( in ); i++ )
|
||||
{
|
||||
wchar_t *next = (wchar_t *)al_get( in, i );
|
||||
|
||||
if( !next )
|
||||
{
|
||||
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !expand_brackets( next, flags, out ))
|
||||
{
|
||||
al_destroy( in );
|
||||
@@ -1508,6 +1543,13 @@ int expand_string( wchar_t *str,
|
||||
for( i=0; i<al_get_count( in ); i++ )
|
||||
{
|
||||
wchar_t *next = (wchar_t *)al_get( in, i );
|
||||
|
||||
if( !next )
|
||||
{
|
||||
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !(next=expand_tilde_internal( next ) ) )
|
||||
{
|
||||
al_destroy( in );
|
||||
@@ -1552,7 +1594,14 @@ int expand_string( wchar_t *str,
|
||||
wchar_t *next = (wchar_t *)al_get( in, i );
|
||||
int wc_res;
|
||||
|
||||
if( !next )
|
||||
{
|
||||
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
|
||||
continue;
|
||||
}
|
||||
|
||||
remove_internal_separator( next, EXPAND_SKIP_WILDCARDS & flags );
|
||||
|
||||
if( ((flags & ACCEPT_INCOMPLETE) && (!(flags & EXPAND_SKIP_WILDCARDS))) ||
|
||||
wildcard_has( next, 1 ) )
|
||||
{
|
||||
@@ -1569,50 +1618,79 @@ int expand_string( wchar_t *str,
|
||||
switch( wc_res )
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
if( !(flags & ACCEPT_INCOMPLETE) )
|
||||
{
|
||||
if( res == EXPAND_OK )
|
||||
res = EXPAND_WILDCARD_NO_MATCH;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
case 1:
|
||||
{
|
||||
int j;
|
||||
res = EXPAND_WILDCARD_MATCH;
|
||||
sort_list( out );
|
||||
al_push_all( end_out, out );
|
||||
|
||||
for( j=0; j<al_get_count( out ); j++ )
|
||||
{
|
||||
wchar_t *next = (wchar_t *)al_get( out, j );
|
||||
if( !next )
|
||||
{
|
||||
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
|
||||
continue;
|
||||
}
|
||||
al_push( end_out, next );
|
||||
}
|
||||
al_truncate( out, 0 );
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( flags & ACCEPT_INCOMPLETE)
|
||||
{
|
||||
free( next );
|
||||
}
|
||||
else
|
||||
{
|
||||
al_push( end_out, next );
|
||||
}
|
||||
}
|
||||
}
|
||||
al_destroy( in );
|
||||
al_destroy( out );
|
||||
}
|
||||
|
||||
if( context )
|
||||
{
|
||||
for( i=start_count; i<al_get_count( end_out ); i++ )
|
||||
{
|
||||
halloc_register( context, (void *)al_get( end_out, i ) );
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
|
||||
wchar_t *expand_one( wchar_t *string, int flags )
|
||||
wchar_t *expand_one( void *context, wchar_t *string, int flags )
|
||||
{
|
||||
array_list_t l;
|
||||
int res;
|
||||
wchar_t *one;
|
||||
|
||||
if( (!(flags & ACCEPT_INCOMPLETE)) && is_clean( string ) )
|
||||
{
|
||||
halloc_register( context, string );
|
||||
return string;
|
||||
|
||||
}
|
||||
|
||||
al_init( &l );
|
||||
res = expand_string( string, &l, flags );
|
||||
res = expand_string( 0, string, &l, flags );
|
||||
if( !res )
|
||||
{
|
||||
one = 0;
|
||||
@@ -1632,6 +1710,8 @@ wchar_t *expand_one( wchar_t *string, int flags )
|
||||
|
||||
al_foreach( &l, (void(*)(const void *))&free );
|
||||
al_destroy( &l );
|
||||
|
||||
halloc_register( context, one );
|
||||
return one;
|
||||
}
|
||||
|
||||
|
||||
5
expand.h
5
expand.h
@@ -130,7 +130,7 @@ enum
|
||||
\param out The list to which the result will be appended.
|
||||
\return One of EXPAND_OK, EXPAND_ERROR, EXPAND_WILDCARD_MATCH and EXPAND_WILDCARD_NO_MATCH
|
||||
*/
|
||||
int expand_string( wchar_t *in, array_list_t *out, int flag );
|
||||
int expand_string( void *context, wchar_t *in, array_list_t *out, int flag );
|
||||
|
||||
/**
|
||||
expand_one is identical to expand_string, except it will fail if in
|
||||
@@ -141,14 +141,13 @@ int expand_string( wchar_t *in, array_list_t *out, int flag );
|
||||
\param flag Specifies if any expansion pass should be skipped. Legal values are any combination of EXPAND_SKIP_SUBSHELL EXPAND_SKIP_VARIABLES and EXPAND_SKIP_WILDCARDS
|
||||
\return The expanded parameter, or 0 on failiure
|
||||
*/
|
||||
wchar_t *expand_one( wchar_t *in, int flag );
|
||||
wchar_t *expand_one( void *context, wchar_t *in, int flag );
|
||||
|
||||
/**
|
||||
Convert the variable value to a human readable form, i.e. escape things, handle arrays, etc. Suitable for pretty-printing.
|
||||
*/
|
||||
wchar_t *expand_escape_variable( const wchar_t *in );
|
||||
|
||||
|
||||
/**
|
||||
Perform tilde expansion and nothing else on the specified string.
|
||||
|
||||
|
||||
44
fish.spec.in
44
fish.spec.in
@@ -13,40 +13,65 @@ Source0: http://roo.no-ip.org/%{name}/files/%{version}/%{name}-%{
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||
BuildRequires: doxygen ncurses-devel xorg-x11-devel
|
||||
|
||||
|
||||
|
||||
|
||||
%description
|
||||
fish is a shell geared towards interactive use. It's features are
|
||||
focused on user friendlieness and discoverability. The language syntax
|
||||
is simple but incompatible with other shell languages.
|
||||
|
||||
|
||||
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
|
||||
%build
|
||||
|
||||
|
||||
|
||||
%build
|
||||
%configure docdir=%_datadir/doc/%{name}-%{version}
|
||||
make %{?_smp_mflags}
|
||||
|
||||
|
||||
|
||||
|
||||
%install
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
make install DESTDIR="$RPM_BUILD_ROOT"
|
||||
|
||||
|
||||
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
|
||||
|
||||
|
||||
%post
|
||||
if ! grep %_bindir/fish %_sysconfdir/shells >/dev/null; then
|
||||
echo %_bindir/fish >>%_sysconfdir/shells
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
%postun
|
||||
if [ "$1" = 0 ]; then
|
||||
grep -v %_bindir/fish %_sysconfdir/shells >%_sysconfdir/fish.tmp
|
||||
mv %_sysconfdir/fish.tmp %_sysconfdir/shells
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
|
||||
%doc %_datadir/doc/%{name}-%{version}
|
||||
|
||||
%_mandir/man1/fish.1*
|
||||
%_mandir/man1/xsel.1x*
|
||||
%_mandir/man1/mimedb.1*
|
||||
@@ -54,6 +79,7 @@ fi
|
||||
%_mandir/man1/count.1*
|
||||
%_mandir/man1/fishd.1*
|
||||
%_mandir/man1/fish_pager.1*
|
||||
|
||||
%attr(0755,root,root) %_bindir/fish
|
||||
%attr(0755,root,root) %_bindir/fishd
|
||||
%attr(0755,root,root) %_bindir/fish_pager
|
||||
@@ -61,14 +87,26 @@ fi
|
||||
%attr(0755,root,root) %_bindir/set_color
|
||||
%attr(0755,root,root) %_bindir/mimedb
|
||||
%attr(0755,root,root) %_bindir/count
|
||||
|
||||
%config %_sysconfdir/fish
|
||||
%config %_sysconfdir/fish_inputrc
|
||||
%dir %_sysconfdir/fish.d
|
||||
%config %_sysconfdir/fish.d/fish_*.fish
|
||||
%dir %_sysconfdir/fish.d/completions
|
||||
%config %_sysconfdir/fish.d/completions/*.fish
|
||||
|
||||
%dir %_datadir/fish
|
||||
%_datadir/fish/fish
|
||||
|
||||
%dir %_datadir/fish/completions
|
||||
%_datadir/fish/completions/*.fish
|
||||
|
||||
%dir %_datadir/fish/functions
|
||||
%_datadir/fish/functions/*.fish
|
||||
|
||||
%_datadir/locale/*/LC_MESSAGES/fish.mo
|
||||
|
||||
|
||||
|
||||
|
||||
%changelog
|
||||
* Tue Nov 29 2005 Axel Liljencrantz <axel@liljencrantz.se> 1.17.0-0
|
||||
- 1.17.0
|
||||
|
||||
601
fish_pager.c
601
fish_pager.c
@@ -42,6 +42,8 @@
|
||||
#include "output.h"
|
||||
#include "input_common.h"
|
||||
#include "env_universal.h"
|
||||
#include "halloc.h"
|
||||
#include "halloc_util.h"
|
||||
|
||||
enum
|
||||
{
|
||||
@@ -74,6 +76,7 @@ static struct termios pager_modes;
|
||||
|
||||
static int is_ca_mode = 0;
|
||||
|
||||
static buffer_t *pager_buffer;
|
||||
|
||||
/**
|
||||
The environment variables used to specify the color of different
|
||||
@@ -91,8 +94,18 @@ static wchar_t *hightlight_var[] =
|
||||
static string_buffer_t out_buff;
|
||||
static FILE *out_file;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
array_list_t *comp;
|
||||
wchar_t *desc;
|
||||
int comp_width;
|
||||
int desc_width;
|
||||
int pref_width;
|
||||
int min_width;
|
||||
}
|
||||
comp_t;
|
||||
|
||||
int get_color( int highlight )
|
||||
static int get_color( int highlight )
|
||||
{
|
||||
if( highlight < 0 )
|
||||
return FISH_COLOR_NORMAL;
|
||||
@@ -101,9 +114,6 @@ int get_color( int highlight )
|
||||
|
||||
wchar_t *val = env_universal_get( hightlight_var[highlight]);
|
||||
|
||||
if( val == 0 )
|
||||
return FISH_COLOR_NORMAL;
|
||||
|
||||
if( val == 0 )
|
||||
{
|
||||
return FISH_COLOR_NORMAL;
|
||||
@@ -112,7 +122,20 @@ int get_color( int highlight )
|
||||
return output_color_code( val );
|
||||
}
|
||||
|
||||
int try_sequence( char *seq )
|
||||
static void recalc_width( array_list_t *l, const wchar_t *prefix )
|
||||
{
|
||||
int i;
|
||||
for( i=0; i<al_get_count( l ); i++ )
|
||||
{
|
||||
comp_t *c = (comp_t *)al_get( l, i );
|
||||
|
||||
c->min_width = mini( c->desc_width, maxi(0,termsize.ws_col/3 - 2)) +
|
||||
mini( c->desc_width, maxi(0,termsize.ws_col/5 - 4)) +4;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int try_sequence( char *seq )
|
||||
{
|
||||
int j, k;
|
||||
wint_t c=0;
|
||||
@@ -195,6 +218,110 @@ static wint_t readch()
|
||||
}
|
||||
|
||||
|
||||
static int pager_buffered_writer( char c)
|
||||
{
|
||||
b_append( pager_buffer, &c, 1 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pager_flush()
|
||||
{
|
||||
write( 1, pager_buffer->buff, pager_buffer->used );
|
||||
pager_buffer->used = 0;
|
||||
}
|
||||
|
||||
|
||||
static int print_max( const wchar_t *str, int max, int has_more )
|
||||
{
|
||||
int i;
|
||||
int written = 0;
|
||||
for( i=0; str[i]; i++ )
|
||||
{
|
||||
if( written + wcwidth(str[i]) > max )
|
||||
break;
|
||||
if( ( written + wcwidth(str[i]) == max) && (has_more || str[i+1]) )
|
||||
{
|
||||
writech( ellipsis_char );
|
||||
written += wcwidth(ellipsis_char );
|
||||
break;
|
||||
}
|
||||
|
||||
writech( str[i] );
|
||||
written+= wcwidth( str[i] );
|
||||
}
|
||||
return written;
|
||||
}
|
||||
|
||||
static void completion_print_item( const wchar_t *prefix, comp_t *c, int width )
|
||||
{
|
||||
int comp_width=0, desc_width=0;
|
||||
int i;
|
||||
int written=0;
|
||||
|
||||
if( c->pref_width <= width )
|
||||
{
|
||||
/*
|
||||
The entry fits, we give it as much space as it wants
|
||||
*/
|
||||
comp_width = c->comp_width;
|
||||
desc_width = c->desc_width;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
The completion and description won't fit on the
|
||||
allocated space. Give a maximum of 2/3 of the
|
||||
space to the completion, and whatever is left to
|
||||
the description.
|
||||
*/
|
||||
int desc_all = c->desc_width?c->desc_width+4:0;
|
||||
|
||||
comp_width = maxi( mini( c->comp_width,
|
||||
2*(width-4)/3 ),
|
||||
width - desc_all );
|
||||
if( c->desc_width )
|
||||
desc_width = width-comp_width-4;
|
||||
else
|
||||
c->desc_width=0;
|
||||
|
||||
}
|
||||
|
||||
for( i=0; i<al_get_count( c->comp ); i++ )
|
||||
{
|
||||
const wchar_t *comp = (const wchar_t *)al_get( c->comp, i );
|
||||
if( i != 0 )
|
||||
written += print_max( L" ", comp_width - written, 2 );
|
||||
set_color( get_color(HIGHLIGHT_PAGER_PREFIX),FISH_COLOR_NORMAL );
|
||||
written += print_max( prefix, comp_width - written, comp[0]?1:0 );
|
||||
set_color( get_color(HIGHLIGHT_PAGER_COMPLETION),FISH_COLOR_IGNORE );
|
||||
written += print_max( comp, comp_width - written, i!=(al_get_count(c->comp)-1) );
|
||||
}
|
||||
|
||||
|
||||
if( desc_width )
|
||||
{
|
||||
while( written < (width-desc_width-2))
|
||||
{
|
||||
written++;
|
||||
writech( L' ');
|
||||
}
|
||||
written += print_max( L"(", 1, 0 );
|
||||
set_color( get_color( HIGHLIGHT_PAGER_DESCRIPTION ),
|
||||
FISH_COLOR_IGNORE );
|
||||
written += print_max( c->desc, desc_width, 0 );
|
||||
written += print_max( L")", 1, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
while( written < width )
|
||||
{
|
||||
written++;
|
||||
writech( L' ');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Print the specified part of the completion list, using the
|
||||
specified column offsets and quoting style.
|
||||
@@ -219,291 +346,29 @@ static void completion_print( int cols,
|
||||
|
||||
int rows = (al_get_count( l )-1)/cols+1;
|
||||
int i, j;
|
||||
int prefix_width= my_wcswidth(prefix);
|
||||
|
||||
for( i = row_start; i<row_stop; i++ )
|
||||
{
|
||||
for( j = 0; j < cols; j++ )
|
||||
{
|
||||
wchar_t *el, *el_end;
|
||||
comp_t *el;
|
||||
|
||||
int is_last = (j==(cols-1));
|
||||
|
||||
if( al_get_count( l ) <= j*rows + i )
|
||||
continue;
|
||||
|
||||
el = (wchar_t *)al_get( l, j*rows + i );
|
||||
el_end= wcschr( el, COMPLETE_SEP );
|
||||
|
||||
set_color( get_color(HIGHLIGHT_PAGER_PREFIX),FISH_COLOR_NORMAL );
|
||||
|
||||
writestr( prefix );
|
||||
|
||||
set_color( get_color(HIGHLIGHT_PAGER_COMPLETION),FISH_COLOR_IGNORE );
|
||||
|
||||
if( el_end == 0 )
|
||||
{
|
||||
/* We do not have a description for this completion */
|
||||
int written = 0;
|
||||
int max_written = width[j] - prefix_width - (j==cols-1?0:2);
|
||||
|
||||
if( is_quoted )
|
||||
{
|
||||
for( i=0; i<max_written; i++ )
|
||||
{
|
||||
if( !el[i] )
|
||||
break;
|
||||
writech( el[i] );
|
||||
written+= wcwidth( el[i] );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
written = write_escaped_str( el, max_written );
|
||||
}
|
||||
|
||||
set_color( get_color( HIGHLIGHT_PAGER_DESCRIPTION ),
|
||||
FISH_COLOR_IGNORE );
|
||||
|
||||
writespace( width[j]-
|
||||
written-
|
||||
prefix_width );
|
||||
}
|
||||
else
|
||||
{
|
||||
int whole_desc_width = my_wcswidth(el_end+1);
|
||||
int whole_comp_width;
|
||||
|
||||
/*
|
||||
Temporarily drop the description so that wcswidth et
|
||||
al only calculate the width of the completion.
|
||||
*/
|
||||
*el_end = L'\0';
|
||||
|
||||
/*
|
||||
Calculate preferred completion width
|
||||
*/
|
||||
if( is_quoted )
|
||||
{
|
||||
whole_comp_width = my_wcswidth(el);
|
||||
}
|
||||
else
|
||||
{
|
||||
wchar_t *tmp = escape( el, 1 );
|
||||
whole_comp_width = my_wcswidth( tmp );
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
/*
|
||||
Calculate how wide this entry 'wants' to be
|
||||
*/
|
||||
int pref_width = whole_desc_width + 4 + prefix_width + 2 -
|
||||
(j==cols-1?2:0) + whole_comp_width;
|
||||
|
||||
int comp_width, desc_width;
|
||||
|
||||
if( pref_width <= width[j] )
|
||||
{
|
||||
/*
|
||||
The entry fits, we give it as much space as it wants
|
||||
*/
|
||||
comp_width = whole_comp_width;
|
||||
desc_width = whole_desc_width;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
The completion and description won't fit on the
|
||||
allocated space. Give a maximum of 2/3 of the
|
||||
space to the completion, and whatever is left to
|
||||
the description.
|
||||
*/
|
||||
int sum = width[j] - prefix_width - 4 - 2 + (j==cols-1?2:0);
|
||||
|
||||
comp_width = maxi( mini( whole_comp_width,
|
||||
2*sum/3 ),
|
||||
sum - whole_desc_width );
|
||||
desc_width = sum-comp_width;
|
||||
}
|
||||
|
||||
/* First we must print the completion. */
|
||||
if( is_quoted )
|
||||
{
|
||||
writestr_ellipsis( el, comp_width);
|
||||
}
|
||||
else
|
||||
{
|
||||
write_escaped_str( el, comp_width );
|
||||
}
|
||||
|
||||
/* Put the description back */
|
||||
*el_end = COMPLETE_SEP;
|
||||
|
||||
/* And print it */
|
||||
set_color( get_color(HIGHLIGHT_PAGER_DESCRIPTION),
|
||||
FISH_COLOR_IGNORE );
|
||||
writespace( maxi( 2,
|
||||
width[j]
|
||||
- comp_width
|
||||
- desc_width
|
||||
- 4
|
||||
- prefix_width
|
||||
+ (j==cols-1?2:0) ) );
|
||||
/* Print description */
|
||||
writestr(L"(");
|
||||
writestr_ellipsis( el_end+1, desc_width);
|
||||
writestr(L")");
|
||||
|
||||
if( j != cols-1)
|
||||
writestr( L" " );
|
||||
|
||||
}
|
||||
el = (comp_t *)al_get( l, j*rows + i );
|
||||
|
||||
completion_print_item( prefix, el, width[j] - (is_last?0:2) );
|
||||
|
||||
if( !is_last)
|
||||
writestr( L" " );
|
||||
}
|
||||
writech( L'\n' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Calculates how long the specified string would be when printed on the command line.
|
||||
|
||||
\param str The string to be printed.
|
||||
\param is_quoted Whether the string would be printed quoted or unquoted
|
||||
\param pref_width the preferred width for this item
|
||||
\param min_width the minimum width for this item
|
||||
*/
|
||||
static void printed_length( wchar_t *str,
|
||||
int is_quoted,
|
||||
int *pref_width,
|
||||
int *min_width )
|
||||
{
|
||||
if( is_quoted )
|
||||
{
|
||||
wchar_t *sep = wcschr(str,COMPLETE_SEP);
|
||||
if( sep )
|
||||
{
|
||||
*sep=0;
|
||||
int cw = my_wcswidth( str );
|
||||
int dw = my_wcswidth(sep+1);
|
||||
|
||||
if( termsize.ws_col > 80 )
|
||||
dw = mini( dw, termsize.ws_col/3 );
|
||||
|
||||
|
||||
*pref_width = cw+dw+4;
|
||||
|
||||
if( dw > termsize.ws_col/3 )
|
||||
{
|
||||
dw = termsize.ws_col/3;
|
||||
}
|
||||
|
||||
*min_width=cw+dw+4;
|
||||
|
||||
*sep= COMPLETE_SEP;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pref_width=*min_width= my_wcswidth( str );
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
int comp_len=0, desc_len=0;
|
||||
int has_description = 0;
|
||||
while( *str != 0 )
|
||||
{
|
||||
if( ( *str >= ENCODE_DIRECT_BASE) &&
|
||||
( *str < ENCODE_DIRECT_BASE+256) )
|
||||
{
|
||||
if( has_description )
|
||||
desc_len+=4;
|
||||
else
|
||||
comp_len+=4;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
switch( *str )
|
||||
{
|
||||
case L'\n':
|
||||
case L'\b':
|
||||
case L'\r':
|
||||
case L'\e':
|
||||
case L'\t':
|
||||
case L'\\':
|
||||
case L'&':
|
||||
case L'$':
|
||||
case L' ':
|
||||
case L'#':
|
||||
case L'^':
|
||||
case L'<':
|
||||
case L'>':
|
||||
case L'(':
|
||||
case L')':
|
||||
case L'[':
|
||||
case L']':
|
||||
case L'{':
|
||||
case L'}':
|
||||
case L'?':
|
||||
case L'*':
|
||||
case L'|':
|
||||
case L';':
|
||||
case L':':
|
||||
case L'\'':
|
||||
case L'"':
|
||||
case L'%':
|
||||
case L'~':
|
||||
|
||||
if( has_description )
|
||||
desc_len++;
|
||||
else
|
||||
comp_len+=2;
|
||||
break;
|
||||
|
||||
case COMPLETE_SEP:
|
||||
has_description = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
if( has_description )
|
||||
desc_len+= wcwidth(*str);
|
||||
else
|
||||
comp_len+= wcwidth(*str);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
str++;
|
||||
}
|
||||
if( has_description )
|
||||
{
|
||||
/*
|
||||
Mangle long descriptions to make formating look nicer
|
||||
*/
|
||||
debug( 3, L"Desc, width = %d %d\n", comp_len, desc_len );
|
||||
// if( termsize.ws_col > 80 )
|
||||
// desc_len = mini( desc_len, termsize.ws_col/3 );
|
||||
|
||||
*pref_width = comp_len+ desc_len+4;;
|
||||
|
||||
comp_len = mini( comp_len, maxi(0,termsize.ws_col/3 - 2));
|
||||
desc_len = mini( desc_len, maxi(0,termsize.ws_col/5 - 4));
|
||||
|
||||
*min_width = comp_len+ desc_len+4;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
debug( 3, L"No desc, width = %d\n", comp_len );
|
||||
|
||||
*pref_width=*min_width= comp_len;
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Try to print the list of completions l with the prefix prefix using
|
||||
@@ -551,8 +416,6 @@ static int completion_try_print( int cols,
|
||||
|
||||
int pref_tot_width=0;
|
||||
int min_tot_width = 0;
|
||||
int prefix_width = my_wcswidth( prefix );
|
||||
|
||||
int res=0;
|
||||
/*
|
||||
Skip completions on tiny terminals
|
||||
@@ -560,25 +423,24 @@ static int completion_try_print( int cols,
|
||||
|
||||
if( termsize.ws_col < 16 )
|
||||
return 1;
|
||||
|
||||
|
||||
memset( pref_width, 0, sizeof(pref_width) );
|
||||
memset( min_width, 0, sizeof(min_width) );
|
||||
|
||||
|
||||
/* Calculate how wide the list would be */
|
||||
for( j = 0; j < cols; j++ )
|
||||
{
|
||||
for( i = 0; i<rows; i++ )
|
||||
{
|
||||
int pref,min;
|
||||
wchar_t *el;
|
||||
comp_t *c;
|
||||
if( al_get_count( l ) <= j*rows + i )
|
||||
continue;
|
||||
|
||||
el = (wchar_t *)al_get( l, j*rows + i );
|
||||
printed_length( el, is_quoted, &pref, &min );
|
||||
|
||||
pref += prefix_width;
|
||||
min += prefix_width;
|
||||
c = (comp_t *)al_get( l, j*rows + i );
|
||||
pref = c->pref_width;
|
||||
min = c->min_width;
|
||||
|
||||
if( j != cols-1 )
|
||||
{
|
||||
pref += 2;
|
||||
@@ -660,6 +522,7 @@ static int completion_try_print( int cols,
|
||||
}
|
||||
|
||||
completion_print( cols, width, 0, rows, prefix, is_quoted, l);
|
||||
pager_flush();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -692,6 +555,7 @@ static int completion_try_print( int cols,
|
||||
percent );
|
||||
writestr(msg);
|
||||
set_color( FISH_COLOR_NORMAL, FISH_COLOR_NORMAL );
|
||||
pager_flush();
|
||||
int c = readch();
|
||||
|
||||
switch( c )
|
||||
@@ -753,7 +617,8 @@ static int completion_try_print( int cols,
|
||||
}
|
||||
else
|
||||
{
|
||||
writembs( flash_screen );
|
||||
if( flash_screen )
|
||||
writembs( flash_screen );
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -777,7 +642,8 @@ static int completion_try_print( int cols,
|
||||
}
|
||||
else
|
||||
{
|
||||
writembs( flash_screen );
|
||||
if( flash_screen )
|
||||
writembs( flash_screen );
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -805,7 +671,9 @@ static int completion_try_print( int cols,
|
||||
}
|
||||
|
||||
/**
|
||||
Substitute any series of tabs, newlines, etc. with a single space character in completion description
|
||||
Substitute any series of whitespace with a single space character
|
||||
inside completion descriptions. Remove all whitespace from
|
||||
beginning/end of completion descriptions.
|
||||
*/
|
||||
static void mangle_descriptions( array_list_t *l )
|
||||
{
|
||||
@@ -843,6 +711,125 @@ static void mangle_descriptions( array_list_t *l )
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Merge multiple completions with the same description to the same line
|
||||
*/
|
||||
static void join_completions( array_list_t *l )
|
||||
{
|
||||
int i, in, out;
|
||||
hash_table_t desc_table;
|
||||
|
||||
hash_init( &desc_table, &hash_wcs_func, &hash_wcs_cmp );
|
||||
|
||||
for( i=0; i<al_get_count(l); i++ )
|
||||
{
|
||||
wchar_t *item = (wchar_t *)al_get( l, i );
|
||||
wchar_t *desc = wcschr( item, COMPLETE_SEP );
|
||||
long prev_idx;
|
||||
|
||||
if( !desc )
|
||||
continue;
|
||||
desc++;
|
||||
prev_idx = ((long)hash_get( &desc_table, desc) )-1;
|
||||
if( prev_idx == -1 )
|
||||
{
|
||||
hash_put( &desc_table, halloc_wcsdup( global_context, desc), (void *)(i+1));
|
||||
}
|
||||
else
|
||||
{
|
||||
string_buffer_t foo;
|
||||
wchar_t *old = (wchar_t *)al_get( l, prev_idx );
|
||||
wchar_t *old_end = wcschr( old, COMPLETE_SEP );
|
||||
|
||||
if( old_end )
|
||||
{
|
||||
*old_end = 0;
|
||||
|
||||
sb_init( &foo );
|
||||
sb_append( &foo, old );
|
||||
sb_append_char( &foo, COMPLETE_ITEM_SEP );
|
||||
sb_append( &foo, item );
|
||||
|
||||
free( (void *)al_get( l, prev_idx ) );
|
||||
al_set( l, prev_idx, foo.buff );
|
||||
|
||||
free( (void *)al_get( l, i ) );
|
||||
al_set( l, i, 0 );
|
||||
}
|
||||
|
||||
// debug( 1, L"WOOT WOOT %ls är släkt med %ls", item, al_get( l, prev_idx ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
hash_destroy( &desc_table );
|
||||
|
||||
out=0;
|
||||
for( in=0; in < al_get_count(l); in++ )
|
||||
{
|
||||
const void * d = al_get( l, in );
|
||||
|
||||
if( d )
|
||||
{
|
||||
al_set( l, out++, d );
|
||||
}
|
||||
}
|
||||
al_truncate( l, out );
|
||||
}
|
||||
|
||||
/**
|
||||
Replace completion strings with a comp_t structure
|
||||
*/
|
||||
static void mangle_completions( array_list_t *l, const wchar_t *prefix )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i=0; i<al_get_count( l ); i++ )
|
||||
{
|
||||
wchar_t *next = (wchar_t *)al_get( l, i );
|
||||
wchar_t *start, *end;
|
||||
comp_t *comp = halloc( global_context, sizeof( comp_t ) );
|
||||
comp->comp = al_halloc( global_context );
|
||||
|
||||
for( start=end=next; 1; end++ )
|
||||
{
|
||||
wchar_t c = *end;
|
||||
|
||||
if( (c == COMPLETE_ITEM_SEP) || (c==COMPLETE_SEP) || !c)
|
||||
{
|
||||
*end = 0;
|
||||
wchar_t * str = escape( start, 1 );
|
||||
comp->comp_width += my_wcswidth( str );
|
||||
halloc_register( global_context, str );
|
||||
al_push( comp->comp, str );
|
||||
start = end+1;
|
||||
}
|
||||
|
||||
if( c == COMPLETE_SEP )
|
||||
{
|
||||
comp->desc = halloc_wcsdup( global_context, start );
|
||||
break;
|
||||
}
|
||||
|
||||
if( !c )
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
comp->comp_width += my_wcswidth(prefix)*al_get_count(comp->comp) + 2*(al_get_count(comp->comp)-1);
|
||||
comp->desc_width = comp->desc?my_wcswidth( comp->desc ):0;
|
||||
|
||||
comp->pref_width = comp->comp_width + comp->desc_width + (comp->desc_width?4:0);
|
||||
|
||||
free( next );
|
||||
al_set( l, i, comp );
|
||||
}
|
||||
|
||||
recalc_width( l, prefix );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Respond to a winch signal by checking the terminal size
|
||||
*/
|
||||
@@ -887,9 +874,12 @@ static void init()
|
||||
*/
|
||||
sb_init( &out_buff );
|
||||
|
||||
output_init();
|
||||
halloc_util_init();
|
||||
env_universal_init( 0, 0, 0, 0);
|
||||
input_common_init( &interrupt_handler );
|
||||
output_set_writer( &pager_buffered_writer );
|
||||
pager_buffer = halloc( global_context, sizeof( buffer_t ) );
|
||||
halloc_register_function( global_context, (void (*)(void *))&b_destroy, pager_buffer );
|
||||
|
||||
sigemptyset( & act.sa_mask );
|
||||
act.sa_flags=0;
|
||||
@@ -914,6 +904,9 @@ static void init()
|
||||
pager_modes.c_cc[VMIN]=1;
|
||||
pager_modes.c_cc[VTIME]=0;
|
||||
|
||||
/*
|
||||
|
||||
*/
|
||||
if( tcsetattr(0,TCSANOW,&pager_modes)) /* set the new modes */
|
||||
{
|
||||
wperror(L"tcsetattr");
|
||||
@@ -932,49 +925,51 @@ void destroy()
|
||||
{
|
||||
env_universal_destroy();
|
||||
input_common_destroy();
|
||||
output_destroy();
|
||||
halloc_util_destroy();
|
||||
del_curterm( cur_term );
|
||||
sb_destroy( &out_buff );
|
||||
fclose( out_file );
|
||||
|
||||
}
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
int i;
|
||||
int is_quoted=0;
|
||||
array_list_t comp;
|
||||
array_list_t *comp;
|
||||
wchar_t *prefix;
|
||||
|
||||
|
||||
init();
|
||||
|
||||
if( argc < 3 )
|
||||
{
|
||||
debug( 0, L"Insufficient arguments" );
|
||||
}
|
||||
else
|
||||
{
|
||||
comp = al_halloc( global_context );
|
||||
prefix = str2wcs( argv[2] );
|
||||
is_quoted = strcmp( "1", argv[1] )==0;
|
||||
|
||||
is_quoted = 0;
|
||||
|
||||
debug( 3, L"prefix is '%ls'", prefix );
|
||||
|
||||
al_init( &comp );
|
||||
|
||||
|
||||
for( i=3; i<argc; i++ )
|
||||
{
|
||||
wchar_t *wcs = str2wcs( argv[i] );
|
||||
if( wcs )
|
||||
{
|
||||
al_push( &comp, wcs );
|
||||
al_push( comp, wcs );
|
||||
}
|
||||
}
|
||||
|
||||
mangle_descriptions( comp );
|
||||
if( wcscmp( prefix, L"-" ) == 0 )
|
||||
join_completions( comp );
|
||||
mangle_completions( comp, prefix );
|
||||
|
||||
mangle_descriptions( &comp );
|
||||
|
||||
for( i = 6; i>0; i-- )
|
||||
{
|
||||
switch( completion_try_print( i, prefix, is_quoted, &comp ) )
|
||||
switch( completion_try_print( i, prefix, is_quoted, comp ) )
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
@@ -988,8 +983,6 @@ int main( int argc, char **argv )
|
||||
|
||||
}
|
||||
|
||||
al_foreach( &comp, (void(*)(const void *))&free );
|
||||
al_destroy( &comp );
|
||||
free(prefix );
|
||||
|
||||
fwprintf( out_file, L"%ls", (wchar_t *)out_buff.buff );
|
||||
|
||||
24
fish_tests.c
24
fish_tests.c
@@ -41,6 +41,7 @@
|
||||
#include "output.h"
|
||||
#include "exec.h"
|
||||
#include "event.h"
|
||||
#include "halloc_util.h"
|
||||
|
||||
/**
|
||||
Number of laps to run performance testing loop
|
||||
@@ -327,7 +328,7 @@ static void sb_test()
|
||||
|
||||
sb_init( &b );
|
||||
|
||||
if( res=sb_printf( &b, L"%ls%s", L"Testing ", "string_buffer_t " ) == -1 )
|
||||
if( (res=sb_printf( &b, L"%ls%s", L"Testing ", "string_buffer_t " )) == -1 )
|
||||
{
|
||||
err( L"Error %d while testing stringbuffers", res );
|
||||
}
|
||||
@@ -336,7 +337,22 @@ static void sb_test()
|
||||
{
|
||||
err( L"Error %d while testing stringbuffers", res );
|
||||
}
|
||||
|
||||
say( (wchar_t *)b.buff );
|
||||
|
||||
sb_clear( &b );
|
||||
|
||||
#define NUM_ANS L"-7 99999999 1234567 deadbeef DEADBEEFDEADBEEF"
|
||||
|
||||
sb_printf( &b, L"%d %u %o %x %llX", -7, 99999999, 01234567, 0xdeadbeef, 0xdeadbeefdeadbeefll );
|
||||
if( wcscmp( (wchar_t *)b.buff, NUM_ANS) != 0 )
|
||||
{
|
||||
err( L"numerical formating is broken, '%ls' != '%ls'", (wchar_t *)b.buff, NUM_ANS );
|
||||
}
|
||||
else
|
||||
say( L"numerical formating works" );
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -533,7 +549,7 @@ static int expand_test( const wchar_t *in, int flags, ... )
|
||||
wchar_t *arg;
|
||||
|
||||
al_init( &out );
|
||||
expand_string( wcsdup(in), &out, flags);
|
||||
expand_string( 0, wcsdup(in), &out, flags);
|
||||
|
||||
va_start( va, flags );
|
||||
|
||||
@@ -669,7 +685,7 @@ int main( int argc, char **argv )
|
||||
say( L"Lines beginning with '(ignore):' are not errors, they are warning messages\ngenerated by the fish parser library when given broken input, and can be\nignored. All actual errors begin with 'Error:'." );
|
||||
|
||||
proc_init();
|
||||
output_init();
|
||||
halloc_util_init();
|
||||
event_init();
|
||||
exec_init();
|
||||
parser_init();
|
||||
@@ -701,7 +717,7 @@ int main( int argc, char **argv )
|
||||
wutil_destroy();
|
||||
exec_destroy();
|
||||
event_destroy();
|
||||
output_destroy();
|
||||
proc_destroy();
|
||||
halloc_util_destroy();
|
||||
|
||||
}
|
||||
|
||||
112
function.c
112
function.c
@@ -19,6 +19,8 @@
|
||||
#include "event.h"
|
||||
#include "reader.h"
|
||||
#include "parse_util.h"
|
||||
#include "env.h"
|
||||
#include "expand.h"
|
||||
|
||||
|
||||
/**
|
||||
@@ -33,6 +35,7 @@ typedef struct
|
||||
const wchar_t *definition_file;
|
||||
int definition_offset;
|
||||
int is_binding;
|
||||
int is_autoload;
|
||||
}
|
||||
function_data_t;
|
||||
|
||||
@@ -40,6 +43,79 @@ typedef struct
|
||||
Table containing all functions
|
||||
*/
|
||||
static hash_table_t function;
|
||||
static int is_autoload = 0;
|
||||
|
||||
/**
|
||||
Make sure that if the specified function is a dynamically loaded
|
||||
function, it has been fully loaded.
|
||||
*/
|
||||
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,
|
||||
L"fish_function_path",
|
||||
&function_remove,
|
||||
1 );
|
||||
is_autoload = was_autoload;
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
Insert a list of all dynamically loaded functions into the
|
||||
specified list.
|
||||
*/
|
||||
static void autoload_names( array_list_t *out, int get_hidden )
|
||||
{
|
||||
int i;
|
||||
|
||||
array_list_t path_list;
|
||||
const wchar_t *path_var = env_get( L"fish_function_path" );
|
||||
|
||||
if( ! path_var )
|
||||
return;
|
||||
|
||||
al_init( &path_list );
|
||||
|
||||
expand_variable_array( path_var, &path_list );
|
||||
for( i=0; i<al_get_count( &path_list ); i++ )
|
||||
{
|
||||
wchar_t *ndir = (wchar_t *)al_get( &path_list, i );
|
||||
DIR *dir = wopendir( ndir );
|
||||
if( !dir )
|
||||
continue;
|
||||
|
||||
struct wdirent *next;
|
||||
while( (next=wreaddir(dir))!=0 )
|
||||
{
|
||||
wchar_t *fn = next->d_name;
|
||||
wchar_t *suffix;
|
||||
if( !get_hidden && fn[0] == L'_' )
|
||||
continue;
|
||||
|
||||
suffix = wcsrchr( fn, L'.' );
|
||||
if( suffix && (wcscmp( suffix, L".fish" ) == 0 ) )
|
||||
{
|
||||
const wchar_t *dup;
|
||||
*suffix = 0;
|
||||
dup = intern( fn );
|
||||
if( !dup )
|
||||
die_mem();
|
||||
al_push( out, dup );
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
al_foreach( &path_list, (void (*)(const void *))&free );
|
||||
al_destroy( &path_list );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Free all contents of an entry to the function hash table
|
||||
@@ -92,7 +168,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 +181,10 @@ void function_add( const wchar_t *name,
|
||||
|
||||
int function_exists( const wchar_t *cmd )
|
||||
{
|
||||
if( parser_is_reserved(cmd) )
|
||||
return 0;
|
||||
|
||||
load( cmd );
|
||||
return (hash_get(&function, cmd) != 0 );
|
||||
}
|
||||
|
||||
@@ -130,8 +211,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 +221,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 +232,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 +257,8 @@ static void get_names_internal( const void *key,
|
||||
|
||||
void function_get_names( array_list_t *list, int get_hidden )
|
||||
{
|
||||
autoload_names( list, get_hidden );
|
||||
|
||||
if( get_hidden )
|
||||
hash_get_keys( &function, list );
|
||||
else
|
||||
@@ -182,8 +268,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,13 +280,12 @@ 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;
|
||||
|
||||
return data->definition_offset;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -69,8 +69,15 @@ int function_exists( const wchar_t *name );
|
||||
void function_get_names( array_list_t *list,
|
||||
int get_hidden );
|
||||
|
||||
/**
|
||||
Returns tha absolute path of the file where the specified function
|
||||
was defined. Returns 0 if the file was defined on the commandline.
|
||||
*/
|
||||
const wchar_t *function_get_definition_file( const wchar_t *name );
|
||||
|
||||
/**
|
||||
Returns the linenumber where the definition of the specified function started
|
||||
*/
|
||||
int function_get_definition_offset( const wchar_t *name );
|
||||
|
||||
#endif
|
||||
|
||||
158
halloc.c
158
halloc.c
@@ -15,10 +15,23 @@
|
||||
#include "common.h"
|
||||
#include "halloc.h"
|
||||
|
||||
#define HALLOC_BLOCK_SIZE 128
|
||||
#define HALLOC_SCRAP_SIZE 16
|
||||
|
||||
#ifdef HALLOC_DEBUG
|
||||
static int child_count=0;
|
||||
static int child_size=0;
|
||||
static int alloc_count =0;
|
||||
static int alloc_spill = 0;
|
||||
static pid_t pid=0;
|
||||
static int parent_count=0;
|
||||
#endif
|
||||
|
||||
typedef struct halloc
|
||||
{
|
||||
array_list_t children;
|
||||
array_list_t hchildren;
|
||||
void *scratch;
|
||||
size_t scratch_free;
|
||||
long long data[0];
|
||||
}
|
||||
halloc_t;
|
||||
@@ -28,51 +41,130 @@ static halloc_t *halloc_from_data( void *data )
|
||||
return (halloc_t *)(data - sizeof( halloc_t ) );
|
||||
}
|
||||
|
||||
static void late_free( void *data)
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef HALLOC_DEBUG
|
||||
static void woot()
|
||||
{
|
||||
if( getpid() == pid )
|
||||
{
|
||||
debug( 1, L"%d parents, %d children with average child size of %.2f bytes caused %d allocs, average spill of %.2f bytes",
|
||||
parent_count, child_count, (double)child_size/child_count,
|
||||
parent_count+alloc_count, (double)alloc_spill/(parent_count+alloc_count) );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void *halloc( void *context, size_t size )
|
||||
{
|
||||
|
||||
{
|
||||
halloc_t *me, *parent;
|
||||
|
||||
me = (halloc_t *)calloc( 1, sizeof(halloc_t) + size );
|
||||
|
||||
if( !me )
|
||||
return 0;
|
||||
|
||||
al_init( &me->children );
|
||||
|
||||
if( context )
|
||||
{
|
||||
parent = halloc_from_data( context );
|
||||
al_push( &parent->hchildren, &me->data );
|
||||
}
|
||||
{
|
||||
void *res;
|
||||
|
||||
return &me->data;
|
||||
}
|
||||
#ifdef HALLOC_DEBUG
|
||||
|
||||
if( !child_count )
|
||||
{
|
||||
pid = getpid();
|
||||
atexit( woot );
|
||||
}
|
||||
|
||||
child_count++;
|
||||
child_size += size;
|
||||
#endif
|
||||
parent = halloc_from_data( context );
|
||||
if( size <= parent->scratch_free )
|
||||
{
|
||||
res = parent->scratch;
|
||||
parent->scratch_free -= size;
|
||||
parent->scratch += size;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
void *halloc_register( void *context, void *data )
|
||||
{
|
||||
halloc_t *me;
|
||||
if( !context )
|
||||
return data;
|
||||
#ifdef HALLOC_DEBUG
|
||||
alloc_count++;
|
||||
#endif
|
||||
|
||||
if( parent->scratch_free < HALLOC_SCRAP_SIZE )
|
||||
{
|
||||
#ifdef HALLOC_DEBUG
|
||||
alloc_spill += parent->scratch_free;
|
||||
#endif
|
||||
res = calloc( 1, size + HALLOC_BLOCK_SIZE );
|
||||
parent->scratch = res + size;
|
||||
parent->scratch_free = HALLOC_BLOCK_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = calloc( 1, size );
|
||||
}
|
||||
al_push( &parent->children, &late_free );
|
||||
al_push( &parent->children, res );
|
||||
|
||||
}
|
||||
return res;
|
||||
|
||||
me = halloc_from_data( context );
|
||||
al_push( &me->children, data );
|
||||
return data;
|
||||
}
|
||||
else
|
||||
{
|
||||
me = (halloc_t *)calloc( 1, sizeof(halloc_t) + size + HALLOC_BLOCK_SIZE );
|
||||
|
||||
if( !me )
|
||||
return 0;
|
||||
#ifdef HALLOC_DEBUG
|
||||
parent_count++;
|
||||
#endif
|
||||
me->scratch = ((void *)me) + sizeof(halloc_t) + size;
|
||||
me->scratch_free = HALLOC_BLOCK_SIZE;
|
||||
|
||||
al_init( &me->children );
|
||||
return &me->data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void halloc_free( void *context )
|
||||
void halloc_register_function( void *context, void (*func)(void *), void *data )
|
||||
{
|
||||
halloc_t *me;
|
||||
if( !context )
|
||||
return;
|
||||
|
||||
|
||||
me = halloc_from_data( context );
|
||||
al_foreach( &me->hchildren, (void (*)(const void *))&halloc_free );
|
||||
al_foreach( &me->children, (void (*)(const void *))&free );
|
||||
al_destroy( &me->children );
|
||||
al_destroy( &me->hchildren );
|
||||
free(me);
|
||||
al_push( &me->children, func );
|
||||
al_push( &me->children, data );
|
||||
}
|
||||
|
||||
void halloc_free( void *context )
|
||||
{
|
||||
halloc_t *me;
|
||||
int i;
|
||||
|
||||
if( !context )
|
||||
return;
|
||||
|
||||
|
||||
me = halloc_from_data( context );
|
||||
|
||||
#ifdef HALLOC_DEBUG
|
||||
alloc_spill += me->scratch_free;
|
||||
#endif
|
||||
for( i=0; i<al_get_count(&me->children); i+=2 )
|
||||
{
|
||||
void (*func)(void *) = (void (*)(void *))al_get( &me->children, i );
|
||||
void * data = (void *)al_get( &me->children, i+1 );
|
||||
if( func != &late_free )
|
||||
func( data );
|
||||
}
|
||||
for( i=0; i<al_get_count(&me->children); i+=2 )
|
||||
{
|
||||
void (*func)(void *) = (void (*)(void *))al_get( &me->children, i );
|
||||
void * data = (void *)al_get( &me->children, i+1 );
|
||||
if( func == &late_free )
|
||||
free( data );
|
||||
}
|
||||
al_destroy( &me->children );
|
||||
free(me);
|
||||
}
|
||||
|
||||
43
halloc.h
43
halloc.h
@@ -1,35 +1,48 @@
|
||||
/** \file halloc.h
|
||||
|
||||
A hierarchical memory allocation system. Works just like talloc
|
||||
A hierarchical memory allocation system. Works mostly like talloc
|
||||
used in Samba, except that an arbitrary block allocated with
|
||||
malloc() can be registered to be freed by halloc_free.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef FISH_HALLOC_H
|
||||
#define FISH_HALLOC_H
|
||||
|
||||
/**
|
||||
Allocate new memory using specified parent memory context. If \c
|
||||
context is null, a new root context is created. Context _must_ be
|
||||
either 0 or the result of a previous call to halloc.
|
||||
Allocate new memory using specified parent memory context. Context
|
||||
_must_ be either 0 or the result of a previous call to halloc.
|
||||
|
||||
If \c context is null, the resulting block must be freed with a
|
||||
call to halloc_free().
|
||||
If \c context is null, the resulting block is a root block, and
|
||||
must be freed with a call to halloc_free().
|
||||
|
||||
If \c context is not null, the resulting memory block must never be
|
||||
If \c context is not null, context must be a halloc root block. the
|
||||
resulting memory block is a child context, and must never be
|
||||
explicitly freed, it will be automatically freed whenever the
|
||||
parent context is freed.
|
||||
parent context is freed. Child blocks can also never be used as the
|
||||
context in calls to halloc_register_function, halloc_free, etc.
|
||||
*/
|
||||
void *halloc( void *context, size_t size );
|
||||
|
||||
/**
|
||||
Make the specified function run whenever context is free'd, using data as argument.
|
||||
|
||||
\c context a halloc root block
|
||||
*/
|
||||
void halloc_register_function( void *context, void (*func)(void *), void *data );
|
||||
|
||||
/**
|
||||
Free memory context and all children contexts. Only root contexts
|
||||
may be freed explicitly.
|
||||
|
||||
All functions registered with halloc_register_function are run in
|
||||
the order they where added. Afterwards, all memory allocated using
|
||||
halloc itself is free'd.
|
||||
|
||||
\c context a halloc root block
|
||||
*/
|
||||
void halloc_free( void *context );
|
||||
|
||||
/**
|
||||
Free the memory pointed to by \c data when the memory pointed to by
|
||||
\c context is free:d. Note that this will _not_ turn the specified
|
||||
memory area into a valid halloc context. Only memory areas created
|
||||
using a call to halloc() can be used as a context.
|
||||
*/
|
||||
void *halloc_register( void *context, void *data );
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
94
halloc_util.c
Normal file
94
halloc_util.c
Normal file
@@ -0,0 +1,94 @@
|
||||
/** \file halloc.c
|
||||
|
||||
A hierarchical memory allocation system. Works just like talloc
|
||||
used in Samba, except that an arbitrary block allocated with
|
||||
malloc() can be registered to be freed by halloc_free.
|
||||
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "common.h"
|
||||
#include "halloc.h"
|
||||
|
||||
void *global_context=0;
|
||||
|
||||
void halloc_util_init()
|
||||
{
|
||||
global_context = halloc( 0, 0 );
|
||||
}
|
||||
|
||||
void halloc_util_destroy()
|
||||
{
|
||||
halloc_free( global_context );
|
||||
}
|
||||
|
||||
array_list_t *al_halloc( void *context )
|
||||
{
|
||||
array_list_t *res = halloc( context, sizeof( array_list_t ) );
|
||||
if( !res )
|
||||
die_mem();
|
||||
al_init( res );
|
||||
halloc_register_function( context, (void (*)(void *)) &al_destroy, res );
|
||||
return res;
|
||||
}
|
||||
|
||||
string_buffer_t *sb_halloc( void *context )
|
||||
{
|
||||
string_buffer_t *res = halloc( context, sizeof( string_buffer_t ) );
|
||||
if( !res )
|
||||
die_mem();
|
||||
sb_init( res );
|
||||
halloc_register_function( context, (void (*)(void *)) &sb_destroy, res );
|
||||
return res;
|
||||
}
|
||||
|
||||
static void halloc_passthrough( void *f )
|
||||
{
|
||||
void (*func)() = (void (*)() )f;
|
||||
func();
|
||||
}
|
||||
|
||||
void halloc_register_function_void( void *context, void (*func)() )
|
||||
{
|
||||
halloc_register_function( context, &halloc_passthrough, (void *)func );
|
||||
}
|
||||
|
||||
void *halloc_register( void *context, void *data )
|
||||
{
|
||||
if( !data )
|
||||
return 0;
|
||||
|
||||
halloc_register_function( context, &free, data );
|
||||
return data;
|
||||
}
|
||||
|
||||
wchar_t *halloc_wcsdup( void *context, wchar_t *in )
|
||||
{
|
||||
size_t len=wcslen(in);
|
||||
wchar_t *out = halloc( context, sizeof( wchar_t)*(len+1));
|
||||
|
||||
if( out == 0 )
|
||||
{
|
||||
die_mem();
|
||||
}
|
||||
memcpy( out, in, sizeof( wchar_t)*(len+1));
|
||||
return out;
|
||||
}
|
||||
|
||||
wchar_t *halloc_wcsndup( void * context, const wchar_t *in, int c )
|
||||
{
|
||||
wchar_t *res = halloc( context, sizeof(wchar_t)*(c+1) );
|
||||
if( res == 0 )
|
||||
{
|
||||
die_mem();
|
||||
}
|
||||
wcslcpy( res, in, c+1 );
|
||||
res[c] = L'\0';
|
||||
return res;
|
||||
}
|
||||
66
halloc_util.h
Normal file
66
halloc_util.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
\file halloc_util.h
|
||||
|
||||
Various halloc-related utility functions.
|
||||
*/
|
||||
|
||||
#ifndef FISH_HALLOC_UTIL_H
|
||||
#define FISH_HALLOC_UTIL_H
|
||||
|
||||
/**
|
||||
This pointer is a valid halloc context that will be freed right
|
||||
before program shutdown. It may be used to allocate memory that
|
||||
should be freed when the program shuts down.
|
||||
*/
|
||||
extern void *global_context;
|
||||
|
||||
/**
|
||||
Create the global_context halloc object
|
||||
*/
|
||||
void halloc_util_init();
|
||||
|
||||
/**
|
||||
Free the global_context halloc object
|
||||
*/
|
||||
void halloc_util_destroy();
|
||||
|
||||
/**
|
||||
Allocate a array_list_t that will be automatically disposed of when
|
||||
the specified context is free'd
|
||||
*/
|
||||
array_list_t *al_halloc( void *context );
|
||||
|
||||
/**
|
||||
Allocate a string_buffer_t that will be automatically disposed of
|
||||
when the specified context is free'd
|
||||
*/
|
||||
string_buffer_t *sb_halloc( void *context );
|
||||
|
||||
/**
|
||||
Register the specified function to run when the specified context
|
||||
is free'd. This function is related to halloc_register_function,
|
||||
but the specified function dowes not take an argument.
|
||||
*/
|
||||
void halloc_register_function_void( void *context, void (*func)() );
|
||||
|
||||
/**
|
||||
Free the memory pointed to by \c data when the memory pointed to by
|
||||
\c context is free:d. Note that this will _not_ turn the specified
|
||||
memory area into a valid halloc context. Only memory areas created
|
||||
using a call to halloc( 0, size ) can be used as a context.
|
||||
*/
|
||||
void *halloc_register( void *context, void *data );
|
||||
|
||||
/**
|
||||
Make a copy of the specified string using memory allocated using
|
||||
halloc and the specified context
|
||||
*/
|
||||
wchar_t *halloc_wcsdup( void *context, wchar_t *str );
|
||||
|
||||
/**
|
||||
Make a copy of the specified substring using memory allocated using
|
||||
halloc and the specified context
|
||||
*/
|
||||
wchar_t *halloc_wcsndup( void * context, const wchar_t *in, int c );
|
||||
|
||||
#endif
|
||||
11
highlight.c
11
highlight.c
@@ -130,10 +130,10 @@ void highlight_shell( wchar_t * buff,
|
||||
/*
|
||||
Command. First check that the command actually exists.
|
||||
*/
|
||||
wchar_t *cmd =
|
||||
(last_type == TOK_STRING) ?
|
||||
expand_one(wcsdup(tok_last( &tok )),EXPAND_SKIP_SUBSHELL | EXPAND_SKIP_VARIABLES) :
|
||||
wcsdup(tok_last( &tok ));
|
||||
wchar_t *cmd = expand_one( 0,
|
||||
wcsdup(tok_last( &tok )),
|
||||
EXPAND_SKIP_SUBSHELL | EXPAND_SKIP_VARIABLES);
|
||||
|
||||
if( cmd == 0 )
|
||||
{
|
||||
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_ERROR;
|
||||
@@ -145,7 +145,6 @@ void highlight_shell( wchar_t * buff,
|
||||
int is_subcommand = 0;
|
||||
int mark = tok_get_pos( &tok );
|
||||
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_COMMAND;
|
||||
|
||||
|
||||
if( parser_is_subcommand( cmd ) )
|
||||
{
|
||||
@@ -248,7 +247,7 @@ void highlight_shell( wchar_t * buff,
|
||||
{
|
||||
case TOK_STRING:
|
||||
{
|
||||
target = expand_one( wcsdup( tok_last( &tok ) ), EXPAND_SKIP_SUBSHELL);
|
||||
target = expand_one( 0, wcsdup( tok_last( &tok ) ), EXPAND_SKIP_SUBSHELL);
|
||||
/*
|
||||
Redirect filename may contain a subshell.
|
||||
If so, it will be ignored/not flagged.
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "reader.h"
|
||||
#include "env.h"
|
||||
#include "sanity.h"
|
||||
#include "signal.h"
|
||||
|
||||
/*
|
||||
The history is implemented using a linked list. Searches are done
|
||||
@@ -102,7 +103,7 @@ static void history_load()
|
||||
|
||||
is_loaded = 1;
|
||||
|
||||
block();
|
||||
signal_block();
|
||||
hash_init2( &used,
|
||||
&hash_wcs_func,
|
||||
&hash_wcs_cmp,
|
||||
@@ -124,7 +125,7 @@ static void history_load()
|
||||
fclose( in_stream );
|
||||
free( fn );
|
||||
free( buff );
|
||||
unblock();
|
||||
signal_unblock();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -181,7 +182,7 @@ static void history_load()
|
||||
free( buff );
|
||||
free( fn );
|
||||
last_loaded = history_last;
|
||||
unblock();
|
||||
signal_unblock();
|
||||
}
|
||||
|
||||
void history_init()
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
|
||||
complete -y btdownloadheadless.py
|
||||
@@ -1,33 +0,0 @@
|
||||
# Bittorrent commands
|
||||
|
||||
for i in btdownloadcurses.py btdownloadheadless.py;
|
||||
complete -c $i -l max_uploads -x -d (_ "Maximum uploads at once")
|
||||
complete -c $i -l keepalive_interval -x -d (_ "Number of seconds between keepalives")
|
||||
complete -c $i -l download_slice_size -x -d (_ "Bytes per request")
|
||||
complete -c $i -l request_backlog -x -d (_ "Requests per pipe")
|
||||
complete -c $i -l max_message_length -x -d (_ "Maximum length prefix encoding")
|
||||
complete -c $i -l ip -d (_ "IP to report to the tracker") -x -a "(__fish_print_addresses)"
|
||||
complete -c $i -l minport -d (_ "Minimum port to listen to")
|
||||
complete -c $i -l maxport -d (_ "Maximum port to listen to")
|
||||
complete -c $i -l responsefile -r -d (_ "File for server response")
|
||||
complete -c $i -l url -x -d (_ "URL to get file from")
|
||||
complete -c $i -l saveas -r -d (_ "Local file target")
|
||||
complete -c $i -l timeout -x -d (_ "Time to close inactive socket")
|
||||
complete -c $i -l timeout_check_interval -x -d (_ "Time between checking timeouts")
|
||||
complete -c $i -l max_slice_length -x -d (_ "Maximum outgoing slice length")
|
||||
complete -c $i -l max_rate_period -x -d (_ "Maximum time to guess rate")
|
||||
complete -c $i -l bind -x -d (_ "IP to bind to locally") -a "(__fish_print_addresses)"
|
||||
complete -c $i -l display_interval -x -d (_ "Time between screen updates")
|
||||
complete -c $i -l rerequest_interval -x -d (_ "Time to wait between requesting more peers")
|
||||
complete -c $i -l min_peers -x -d (_ "Minimum number of peers to not do requesting")
|
||||
complete -c $i -l http_timeout -x -d (_ "Number of seconds before assuming http timeout")
|
||||
complete -c $i -l max_initiate -x -d (_ "Number of peers at which to stop initiating new connections")
|
||||
complete -c $i -l max_allow_in -x -d (_ "Maximum number of connections to allow")
|
||||
complete -c $i -l check_hashes -x -d (_ "Whether to check hashes on disk")
|
||||
complete -c $i -l max_upload_rate -x -d (_ "Maximum kB/s to upload at")
|
||||
complete -c $i -l snub_time -x -d (_ "Seconds to wait for data to come in before assuming choking")
|
||||
complete -c $i -l spew -x -d (_ "Whether to display diagnostic info")
|
||||
complete -c $i -l rarest_first_cutoff -x -d (_ "Number of downloads at which to switch from random to rarest first")
|
||||
complete -c $i -l min_uploads -x -d (_ "Number of uploads to fill out to with optimistic unchokes")
|
||||
complete -c $i -l report_hash_failiures -x -d (_ "Whether to inform the user that hash failures occur")
|
||||
end;
|
||||
@@ -1,53 +0,0 @@
|
||||
#
|
||||
# I don't use CVS, so these completions are probably not all that good.
|
||||
#
|
||||
|
||||
complete -c cvs -x -a 'add' -d (_ "Add a new file/directory to the repository")
|
||||
complete -c cvs -x -a 'admin' -d (_ "Administration front end for rcs")
|
||||
complete -c cvs -x -a 'annotate' -d (_ "Show last revision where each line was modified")
|
||||
complete -c cvs -x -a 'checkout' -d (_ "Checkout sources for editing")
|
||||
complete -c cvs -x -a 'commit' -d (_ "Check files into the repository")
|
||||
complete -c cvs -x -a 'diff' -d (_ "Show differences between revisions")
|
||||
complete -c cvs -x -a 'edit' -d (_ "Get ready to edit a watched file")
|
||||
complete -c cvs -x -a 'editors' -d (_ "See who is editing a watched file")
|
||||
complete -c cvs -x -a 'export' -d (_ "Export sources from CVS, similar to checkout")
|
||||
complete -c cvs -x -a 'history' -d (_ "Show repository access history")
|
||||
complete -c cvs -x -a 'import' -d (_ "Import sources into CVS, using vendor branches")
|
||||
complete -c cvs -x -a 'init' -d (_ "Create a CVS repository if it doesnt exist")
|
||||
complete -c cvs -x -a 'kserver' -d (_ "Kerberos server mode")
|
||||
complete -c cvs -x -a 'log' -d (_ "Print out history information for files")
|
||||
complete -c cvs -x -a 'login' -d (_ "Prompt for password for authenticating server")
|
||||
complete -c cvs -x -a 'logout' -d (_ "Removes entry in .cvspass for remote repository")
|
||||
complete -c cvs -x -a 'pserver' -d (_ "Password server mode")
|
||||
complete -c cvs -x -a 'rannotate' -d (_ "Show last revision where each line of module was modified")
|
||||
complete -c cvs -x -a 'rdiff' -d (_ "Create "patch" format diffs between releases")
|
||||
complete -c cvs -x -a 'release' -d (_ "Indicate that a Module is no longer in use")
|
||||
complete -c cvs -x -a 'remove' -d (_ "Remove an entry from the repository")
|
||||
complete -c cvs -x -a 'rlog' -d (_ "Print out history information for a module")
|
||||
complete -c cvs -x -a 'rtag' -d (_ "Add a symbolic tag to a module")
|
||||
complete -c cvs -x -a 'server' -d (_ "Server mode")
|
||||
complete -c cvs -x -a 'status' -d (_ "Display status information on checked out files")
|
||||
complete -c cvs -x -a 'tag' -d (_ "Add a symbolic tag to checked out version of files")
|
||||
complete -c cvs -x -a 'unedit' -d (_ "Undo an edit command")
|
||||
complete -c cvs -x -a 'update' -d (_ "Bring work tree in sync with repository")
|
||||
complete -c cvs -x -a 'version' -d (_ "Display version and exit")
|
||||
complete -c cvs -x -a 'watch' -d (_ "Set watches")
|
||||
complete -c cvs -x -a 'watchers' -d (_ "See who is watching a file")
|
||||
|
||||
complete -c cvs -x -s H -d (_ "Displays usage information for command")
|
||||
complete -c cvs -x -s Q -d (_ "Cause CVS to be really quiet")
|
||||
complete -c cvs -x -s q -d (_ "Cause CVS to be somewhat quiet")
|
||||
complete -c cvs -x -s r -d (_ "Make checked-out files read-only")
|
||||
complete -c cvs -x -s w -d (_ "Make checked-out files read-write (default)")
|
||||
complete -c cvs -x -s n -d (_ "Do not change any files")
|
||||
complete -c cvs -x -s t -d (_ "Show trace of program execution -- try with -n")
|
||||
complete -c cvs -x -s v -d (_ "Display version and exit")
|
||||
complete -c cvs -x -s T -r -d (_ "Use "tmpdir" for temporary files")
|
||||
complete -c cvs -x -s e -r -d (_ "Use "editor" for editing log information")
|
||||
complete -c cvs -x -s d -r -d (_ "Overrides $CVSROOT as the root of the CVS tree")
|
||||
complete -c cvs -x -s f -d (_ "Do not use the ~/.cvsrc file")
|
||||
complete -c cvs -x -s z -d (_ "Compression level for net traffic") -x -a '1 2 3 4 5 6 7 8 9'
|
||||
complete -c cvs -x -s x -d (_ "Encrypt all net traffic")
|
||||
complete -c cvs -x -s a -d (_ "Authenticate all net traffic")
|
||||
complete -c cvs -x -s s -d (_ "Set CVS user variable") -x
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
complete -y tex
|
||||
@@ -1 +0,0 @@
|
||||
complete -y tex
|
||||
@@ -1,2 +0,0 @@
|
||||
|
||||
complete -y ls
|
||||
@@ -1 +0,0 @@
|
||||
complete -y tex
|
||||
@@ -1,2 +0,0 @@
|
||||
|
||||
complete -y ls
|
||||
@@ -1,105 +0,0 @@
|
||||
#
|
||||
# Completions for the ls command and its aliases
|
||||
#
|
||||
|
||||
# Test if we are using GNU ls
|
||||
|
||||
set -l is_gnu
|
||||
ls --version >/dev/null ^/dev/null; and set is_gnu --is-gnu
|
||||
|
||||
set -l cmds -c ls -c ll -c la
|
||||
|
||||
# Shared ls switches
|
||||
|
||||
__fish_gnu_complete $cmds -s a -l all -d (_ "Show hidden") $is_gnu
|
||||
__fish_gnu_complete $cmds -s A -l almost-all -d (_ "Show hidden except . and ..") $is_gnu
|
||||
__fish_gnu_complete $cmds -s F -l classify -d (_ "Append filetype indicator") $is_gnu
|
||||
__fish_gnu_complete $cmds -s H -l dereference-command-line -d (_ "Follow symlinks") $is_gnu
|
||||
__fish_gnu_complete $cmds -s L -l dereference -d (_ "Follow symlinks") $is_gnu
|
||||
__fish_gnu_complete $cmds -s R -l recursive -d (_ "List subdirectory recursively") $is_gnu
|
||||
__fish_gnu_complete $cmds -s b -l escape -d (_ "Octal escapes for non graphic characters") $is_gnu
|
||||
__fish_gnu_complete $cmds -s d -l directory -d (_ "List directories, not their content") $is_gnu
|
||||
__fish_gnu_complete $cmds -s h -l human-readable -d (_ "Human readable sizes") $is_gnu
|
||||
__fish_gnu_complete $cmds -s i -l inode -d (_ "Print inode number of files") $is_gnu
|
||||
__fish_gnu_complete $cmds -s n -l numeric-uid-gid -d (_ "Long format, numeric IDs") $is_gnu
|
||||
__fish_gnu_complete $cmds -s p -l file-type -d (_ "Append filetype indicator") $is_gnu
|
||||
__fish_gnu_complete $cmds -s q -l hide-control-chars -d (_ "Replace non-graphic characters with '?'") $is_gnu
|
||||
__fish_gnu_complete $cmds -s r -l reverse -d (_ "Reverse sort order") $is_gnu
|
||||
__fish_gnu_complete $cmds -s s -l size -d (_ "Print size of files") $is_gnu
|
||||
|
||||
complete $cmds -s C -d (_ "List by columns")
|
||||
complete $cmds -s S -d (_ "Sort by size")
|
||||
complete $cmds -s c -d (_ "Show and sort by ctime")
|
||||
complete $cmds -s f -d (_ "Don't sort")
|
||||
complete $cmds -s g -d (_ "Long format without owner")
|
||||
complete $cmds -s k -d (_ "Set blocksize to 1kB")
|
||||
complete $cmds -s l -d (_ "Long format")
|
||||
complete $cmds -s m -d (_ "Comma separated format")
|
||||
complete $cmds -s t -d (_ "Sort by modification time")
|
||||
complete $cmds -s u -d (_ "Show access time")
|
||||
complete $cmds -s x -d (_ "List entries by lines")
|
||||
complete $cmds -s 1 -d (_ "List one file per line")
|
||||
|
||||
if test -n "$is_gnu"
|
||||
|
||||
# GNU specific features
|
||||
|
||||
complete $cmds -l author -d (_ "Print author")
|
||||
complete $cmds -l blocksize -x -d (_ "Set block size")
|
||||
complete $cmds -s B -l ignore-backups -d (_ "Ignore files ending with ~")
|
||||
complete $cmds -l color -f -a "never always auto" -d (_ "Use colors")
|
||||
complete $cmds -s D -l dired -d (_ "Generate dired output")
|
||||
complete $cmds -l format -x -a "across commas horizontal long single-column verbose vertical" -d (_ "List format")
|
||||
complete $cmds -l full-time -d (_ "Long format, full-iso time")
|
||||
complete $cmds -s G -l no-group -d (_ "Don't print group information")
|
||||
complete $cmds -l si -d (_ "Human readable sizes, powers of 1000")
|
||||
complete $cmds -l dereference-command-line-symlink-to-dir #-d (_ "Follow directory symlinks from command line")
|
||||
complete $cmds -l indicator-style -x -a "none classify file-type" -d (_ "Append filetype indicator")
|
||||
complete $cmds -s I -l ignore -r -d (_ "Skip entries matching pattern")
|
||||
complete $cmds -s N -l literal -d (_ "Print raw entry names")
|
||||
complete $cmds -s o -d (_ "Long format without groups")
|
||||
complete $cmds -l show-control-chars -d (_ "Non graphic as-is")
|
||||
complete $cmds -s Q -l quote-name -d (_ "Enclose entry in quotes")
|
||||
complete $cmds -l quoting-style -x -a "literal locale shell shell-always c escape" -d (_ "Select quoting style")
|
||||
complete $cmds -l sort -x -d (_ "Sort criteria") -a "
|
||||
extension\t'Sort by file extension'
|
||||
none\tDon't\ sort
|
||||
size\t'Sort by size'
|
||||
time\t'Sort by modification time'
|
||||
version\t'Sort by version'
|
||||
status\t'Sort by file status modification time'
|
||||
atime\t'Sort by access time'
|
||||
access\t'Sort by access time'
|
||||
use\t'Sort by access time'
|
||||
"
|
||||
complete $cmds -l time -x -d (_ "Show time type") -a "
|
||||
time\t'Sort by modification time'
|
||||
access\t'Sort by access time'
|
||||
use\t'Sort by use time'
|
||||
ctime\t'Sort by file status modification time'
|
||||
status\t'Sort by status time'
|
||||
"
|
||||
complete $cmds -l time-style -x -a "full-iso long-iso iso locale" -d (_ "Select time style")
|
||||
complete $cmds -s T -l tabsize -x -a "1 2 3 4 5 6 7 8 9 10 11 12" -d (_ "Assume tab stops at each COLS")
|
||||
complete $cmds -s U -d (_ "Do not sort")
|
||||
complete $cmds -s v -d (_ "Sort by version")
|
||||
complete $cmds -s w -l width -x -d (_ "Assume screen width")
|
||||
complete $cmds -s X -d (_ "Sort by extension")
|
||||
complete $cmds -l help -d (_ "Display help and exit")
|
||||
complete $cmds -l version -d (_ "Display version and exit")
|
||||
|
||||
else
|
||||
|
||||
# If not a GNU system, assume we have standard BSD ls features instead
|
||||
|
||||
complete $cmds -s B -d (_ "Octal escapes for non graphic characters")
|
||||
complete $cmds -s G -d (_ "Use colors")
|
||||
complete $cmds -s I -d (_ "Prevent -A from being automatically set for root")
|
||||
complete $cmds -s P -d (_ "Don't follow symlinks")
|
||||
complete $cmds -s T -d (_ "Show modification time")
|
||||
complete $cmds -s W -d (_ "Show whiteouts when scanning directories")
|
||||
complete $cmds -s Z -d (_ "Display each file's MAC label")
|
||||
complete $cmds -s o -d (_ "Include the file flags in a long (-l) output")
|
||||
complete $cmds -s w -d (_ "Print raw entry names")
|
||||
|
||||
end
|
||||
@@ -1 +0,0 @@
|
||||
complete -y tex
|
||||
@@ -1 +0,0 @@
|
||||
complete -y tex
|
||||
@@ -1 +0,0 @@
|
||||
complete -y tex
|
||||
@@ -1 +0,0 @@
|
||||
complete -y tex
|
||||
@@ -1 +0,0 @@
|
||||
complete -y tex
|
||||
@@ -1,7 +0,0 @@
|
||||
set -l cmds -c etex -c tex -c elatex -c latex -c pdflatex -c pdfelatex -c pdftex -c pdfetex -c omega
|
||||
complete $cmds -o help -d (_ "Display help and exit")
|
||||
complete $cmds -o version -d (_ "Display version and exit")
|
||||
complete $cmds -x -a "(
|
||||
__fish_complete_suffix (commandline -ct) .tex '(La)TeX file'
|
||||
)"
|
||||
|
||||
@@ -1,362 +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@
|
||||
|
||||
#
|
||||
# Don't need completions in non-interactive mode
|
||||
#
|
||||
|
||||
if not status --is-interactive
|
||||
exit
|
||||
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
|
||||
#
|
||||
# The naming heuristic is that __fish_complete_* prints completions
|
||||
# and descriptions, while __fish_print_* only prints the completion,
|
||||
# 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
|
||||
|
||||
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_pids -d "Print a list of process identifiers along with brief descriptions"
|
||||
# This may be a bit slower, but it's nice - having the tty displayed is really handy
|
||||
ps --no-heading -o pid,comm,tty --ppid %self -N | sed -r 's/ *([0-9]+) +([^ ].*[^ ]|[^ ]) +([^ ]+)$/\1\t\2 [\3]/' ^/dev/null
|
||||
|
||||
# If the above is too slow, this is faster but a little less useful
|
||||
# pgrep -l -v -P %self | sed 's/ /\t/'
|
||||
end
|
||||
|
||||
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"
|
||||
|
||||
# Print all hosts from /etc/hosts
|
||||
if test -f /etc/hosts
|
||||
sed </etc/hosts -e 's/[0-9.]*\( \|\t\)*\(.*\)/\2/'|sed -e 's/\#.*//'|tr \t \n |grep -v '^$'
|
||||
end
|
||||
# Print nfs servers from /etc/fstab
|
||||
if test -f /etc/fstab
|
||||
grep </etc/fstab "^\([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*\|[a-zA-Z.]*\):"|cut -d : -f 1
|
||||
end
|
||||
|
||||
# Print hosts with known ssh keys
|
||||
cat ~/.ssh/known_hosts{,2} ^/dev/null|cut -d ' ' -f 1| cut -d , -f 1
|
||||
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
|
||||
|
||||
|
||||
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
|
||||
#
|
||||
|
||||
set -l __fish_help_desc (_ "Display help and exit")
|
||||
for i in (builtin -n|grep -vE '(while|for|if|function|switch)' )
|
||||
|
||||
complete -c $i -s h -l help -d $__fish_help_desc
|
||||
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]
|
||||
set str (commandline -tc| sed -ne "s/\(.*$separator\)[^$separator]*/\1/p"|sed -e "s/--.*=//")
|
||||
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]
|
||||
for i in $cmd
|
||||
switch $i
|
||||
case '-*'
|
||||
|
||||
case '*'
|
||||
return 1;
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
function __fish_no_arguments -d "Internal fish function"
|
||||
set -l cmd (commandline -poc) (commandline -tc)
|
||||
set -e cmd[1]
|
||||
for i in $cmd
|
||||
switch $i
|
||||
case '-*'
|
||||
|
||||
case '*'
|
||||
return 1
|
||||
end
|
||||
end
|
||||
return 0
|
||||
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')
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
6
input.c
6
input.c
@@ -55,7 +55,9 @@ implementation in fish is as of yet incomplete.
|
||||
#include "env.h"
|
||||
#include "expand.h"
|
||||
#include "event.h"
|
||||
#include "signal.h"
|
||||
#include "translate.h"
|
||||
#include "output.h"
|
||||
|
||||
static void input_read_inputrc( wchar_t *fn );
|
||||
|
||||
@@ -1085,7 +1087,7 @@ static void input_read_inputrc( wchar_t *fn )
|
||||
int error=0;
|
||||
// fwprintf( stderr, L"read %ls\n", fn );
|
||||
|
||||
block();
|
||||
signal_block();
|
||||
rc = wfopen( fn, "r" );
|
||||
|
||||
if( rc )
|
||||
@@ -1120,7 +1122,7 @@ static void input_read_inputrc( wchar_t *fn )
|
||||
free( buff );
|
||||
fclose( rc );
|
||||
}
|
||||
unblock();
|
||||
signal_unblock();
|
||||
|
||||
inputrc_skip_block_count=0;
|
||||
inputrc_block_count=0;
|
||||
|
||||
2
kill.c
2
kill.c
@@ -136,7 +136,7 @@ static void kill_check_x_buffer()
|
||||
|
||||
for( i=0; i<al_get_count( &list ); i++ )
|
||||
{
|
||||
wchar_t *next_line = escape( (wchar_t *)al_get( &list, i ), 0);
|
||||
wchar_t *next_line = escape( (wchar_t *)al_get( &list, i ), 0 );
|
||||
if( i==0 )
|
||||
{
|
||||
new_cut_buffer = next_line;
|
||||
|
||||
44
main.c
44
main.c
@@ -57,6 +57,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#include "event.h"
|
||||
#include "output.h"
|
||||
#include "translate.h"
|
||||
#include "halloc_util.h"
|
||||
|
||||
/**
|
||||
Parse init files
|
||||
@@ -73,7 +74,8 @@ static int read_init()
|
||||
}
|
||||
|
||||
env_set( L"__fish_help_dir", DOCDIR, 0);
|
||||
|
||||
|
||||
eval( L"builtin cd " DATADIR L"/fish 2>/dev/null; . fish 2>/dev/null", 0, TOP );
|
||||
eval( L"builtin cd " SYSCONFDIR L" 2>/dev/null; . fish 2>/dev/null", 0, TOP );
|
||||
eval( L"builtin cd 2>/dev/null;. .fish 2>/dev/null", 0, TOP );
|
||||
|
||||
@@ -120,6 +122,10 @@ int main( int argc, char **argv )
|
||||
"command", required_argument, 0, 'c'
|
||||
}
|
||||
,
|
||||
{
|
||||
"debug-level", required_argument, 0, 'd'
|
||||
}
|
||||
,
|
||||
{
|
||||
"interactive", no_argument, 0, 'i'
|
||||
}
|
||||
@@ -150,14 +156,14 @@ int main( int argc, char **argv )
|
||||
|
||||
int opt = getopt_long( argc,
|
||||
argv,
|
||||
"hilvc:p:",
|
||||
"hilvc:p:d:",
|
||||
long_options,
|
||||
&opt_index );
|
||||
|
||||
#else
|
||||
int opt = getopt( argc,
|
||||
argv,
|
||||
"hilvc:p:" );
|
||||
"hilvc:p:d:" );
|
||||
#endif
|
||||
if( opt == -1 )
|
||||
break;
|
||||
@@ -172,6 +178,22 @@ int main( int argc, char **argv )
|
||||
is_interactive_session = 0;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
{
|
||||
char *end;
|
||||
int tmp = strtol(optarg, &end, 10);
|
||||
if( tmp >= 0 && tmp <=10 && !*end )
|
||||
{
|
||||
debug_level=tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
debug( 0, _(L"Invalid value '%s' for debug level switch"), optarg );
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'h':
|
||||
cmd = "help";
|
||||
break;
|
||||
@@ -203,16 +225,17 @@ int main( int argc, char **argv )
|
||||
|
||||
my_optind = optind;
|
||||
|
||||
is_login |= strcmp( argv[0], "-fish") == 0;
|
||||
is_login |= (strcmp( argv[0], "-fish") == 0);
|
||||
|
||||
is_interactive_session &= (cmd == 0);
|
||||
is_interactive_session &= (my_optind == argc);
|
||||
is_interactive_session &= isatty(STDIN_FILENO);
|
||||
is_interactive_session |= force_interactive;
|
||||
|
||||
translate_init();
|
||||
common_init();
|
||||
halloc_util_init();
|
||||
|
||||
proc_init();
|
||||
output_init();
|
||||
event_init();
|
||||
exec_init();
|
||||
wutil_init();
|
||||
@@ -230,7 +253,7 @@ int main( int argc, char **argv )
|
||||
wchar_t *cmd_wcs = str2wcs( cmd );
|
||||
res = eval( cmd_wcs, 0, TOP );
|
||||
free(cmd_wcs);
|
||||
reader_exit(0);
|
||||
reader_exit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -293,20 +316,19 @@ int main( int argc, char **argv )
|
||||
|
||||
proc_fire_event( L"PROCESS_EXIT", EVENT_EXIT, getpid(), res );
|
||||
|
||||
complete_destroy();
|
||||
proc_destroy();
|
||||
env_destroy();
|
||||
builtin_destroy();
|
||||
function_destroy();
|
||||
complete_destroy();
|
||||
reader_destroy();
|
||||
parser_destroy();
|
||||
wutil_destroy();
|
||||
common_destroy();
|
||||
exec_destroy();
|
||||
event_destroy();
|
||||
output_destroy();
|
||||
translate_destroy();
|
||||
|
||||
common_destroy();
|
||||
halloc_util_destroy();
|
||||
intern_free_all();
|
||||
|
||||
return res;
|
||||
|
||||
145
output.c
145
output.c
@@ -43,6 +43,7 @@
|
||||
#include "expand.h"
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "halloc_util.h"
|
||||
#include "highlight.h"
|
||||
|
||||
/**
|
||||
@@ -50,6 +51,8 @@
|
||||
*/
|
||||
#define COLORS (sizeof(col)/sizeof(wchar_t *))
|
||||
|
||||
static int writeb_internal( char c );
|
||||
|
||||
/**
|
||||
Names of different colors.
|
||||
*/
|
||||
@@ -101,15 +104,22 @@ static size_t writestr_buff_sz=0;
|
||||
*/
|
||||
static char *writestr_buff = 0;
|
||||
|
||||
void output_init()
|
||||
{
|
||||
}
|
||||
/**
|
||||
The function used for output
|
||||
*/
|
||||
|
||||
void output_destroy()
|
||||
static int (*out)(char c) = &writeb_internal;
|
||||
|
||||
static void output_destroy()
|
||||
{
|
||||
free( writestr_buff );
|
||||
}
|
||||
|
||||
void output_set_writer( int (*writer)(char) )
|
||||
{
|
||||
out = writer;
|
||||
}
|
||||
|
||||
|
||||
void set_color( int c, int c2 )
|
||||
{
|
||||
@@ -133,7 +143,9 @@ void set_color( int c, int c2 )
|
||||
{
|
||||
c = c2 = FISH_COLOR_NORMAL;
|
||||
if( fg )
|
||||
{
|
||||
writembs( tparm( fg, 0 ) );
|
||||
}
|
||||
writembs( exit_attribute_mode );
|
||||
return;
|
||||
}
|
||||
@@ -193,12 +205,14 @@ void set_color( int c, int c2 )
|
||||
if( c==FISH_COLOR_NORMAL )
|
||||
{
|
||||
if( fg )
|
||||
{
|
||||
writembs( tparm( fg, 0 ) );
|
||||
}
|
||||
writembs( exit_attribute_mode );
|
||||
|
||||
last_color2 = FISH_COLOR_NORMAL;
|
||||
}
|
||||
else if( ( c >= 0) && ( c < FISH_COLOR_NORMAL ) )
|
||||
else if( ( c >= 0 ) && ( c < FISH_COLOR_NORMAL ) )
|
||||
{
|
||||
if( fg )
|
||||
{
|
||||
@@ -218,15 +232,15 @@ void set_color( int c, int c2 )
|
||||
writembs( tparm( bg, 0 ) );
|
||||
}
|
||||
|
||||
writembs(exit_attribute_mode);
|
||||
if(( last_color != FISH_COLOR_NORMAL ) && fg )
|
||||
writembs( exit_attribute_mode );
|
||||
if( ( last_color != FISH_COLOR_NORMAL ) && fg )
|
||||
{
|
||||
writembs(tparm( fg, last_color ));
|
||||
writembs( tparm( fg, last_color ) );
|
||||
}
|
||||
|
||||
last_color2 = c2;
|
||||
}
|
||||
else if ((c2 >= 0 ) &&(c2 < FISH_COLOR_NORMAL))
|
||||
else if ( ( c2 >= 0 ) && ( c2 < FISH_COLOR_NORMAL ) )
|
||||
{
|
||||
if( bg )
|
||||
{
|
||||
@@ -237,40 +251,96 @@ void set_color( int c, int c2 )
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
perm_left_cursor and parm_right_cursor don't seem to be properly
|
||||
emulated by many terminal emulators, so we only use plain
|
||||
curor_left, curor_right...
|
||||
*/
|
||||
void move_cursor( int steps )
|
||||
{
|
||||
int i;
|
||||
|
||||
if( !steps )
|
||||
return;
|
||||
|
||||
if( steps < 0 ){
|
||||
for( i=0; i>steps; i--)
|
||||
{
|
||||
writembs(cursor_left);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i=0; i<steps; i++)
|
||||
{
|
||||
writembs(cursor_right);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int writeb_internal( char c )
|
||||
{
|
||||
write( 1, &c, 1 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int writeb( tputs_arg_t b )
|
||||
{
|
||||
out( b );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int writembs( char *str )
|
||||
{
|
||||
#ifdef TPUTS_KLUDGE
|
||||
write( 1, str, strlen(str));
|
||||
while( *str )
|
||||
{
|
||||
out( *str );
|
||||
}
|
||||
#else
|
||||
tputs(str,1,&writeb);
|
||||
tputs(str,1,writeb);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int writech( wint_t ch )
|
||||
{
|
||||
static mbstate_t out_state;
|
||||
char buff[MB_CUR_MAX];
|
||||
size_t bytes = wcrtomb( buff, ch, &out_state );
|
||||
int err;
|
||||
|
||||
while( (err =write( 1, buff, bytes ) ) )
|
||||
mbstate_t state;
|
||||
int i;
|
||||
char buff[MB_CUR_MAX+1];
|
||||
size_t bytes;
|
||||
|
||||
if( ( ch >= ENCODE_DIRECT_BASE) &&
|
||||
( ch < ENCODE_DIRECT_BASE+256) )
|
||||
{
|
||||
if( err >= 0 )
|
||||
break;
|
||||
buff[0] = ch - ENCODE_DIRECT_BASE;
|
||||
bytes=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset( &state, 0, sizeof(state) );
|
||||
bytes= wcrtomb( buff, ch, &state );
|
||||
|
||||
if( errno == EINTR )
|
||||
continue;
|
||||
|
||||
wperror( L"write" );
|
||||
return 1;
|
||||
switch( bytes )
|
||||
{
|
||||
case (size_t)(-1):
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( i=0; i<bytes; i++ )
|
||||
{
|
||||
out( buff[i] );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void writestr( const wchar_t *str )
|
||||
{
|
||||
char *pos;
|
||||
|
||||
// while( *str )
|
||||
// writech( *str++ );
|
||||
|
||||
@@ -292,9 +362,16 @@ void writestr( const wchar_t *str )
|
||||
*/
|
||||
if( writestr_buff_sz < len )
|
||||
{
|
||||
if( !writestr_buff )
|
||||
{
|
||||
halloc_register_function_void( global_context, &output_destroy );
|
||||
}
|
||||
|
||||
writestr_buff = realloc( writestr_buff, len );
|
||||
if( !writestr_buff )
|
||||
{
|
||||
die_mem();
|
||||
}
|
||||
writestr_buff_sz = len;
|
||||
}
|
||||
|
||||
@@ -308,8 +385,10 @@ void writestr( const wchar_t *str )
|
||||
/*
|
||||
Write
|
||||
*/
|
||||
write( 1, writestr_buff, strlen( writestr_buff ) );
|
||||
|
||||
for( pos = writestr_buff; *pos; pos++ )
|
||||
{
|
||||
out( *pos );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -328,7 +407,9 @@ void writestr_ellipsis( const wchar_t *str, int max_width )
|
||||
{
|
||||
int w = wcwidth( *str );
|
||||
if( written+w+wcwidth( ellipsis_char )>max_width )
|
||||
{
|
||||
break;
|
||||
}
|
||||
written+=w;
|
||||
writech( *(str++) );
|
||||
}
|
||||
@@ -386,13 +467,13 @@ int writespace( int c )
|
||||
}
|
||||
else
|
||||
{
|
||||
write( 1, " ", mini(c,8) );
|
||||
if( c>8)
|
||||
int i;
|
||||
|
||||
for( i=0; i<c; i++ )
|
||||
{
|
||||
writespace( c-8);
|
||||
out( ' ' );
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -411,7 +492,11 @@ int output_color_code( const wchar_t *val )
|
||||
}
|
||||
|
||||
if( color >= 0 )
|
||||
{
|
||||
return color;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FISH_COLOR_NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
24
output.h
24
output.h
@@ -80,7 +80,9 @@ void set_color( int c, int c2 );
|
||||
|
||||
/**
|
||||
Write a char * narrow string to FD 1, needed for the terminfo
|
||||
strings.
|
||||
strings. This is usually just a wrapper aound tputs, using writeb
|
||||
as the sending function. But a weird bug on PPC Linux means that on
|
||||
this platform, write is instead used directly.
|
||||
*/
|
||||
int writembs( char *str );
|
||||
|
||||
@@ -117,13 +119,25 @@ int writespace( int c );
|
||||
int output_color_code( const wchar_t *val );
|
||||
|
||||
/**
|
||||
Initialize static data
|
||||
perm_left_cursor and parm_right_cursor don't seem to be defined
|
||||
very often so we use cursor_left and cursor_right as a fallback.
|
||||
*/
|
||||
void output_init();
|
||||
void move_cursor( int steps );
|
||||
|
||||
/**
|
||||
Destroy static data
|
||||
This is for writing process notification messages. Has to write to
|
||||
stdout, so clr_eol and such functions will work correctly. Not an
|
||||
issue since this function is only used in interactive mode anyway.
|
||||
*/
|
||||
void output_destroy();
|
||||
int writeb( tputs_arg_t b );
|
||||
|
||||
/**
|
||||
Set the function used for writing in move_cursor, writespace and
|
||||
set_color and all other output functions in this library. By
|
||||
default, the write call is used to give completely unbuffered
|
||||
output to stdout.
|
||||
*/
|
||||
void output_set_writer( int (*writer)(char) );
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
305
parse_util.c
305
parse_util.c
@@ -1,6 +1,7 @@
|
||||
/** \file parse_util.c
|
||||
|
||||
Various utility functions for parsing a command
|
||||
Various mostly unrelated utility functions related to parsing,
|
||||
loading and evaluating fish code.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@@ -13,6 +14,7 @@
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "util.h"
|
||||
@@ -20,13 +22,30 @@
|
||||
#include "common.h"
|
||||
#include "tokenizer.h"
|
||||
#include "parse_util.h"
|
||||
#include "expand.h"
|
||||
#include "intern.h"
|
||||
#include "exec.h"
|
||||
#include "env.h"
|
||||
#include "wildcard.h"
|
||||
#include "halloc_util.h"
|
||||
|
||||
/**
|
||||
Set of files which have been autoloaded
|
||||
*/
|
||||
static hash_table_t *all_loaded=0;
|
||||
|
||||
int parse_util_lineno( const wchar_t *str, int len )
|
||||
{
|
||||
static int res = 1;
|
||||
static int i=0;
|
||||
/**
|
||||
First cached state
|
||||
*/
|
||||
static const wchar_t *prev_str = 0;
|
||||
static int i=0;
|
||||
static int res = 1;
|
||||
|
||||
/**
|
||||
Second cached state
|
||||
*/
|
||||
static const wchar_t *prev_str2 = 0;
|
||||
static int i2 = 0;
|
||||
static int res2 = 1;
|
||||
@@ -84,7 +103,7 @@ int parse_util_locate_cmdsubst( const wchar_t *in,
|
||||
{
|
||||
if( wcschr( L"\'\"", *pos ) )
|
||||
{
|
||||
wchar_t *end = quote_end( pos );
|
||||
const wchar_t *end = quote_end( pos );
|
||||
if( end && *end)
|
||||
{
|
||||
pos=end;
|
||||
@@ -98,7 +117,7 @@ int parse_util_locate_cmdsubst( const wchar_t *in,
|
||||
{
|
||||
if(( paran_count == 0)&&(paran_begin==0))
|
||||
paran_begin = pos;
|
||||
|
||||
|
||||
paran_count++;
|
||||
}
|
||||
else if( *pos == ')' )
|
||||
@@ -136,16 +155,12 @@ int parse_util_locate_cmdsubst( const wchar_t *in,
|
||||
return 0;
|
||||
}
|
||||
|
||||
*begin = paran_begin;
|
||||
*end = paran_count?in+wcslen(in):paran_end;
|
||||
if( begin )
|
||||
*begin = paran_begin;
|
||||
if( end )
|
||||
*end = paran_count?in+wcslen(in):paran_end;
|
||||
|
||||
/* assert( *begin >= in );
|
||||
assert( *begin < (in+wcslen(in) ) );
|
||||
assert( *end >= *begin );
|
||||
assert( *end < (in+wcslen(in) ) );
|
||||
*/
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -228,7 +243,6 @@ static void job_or_process_extent( const wchar_t *buff,
|
||||
return;
|
||||
|
||||
pos = cursor_pos - (begin - buff);
|
||||
// fwprintf( stderr, L"Subshell extent: %d %d %d\n", begin-buff, end-buff, pos );
|
||||
|
||||
if( a )
|
||||
{
|
||||
@@ -246,14 +260,12 @@ static void job_or_process_extent( const wchar_t *buff,
|
||||
{
|
||||
die_mem();
|
||||
}
|
||||
// fwprintf( stderr, L"Strlen: %d\n", wcslen(buffcpy ) );
|
||||
|
||||
for( tok_init( &tok, buffcpy, TOK_ACCEPT_UNFINISHED );
|
||||
tok_has_next( &tok ) && !finished;
|
||||
tok_next( &tok ) )
|
||||
{
|
||||
int tok_begin = tok_get_pos( &tok );
|
||||
// fwprintf( stderr, L".");
|
||||
|
||||
switch( tok_last_type( &tok ) )
|
||||
{
|
||||
@@ -264,8 +276,6 @@ static void job_or_process_extent( const wchar_t *buff,
|
||||
case TOK_END:
|
||||
case TOK_BACKGROUND:
|
||||
{
|
||||
|
||||
// fwprintf( stderr, L"New cmd at %d\n", tok_begin );
|
||||
|
||||
if( tok_begin >= pos )
|
||||
{
|
||||
@@ -284,7 +294,6 @@ static void job_or_process_extent( const wchar_t *buff,
|
||||
}
|
||||
}
|
||||
|
||||
// fwprintf( stderr, L"Res: %d %d\n", *a-buff, *b-buff );
|
||||
free( buffcpy);
|
||||
|
||||
tok_destroy( &tok );
|
||||
@@ -418,5 +427,263 @@ void parse_util_token_extent( const wchar_t *buff,
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Free hash value, but not hash key
|
||||
*/
|
||||
static void clear_hash_value( const void *key, const void *data )
|
||||
{
|
||||
free( (void *)data );
|
||||
}
|
||||
|
||||
/**
|
||||
Part of the autoloader cleanup
|
||||
*/
|
||||
static void clear_loaded_entry( const void *key, const void *data )
|
||||
{
|
||||
hash_table_t *loaded = (hash_table_t *)data;
|
||||
hash_foreach( loaded,
|
||||
&clear_hash_value );
|
||||
hash_destroy( loaded );
|
||||
free( loaded );
|
||||
free( (void *)key );
|
||||
}
|
||||
|
||||
/**
|
||||
The autoloader cleanup function. It is run on shutdown and frees
|
||||
any memory used by the autoloader code to keep track of loaded
|
||||
files.
|
||||
*/
|
||||
static void parse_util_destroy()
|
||||
{
|
||||
if( all_loaded )
|
||||
{
|
||||
hash_foreach( all_loaded,
|
||||
&clear_loaded_entry );
|
||||
|
||||
hash_destroy( all_loaded );
|
||||
free( all_loaded );
|
||||
all_loaded = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void parse_util_load_reset( const wchar_t *path_var )
|
||||
{
|
||||
if( all_loaded )
|
||||
{
|
||||
void *key, *data;
|
||||
hash_remove( all_loaded, path_var, (const void **)&key, (const void **)&data );
|
||||
if( key )
|
||||
clear_loaded_entry( key, data );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
int parse_util_load( const wchar_t *cmd,
|
||||
const wchar_t *path_var_name,
|
||||
void (*on_load)(const wchar_t *cmd),
|
||||
int reload )
|
||||
{
|
||||
static array_list_t *path_list=0;
|
||||
static string_buffer_t *path=0;
|
||||
|
||||
int i;
|
||||
time_t *tm;
|
||||
int reloaded = 0;
|
||||
hash_table_t *loaded;
|
||||
|
||||
const wchar_t *path_var = env_get( path_var_name );
|
||||
|
||||
/*
|
||||
Do we know where to look
|
||||
*/
|
||||
|
||||
if( !path_var )
|
||||
return 0;
|
||||
|
||||
if( !all_loaded )
|
||||
{
|
||||
all_loaded = malloc( sizeof( hash_table_t ) );
|
||||
halloc_register_function_void( global_context, &parse_util_destroy );
|
||||
if( !all_loaded )
|
||||
{
|
||||
die_mem();
|
||||
}
|
||||
hash_init( all_loaded, &hash_wcs_func, &hash_wcs_cmp );
|
||||
}
|
||||
|
||||
loaded = (hash_table_t *)hash_get( all_loaded, path_var_name );
|
||||
|
||||
if( !loaded )
|
||||
{
|
||||
loaded = malloc( sizeof( hash_table_t ) );
|
||||
if( !loaded )
|
||||
{
|
||||
die_mem();
|
||||
}
|
||||
hash_init( loaded, &hash_wcs_func, &hash_wcs_cmp );
|
||||
hash_put( all_loaded, wcsdup(path_var_name), loaded );
|
||||
}
|
||||
|
||||
/*
|
||||
Get modification time of file
|
||||
*/
|
||||
tm = (time_t *)hash_get( loaded, cmd );
|
||||
|
||||
/*
|
||||
Did we just check this?
|
||||
*/
|
||||
if( tm )
|
||||
{
|
||||
if(time(0)-tm[1]<=1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Return if already loaded and we are skipping reloading
|
||||
*/
|
||||
if( !reload && tm )
|
||||
return 0;
|
||||
|
||||
if( !path_list )
|
||||
path_list = al_halloc( global_context);
|
||||
|
||||
if( !path )
|
||||
path = sb_halloc( global_context );
|
||||
else
|
||||
sb_clear( 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[0] != 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 );
|
||||
|
||||
if( on_load )
|
||||
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 );
|
||||
}
|
||||
|
||||
al_foreach( path_list, (void (*)(const void *))&free );
|
||||
al_truncate( path_list, 0 );
|
||||
|
||||
return reloaded;
|
||||
}
|
||||
|
||||
void parse_util_set_argv( wchar_t **argv )
|
||||
{
|
||||
if( *argv )
|
||||
{
|
||||
wchar_t **arg;
|
||||
string_buffer_t sb;
|
||||
sb_init( &sb );
|
||||
|
||||
for( arg=argv; *arg; arg++ )
|
||||
{
|
||||
if( arg != argv )
|
||||
sb_append( &sb, ARRAY_SEP_STR );
|
||||
sb_append( &sb, *arg );
|
||||
}
|
||||
|
||||
env_set( L"argv", (wchar_t *)sb.buff, ENV_LOCAL );
|
||||
sb_destroy( &sb );
|
||||
}
|
||||
else
|
||||
{
|
||||
env_set( L"argv", 0, ENV_LOCAL );
|
||||
}
|
||||
}
|
||||
|
||||
wchar_t *parse_util_unescape_wildcards( const wchar_t *str )
|
||||
{
|
||||
wchar_t *in, *out;
|
||||
wchar_t *unescaped = wcsdup(str);
|
||||
|
||||
if( !unescaped )
|
||||
die_mem();
|
||||
|
||||
for( in=out=unescaped; *in; in++ )
|
||||
{
|
||||
switch( *in )
|
||||
{
|
||||
case L'\\':
|
||||
if( *(in+1) )
|
||||
{
|
||||
in++;
|
||||
*(out++)=*in;
|
||||
}
|
||||
*(out++)=*in;
|
||||
break;
|
||||
|
||||
case L'*':
|
||||
*(out++)=ANY_STRING;
|
||||
break;
|
||||
|
||||
case L'?':
|
||||
*(out++)=ANY_CHAR;
|
||||
break;
|
||||
|
||||
default:
|
||||
*(out++)=*in;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return unescaped;
|
||||
}
|
||||
|
||||
|
||||
74
parse_util.h
74
parse_util.h
@@ -1,6 +1,7 @@
|
||||
/** \file parse_util.h
|
||||
|
||||
Various utility functions for parsing a command
|
||||
Various mostly unrelated utility functions related to parsing,
|
||||
loading and evaluating fish code.
|
||||
*/
|
||||
|
||||
#ifndef FISH_PARSE_UTIL_H
|
||||
@@ -9,7 +10,7 @@
|
||||
#include <wchar.h>
|
||||
|
||||
/**
|
||||
Locate the first subshell in the specified string.
|
||||
Find the beginning and end of the first subshell in the specified string.
|
||||
|
||||
\param in the string to search for subshells
|
||||
\param begin the starting paranthesis of the subshell
|
||||
@@ -23,23 +24,54 @@ int parse_util_locate_cmdsubst( const wchar_t *in,
|
||||
const wchar_t **end,
|
||||
int allow_incomplete );
|
||||
|
||||
/**
|
||||
Find the beginning and end of the command substitution under the cursor
|
||||
|
||||
\param buff the string to search for subshells
|
||||
\param cursor_pos the position of the cursor
|
||||
\param a the start of the searched string
|
||||
\param b the end of the searched string
|
||||
*/
|
||||
void parse_util_cmdsubst_extent( const wchar_t *buff,
|
||||
int cursor_pos,
|
||||
const wchar_t **a,
|
||||
const wchar_t **b );
|
||||
|
||||
/**
|
||||
Find the beginning and end of the process definition under the cursor
|
||||
|
||||
\param buff the string to search for subshells
|
||||
\param cursor_pos the position of the cursor
|
||||
\param a the start of the searched string
|
||||
\param b the end of the searched string
|
||||
*/
|
||||
void parse_util_process_extent( const wchar_t *buff,
|
||||
int pos,
|
||||
int cursor_pos,
|
||||
const wchar_t **a,
|
||||
const wchar_t **b );
|
||||
|
||||
|
||||
/**
|
||||
Find the beginning and end of the job definition under the cursor
|
||||
|
||||
\param buff the string to search for subshells
|
||||
\param cursor_pos the position of the cursor
|
||||
\param a the start of the searched string
|
||||
\param b the end of the searched string
|
||||
*/
|
||||
void parse_util_job_extent( const wchar_t *buff,
|
||||
int pos,
|
||||
int cursor_pos,
|
||||
const wchar_t **a,
|
||||
const wchar_t **b );
|
||||
|
||||
/**
|
||||
Find the beginning and end of the token under the cursor
|
||||
|
||||
\param buff the string to search for subshells
|
||||
\param cursor_pos the position of the cursor
|
||||
\param a the start of the searched string
|
||||
\param b the end of the searched string
|
||||
*/
|
||||
void parse_util_token_extent( const wchar_t *buff,
|
||||
int cursor_pos,
|
||||
const wchar_t **tok_begin,
|
||||
@@ -47,7 +79,41 @@ void parse_util_token_extent( const wchar_t *buff,
|
||||
const wchar_t **prev_begin,
|
||||
const wchar_t **prev_end );
|
||||
|
||||
|
||||
/**
|
||||
Get the linenumber at the specified character offset
|
||||
*/
|
||||
int parse_util_lineno( const wchar_t *str, int len );
|
||||
|
||||
/**
|
||||
Autoload the specified file, if it exists in the specified path. Do
|
||||
not load it multiple times unless it's timestamp changes.
|
||||
|
||||
\param cmd the filename to search for. The suffix '.fish' is always added to this name
|
||||
\param path_var_name the name of an environment variable containing a search path
|
||||
\param on_load a callback function to run if a suitable file is found, which has not already been run
|
||||
\param reload wheter to recheck file timestamps on already loaded files
|
||||
*/
|
||||
int parse_util_load( const wchar_t *cmd,
|
||||
const wchar_t *path_var_name,
|
||||
void (*on_load)(const wchar_t *cmd),
|
||||
int reload );
|
||||
|
||||
/**
|
||||
Reset the loader for the specified path variable
|
||||
*/
|
||||
void parse_util_load_reset( const wchar_t *path_var );
|
||||
|
||||
/**
|
||||
Set the argv environment variable to the specified null-terminated
|
||||
array of strings.
|
||||
*/
|
||||
void parse_util_set_argv( wchar_t **argv );
|
||||
|
||||
/**
|
||||
Make a duplicate of the specified string, unescape wildcard
|
||||
characters but not performing any other character transformation.
|
||||
*/
|
||||
wchar_t *parse_util_unescape_wildcards( const wchar_t *in );
|
||||
|
||||
#endif
|
||||
|
||||
327
parser.c
327
parser.c
@@ -39,6 +39,7 @@ The fish parser. Contains functions for parsing code.
|
||||
#include "intern.h"
|
||||
#include "parse_util.h"
|
||||
#include "halloc.h"
|
||||
#include "halloc_util.h"
|
||||
|
||||
/**
|
||||
Maximum number of block levels in code. This is not the same as
|
||||
@@ -70,9 +71,9 @@ The fish parser. Contains functions for parsing code.
|
||||
#define TOK_ERR_MSG _( L"Tokenizer error: '%ls'")
|
||||
|
||||
/**
|
||||
Error message for short circut command error.
|
||||
Error message for short circuit command error.
|
||||
*/
|
||||
#define COND_ERR_MSG _( L"Short circut command requires additional command")
|
||||
#define COND_ERR_MSG _( L"Short circuit command requires additional command")
|
||||
|
||||
/**
|
||||
Error message on reaching maximum recusrion depth
|
||||
@@ -340,15 +341,13 @@ static int block_count( block_t *b )
|
||||
void parser_push_block( int type )
|
||||
{
|
||||
block_t *new = halloc( 0, sizeof( block_t ));
|
||||
|
||||
|
||||
new->src_lineno = parser_get_lineno();
|
||||
new->src_filename = parser_current_filename()?intern(parser_current_filename()):0;
|
||||
|
||||
// debug( 3, L"Block push %ls %d\n", parser_get_block_desc(type), block_count( current_block)+1 );
|
||||
|
||||
new->outer = current_block;
|
||||
new->type = (current_block && current_block->skip)?FAKE:type;
|
||||
|
||||
|
||||
/*
|
||||
New blocks should be skipped if the outer block is skipped,
|
||||
except TOP ans SUBST block, which open up new environments. Fake
|
||||
@@ -356,12 +355,15 @@ void parser_push_block( int type )
|
||||
*/
|
||||
new->skip=current_block?current_block->skip:0;
|
||||
if( type == TOP || type == SUBST )
|
||||
{
|
||||
new->skip = 0;
|
||||
}
|
||||
if( type == FAKE )
|
||||
{
|
||||
new->skip = 1;
|
||||
|
||||
}
|
||||
|
||||
new->job = 0;
|
||||
|
||||
new->loop_status=LOOP_NORMAL;
|
||||
|
||||
current_block = new;
|
||||
@@ -371,20 +373,12 @@ void parser_push_block( int type )
|
||||
(new->type != TOP) )
|
||||
{
|
||||
env_push( type == FUNCTION_CALL );
|
||||
halloc_register_function_void( current_block, &env_pop );
|
||||
}
|
||||
}
|
||||
|
||||
void parser_pop_block()
|
||||
{
|
||||
// debug( 3, L"Block pop %ls %d\n", parser_get_block_desc(current_block->type), block_count(current_block)-1 );
|
||||
|
||||
if( (current_block->type != FUNCTION_DEF ) &&
|
||||
(current_block->type != FAKE) &&
|
||||
(current_block->type != TOP) )
|
||||
{
|
||||
env_pop();
|
||||
}
|
||||
|
||||
block_t *old = current_block;
|
||||
current_block = current_block->outer;
|
||||
halloc_free( old );
|
||||
@@ -470,7 +464,7 @@ int parser_is_subcommand( const wchar_t *cmd )
|
||||
Test if the specified string is command that opens a new block
|
||||
*/
|
||||
|
||||
static int parser_is_block( wchar_t *word)
|
||||
static int parser_is_block( const wchar_t *word)
|
||||
{
|
||||
return contains_str( word,
|
||||
L"for",
|
||||
@@ -482,7 +476,7 @@ static int parser_is_block( wchar_t *word)
|
||||
(void *)0 );
|
||||
}
|
||||
|
||||
int parser_is_reserved( wchar_t *word)
|
||||
int parser_is_reserved( const wchar_t *word)
|
||||
{
|
||||
return parser_is_block(word) ||
|
||||
parser_is_subcommand( word ) ||
|
||||
@@ -605,7 +599,7 @@ wchar_t *parser_cdpath_get( wchar_t *dir )
|
||||
return 0;
|
||||
|
||||
|
||||
if( dir[0] == L'/' )
|
||||
if( dir[0] == L'/'|| (wcsncmp( dir, L"./", 2 )==0) )
|
||||
{
|
||||
struct stat buf;
|
||||
if( wstat( dir, &buf ) == 0 )
|
||||
@@ -714,9 +708,9 @@ wchar_t *get_filename( const wchar_t *cmd )
|
||||
{
|
||||
wchar_t *path;
|
||||
|
||||
debug( 2, L"get_filename( '%ls' )", cmd );
|
||||
debug( 3, L"get_filename( '%ls' )", cmd );
|
||||
|
||||
if(wcschr( cmd, '/' ) != 0 )
|
||||
if(wcschr( cmd, L'/' ) != 0 )
|
||||
{
|
||||
if( waccess( cmd, X_OK )==0 )
|
||||
{
|
||||
@@ -744,11 +738,10 @@ wchar_t *get_filename( const wchar_t *cmd )
|
||||
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 );
|
||||
@@ -757,9 +750,9 @@ wchar_t *get_filename( const wchar_t *cmd )
|
||||
{
|
||||
int path_len = wcslen( nxt_path );
|
||||
wcscpy( new_cmd, nxt_path );
|
||||
if( new_cmd[path_len-1] != '/' )
|
||||
if( new_cmd[path_len-1] != L'/' )
|
||||
{
|
||||
new_cmd[path_len++]='/';
|
||||
new_cmd[path_len++]=L'/';
|
||||
}
|
||||
wcscpy( &new_cmd[path_len], cmd );
|
||||
if( waccess( new_cmd, X_OK )==0 )
|
||||
@@ -768,7 +761,9 @@ wchar_t *get_filename( const wchar_t *cmd )
|
||||
if( wstat( new_cmd, &buff )==-1 )
|
||||
{
|
||||
if( errno != EACCES )
|
||||
{
|
||||
wperror( L"stat" );
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if( S_ISREG(buff.st_mode) )
|
||||
@@ -787,10 +782,12 @@ wchar_t *get_filename( const wchar_t *cmd )
|
||||
case ENOTDIR:
|
||||
break;
|
||||
default:
|
||||
{
|
||||
debug( 1,
|
||||
MISSING_COMMAND_ERR_MSG,
|
||||
new_cmd );
|
||||
wperror( L"access" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -823,8 +820,10 @@ static void print_profile( array_list_t *p,
|
||||
int my_time;
|
||||
|
||||
if( pos >= al_get_count( p ) )
|
||||
{
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
me= (profile_element_t *)al_get( p, pos );
|
||||
if( !me->skipped )
|
||||
{
|
||||
@@ -834,12 +833,20 @@ static void print_profile( array_list_t *p,
|
||||
{
|
||||
prev = (profile_element_t *)al_get( p, i );
|
||||
if( prev->skipped )
|
||||
{
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
if( prev->level <= me->level )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if( prev->level > me->level+1 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
my_time -= prev->parse;
|
||||
my_time -= prev->exec;
|
||||
}
|
||||
@@ -926,9 +933,9 @@ int eval_args( const wchar_t *line, array_list_t *args )
|
||||
tokenizer *previous_tokenizer=current_tokenizer;
|
||||
int previous_pos=current_tokenizer_pos;
|
||||
int do_loop=1;
|
||||
int was_interactive = is_interactive;
|
||||
|
||||
is_interactive = 0;
|
||||
proc_push_interactive(0);
|
||||
|
||||
current_tokenizer_pos = 0;
|
||||
|
||||
tok_init( &tok, line, 0 );
|
||||
@@ -940,26 +947,27 @@ int eval_args( const wchar_t *line, array_list_t *args )
|
||||
switch(tok_last_type( &tok ) )
|
||||
{
|
||||
case TOK_STRING:
|
||||
switch( expand_string( wcsdup(tok_last( &tok )), args, 0 ) )
|
||||
{
|
||||
wchar_t *tmp = wcsdup(tok_last( &tok ));
|
||||
|
||||
if( !tmp )
|
||||
{
|
||||
case EXPAND_ERROR:
|
||||
{
|
||||
err_pos=tok_get_pos( &tok );
|
||||
do_loop=0;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
die_mem();
|
||||
}
|
||||
|
||||
if( expand_string( 0, tmp, args, 0 ) == EXPAND_ERROR )
|
||||
{
|
||||
err_pos=tok_get_pos( &tok );
|
||||
do_loop=0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case TOK_END:
|
||||
{
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case TOK_ERROR:
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
@@ -972,6 +980,7 @@ int eval_args( const wchar_t *line, array_list_t *args )
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( &tok ),
|
||||
UNEXPECTED_TOKEN_ERR_MSG,
|
||||
@@ -979,16 +988,16 @@ int eval_args( const wchar_t *line, array_list_t *args )
|
||||
|
||||
do_loop=0;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
print_errors();
|
||||
tok_destroy( &tok );
|
||||
|
||||
|
||||
current_tokenizer=previous_tokenizer;
|
||||
current_tokenizer_pos = previous_pos;
|
||||
is_interactive = was_interactive;
|
||||
proc_pop_interactive();
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -1013,27 +1022,37 @@ void parser_stack_trace( block_t *b, string_buffer_t *buff)
|
||||
switch( b->type)
|
||||
{
|
||||
case SOURCE:
|
||||
{
|
||||
sb_printf( buff, _(L"in . (source) call of file '%ls',\n"), b->param1.source_dest );
|
||||
break;
|
||||
}
|
||||
case FUNCTION_CALL:
|
||||
{
|
||||
sb_printf( buff, _(L"in function '%ls',\n"), b->param1.function_name );
|
||||
break;
|
||||
}
|
||||
case SUBST:
|
||||
{
|
||||
sb_printf( buff, _(L"in command substitution\n") );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const wchar_t *file = b->src_filename;
|
||||
|
||||
if( file )
|
||||
{
|
||||
sb_printf( buff,
|
||||
_(L"\tcalled on line %d of file '%ls',\n"),
|
||||
b->src_lineno,
|
||||
file );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb_printf( buff,
|
||||
_(L"\tcalled on standard input,\n") );
|
||||
|
||||
}
|
||||
|
||||
if( b->type == FUNCTION_CALL )
|
||||
{
|
||||
if( b->param2.function_call_process->argv[1] )
|
||||
@@ -1169,7 +1188,7 @@ wchar_t *parser_current_line()
|
||||
/*
|
||||
Calculate line number, line offset, etc.
|
||||
*/
|
||||
for( i=0; i<current_tokenizer_pos; i++ )
|
||||
for( i=0; i<current_tokenizer_pos && whole_str[i]; i++ )
|
||||
{
|
||||
if( whole_str[i] == L'\n' )
|
||||
{
|
||||
@@ -1179,6 +1198,9 @@ wchar_t *parser_current_line()
|
||||
}
|
||||
}
|
||||
|
||||
// lineno = current_tokenizer_pos;
|
||||
|
||||
|
||||
current_line_width=printed_width(whole_str+current_line_start, current_tokenizer_pos-current_line_start );
|
||||
|
||||
if( (function_name = is_function()) )
|
||||
@@ -1318,11 +1340,10 @@ static void parse_job_main_loop( process_t *p,
|
||||
while( 1 )
|
||||
{
|
||||
|
||||
/* debug( 2, L"Read token %ls\n", wcsdup(tok_last( tok )) ); */
|
||||
|
||||
switch( tok_last_type( tok ) )
|
||||
{
|
||||
case TOK_PIPE:
|
||||
{
|
||||
if( (p->type == INTERNAL_EXEC) )
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
@@ -1331,29 +1352,33 @@ static void parse_job_main_loop( process_t *p,
|
||||
return;
|
||||
}
|
||||
p->pipe_fd = wcstol( tok_last( tok ), 0, 10 );
|
||||
p->argv = list_to_char_arr( j, args );
|
||||
if( !p->argv )
|
||||
halloc_register( j, p->argv = list_to_char_arr( args ) );
|
||||
p->next = halloc( j, sizeof( process_t ) );
|
||||
if( p->next == 0 )
|
||||
{
|
||||
die_mem();
|
||||
}
|
||||
tok_next( tok );
|
||||
if( !parse_job( p->next, j, tok ))
|
||||
{
|
||||
/*
|
||||
Don't do anything on failiure. parse_job will notice the error flag beeing set
|
||||
*/
|
||||
|
||||
/*
|
||||
Don't do anything on failiure. parse_job will notice the error flag beeing set
|
||||
*/
|
||||
parse_job( p->next, j, tok );
|
||||
|
||||
}
|
||||
is_finished = 1;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case TOK_BACKGROUND:
|
||||
{
|
||||
j->fg = 0;
|
||||
|
||||
}
|
||||
|
||||
case TOK_END:
|
||||
{
|
||||
p->argv = list_to_char_arr( j, args );
|
||||
if( !p->argv )
|
||||
halloc_register( j, p->argv = list_to_char_arr( args ) );
|
||||
if( tok_has_next(tok))
|
||||
tok_next(tok);
|
||||
|
||||
@@ -1399,7 +1424,7 @@ static void parse_job_main_loop( process_t *p,
|
||||
}
|
||||
|
||||
|
||||
switch( expand_string( wcsdup(tok_last( tok )), args, 0 ) )
|
||||
switch( expand_string( j, wcsdup(tok_last( tok )), args, 0 ) )
|
||||
{
|
||||
case EXPAND_ERROR:
|
||||
{
|
||||
@@ -1420,7 +1445,7 @@ static void parse_job_main_loop( process_t *p,
|
||||
unmatched_wildcard = 1;
|
||||
if( !unmatched )
|
||||
{
|
||||
unmatched = halloc_register( j, wcsdup( tok_last( tok )));
|
||||
unmatched = halloc_wcsdup( j, tok_last( tok ));
|
||||
unmatched_pos = tok_get_pos( tok );
|
||||
}
|
||||
|
||||
@@ -1487,7 +1512,7 @@ static void parse_job_main_loop( process_t *p,
|
||||
{
|
||||
case TOK_STRING:
|
||||
{
|
||||
target = (wchar_t *)halloc_register( j, expand_one( wcsdup( tok_last( tok ) ), 0));
|
||||
target = (wchar_t *)expand_one( j, wcsdup( tok_last( tok ) ), 0);
|
||||
|
||||
if( target == 0 && error_code == 0 )
|
||||
{
|
||||
@@ -1634,35 +1659,35 @@ static int parse_job( process_t *p,
|
||||
job_t *j,
|
||||
tokenizer *tok )
|
||||
{
|
||||
array_list_t args; // The list that will become the argc array for the program
|
||||
array_list_t *args = al_halloc( j ); // The list that will become the argc array for the program
|
||||
int use_function = 1; // May functions be considered when checking what action this command represents
|
||||
int use_builtin = 1; // May builtins be considered when checking what action this command represents
|
||||
int is_new_block=0; // Does this command create a new block?
|
||||
|
||||
block_t *prev_block = current_block;
|
||||
|
||||
al_init( &args );
|
||||
int prev_tokenizer_pos = current_tokenizer_pos;
|
||||
|
||||
current_tokenizer_pos = tok_get_pos( tok );
|
||||
|
||||
while( al_get_count( &args ) == 0 )
|
||||
while( al_get_count( args ) == 0 )
|
||||
{
|
||||
wchar_t *nxt=0;
|
||||
switch( tok_last_type( tok ))
|
||||
{
|
||||
case TOK_STRING:
|
||||
{
|
||||
nxt = expand_one( wcsdup(tok_last( tok )),
|
||||
nxt = expand_one( j,
|
||||
wcsdup(tok_last( tok )),
|
||||
EXPAND_SKIP_SUBSHELL | EXPAND_SKIP_VARIABLES);
|
||||
|
||||
|
||||
if( nxt == 0 )
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( tok ),
|
||||
ILLEGAL_CMD_ERR_MSG,
|
||||
tok_last( tok ) );
|
||||
|
||||
al_destroy( &args );
|
||||
|
||||
current_tokenizer_pos = prev_tokenizer_pos;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
@@ -1675,7 +1700,7 @@ static int parse_job( process_t *p,
|
||||
TOK_ERR_MSG,
|
||||
tok_last(tok) );
|
||||
|
||||
al_destroy( &args );
|
||||
current_tokenizer_pos = prev_tokenizer_pos;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1697,7 +1722,7 @@ static int parse_job( process_t *p,
|
||||
tok_get_desc( tok_last_type(tok) ) );
|
||||
}
|
||||
|
||||
al_destroy( &args );
|
||||
current_tokenizer_pos = prev_tokenizer_pos;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1708,13 +1733,16 @@ static int parse_job( process_t *p,
|
||||
CMD_ERR_MSG,
|
||||
tok_get_desc( tok_last_type(tok) ) );
|
||||
|
||||
al_destroy( &args );
|
||||
current_tokenizer_pos = prev_tokenizer_pos;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int mark = tok_get_pos( tok );
|
||||
|
||||
int consumed = 0;
|
||||
|
||||
|
||||
if( wcscmp( L"command", nxt )==0 )
|
||||
{
|
||||
tok_next( tok );
|
||||
@@ -1726,8 +1754,7 @@ static int parse_job( process_t *p,
|
||||
{
|
||||
use_function = 0;
|
||||
use_builtin=0;
|
||||
free( nxt );
|
||||
continue;
|
||||
consumed=1;
|
||||
}
|
||||
}
|
||||
else if( wcscmp( L"builtin", nxt )==0 )
|
||||
@@ -1740,8 +1767,7 @@ static int parse_job( process_t *p,
|
||||
else
|
||||
{
|
||||
use_function = 0;
|
||||
free( nxt );
|
||||
continue;
|
||||
consumed=1;
|
||||
}
|
||||
}
|
||||
else if( wcscmp( L"not", nxt )==0 )
|
||||
@@ -1754,8 +1780,7 @@ static int parse_job( process_t *p,
|
||||
else
|
||||
{
|
||||
j->negate=1-j->negate;
|
||||
free( nxt );
|
||||
continue;
|
||||
consumed=1;
|
||||
}
|
||||
}
|
||||
else if( wcscmp( L"and", nxt )==0 )
|
||||
@@ -1768,8 +1793,7 @@ static int parse_job( process_t *p,
|
||||
else
|
||||
{
|
||||
j->skip = proc_get_last_status();
|
||||
free( nxt );
|
||||
continue;
|
||||
consumed=1;
|
||||
}
|
||||
}
|
||||
else if( wcscmp( L"or", nxt )==0 )
|
||||
@@ -1782,8 +1806,7 @@ static int parse_job( process_t *p,
|
||||
else
|
||||
{
|
||||
j->skip = !proc_get_last_status();
|
||||
free( nxt );
|
||||
continue;
|
||||
consumed=1;
|
||||
}
|
||||
}
|
||||
else if( wcscmp( L"exec", nxt )==0 )
|
||||
@@ -1793,8 +1816,7 @@ static int parse_job( process_t *p,
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( tok ),
|
||||
EXEC_ERR_MSG );
|
||||
al_destroy( &args );
|
||||
free(nxt);
|
||||
current_tokenizer_pos = prev_tokenizer_pos;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1808,8 +1830,8 @@ static int parse_job( process_t *p,
|
||||
use_function = 0;
|
||||
use_builtin=0;
|
||||
p->type=INTERNAL_EXEC;
|
||||
free( nxt );
|
||||
continue;
|
||||
consumed=1;
|
||||
current_tokenizer_pos = prev_tokenizer_pos;
|
||||
}
|
||||
}
|
||||
else if( wcscmp( L"while", nxt ) ==0 )
|
||||
@@ -1837,10 +1859,8 @@ static int parse_job( process_t *p,
|
||||
current_block->tok_pos = mark;
|
||||
}
|
||||
|
||||
free( nxt );
|
||||
consumed=1;
|
||||
is_new_block=1;
|
||||
|
||||
continue;
|
||||
}
|
||||
else if( wcscmp( L"if", nxt ) ==0 )
|
||||
{
|
||||
@@ -1851,12 +1871,16 @@ static int parse_job( process_t *p,
|
||||
current_block->param1.if_state=0;
|
||||
current_block->tok_pos = mark;
|
||||
|
||||
free( nxt );
|
||||
is_new_block=1;
|
||||
consumed=1;
|
||||
}
|
||||
|
||||
if( consumed )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if( use_function)
|
||||
if( use_function && !current_block->skip )
|
||||
{
|
||||
int nxt_forbidden;
|
||||
wchar_t *forbid;
|
||||
@@ -1885,7 +1909,7 @@ static int parse_job( process_t *p,
|
||||
}
|
||||
}
|
||||
}
|
||||
al_push( &args, nxt );
|
||||
al_push( args, nxt );
|
||||
}
|
||||
|
||||
if( error_code == 0 )
|
||||
@@ -1893,10 +1917,10 @@ static int parse_job( process_t *p,
|
||||
if( !p->type )
|
||||
{
|
||||
if( use_builtin &&
|
||||
builtin_exists( (wchar_t *)al_get( &args, 0 ) ) )
|
||||
builtin_exists( (wchar_t *)al_get( args, 0 ) ) )
|
||||
{
|
||||
p->type = INTERNAL_BUILTIN;
|
||||
is_new_block = parser_is_block( (wchar_t *)al_get( &args, 0 ) );
|
||||
is_new_block = parser_is_block( (wchar_t *)al_get( args, 0 ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1912,7 +1936,7 @@ static int parse_job( process_t *p,
|
||||
}
|
||||
else
|
||||
{
|
||||
p->actual_cmd = halloc_register(j, get_filename( (wchar_t *)al_get( &args, 0 ) ));
|
||||
p->actual_cmd = halloc_register(j, get_filename( (wchar_t *)al_get( args, 0 ) ));
|
||||
|
||||
/*
|
||||
Check if the specified command exists
|
||||
@@ -1926,16 +1950,16 @@ static int parse_job( process_t *p,
|
||||
implicit command.
|
||||
*/
|
||||
wchar_t *pp =
|
||||
parser_cdpath_get( (wchar_t *)al_get( &args, 0 ) );
|
||||
parser_cdpath_get( (wchar_t *)al_get( args, 0 ) );
|
||||
if( pp )
|
||||
{
|
||||
wchar_t *tmp;
|
||||
free( pp );
|
||||
|
||||
tmp = (wchar_t *)al_get( &args, 0 );
|
||||
al_truncate( &args, 0 );
|
||||
al_push( &args, wcsdup( L"cd" ) );
|
||||
al_push( &args, tmp );
|
||||
tmp = (wchar_t *)al_get( args, 0 );
|
||||
al_truncate( args, 0 );
|
||||
al_push( args, wcsdup( L"cd" ) );
|
||||
al_push( args, tmp );
|
||||
/*
|
||||
If we have defined a wrapper around cd, use it,
|
||||
otherwise use the cd builtin
|
||||
@@ -1947,31 +1971,54 @@ static int parse_job( process_t *p,
|
||||
}
|
||||
else
|
||||
{
|
||||
if( wcschr( (wchar_t *)al_get( &args, 0 ), L'=' ) )
|
||||
{
|
||||
error( EVAL_ERROR,
|
||||
tok_get_pos( tok ),
|
||||
COMMAND_ASSIGN_ERR_MSG,
|
||||
(wchar_t *)al_get( &args, 0 ) );
|
||||
int tmp;
|
||||
|
||||
/*
|
||||
We couln't find the specified command.
|
||||
|
||||
What we want to happen now is that the
|
||||
specified job won't get executed, and an
|
||||
error message is printed on-screen, but
|
||||
otherwise, the parsing/execution of the
|
||||
file continues. Because of this, we don't
|
||||
want to call error(), since that would stop
|
||||
execution of the file. Instead we let
|
||||
p->actual_command be 0 (null), which will
|
||||
cause the job to silently not execute. We
|
||||
also print an error message.
|
||||
*/
|
||||
if( wcschr( (wchar_t *)al_get( args, 0 ), L'=' ) )
|
||||
{
|
||||
debug( 0,
|
||||
COMMAND_ASSIGN_ERR_MSG,
|
||||
(wchar_t *)al_get( args, 0 ) );
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
error( EVAL_ERROR,
|
||||
tok_get_pos( tok ),
|
||||
debug( 0,
|
||||
_(L"Unknown command '%ls'"),
|
||||
(wchar_t *)al_get( &args, 0 ) );
|
||||
|
||||
(wchar_t *)al_get( args, 0 ) );
|
||||
}
|
||||
|
||||
tmp = current_tokenizer_pos;
|
||||
current_tokenizer_pos = tok_get_pos(tok);
|
||||
|
||||
fwprintf( stderr, L"%ls", parser_current_line() );
|
||||
|
||||
current_tokenizer_pos=tmp;
|
||||
j->skip=1;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( is_new_block )
|
||||
{
|
||||
|
||||
const wchar_t *end=parser_find_end( tok_string( tok ) +
|
||||
current_tokenizer_pos );
|
||||
tokenizer subtok;
|
||||
@@ -1982,6 +2029,7 @@ static int parse_job( process_t *p,
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( tok ),
|
||||
BLOCK_END_ERR_MSG );
|
||||
|
||||
}
|
||||
|
||||
if( !make_sub_block )
|
||||
@@ -2020,8 +2068,7 @@ static int parse_job( process_t *p,
|
||||
end_pos - current_tokenizer_pos);
|
||||
|
||||
p->type = INTERNAL_BLOCK;
|
||||
free( (void *)al_get( &args, 0 ) );
|
||||
al_set( &args, 0, sub_block );
|
||||
al_set( args, 0, sub_block );
|
||||
|
||||
tok_set_pos( tok,
|
||||
end_pos );
|
||||
@@ -2039,27 +2086,19 @@ static int parse_job( process_t *p,
|
||||
|
||||
if( !error_code )
|
||||
{
|
||||
if( p->type == INTERNAL_BUILTIN && parser_skip_arguments( (wchar_t *)al_get(&args, 0) ) )
|
||||
{
|
||||
p->argv = list_to_char_arr( j, &args );
|
||||
// tok_next(tok);
|
||||
if( p->type == INTERNAL_BUILTIN && parser_skip_arguments( (wchar_t *)al_get(args, 0) ) )
|
||||
{
|
||||
if( !p->argv )
|
||||
halloc_register( j, p->argv = list_to_char_arr( args ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
parse_job_main_loop( p, j, tok, &args );
|
||||
parse_job_main_loop( p, j, tok, args );
|
||||
}
|
||||
}
|
||||
|
||||
if( error_code )
|
||||
{
|
||||
/*
|
||||
We don't know what the state of the args array and the argv
|
||||
vector is on error, so we do an internal cleanup here.
|
||||
*/
|
||||
al_foreach( &args,
|
||||
(void (*)(const void *))&free );
|
||||
free(p->argv);
|
||||
p->argv=0;
|
||||
/*
|
||||
Make sure the block stack is consistent
|
||||
*/
|
||||
@@ -2067,10 +2106,8 @@ static int parse_job( process_t *p,
|
||||
{
|
||||
parser_pop_block();
|
||||
}
|
||||
|
||||
}
|
||||
al_destroy( &args );
|
||||
|
||||
current_tokenizer_pos = prev_tokenizer_pos;
|
||||
return !error_code;
|
||||
}
|
||||
|
||||
@@ -2143,7 +2180,8 @@ static void eval_job( tokenizer *tok )
|
||||
long long t1=0, t2=0, t3=0;
|
||||
profile_element_t *p=0;
|
||||
int skip = 0;
|
||||
|
||||
int job_begin_pos, prev_tokenizer_pos;
|
||||
|
||||
if( profile )
|
||||
{
|
||||
p=malloc( sizeof(profile_element_t));
|
||||
@@ -2177,6 +2215,8 @@ static void eval_job( tokenizer *tok )
|
||||
|
||||
j->first_process = halloc( j, sizeof( process_t ) );
|
||||
|
||||
job_begin_pos = tok_get_pos( tok );
|
||||
|
||||
if( parse_job( j->first_process, j, tok ) &&
|
||||
j->first_process->argv )
|
||||
{
|
||||
@@ -2188,8 +2228,9 @@ static void eval_job( tokenizer *tok )
|
||||
if( newline )
|
||||
stop_pos = mini( stop_pos, newline - tok_string(tok) );
|
||||
|
||||
j->command = halloc_register( j, wcsndup( tok_string(tok)+start_pos,
|
||||
stop_pos-start_pos ));
|
||||
j->command = halloc_wcsndup( j,
|
||||
tok_string(tok)+start_pos,
|
||||
stop_pos-start_pos );
|
||||
}
|
||||
else
|
||||
j->command = L"";
|
||||
@@ -2210,9 +2251,11 @@ static void eval_job( tokenizer *tok )
|
||||
int was_builtin = 0;
|
||||
// if( j->first_process->type==INTERNAL_BUILTIN && !j->first_process->next)
|
||||
// was_builtin = 1;
|
||||
|
||||
prev_tokenizer_pos = current_tokenizer_pos;
|
||||
current_tokenizer_pos = job_begin_pos;
|
||||
exec( j );
|
||||
|
||||
current_tokenizer_pos = prev_tokenizer_pos;
|
||||
|
||||
/* Only external commands require a new fishd barrier */
|
||||
if( !was_builtin )
|
||||
proc_had_barrier=0;
|
||||
@@ -2334,7 +2377,7 @@ int eval( const wchar_t *cmd, io_data_t *io, int block_type )
|
||||
{
|
||||
forbidden_function = al_new();
|
||||
}
|
||||
|
||||
|
||||
forbid_count = al_get_count( forbidden_function );
|
||||
|
||||
block_io = io;
|
||||
@@ -2573,7 +2616,7 @@ int parser_test( wchar_t * buff,
|
||||
}
|
||||
|
||||
/*
|
||||
The short circut commands requires _two_ additional commands.
|
||||
The short circuit commands requires _two_ additional commands.
|
||||
*/
|
||||
if( contains_str( tok_last( &tok ),
|
||||
L"or",
|
||||
|
||||
2
parser.h
2
parser.h
@@ -257,7 +257,7 @@ int parser_is_subcommand( const wchar_t *cmd );
|
||||
\param word The command name to test
|
||||
\return 1 of the command parameter is a command, 0 otherwise
|
||||
*/
|
||||
int parser_is_reserved( wchar_t *word );
|
||||
int parser_is_reserved( const wchar_t *word );
|
||||
|
||||
/**
|
||||
Returns a string describing the current parser pisition in the format 'FILENAME (line LINE_NUMBER): LINE'.
|
||||
|
||||
24
proc.c
24
proc.c
@@ -54,6 +54,8 @@ Some of the code in this file is based on code from the Glibc manual.
|
||||
#include "event.h"
|
||||
#include "translate.h"
|
||||
#include "halloc.h"
|
||||
#include "halloc_util.h"
|
||||
#include "output.h"
|
||||
|
||||
/**
|
||||
Size of message buffer
|
||||
@@ -76,7 +78,7 @@ static int last_status=0;
|
||||
static sig_atomic_t got_signal=0;
|
||||
|
||||
job_t *first_job=0;
|
||||
int is_interactive=0;
|
||||
int is_interactive=-1;
|
||||
int is_interactive_session=0;
|
||||
int is_subshell=0;
|
||||
int is_block=0;
|
||||
@@ -101,14 +103,18 @@ static string_buffer_t event_pid;
|
||||
*/
|
||||
static string_buffer_t event_status;
|
||||
|
||||
static array_list_t *interactive_stack;
|
||||
|
||||
void proc_init()
|
||||
{
|
||||
interactive_stack = al_halloc( global_context );
|
||||
proc_push_interactive( 0 );
|
||||
al_init( &event.arguments );
|
||||
sb_init( &event_pid );
|
||||
sb_init( &event_status );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Remove job from list of jobs
|
||||
*/
|
||||
@@ -1076,3 +1082,19 @@ void proc_sanity_check()
|
||||
}
|
||||
}
|
||||
|
||||
void proc_push_interactive( int value )
|
||||
{
|
||||
int old = is_interactive;
|
||||
al_push( interactive_stack, (void *)(long)is_interactive );
|
||||
is_interactive = value;
|
||||
if( old != value )
|
||||
signal_set_handlers();
|
||||
}
|
||||
|
||||
void proc_pop_interactive()
|
||||
{
|
||||
int old = is_interactive;
|
||||
is_interactive= (int)(long)al_pop(interactive_stack);
|
||||
if( is_interactive != old )
|
||||
signal_set_handlers();
|
||||
}
|
||||
|
||||
13
proc.h
13
proc.h
@@ -298,7 +298,6 @@ int job_reap( int interactive );
|
||||
*/
|
||||
void job_handle_signal( int signal, siginfo_t *info, void *con );
|
||||
|
||||
|
||||
#ifdef HAVE__PROC_SELF_STAT
|
||||
/**
|
||||
Use the procfs filesystem to look up how many jiffies of cpu time
|
||||
@@ -337,4 +336,16 @@ void proc_init();
|
||||
*/
|
||||
void proc_destroy();
|
||||
|
||||
/**
|
||||
Set new value for is_interactive flag, saving previous value. If
|
||||
needed, update signal handlers.
|
||||
*/
|
||||
void proc_push_interactive( int value );
|
||||
|
||||
/**
|
||||
Set is_interactive flag to the previous value. If needed, update
|
||||
signal handlers.
|
||||
*/
|
||||
void proc_pop_interactive();
|
||||
|
||||
#endif
|
||||
|
||||
71
reader.c
71
reader.c
@@ -567,11 +567,12 @@ static void remove_duplicates( array_list_t *l )
|
||||
|
||||
prev = (wchar_t *)al_get( l, 0 );
|
||||
for( in=1, out=1; in < al_get_count( l ); in++ )
|
||||
{
|
||||
{
|
||||
wchar_t *curr = (wchar_t *)al_get( l, in );
|
||||
|
||||
if( fldcmp( prev, curr )==0 )
|
||||
{
|
||||
free( curr );
|
||||
free( curr );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -606,7 +607,6 @@ void reader_write_title()
|
||||
wchar_t *title;
|
||||
array_list_t l;
|
||||
wchar_t *term = env_get( L"TERM" );
|
||||
int was_interactive = is_interactive;
|
||||
|
||||
/*
|
||||
This is a pretty lame heuristic for detecting terminals that do
|
||||
@@ -628,7 +628,7 @@ void reader_write_title()
|
||||
|
||||
al_init( &l );
|
||||
|
||||
is_interactive = 0;
|
||||
proc_push_interactive(0);
|
||||
if( exec_subshell( title, &l ) != -1 )
|
||||
{
|
||||
int i;
|
||||
@@ -639,8 +639,8 @@ void reader_write_title()
|
||||
}
|
||||
writestr( L"\7" );
|
||||
}
|
||||
is_interactive = was_interactive;
|
||||
|
||||
proc_pop_interactive();
|
||||
|
||||
al_foreach( &l, (void (*)(const void *))&free );
|
||||
al_destroy( &l );
|
||||
set_color( FISH_COLOR_RESET, FISH_COLOR_RESET );
|
||||
@@ -790,8 +790,8 @@ static void write_prompt()
|
||||
|
||||
if( data->prompt )
|
||||
{
|
||||
int was_interactive = is_interactive;
|
||||
is_interactive = 0;
|
||||
proc_push_interactive( 0 );
|
||||
|
||||
if( exec_subshell( data->prompt, &prompt_list ) == -1 )
|
||||
{
|
||||
/* If executing the prompt fails, make sure we at least don't print any junk */
|
||||
@@ -799,7 +799,7 @@ static void write_prompt()
|
||||
al_destroy( &prompt_list );
|
||||
al_init( &prompt_list );
|
||||
}
|
||||
is_interactive = was_interactive;
|
||||
proc_pop_interactive();
|
||||
}
|
||||
|
||||
data->prompt_width=calc_prompt_width( &prompt_list );
|
||||
@@ -835,25 +835,6 @@ static void write_cmdline()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
perm_left_cursor and parm_right_cursor don't seem to be defined as
|
||||
often as cursor_left and cursor_right, so we use this workalike.
|
||||
*/
|
||||
static void move_cursor( int steps )
|
||||
{
|
||||
int i;
|
||||
|
||||
if( steps < 0 ){
|
||||
for( i=0; i>steps; i--)
|
||||
{
|
||||
writembs(cursor_left);
|
||||
}
|
||||
}
|
||||
else
|
||||
for( i=0; i<steps; i++)
|
||||
writembs(cursor_right);
|
||||
}
|
||||
|
||||
|
||||
void reader_init()
|
||||
{
|
||||
@@ -875,10 +856,9 @@ void reader_destroy()
|
||||
|
||||
void reader_exit( int do_exit )
|
||||
{
|
||||
if( is_interactive )
|
||||
if( data )
|
||||
data->end_loop=do_exit;
|
||||
else
|
||||
end_loop=do_exit;
|
||||
end_loop=do_exit;
|
||||
}
|
||||
|
||||
void repaint()
|
||||
@@ -1221,7 +1201,7 @@ static wchar_t get_quote( wchar_t *cmd, int l )
|
||||
|
||||
if( cmd[i] == L'\'' || cmd[i] == L'\"' )
|
||||
{
|
||||
wchar_t *end = quote_end( &cmd[i] );
|
||||
const wchar_t *end = quote_end( &cmd[i] );
|
||||
//fwprintf( stderr, L"Jump %d\n", end-cmd );
|
||||
if(( end == 0 ) || (!*end) || (end-cmd > l))
|
||||
{
|
||||
@@ -1418,6 +1398,7 @@ static void run_pager( wchar_t *prefix, int is_quoted, array_list_t *comp )
|
||||
sb_init( &cmd );
|
||||
sb_printf( &cmd,
|
||||
L"fish_pager %d %ls",
|
||||
// L"valgrind --track-fds=yes --log-file=pager.txt --leak-check=full ./fish_pager %d %ls",
|
||||
is_quoted,
|
||||
prefix_esc );
|
||||
|
||||
@@ -1463,7 +1444,7 @@ static void run_pager( wchar_t *prefix, int is_quoted, array_list_t *comp )
|
||||
|
||||
/**
|
||||
Handle the list of completions. This means the following:
|
||||
|
||||
|
||||
- If the list is empty, flash the terminal.
|
||||
- If the list contains one element, write the whole element, and if
|
||||
the element does not end on a '/', '@', ':', or a '=', also write a trailing
|
||||
@@ -1472,7 +1453,7 @@ static void run_pager( wchar_t *prefix, int is_quoted, array_list_t *comp )
|
||||
the prefix.
|
||||
- If the list contains multiple elements without
|
||||
a common prefix, call run_pager to display a list of completions
|
||||
|
||||
|
||||
\param comp the list of completion strings
|
||||
*/
|
||||
|
||||
@@ -1480,7 +1461,7 @@ static void run_pager( wchar_t *prefix, int is_quoted, array_list_t *comp )
|
||||
static int handle_completions( array_list_t *comp )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
if( al_get_count( comp ) == 0 )
|
||||
{
|
||||
if( flash_screen != 0 )
|
||||
@@ -2056,7 +2037,6 @@ void reader_set_buffer( wchar_t *b, int p )
|
||||
else
|
||||
{
|
||||
data->buff_pos=l;
|
||||
// fwprintf( stderr, L"Pos %d\n", l );
|
||||
}
|
||||
|
||||
reader_super_highlight_me_plenty( data->buff,
|
||||
@@ -2307,7 +2287,6 @@ static int read_i()
|
||||
{
|
||||
prev_end_loop=0;
|
||||
}
|
||||
error_reset();
|
||||
|
||||
}
|
||||
reader_pop();
|
||||
@@ -2793,8 +2772,8 @@ wchar_t *reader_readline()
|
||||
|
||||
case R_CLEAR_SCREEN:
|
||||
{
|
||||
writembs( clear_screen );
|
||||
|
||||
if( clear_screen )
|
||||
writembs( clear_screen );
|
||||
repaint();
|
||||
break;
|
||||
}
|
||||
@@ -2955,7 +2934,6 @@ static int read_ni( int fd )
|
||||
free( buff );
|
||||
res=1;
|
||||
}
|
||||
error_reset();
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -2967,20 +2945,19 @@ int reader_read( int fd )
|
||||
we need to preserve is_interactive, so we save the
|
||||
original state. We also update the signal handlers.
|
||||
*/
|
||||
int shell_was_interactive = is_interactive;
|
||||
|
||||
is_interactive = ((fd == 0) && isatty(STDIN_FILENO));
|
||||
signal_set_handlers();
|
||||
|
||||
proc_push_interactive( ((fd == 0) && isatty(STDIN_FILENO)));
|
||||
|
||||
res= is_interactive?read_i():read_ni( fd );
|
||||
|
||||
/*
|
||||
If the exit command was called in a script, only exit the
|
||||
script, not the program
|
||||
*/
|
||||
if( data )
|
||||
data->end_loop = 0;
|
||||
end_loop = 0;
|
||||
|
||||
is_interactive = shell_was_interactive;
|
||||
signal_set_handlers();
|
||||
|
||||
proc_pop_interactive();
|
||||
return res;
|
||||
}
|
||||
|
||||
2
seq.in
2
seq.in
@@ -1,4 +1,4 @@
|
||||
#!@prefix@/bin/fish
|
||||
#!/usr/bin/env fish
|
||||
#
|
||||
# Fallback implementation of the seq command
|
||||
#
|
||||
|
||||
@@ -12,7 +12,7 @@ complete -c apropos -s h -l help -d (_ "Display help and exit")
|
||||
complete -f -c apropos -s d -l debug -d (_ "Print debugging info")
|
||||
complete -f -c apropos -s v -l verbose -d (_ "Verbose mode")
|
||||
complete -f -c apropos -s r -l regex -d (_ "Keyword as regex")
|
||||
complete -f -c apropos -s w -l wildcard -d (_ "Keyword as wildwards")
|
||||
complete -f -c apropos -s w -l wildcard -d (_ "Keyword as wildcards")
|
||||
complete -f -c apropos -s e -l exact -d (_ "Keyword as exactly match")
|
||||
complete -x -c apropos -s m -l system -d (_ "Search for other system")
|
||||
complete -x -c apropos -s M -l manpath -a '(echo $MANPATH)' -d (_ "Specify man path")
|
||||
1
share/completions/btdownloadcurses.py.fish
Normal file
1
share/completions/btdownloadcurses.py.fish
Normal file
@@ -0,0 +1 @@
|
||||
__fish_complete_bittorrent btdownloadcurses.py
|
||||
1
share/completions/btdownloadheadless.py.fish
Normal file
1
share/completions/btdownloadheadless.py.fish
Normal file
@@ -0,0 +1 @@
|
||||
__fish_complete_bittorrent btdownloadheadless.py
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user