mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-05-21 19:41:14 -03:00
Compare commits
188 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 | ||
|
|
0b044b785a | ||
|
|
ddff3561e3 | ||
|
|
c4dfdfa849 | ||
|
|
08251dcc98 | ||
|
|
57d53c70e3 | ||
|
|
4e77ee4516 | ||
|
|
6291be256b | ||
|
|
e756f7d619 | ||
|
|
cf3d30d4e4 | ||
|
|
585191310b | ||
|
|
530bbfc9ac | ||
|
|
a521fa4165 | ||
|
|
0f76f77173 | ||
|
|
c743ebf211 | ||
|
|
04ce9ecf16 | ||
|
|
bde5921258 | ||
|
|
89ae02976f | ||
|
|
d8382acc74 | ||
|
|
749c44fe27 | ||
|
|
88ec924323 | ||
|
|
7ff069a2e1 | ||
|
|
8e05c8bee8 | ||
|
|
0fa3c15114 | ||
|
|
58667673d9 | ||
|
|
a53a9aa293 | ||
|
|
09402223e8 | ||
|
|
4f947015d2 | ||
|
|
9f3a7543aa | ||
|
|
7ae6805698 | ||
|
|
1401c44a79 | ||
|
|
40ea5987b2 | ||
|
|
6920f039eb | ||
|
|
ff00354305 | ||
|
|
f9c63a142b | ||
|
|
3733fe3997 | ||
|
|
7e3128f097 | ||
|
|
727472d5bd | ||
|
|
3616a23bdd | ||
|
|
f13262d87e | ||
|
|
f71cd494de | ||
|
|
264c065006 | ||
|
|
07c89c71d8 | ||
|
|
19c67db731 | ||
|
|
294da72d11 | ||
|
|
847b6daa34 | ||
|
|
807a0b8dbd | ||
|
|
c3a1473419 | ||
|
|
29707e66e6 | ||
|
|
a97b652046 | ||
|
|
91b46b305d | ||
|
|
fbe66f54aa | ||
|
|
ff03fe7e41 | ||
|
|
06fd1aa9f8 | ||
|
|
5942a6d6c1 | ||
|
|
a781736fb7 | ||
|
|
feabc032f6 | ||
|
|
9f9f7bf95a | ||
|
|
02f638ad2b | ||
|
|
e95effb043 | ||
|
|
7a1a5a6f01 | ||
|
|
bfefe7f262 | ||
|
|
44e8dcd331 | ||
|
|
3580811f8e | ||
|
|
35cf20640f | ||
|
|
eff36003db | ||
|
|
0eab394c24 | ||
|
|
028e1f36a1 | ||
|
|
f59e9baab9 | ||
|
|
1c6f685522 | ||
|
|
c8a36c9889 | ||
|
|
521d09b6d0 | ||
|
|
3efb0bf5cf | ||
|
|
003c4d776f | ||
|
|
00dea8a082 | ||
|
|
7f195b2f23 | ||
|
|
ecc2fbca98 | ||
|
|
631acd529d | ||
|
|
369f1709be | ||
|
|
1505cc3d81 | ||
|
|
78ae6d3bea | ||
|
|
ea81321ccb | ||
|
|
1977d3beb3 | ||
|
|
285984196d | ||
|
|
5f8e6c85e4 | ||
|
|
e01ccb14af | ||
|
|
86b7ae6d21 |
31
INSTALL
31
INSTALL
@@ -2,39 +2,38 @@
|
||||
Known issues
|
||||
============
|
||||
|
||||
Older versions of Doxygen has bugs in the man-page generation which
|
||||
cause the builtin help to render incorrectly. Version 1.2.14 is known
|
||||
to have this problem.
|
||||
Fish currently requires a semi-modern GCC version to
|
||||
compile. Specifically, GCC 2.95.* won't compile fish, but GCC 3.23
|
||||
should work. Fish has not been coded with an C99- or GNU-specific
|
||||
features in mind, so it is hoped that it should be possible to make
|
||||
fish work with other compilers. Patches are welcome.
|
||||
|
||||
In version 1.9.2, the installation prefix for fish rpms and debs has
|
||||
changed from /usr/local to /usr. The package should automatically
|
||||
change any instances of /usr/local/bin/fish in /etc/passwd to
|
||||
/usr/bin/fish, but some programs, like screen, may need to be
|
||||
restarted to notice the changes. You may also run into problems when
|
||||
switching between using a package and personal builds.
|
||||
Older versions of Doxygen has bugs in the man-page generation which
|
||||
cause the builtin help to render incorrectly. Doxygen 1.2.14 is known
|
||||
to have this problem.
|
||||
|
||||
|
||||
Prerequisites
|
||||
=============
|
||||
|
||||
Fish requires the following packages to build:
|
||||
Fish requires the following programs and libraries to build:
|
||||
|
||||
- Doxygen
|
||||
- Curses or Ncurses
|
||||
- GNU make
|
||||
- GCC
|
||||
|
||||
fish also relies on standard unix tools such as cat, cut, grep, sed,
|
||||
whoami and echo. Fish does not support cross-compilation, separate
|
||||
build directories or any other fancy configure options. Use a recent
|
||||
version of Doxygen, since older versions have bugs that make the
|
||||
builtin help pages render incorrectly. Version 1.2.14 is known to be
|
||||
broken.
|
||||
whoami, bc and echo. Fish does not yet support cross-compilation,
|
||||
separate build directories or any other fancy configure options.
|
||||
|
||||
|
||||
Simple install procedure
|
||||
========================
|
||||
|
||||
If you have downloaded the darcs repository of fish, you need to run
|
||||
autoconf.
|
||||
the autoconf command first. Then use the following commands to compile
|
||||
fish:
|
||||
|
||||
% ./configure
|
||||
% make # Compile fish
|
||||
|
||||
278
Makefile.in
278
Makefile.in
@@ -16,6 +16,10 @@
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
|
||||
#
|
||||
# @configure_input@
|
||||
#
|
||||
|
||||
#
|
||||
# Makefile for the fish shell. Can build fish and associated
|
||||
# applications, install them, recalculate dependencies and also create
|
||||
@@ -33,9 +37,9 @@ CC := @CC@
|
||||
INSTALL:=@INSTALL@
|
||||
|
||||
# Compiler flags
|
||||
CFLAGS := @CFLAGS@ @INCLUDEDIR@ -Wall -std=gnu99 -fno-strict-aliasing
|
||||
CFLAGS:=@CFLAGS@ -Wall -std=gnu99 -fno-strict-aliasing
|
||||
CPPFLAGS=@CPPFLAGS@
|
||||
LDFLAGS:= -l@CURSESLIB@ @LIBS@ @LDFLAGS@ @LIBDIR@
|
||||
LDFLAGS:= @LIBS@ @LDFLAGS@
|
||||
|
||||
# Installation directories
|
||||
prefix = @prefix@
|
||||
@@ -44,24 +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
|
||||
input_common.o event.o signal.o io.o translate.o parse_util.o \
|
||||
$(CORE_OBJS)
|
||||
|
||||
# builtin_help.h exists, but builtin_help.c is autogenerated
|
||||
COMMON_OBJS_WITH_HEADER := builtin_help.o
|
||||
@@ -75,20 +80,20 @@ 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
|
||||
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
|
||||
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 \
|
||||
MIME_OBJS := mimedb.o xdgmimealias.o xdgmime.o xdgmimeglob.o \
|
||||
xdgmimeint.o xdgmimemagic.o xdgmimeparent.o wutil.o
|
||||
|
||||
#
|
||||
@@ -119,12 +124,13 @@ BUILTIN_DOC_HDR := $(BUILTIN_DOC_SRC:.txt=.doxygen)
|
||||
# alphabetically, since this is the order in which they will be written
|
||||
# in the help file.
|
||||
#
|
||||
CMD_DOC_SRC := doc_src/count.txt doc_src/dirh.txt doc_src/dirs.txt \
|
||||
doc_src/fish_pager.txt doc_src/fishd.txt doc_src/help.txt \
|
||||
doc_src/mimedb.txt doc_src/nextd.txt doc_src/open.txt \
|
||||
doc_src/popd.txt doc_src/prevd.txt doc_src/psub.txt \
|
||||
doc_src/pushd.txt doc_src/set_color.txt doc_src/trap.txt \
|
||||
doc_src/type.txt doc_src/umask.txt doc_src/vared.txt
|
||||
CMD_DOC_SRC := doc_src/contains.txt doc_src/count.txt doc_src/dirh.txt \
|
||||
doc_src/dirs.txt doc_src/fish_pager.txt doc_src/fishd.txt \
|
||||
doc_src/help.txt doc_src/mimedb.txt doc_src/nextd.txt \
|
||||
doc_src/open.txt doc_src/popd.txt doc_src/prevd.txt \
|
||||
doc_src/psub.txt doc_src/pushd.txt doc_src/set_color.txt \
|
||||
doc_src/trap.txt doc_src/type.txt doc_src/umask.txt \
|
||||
doc_src/vared.txt
|
||||
|
||||
#
|
||||
# Files generated by running doxygen on the files in $(CMD_DOC_SRC)
|
||||
@@ -154,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
|
||||
@@ -187,7 +197,7 @@ all: $(PROGRAMS) user_doc
|
||||
.PHONY: all
|
||||
|
||||
debug:
|
||||
make fish CFLAGS="-O0 -Wno-unused -Werror -g @INCLUDEDIR@ -Wall -std=gnu99 -fno-strict-aliasing"
|
||||
make fish CFLAGS="-O0 -Wno-unused -Werror -g -Wall -std=gnu99 -fno-strict-aliasing"
|
||||
.PHONY: debug
|
||||
|
||||
# User documentation, describing the features of the fish shell.
|
||||
@@ -256,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;\
|
||||
@@ -330,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 \
|
||||
@@ -366,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 \
|
||||
@@ -389,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
|
||||
@@ -444,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
|
||||
@@ -483,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
|
||||
|
||||
@@ -506,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
|
||||
|
||||
@@ -159,6 +159,8 @@ int builtin_ulimit(wchar_t **argv);
|
||||
*/
|
||||
int builtin_complete(wchar_t **argv);
|
||||
|
||||
const wchar_t *builtin_complete_get_temporary_buffer();
|
||||
|
||||
/**
|
||||
This function works like wperror, but it prints its result into
|
||||
the sb_err string_buffer_t instead of to stderr. Used by the builtin
|
||||
|
||||
@@ -24,6 +24,7 @@ Functions used for implementing the commandline builtin.
|
||||
#include "input_common.h"
|
||||
#include "input.h"
|
||||
#include "translate.h"
|
||||
#include "parse_util.h"
|
||||
|
||||
/**
|
||||
Which part of the comandbuffer are we operating on
|
||||
@@ -48,6 +49,26 @@ enum
|
||||
}
|
||||
;
|
||||
|
||||
/**
|
||||
Returns the current commandline buffer.
|
||||
*/
|
||||
static const wchar_t *get_buffer()
|
||||
{
|
||||
const wchar_t *buff = builtin_complete_get_temporary_buffer();
|
||||
if( !buff )
|
||||
buff = reader_get_buffer();
|
||||
return buff;
|
||||
}
|
||||
|
||||
static int get_cursor_pos()
|
||||
{
|
||||
const wchar_t *buff = builtin_complete_get_temporary_buffer();
|
||||
if( buff )
|
||||
return wcslen( buff );
|
||||
else
|
||||
return reader_get_cursor_pos();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Replace/append/insert the selection with/at/after the specified string.
|
||||
@@ -57,14 +78,14 @@ enum
|
||||
\param insert the string to insert
|
||||
\param append_mode can be one of REPLACE_MODE, INSERT_MODE or APPEND_MODE, affects the way the test update is performed
|
||||
*/
|
||||
static void replace_part( wchar_t *begin,
|
||||
wchar_t *end,
|
||||
static void replace_part( const wchar_t *begin,
|
||||
const wchar_t *end,
|
||||
wchar_t *insert,
|
||||
int append_mode )
|
||||
{
|
||||
wchar_t *buff = reader_get_buffer();
|
||||
const wchar_t *buff = get_buffer();
|
||||
string_buffer_t out;
|
||||
int out_pos=reader_get_cursor_pos();
|
||||
int out_pos=get_cursor_pos();
|
||||
|
||||
sb_init( &out );
|
||||
|
||||
@@ -88,7 +109,7 @@ static void replace_part( wchar_t *begin,
|
||||
}
|
||||
case INSERT_MODE:
|
||||
{
|
||||
int cursor = reader_get_cursor_pos() -(begin-buff);
|
||||
int cursor = get_cursor_pos() -(begin-buff);
|
||||
sb_append_substring( &out, begin, cursor );
|
||||
sb_append( &out, insert );
|
||||
sb_append_substring( &out, begin+cursor, end-begin-cursor );
|
||||
@@ -109,8 +130,8 @@ static void replace_part( wchar_t *begin,
|
||||
\param cut_at_cursor whether printing should stop at the surrent cursor position
|
||||
\param tokenize whether the string should be tokenized, printing one string token on every line and skipping non-string tokens
|
||||
*/
|
||||
static void write_part( wchar_t *begin,
|
||||
wchar_t *end,
|
||||
static void write_part( const wchar_t *begin,
|
||||
const wchar_t *end,
|
||||
int cut_at_cursor,
|
||||
int tokenize )
|
||||
{
|
||||
@@ -119,7 +140,7 @@ static void write_part( wchar_t *begin,
|
||||
wchar_t *buff;
|
||||
int pos;
|
||||
|
||||
pos = reader_get_cursor_pos()-(begin-reader_get_buffer());
|
||||
pos = get_cursor_pos()-(begin-get_buffer());
|
||||
|
||||
if( tokenize )
|
||||
{
|
||||
@@ -184,7 +205,7 @@ int builtin_commandline( wchar_t **argv )
|
||||
|
||||
int tokenize = 0;
|
||||
|
||||
if( !reader_get_buffer() )
|
||||
if( !get_buffer() )
|
||||
{
|
||||
sb_append2( sb_err,
|
||||
argv[0],
|
||||
@@ -429,32 +450,42 @@ int builtin_commandline( wchar_t **argv )
|
||||
buffer_part = STRING_MODE;
|
||||
}
|
||||
|
||||
wchar_t *begin, *end;
|
||||
const wchar_t *begin, *end;
|
||||
|
||||
switch( buffer_part )
|
||||
{
|
||||
case STRING_MODE:
|
||||
{
|
||||
begin = reader_get_buffer();
|
||||
begin = get_buffer();
|
||||
end = begin+wcslen(begin);
|
||||
break;
|
||||
}
|
||||
|
||||
case PROCESS_MODE:
|
||||
{
|
||||
reader_current_process_extent( &begin, &end );
|
||||
parse_util_process_extent( get_buffer(),
|
||||
get_cursor_pos(),
|
||||
&begin,
|
||||
&end );
|
||||
break;
|
||||
}
|
||||
|
||||
case JOB_MODE:
|
||||
{
|
||||
reader_current_job_extent( &begin, &end );
|
||||
parse_util_job_extent( get_buffer(),
|
||||
get_cursor_pos(),
|
||||
&begin,
|
||||
&end );
|
||||
break;
|
||||
}
|
||||
|
||||
case TOKEN_MODE:
|
||||
{
|
||||
reader_current_token_extent( &begin, &end, 0, 0 );
|
||||
parse_util_token_extent( get_buffer(),
|
||||
get_cursor_pos(),
|
||||
&begin,
|
||||
&end,
|
||||
0, 0 );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,12 +19,15 @@ Functions used for implementing the complete builtin.
|
||||
#include "complete.h"
|
||||
#include "wgetopt.h"
|
||||
#include "parser.h"
|
||||
#include "reader.h"
|
||||
#include "translate.h"
|
||||
|
||||
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,
|
||||
@@ -235,6 +238,11 @@ static void builtin_complete_remove( array_list_t *cmd,
|
||||
}
|
||||
|
||||
|
||||
const wchar_t *builtin_complete_get_temporary_buffer()
|
||||
{
|
||||
return temporary_buffer;
|
||||
}
|
||||
|
||||
int builtin_complete( wchar_t **argv )
|
||||
{
|
||||
int res=0;
|
||||
@@ -245,11 +253,20 @@ 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;
|
||||
|
||||
array_list_t cmd;
|
||||
array_list_t path;
|
||||
|
||||
static int recursion_level=0;
|
||||
|
||||
if( !is_interactive_session )
|
||||
{
|
||||
debug( 1, _(L"%ls: Command only available in interactive sessions"), argv[0] );
|
||||
}
|
||||
|
||||
al_init( &cmd );
|
||||
al_init( &path );
|
||||
sb_init( &short_opt );
|
||||
@@ -290,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'
|
||||
@@ -317,7 +335,7 @@ int builtin_complete( wchar_t **argv )
|
||||
}
|
||||
,
|
||||
{
|
||||
L"load", required_argument, 0, 'y'
|
||||
L"do-complete", required_argument, 0, 'C'
|
||||
}
|
||||
,
|
||||
{
|
||||
@@ -330,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:",
|
||||
L"a:c:p:s:l:o:d:frxeun:C:",
|
||||
long_options,
|
||||
&opt_index );
|
||||
if( opt == -1 )
|
||||
@@ -347,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 );
|
||||
|
||||
|
||||
@@ -397,22 +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;
|
||||
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;
|
||||
@@ -422,56 +440,85 @@ int builtin_complete( wchar_t **argv )
|
||||
|
||||
}
|
||||
|
||||
if( res != 0 )
|
||||
if( !res )
|
||||
{
|
||||
}
|
||||
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 )
|
||||
if( do_complete )
|
||||
{
|
||||
builtin_complete_remove( &cmd,
|
||||
&path,
|
||||
(wchar_t *)short_opt.buff,
|
||||
&gnu_opt,
|
||||
&old_opt );
|
||||
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;
|
||||
|
||||
}
|
||||
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( (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 );
|
||||
|
||||
|
||||
@@ -509,9 +509,6 @@ int builtin_set( wchar_t **argv )
|
||||
!erase &&
|
||||
!list )
|
||||
{
|
||||
/*
|
||||
Only update the variable scope
|
||||
*/
|
||||
env_set( name, 0, scope );
|
||||
finished = 1;
|
||||
}
|
||||
|
||||
332
common.c
332
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>
|
||||
@@ -59,11 +58,6 @@ parts of fish.
|
||||
#include "wildcard.h"
|
||||
#include "parser.h"
|
||||
|
||||
/**
|
||||
Error message to show on string convertion error
|
||||
*/
|
||||
#define STR2WCS_MSG "fish: Invalid multibyte sequence \'"
|
||||
|
||||
/**
|
||||
The maximum number of minor errors to report. Further errors will be omitted.
|
||||
*/
|
||||
@@ -77,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;
|
||||
@@ -99,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 );
|
||||
@@ -120,7 +101,9 @@ void common_destroy()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void common_init()
|
||||
{
|
||||
}
|
||||
|
||||
wchar_t **list_to_char_arr( array_list_t *l )
|
||||
{
|
||||
@@ -131,38 +114,13 @@ wchar_t **list_to_char_arr( array_list_t *l )
|
||||
die_mem();
|
||||
}
|
||||
for( i=0; i<al_get_count( l ); i++ )
|
||||
{
|
||||
res[i] = (wchar_t *)al_get(l,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;
|
||||
@@ -176,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 */
|
||||
@@ -216,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':
|
||||
@@ -230,7 +184,6 @@ int fgetws2( wchar_t **b, int *len, FILE *f )
|
||||
|
||||
|
||||
}
|
||||
unblock();
|
||||
|
||||
}
|
||||
|
||||
@@ -255,61 +208,115 @@ void sort_list( array_list_t *comp )
|
||||
|
||||
wchar_t *str2wcs( const char *in )
|
||||
{
|
||||
wchar_t *res;
|
||||
wchar_t *out;
|
||||
size_t len = strlen(in);
|
||||
|
||||
res = malloc( sizeof(wchar_t)*(strlen(in)+1) );
|
||||
|
||||
if( !res )
|
||||
out = malloc( sizeof(wchar_t)*(len+1) );
|
||||
|
||||
if( !out )
|
||||
{
|
||||
die_mem();
|
||||
}
|
||||
|
||||
if( (size_t)-1 == mbstowcs( res, in, sizeof(wchar_t)*(strlen(in)) +1) )
|
||||
{
|
||||
error_count++;
|
||||
if( error_count <=error_max )
|
||||
{
|
||||
fflush( stderr );
|
||||
write( 2,
|
||||
STR2WCS_MSG,
|
||||
strlen(STR2WCS_MSG) );
|
||||
write( 2,
|
||||
in,
|
||||
strlen(in ));
|
||||
write( 2,
|
||||
"\'\n",
|
||||
2 );
|
||||
}
|
||||
|
||||
free(res);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
|
||||
return str2wcs_internal( in, out );
|
||||
}
|
||||
|
||||
void error_reset()
|
||||
wchar_t *str2wcs_internal( const char *in, wchar_t *out )
|
||||
{
|
||||
error_count=0;
|
||||
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 );
|
||||
|
||||
switch( res )
|
||||
{
|
||||
case (size_t)(-2):
|
||||
case (size_t)(-1):
|
||||
{
|
||||
out[out_pos] = ENCODE_DIRECT_BASE + (unsigned char)in[in_pos];
|
||||
in_pos++;
|
||||
memset( &state, 0, sizeof(state) );
|
||||
break;
|
||||
}
|
||||
|
||||
case 0:
|
||||
{
|
||||
return out;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
in_pos += res;
|
||||
break;
|
||||
}
|
||||
}
|
||||
out_pos++;
|
||||
}
|
||||
out[out_pos] = 0;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
char *wcs2str( const wchar_t *in )
|
||||
{
|
||||
char *res = malloc( MAX_UTF8_BYTES*wcslen(in)+1 );
|
||||
char *out;
|
||||
|
||||
out = malloc( MAX_UTF8_BYTES*wcslen(in)+1 );
|
||||
|
||||
if( res == 0 )
|
||||
if( !out )
|
||||
{
|
||||
die_mem();
|
||||
}
|
||||
|
||||
wcstombs( res,
|
||||
in,
|
||||
MAX_UTF8_BYTES*wcslen(in)+1 );
|
||||
return wcs2str_internal( in, out );
|
||||
}
|
||||
|
||||
res = realloc( res, strlen( res )+1 );
|
||||
|
||||
return res;
|
||||
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) &&
|
||||
( in[in_pos] < ENCODE_DIRECT_BASE+256) )
|
||||
{
|
||||
out[out_pos++] = in[in_pos]- ENCODE_DIRECT_BASE;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = wcrtomb( &out[out_pos], in[in_pos], &state );
|
||||
|
||||
switch( res )
|
||||
{
|
||||
case (size_t)(-1):
|
||||
{
|
||||
debug( 1, L"Wide character has no narrow representation" );
|
||||
memset( &state, 0, sizeof(state) );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
out_pos += res;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
in_pos++;
|
||||
}
|
||||
out[out_pos] = 0;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
char **wcsv2strv( const wchar_t **in )
|
||||
@@ -508,8 +515,6 @@ int wcsvarname( wchar_t *str )
|
||||
str++;
|
||||
}
|
||||
return 1;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -532,30 +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 )
|
||||
{
|
||||
switch( *in )
|
||||
wchar_t c = *pos;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
case '"':
|
||||
pos++;
|
||||
|
||||
if( !*pos )
|
||||
return 0;
|
||||
|
||||
if( *pos == L'\\')
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
in = wcschr( in+1, L'"' );
|
||||
if( !in )
|
||||
return 0;
|
||||
if( *(in-1) != L'\\' )
|
||||
return (wchar_t *)in;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
case '\'':
|
||||
else
|
||||
{
|
||||
return wcschr( in+1, L'\'' );
|
||||
if( *pos == c )
|
||||
{
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
const wchar_t *wsetlocale(int category, const wchar_t *locale)
|
||||
{
|
||||
|
||||
@@ -618,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()
|
||||
{
|
||||
@@ -752,6 +755,26 @@ wchar_t *escape( const wchar_t *in,
|
||||
|
||||
while( *in != 0 )
|
||||
{
|
||||
|
||||
if( ( *in >= ENCODE_DIRECT_BASE) &&
|
||||
( *in < ENCODE_DIRECT_BASE+256) )
|
||||
{
|
||||
int val = *in - ENCODE_DIRECT_BASE;
|
||||
int tmp;
|
||||
|
||||
*(pos++) = L'\\';
|
||||
*(pos++) = L'X';
|
||||
|
||||
tmp = val/16;
|
||||
*pos++ = tmp > 9? L'a'+(tmp-10):L'0'+tmp;
|
||||
|
||||
tmp = val%16;
|
||||
*pos++ = tmp > 9? L'a'+(tmp-10):L'0'+tmp;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
switch( *in )
|
||||
{
|
||||
case L'\t':
|
||||
@@ -820,6 +843,8 @@ wchar_t *escape( const wchar_t *in,
|
||||
*pos++ = *in;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
in++;
|
||||
}
|
||||
*pos = 0;
|
||||
@@ -895,60 +920,84 @@ wchar_t *unescape( const wchar_t * orig, int unescape_special )
|
||||
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'o':
|
||||
case L'X':
|
||||
{
|
||||
byte=1;
|
||||
max_val = 255;
|
||||
break;
|
||||
}
|
||||
|
||||
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] = res;
|
||||
|
||||
|
||||
if( (res > 0) && (res <= max_val) )
|
||||
{
|
||||
in[out_pos] = (byte?ENCODE_DIRECT_BASE:0)+res;
|
||||
}
|
||||
else
|
||||
{
|
||||
free(in);
|
||||
return 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1103,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;
|
||||
@@ -1141,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'\\';
|
||||
|
||||
48
common.h
48
common.h
@@ -8,6 +8,8 @@
|
||||
*/
|
||||
#define FISH_COMMON_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <wchar.h>
|
||||
#include <termios.h>
|
||||
|
||||
@@ -42,6 +44,11 @@ typedef char tputs_arg_t;
|
||||
*/
|
||||
#define FISH_COLOR_RESET -2
|
||||
|
||||
/**
|
||||
This is in the unicode private use area.
|
||||
*/
|
||||
#define ENCODE_DIRECT_BASE 0xf100
|
||||
|
||||
/**
|
||||
Save the shell mode on startup so we can restore them on exit
|
||||
*/
|
||||
@@ -76,7 +83,10 @@ extern wchar_t *program_name;
|
||||
|
||||
/**
|
||||
Take an array_list_t containing wide strings and converts them to a
|
||||
single null-terminated wchar_t **.
|
||||
single null-terminated wchar_t **. The array is allocated using
|
||||
halloc, and uses the \c context parameter as context. If \c context
|
||||
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( array_list_t *l );
|
||||
|
||||
@@ -104,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
|
||||
@@ -111,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
|
||||
@@ -172,12 +185,12 @@ int my_wcswidth( const wchar_t *c );
|
||||
|
||||
/**
|
||||
This functions returns the end of the quoted substring beginning at
|
||||
\c in. It can handle both single and double quotes. Returns 0 on
|
||||
error.
|
||||
\c in. The type of quoting character is detemrined by examining \c
|
||||
in. Returns 0 on error.
|
||||
|
||||
\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
|
||||
@@ -210,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();
|
||||
|
||||
@@ -252,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
|
||||
@@ -269,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,
|
||||
|
||||
828
complete.c
828
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
|
||||
|
||||
96
configure.ac
96
configure.ac
@@ -1,17 +1,50 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
AC_INIT(fish,1.20.0,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
|
||||
|
||||
AC_MSG_CHECKING([for $i/include include directory])
|
||||
if test -d $i/include; then
|
||||
AC_MSG_RESULT(yes)
|
||||
CPPFLAGS="$CPPFLAGS -I$i/include/"
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([for $i/lib library directory])
|
||||
if test -d $i/lib; then
|
||||
AC_MSG_RESULT(yes)
|
||||
LDFLAGS="$LDFLAGS -L$i/lib/ -R$i/lib/"
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([for $i/bin command directory])
|
||||
if test -d $i/bin; then
|
||||
AC_MSG_RESULT(yes)
|
||||
optbindirs="$optbindirs $i/bin"
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
AC_SUBST( optbindirs, $optbindirs )
|
||||
|
||||
# If needed, run autoheader automatically
|
||||
AC_MSG_CHECKING([if autoheader needs to be run])
|
||||
if test ! -f ./config.h.in -o config.h.in -ot configure.ac; then
|
||||
AC_MSG_RESULT([yes])
|
||||
if which autoheader >/dev/null; then
|
||||
echo running autoheader...
|
||||
AC_MSG_NOTICE([running autoheader])
|
||||
autoheader
|
||||
else
|
||||
echo Could not find the autoheader program in your path.
|
||||
echo This program is needed because the configure.ac file has been modified.
|
||||
echo Please install it and try again.
|
||||
exit 1
|
||||
AC_MSG_ERROR( [cannot find the autoheader program in your path.
|
||||
This program is needed because the configure.ac file has been modified.
|
||||
Please install it and try again.])
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
# Tell autoconf to create config.h header
|
||||
@@ -26,10 +59,9 @@ AC_PROG_INSTALL
|
||||
AC_CHECK_PROG( has_doxygen, [doxygen], "true")
|
||||
|
||||
if ! test $has_doxygen = "true"; then
|
||||
echo Could not find the Doxygen program in your path.
|
||||
echo This program is needed to build fish.
|
||||
echo Please install it and try again.
|
||||
exit 1
|
||||
AC_MSG_ERROR( [cannot find the Doxygen program in your path.
|
||||
This program is needed to build fish.
|
||||
Please install it and try again.])
|
||||
fi
|
||||
|
||||
# Check for seq program. If missing, install fallback shellscript implementation
|
||||
@@ -72,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
|
||||
@@ -84,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])
|
||||
@@ -93,10 +123,6 @@ AC_SUBST( [LOCALEDIR], [$datadir/locale])
|
||||
# See if Linux procfs is present
|
||||
AC_CHECK_FILES([/proc/self/stat])
|
||||
|
||||
# See if NetBSD pkgsrc is installed
|
||||
AC_CHECK_FILE([/usr/pkg/lib],[AC_SUBST(LIBDIR,[-L/usr/pkg/lib\ -R/usr/pkg/lib])])
|
||||
AC_CHECK_FILE([/usr/pkg/include],[AC_SUBST(INCLUDEDIR,[-I/usr/pkg/include])])
|
||||
|
||||
# Check for RLIMIT_AS in sys/resource.h.
|
||||
AC_MSG_CHECKING([for RLIMIT_AS in sys/resource.h])
|
||||
AC_TRY_COMPILE([#include <sys/resource.h>],
|
||||
@@ -146,6 +172,24 @@ else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
# Check if realpath accepts null for its second argument
|
||||
AC_MSG_CHECKING([if realpath accepts null for its second argument])
|
||||
AC_RUN_IFELSE(
|
||||
[AC_LANG_PROGRAM([#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>],
|
||||
[int status; char *res; res = realpath( "somefile", 0 ); status = !(res != 0 || errno == ENOENT); exit( status );])],
|
||||
[have_realpath_null=yes],
|
||||
[have_realpath_null=no] )
|
||||
|
||||
if test "$have_realpath_null" = yes; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE([HAVE_REALPATH_NULL], [1],
|
||||
[Define to 1 if realpath accepts null for its second argument.])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
|
||||
# Check for libraries
|
||||
AC_CHECK_LIB(socket, connect)
|
||||
@@ -153,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.])],
|
||||
@@ -165,6 +209,9 @@ AC_CHECK_FUNCS( wcsdup wcsndup wcslen wcscasecmp wcsncasecmp gettext fwprintf )
|
||||
AC_CHECK_FUNCS( futimes wcwidth wcswidth getopt_long wcstok fputwc fgetwc )
|
||||
AC_CHECK_FUNCS( wcstol dcgettext )
|
||||
|
||||
AC_DEFINE([HAVE_TRANSLATE_H], [1],
|
||||
[Define to 1 if the wgettext function should be used for translating strings.])
|
||||
|
||||
# Check again for gettext library, and insert results into the Makefile
|
||||
AC_CHECK_FUNC(gettext, AC_SUBST(HAVE_GETTEXT,1), AC_SUBST(HAVE_GETTEXT,0) )
|
||||
|
||||
@@ -174,7 +221,7 @@ AC_TRY_LINK([#if HAVE_LIBINTL_H]
|
||||
[#include <libintl.h>]
|
||||
[#endif],
|
||||
[extern int _nl_msg_cat_cntr;]
|
||||
[int tmp = _nl_msg_cat_cntr;], have__nl_msg_cat_cntr=yes, have__nl_msg_cat_cntr=no)
|
||||
[int tmp = _nl_msg_cat_cntr; exit(tmp);], have__nl_msg_cat_cntr=yes, have__nl_msg_cat_cntr=no)
|
||||
if test "$have__nl_msg_cat_cntr" = yes; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE([HAVE__NL_MSG_CAT_CNTR], [1],
|
||||
@@ -184,14 +231,9 @@ else
|
||||
fi
|
||||
|
||||
# Check if we have ncurses, and use it rather than curses if possible.
|
||||
AC_CHECK_HEADERS([ncurses.h],[AC_SUBST(CURSESLIB,[ncurses]) AC_DEFINE(HAVE_NCURSES_H)],[AC_SUBST(CURSESLIB,[curses])])
|
||||
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])] )
|
||||
|
||||
# Force use of ncurses if it is avialable via NetBSD pkgsrc. This is an
|
||||
# ugly kludge to force NetBSD to use ncurses, since NetBSDs own version
|
||||
# does not properly support terminfo.
|
||||
AC_CHECK_FILE([/usr/pkg/include/ncurses.h],[AC_SUBST(CURSESLIB,[ncurses]) AC_DEFINE(HAVE_NCURSES_H)])
|
||||
|
||||
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.
|
||||
|
||||
@@ -43,6 +43,10 @@ Other switches
|
||||
that they will be returned to the reader before any additional
|
||||
actual keypresses are read.
|
||||
|
||||
If commandline is called during a call to complete a given string
|
||||
using <code>complete -C STRING</code>, commandline will consider the
|
||||
specified string to be the current contents of the commandline.
|
||||
|
||||
\subsection commandline-example Example
|
||||
|
||||
<tt>commandline -j $history[3]</tt>
|
||||
|
||||
@@ -14,6 +14,7 @@ the fish manual.
|
||||
- <tt>LONG_OPTION</tt> is a multi character option for the command
|
||||
- <tt>OPTION_ARGUMENTS</tt> is parameter containing a space-separated list of possible option-arguments, which may contain subshells
|
||||
- <tt>DESCRIPTION</tt> is a description of what the option and/or option arguments do
|
||||
- <tt>-C STRING</tt> or <tt>--do-complete=STRING</tt> makes complete try to find all possible completions for the specified string
|
||||
- <tt>-e</tt> or <tt>--erase</tt> implies that the specified completion should be deleted
|
||||
- <tt>-f</tt> or <tt>--no-files</tt> specifies that the option specified by this completion may not be followed by a filename
|
||||
- <tt>-n</tt> or <tt>--condition</tt> specifies a shell command that must return 0 if the completion is to be used. This makes it possible to specify completions that should only be used in some cases.
|
||||
@@ -31,8 +32,8 @@ options, the same styles as the GNU version of the getopt
|
||||
library. These styles are:
|
||||
|
||||
- Short options, like '-a'. Short options are a single character long, are preceded by a single hyphen and may be grouped together (like '-la', which is equivalent to '-l -a'). Option arguments may be specified in the following parameter ('-w 32') or by appending the option with the value ('-w32').
|
||||
- Old style long options, like '-Wall'. Old style long options are more than one character long, are preceded by a single hyphen and may not be grouped together. Option arguments are specified in the following parameter ('-ao null').
|
||||
- GNU style long options, like '--colors'. GNU style long options are more than one character long, are preceded by two hyphens, and may not be grouped together. Option arguments may be specified in the following parameter ('--quoting-style shell') or by appending the option with a '=' and the value ('--quoting-style=shell'). GNU style long options may be abbreviated so long as the abbreviation is unique ('--h' is equivalent to '--help' if help is the only long option beginning with an 'h').
|
||||
- Old style long options, like '-Wall'. Old style long options can be more than one character long, are preceded by a single hyphen and may not be grouped together. Option arguments are specified in the following parameter ('-ao null').
|
||||
- GNU style long options, like '--colors'. GNU style long options can be more than one character long, are preceded by two hyphens, and may not be grouped together. Option arguments may be specified in the following parameter ('--quoting-style shell') or by appending the option with a '=' and the value ('--quoting-style=shell'). GNU style long options may be abbreviated so long as the abbreviation is unique ('--h' is equivalent to '--help' if help is the only long option beginning with an 'h').
|
||||
|
||||
The options for specifying command name, command path, or command
|
||||
switches may all be used multiple times to specify multiple commands
|
||||
|
||||
24
doc_src/contains.txt
Normal file
24
doc_src/contains.txt
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
\section contains contains - Test if a word is present in a list
|
||||
|
||||
\subsection contains-synopsis Synopsis
|
||||
<code>contains [OPTIONS] KEY [VALUES...]</code>
|
||||
|
||||
\subsection contains-description Description
|
||||
|
||||
- \c -h or \c --help display this message
|
||||
|
||||
Test if the set VALUES contains the string KEY. Return status is 0 if
|
||||
yes, 1 otherwise
|
||||
|
||||
|
||||
\subsection contains-example Example
|
||||
<pre>
|
||||
for i in ~/bin /usr/local/bin
|
||||
if not contains \$i \$PATH
|
||||
set PATH \$PATH i
|
||||
end
|
||||
end
|
||||
</pre>
|
||||
|
||||
The above code tests if ~/bin and /usr/local/bin are in the path and if they are not, they are added.
|
||||
1178
doc_src/doc.hdr
1178
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.
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
\section nextd nextd
|
||||
|
||||
\subsection nextd-synopsis Synopsis
|
||||
<tt>nextd [-l] [pos]</tt>
|
||||
<tt>nextd [-l | --list] [pos]</tt>
|
||||
|
||||
\subsection nextd-description Description
|
||||
<tt>nextd</tt> moves forwards <tt>pos</tt> positions in the history of visited directories;
|
||||
if the end of the history has been hit, a warning is printed. If the <tt>-l></tt> flag is
|
||||
specified, the current history is also displayed.
|
||||
\subsection nextd-description Description <tt>nextd</tt> moves
|
||||
forwards <tt>pos</tt> positions in the history of visited directories;
|
||||
if the end of the history has been hit, a warning is printed. If the
|
||||
<code>-l></code> or <code>--list</code> flag is specified, the current
|
||||
history is also displayed.
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
\section prevd prevd
|
||||
|
||||
\subsection prevd-synopsis Synopsis
|
||||
<tt>prevd [-l] [pos]</tt>
|
||||
<tt>prevd [-l | --list] [pos]</tt>
|
||||
|
||||
\subsection prevd-description Description
|
||||
<tt>prevd</tt> moves backwards <tt>pos</tt> positions in the history of visited directories;
|
||||
if the beginning of the history has been hit, a warning is printed. If the <tt>-l</tt> flag
|
||||
is specified, the current history is also displayed.
|
||||
\subsection prevd-description Description <tt>prevd</tt> moves
|
||||
backwards <tt>pos</tt> positions in the history of visited
|
||||
directories; if the beginning of the history has been hit, a warning
|
||||
is printed. If the <code>-l</code> or <code>--list</code> flag is
|
||||
specified, the current history is also displayed.
|
||||
|
||||
@@ -27,8 +27,14 @@ If a variable is set to more than one value, the variable will be an
|
||||
array with the specified elements. If a variable is set to zero
|
||||
elements, it will become an array with zero elements.
|
||||
|
||||
If the variable name is one or more array elements, such as <code>PATH[1
|
||||
3 7]</code>, only those array elements specified will be changed.
|
||||
If the variable name is one or more array elements, such as
|
||||
<code>PATH[1 3 7]</code>, only those array elements specified will be
|
||||
changed.
|
||||
|
||||
The set command requires all switch arguments to come before any
|
||||
non-switch arguments. For example, <code>set flags -l</code> will have
|
||||
the effect of setting the value of the variable <code>flags</code> to
|
||||
'-l', not making the variable local.
|
||||
|
||||
\subsection set-example Example
|
||||
|
||||
|
||||
2
env.c
2
env.c
@@ -386,7 +386,7 @@ static void setup_path()
|
||||
path = env_get( L"PATH" );
|
||||
if( !path )
|
||||
{
|
||||
env_set( L"PATH", 0, ENV_EXPORT | ENV_GLOBAL | ENV_USER );
|
||||
env_set( L"PATH", 0, ENV_EXPORT | ENV_GLOBAL );
|
||||
path=0;
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
client library and by the daemon.
|
||||
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <wchar.h>
|
||||
@@ -103,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 );
|
||||
}
|
||||
@@ -186,7 +188,7 @@ void read_message( connection_t *src )
|
||||
}
|
||||
else
|
||||
{
|
||||
sb_printf( &src->input, L"%lc", res );
|
||||
sb_append_char( &src->input, res );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -227,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;
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
#
|
||||
# Init file for fish
|
||||
#
|
||||
# @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
|
||||
@@ -15,11 +22,10 @@ set -g IFS \ \t\n
|
||||
# want this even for text-only terminals.
|
||||
#
|
||||
|
||||
set -l path_list /bin /usr/bin /usr/X11R6/bin @PREFIX@/bin
|
||||
set -l path_list /bin /usr/bin /usr/X11R6/bin @PREFIX@/bin @optbindirs@
|
||||
|
||||
# Root should also have the sbin directories in the path
|
||||
set -l uid (id -u 2>/dev/null)
|
||||
if test "$uid" = 0
|
||||
if test "$USER" = root
|
||||
set path_list $path_list /sbin /usr/sbin /usr/local/sbin
|
||||
end
|
||||
|
||||
@@ -32,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
|
||||
@@ -71,22 +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.
|
||||
#
|
||||
|
||||
if test 1 = "@HAVE_GETTEXT@"; and which gettext >/dev/null ^/dev/null
|
||||
function _ -d "Alias for the gettext command"
|
||||
gettext fish $argv
|
||||
end
|
||||
else
|
||||
function _ -d "Alias for the gettext command"
|
||||
printf "%s" $argv
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Load additional initialization files
|
||||
#
|
||||
97
etc/fish_interactive.fish.in
Normal file
97
etc/fish_interactive.fish.in
Normal file
@@ -0,0 +1,97 @@
|
||||
#
|
||||
# Initializations that should only be performed when in interactive mode
|
||||
#
|
||||
# @configure_input@
|
||||
|
||||
if not status --is-interactive
|
||||
exit
|
||||
end
|
||||
|
||||
#
|
||||
# Print a greeting
|
||||
#
|
||||
|
||||
printf (_ 'Welcome to fish, the friendly interactive shell\n')
|
||||
printf (_ 'Type %shelp%s for instructions on how to use fish\n') (set_color green) (set_color normal)
|
||||
|
||||
#
|
||||
# Set exit message
|
||||
#
|
||||
|
||||
function fish_on_exit -d (_ "Commands to execute when fish exits") --on-process %self
|
||||
printf (_ "Good bye\n")
|
||||
end
|
||||
|
||||
#
|
||||
# Set INPUTRC to something nice
|
||||
#
|
||||
# We override INPUTRC if already set, since it may be set by a shell
|
||||
# other than fish, which may use a different file. The new value should
|
||||
# be exported, since the fish inputrc file plays nice with other files
|
||||
# by including them when found.
|
||||
# Give priority to the default file installed with fish in
|
||||
# @SYSCONFDIR@/fish_inputrc.
|
||||
#
|
||||
|
||||
for i in ~/.fish_inputrc @SYSCONFDIR@/fish_inputrc ~/.inputrc /etc/inputrc
|
||||
if test -f $i
|
||||
set -xg INPUTRC $i
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Set various color values
|
||||
#
|
||||
|
||||
function set_default -d "Set an exported universal variable, unless it has already been set"
|
||||
if not set -q $argv[1]
|
||||
set -Ux -- $argv
|
||||
end
|
||||
end
|
||||
|
||||
function set_exported_default -d "Set an exported universal variable, unless it has already been set"
|
||||
if not set -q $argv[1]
|
||||
set -Ux -- $argv
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Regular syntax highlighting colors
|
||||
set_default fish_color_normal normal
|
||||
set_default fish_color_command green
|
||||
set_default fish_color_redirection normal
|
||||
set_default fish_color_comment brown
|
||||
set_default fish_color_error red
|
||||
|
||||
set_default fish_color_cwd green
|
||||
|
||||
# Background color for matching quotes and parenthesis
|
||||
set_default fish_color_match cyan
|
||||
|
||||
# Background color for search matches
|
||||
set_default fish_color_search_match purple
|
||||
|
||||
# Pager colors
|
||||
set_default fish_pager_color_prefix cyan
|
||||
set_default fish_pager_color_completion normal
|
||||
set_default fish_pager_color_description normal
|
||||
set_default fish_pager_color_progress cyan
|
||||
|
||||
# Directory history colors
|
||||
set_default fish_color_history_current cyan
|
||||
|
||||
|
||||
#
|
||||
# Setup the CDPATH variable
|
||||
#
|
||||
|
||||
set_default CDPATH . ~
|
||||
|
||||
#
|
||||
# Remove temporary functions
|
||||
#
|
||||
|
||||
functions -e set_exported_default
|
||||
functions -e set_default
|
||||
83
event.c
83
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
|
||||
@@ -74,11 +75,15 @@ static array_list_t *killme;
|
||||
*/
|
||||
static array_list_t *blocked;
|
||||
|
||||
/**
|
||||
String buffer used for formating event descriptions in event_get_desc()
|
||||
*/
|
||||
static string_buffer_t *get_desc_buff=0;
|
||||
|
||||
/**
|
||||
Tests if one event instance matches the definition of a event
|
||||
class. If the class defines a function name, that will also be a
|
||||
match criterion.
|
||||
class. If both the class and the instance name a function,
|
||||
they must name the same function.
|
||||
|
||||
*/
|
||||
static int event_match( event_t *class, event_t *instance )
|
||||
@@ -186,6 +191,60 @@ static int event_is_blocked( event_t *e )
|
||||
return 0;
|
||||
}
|
||||
|
||||
const wchar_t *event_get_desc( event_t *e )
|
||||
{
|
||||
if( !get_desc_buff )
|
||||
{
|
||||
get_desc_buff=sb_halloc( global_context );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb_clear( get_desc_buff );
|
||||
}
|
||||
|
||||
switch( e->type )
|
||||
{
|
||||
|
||||
case EVENT_SIGNAL:
|
||||
sb_printf( get_desc_buff, _(L"signal handler for %ls (%ls)"), sig2wcs(e->param1.signal ), signal_get_desc( e->param1.signal ) );
|
||||
break;
|
||||
|
||||
case EVENT_VARIABLE:
|
||||
sb_printf( get_desc_buff, _(L"handler for variable '%ls'"), e->param1.variable );
|
||||
break;
|
||||
|
||||
case EVENT_EXIT:
|
||||
if( e->param1.pid > 0 )
|
||||
{
|
||||
sb_printf( get_desc_buff, _(L"exit handler for process %d"), e->param1.pid );
|
||||
}
|
||||
else
|
||||
{
|
||||
job_t *j = job_get_from_pid( -e->param1.pid );
|
||||
if( j )
|
||||
sb_printf( get_desc_buff, _(L"exit handler for job %d, '%ls'"), j->job_id, j->command );
|
||||
else
|
||||
sb_printf( get_desc_buff, _(L"exit handler for job with process group %d"), -e->param1.pid );
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case EVENT_JOB_ID:
|
||||
{
|
||||
job_t *j = job_get( e->param1.job_id );
|
||||
if( j )
|
||||
sb_printf( get_desc_buff, _(L"exit handler for job %d, '%ls'"), j->job_id, j->command );
|
||||
else
|
||||
sb_printf( get_desc_buff, _(L"exit handler for job with job id %d"), j->job_id );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return (const wchar_t *)get_desc_buff->buff;
|
||||
}
|
||||
|
||||
|
||||
void event_add_handler( event_t *event )
|
||||
{
|
||||
@@ -194,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 )
|
||||
{
|
||||
@@ -326,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_subshell = is_subshell;
|
||||
|
||||
/*
|
||||
First we free all events that have been removed
|
||||
@@ -391,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 );
|
||||
@@ -403,16 +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_subshell=1;
|
||||
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_subshell = was_subshell;
|
||||
|
||||
if( b )
|
||||
{
|
||||
sb_destroy( b );
|
||||
@@ -564,6 +619,7 @@ void event_init()
|
||||
|
||||
void event_destroy()
|
||||
{
|
||||
|
||||
if( events )
|
||||
{
|
||||
al_foreach( events, (void (*)(const void *))&event_free );
|
||||
@@ -571,6 +627,7 @@ void event_destroy()
|
||||
free( events );
|
||||
events=0;
|
||||
}
|
||||
|
||||
if( killme )
|
||||
{
|
||||
al_foreach( killme, (void (*)(const void *))&event_free );
|
||||
|
||||
6
event.h
6
event.h
@@ -130,4 +130,10 @@ void event_destroy();
|
||||
*/
|
||||
void event_free( event_t *e );
|
||||
|
||||
/**
|
||||
Returns a string describing the specified event. The string should
|
||||
not be freed.
|
||||
*/
|
||||
const wchar_t *event_get_desc( event_t *e );
|
||||
|
||||
#endif
|
||||
|
||||
220
exec.c
220
exec.c
@@ -37,6 +37,9 @@
|
||||
#include "signal.h"
|
||||
#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
|
||||
@@ -67,6 +70,8 @@ pid_t getpgid( pid_t pid );
|
||||
*/
|
||||
static array_list_t *open_fds=0;
|
||||
|
||||
static int set_child_group( job_t *j, process_t *p, int print_errors );
|
||||
|
||||
|
||||
void exec_close( int fd )
|
||||
{
|
||||
@@ -238,7 +243,7 @@ void free_fd( io_data_t *io, int fd )
|
||||
\param io the list of IO redirections for the child
|
||||
\param exit_on_error whether to call exit() on errors
|
||||
|
||||
\return 1 on sucess, 0 on failiure
|
||||
\return 0 on sucess, -1 on failiure
|
||||
*/
|
||||
static int handle_child_io( io_data_t *io, int exit_on_error )
|
||||
{
|
||||
@@ -257,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 );
|
||||
}
|
||||
@@ -283,7 +288,7 @@ static int handle_child_io( io_data_t *io, int exit_on_error )
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if( tmp != io->fd)
|
||||
@@ -302,7 +307,7 @@ static int handle_child_io( io_data_t *io, int exit_on_error )
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
exec_close( tmp );
|
||||
@@ -326,7 +331,7 @@ static int handle_child_io( io_data_t *io, int exit_on_error )
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -349,7 +354,7 @@ static int handle_child_io( io_data_t *io, int exit_on_error )
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -373,7 +378,7 @@ static int handle_child_io( io_data_t *io, int exit_on_error )
|
||||
if( env_universal_server.fd >= 0 )
|
||||
exec_close( env_universal_server.fd );
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
@@ -387,41 +392,24 @@ static int handle_child_io( io_data_t *io, int exit_on_error )
|
||||
\param j the job to set up the IO for
|
||||
\param p the child process to set up
|
||||
|
||||
\return 1 on sucess, 0 on failiure
|
||||
\return 0 on sucess, -1 on failiure
|
||||
*/
|
||||
static int setup_child_process( job_t *j, process_t *p )
|
||||
{
|
||||
int res;
|
||||
|
||||
if( j->terminal )
|
||||
{
|
||||
pid_t pid;
|
||||
/*
|
||||
Put the process into the process group and give the process
|
||||
group the terminal, if appropriate. This has to be done
|
||||
both by the shell and in the individual child processes
|
||||
because of potential race conditions.
|
||||
*/
|
||||
pid = getpid ();
|
||||
if (j->pgid == 0)
|
||||
j->pgid = pid;
|
||||
|
||||
/* Wait till shell puts os in our own group */
|
||||
while( getpgrp() != j->pgid )
|
||||
sleep(0);
|
||||
|
||||
/* Wait till shell gives us stdin */
|
||||
if ( j->fg )
|
||||
{
|
||||
while( tcgetpgrp( 0 ) != j->pgid )
|
||||
sleep(0);
|
||||
}
|
||||
int res=0;
|
||||
|
||||
if( p )
|
||||
{
|
||||
res = set_child_group( j, p, 1 );
|
||||
}
|
||||
|
||||
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. */
|
||||
if( res )
|
||||
if( !res )
|
||||
{
|
||||
signal_reset_handlers();
|
||||
}
|
||||
@@ -595,14 +583,22 @@ static void internal_exec_helper( const wchar_t *def,
|
||||
}
|
||||
|
||||
/**
|
||||
This function should be called by the parent process right after
|
||||
fork() has been called. If job control is enabled, the child is put
|
||||
in the jobs group.
|
||||
This function should be called by both the parent process and the
|
||||
child right after fork() has been called. If job control is
|
||||
enabled, the child is put in the jobs group, and if the child is
|
||||
also in the foreground, it is also given control of the
|
||||
terminal. When called in the parent process, this function may
|
||||
fail, since the child might have already finished and called
|
||||
exit. The parent process may safely ignore the exit status of this
|
||||
call.
|
||||
|
||||
Returns 0 on sucess, -1 on failiure.
|
||||
*/
|
||||
static int handle_new_child( job_t *j, process_t *p )
|
||||
static int set_child_group( job_t *j, process_t *p, int print_errors )
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
if( j->terminal )
|
||||
if( j->job_control )
|
||||
{
|
||||
int new_pgid=0;
|
||||
|
||||
@@ -614,7 +610,7 @@ static int handle_new_child( job_t *j, process_t *p )
|
||||
|
||||
if( setpgid (p->pid, j->pgid) )
|
||||
{
|
||||
if( getpgid( p->pid) != j->pgid )
|
||||
if( getpgid( p->pid) != j->pgid && print_errors )
|
||||
{
|
||||
debug( 1,
|
||||
_( L"Could not send process %d from group %d to group %d" ),
|
||||
@@ -622,38 +618,28 @@ static int handle_new_child( job_t *j, process_t *p )
|
||||
getpgid( p->pid),
|
||||
j->pgid );
|
||||
wperror( L"setpgid" );
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if( j->fg )
|
||||
{
|
||||
if( tcsetpgrp (0, j->pgid) )
|
||||
{
|
||||
debug( 1, _( L"Could not send job %d ('%ls') to foreground" ),
|
||||
j->job_id,
|
||||
j->command );
|
||||
wperror( L"tcsetpgrp" );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if( j->fg && new_pgid)
|
||||
{
|
||||
if( tcsetpgrp (0, j->pgid) )
|
||||
{
|
||||
debug( 1, _( L"Could not send job %d ('%ls') to foreground" ),
|
||||
j->job_id,
|
||||
j->command );
|
||||
wperror( L"tcsetpgrp" );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
j->pgid = getpid();
|
||||
}
|
||||
return 0;
|
||||
|
||||
if( j->terminal && j->fg )
|
||||
{
|
||||
if( tcsetpgrp (0, j->pgid) && print_errors )
|
||||
{
|
||||
debug( 1, _( L"Could not send job %d ('%ls') to foreground" ),
|
||||
j->job_id,
|
||||
j->command );
|
||||
wperror( L"tcsetpgrp" );
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@@ -689,9 +675,10 @@ void exec( job_t *j )
|
||||
signal_block();
|
||||
|
||||
/*
|
||||
setup_child_process make sure signals are propelry set up
|
||||
setup_child_process make sure signals are properly set
|
||||
up. It will also call signal_unblock
|
||||
*/
|
||||
if( setup_child_process( j, 0 ) )
|
||||
if( !setup_child_process( j, 0 ) )
|
||||
{
|
||||
/*
|
||||
launch_process never returns
|
||||
@@ -722,9 +709,9 @@ void exec( job_t *j )
|
||||
if( block_io )
|
||||
{
|
||||
if( j->io )
|
||||
j->io = io_add( io_duplicate(block_io), j->io );
|
||||
j->io = io_add( io_duplicate( j, block_io), j->io );
|
||||
else
|
||||
j->io=io_duplicate(block_io);
|
||||
j->io=io_duplicate( j, block_io);
|
||||
}
|
||||
|
||||
j->io = io_add( j->io, &pipe_write );
|
||||
@@ -803,53 +790,22 @@ void exec( job_t *j )
|
||||
{
|
||||
case INTERNAL_FUNCTION:
|
||||
{
|
||||
wchar_t **arg;
|
||||
int i;
|
||||
string_buffer_t sb;
|
||||
|
||||
const wchar_t * def = function_get_definition( p->argv[0] );
|
||||
// fwprintf( stderr, L"run function %ls\n", argv[0] );
|
||||
wchar_t * def = halloc_register( j, wcsdup( function_get_definition( p->argv[0] )));
|
||||
//fwprintf( stderr, L"run function %ls\n", argv[0] );
|
||||
if( def == 0 )
|
||||
{
|
||||
debug( 0, _( L"Unknown function '%ls'" ), p->argv[0] );
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
These two lines must be called before the new block is pushed
|
||||
*/
|
||||
int lineno = parser_get_lineno();
|
||||
wchar_t *file = parser_current_filename()?wcsdup(parser_current_filename()):0;
|
||||
|
||||
parser_push_block( FUNCTION_CALL );
|
||||
|
||||
al_init( ¤t_block->param2.function_vars );
|
||||
current_block->param1.function_name = wcsdup( p->argv[0] );
|
||||
current_block->param3.function_lineno = lineno;
|
||||
current_block->param4.function_filename = file;
|
||||
|
||||
if( builtin_count_args(p->argv)>1 )
|
||||
{
|
||||
sb_init( &sb );
|
||||
|
||||
for( i=1, arg=p->argv+1; *arg; i++, arg++ )
|
||||
{
|
||||
al_push( ¤t_block->param2.function_vars,
|
||||
escape(*arg, 1) );
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
current_block->param2.function_call_process = p;
|
||||
current_block->param1.function_name = halloc_register( current_block, wcsdup( p->argv[0] ) );
|
||||
|
||||
parse_util_set_argv( p->argv+1 );
|
||||
|
||||
parser_forbid_function( p->argv[0] );
|
||||
|
||||
if( p->next )
|
||||
@@ -1016,7 +972,7 @@ void exec( job_t *j )
|
||||
if( !io_buffer )
|
||||
{
|
||||
/*
|
||||
No buffer, se we exit directly. This means we
|
||||
No buffer, so we exit directly. This means we
|
||||
have to manually set the exit status.
|
||||
*/
|
||||
if( p->next == 0 )
|
||||
@@ -1062,12 +1018,19 @@ void exec( job_t *j )
|
||||
it control over the terminal.
|
||||
*/
|
||||
p->pid = pid;
|
||||
if( handle_new_child( j, p ) )
|
||||
exit(1);
|
||||
|
||||
set_child_group( j, p, 0 );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if( p->next == 0 )
|
||||
{
|
||||
proc_set_last_status( j->negate?(status?0:1):status);
|
||||
}
|
||||
p->completed = 1;
|
||||
}
|
||||
|
||||
io_buffer_destroy( io_buffer );
|
||||
|
||||
@@ -1154,9 +1117,8 @@ void exec( job_t *j )
|
||||
*/
|
||||
p->pid = pid;
|
||||
|
||||
if( handle_new_child( j, p ) )
|
||||
exit( 1 );
|
||||
|
||||
set_child_group( j, p, 0 );
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -1194,20 +1156,16 @@ void exec( job_t *j )
|
||||
*/
|
||||
p->pid = pid;
|
||||
|
||||
if( handle_new_child( j, p ) )
|
||||
exit( 1 );
|
||||
|
||||
|
||||
set_child_group( j, p, 0 );
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if( p->type == INTERNAL_BUILTIN )
|
||||
builtin_pop_io();
|
||||
|
||||
builtin_pop_io();
|
||||
|
||||
/*
|
||||
Close the pipe the current process uses to read from the previous process_t
|
||||
@@ -1302,24 +1260,30 @@ 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':
|
||||
{
|
||||
wchar_t *el;
|
||||
*end=0;
|
||||
el = str2wcs( begin );
|
||||
if( !el )
|
||||
el = str2wcs( begin );
|
||||
if( el )
|
||||
{
|
||||
debug( 0, _( L"Subshell '%ls' returned illegal string, discarded one entry" ), cmd );
|
||||
al_push( l, el );
|
||||
}
|
||||
else
|
||||
{
|
||||
al_push( l, el );
|
||||
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
|
||||
}
|
||||
begin = end+1;
|
||||
break;
|
||||
|
||||
44
expand.h
44
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,39 +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 );
|
||||
|
||||
/**
|
||||
Expand backslashed escapes and substitute them with their unescaped
|
||||
counterparts. Also optionally change the wildcards, the tilde
|
||||
character and a few more into constants which are defined in a
|
||||
private use area of Unicode. This assumes wchar_t is a unicode
|
||||
character. character set.
|
||||
|
||||
The result must be free()d. The original string is not modified. If
|
||||
an invalid sequence is specified, 0 is returned.
|
||||
|
||||
*/
|
||||
wchar_t *expand_unescape( const wchar_t * in, int escape_special );
|
||||
|
||||
/**
|
||||
Replace special characters with escape sequences. Newline is
|
||||
replaced with \n, etc.
|
||||
|
||||
The result must be free()d. The original string is not modified.
|
||||
|
||||
\param in The string to be escaped
|
||||
\param escape_all Whether all characters wich hold special meaning in fish (Pipe, semicolon, etc,) should be escaped, or only unprintable characters
|
||||
\return The escaped string
|
||||
*/
|
||||
wchar_t *expand_escape( const wchar_t *in, int escape_all );
|
||||
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.
|
||||
|
||||
@@ -182,20 +156,6 @@ wchar_t *expand_escape_variable( const wchar_t *in );
|
||||
*/
|
||||
wchar_t *expand_tilde(wchar_t *in);
|
||||
|
||||
/**
|
||||
Locate the first subshell in the specified string.
|
||||
|
||||
\param in the string to search for subshells
|
||||
\param begin the starting paranthesis of the subshell
|
||||
\param end the ending paranthesis of the subshell
|
||||
\param flags set this variable to ACCEPT_INCOMPLETE if in tab_completion mode
|
||||
\return -1 on syntax error, 0 if no subshells exist and 1 on sucess
|
||||
*/
|
||||
int expand_locate_subshell( wchar_t *in,
|
||||
wchar_t **begin,
|
||||
wchar_t **end,
|
||||
int flags );
|
||||
|
||||
|
||||
/**
|
||||
Tokenize the specified string into the specified array_list_t.
|
||||
|
||||
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
|
||||
|
||||
632
fish_pager.c
632
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,277 +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 )
|
||||
{
|
||||
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
|
||||
@@ -537,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
|
||||
@@ -546,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) );
|
||||
|
||||
/* Calculated how wide the list would be */
|
||||
|
||||
/* 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;
|
||||
@@ -646,6 +522,7 @@ static int completion_try_print( int cols,
|
||||
}
|
||||
|
||||
completion_print( cols, width, 0, rows, prefix, is_quoted, l);
|
||||
pager_flush();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -678,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 )
|
||||
@@ -739,7 +617,8 @@ static int completion_try_print( int cols,
|
||||
}
|
||||
else
|
||||
{
|
||||
writembs( flash_screen );
|
||||
if( flash_screen )
|
||||
writembs( flash_screen );
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -763,7 +642,8 @@ static int completion_try_print( int cols,
|
||||
}
|
||||
else
|
||||
{
|
||||
writembs( flash_screen );
|
||||
if( flash_screen )
|
||||
writembs( flash_screen );
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -791,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 )
|
||||
{
|
||||
@@ -800,7 +682,7 @@ static void mangle_descriptions( array_list_t *l )
|
||||
{
|
||||
wchar_t *next = (wchar_t *)al_get(l, i);
|
||||
wchar_t *in, *out;
|
||||
skip=0;
|
||||
skip=1;
|
||||
|
||||
while( *next != COMPLETE_SEP && *next )
|
||||
next++;
|
||||
@@ -829,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
|
||||
*/
|
||||
@@ -851,7 +852,11 @@ static void init()
|
||||
struct sigaction act;
|
||||
program_name = L"fish_pager";
|
||||
wsetlocale( LC_ALL, L"" );
|
||||
|
||||
|
||||
/*
|
||||
Make fd 1 output to screen, and use some other fd for writing
|
||||
the resulting output back to the caller
|
||||
*/
|
||||
int out = dup( 1 );
|
||||
close(1);
|
||||
if( open( ttyname(0), O_WRONLY ) != 1 )
|
||||
@@ -863,11 +868,18 @@ static void init()
|
||||
}
|
||||
}
|
||||
out_file = fdopen( out, "w" );
|
||||
|
||||
/**
|
||||
Init the stringbuffer used to keep any output in
|
||||
*/
|
||||
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;
|
||||
@@ -880,33 +892,6 @@ static void init()
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Loop until we are in the foreground. */
|
||||
while (tcgetpgrp( 0 ) != getpid())
|
||||
{
|
||||
kill (- getpid(), SIGTTIN);
|
||||
}
|
||||
|
||||
/* Put ourselves in our own process group. */
|
||||
if( getpgrp() != getpid() )
|
||||
{
|
||||
if (setpgid (getpid(), getpid()) < 0)
|
||||
{
|
||||
debug( 1,
|
||||
L"Couldn't put the shell in its own process group");
|
||||
wperror( L"setpgid" );
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Grab control of the terminal. */
|
||||
if( tcsetpgrp (STDIN_FILENO, getpid()) )
|
||||
{
|
||||
debug( 1,
|
||||
L"Couldn't grab control of terminal" );
|
||||
wperror( L"tcsetpgrp" );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
handle_winch( 0 ); /* Set handler for window change events */
|
||||
|
||||
tcgetattr(0,&pager_modes); /* get the current terminal modes */
|
||||
@@ -919,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");
|
||||
@@ -937,45 +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++ )
|
||||
{
|
||||
al_push( &comp, str2wcs( argv[i] ) );
|
||||
wchar_t *wcs = str2wcs( argv[i] );
|
||||
if( 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;
|
||||
@@ -989,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();
|
||||
|
||||
}
|
||||
|
||||
148
function.c
148
function.c
@@ -18,6 +18,9 @@
|
||||
#include "intern.h"
|
||||
#include "event.h"
|
||||
#include "reader.h"
|
||||
#include "parse_util.h"
|
||||
#include "env.h"
|
||||
#include "expand.h"
|
||||
|
||||
|
||||
/**
|
||||
@@ -32,6 +35,7 @@ typedef struct
|
||||
const wchar_t *definition_file;
|
||||
int definition_offset;
|
||||
int is_binding;
|
||||
int is_autoload;
|
||||
}
|
||||
function_data_t;
|
||||
|
||||
@@ -39,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
|
||||
@@ -65,18 +142,6 @@ void function_destroy()
|
||||
hash_destroy( &function );
|
||||
}
|
||||
|
||||
static int count_lineno( const wchar_t *str, int len )
|
||||
{
|
||||
int res = 0;
|
||||
int i;
|
||||
for( i=0; i<len; i++ )
|
||||
{
|
||||
if( str[i] == L'\n' )
|
||||
res++;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void function_add( const wchar_t *name,
|
||||
const wchar_t *val,
|
||||
@@ -86,16 +151,14 @@ void function_add( const wchar_t *name,
|
||||
{
|
||||
int i;
|
||||
wchar_t *cmd_end;
|
||||
function_data_t *d;
|
||||
|
||||
|
||||
if( function_exists( name ) )
|
||||
function_remove( name );
|
||||
function_remove( name );
|
||||
|
||||
|
||||
|
||||
function_data_t *d = malloc( sizeof( function_data_t ) );
|
||||
d->definition_offset = count_lineno( parser_get_buffer(), current_block->tok_pos );
|
||||
d = malloc( sizeof( function_data_t ) );
|
||||
d->definition_offset = parse_util_lineno( parser_get_buffer(), current_block->tok_pos );
|
||||
d->cmd = wcsdup( val );
|
||||
|
||||
cmd_end = d->cmd + wcslen(d->cmd)-1;
|
||||
while( (cmd_end>d->cmd) && wcschr( L"\n\r\t ", *cmd_end ) )
|
||||
{
|
||||
@@ -104,7 +167,9 @@ void function_add( const wchar_t *name,
|
||||
|
||||
d->desc = desc?wcsdup( desc ):0;
|
||||
d->is_binding = is_binding;
|
||||
d->definition_file = reader_current_filename()?intern(reader_current_filename()):0;
|
||||
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++ )
|
||||
@@ -116,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 );
|
||||
}
|
||||
|
||||
@@ -123,27 +192,28 @@ void function_remove( const wchar_t *name )
|
||||
{
|
||||
void *key;
|
||||
function_data_t *d;
|
||||
|
||||
event_t ev;
|
||||
ev.type=EVENT_ANY;
|
||||
ev.function_name=name;
|
||||
event_remove( &ev );
|
||||
|
||||
hash_remove( &function,
|
||||
name,
|
||||
(const void **) &key,
|
||||
(const void **)&d );
|
||||
|
||||
if( !d )
|
||||
if( !key )
|
||||
return;
|
||||
|
||||
ev.type=EVENT_ANY;
|
||||
ev.function_name=name;
|
||||
event_remove( &ev );
|
||||
|
||||
clear_function_entry( key, d );
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -151,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;
|
||||
|
||||
@@ -161,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;
|
||||
|
||||
@@ -185,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
|
||||
@@ -194,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;
|
||||
|
||||
@@ -205,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
|
||||
|
||||
170
halloc.c
Normal file
170
halloc.c
Normal file
@@ -0,0 +1,170 @@
|
||||
/** \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 "util.h"
|
||||
#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;
|
||||
void *scratch;
|
||||
size_t scratch_free;
|
||||
long long data[0];
|
||||
}
|
||||
halloc_t;
|
||||
|
||||
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;
|
||||
if( context )
|
||||
{
|
||||
void *res;
|
||||
|
||||
#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
|
||||
{
|
||||
|
||||
#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;
|
||||
|
||||
}
|
||||
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_register_function( void *context, void (*func)(void *), void *data )
|
||||
{
|
||||
halloc_t *me;
|
||||
if( !context )
|
||||
return;
|
||||
|
||||
me = halloc_from_data( context );
|
||||
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);
|
||||
}
|
||||
48
halloc.h
Normal file
48
halloc.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/** \file halloc.h
|
||||
|
||||
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. Context
|
||||
_must_ be either 0 or the result of a previous call to halloc.
|
||||
|
||||
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, 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. 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 );
|
||||
|
||||
|
||||
#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
|
||||
22
highlight.c
22
highlight.c
@@ -18,6 +18,7 @@
|
||||
#include "tokenizer.h"
|
||||
#include "proc.h"
|
||||
#include "parser.h"
|
||||
#include "parse_util.h"
|
||||
#include "builtin.h"
|
||||
#include "function.h"
|
||||
#include "env.h"
|
||||
@@ -129,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;
|
||||
@@ -144,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 ) )
|
||||
{
|
||||
@@ -247,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.
|
||||
@@ -365,11 +365,11 @@ void highlight_shell( wchar_t * buff,
|
||||
while( 1 )
|
||||
{
|
||||
wchar_t *begin, *end;
|
||||
|
||||
if( expand_locate_subshell( subpos,
|
||||
&begin,
|
||||
&end,
|
||||
1) <= 0)
|
||||
|
||||
if( parse_util_locate_cmdsubst( subpos,
|
||||
(const wchar_t **)&begin,
|
||||
(const wchar_t **)&end,
|
||||
1) <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
58
history.c
58
history.c
@@ -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
|
||||
@@ -45,6 +46,8 @@ typedef struct
|
||||
The last item loaded from file
|
||||
*/
|
||||
ll_node_t *last_loaded;
|
||||
|
||||
int is_loaded;
|
||||
}
|
||||
history_data;
|
||||
|
||||
@@ -82,25 +85,31 @@ static wchar_t *mode_name;
|
||||
*/
|
||||
static hash_table_t history_table;
|
||||
|
||||
/**
|
||||
Flag, set to 1 once the history file has been loaded
|
||||
*/
|
||||
static int is_loaded;
|
||||
|
||||
/**
|
||||
Load history from ~/.fish_history
|
||||
Load history from file
|
||||
*/
|
||||
static void history_load( wchar_t *name )
|
||||
static void history_load()
|
||||
{
|
||||
wchar_t *fn;
|
||||
wchar_t *buff=0;
|
||||
int buff_len=0;
|
||||
FILE *in_stream;
|
||||
hash_table_t used;
|
||||
|
||||
block();
|
||||
|
||||
is_loaded = 1;
|
||||
|
||||
signal_block();
|
||||
hash_init2( &used,
|
||||
&hash_wcs_func,
|
||||
&hash_wcs_cmp,
|
||||
4096 );
|
||||
|
||||
fn = wcsdupcat2( env_get(L"HOME"), L"/.", name, L"_history", 0 );
|
||||
fn = wcsdupcat2( env_get(L"HOME"), L"/.", mode_name, L"_history", 0 );
|
||||
|
||||
in_stream = wfopen( fn, "r" );
|
||||
|
||||
@@ -111,12 +120,12 @@ static void history_load( wchar_t *name )
|
||||
int buff_read = fgetws2( &buff, &buff_len, in_stream );
|
||||
if( buff_read == -1 )
|
||||
{
|
||||
debug( 1, L"The following non-fatal error occurred while reading command history from \'%ls\':", name );
|
||||
debug( 1, L"The following non-fatal error occurred while reading command history from \'%ls\':", mode_name );
|
||||
wperror( L"fgetws2" );
|
||||
fclose( in_stream );
|
||||
free( fn );
|
||||
free( buff );
|
||||
unblock();
|
||||
signal_unblock();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -161,7 +170,7 @@ static void history_load( wchar_t *name )
|
||||
{
|
||||
if( errno != ENOENT )
|
||||
{
|
||||
debug( 1, L"The following non-fatal error occurred while reading command history from \'%ls\':", name );
|
||||
debug( 1, L"The following non-fatal error occurred while reading command history from \'%ls\':", mode_name );
|
||||
wperror( L"fopen" );
|
||||
}
|
||||
|
||||
@@ -173,7 +182,7 @@ static void history_load( wchar_t *name )
|
||||
free( buff );
|
||||
free( fn );
|
||||
last_loaded = history_last;
|
||||
unblock();
|
||||
signal_unblock();
|
||||
}
|
||||
|
||||
void history_init()
|
||||
@@ -198,6 +207,7 @@ static void history_to_hash()
|
||||
d->last=history_last;
|
||||
d->last_loaded=last_loaded;
|
||||
d->count=history_count;
|
||||
d->is_loaded = is_loaded;
|
||||
|
||||
hash_put( &history_table,
|
||||
mode_name,
|
||||
@@ -223,13 +233,14 @@ void history_set_mode( wchar_t *name )
|
||||
history_current = history_last = curr->last;
|
||||
last_loaded = curr->last_loaded;
|
||||
history_count = curr->count;
|
||||
is_loaded = curr->is_loaded;
|
||||
}
|
||||
else
|
||||
{
|
||||
history_count=0;
|
||||
history_last = history_current = last_loaded=0;
|
||||
mode_name = wcsdup( name );
|
||||
history_load( name );
|
||||
is_loaded = 0;
|
||||
}
|
||||
|
||||
past_end=1;
|
||||
@@ -259,6 +270,9 @@ static void history_save()
|
||||
/* First we save this sessions history in local variables */
|
||||
ll_node_t *real_pos = history_last, *real_first = last_loaded;
|
||||
|
||||
if( !is_loaded )
|
||||
return;
|
||||
|
||||
if( !real_first )
|
||||
{
|
||||
real_first = history_current;
|
||||
@@ -390,6 +404,9 @@ void history_destroy()
|
||||
*/
|
||||
static ll_node_t *history_find( ll_node_t *n, const wchar_t *s )
|
||||
{
|
||||
if( !is_loaded )
|
||||
history_load();
|
||||
|
||||
if( n == 0 )
|
||||
return 0;
|
||||
|
||||
@@ -406,6 +423,9 @@ void history_add( const wchar_t *str )
|
||||
{
|
||||
ll_node_t *old_node;
|
||||
|
||||
if( !is_loaded )
|
||||
history_load();
|
||||
|
||||
if( wcslen( str ) == 0 )
|
||||
return;
|
||||
|
||||
@@ -460,6 +480,9 @@ static int history_test( const wchar_t *needle, const wchar_t *haystack )
|
||||
|
||||
const wchar_t *history_prev_match( const wchar_t *str )
|
||||
{
|
||||
if( !is_loaded )
|
||||
history_load();
|
||||
|
||||
if( history_current == 0 )
|
||||
return str;
|
||||
|
||||
@@ -481,6 +504,9 @@ const wchar_t *history_prev_match( const wchar_t *str )
|
||||
|
||||
const wchar_t *history_next_match( const wchar_t *str)
|
||||
{
|
||||
if( !is_loaded )
|
||||
history_load();
|
||||
|
||||
if( history_current == 0 )
|
||||
return str;
|
||||
|
||||
@@ -507,15 +533,21 @@ void history_reset()
|
||||
*/
|
||||
void history_first()
|
||||
{
|
||||
while( history_current->prev )
|
||||
history_current = history_current->prev;
|
||||
if( is_loaded )
|
||||
while( history_current->prev )
|
||||
history_current = history_current->prev;
|
||||
|
||||
}
|
||||
|
||||
wchar_t *history_get( int idx )
|
||||
{
|
||||
ll_node_t *n=history_last;
|
||||
ll_node_t *n;
|
||||
int i;
|
||||
if( !is_loaded )
|
||||
history_load();
|
||||
|
||||
n = history_last;
|
||||
|
||||
if( idx<0)
|
||||
{
|
||||
debug( 1, L"Tried to access negative history index %d", idx );
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
#include <wchar.h>
|
||||
|
||||
/**
|
||||
Load history from file.
|
||||
Init history library. The history file won't actually be loaded
|
||||
until the first time a history search is performed.
|
||||
*/
|
||||
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 execute anything that will change the disk")
|
||||
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,10 +0,0 @@
|
||||
#
|
||||
# Completion for sudo
|
||||
#
|
||||
# Generate a list of commands
|
||||
#
|
||||
|
||||
complete -c sudo -d (_ "Command to run") -x -a "(__fish_complete_commands)"
|
||||
|
||||
complete -c sudo -s h -d (_ "Display help and exit")
|
||||
complete -c sudo -s v -d (_ "Validate")
|
||||
@@ -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,11 +0,0 @@
|
||||
|
||||
complete -c time -a "(__fish_complete_command)" -d (_ "Command")
|
||||
|
||||
complete -c time -s f -l format -d (_ "Specify output format") -x
|
||||
complete -c time -s p -l portable -d (_ "Use the portable output format")
|
||||
complete -c time -s o -l output -d (_ "Do not send the results to stderr, but overwrite the specified file") -r
|
||||
complete -c time -s a -l append -d (_ "(Used together with -o) Do not overwrite but append")
|
||||
complete -c time -s v -l verbose -d (_ "Verbose mode")
|
||||
complete -c time -l help -d (_ "Display help and exit")
|
||||
complete -c time -s V -l version -d (_ "Display version and exit")
|
||||
|
||||
@@ -1,306 +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.
|
||||
|
||||
#
|
||||
# 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"
|
||||
for i in $PATH; command ls $i; end
|
||||
end
|
||||
|
||||
|
||||
function __fish_print_hostnames -d "Print a list of known hostnames"
|
||||
|
||||
# Print all hosts from /etc/hosts
|
||||
cat /etc/hosts|sed -e 's/[0-9.]*\( \|\t\)*\(.*\)/\2/'|sed -e 's/\#.*//'|sed -e 'y/\t/\n/'|grep -v '^$'
|
||||
|
||||
# Print nfs servers from /etc/fstab
|
||||
cat /etc/fstab| grep "^\([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*\|[a-zA-Z.]*\):"|cut -d : -f 1
|
||||
|
||||
# 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
|
||||
|
||||
#
|
||||
# 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
@@ -1,127 +0,0 @@
|
||||
#
|
||||
# Initializations that should only be performed when in interactive mode
|
||||
#
|
||||
|
||||
if not status --is-interactive
|
||||
exit
|
||||
end
|
||||
|
||||
#
|
||||
# Print a greeting
|
||||
#
|
||||
|
||||
printf (_ 'Welcome to fish, the friendly interactive shell\n')
|
||||
printf (_ 'Type %shelp%s for instructions on how to use fish\n') (set_color green) (set_color normal)
|
||||
|
||||
#
|
||||
# Set exit message
|
||||
#
|
||||
|
||||
function fish_on_exit -d (_ "Commands to execute when fish exits") --on-process %self
|
||||
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")
|
||||
printf '%s@%s %s%s%s> \n' (whoami) (hostname|cut -d . -f 1) (set_color $fish_color_cwd) (prompt_pwd) (set_color normal)
|
||||
end
|
||||
|
||||
#
|
||||
# Set INPUTRC to something nice
|
||||
#
|
||||
# We override INPUTRC if already set, since it may be set by a shell
|
||||
# other than fish, which may use a different file. The new value should
|
||||
# be exported, since the fish inputrc file plays nice with other files
|
||||
# by including them when found.
|
||||
# Give priority to the default file installed with fish in
|
||||
# @SYSCONFDIR@/fish_inputrc.
|
||||
#
|
||||
|
||||
for i in ~/.fish_inputrc @SYSCONFDIR@/fish_inputrc ~/.inputrc /etc/inputrc
|
||||
if test -f $i
|
||||
set -xg INPUTRC $i
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Set various color values
|
||||
#
|
||||
|
||||
function set_default_color -d "Set an universal variable, unless it has already been set. If set, verify that it is a valid color name"
|
||||
if not set -q $argv[1]
|
||||
set -U -- $argv
|
||||
return
|
||||
end
|
||||
if contains -- $$argv[1] (set_color -c)
|
||||
return
|
||||
end
|
||||
set -U -- $argv
|
||||
end
|
||||
|
||||
function set_exported_default -d "Set an exported universal variable, unless it has already been set"
|
||||
if not set -q $argv[1]
|
||||
set -Ux -- $argv
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Regular syntax highlighting colors
|
||||
set_default_color fish_color_normal normal
|
||||
set_default_color fish_color_command green
|
||||
set_default_color fish_color_redirection normal
|
||||
set_default_color fish_color_comment brown
|
||||
set_default_color fish_color_error red
|
||||
|
||||
set_default_color fish_color_cwd green
|
||||
|
||||
# Background color for matching quotes and parenthesis
|
||||
set_default_color fish_color_match cyan
|
||||
|
||||
# Background color for search matches
|
||||
set_default_color fish_color_search_match purple
|
||||
|
||||
# Pager colors
|
||||
set_default_color fish_pager_color_prefix cyan
|
||||
set_default_color fish_pager_color_completion normal
|
||||
set_default_color fish_pager_color_description normal
|
||||
set_default_color fish_pager_color_progress cyan
|
||||
|
||||
# Directory history colors
|
||||
set_default_color fish_color_history_current cyan
|
||||
|
||||
|
||||
#
|
||||
# Setup the CDPATH variable
|
||||
#
|
||||
|
||||
set_exported_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_exported_default LS_COLORS $LS_COLORS '*.jar=01;31' '*.doc=35' '*.pdf=35' '*.ps=35' '*.xls=35' '*.swf=35' '*~=37'
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Remove temporary functions
|
||||
#
|
||||
|
||||
functions -e set_default_color
|
||||
functions -e set_exported_default
|
||||
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;
|
||||
|
||||
11
intern.c
11
intern.c
@@ -25,14 +25,6 @@ static hash_table_t *intern_table=0;
|
||||
*/
|
||||
static hash_table_t *intern_static_table=0;
|
||||
|
||||
/**
|
||||
Load static strings that are universally common. Currently only loads the empty string.
|
||||
*/
|
||||
static void intern_load_common_static()
|
||||
{
|
||||
intern_static( L"" );
|
||||
}
|
||||
|
||||
const wchar_t *intern( const wchar_t *in )
|
||||
{
|
||||
const wchar_t *res=0;
|
||||
@@ -40,9 +32,6 @@ const wchar_t *intern( const wchar_t *in )
|
||||
if( !in )
|
||||
return 0;
|
||||
|
||||
intern_load_common_static();
|
||||
|
||||
|
||||
if( !intern_table )
|
||||
{
|
||||
intern_table = malloc( sizeof( hash_table_t ) );
|
||||
|
||||
8
io.c
8
io.c
@@ -37,7 +37,7 @@ Utilities for io redirection.
|
||||
#include "common.h"
|
||||
#include "io.h"
|
||||
#include "translate.h"
|
||||
|
||||
#include "halloc.h"
|
||||
|
||||
|
||||
void io_buffer_read( io_data_t *d )
|
||||
@@ -175,14 +175,14 @@ io_data_t *io_remove( io_data_t *list, io_data_t *element )
|
||||
return list;
|
||||
}
|
||||
|
||||
io_data_t *io_duplicate( io_data_t *l )
|
||||
io_data_t *io_duplicate( void *context, io_data_t *l )
|
||||
{
|
||||
io_data_t *res;
|
||||
|
||||
if( l == 0 )
|
||||
return 0;
|
||||
|
||||
res = malloc( sizeof( io_data_t) );
|
||||
res = halloc( context, sizeof( io_data_t) );
|
||||
|
||||
if( !res )
|
||||
{
|
||||
@@ -191,7 +191,7 @@ io_data_t *io_duplicate( io_data_t *l )
|
||||
}
|
||||
|
||||
memcpy( res, l, sizeof(io_data_t ));
|
||||
res->next=io_duplicate( l->next );
|
||||
res->next=io_duplicate( context, l->next );
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
4
io.h
4
io.h
@@ -62,9 +62,9 @@ io_data_t *io_add( io_data_t *first_chain, io_data_t *decond_chain );
|
||||
io_data_t *io_remove( io_data_t *list, io_data_t *element );
|
||||
|
||||
/**
|
||||
Make a copy of the specified chain of redirections
|
||||
Make a copy of the specified chain of redirections. Uses halloc.
|
||||
*/
|
||||
io_data_t *io_duplicate( io_data_t *l );
|
||||
io_data_t *io_duplicate( void *context, io_data_t *l );
|
||||
|
||||
/**
|
||||
Return the last io redirection in ht e chain for the specified file descriptor.
|
||||
|
||||
5
kill.c
5
kill.c
@@ -25,7 +25,6 @@
|
||||
#include "sanity.h"
|
||||
#include "common.h"
|
||||
#include "env.h"
|
||||
#include "expand.h"
|
||||
#include "exec.h"
|
||||
#include "parser.h"
|
||||
|
||||
@@ -95,7 +94,7 @@ void kill_add( wchar_t *str )
|
||||
wchar_t *disp;
|
||||
if( (disp = env_get( L"DISPLAY" )) )
|
||||
{
|
||||
wchar_t *escaped_str = expand_escape( str, 1 );
|
||||
wchar_t *escaped_str = escape( str, 1 );
|
||||
wchar_t *cmd = wcsdupcat2(L"echo ", escaped_str, L"|xsel -b",0);
|
||||
exec_subshell( cmd, 0 );
|
||||
free( cut_buffer );
|
||||
@@ -137,7 +136,7 @@ static void kill_check_x_buffer()
|
||||
|
||||
for( i=0; i<al_get_count( &list ); i++ )
|
||||
{
|
||||
wchar_t *next_line = expand_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;
|
||||
|
||||
79
main.c
79
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,10 +122,18 @@ int main( int argc, char **argv )
|
||||
"command", required_argument, 0, 'c'
|
||||
}
|
||||
,
|
||||
{
|
||||
"debug-level", required_argument, 0, 'd'
|
||||
}
|
||||
,
|
||||
{
|
||||
"interactive", no_argument, 0, 'i'
|
||||
}
|
||||
,
|
||||
{
|
||||
"login", no_argument, 0, 'l'
|
||||
}
|
||||
,
|
||||
{
|
||||
"profile", required_argument, 0, 'p'
|
||||
}
|
||||
@@ -146,14 +156,14 @@ int main( int argc, char **argv )
|
||||
|
||||
int opt = getopt_long( argc,
|
||||
argv,
|
||||
"hivc:p:",
|
||||
"hilvc:p:d:",
|
||||
long_options,
|
||||
&opt_index );
|
||||
|
||||
#else
|
||||
int opt = getopt( argc,
|
||||
argv,
|
||||
"hivc:p:" );
|
||||
"hilvc:p:d:" );
|
||||
#endif
|
||||
if( opt == -1 )
|
||||
break;
|
||||
@@ -168,16 +178,34 @@ 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";
|
||||
//interactive=0;
|
||||
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
force_interactive = 1;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
is_login=1;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
profile = optarg;
|
||||
break;
|
||||
@@ -197,21 +225,17 @@ int main( int argc, char **argv )
|
||||
|
||||
my_optind = optind;
|
||||
|
||||
is_login |= strcmp( argv[0], "-fish") == 0;
|
||||
// fwprintf( stderr, L"%s\n", argv[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);
|
||||
|
||||
// fwprintf( stderr, L"%d %d %d\n", cmd==0, my_optind == argc, isatty(STDIN_FILENO) );
|
||||
is_interactive_session |= force_interactive;
|
||||
|
||||
if( force_interactive )
|
||||
is_interactive_session=1;
|
||||
common_init();
|
||||
halloc_util_init();
|
||||
|
||||
translate_init();
|
||||
proc_init();
|
||||
output_init();
|
||||
event_init();
|
||||
exec_init();
|
||||
wutil_init();
|
||||
@@ -229,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
|
||||
{
|
||||
@@ -244,7 +268,8 @@ int main( int argc, char **argv )
|
||||
int i;
|
||||
string_buffer_t sb;
|
||||
int fd;
|
||||
|
||||
wchar_t *rel_filename, *abs_filename;
|
||||
|
||||
if( ( fd = open(file, O_RDONLY) ) == -1 )
|
||||
{
|
||||
wperror( L"open" );
|
||||
@@ -267,8 +292,15 @@ int main( int argc, char **argv )
|
||||
env_set( L"argv", (wchar_t *)sb.buff, 0 );
|
||||
sb_destroy( &sb );
|
||||
}
|
||||
|
||||
reader_push_current_filename( str2wcs( file ) );
|
||||
|
||||
rel_filename = str2wcs( file );
|
||||
abs_filename = wrealpath( rel_filename, 0 );
|
||||
if( !abs_filename )
|
||||
abs_filename = wcsdup(rel_filename);
|
||||
reader_push_current_filename( intern( abs_filename ) );
|
||||
free( rel_filename );
|
||||
free( abs_filename );
|
||||
|
||||
res = reader_read( fd );
|
||||
|
||||
if( res )
|
||||
@@ -277,27 +309,26 @@ int main( int argc, char **argv )
|
||||
_(L"Error while reading file %ls\n"),
|
||||
reader_current_filename()?reader_current_filename(): _(L"Standard input") );
|
||||
}
|
||||
free(reader_pop_current_filename());
|
||||
reader_pop_current_filename();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
689
parse_util.c
Normal file
689
parse_util.c
Normal file
@@ -0,0 +1,689 @@
|
||||
/** \file parse_util.c
|
||||
|
||||
Various mostly unrelated utility functions related to parsing,
|
||||
loading and evaluating fish code.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <wctype.h>
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "wutil.h"
|
||||
#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 )
|
||||
{
|
||||
/**
|
||||
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;
|
||||
|
||||
if( str != prev_str || i>len )
|
||||
{
|
||||
if( prev_str2 == str && i2 <= len )
|
||||
{
|
||||
const wchar_t *tmp_str = prev_str;
|
||||
int tmp_i = i;
|
||||
int tmp_res = res;
|
||||
prev_str = prev_str2;
|
||||
i=i2;
|
||||
res=res2;
|
||||
|
||||
prev_str2 = tmp_str;
|
||||
i2 = tmp_i;
|
||||
res2 = tmp_res;
|
||||
}
|
||||
else
|
||||
{
|
||||
prev_str2 = prev_str;
|
||||
i2 = i;
|
||||
res2=res;
|
||||
|
||||
prev_str = str;
|
||||
i=0;
|
||||
res=1;
|
||||
}
|
||||
}
|
||||
|
||||
for( ; str[i] && i<len; i++ )
|
||||
{
|
||||
if( str[i] == L'\n' )
|
||||
res++;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int parse_util_locate_cmdsubst( const wchar_t *in,
|
||||
const wchar_t **begin,
|
||||
const wchar_t **end,
|
||||
int allow_incomplete )
|
||||
{
|
||||
const wchar_t *pos;
|
||||
wchar_t prev=0;
|
||||
int syntax_error=0;
|
||||
int paran_count=0;
|
||||
|
||||
const wchar_t *paran_begin=0, *paran_end=0;
|
||||
|
||||
for( pos=in; *pos; pos++ )
|
||||
{
|
||||
if( prev != '\\' )
|
||||
{
|
||||
if( wcschr( L"\'\"", *pos ) )
|
||||
{
|
||||
const wchar_t *end = quote_end( pos );
|
||||
if( end && *end)
|
||||
{
|
||||
pos=end;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( *pos == '(' )
|
||||
{
|
||||
if(( paran_count == 0)&&(paran_begin==0))
|
||||
paran_begin = pos;
|
||||
|
||||
paran_count++;
|
||||
}
|
||||
else if( *pos == ')' )
|
||||
{
|
||||
paran_count--;
|
||||
if( (paran_count == 0) && (paran_end == 0) )
|
||||
{
|
||||
paran_end = pos;
|
||||
break;
|
||||
}
|
||||
|
||||
if( paran_count < 0 )
|
||||
{
|
||||
syntax_error = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
prev = *pos;
|
||||
}
|
||||
|
||||
syntax_error |= (paran_count < 0 );
|
||||
syntax_error |= ((paran_count>0)&&(!allow_incomplete));
|
||||
|
||||
if( syntax_error )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( paran_begin == 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( begin )
|
||||
*begin = paran_begin;
|
||||
if( end )
|
||||
*end = paran_count?in+wcslen(in):paran_end;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void parse_util_cmdsubst_extent( const wchar_t *buff,
|
||||
int cursor_pos,
|
||||
const wchar_t **a,
|
||||
const wchar_t **b )
|
||||
{
|
||||
const wchar_t *begin, *end;
|
||||
const wchar_t *pos;
|
||||
|
||||
if( a )
|
||||
*a=0;
|
||||
if( b )
|
||||
*b = 0;
|
||||
|
||||
if( !buff )
|
||||
return;
|
||||
|
||||
pos = buff;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
int bc, ec;
|
||||
|
||||
if( parse_util_locate_cmdsubst( pos,
|
||||
&begin,
|
||||
&end,
|
||||
1 ) <= 0)
|
||||
{
|
||||
begin=buff;
|
||||
end = buff + wcslen(buff);
|
||||
break;
|
||||
}
|
||||
|
||||
if( !end )
|
||||
{
|
||||
end = buff + wcslen(buff);
|
||||
}
|
||||
|
||||
bc = begin-buff;
|
||||
ec = end-buff;
|
||||
|
||||
if(( bc < cursor_pos ) && (ec >= cursor_pos) )
|
||||
{
|
||||
begin++;
|
||||
break;
|
||||
}
|
||||
pos = end+1;
|
||||
}
|
||||
if( a )
|
||||
*a = begin;
|
||||
if( b )
|
||||
*b = end;
|
||||
}
|
||||
|
||||
/**
|
||||
Get the beginning and end of the job or process definition under the cursor
|
||||
*/
|
||||
static void job_or_process_extent( const wchar_t *buff,
|
||||
int cursor_pos,
|
||||
const wchar_t **a,
|
||||
const wchar_t **b,
|
||||
int process )
|
||||
{
|
||||
const wchar_t *begin, *end;
|
||||
int pos;
|
||||
wchar_t *buffcpy;
|
||||
int finished=0;
|
||||
|
||||
tokenizer tok;
|
||||
|
||||
if( a )
|
||||
*a=0;
|
||||
if( b )
|
||||
*b = 0;
|
||||
|
||||
parse_util_cmdsubst_extent( buff, cursor_pos, &begin, &end );
|
||||
if( !end || !begin )
|
||||
return;
|
||||
|
||||
pos = cursor_pos - (begin - buff);
|
||||
|
||||
if( a )
|
||||
{
|
||||
*a = begin;
|
||||
}
|
||||
|
||||
if( b )
|
||||
{
|
||||
*b = end;
|
||||
}
|
||||
|
||||
buffcpy = wcsndup( begin, end-begin );
|
||||
|
||||
if( !buffcpy )
|
||||
{
|
||||
die_mem();
|
||||
}
|
||||
|
||||
for( tok_init( &tok, buffcpy, TOK_ACCEPT_UNFINISHED );
|
||||
tok_has_next( &tok ) && !finished;
|
||||
tok_next( &tok ) )
|
||||
{
|
||||
int tok_begin = tok_get_pos( &tok );
|
||||
|
||||
switch( tok_last_type( &tok ) )
|
||||
{
|
||||
case TOK_PIPE:
|
||||
if( !process )
|
||||
break;
|
||||
|
||||
case TOK_END:
|
||||
case TOK_BACKGROUND:
|
||||
{
|
||||
|
||||
if( tok_begin >= pos )
|
||||
{
|
||||
finished=1;
|
||||
if( b )
|
||||
*b = buff + tok_begin;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( a )
|
||||
*a = buff + tok_begin+1;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free( buffcpy);
|
||||
|
||||
tok_destroy( &tok );
|
||||
|
||||
}
|
||||
|
||||
void parse_util_process_extent( const wchar_t *buff,
|
||||
int pos,
|
||||
const wchar_t **a,
|
||||
const wchar_t **b )
|
||||
{
|
||||
job_or_process_extent( buff, pos, a, b, 1 );
|
||||
}
|
||||
|
||||
void parse_util_job_extent( const wchar_t *buff,
|
||||
int pos,
|
||||
const wchar_t **a,
|
||||
const wchar_t **b )
|
||||
{
|
||||
job_or_process_extent( buff,pos,a, b, 0 );
|
||||
}
|
||||
|
||||
|
||||
void parse_util_token_extent( const wchar_t *buff,
|
||||
int cursor_pos,
|
||||
const wchar_t **tok_begin,
|
||||
const wchar_t **tok_end,
|
||||
const wchar_t **prev_begin,
|
||||
const wchar_t **prev_end )
|
||||
{
|
||||
const wchar_t *begin, *end;
|
||||
int pos;
|
||||
wchar_t *buffcpy;
|
||||
|
||||
tokenizer tok;
|
||||
|
||||
const wchar_t *a, *b, *pa, *pb;
|
||||
|
||||
|
||||
a = b = pa = pb = 0;
|
||||
|
||||
parse_util_cmdsubst_extent( buff, cursor_pos, &begin, &end );
|
||||
|
||||
if( !end || !begin )
|
||||
return;
|
||||
|
||||
pos = cursor_pos - (begin - buff);
|
||||
|
||||
a = buff + pos;
|
||||
b = a;
|
||||
pa = buff + pos;
|
||||
pb = pa;
|
||||
|
||||
assert( begin >= buff );
|
||||
assert( begin <= (buff+wcslen(buff) ) );
|
||||
assert( end >= begin );
|
||||
assert( end <= (buff+wcslen(buff) ) );
|
||||
|
||||
buffcpy = wcsndup( begin, end-begin );
|
||||
|
||||
if( !buffcpy )
|
||||
{
|
||||
die_mem();
|
||||
}
|
||||
|
||||
for( tok_init( &tok, buffcpy, TOK_ACCEPT_UNFINISHED );
|
||||
tok_has_next( &tok );
|
||||
tok_next( &tok ) )
|
||||
{
|
||||
int tok_begin = tok_get_pos( &tok );
|
||||
int tok_end=tok_begin;
|
||||
|
||||
/*
|
||||
Calculate end of token
|
||||
*/
|
||||
if( tok_last_type( &tok ) == TOK_STRING )
|
||||
tok_end +=wcslen(tok_last(&tok));
|
||||
|
||||
/*
|
||||
Cursor was before beginning of this token, means that the
|
||||
cursor is between two tokens, so we set it to a zero element
|
||||
string and break
|
||||
*/
|
||||
if( tok_begin > pos )
|
||||
{
|
||||
a = b = buff + pos;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
If cursor is inside the token, this is the token we are
|
||||
looking for. If so, set a and b and break
|
||||
*/
|
||||
if( tok_end >= pos )
|
||||
{
|
||||
a = begin + tok_get_pos( &tok );
|
||||
b = a + wcslen(tok_last(&tok));
|
||||
|
||||
// fwprintf( stderr, L"Whee %ls\n", *a );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
Remember previous string token
|
||||
*/
|
||||
if( tok_last_type( &tok ) == TOK_STRING )
|
||||
{
|
||||
pa = begin + tok_get_pos( &tok );
|
||||
pb = pa + wcslen(tok_last(&tok));
|
||||
}
|
||||
}
|
||||
|
||||
free( buffcpy);
|
||||
|
||||
tok_destroy( &tok );
|
||||
|
||||
if( tok_begin )
|
||||
*tok_begin = a;
|
||||
if( tok_end )
|
||||
*tok_end = b;
|
||||
if( prev_begin )
|
||||
*prev_begin = pa;
|
||||
if( prev_end )
|
||||
*prev_end = pb;
|
||||
|
||||
assert( pa >= buff );
|
||||
assert( pa <= (buff+wcslen(buff) ) );
|
||||
assert( pb >= pa );
|
||||
assert( pb <= (buff+wcslen(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;
|
||||
}
|
||||
|
||||
119
parse_util.h
Normal file
119
parse_util.h
Normal file
@@ -0,0 +1,119 @@
|
||||
/** \file parse_util.h
|
||||
|
||||
Various mostly unrelated utility functions related to parsing,
|
||||
loading and evaluating fish code.
|
||||
*/
|
||||
|
||||
#ifndef FISH_PARSE_UTIL_H
|
||||
#define FISH_PARSE_UTIL_H
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
/**
|
||||
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
|
||||
\param end the ending paranthesis of the subshell
|
||||
\param flags set this variable to ACCEPT_INCOMPLETE if in tab_completion mode
|
||||
\return -1 on syntax error, 0 if no subshells exist and 1 on sucess
|
||||
*/
|
||||
|
||||
int parse_util_locate_cmdsubst( const wchar_t *in,
|
||||
const wchar_t **begin,
|
||||
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 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 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,
|
||||
const wchar_t **tok_end,
|
||||
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
|
||||
26
parser.h
26
parser.h
@@ -10,6 +10,7 @@
|
||||
#include "proc.h"
|
||||
#include "util.h"
|
||||
#include "parser.h"
|
||||
#include "event.h"
|
||||
|
||||
/**
|
||||
event_block_t represents a block on events of the specified type
|
||||
@@ -64,6 +65,8 @@ typedef struct block
|
||||
int if_state; /**< The state of the if block */
|
||||
wchar_t *switch_value; /**< The value to test in a switch block */
|
||||
wchar_t *function_name; /**< The name of the function to define or the function called*/
|
||||
const wchar_t *source_dest; /**< The name of the file to source*/
|
||||
event_t *event; /**<The event that triggered this block */
|
||||
} param1;
|
||||
|
||||
/**
|
||||
@@ -74,7 +77,7 @@ typedef struct block
|
||||
array_list_t for_vars; /**< List of values for a for block */
|
||||
int switch_taken; /**< Whether a switch match has already been found */
|
||||
wchar_t *function_description; /**< The description of the function to define */
|
||||
array_list_t function_vars; /**< List of arguments for a function call */
|
||||
process_t *function_call_process; /**< The process representing this function call */
|
||||
} param2;
|
||||
|
||||
/**
|
||||
@@ -83,7 +86,6 @@ typedef struct block
|
||||
union
|
||||
{
|
||||
int function_is_binding; /**< Whether a function is a keybinding */
|
||||
int function_lineno; /**< Function invocation line number */
|
||||
} param3;
|
||||
|
||||
/**
|
||||
@@ -92,8 +94,17 @@ typedef struct block
|
||||
union
|
||||
{
|
||||
array_list_t *function_events;
|
||||
wchar_t *function_filename;
|
||||
} param4;
|
||||
|
||||
/**
|
||||
Name of file that created this block
|
||||
*/
|
||||
const wchar_t *src_filename;
|
||||
|
||||
/**
|
||||
Line number where this block was created
|
||||
*/
|
||||
int src_lineno;
|
||||
|
||||
/**
|
||||
Some naming confusion. This is a pointer to the first element in the list of all event blocks.
|
||||
@@ -121,6 +132,8 @@ enum block_type
|
||||
SUBST, /**< Command substitution scope */
|
||||
TOP, /**< Outermost block */
|
||||
BEGIN, /**< Unconditional block */
|
||||
SOURCE, /**< Block created by the . (source) builtin */
|
||||
EVENT, /**< Block created on event notifier invocation */
|
||||
}
|
||||
;
|
||||
|
||||
@@ -244,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'.
|
||||
@@ -346,5 +359,10 @@ int parser_is_help( wchar_t *s, int min_match );
|
||||
*/
|
||||
const wchar_t *parser_current_filename();
|
||||
|
||||
/**
|
||||
Write a stack trace starting at the specified block to the specified string_buffer_t
|
||||
*/
|
||||
void parser_stack_trace( block_t *b, string_buffer_t *buff);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
166
proc.c
166
proc.c
@@ -53,6 +53,9 @@ Some of the code in this file is based on code from the Glibc manual.
|
||||
#include "signal.h"
|
||||
#include "event.h"
|
||||
#include "translate.h"
|
||||
#include "halloc.h"
|
||||
#include "halloc_util.h"
|
||||
#include "output.h"
|
||||
|
||||
/**
|
||||
Size of message buffer
|
||||
@@ -75,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;
|
||||
@@ -83,6 +86,7 @@ int is_login=0;
|
||||
int is_event=0;
|
||||
int proc_had_barrier;
|
||||
pid_t proc_last_bg_pid = 0;
|
||||
int job_control_mode = JOB_CONTROL_INTERACTIVE;
|
||||
|
||||
/**
|
||||
The event variable used to send all process event
|
||||
@@ -99,43 +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 );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Recursively free a process and those following it
|
||||
*/
|
||||
static void free_process( process_t *p )
|
||||
{
|
||||
wchar_t **arg;
|
||||
|
||||
if( p==0 )
|
||||
return;
|
||||
|
||||
|
||||
|
||||
free_process( p->next );
|
||||
debug( 3, L"Free process %ls", p->actual_cmd );
|
||||
free( p->actual_cmd );
|
||||
if( p->argv != 0 )
|
||||
{
|
||||
debug( 3, L"Process has argument vector" );
|
||||
for( arg=p->argv; *arg; arg++ )
|
||||
{
|
||||
debug( 3, L"Free argument %ls", *arg );
|
||||
free( *arg );
|
||||
}
|
||||
free(p->argv );
|
||||
}
|
||||
free( p );
|
||||
}
|
||||
|
||||
/**
|
||||
Remove job from list of jobs
|
||||
*/
|
||||
@@ -169,30 +148,8 @@ static int job_remove( job_t *j )
|
||||
*/
|
||||
void job_free( job_t * j )
|
||||
{
|
||||
io_data_t *io, *ionext;
|
||||
|
||||
// fwprintf( stderr, L"Remove job %d (%ls)\n", j->job_id, j->command );
|
||||
|
||||
job_remove( j );
|
||||
|
||||
/* Then free ourselves */
|
||||
free_process( j->first_process);
|
||||
|
||||
if( j->command != 0 )
|
||||
free( j->command );
|
||||
|
||||
for( io=j->io; io; io=ionext )
|
||||
{
|
||||
ionext = io->next;
|
||||
// fwprintf( stderr, L"Kill redirect %d of type %d\n", ionext, io->io_mode );
|
||||
if( io->io_mode == IO_FILE )
|
||||
{
|
||||
free( io->param1.filename );
|
||||
}
|
||||
free( io );
|
||||
}
|
||||
|
||||
free( j );
|
||||
halloc_free( j );
|
||||
}
|
||||
|
||||
void proc_destroy()
|
||||
@@ -225,10 +182,14 @@ job_t *job_create()
|
||||
|
||||
while( job_get( free_id ) != 0 )
|
||||
free_id++;
|
||||
res = calloc( 1, sizeof(job_t) );
|
||||
res = halloc( 0, sizeof(job_t) );
|
||||
res->next = first_job;
|
||||
res->job_id = free_id;
|
||||
first_job = res;
|
||||
|
||||
res->job_control = (job_control_mode==JOB_CONTROL_ALL) ||
|
||||
((job_control_mode == JOB_CONTROL_INTERACTIVE) && (is_interactive));
|
||||
|
||||
// if( res->job_id > 2 )
|
||||
// fwprintf( stderr, L"Create job %d\n", res->job_id );
|
||||
return res;
|
||||
@@ -388,7 +349,7 @@ static void handle_child_status( pid_t pid, int status )
|
||||
"Process %d is %ls from job %ls\n",
|
||||
(int) pid, p->actual_cmd, j->command );
|
||||
write( 2, mess, strlen(mess ));
|
||||
*/
|
||||
*/
|
||||
|
||||
mark_process_status ( j, p, status);
|
||||
if( p->completed && prev != 0 )
|
||||
@@ -583,7 +544,7 @@ int job_reap( int interactive )
|
||||
j->job_id,
|
||||
j->command,
|
||||
sig2wcs(WTERMSIG(p->status)),
|
||||
sig_description( WTERMSIG(p->status) ) );
|
||||
signal_get_desc( WTERMSIG(p->status) ) );
|
||||
else
|
||||
fwprintf( stdout,
|
||||
_( L"%ls: Process %d, \'%ls\' from job %d, \'%ls\' terminated by signal %ls (%ls)" ),
|
||||
@@ -593,7 +554,7 @@ int job_reap( int interactive )
|
||||
j->job_id,
|
||||
j->command,
|
||||
sig2wcs(WTERMSIG(p->status)),
|
||||
sig_description( WTERMSIG(p->status) ) );
|
||||
signal_get_desc( WTERMSIG(p->status) ) );
|
||||
tputs(clr_eol,1,&writeb);
|
||||
fwprintf (stdout, L"\n" );
|
||||
found=1;
|
||||
@@ -875,37 +836,33 @@ void job_continue (job_t *j, int cont)
|
||||
|
||||
if( !job_is_completed( j ) )
|
||||
{
|
||||
if( j->terminal )
|
||||
{
|
||||
|
||||
if( j->terminal && j->fg )
|
||||
{
|
||||
/* Put the job into the foreground. */
|
||||
if( j->fg )
|
||||
signal_block();
|
||||
if( tcsetpgrp (0, j->pgid) )
|
||||
{
|
||||
signal_block();
|
||||
if( tcsetpgrp (0, j->pgid) )
|
||||
{
|
||||
debug( 1,
|
||||
_( L"Could not send job %d ('%ls') to foreground" ),
|
||||
j->job_id,
|
||||
j->command );
|
||||
wperror( L"tcsetpgrp" );
|
||||
return;
|
||||
}
|
||||
|
||||
if( cont )
|
||||
{
|
||||
if( tcsetattr (0, TCSADRAIN, &j->tmodes))
|
||||
{
|
||||
debug( 1,
|
||||
_( L"Could not send job %d ('%ls') to foreground" ),
|
||||
j->job_id,
|
||||
j->command );
|
||||
wperror( L"tcsetattr" );
|
||||
return;
|
||||
}
|
||||
}
|
||||
signal_unblock();
|
||||
debug( 1,
|
||||
_( L"Could not send job %d ('%ls') to foreground" ),
|
||||
j->job_id,
|
||||
j->command );
|
||||
wperror( L"tcsetpgrp" );
|
||||
return;
|
||||
}
|
||||
|
||||
if( cont )
|
||||
{
|
||||
if( tcsetattr (0, TCSADRAIN, &j->tmodes))
|
||||
{
|
||||
debug( 1,
|
||||
_( L"Could not send job %d ('%ls') to foreground" ),
|
||||
j->job_id,
|
||||
j->command );
|
||||
wperror( L"tcsetattr" );
|
||||
return;
|
||||
}
|
||||
}
|
||||
signal_unblock();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -914,15 +871,28 @@ void job_continue (job_t *j, int cont)
|
||||
if( cont )
|
||||
{
|
||||
process_t *p;
|
||||
|
||||
for( p=j->first_process; p; p=p->next )
|
||||
p->stopped=0;
|
||||
for( p=j->first_process; p; p=p->next )
|
||||
|
||||
if( j->job_control )
|
||||
{
|
||||
if (kill ( p->pid, SIGCONT) < 0)
|
||||
if( killpg( j->pgid, SIGCONT ) )
|
||||
{
|
||||
wperror (L"kill (SIGCONT)");
|
||||
wperror( L"killpg (SIGCONT)" );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( p=j->first_process; p; p=p->next )
|
||||
{
|
||||
if (kill ( p->pid, SIGCONT) < 0)
|
||||
{
|
||||
wperror (L"kill (SIGCONT)");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -979,7 +949,7 @@ void job_continue (job_t *j, int cont)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( j->fg )
|
||||
{
|
||||
|
||||
@@ -1005,7 +975,7 @@ void job_continue (job_t *j, int cont)
|
||||
/*
|
||||
Put the shell back in the foreground.
|
||||
*/
|
||||
if( j->terminal )
|
||||
if( j->terminal && j->fg )
|
||||
{
|
||||
signal_block();
|
||||
if( tcsetpgrp (0, getpid()) )
|
||||
@@ -1112,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();
|
||||
}
|
||||
|
||||
36
proc.h
36
proc.h
@@ -48,6 +48,13 @@ enum
|
||||
}
|
||||
;
|
||||
|
||||
enum
|
||||
{
|
||||
JOB_CONTROL_ALL,
|
||||
JOB_CONTROL_INTERACTIVE,
|
||||
JOB_CONTROL_NONE,
|
||||
}
|
||||
;
|
||||
|
||||
/**
|
||||
A structure representing a single fish process. Contains variables
|
||||
@@ -156,9 +163,12 @@ typedef struct job
|
||||
/** Skip executing this job. This flag is set by the short-circut builtins, i.e. and and or */
|
||||
int skip;
|
||||
|
||||
/** Whether this job wants to have control of the terminal when it is in the foreground */
|
||||
/** Whether the job is under job control */
|
||||
int job_control;
|
||||
|
||||
/** Whether the job wants to own the terminal when in the foreground */
|
||||
int terminal;
|
||||
|
||||
|
||||
/** Pointer to the next job */
|
||||
struct job *next;
|
||||
}
|
||||
@@ -216,6 +226,11 @@ extern int proc_had_barrier;
|
||||
*/
|
||||
extern pid_t proc_last_bg_pid;
|
||||
|
||||
/**
|
||||
Can be one of JOB_CONTROL_ALL, JOB_CONTROL_INTERACTIVE and JOB_CONTROL_NONE
|
||||
*/
|
||||
extern int job_control_mode;
|
||||
|
||||
/**
|
||||
Sets the status of the last process to exit
|
||||
*/
|
||||
@@ -232,7 +247,9 @@ int proc_get_last_status();
|
||||
void job_free( job_t* j );
|
||||
|
||||
/**
|
||||
Create a new job
|
||||
Create a new job. Job struct is allocated using halloc, so anything
|
||||
that should be freed with the job can uset it as a halloc context
|
||||
when allocating.
|
||||
*/
|
||||
job_t *job_create();
|
||||
|
||||
@@ -281,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
|
||||
@@ -320,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
|
||||
|
||||
23
reader.h
23
reader.h
@@ -48,7 +48,7 @@ wchar_t *reader_current_filename();
|
||||
|
||||
\param fn The fileanme to push
|
||||
*/
|
||||
void reader_push_current_filename( wchar_t *fn );
|
||||
void reader_push_current_filename( const wchar_t *fn );
|
||||
/**
|
||||
Pop the current filename from the stack of read files
|
||||
*/
|
||||
@@ -152,27 +152,6 @@ void reader_set_prompt( wchar_t *prompt );
|
||||
*/
|
||||
int exit_status();
|
||||
|
||||
/**
|
||||
Find the beginning and the end of the current subshell
|
||||
*/
|
||||
void reader_current_subshell_extent( wchar_t **a, wchar_t **b );
|
||||
|
||||
/**
|
||||
Find the beginning and the end of the job under the cursor
|
||||
*/
|
||||
void reader_current_job_extent( wchar_t **a, wchar_t **b );
|
||||
|
||||
/**
|
||||
Find the beginning and the end of the process under the cursor
|
||||
*/
|
||||
void reader_current_process_extent( wchar_t **a, wchar_t **b );
|
||||
|
||||
/**
|
||||
Find the beginning and the end of the token under the curor and the token before the cursor
|
||||
*/
|
||||
|
||||
void reader_current_token_extent( wchar_t **a, wchar_t **b, wchar_t **pa, wchar_t **pb );
|
||||
|
||||
/**
|
||||
Replace the current token with the specified string
|
||||
*/
|
||||
|
||||
17
seq.in
17
seq.in
@@ -1,9 +1,24 @@
|
||||
#!@prefix@/bin/fish
|
||||
#!/usr/bin/env fish
|
||||
#
|
||||
# Fallback implementation of the seq command
|
||||
#
|
||||
# @configure_input@
|
||||
|
||||
set -l from 1
|
||||
set -l step 1
|
||||
set -l to 1
|
||||
|
||||
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
|
||||
|
||||
switch (count $argv)
|
||||
case 1
|
||||
set to $argv[1]
|
||||
|
||||
13
set_color.c
13
set_color.c
@@ -125,8 +125,13 @@ void print_colors()
|
||||
}
|
||||
}
|
||||
|
||||
static void locale_init()
|
||||
static void check_locale_init()
|
||||
{
|
||||
static int is_init = 0;
|
||||
if( is_init )
|
||||
return;
|
||||
|
||||
is_init = 1;
|
||||
setlocale( LC_ALL, "" );
|
||||
#if HAVE_GETTEXT
|
||||
bindtextdomain( PACKAGE_NAME, LOCALEDIR );
|
||||
@@ -142,7 +147,6 @@ int main( int argc, char **argv )
|
||||
int fg, bg;
|
||||
int bold=0;
|
||||
|
||||
locale_init();
|
||||
|
||||
|
||||
while( 1 )
|
||||
@@ -209,6 +213,7 @@ int main( int argc, char **argv )
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
check_locale_init();
|
||||
fprintf( stderr, _("%s, version %s\n"), SET_COLOR, PACKAGE_VERSION );
|
||||
exit( 0 );
|
||||
|
||||
@@ -235,12 +240,14 @@ int main( int argc, char **argv )
|
||||
break;
|
||||
|
||||
default:
|
||||
check_locale_init();
|
||||
printf( _("%s: Too many arguments\n"), SET_COLOR );
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( !fgcolor && !bgcolor && !bold )
|
||||
{
|
||||
check_locale_init();
|
||||
fprintf( stderr, _("%s: Expected an argument\n"), SET_COLOR );
|
||||
print_help();
|
||||
return 1;
|
||||
@@ -249,6 +256,7 @@ int main( int argc, char **argv )
|
||||
fg = translate_color(fgcolor);
|
||||
if( fgcolor && (fg==-1))
|
||||
{
|
||||
check_locale_init();
|
||||
fprintf( stderr, _("%s: Unknown color '%s'\n"), SET_COLOR, fgcolor );
|
||||
return 1;
|
||||
}
|
||||
@@ -256,6 +264,7 @@ int main( int argc, char **argv )
|
||||
bg = translate_color(bgcolor);
|
||||
if( bgcolor && (bg==-1))
|
||||
{
|
||||
check_locale_init();
|
||||
fprintf( stderr, _("%s: Unknown color '%s'\n"), SET_COLOR, bgcolor );
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
@@ -2,7 +2,7 @@
|
||||
complete -c apt-listchanges -l help -d (_ "Display help and exit")
|
||||
complete -c apt-listchanges -l apt -d (_ "Read filenames from pipe")
|
||||
complete -f -c apt-listchanges -s v -l verbose -d (_ "Verbose mode")
|
||||
complete -f -c apt-listchanges -s f -l frontend -a "pager browser xterm-pager xterm-browser text mail none" -d (_ "Select fronend interface")
|
||||
complete -f -c apt-listchanges -s f -l frontend -a "pager browser xterm-pager xterm-browser text mail none" -d (_ "Select frontend interface")
|
||||
complete -r -f -c apt-listchanges -l email-address -d (_ "Specify email address")
|
||||
complete -f -c apt-listchanges -s c -l confirm -d (_ "Ask confirmation")
|
||||
complete -f -c apt-listchanges -s a -l all -d (_ "Display all changelogs")
|
||||
@@ -12,7 +12,7 @@ complete -f -c apt-move -a mirror -d (_ "Download package missing from mirror")
|
||||
complete -f -c apt-move -a sync -d (_ "Sync packages installed")
|
||||
complete -f -c apt-move -a exclude -d 'test $LOCALDIR/.exclude file'
|
||||
complete -c apt-move -a movefile -d (_ "Move file specified on commandline")
|
||||
complete -f -c apt-move -a listbin -d (_ "List packags that may serve as input to mirrorbin or mirrorsource" )
|
||||
complete -f -c apt-move -a listbin -d (_ "List packages that may serve as input to mirrorbin or mirrorsource" )
|
||||
complete -f -c apt-move -a mirrorbin -d (_ "Fetch package from STDIN")
|
||||
complete -f -c apt-move -a mirrorsrc -d (_ "Fetch source package from STDIN")
|
||||
complete -f -c apt-move -s a -d (_ "Process all packages")
|
||||
@@ -1,6 +1,6 @@
|
||||
#apt-rdepends
|
||||
complete -c apt-rdepends -l help -d (_ "Display help and exit")
|
||||
complete -f -c apt-rdepends -s b -l build-depends -d (_ "Show bulid dependencies")
|
||||
complete -f -c apt-rdepends -s b -l build-depends -d (_ "Show build dependencies")
|
||||
complete -f -c apt-rdepends -s d -l dotty -d (_ "Generate a dotty graph")
|
||||
complete -f -c apt-rdepends -s p -l print-state -d (_ "Show state of dependencies")
|
||||
complete -f -c apt-rdepends -s r -l reverse -d (_ "List packages depending on")
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user