Merge branch 'master' of https://github.com/fish-shell/fish-shell into colorfix

This commit is contained in:
Aaron Gyes 2016-09-10 15:09:12 -07:00
commit af95813514
98 changed files with 2936 additions and 1742 deletions

21
.editorconfig Normal file
View file

@ -0,0 +1,21 @@
root = true
[*]
indent_size = 4
indent_style = space
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[{Makefile,*.in}]
indent_style = tab
[*.md]
trim_trailing_whitespace = false
[*.{sh,ac}]
indent_size = 2
[Dockerfile]
indent_size = 2

30
.gitattributes vendored
View file

@ -1,28 +1,42 @@
# normalize newlines
* text=auto
*.fish text
*.bat eol=crlf
# let git show off diff hunk headers, help git diff -L:
# https://git-scm.com/docs/gitattributes
*.cpp diff=cpp
*.py diff=py
# add a [diff "fish"] to git config with pattern
*.fish diff=fish
# omit from git archive
.gitattributes export-ignore .gitattributes export-ignore
.gitignore export-ignore .gitignore export-ignore
.travis.yml export-ignore .travis.yml export-ignore
fish.spec.in export-ignore fish.spec.in export-ignore
/build_tools/make_svn_completions.fish export-ignore /build_tools/make_svn_completions.fish export-ignore
/build_tools/description-pak export-ignore
/build_tools/make_hg_completions.fish export-ignore /build_tools/make_hg_completions.fish export-ignore
/build_tools/make_vcs_completions.fish export-ignore /build_tools/make_vcs_completions.fish export-ignore
/build_tools/make_vcs_completions_generic.fish export-ignore /build_tools/make_vcs_completions_generic.fish export-ignore
/build_tools/osx_package_resources export-ignore /build_tools/osx_package_resources export-ignore
/build_tools/osx_package_resources/terminal_logo.png export-ignore /build_tools/osx_package_resources/* export-ignore
/build_tools/osx_package_resources/welcome.rtf export-ignore
/build_tools/make_csv_completions.fish export-ignore /build_tools/make_csv_completions.fish export-ignore
/build_tools/osx_distribution.xml export-ignore /build_tools/osx_distribution.xml export-ignore
/build_tools/make_tarball.sh export-ignore /build_tools/make_tarball.sh export-ignore
/build_tools/make_deb.sh export-ignore
/build_tools/osx_package_scripts export-ignore /build_tools/osx_package_scripts export-ignore
/build_tools/osx_package_scripts/add-shell export-ignore /build_tools/osx_package_scripts/* export-ignore
/build_tools/osx_package_scripts/postinstall export-ignore
/build_tools/make_pkg.sh export-ignore /build_tools/make_pkg.sh export-ignore
/build_tools/make_darcs_completions.fish export-ignore /build_tools/make_darcs_completions.fish export-ignore
/debian export-ignore /debian export-ignore
/debian/* export-ignore /debian/* export-ignore
/.github export-ignore /.github export-ignore
/.github/* export-ignore /.github/* export-ignore
/pcre2-* linguist-vendored
/share/tools/web_config/js/angular.js linguist-vendored # for linguist; let github identify our project as C++ instead of C due to pcre2
/pcre2-10.21/ linguist-vendored
/pcre2-10.21/* linguist-vendored
angular.js linguist-vendored
/doc_src/* linguist-documentation /doc_src/* linguist-documentation
*.fish linguist-language=fish
tests/*.in linguist-language=fish

View file

@ -9,14 +9,13 @@
Talk about the the issue here. Talk about the the issue here.
## Reproduction steps ## Reproduction steps
Hard to explain? Link to [a screen recording](https://asciinema.org) 1. step one
1. Launch fish
2. … 2. …
## Expected results <!-- Hard to explain? Post a screen recording on asciinema.org then link it here -->
Fish should…
## Actual results ## Results
~ $ math 2 + 2 ```console
5 ~ $ math 2 + 2
5
```

127
.gitignore vendored
View file

@ -1,45 +1,98 @@
*.o # Note that some of the patterns below should be in an individual's
*~ # ~/.config/git/ignore file. For example, ".DS_Store" from people working on
*.exe # MacOS.
*.xccheckout
.DS_Store # File extensions that should never be checked in regardless of which project
# directory they reside in.
*.exe
*.app
*.out
*.so
*.dylib
*.dll
*.lai
*.la
*.a
*.lib
*.o
*.obj
*.lo
*.slo
*.d
*.gch
*.pch
*.xccheckout
*~
*~HEAD
*bak
*.new
*.orig
*.log
.Trash-*
*.DS_Store
.AppleDouble
.LSOverride
._*
Thumbs.db
ehthumbs.db
Desktop.ini
# These file names can appear anywhere in the hierarchy. They tend to be OS
# or build system artifacts.
autom4te.cache
Makefile Makefile
autom4te.cache/
build/
command_list.txt
command_list_toc.txt
confdefs.h
config.h config.h
config.cache
config.h.in config.h.in
config.log
config.status config.status
configure configure
doc/
doc.h
doc_src/commands.hdr
doc_src/index.hdr
po/*.gmo
fish
fish_key_reader
fish_indent
fish_tests
fish.pc
seq
set_color
share/__fish_build_paths.fish
share/man/
toc.txt
user_doc/
xcuserdata
test/
tests/*.tmp.*
FISH-BUILD-VERSION-FILE
version
messages.pot messages.pot
lexicon.txt .directory
lexicon_filter .fuse_hidden*
lexicon.log
# Directories that only contain transitory files from building and testing.
/doc/
/obj/
/share/man/
/share/doc/
/test/
/user_doc/
# File names that can appear in the project root that represent artifacts from
# building and testing.
/FISH-BUILD-VERSION-FILE
/command_list.txt
/command_list_toc.txt
/compile_commands.json
/confdefs.h
/doc.h
/fish
/fish.pc
/fish_indent
/fish_key_reader
/fish_tests
/lexicon.txt
/lexicon_filter
/toc.txt
/version
# File names that can appear below the project root that represent artifacts
# from building and testing.
/doc_src/commands.hdr
/doc_src/index.hdr
/po/*.gmo
/share/__fish_build_paths.fish
/tests/*.tmp.*
/share/pkgconfig
# xcode
## Build generated
build/
DerivedData/ DerivedData/
compile_commands.json xcuserdata/
xcodebuild.log *.moved-aside
*.xccheckout
*.xcscmblueprin

View file

@ -1,6 +1,25 @@
# next-2.x # next-2.x
## Significant changes ## Significant changes
- The clipboard integration has been revamped with explicit bindings. OS X clipboard support provided for out of the box in addition to X11. (#3061) - The clipboard integration has been revamped with explicit bindings. OS X clipboard support provided for out of the box in addition to X11. (#3061)
- Vi-style bindings no longer build upon the default emacs-style bindings, instead they share some definitions (#3068).
- Fish will now try to set the locale when it doesn't inherit one by reading system configuration (#277)
- A number followed by a caret is no longer treated as a redirection (#1873)
## Notable fixes and improvements
- Completions that don't match the prefix will no longer expand to a common prefix (#3090)
- Suggestions will be offered more often, like after removing characters (#3069)
- The argument handling for the `history` function has been revamped (#3293, #3224, #3220, #3182)
- Improved argument handling for the `abbr` function (#2997, #3267)
- `history --merge` now correctly interleaves items in chronological order (#2312)
- `history` gained a new "--with-time" ("-t") option to show timestamps (#3175)
- The "-d" option to `fish_indent` was removed (#3191)
- A bug where fish would sometimes hang using 100% CPU in the C locale (#3214)
- Fish now uses the $TZ variable for its idea of localtime (#3181)
- Some performance improvments to the git prompt (#3294, 3083)
- Working completion after an escaped space character (#2447)
- Less output to fish's build (#3248)
- Some additions or fixes to the completions for `brew` (#3309), `git` (#3274, #3226, #3225, #3094, #3087, #3035, #3021, #2982, #3230), `aura` (#3297)
- New completions for perforce ("p4") (#3314)
--- ---

View file

@ -741,7 +741,7 @@ CITE_BIB_FILES =
# messages are off. # messages are off.
# The default value is: NO. # The default value is: NO.
QUIET = NO QUIET = YES
# The WARNINGS tag can be used to turn on/off the warning messages that are # The WARNINGS tag can be used to turn on/off the warning messages that are
# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES # generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES

View file

@ -741,7 +741,7 @@ CITE_BIB_FILES =
# messages are off. # messages are off.
# The default value is: NO. # The default value is: NO.
QUIET = NO QUIET = YES
# The WARNINGS tag can be used to turn on/off the warning messages that are # The WARNINGS tag can be used to turn on/off the warning messages that are
# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES # generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES

View file

@ -23,6 +23,13 @@
# applications, install them, and recalculate dependencies. # applications, install them, and recalculate dependencies.
# #
# Verbosity
# make V=1 causes a noisy make, V=0 is silent/quiet. If one uses (lower case v)
# $(v) as a substitute for @, it will be replaced with an empty string for the
# default (V=1) case and replaced with @ in the V=0 case. You can use a bare @
# for things that should almost never print.
V := 0
# #
# This is the default value for SHELL but I like to be explicit about such # This is the default value for SHELL but I like to be explicit about such
# things. Especially in a project like fish where someone might otherwise # things. Especially in a project like fish where someone might otherwise
@ -38,11 +45,10 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
# #
# Programs # Programs
# #
CXX := @CXX@ CXX = @CXX@
INSTALL:=@INSTALL@ INSTALL := @INSTALL@
SED := @SED@ SED := @SED@
# #
# Installation directories # Installation directories
# #
@ -72,9 +78,8 @@ EXTRA_PCRE2 = @EXTRA_PCRE2@
# #
# Various flags # Various flags
# #
MACROS = -DLOCALEDIR=\"$(localedir)\" -DPREFIX=L\"$(prefix)\" -DDATADIR=L\"$(datadir)\" -DSYSCONFDIR=L\"$(sysconfdir)\" -DBINDIR=L\"$(bindir)\" -DDOCDIR=L\"$(docdir)\" CXXFLAGS = @CXXFLAGS@ $(EXTRA_CXXFLAGS)
CXXFLAGS = @CXXFLAGS@ -iquote. -iquote./src/ $(MACROS) $(EXTRA_CXXFLAGS) CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" -DPREFIX=L\"$(prefix)\" -DDATADIR=L\"$(datadir)\" -DSYSCONFDIR=L\"$(sysconfdir)\" -DBINDIR=L\"$(bindir)\" -DDOCDIR=L\"$(docdir)\" -iquote. -iquote./src/
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@ LDFLAGS = @LDFLAGS@
LIBS = @LIBS@ LIBS = @LIBS@
LDFLAGS_FISH = ${LDFLAGS} @LDFLAGS_FISH@ LDFLAGS_FISH = ${LDFLAGS} @LDFLAGS_FISH@
@ -122,7 +127,7 @@ FISH_TESTS_OBJS := $(FISH_OBJS) obj/fish_tests.o
# (that is, are not themselves #included in other source files) # (that is, are not themselves #included in other source files)
# #
FISH_ALL_OBJS := $(sort $(FISH_OBJS) $(FISH_INDENT_OBJS) $(FISH_TESTS_OBJS) $(FISH_KEYREAD_OBJS) \ FISH_ALL_OBJS := $(sort $(FISH_OBJS) $(FISH_INDENT_OBJS) $(FISH_TESTS_OBJS) $(FISH_KEYREAD_OBJS) \
obj/fish.o) obj/fish.o)
# #
# Files containing user documentation # Files containing user documentation
@ -135,7 +140,6 @@ FISH_ALL_OBJS := $(sort $(FISH_OBJS) $(FISH_INDENT_OBJS) $(FISH_TESTS_OBJS) $(FI
HDR_FILES_SRC := doc_src/index.hdr.in doc_src/tutorial.hdr doc_src/design.hdr \ HDR_FILES_SRC := doc_src/index.hdr.in doc_src/tutorial.hdr doc_src/design.hdr \
doc_src/license.hdr doc_src/commands.hdr.in doc_src/faq.hdr doc_src/license.hdr doc_src/commands.hdr.in doc_src/faq.hdr
# #
# These are the generated result files # These are the generated result files
# #
@ -178,8 +182,7 @@ PROGRAMS := fish fish_indent fish_key_reader
# #
# Manual pages to install # Manual pages to install
# #
MANUALS := $(addsuffix .1, $(addprefix share/man/man1/, \ MANUALS := $(addsuffix .1, $(addprefix share/man/man1/, $(PROGRAMS)))
$(PROGRAMS)))
# #
# All translation message catalogs # All translation message catalogs
@ -202,21 +205,53 @@ else
share_man= share_man=
endif endif
T_COLORS:=$(shell tput colors || echo 0 2> /dev/null)
#
# Functions for status output
#
T_GREEN := $(shell ( tput setaf 2 || tput AF 2 ) 2> /dev/null )
T_YELLOWB := $(shell ( tput setaf 3 || tput AF 3 ) 2> /dev/null )
T_CYAN := $(shell ( tput setaf 6 || tput AF 6 ) 2> /dev/null )
T_RED := $(shell ( tput setaf 1 || tput AF 1 ) 2> /dev/null )
T_BOLD := $(shell ( tput bold || tput md ) 2> /dev/null )
# * Italic: Rarely defined - it's common for it to work despite
# terminfo entries and isn't known to cause any recent > 256-color terminals
# to explode. If terminfo says a terminal supports 256 colors - it's fancy enough
# and won't have trouble the escape.
ifeq ($(T_COLORS), 256)
T_ITALIC := $(shell ( tput sitm || tput ZH || echo "\\033[3m" ) 2> /dev/null )
# * Half-bright/faint 'dim' mode - rarely works - rarely in terminfo when it does - but it's cool.
# Use it with one of the basic colors to get a fainter version of it.
T_DIM := $(shell ( tput dim || tput mh || [ $(TERM_PROGRAM) = Apple_Terminal ] && echo "\\033[2m") 2> /dev/null )
else
T_ITALIC := $(shell ( tput sitm || tput ZH ) 2> /dev/null )
T_DIM := $(shell ( tput dim || tput mh) 2> /dev/null )
endif
T_RESET := $(shell ( tput sgr0 || tput me) 2> /dev/null )
#
# A target that prettily shows VAR='$(VAR)' (properly escaped)
# Cool trick: `make show-$var` (e.g. make show-HAVE_DOXYGEN) to quickly see what $var is.
#
show-%:
@echo " $* = $(T_ITALIC)$(T_CYAN)'$(subst ',''',$($*))'$(T_RESET)" ||:
# #
# Make everything needed for installing fish # Make everything needed for installing fish
# #
all: $(PROGRAMS) $(user_doc) $(share_man) $(TRANSLATIONS) fish.pc share/__fish_build_paths.fish all: show-CXX show-CXXFLAGS $(PROGRAMS) $(user_doc) $(share_man) $(TRANSLATIONS) fish.pc share/__fish_build_paths.fish
@echo fish has now been built. @echo $(MAKECMDGOALS) | grep -vq install && echo "$(T_GREEN)fish has now been built.$(T_RESET)" ||:
@echo Use \'$(MAKE) install\' to install fish. @echo "Run $(T_YELLOWB)$(notdir $(MAKE)) install$(T_RESET) to install fish.$(T_RESET)" ||:
.PHONY: all .PHONY: all
# #
# Pull version information # Pull version information
# #
FISH-BUILD-VERSION-FILE: FORCE FISH-BUILD-VERSION-FILE: FORCE |
@./build_tools/git_version_gen.sh $(v)build_tools/git_version_gen.sh 2> /dev/null
-include FISH-BUILD-VERSION-FILE -include FISH-BUILD-VERSION-FILE
CXXFLAGS += -DFISH_BUILD_VERSION=\"$(FISH_BUILD_VERSION)\" CPPFLAGS += -DFISH_BUILD_VERSION=\"$(FISH_BUILD_VERSION)\"
.PHONY: FORCE .PHONY: FORCE
obj/fish_version.o: FISH-BUILD-VERSION-FILE obj/fish_version.o: FISH-BUILD-VERSION-FILE
@ -225,14 +260,18 @@ obj/fish_version.o: FISH-BUILD-VERSION-FILE
# when the source code for the build configuration has changed. # when the source code for the build configuration has changed.
# #
configure: configure.ac configure: configure.ac
./config.status --recheck @echo "Rechecking config.status; rerunning ./configure if necessary..."$(T_DIM)
$(v) ./config.status --recheck
@echo $(T_RESET)
Makefile: Makefile.in configure Makefile: Makefile.in configure
./config.status @echo "Checking config.status..."$(T_DIM)
$(v) ./config.status
@echo $(T_RESET)
# #
# Build fish with some debug flags specified. This is GCC specific, # Build fish with some debug flags specified. This is GCC specific,
# and should only be used when debuging fish. # and should only be used when debugging fish.
# #
prof: EXTRA_CXXFLAGS += -pg prof: EXTRA_CXXFLAGS += -pg
prof: LDFLAGS += -pg prof: LDFLAGS += -pg
@ -247,12 +286,12 @@ prof: all
# after the first -, for simpler version numbers. Cleans up the user_doc/html # after the first -, for simpler version numbers. Cleans up the user_doc/html
# directory once Doxygen is done. # directory once Doxygen is done.
# #
doc: $(HDR_FILES_SRC) Doxyfile.user $(HTML_SRC) $(HELP_SRC) doc.h \ doc: $(HDR_FILES_SRC) Doxyfile.user $(HTML_SRC) $(HELP_SRC) doc.h $(HDR_FILES) lexicon_filter | show-SED
$(HDR_FILES) lexicon_filter @echo " doxygen $(T_ITALIC)user_doc$(T_RESET)"
(cat Doxyfile.user; echo INPUT_FILTER=./lexicon_filter; \ $(v)(cat Doxyfile.user; echo INPUT_FILTER=./lexicon_filter; \
echo PROJECT_NUMBER=$(FISH_BUILD_VERSION) | $(SED) "s/-.*//") | \ echo PROJECT_NUMBER=$(FISH_BUILD_VERSION) | $(SED) "s/-.*//") | \
doxygen - && touch user_doc; \ doxygen - && touch user_doc
cd user_doc/html && rm -f arrow*.png bc_s.png bdwn.png closed.png \ $(v)cd user_doc/html && rm -f arrow*.png bc_s.png bdwn.png closed.png \
doc.png folder*.png ftv2*.png nav*.png open.png splitbar.png \ doc.png folder*.png ftv2*.png nav*.png open.png splitbar.png \
sync_*.png tab*.* doxygen.* dynsections.js jquery.js pages.html sync_*.png tab*.* doxygen.* dynsections.js jquery.js pages.html
@ -260,10 +299,8 @@ doc: $(HDR_FILES_SRC) Doxyfile.user $(HTML_SRC) $(HELP_SRC) doc.h \
# PDF version of the source code documentation. # PDF version of the source code documentation.
# #
doc/refman.pdf: doc doc/refman.pdf: doc
cd doc/latex && \ $(v)cd doc/latex && $(MAKE) V=$(V) && mv refman.pdf ..
make && \ $(v)rm -rf doc/latex
mv refman.pdf ..;
rm -r doc/latex;
# #
# Prep the environment for running the unit tests. When specifying DESTDIR on # Prep the environment for running the unit tests. When specifying DESTDIR on
@ -272,12 +309,12 @@ doc/refman.pdf: doc
# followed by `make install`. # followed by `make install`.
# #
test-prep: test-prep:
rm -rf test $(v)rm -rf test
mkdir test test/data test/home test/temp $(v)mkdir test test/data test/home test/temp
ifdef DESTDIR ifdef DESTDIR
ln -s $(DESTDIR) test/root $(v)ln -s $(DESTDIR) test/root
else else
mkdir test/root $(v)mkdir test/root
endif endif
.PHONY: test-prep .PHONY: test-prep
@ -290,8 +327,8 @@ endif
test: DESTDIR = $(PWD)/test/root/ test: DESTDIR = $(PWD)/test/root/
test: prefix = . test: prefix = .
test: test-prep install-force test_low_level test_high_level test: test-prep install-force test_low_level test_high_level
@rm -f /tmp/file_truncation_test.txt /tmp/tee_test.txt /tmp/fish_foo.txt $(v)rm -f /tmp/file_truncation_test.txt /tmp/tee_test.txt /tmp/fish_foo.txt
@rm -rf /tmp/is_potential_path_test $(v)rm -rf /tmp/is_potential_path_test
.PHONY: test .PHONY: test
# #
@ -333,8 +370,8 @@ test_interactive: $(call filter_up_to,test_interactive,$(active_test_goals))
# builtins # builtins
# #
doc_src/commands.hdr:$(HELP_SRC) doc_src/commands.hdr.in doc_src/commands.hdr:$(HELP_SRC) doc_src/commands.hdr.in
-rm command_list.tmp command_list_toc.tmp $@ $(v)rm -f command_list.tmp command_list_toc.tmp $@
for i in `printf "%s\n" $(HELP_SRC)|sort`; do \ $(v)for i in `printf "%s\n" $(HELP_SRC)|sort`; do \
echo "<hr>" >>command_list.tmp; \ echo "<hr>" >>command_list.tmp; \
cat $$i >>command_list.tmp; \ cat $$i >>command_list.tmp; \
echo >>command_list.tmp; \ echo >>command_list.tmp; \
@ -343,28 +380,28 @@ doc_src/commands.hdr:$(HELP_SRC) doc_src/commands.hdr.in
echo '- <a href="#'$$NAME'">'$$NAME'</a>' >> command_list_toc.tmp; \ echo '- <a href="#'$$NAME'">'$$NAME'</a>' >> command_list_toc.tmp; \
echo "Back to <a href='index.html#toc-commands'>index</a>". >>command_list.tmp; \ echo "Back to <a href='index.html#toc-commands'>index</a>". >>command_list.tmp; \
done done
mv command_list.tmp command_list.txt $(v)mv command_list.tmp command_list.txt
mv command_list_toc.tmp command_list_toc.txt $(v)mv command_list_toc.tmp command_list_toc.txt
cat $@.in | awk '{if ($$0 ~ /@command_list_toc@/) { system("cat command_list_toc.txt"); } else if ($$0 ~ /@command_list@/){ system("cat command_list.txt");} else{ print $$0;}}' >$@ $(v)cat $@.in | awk '{if ($$0 ~ /@command_list_toc@/) { system("cat command_list_toc.txt"); } else if ($$0 ~ /@command_list@/){ system("cat command_list.txt");} else{ print $$0;}}' >$@
toc.txt: $(HDR_FILES:index.hdr=index.hdr.in) toc.txt: $(HDR_FILES:index.hdr=index.hdr.in)
-rm toc.tmp $@ $(v)rm -f toc.tmp $@
# Ugly hack to set the toc initial title for the main page # Ugly hack to set the toc initial title for the main page
echo '- <a href="index.html" id="toc-index">Documentation</a>' > toc.tmp $(v)echo '- <a href="index.html" id="toc-index">Documentation</a>' > toc.tmp
# The first sed command captures the page name, followed by the description # The first sed command captures the page name, followed by the description
# The second sed command captures the command name \1 and the description \2, but only up to a dash # The second sed command captures the command name \1 and the description \2, but only up to a dash
# This is to reduce the size of the TOC in the command listing on the main page # This is to reduce the size of the TOC in the command listing on the main page
for i in $(HDR_FILES:index.hdr=index.hdr.in); do\ $(v)for i in $(HDR_FILES:index.hdr=index.hdr.in); do\
NAME=`basename $$i .hdr`; \ NAME=`basename $$i .hdr`; \
NAME=`basename $$NAME .hdr.in`; \ NAME=`basename $$NAME .hdr.in`; \
$(SED) <$$i >>toc.tmp -n \ $(SED) <$$i >>toc.tmp -n \
-e 's,.*\\page *\([^ ]*\) *\(.*\)$$,- <a href="'$$NAME'.html" id="toc-'$$NAME'">\2</a>,p' \ -e 's,.*\\page *\([^ ]*\) *\(.*\)$$,- <a href="'$$NAME'.html" id="toc-'$$NAME'">\2</a>,p' \
-e 's,.*\\section *\([^ ]*\) *\([^-]*\)\(.*\)$$, - <a href="'$$NAME'.html#\1">\2</a>,p'; \ -e 's,.*\\section *\([^ ]*\) *\([^-]*\)\(.*\)$$, - <a href="'$$NAME'.html#\1">\2</a>,p'; \
done done
mv toc.tmp $@ $(v)mv toc.tmp $@
doc_src/index.hdr: toc.txt doc_src/index.hdr.in doc_src/index.hdr: toc.txt doc_src/index.hdr.in
cat $@.in | awk '{if ($$0 ~ /@toc@/){ system("cat toc.txt");} else{ print $$0;}}' >$@ $(v)cat $@.in | awk '{if ($$0 ~ /@toc@/){ system("cat toc.txt");} else{ print $$0;}}' >$@
# #
# To enable the lexicon filter, we first need to be aware of what fish # To enable the lexicon filter, we first need to be aware of what fish
@ -375,10 +412,11 @@ doc_src/index.hdr: toc.txt doc_src/index.hdr.in
# colour defaults from __fish_config_interactive to set the docs colours when # colour defaults from __fish_config_interactive to set the docs colours when
# used in a 'cli' style context. # used in a 'cli' style context.
# #
lexicon.txt: doc_src/commands.hdr $(FUNCTIONS_DIR_FILES) $(COMPLETIONS_DIR_FILES) share/functions/__fish_config_interactive.fish lexicon.txt: doc_src/commands.hdr $(FUNCTIONS_DIR_FILES) $(COMPLETIONS_DIR_FILES) share/functions/__fish_config_interactive.fish | show-SED
-rm lexicon.tmp lexicon_catalog.tmp lexicon_catalog.txt $@ $(v)rm -f lexicon.tmp lexicon_catalog.tmp lexicon_catalog.txt $@
# Scan sources for commands/functions/binaries/colours. If GNU sed was portable, this could be much smarter. # Scan sources for commands/functions/binaries/colours. If GNU sed was portable, this could be much smarter.
$(SED) <command_list_toc.txt >>lexicon.tmp -n \ @echo " SED $(T_ITALIC)$@$(T_RESET)"
$(v)$(SED) <command_list_toc.txt >>lexicon.tmp -n \
-e "s|^.*>\([a-z][a-z_]*\)</a>|'\1'|w lexicon_catalog.tmp" \ -e "s|^.*>\([a-z][a-z_]*\)</a>|'\1'|w lexicon_catalog.tmp" \
-e "s|'\(.*\)'|bltn \1|p"; mv lexicon_catalog.tmp lexicon_catalog.txt; \ -e "s|'\(.*\)'|bltn \1|p"; mv lexicon_catalog.tmp lexicon_catalog.txt; \
printf "%s\n" $(COMPLETIONS_DIR_FILES) | $(SED) -n \ printf "%s\n" $(COMPLETIONS_DIR_FILES) | $(SED) -n \
@ -389,7 +427,7 @@ lexicon.txt: doc_src/commands.hdr $(FUNCTIONS_DIR_FILES) $(COMPLETIONS_DIR_FILES
-e "s|[^ ]*/\([a-z][a-z_-]*\).fish|'\1'|p" | fgrep -vx -f lexicon_catalog.txt | $(SED) >>lexicon.tmp -n \ -e "s|[^ ]*/\([a-z][a-z_-]*\).fish|'\1'|p" | fgrep -vx -f lexicon_catalog.txt | $(SED) >>lexicon.tmp -n \
-e 'w lexicon_catalog.tmp' \ -e 'w lexicon_catalog.tmp' \
-e "s|'\(.*\)'|func \1|p"; \ -e "s|'\(.*\)'|func \1|p"; \
$(SED) <share/functions/__fish_config_interactive.fish >>lexicon.tmp -n \ $(SED) <share/functions/__fish_config_interactive.fish >>lexicon.tmp -n \
-e '/set_default/s/.*\(fish_[a-z][a-z_]*\).*$$/clrv \1/p'; \ -e '/set_default/s/.*\(fish_[a-z][a-z_]*\).*$$/clrv \1/p'; \
$(SED) <lexicon_filter.in >>lexicon.tmp -n \ $(SED) <lexicon_filter.in >>lexicon.tmp -n \
-e '/^#.!#/s/^#.!# \(.... [a-z][a-z_]*\)/\1/p'; \ -e '/^#.!#/s/^#.!# \(.... [a-z][a-z_]*\)/\1/p'; \
@ -405,12 +443,13 @@ lexicon.txt: doc_src/commands.hdr $(FUNCTIONS_DIR_FILES) $(COMPLETIONS_DIR_FILES
# HTML, a style context can be applied through the /fish{style} block and # HTML, a style context can be applied through the /fish{style} block and
# providing suitable CSS in user_doc.css.in # providing suitable CSS in user_doc.css.in
# #
lexicon_filter: lexicon.txt lexicon_filter.in lexicon_filter: lexicon.txt lexicon_filter.in | show-SED
-rm $@.tmp $@ $(v)rm -f $@.tmp $@
# Set the shebang as sed can reside in multiple places. @echo " SED $(T_ITALIC)$@$(T_RESET)"
$(SED) <$@.in >$@.tmp -e 's|@sed@|'$(SED)'|' # Set the shebang as sed can reside in multiple places.
# Scan through the lexicon, transforming each line to something useful to Doxygen. $(v)$(SED) <$@.in >$@.tmp -e 's|@sed@|'$(SED)'|'
if echo x | $(SED) "/[[:<:]]x/d" 2>/dev/null; then \ # Scan through the lexicon, transforming each line to something useful to Doxygen.
$(v)if echo x | $(SED) "/[[:<:]]x/d" 2>/dev/null; then \
WORDBL='[[:<:]]'; WORDBR='[[:>:]]'; \ WORDBL='[[:<:]]'; WORDBR='[[:>:]]'; \
else \ else \
WORDBL='\\<'; WORDBR='\\>'; \ WORDBL='\\<'; WORDBR='\\>'; \
@ -427,7 +466,7 @@ lexicon_filter: lexicon.txt lexicon_filter.in
# documentation. # documentation.
# #
doc.h: $(HDR_FILES) doc.h: $(HDR_FILES)
cat $(HDR_FILES) >$@ $(v)cat $(HDR_FILES) >$@
# #
# This rule creates complete doxygen headers from each of the various # This rule creates complete doxygen headers from each of the various
@ -444,8 +483,8 @@ doc.h: $(HDR_FILES)
# Depend on Makefile because I don't see a better way of rebuilding # Depend on Makefile because I don't see a better way of rebuilding
# if any of the paths change. # if any of the paths change.
# #
%: %.in Makefile FISH-BUILD-VERSION-FILE %: %.in Makefile FISH-BUILD-VERSION-FILE | show-prefix show-sysconfdir show-docdir show-extra_completionsdir show-extra_functionsdir show-extra_confdir show-prefix show-FISH_BUILD_VERSION
$(SED) <$< >$@ \ $(v)$(SED) <$< >$@ \
-e "s,@sysconfdir\@,$(sysconfdir),g" \ -e "s,@sysconfdir\@,$(sysconfdir),g" \
-e "s,@datadir\@,$(datadir),g" \ -e "s,@datadir\@,$(datadir),g" \
-e "s,@docdir\@,$(docdir),g" \ -e "s,@docdir\@,$(docdir),g" \
@ -461,13 +500,15 @@ doc.h: $(HDR_FILES)
# Compile translation files to binary format # Compile translation files to binary format
# #
%.gmo: %.gmo:
msgfmt -o $@ $*.po @echo " msgfmt $(T_ITALIC)$@$(T_RESET)"
$(v)msgfmt -o $@ $*.po
# #
# Update existing po file or copy messages.pot # Update existing po file or copy messages.pot
# #
%.po:messages.pot %.po:messages.pot
if test -f $*.po; then \ @echo " msgmerge $(T_ITALIC)$@$(T_RESET)"
$(v)if test -f $*.po; then \
msgmerge -U --backup=existing $*.po messages.pot;\ msgmerge -U --backup=existing $*.po messages.pot;\
else \ else \
cp messages.pot $*.po;\ cp messages.pot $*.po;\
@ -477,8 +518,9 @@ doc.h: $(HDR_FILES)
# Create a template translation object # Create a template translation object
# #
messages.pot: src/*.cpp src/*.h share/completions/*.fish share/functions/*.fish messages.pot: src/*.cpp src/*.h share/completions/*.fish share/functions/*.fish
xgettext -k_ -kN_ src/*.cpp src/*.h -o messages.pot @echo " xgettext $(T_ITALIC)$@$(T_RESET)"
xgettext -j -k_ -kN_ -k--description -LShell --from-code=UTF-8 share/completions/*.fish share/functions/*.fish -o messages.pot $(v)xgettext -k_ -kN_ src/*.cpp src/*.h -o messages.pot
$(v)xgettext -j -k_ -kN_ -k--description -LShell --from-code=UTF-8 share/completions/*.fish share/functions/*.fish -o messages.pot
ifdef EXTRA_PCRE2 ifdef EXTRA_PCRE2
src/builtin_string.cpp: $(PCRE2_H) src/builtin_string.cpp: $(PCRE2_H)
@ -510,49 +552,59 @@ endif
# #
# There ought to be something simpler. # There ought to be something simpler.
# #
share/man: $(HELP_SRC) lexicon_filter share/man: $(HELP_SRC) lexicon_filter | show-FISH_BUILD_VERSION show-SED
-mkdir share/man -$(v)mkdir -p share/man
touch share/man @echo " doxygen $(T_ITALIC)$@$(T_RESET)"
-rm -Rf share/man/man1 $(v)touch share/man
-$(v)rm -Rf share/man/man1
$(v)echo "$(T_DIM)" && \
PROJECT_NUMBER=`echo $(FISH_BUILD_VERSION)| $(SED) "s/-.*//"` INPUT_FILTER=./lexicon_filter \ PROJECT_NUMBER=`echo $(FISH_BUILD_VERSION)| $(SED) "s/-.*//"` INPUT_FILTER=./lexicon_filter \
./build_tools/build_documentation.sh Doxyfile.help ./doc_src ./share build_tools/build_documentation.sh Doxyfile.help ./doc_src ./share; echo "$(T_RESET)";
# #
# The build rules for installing/uninstalling fish # The build rules for installing/uninstalling fish
# #
check-legacy-binaries: check-legacy-binaries:
@SEQLOC=$(prefix)/bin/seq;\ @echo "Checking for legacy binaries..."
$(v)KR_LOC=$(prefix)/bin/key_reader;\
if test -x "$$KR_LOC" && env TERM=dumb "$$KR_LOC" cr | grep -q 26; then\
echo "$(T_RED)A key_reader binary was found. You might want to remove this, and use 'fish_key_reader':";\
echo " '$$KR_LOC'$(T_RESET)";\
fi;
$(v)SEQLOC=$(prefix)/bin/seq;\
if test -f "$$SEQLOC" && grep -q '\(^#!/.*/fish\|^#!/usr/bin/env fish\)' "$$SEQLOC"; then\ if test -f "$$SEQLOC" && grep -q '\(^#!/.*/fish\|^#!/usr/bin/env fish\)' "$$SEQLOC"; then\
echo "An outdated seq from a previous fish install was found. You should remove it with:";\ echo "$(T_RED)An outdated seq from a previous fish install was found. You should remove it with:";\
echo " rm '$$SEQLOC'";\ echo " rm '$$SEQLOC'$(T_RESET)";\
fi; fi;
@SETCOLOR_LOC=$(prefix)/bin/set_color;\ $(v)SETCOLOR_LOC=$(prefix)/bin/set_color;\
if test -x "$$SETCOLOR_LOC" && $$SETCOLOR_LOC -v 2>&1 >/dev/null | grep -q "^set_color, version "; then\ if test -x "$$SETCOLOR_LOC" && $$SETCOLOR_LOC -v 2>&1 >/dev/null | grep -q "^set_color, version "; then\
echo "An outdated set_color from a previous fish install was found. You should remove it with:";\ echo "$(T_RED)An outdated set_color from a previous fish install was found. You should remove it with:";\
echo " rm '$$SETCOLOR_LOC'";\ echo " rm '$$SETCOLOR_LOC'$(T_RESET)";\
fi; fi;
@MIMEDB_LOC=$(prefix)/bin/mimedb;\ $(v)MIMEDB_LOC=$(prefix)/bin/mimedb;\
if test -x "$$MIMEDB_LOC" && $$MIMEDB_LOC --version 2>&1 | grep -q "^mimedb, version "; then\ if test -x "$$MIMEDB_LOC" && $$MIMEDB_LOC --version 2>&1 | grep -q "^mimedb, version "; then\
echo "An outdated mimedb binary from a previous fish install was found. You should remove it with:";\ echo "$(T_RED)An outdated mimedb binary from a previous fish install was found. You should remove it with:";\
echo " rm '$$MIMEDB_LOC'";\ echo " rm '$$MIMEDB_LOC'$(T_RESET)";\
fi; fi;
@FISHD_LOC=$(prefix)/bin/fishd;\ $(v)FISHD_LOC=$(prefix)/bin/fishd;\
if test -x "$$FISHD_LOC" && $$FISHD_LOC --version 2>&1 | grep -q "^fishd: fishd, version "; then\ if test -x "$$FISHD_LOC" && $$FISHD_LOC --version 2>&1 | grep -q "^fishd: fishd, version "; then\
echo "An outdated fishd binary from a previous fish install was found. You should remove it with:";\ echo "$(T_RED)An outdated fishd binary from a previous fish install was found. You should remove it with:";\
echo " rm '$$FISHD_LOC'";\ echo " rm '$$FISHD_LOC'$(T_RESET)";\
fi; fi;
@true; $(v)true;
.PHONY: check-legacy-binaries .PHONY: check-legacy-binaries
install: all install-force check-legacy-binaries install: all install-force | check-legacy-binaries
@echo fish is now installed on your system. @echo
@echo To run fish, type \'fish\' in your terminal. @echo "$(T_BOLD)fish is now installed on your system.$(T_RESET)"
@echo "To run fish, type $(T_BOLD)$(T_GREEN)fish$(T_RESET) in your terminal."
@echo "$(T_YELLOW)Even if you are already in fish, you should now start a new fish session.$(T_RESET)"
@echo @echo
@if type chsh >/dev/null 2>&1; then \ @if type chsh >/dev/null 2>&1; then \
echo To use fish as your login shell:; \ echo To use fish as your login shell:; \
grep -q -- "$(DESTDIR)$(bindir)/fish" /etc/shells || echo \* add the line \'$(DESTDIR)$(bindir)/fish\' to the file \'/etc/shells\'.; \ grep -q -- "$(DESTDIR)$(bindir)/fish" /etc/shells || echo \* add the line \'$(DESTDIR)$(bindir)/fish\' to the file \'/etc/shells\'; \
echo \* use the command \'chsh -s $(DESTDIR)$(bindir)/fish\'.; \ echo " * run $(T_YELLOWB)chsh -s $(DESTDIR)$(bindir)/fish$(T_RESET)"; \
echo; \ echo; \
fi; fi;
@if type chcon >/dev/null 2>&1; then \ @if type chcon >/dev/null 2>&1; then \
@ -560,97 +612,107 @@ install: all install-force check-legacy-binaries
echo \* use the command \'chcon -t shell_exec_t $(DESTDIR)$(bindir)/fish\'.; \ echo \* use the command \'chcon -t shell_exec_t $(DESTDIR)$(bindir)/fish\'.; \
echo; \ echo; \
fi; fi;
@echo To set your colors, run \'fish_config\' @echo "To set your colors, run $(T_GREEN)$(T_BOLD)fish_config$(T_RESET)"
@echo To scan your man pages for completions, run \'fish_update_completions\' @echo "To scan your man pages for completions, run $(T_GREEN)$(T_BOLD)fish_update_completions$(T_RESET)"
@echo To autocomplete command suggestions press Ctrl + F or right arrow key. @echo "To accept autosuggestions (in $(T_DIM)grey$(T_RESET)) as you type, hit $(T_BOLD)ctrl-F$(T_RESET) or right arrow key."
@echo @echo
@echo Have fun! @echo "$(T_BOLD)Have fun! <><$(T_RESET)"
.PHONY: install .PHONY: install
# #
# Xcode install # Xcode install
# #
xcode-install: xcode-install:
rm -Rf /tmp/fish_build;\ rm -Rf /tmp/fish_build
xcodebuild install DSTROOT=/tmp/fish_build;\ xcodebuild install DSTROOT=/tmp/fish_build
ditto /tmp/fish_build / ditto /tmp/fish_build
.PHONY: xcode-install .PHONY: xcode-install
# #
# Actually do the installation. These 'true' lines are to prevent installs # Actually do the installation. These '||true', '||:' lines are to prevent installs
# from failing for (e.g.) missing man pages or extra_dirs outside the # from failing for (e.g.) missing man pages or extra_dirs outside the
# writeable prefix. # writeable prefix.
# #
install-force: all install-translations install-force: all install-translations | show-datadir show-sysconfdir show-extra_completionsdir show-extra_functionsdir show-extra_confdir show-mandir
$(INSTALL) -m 755 -d $(DESTDIR)$(bindir) $(v)$(INSTALL) -m 755 -d $(DESTDIR)$(bindir)
for i in $(PROGRAMS); do\ $(v)for i in $(PROGRAMS); do\
$(INSTALL) -m 755 $$i $(DESTDIR)$(bindir) ; \ $(INSTALL) -m 755 $$i $(DESTDIR)$(bindir);\
echo " Installing $(T_BOLD)$$i$(T_RESET)";\
true ;\ true ;\
done; done;
$(INSTALL) -m 755 -d $(DESTDIR)$(sysconfdir)/fish @echo "Creating sysconfdir tree"
$(INSTALL) -m 755 -d $(DESTDIR)$(sysconfdir)/fish/conf.d $(v)$(INSTALL) -m 755 -d $(DESTDIR)$(sysconfdir)/fish
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish $(v)$(INSTALL) -m 755 -d $(DESTDIR)$(sysconfdir)/fish/conf.d
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/completions $(v)$(INSTALL) -m 644 etc/config.fish $(DESTDIR)$(sysconfdir)/fish/
$(INSTALL) -m 755 -d $(DESTDIR)$(extra_completionsdir); true @echo "Creating datadir tree"
$(INSTALL) -m 755 -d $(DESTDIR)$(extra_functionsdir); true $(v)$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish
$(INSTALL) -m 755 -d $(DESTDIR)$(extra_confdir); true $(v)$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/completions
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/functions $(v)$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/functions
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/man/man1 $(v)$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/man/man1
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/tools $(v)$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/tools
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/tools/web_config $(v)$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/tools/web_config
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/tools/web_config/js $(v)$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/tools/web_config/js
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/tools/web_config/partials $(v)$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/tools/web_config/partials
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/tools/web_config/sample_prompts $(v)$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/tools/web_config/sample_prompts
$(INSTALL) -m 644 etc/config.fish $(DESTDIR)$(sysconfdir)/fish/ $(v)$(INSTALL) -m 644 share/config.fish $(DESTDIR)$(datadir)/fish/
$(INSTALL) -m 644 share/config.fish $(DESTDIR)$(datadir)/fish/ $(v)$(INSTALL) -m 644 share/__fish_build_paths.fish $(DESTDIR)$(datadir)/fish/
$(INSTALL) -m 644 share/__fish_build_paths.fish $(DESTDIR)$(datadir)/fish/ $(v)$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/pkgconfig
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/pkgconfig @echo "Creating empty vendor/'extra_' directories"
$(INSTALL) -m 644 fish.pc $(DESTDIR)$(datadir)/pkgconfig $(v)$(INSTALL) -m 755 -d $(DESTDIR)$(extra_completionsdir) ||:
for i in $(COMPLETIONS_DIR_FILES:%='%'); do \ $(v)$(INSTALL) -m 755 -d $(DESTDIR)$(extra_functionsdir) ||:
$(v)$(INSTALL) -m 755 -d $(DESTDIR)$(extra_confdir) ||:
@echo "Installing pkgconfig file"
$(v)$(INSTALL) -m 644 fish.pc $(DESTDIR)$(datadir)/pkgconfig
@echo "Installing the $(T_BOLD)fish completion libraryn$(T_RESET)...";
$(v)for i in $(COMPLETIONS_DIR_FILES:%='%'); do \
$(INSTALL) -m 644 $$i $(DESTDIR)$(datadir)/fish/completions/; \ $(INSTALL) -m 644 $$i $(DESTDIR)$(datadir)/fish/completions/; \
true; \ true; \
done; done;
for i in $(FUNCTIONS_DIR_FILES:%='%'); do \ @echo "Installing $(T_BOLD)fish functions$(T_RESET)";
$(v)for i in $(FUNCTIONS_DIR_FILES:%='%'); do \
$(INSTALL) -m 644 $$i $(DESTDIR)$(datadir)/fish/functions/; \ $(INSTALL) -m 644 $$i $(DESTDIR)$(datadir)/fish/functions/; \
true; \ true; \
done; done;
for i in share/man/man1/*.1; do \ @echo "Installing $(T_BOLD)man pages$(T_RESET)";
$(v)for i in share/man/man1/*.1; do \
$(INSTALL) -m 644 $$i $(DESTDIR)$(datadir)/fish/man/man1/; \ $(INSTALL) -m 644 $$i $(DESTDIR)$(datadir)/fish/man/man1/; \
true; \ true; \
done; done;
for i in share/tools/*.py; do\ @echo "Installing $(T_BOLD)fish tools$(T_RESET)";
$(v)for i in share/tools/*.py; do\
$(INSTALL) -m 755 $$i $(DESTDIR)$(datadir)/fish/tools/; \ $(INSTALL) -m 755 $$i $(DESTDIR)$(datadir)/fish/tools/; \
true; \ true; \
done; done;
for i in share/tools/web_config/*; do\ $(v)for i in share/tools/web_config/*.*; do\
$(INSTALL) -m 644 $$i $(DESTDIR)$(datadir)/fish/tools/web_config/; \ $(INSTALL) -m 644 $$i $(DESTDIR)$(datadir)/fish/tools/web_config/; \
true; \ true; \
done; done;
for i in share/tools/web_config/js/*; do\ $(v)for i in share/tools/web_config/js/*.*; do\
$(INSTALL) -m 644 $$i $(DESTDIR)$(datadir)/fish/tools/web_config/js/; \ $(INSTALL) -m 644 $$i $(DESTDIR)$(datadir)/fish/tools/web_config/js/; \
true; \ true; \
done; done;
for i in share/tools/web_config/partials/*; do\ $(v)for i in share/tools/web_config/partials/*; do\
$(INSTALL) -m 644 $$i $(DESTDIR)$(datadir)/fish/tools/web_config/partials/; \ $(INSTALL) -m 644 $$i $(DESTDIR)$(datadir)/fish/tools/web_config/partials/; \
true; \ true; \
done; done;
for i in share/tools/web_config/sample_prompts/*.fish; do\ $(v)for i in share/tools/web_config/sample_prompts/*.fish; do\
$(INSTALL) -m 644 $$i $(DESTDIR)$(datadir)/fish/tools/web_config/sample_prompts/; \ $(INSTALL) -m 644 $$i $(DESTDIR)$(datadir)/fish/tools/web_config/sample_prompts/; \
true; \ true; \
done; done;
for i in share/tools/web_config/*.py; do\ $(v)for i in share/tools/web_config/*.py; do\
$(INSTALL) -m 755 $$i $(DESTDIR)$(datadir)/fish/tools/web_config/; \ $(INSTALL) -m 755 $$i $(DESTDIR)$(datadir)/fish/tools/web_config/; \
true; \ true; \
done; done;
@echo "Installing HTML documentation";
$(INSTALL) -m 755 -d $(DESTDIR)$(docdir) $(v)$(INSTALL) -m 755 -d $(DESTDIR)$(docdir)
for i in user_doc/html/* CHANGELOG.md; do \ $(v) for i in user_doc/html/* CHANGELOG.md; do \
if test -f $$i; then \ if test -f $$i; then \
$(INSTALL) -m 644 $$i $(DESTDIR)$(docdir); \ $(INSTALL) -m 644 $$i $(DESTDIR)$(docdir); \
fi; \ fi; \
done; done;
$(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man1 @echo "Installing more man pages";
for i in $(MANUALS); do \ $(v)$(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man1;
$(v) for i in $(MANUALS); do \
$(INSTALL) -m 644 $$i $(DESTDIR)$(mandir)/man1/; \ $(INSTALL) -m 644 $$i $(DESTDIR)$(mandir)/man1/; \
true; \ true; \
done; done;
@ -659,37 +721,72 @@ install-force: all install-translations
# #
# Uninstall this fish version # Uninstall this fish version
# #
uninstall: uninstall-translations uninstall: uninstall-translations | show-prefix show-bindir show-sysconfdir show-datadir show-docdir show-mandir
-for i in $(PROGRAMS); do \ @echo
@echo "$(T_BOLD)$(T_YELLOWB)Uninstalling fish$(T_RESET) from configured \$$prefix: $(T_BOLD)$(prefix)$(T_RESET)"
@echo
@echo "Deleting programs: [ $(T_BOLD)$(PROGRAMS)$(T_RESET) ] in $(T_ITALIC)$(bindir)$(T_RESET)"
-$(v)for i in $(PROGRAMS); do \
rm -f $(DESTDIR)$(bindir)/$$i; \ rm -f $(DESTDIR)$(bindir)/$$i; \
done; done;
-rm -rf $(DESTDIR)$(sysconfdir)/fish @echo "Deleting configuration: $(T_BOLD)$(DESTDIR)$(sysconfdir)/fish/*$(T_RESET)"
-if test -d $(DESTDIR)$(datadir)/fish; then \ -$(v)rm -rf $(DESTDIR)$(sysconfdir)/fish
rm -r $(DESTDIR)$(datadir)/fish; \ @echo
@echo "In 5 seconds, $(T_RED)all data$(T_RESET) (includes functions, completions, tools) in"
@echo $$"\t$(T_BOLD)$(DESTDIR)$(datadir)/fish$(T_RESET) will be deleted!"
@echo
@echo $$"If you put things there, $(T_RED)stop now!$(T_RESET) $(T_BOLD)\\c"
@echo $$"$(T_BOLD)5$(T_RESET) \\c"
@sleep 1
@echo $$"$(T_BOLD)4$(T_RESET) \\c"
@sleep 1
@echo $$"$(T_BOLD)3$(T_RESET) \\c"
@sleep 1
@echo $$"$(T_BOLD)2$(T_RESET) \\c"
@sleep 1
@echo $$"$(T_BOLD)1$(T_RESET) \\c"
@sleep 1
@echo ...
@sleep 2
@echo "... deleting $(T_BOLD)$(DESTDIR)$(datadir)/fish/*$(T_RESET)"
-$(v) if test -d $(DESTDIR)$(datadir)/fish; then \
rm -rf $(DESTDIR)$(datadir)/fish; \
fi fi
-if test -d $(DESTDIR)$(docdir); then \ @echo
@echo "Deleting documentation: $(T_BOLD)$(DESTDIR)$(docdir)/*$(T_RESET)"
-$(v) if test -d $(DESTDIR)$(docdir); then \
rm -rf $(DESTDIR)$(docdir);\ rm -rf $(DESTDIR)$(docdir);\
fi fi
-if test -f $(DESTDIR)$(datadir)/pkgconfig/fish.pc; then \ @echo
@echo "Deleting pkgconfig file: $(T_BOLD)$(DESTDIR)$(datadir)/pkgconfig/fish.pc$(T_RESET)"
-$(v) if test -f $(DESTDIR)$(datadir)/pkgconfig/fish.pc; then \
rm -f $(DESTDIR)$(datadir)/pkgconfig/fish.pc;\ rm -f $(DESTDIR)$(datadir)/pkgconfig/fish.pc;\
fi fi
-for i in $(MANUALS); do \ @echo
@echo $$"Deleting \\c"
@echo "[ $(T_BOLD)"`basename $(MANUALS)`$(T_RESET) $$"] in \\c"
@echo "$(T_ITALIC)$(mandir)/man1$(T_RESET)"
-$(v) for i in $(MANUALS); do \
rm -rf $(DESTDIR)$(mandir)/man1/`basename $$i`*; \ rm -rf $(DESTDIR)$(mandir)/man1/`basename $$i`*; \
done; done;
@echo
@echo "$(T_GREEN)Fish (likely) unintalled$(T_RESET)"
@echo
@echo "$(T_BOLD)./configure --prefix=$(T_RESET) to uninstall fish from a different prefix"
.PHONY: uninstall .PHONY: uninstall
install-translations: $(TRANSLATIONS) install-translations: $(TRANSLATIONS)
ifdef HAVE_GETTEXT ifdef HAVE_GETTEXT
for i in $(TRANSLATIONS); do \ @echo "Installing translations..."
$(v)for i in $(TRANSLATIONS); do \
$(INSTALL) -m 755 -d $(DESTDIR)$(localedir)/`basename $$i .gmo`/LC_MESSAGES; \ $(INSTALL) -m 755 -d $(DESTDIR)$(localedir)/`basename $$i .gmo`/LC_MESSAGES; \
$(INSTALL) -m 644 $$i $(DESTDIR)$(localedir)/`basename $$i .gmo`/LC_MESSAGES/fish.mo; \ $(INSTALL) -m 644 $$i $(DESTDIR)$(localedir)/`basename $$i .gmo`/LC_MESSAGES/fish.mo; \
echo $(DESTDIR)$(localedir)/`basename $$i .gmo`/LC_MESSAGES/fish.mo;\
done done
endif endif
.PHONY: install-translations .PHONY: install-translations
uninstall-translations: uninstall-translations:
rm -f $(DESTDIR)$(localedir)/*/LC_MESSAGES/fish.mo $(v)rm -f $(DESTDIR)$(localedir)/*/LC_MESSAGES/fish.mo
.PHONY: uninstall-translations .PHONY: uninstall-translations
# #
@ -700,43 +797,49 @@ uninstall-translations:
# How basic files get compiled # How basic files get compiled
# #
obj/%.o: src/%.cpp | obj obj/%.o: src/%.cpp | obj
$(CXX) $(CXXFLAGS) -c $< -o $@ @echo " CXX $(T_ITALIC)$@$(T_RESET)"
$(v)$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@
# #
# obj directory # obj directory
# #
obj: obj:
mkdir obj $(v)mkdir obj
# #
# Build the fish program. # Build the fish program.
# #
fish: obj/fish.o $(FISH_OBJS) $(EXTRA_PCRE2) fish: obj/fish.o $(FISH_OBJS) $(EXTRA_PCRE2)
$(CXX) $(CXXFLAGS) $(LDFLAGS_FISH) $(FISH_OBJS) obj/fish.o $(LIBS) -o $@ @echo " CXXLD $(T_ITALIC)$@$(T_RESET)"
$(v)$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS_FISH) $(FISH_OBJS) obj/fish.o $(LIBS) -o $@
$(PCRE2_LIB): $(PCRE2_H) $(PCRE2_LIB): $(PCRE2_H)
$(MAKE) -C $(PCRE2_DIR) libpcre2-$(PCRE2_WIDTH).la @echo " MAKE $(T_ITALIC)$@$(T_RESET)"
@$(MAKE) V=$(V) -C $(PCRE2_DIR) libpcre2-$(PCRE2_WIDTH).la
$(PCRE2_H): $(PCRE2_H):
(cd $(PCRE2_DIR) && ./config.status) $(v)(cd $(PCRE2_DIR) && ./config.status)
# #
# Build the fish_tests program. # Build the fish_tests program.
# #
fish_tests: $(FISH_TESTS_OBJS) $(EXTRA_PCRE2) fish_tests: $(FISH_TESTS_OBJS) $(EXTRA_PCRE2)
$(CXX) $(CXXFLAGS) $(LDFLAGS_FISH) $(FISH_TESTS_OBJS) $(LIBS) -o $@ @echo " CXXLD $(T_ITALIC)$@$(T_RESET)"
$(v)$(CXX) $(CXXFLAGS) $(LDFLAGS_FISH) $(FISH_TESTS_OBJS) $(LIBS) -o $@
# #
# Build the fish_indent program. # Build the fish_indent program.
# #
fish_indent: $(FISH_INDENT_OBJS) $(EXTRA_PCRE2) fish_indent: $(FISH_INDENT_OBJS) $(EXTRA_PCRE2)
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(FISH_INDENT_OBJS) $(LIBS) -o $@ @echo " CXXLD $(T_ITALIC)$@$(T_RESET)"
$(v)$(CXX) $(CXXFLAGS) $(LDFLAGS) $(FISH_INDENT_OBJS) $(LIBS) -o $@
# #
# Build the fish_key_reader program to show input from the terminal. # Build the fish_key_reader program to show input from the terminal.
# #
fish_key_reader: $(FISH_KEYREAD_OBJS) $(EXTRA_PCRE2) fish_key_reader: $(FISH_KEYREAD_OBJS) $(EXTRA_PCRE2)
$(CXX) $(CXXFLAGS) $(LDFLAGS_FISH) $^ $(LIBS) -o $@ @echo " CXXLD $(T_ITALIC)$@$(T_RESET)"
$(v)$(CXX) $(CXXFLAGS) $(LDFLAGS_FISH) $^ $(LIBS) -o $@
# #
# Update dependencies # Update dependencies
@ -750,23 +853,23 @@ fish_key_reader: $(FISH_KEYREAD_OBJS) $(EXTRA_PCRE2)
# behind. # behind.
# #
depend: depend:
mkdir -p /tmp/fish_make_depend/src @echo $(T_ITALIC)"Running makedepend..."$(T_RESET)
cp src/*.cpp src/*.h /tmp/fish_make_depend/src $(v)mkdir -p /tmp/fish_make_depend/src
cp config.h /tmp/fish_make_depend/ $(v)cp src/*.cpp src/*.h /tmp/fish_make_depend/src
mv $(subst obj/,/tmp/fish_make_depend/src/,$(FISH_ALL_OBJS:.o=.cpp)) /tmp/fish_make_depend/ $(v)cp config.h /tmp/fish_make_depend/
cd /tmp/fish_make_depend && \ $(v)mv $(subst obj/,/tmp/fish_make_depend/src/,$(FISH_ALL_OBJS:.o=.cpp)) /tmp/fish_make_depend/
makedepend -f$(CURDIR)/Makefile.in -pobj/ -Y -Isrc *.cpp $(v)cd /tmp/fish_make_depend && makedepend -f$(CURDIR)/Makefile.in -pobj/ -Y -Isrc *.cpp
rm -Rf /tmp/fish_make_depend $(v)rm -Rf /tmp/fish_make_depend
./config.status $(v)./config.status
.PHONY: depend .PHONY: depend
# #
# Lint the code. This only deals with C++ files. # Lint the code. This only deals with C++
# #
lint: lint:
build_tools/lint.fish $(CXX) $(CXXFLAGS) $(v)build_tools/lint.fish $(CXX) $(CXXFLAGS) $(CPPFLAGS)
lint-all: lint-all:
build_tools/lint.fish $(CXX) --all $(CXXFLAGS) $(v)build_tools/lint.fish $(CXX) --all $(CXXFLAGS) $(CPPFLAGS)
.PHONY: lint lint-all .PHONY: lint lint-all
# #
@ -774,21 +877,17 @@ lint-all:
# fish scripts (*.fish). # fish scripts (*.fish).
# #
style: style:
build_tools/style.fish $(v)build_tools/style.fish
style-all: style-all:
build_tools/style.fish --all $(v)build_tools/style.fish --all
.PHONY: style style-all .PHONY: style style-all
#
# Cleanup targets
#
# #
# Restore the source tree to the state right after extracting a tarball. # Restore the source tree to the state right after extracting a tarball.
# #
distclean: clean distclean: clean
$(MAKE) -C $(PCRE2_DIR) distclean || true $(v)$(MAKE) V=$(V) -C $(PCRE2_DIR) distclean ||:
rm -f config.status config.log config.h Makefile $(v)rm -f config.status config.log config.h Makefile
.PHONY: distclean .PHONY: distclean
# #
@ -800,23 +899,39 @@ distclean: clean
# them. # them.
# #
clean: clean:
$(MAKE) -C $(PCRE2_DIR) clean || true @echo "$(T_BOLD)Removing everything built by the Makefile...$(T_RESET)"
rm -f obj/*.o *.o doc.h doc.tmp # PCRE's make clean has a few slightly annoying exceptions to the V= rule. If V=0
rm -f doc_src/*.doxygen doc_src/*.cpp doc_src/*.o doc_src/commands.hdr # send all output to /dev/null - unless there's an error, in which case run it again not silenced.
rm -f tests/tmp.err tests/tmp.out tests/tmp.status tests/foo.txt ifeq ($(V), 0 )
rm -f $(PROGRAMS) fish_tests fish_key_reader $(MAKE) -C $(PCRE2_DIR) clean ||:
rm -f command_list.txt command_list_toc.txt toc.txt else
rm -f doc_src/index.hdr doc_src/commands.hdr @$(MAKE) -s -C $(PCRE2_DIR) clean > /dev/null || $(MAKE) -s -C $(PCRE2_DIR) clean ||:
rm -f lexicon_filter lexicon.txt lexicon.log endif
rm -f compile_commands.json xcodebuild.log $(v)rm -f obj/*.o *.o doc.h doc.tmp
rm -f FISH-BUILD-VERSION-FILE fish.pc share/__fish_build_paths.fish $(v)rm -f doc_src/*.doxygen doc_src/*.cpp doc_src/*.o doc_src/commands.hdr
if test "$(HAVE_DOXYGEN)" = 1; then \ $(v)rm -f tests/tmp.err tests/tmp.out tests/tmp.status tests/foo.txt
$(v)rm -f $(PROGRAMS) fish_tests fish_key_reader
$(v)rm -f command_list.txt command_list_toc.txt toc.txt
$(v)rm -f doc_src/index.hdr doc_src/commands.hdr
$(v)rm -f lexicon_filter lexicon.txt lexicon.log
$(v)rm -f compile_commands.json xcodebuild.log
$(v)rm -f FISH-BUILD-VERSION-FILE fish.pc share/__fish_build_paths.fish
$(v)if test "$(HAVE_DOXYGEN)" = 1; then \
rm -rf doc user_doc share/man; \ rm -rf doc user_doc share/man; \
fi fi
rm -f po/*.gmo $(v)rm -f po/*.gmo
rm -rf obj build test $(v)rm -rf obj build test
.PHONY: clean .PHONY: clean
# For silent build
# These rules need to stay at the end - $(v) won't work after this.
# if V=0:
# $(v)cmd ⇒ @cmd
V0 := @
# if V=1
# $(v)cmd ⇒ cmd
V1 :=
v = $(V$(V))
# DO NOT DELETE THIS LINE -- make depend depends on it. # DO NOT DELETE THIS LINE -- make depend depends on it.
@ -916,9 +1031,9 @@ obj/fish_indent.o: src/input.h src/output.h src/parse_constants.h
obj/fish_indent.o: src/parse_tree.h src/tokenizer.h src/print_help.h obj/fish_indent.o: src/parse_tree.h src/tokenizer.h src/print_help.h
obj/fish_indent.o: src/wutil.h obj/fish_indent.o: src/wutil.h
obj/fish_key_reader.o: config.h src/signal.h src/common.h src/fallback.h obj/fish_key_reader.o: config.h src/signal.h src/common.h src/fallback.h
obj/fish_key_reader.o: src/env.h src/input.h src/input_common.h src/proc.h obj/fish_key_reader.o: src/env.h src/input.h src/input_common.h
obj/fish_key_reader.o: src/io.h src/parse_tree.h src/parse_constants.h obj/fish_key_reader.o: src/print_help.h src/proc.h src/io.h src/parse_tree.h
obj/fish_key_reader.o: src/tokenizer.h src/print_help.h src/reader.h obj/fish_key_reader.o: src/parse_constants.h src/tokenizer.h src/reader.h
obj/fish_key_reader.o: src/complete.h src/highlight.h src/color.h src/wutil.h obj/fish_key_reader.o: src/complete.h src/highlight.h src/color.h src/wutil.h
obj/fish_tests.o: config.h src/signal.h src/builtin.h src/common.h obj/fish_tests.o: config.h src/signal.h src/builtin.h src/common.h
obj/fish_tests.o: src/fallback.h src/color.h src/complete.h src/env.h obj/fish_tests.o: src/fallback.h src/color.h src/complete.h src/env.h
@ -942,10 +1057,10 @@ obj/highlight.o: src/highlight.h src/history.h src/wutil.h src/output.h
obj/highlight.o: src/parse_tree.h src/tokenizer.h src/parse_util.h src/path.h obj/highlight.o: src/parse_tree.h src/tokenizer.h src/parse_util.h src/path.h
obj/highlight.o: src/wildcard.h src/complete.h obj/highlight.o: src/wildcard.h src/complete.h
obj/history.o: config.h src/common.h src/fallback.h src/signal.h src/env.h obj/history.o: config.h src/common.h src/fallback.h src/signal.h src/env.h
obj/history.o: src/history.h src/wutil.h src/iothread.h src/lru.h obj/history.o: src/history.h src/wutil.h src/io.h src/iothread.h src/lru.h
obj/history.o: src/parse_constants.h src/parse_tree.h src/tokenizer.h obj/history.o: src/parse_constants.h src/parse_tree.h src/tokenizer.h
obj/history.o: src/path.h src/reader.h src/complete.h src/highlight.h obj/history.o: src/path.h src/reader.h src/complete.h src/highlight.h
obj/history.o: src/color.h src/sanity.h obj/history.o: src/color.h
obj/input.o: config.h src/common.h src/fallback.h src/signal.h src/env.h obj/input.o: config.h src/common.h src/fallback.h src/signal.h src/env.h
obj/input.o: src/event.h src/input.h src/input_common.h src/io.h src/output.h obj/input.o: src/event.h src/input.h src/input_common.h src/io.h src/output.h
obj/input.o: src/color.h src/parser.h src/expand.h src/parse_constants.h obj/input.o: src/color.h src/parser.h src/expand.h src/parse_constants.h

View file

@ -64,9 +64,11 @@ fish requires a number of utilities to operate, which should be present on any U
Translation support requires the gettext program. Translation support requires the gettext program.
Usage output for builtin functions is generated on-demand from the installed manpages using `nroff` and `ul`.
Some optional features of fish, such as the manual page completion parser and the web configuration tool, require Python. Some optional features of fish, such as the manual page completion parser and the web configuration tool, require Python.
In order to generate completions from man pages compressed with either lzma or xz, you may need to install an extra Python package. Python versions prior to 2.6 are not supported. For Python versions 2.6 to 3.2 you need to install the module `backports.lzma`. How to install it depends on your system and how you installed Python. Most Linux distributions should include it as a package named `backports-lzma` (or similar). From version 3.3 onwards, Python already includes the required module. In order to generate completions from man pages compressed with either lzma or xz, you may need to install an extra Python package. Python versions prior to 2.6 are not supported. To process lzma-compresed manpages, backports.lzma is needed for Python 3.2 or older. From version 3.3 onwards, Python already includes the required module.
## Packages for Linux ## Packages for Linux

View file

@ -46,6 +46,9 @@ echo " input filter: $INPUTFILTER"
echo " output directory: $OUTPUTDIR" echo " output directory: $OUTPUTDIR"
echo " skipping: $CONDEMNED_PAGES" echo " skipping: $CONDEMNED_PAGES"
#Until now the makefile likely has been affecting our output, reset for upcoming warnings
tput sgr0
# Make sure INPUTDIR is found # Make sure INPUTDIR is found
if test ! -d "$INPUTDIR"; then if test ! -d "$INPUTDIR"; then
echo >&2 "Could not find input directory '${INPUTDIR}'" echo >&2 "Could not find input directory '${INPUTDIR}'"
@ -132,13 +135,18 @@ if test "$RESULT" = 0 ; then
fi fi
# Destroy TMPLOC # Destroy TMPLOC
echo "Cleaning up '$TMPLOC'" if test "$RESULT" -ne 0; then
echo "Cleaning up '$TMPLOC'"
fi
rm -Rf "$TMPLOC" rm -Rf "$TMPLOC"
if test "$RESULT" = 0; then if test "$RESULT" -ne 0; then
# Tell the user what we did tput smso 2> /dev/null || true
echo "Output man pages into '${OUTPUTDIR}'" echo "Doxygen failed creating manpages. See the output log for details."
tput sgr0 2> /dev/null || true
else else
echo "Doxygen failed. See the output log for details." tput bold 2> /dev/null || true
echo Built manpages
tput sgr0 2> /dev/null || true
fi fi
exit $RESULT exit $RESULT

View file

@ -24,13 +24,13 @@ end
if test $all = yes if test $all = yes
set files (git status --porcelain --short --untracked-files=all | sed -e 's/^ *[^ ]* *//') set files (git status --porcelain --short --untracked-files=all | sed -e 's/^ *[^ ]* *//')
if set -q files[1] if set -q files[1]
set_color --bold echo
echo "Will not proceed with style.fish --all as there are uncommited or untracked files." echo You have uncommited changes. Cowardly refusing to restyle the entire code base.
set_color normal echo
echo "hint: git-clang-format can be ran directly" exit 1
exit 2
end end
set c_files {src,osx,build_tools,share}/{***.h,***.cpp,***.m,***.js} set c_files src/*.h src/*.cpp
set f_files share/***.fish
else else
# We haven't been asked to reformat all the source. If there are uncommitted changes reformat # We haven't been asked to reformat all the source. If there are uncommitted changes reformat
# those using `git clang-format`. Else reformat the files in the most recent commit. # those using `git clang-format`. Else reformat the files in the most recent commit.
@ -43,45 +43,50 @@ else
set files (git diff-tree --no-commit-id --name-only -r HEAD) set files (git diff-tree --no-commit-id --name-only -r HEAD)
end end
# Extract just the C/C++/ObjC/js files that exist. # Extract just the C/C++ files that exist.
set c_files set c_files
for file in (string match -ri '^.*\.(?:c|cpp|h|m|js)$' -- $files) for file in (string match -r '^.*\.(?:c|cpp|h)$' -- $files)
test -f $file test -f $file; and set c_files $c_files $file
and set c_files $c_files $file
end end
# Extract just the fish files. # Extract just the fish files.
set f_files (string match -r '^.*\.fish$' -- $files) set f_files (string match -r '^.*\.fish$' -- $files)
end end
# Run the git-clang-format if we have any C++ files. # Run the C++ reformatter if we have any C++ files.
if set -q c_files[1] if set -q c_files[1]
if test $git_clang_format = yes if test $git_clang_format = yes
if type -q git-clang-format if type -q git-clang-format
echo echo
echo ========================================
echo Running git-clang-format echo Running git-clang-format
echo ======================== echo ========================================
git add $c_files git add $c_files
git-clang-format git-clang-format
else else
echo (set_color bold)'Warning: git-clang-format not installed or in $PATH'(set_color normal) echo
echo 'WARNING: Cannot find git-clang-format command'
echo
end end
else if type -q clang-format else if type -q clang-format
echo echo
echo ========================================
echo Running clang-format echo Running clang-format
echo ==================== echo ========================================
for file in $c_files for file in $c_files
cp $file $file.new # preserves mode bits cp $file $file.new # preserves mode bits
clang-format $file >$file.new clang-format $file >$file.new
if cmp --quiet $file $file.new if cmp --quiet $file $file.new
echo $file echo $file was correctly formatted
rm $file.new rm $file.new
else else
echo (set_color --underline)$file(set_color normal) is being reformatted echo $file was NOT correctly formatted
mv $file.new $file mv $file.new $file
end end
end end
else else
echo
echo 'WARNING: Cannot find clang-format command' echo 'WARNING: Cannot find clang-format command'
echo
end end
end end
@ -92,16 +97,17 @@ if set -q f_files[1]
set PATH . $PATH set PATH . $PATH
end end
echo echo
echo ========================================
echo Running fish_indent echo Running fish_indent
echo =================== echo ========================================
for file in $f_files for file in $f_files
cp $file $file.new # preserves mode bits cp $file $file.new # preserves mode bits
fish_indent <$file >$file.new fish_indent <$file >$file.new
if cmp --quiet $file $file.new if cmp --quiet $file $file.new
echo $file echo $file was correctly formatted
rm $file.new rm $file.new
else else
echo (set_color --underline)$file(set_color normal) is being reformatted echo $file was NOT correctly formatted
mv $file.new $file mv $file.new $file
end end
end end

View file

@ -1,9 +0,0 @@
This directory is for images relevant to the fish brand.
The logo.psd and logo.svg files were created by Steve Stagg
(http://github.com/stestagg). They were uploaded to SickerMule by Andrei
Zvonimir Crnković (https://github.com/andreicek). See
https://www.stickermule.com/marketplace/tags/shell
https://www.stickermule.com/marketplace/3507-fish-shell-sticker-die-cut
https://www.stickermule.com/marketplace/3508-fish-shell-sticker-square-cut

Binary file not shown.

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 109 KiB

View file

@ -24,6 +24,7 @@
- <a href='#faq-greeting'>How do I change the greeting message?</a> - <a href='#faq-greeting'>How do I change the greeting message?</a>
- <a href='#faq-history'>Why doesn't history substitution ("!$" etc.) work?</a> - <a href='#faq-history'>Why doesn't history substitution ("!$" etc.) work?</a>
- <a href='#faq-uninstalling'>How do I uninstall fish?</a> - <a href='#faq-uninstalling'>How do I uninstall fish?</a>
- <a href='#faq-third-party'>Where can I find extra tools for fish?</a>
\htmlonly[block] \htmlonly[block]
</div> </div>
@ -220,6 +221,18 @@ rm -f fish fish_indent
Fish reserves the <a href="http://www.unicode.org/faq/private_use.html">Unicode private-use character range</a> from U+F600 thru U+F73F for internal use. Any attempt to feed characters in that range to fish will result in them being replaced by the Unicode "replacement character" U+FFFD. This includes both interactive input as well as any file read by fish (but not programs run by fish). Fish reserves the <a href="http://www.unicode.org/faq/private_use.html">Unicode private-use character range</a> from U+F600 thru U+F73F for internal use. Any attempt to feed characters in that range to fish will result in them being replaced by the Unicode "replacement character" U+FFFD. This includes both interactive input as well as any file read by fish (but not programs run by fish).
<hr>
\section faq-third-party Where can I find extra tools for fish?
The fish user community extends fish in unique and useful ways via scripts that aren't always appropriate for bundling with the fish package. Typically because they solve a niche problem unlikely to appeal to a broad audience. You can find those extensions, including prompts, themes and useful functions, in various third-party repositories. These include:
- <a href="https://github.com/fisherman/fisherman">Fisherman</a>
- <a href="https://github.com/tuvistavie/fundle">Fundle</a>
- <a href="https://github.com/oh-my-fish/oh-my-fish">Oh My Fish</a>
- <a href="https://github.com/justinmayer/tacklebox">Tacklebox</a>
This is not an exhaustive list and the fish project has no opinion regarding the merits of the repositories listed above or the scripts found therein. We mention these only because you may find within them a solution to a need you have such as supporting the `&&` and `||` operators or improved integration with other tools that you use.
\htmlonly[block] \htmlonly[block]
</div> </div>
\endhtmlonly \endhtmlonly

View file

@ -29,8 +29,6 @@ The following options are available:
- `-s` or `--on-signal SIGSPEC` tells fish to run this function when the signal SIGSPEC is delivered. SIGSPEC can be a signal number, or the signal name, such as SIGHUP (or just HUP). - `-s` or `--on-signal SIGSPEC` tells fish to run this function when the signal SIGSPEC is delivered. SIGSPEC can be a signal number, or the signal name, such as SIGHUP (or just HUP).
- `-B` or `--shadow-builtin` must be specified if the function name is the same as a builtin. Specifying this flag indicates your acknowledgement that you are wrapping or replacing the builtin command. This is a safety feature to make it harder for people to inadvertently break the shell by doing things like `function test; return 0; end`. If the function name is not currently a builtin using this flag will produce an error. If you want to write a function that provides a builtin to an older version of fish you need to add something like `builtin --names | grep -q '^cmd$'; and return` to the top of the function script (where `cmd` is the name of the builtin/function). That will keep your script from replacing the builtin with your function on the newer fish version while allowing your function to provide similar functionality on older versions of fish.
- `-S` or `--no-scope-shadowing` allows the function to access the variables of calling functions. Normally, any variables inside the function that have the same name as variables from the calling function are "shadowed", and their contents is independent of the calling function. - `-S` or `--no-scope-shadowing` allows the function to access the variables of calling functions. Normally, any variables inside the function that have the same name as variables from the calling function are "shadowed", and their contents is independent of the calling function.
- `-V` or `--inherit-variable NAME` snapshots the value of the variable `NAME` and defines a local variable with that same name and value when the function is executed. - `-V` or `--inherit-variable NAME` snapshots the value of the variable `NAME` and defines a local variable with that same name and value when the function is executed.

View file

@ -2,8 +2,8 @@
\subsection history-synopsis Synopsis \subsection history-synopsis Synopsis
\fish{synopsis} \fish{synopsis}
history ( -s | --search ) [ -t | --with-time ] [ -p | --prefix | -c | --contains ] [ "search string"... ] history ( -s | --search ) [ -t | --with-time ] [ -e | --exact | -p | --prefix | -c | --contains ] [ "search string"... ]
history ( -d | --delete ) [ -t | --with-time ] [ -p | --prefix | -c | --contains ] "search string"... history ( -d | --delete ) [ -t | --with-time ] [ -e | --exact | -p | --prefix | -c | --contains ] "search string"...
history ( -m | --merge ) history ( -m | --merge )
history ( -s | --save ) history ( -s | --save )
history ( -l | --clear ) history ( -l | --clear )
@ -24,15 +24,17 @@ The following commands are available:
- `-v` or `--save` saves all changes in the history file. The shell automatically saves the history file; this option is provided for internal use. - `-v` or `--save` saves all changes in the history file. The shell automatically saves the history file; this option is provided for internal use.
- `-l` or `--clear` clears the history file. A prompt is displayed before the history is erased asking you to confirm you really want to clear all history. - `-l` or `--clear` clears the history file. A prompt is displayed before the history is erased asking you to confirm you really want to clear all history unless `builtin history` is used.
The following options are available: The following options are available:
- `-p` or `--prefix` searches or deletes items in the history that begin with the specified text string. - `-c` or `--contains` searches or deletes items in the history that contain the specified text string. This is the default for the `--search` flag. This is not currently supported by the `--delete` flag.
- `-c` or `--contains` searches or deletes items in the history that contain the specified text string. This is the default. - `-e` or `--exact` searches or deletes items in the history that exactly match the specified text string. This is the default for the `--delete` flag.
- `-t` or `--with-time` prefixes the output of each displayed history entry with the time it was recorded in the format "%Y-%m-%d %H:%M:%S" in your local timezone. - `-p` or `--prefix` searches or deletes items in the history that begin with the specified text string. This is not currently supported by the `--delete` flag.
- `-t` or `--with-time` outputs the date and time ("%Y-%m-%d %H:%M:%S") history items were recorded at on a line starting with "#" before each history entry.
\subsection history-examples Example \subsection history-examples Example

View file

@ -953,33 +953,34 @@ For a list of all builtins, functions and commands shipped with fish, see the <a
The `fish` editor features copy and paste, a searchable history and many editor functions that can be bound to special keyboard shortcuts. The `fish` editor features copy and paste, a searchable history and many editor functions that can be bound to special keyboard shortcuts.
Similar to bash, fish has Emacs and Vi editing modes. The default editing mode is Emacs. You can switch to Vi mode with `fish_vi_key_bindings` and switch back with `fish_default_key_bindings`. Similar to bash, fish has Emacs and Vi editing modes. The default editing mode is Emacs. You can switch to Vi mode with `fish_vi_key_bindings` and switch back with `fish_default_key_bindings`. You can also make your own key bindings by creating a function and setting $fish_key_bindings to its name. For example:
\fish
function hybrid_bindings --description "Vi-style bindings that inherit emacs-style bindings in all modes"
for mode in default insert visual
fish_default_key_bindings -M $mode
end
fish_vi_key_bindings --no-erase
end
set -g fish_key_bindings hybrid_bindings
\endfish
\subsection emacs-mode Emacs mode commands \subsection shared-binds Shared bindings
Some bindings are shared between emacs- and vi-mode because they aren't text editing bindings or because what Vi/Vim does for a particular key doesn't make sense for a shell.
- @key{Tab} <a href="#completion">completes</a> the current token. @key{Shift, Tab} completes the current token and starts the pager's search mode. - @key{Tab} <a href="#completion">completes</a> the current token. @key{Shift, Tab} completes the current token and starts the pager's search mode.
- @key{Home} or @key{Control,A} moves the cursor to the beginning of the line.
- @key{End} or @key{Control,E} moves to the end of line. If the cursor is already at the end of the line, and an autosuggestion is available, @key{End} or @key{Control,E} accepts the autosuggestion.
- @cursor_key{&larr;,Left} (or @key{Control,B}) and @cursor_key{&rarr;,Right} (or @key{Control,F}) move the cursor left or right by one character. If the cursor is already at the end of the line, and an autosuggestion is available, the @cursor_key{&rarr;,Right} key and the @key{Control,F} combination accept the suggestion.
- @key{Alt,&larr;,Left} and @key{Alt,&rarr;,Right} move the cursor one word left or right, or moves forward/backward in the directory history if the command line is empty. If the cursor is already at the end of the line, and an autosuggestion is available, @key{Alt,&rarr;,Right} (or @key{Alt,F}) accepts the first word in the suggestion. - @key{Alt,&larr;,Left} and @key{Alt,&rarr;,Right} move the cursor one word left or right, or moves forward/backward in the directory history if the command line is empty. If the cursor is already at the end of the line, and an autosuggestion is available, @key{Alt,&rarr;,Right} (or @key{Alt,F}) accepts the first word in the suggestion.
- @cursor_key{&uarr;,Up} and @cursor_key{&darr;,Down} search the command history for the previous/next command containing the string that was specified on the commandline before the search was started. If the commandline was empty when the search started, all commands match. See the <a href='#history'>history</a> section for more information on history searching. - @cursor_key{&uarr;,Up} and @cursor_key{&darr;,Down} search the command history for the previous/next command containing the string that was specified on the commandline before the search was started. If the commandline was empty when the search started, all commands match. See the <a href='#history'>history</a> section for more information on history searching.
- @key{Alt,&uarr;,Up} and @key{Alt,&darr;,Down} search the command history for the previous/next token containing the token under the cursor before the search was started. If the commandline was not on a token when the search started, all tokens match. See the <a href='#history'>history</a> section for more information on history searching. - @key{Alt,&uarr;,Up} and @key{Alt,&darr;,Down} search the command history for the previous/next token containing the token under the cursor before the search was started. If the commandline was not on a token when the search started, all tokens match. See the <a href='#history'>history</a> section for more information on history searching.
- @key{Delete} and @key{Backspace} removes one character forwards or backwards respectively.
- @key{Control,C} deletes the entire line. - @key{Control,C} deletes the entire line.
- @key{Control,D} delete one character to the right of the cursor. If the command line is empty, @key{Control,D} will exit fish. - @key{Control,D} delete one character to the right of the cursor. If the command line is empty, @key{Control,D} will exit fish.
- @key{Control,K} moves contents from the cursor to the end of line to the <a href="#killring">killring</a>.
- @key{Control,U} moves contents from the beginning of line to the cursor to the <a href="#killring">killring</a>. - @key{Control,U} moves contents from the beginning of line to the cursor to the <a href="#killring">killring</a>.
- @key{Control,L} clears and repaints the screen. - @key{Control,L} clears and repaints the screen.
@ -988,18 +989,30 @@ Similar to bash, fish has Emacs and Vi editing modes. The default editing mode i
- @key{Alt,D} moves the next word to the <a href="#killring">killring</a>. - @key{Alt,D} moves the next word to the <a href="#killring">killring</a>.
- @key{Alt,W} prints a short description of the command under the cursor. - @key{Alt,H} (or @key{F1}) shows the manual page for the current command, if one exists.
- @key{Alt,L} lists the contents of the current directory, unless the cursor is over a directory argument, in which case the contents of that directory will be listed. - @key{Alt,L} lists the contents of the current directory, unless the cursor is over a directory argument, in which case the contents of that directory will be listed.
- @key{Alt,P} adds the string '`| less;`' to the end of the job under the cursor. The result is that the output of the command will be paged. - @key{Alt,P} adds the string '`| less;`' to the end of the job under the cursor. The result is that the output of the command will be paged.
- @key{Alt,W} prints a short description of the command under the cursor.
\subsection emacs-mode Emacs mode commands
- @key{Home} or @key{Control,A} moves the cursor to the beginning of the line.
- @key{End} or @key{Control,E} moves to the end of line. If the cursor is already at the end of the line, and an autosuggestion is available, @key{End} or @key{Control,E} accepts the autosuggestion.
- @cursor_key{&larr;,Left} (or @key{Control,B}) and @cursor_key{&rarr;,Right} (or @key{Control,F}) move the cursor left or right by one character. If the cursor is already at the end of the line, and an autosuggestion is available, the @cursor_key{&rarr;,Right} key and the @key{Control,F} combination accept the suggestion.
- @key{Delete} and @key{Backspace} removes one character forwards or backwards respectively.
- @key{Control,K} moves contents from the cursor to the end of line to the <a href="#killring">killring</a>.
- @key{Alt,C} capitalizes the current word. - @key{Alt,C} capitalizes the current word.
- @key{Alt,U} makes the current word uppercase. - @key{Alt,U} makes the current word uppercase.
- @key{Alt,H} (or @key{F1}) shows the manual page for the current command, if one exists.
- @key{Control, t} transposes the last two characters - @key{Control, t} transposes the last two characters
- @key{Alt,t} transposes the last two words - @key{Alt,t} transposes the last two words
@ -1010,9 +1023,22 @@ You can change these key bindings using the <a href="commands.html#bind">bind</a
\subsection vi-mode Vi mode commands \subsection vi-mode Vi mode commands
Vi mode allows for the use of Vi-like commands at the prompt. Initially, <a href="#vi-mode-insert">insert mode</a> is active. @key{Escape} enters <a href="#vi-mode-command">command mode</a>. The commands available in command, insert and visual mode are described below. Vi mode builds on top of <a href="#emacs-mode">Emacs mode</a>, so all keybindings mentioned there that do not contradict the ones mentioned here also work. Vi mode allows for the use of Vi-like commands at the prompt. Initially, <a href="#vi-mode-insert">insert mode</a> is active. @key{Escape} enters <a href="#vi-mode-command">command mode</a>. The commands available in command, insert and visual mode are described below. Vi mode shares <a href="#shared-binds">some bindings</a> with <a href="#emacs-mode">Emacs mode</a>.
When in vi-mode, the <a href="fish_mode_prompt.html">`fish_mode_prompt`</a> function will display a mode indicator to the left of the prompt. The `fish_vi_cursor` function is available to change the cursor's shape depending on the mode in supported terminals. It is also possible to add all emacs-mode bindings to vi-mode by using something like
\fish
function fish_user_key_bindings
# Execute this once per mode that emacs bindings should be used in
fish_default_key_bindings -M insert
# Without an argument, fish_vi_key_bindings will default to
# resetting all bindings.
# The argument specifies the initial mode (insert, "default" or visual).
fish_vi_key_bindings insert
end
\endfish
When in vi-mode, the <a href="fish_mode_prompt.html">`fish_mode_prompt`</a> function will display a mode indicator to the left of the prompt. The `fish_vi_cursor` function will be used to change the cursor's shape depending on the mode in supported terminals. To disable this feature, override it with an empty function.
\subsubsection vi-mode-command Command mode \subsubsection vi-mode-command Command mode
@ -1045,20 +1071,16 @@ Command mode is also known as normal mode.
- @key{Control, X} copies the current buffer to the system's clipboard, @key{Control, V} inserts the clipboard contents. - @key{Control, X} copies the current buffer to the system's clipboard, @key{Control, V} inserts the clipboard contents.
- @key{Control,C} deletes the entire line. - @key{Control,C} deletes the entire line.
\subsubsection vi-mode-insert Insert mode - @key{Backspace} moves the cursor left.
- @key{Tab} <a href="#completion">completes</a> the current token. \subsubsection vi-mode-insert Insert mode
- @key{Escape} or @key{Control,C} enters <a href="#vi-mode-command">command mode</a>. - @key{Escape} or @key{Control,C} enters <a href="#vi-mode-command">command mode</a>.
- @cursor_key{&uarr;,Up} and @cursor_key{&darr;,Down} search the command history. See the <a href='#history'>history</a> section for more information on history searching.
- @key{Control,W} moves the previous word to the <a href="#killring">killring</a>.
- @key{Control,U} moves contents from the beginning of line to the cursor to the <a href="#killring">killring</a>.
- @key{Control,x} moves the cursor to the end of the line. If an autosuggestion is available, it will be accepted completely. - @key{Control,x} moves the cursor to the end of the line. If an autosuggestion is available, it will be accepted completely.
- @key{Backspace} removes one character to the left.
\subsubsection vi-mode-visual Visual mode \subsubsection vi-mode-visual Visual mode
- @cursor_key{&larr;,Left} and @cursor_key{&rarr;,Right} extend the selection backward/forward by one character. - @cursor_key{&larr;,Left} and @cursor_key{&rarr;,Right} extend the selection backward/forward by one character.
@ -1120,15 +1142,15 @@ Note that functions cannot be started in the background. Functions that are stop
\section initialization Initialization files \section initialization Initialization files
On startup, Fish evaluates a number of configuration files, which can be used to control the behavior of the shell. On startup, Fish evaluates a number of configuration files, which can be used to control the behavior of the shell. The location of these configuration variables is controlled by a number of environment variables, and their default or usual location is given below.
Configuration files are evaluated in the following order: Configuration files are evaluated in the following order:
- Configuration shipped with fish, which should not be edited, usually `/usr/share/fish/config.fish`. - Configuration shipped with fish, which should not be edited, in `$__fish_datadir/config.fish` (usually `/usr/share/fish/config.fish`).
- System-wide configuration files, where administrators can include initialization that should be run for all users on the system - similar to `/etc/profile` for POSIX-style shells - usually `/etc/fish/config.fish`; - System-wide configuration files, where administrators can include initialization that should be run for all users on the system - similar to `/etc/profile` for POSIX-style shells - in `$__fish_sysconfdir` (usually `/etc/fish/config.fish`);
- Configuration snippets in files ending in `.fish`, in the directories: - Configuration snippets in files ending in `.fish`, in the directories:
- `~/.config/fish/conf.d/` - `$XDG_CONFIG_HOME/fish/conf.d` (by default, `~/.config/fish/conf.d/`)
- `/etc/fish/conf.d` - `$__fish_sysconfdir/conf.d` (by default, `/etc/fish/conf.d`)
- `/usr/share/fish/vendor_conf.d` - `/usr/share/fish/vendor_conf.d` (set at compile time; by default, `$__fish_datadir/conf.d`)
If there are multiple files with the same name in these directories, only the first will be executed. If there are multiple files with the same name in these directories, only the first will be executed.
@ -1136,7 +1158,7 @@ Configuration files are evaluated in the following order:
These paths are controlled by parameters set at build, install, or run time, and may vary from the defaults listed above. These paths are controlled by parameters set at build, install, or run time, and may vary from the defaults listed above.
This wide search may be confusing. If you are unsure, use `~/.config/fish/config.fish`. This wide search may be confusing. If you are unsure where to put your own customisations, use `~/.config/fish/config.fish`.
These files are all executed on the startup of every shell. If you want to run a command only on starting an interactive shell, use the exit status of the command `status --is-interactive` to determine if the shell is interactive. If you want to run a command only when using a login shell, use `status --is-login` instead. This will speed up the starting of non-interactive or non-login shells. These files are all executed on the startup of every shell. If you want to run a command only on starting an interactive shell, use the exit status of the command `status --is-interactive` to determine if the shell is interactive. If you want to run a command only when using a login shell, use `status --is-login` instead. This will speed up the starting of non-interactive or non-login shells.

View file

@ -38,7 +38,7 @@ Using the *normal* keyword will reset foreground, background, and all formatting
set_color red; echo "Roses are red" set_color red; echo "Roses are red"
set_color blue; echo "Violets are blue" set_color blue; echo "Violets are blue"
set_color 62A; echo "Eggplants are dark purple" set_color 62A; echo "Eggplants are dark purple"
set_color normal; echo "Normal is nice" # This will reset background, too set_color normal; echo "Normal is nice" # Resets the background too
\endfish \endfish
\subsection set_color-detection Terminal Capability Detection \subsection set_color-detection Terminal Capability Detection

View file

@ -9,7 +9,6 @@ html, body {
color: #111; color: #111;
} }
body { body {
text-rendering: optimizeLegibility;
overflow: hidden; overflow: hidden;
} }
.logo { .logo {
@ -96,9 +95,6 @@ a { color: #3d5cb3; }
.fish_right_bar ul li { .fish_right_bar ul li {
margin-bottom: 0.6rem; margin-bottom: 0.6rem;
} }
.fish_right_bar p > code {
display: inline-block;
}
/* Typography */ /* Typography */
p { margin: 1rem 0; } p { margin: 1rem 0; }
h1, h2, h3, h4, h5, h6 { h1, h2, h3, h4, h5, h6 {
@ -271,5 +267,3 @@ tt, code, pre, .fish {
position: absolute; position: absolute;
left: -2rem; left: -2rem;
} }

View file

@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# install - install a program, script, or datafile # install - install a program, script, or datafile
scriptversion=2011-11-20.07; # UTC scriptversion=2013-12-25.23; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was # This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the # later released in X11R6 (xc/config/util/install.sh) with the
@ -41,19 +41,15 @@ scriptversion=2011-11-20.07; # UTC
# This script is compatible with the BSD install script, but was written # This script is compatible with the BSD install script, but was written
# from scratch. # from scratch.
tab=' '
nl=' nl='
' '
IFS=" "" $nl" IFS=" $tab$nl"
# set DOITPROG to echo to test this script # Set DOITPROG to "echo" to test this script.
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit=${DOITPROG-} doit=${DOITPROG-}
if test -z "$doit"; then doit_exec=${doit:-exec}
doit_exec=exec
else
doit_exec=$doit
fi
# Put in absolute file names if you don't have them in your path; # Put in absolute file names if you don't have them in your path;
# or use environment vars. # or use environment vars.
@ -68,17 +64,6 @@ mvprog=${MVPROG-mv}
rmprog=${RMPROG-rm} rmprog=${RMPROG-rm}
stripprog=${STRIPPROG-strip} stripprog=${STRIPPROG-strip}
posix_glob='?'
initialize_posix_glob='
test "$posix_glob" != "?" || {
if (set -f) 2>/dev/null; then
posix_glob=
else
posix_glob=:
fi
}
'
posix_mkdir= posix_mkdir=
# Desired mode of installed file. # Desired mode of installed file.
@ -97,7 +82,7 @@ dir_arg=
dst_arg= dst_arg=
copy_on_change=false copy_on_change=false
no_target_directory= is_target_a_directory=possibly
usage="\ usage="\
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
@ -137,46 +122,57 @@ while test $# -ne 0; do
-d) dir_arg=true;; -d) dir_arg=true;;
-g) chgrpcmd="$chgrpprog $2" -g) chgrpcmd="$chgrpprog $2"
shift;; shift;;
--help) echo "$usage"; exit $?;; --help) echo "$usage"; exit $?;;
-m) mode=$2 -m) mode=$2
case $mode in case $mode in
*' '* | *' '* | *' *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
'* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2
echo "$0: invalid mode: $mode" >&2 exit 1;;
exit 1;; esac
esac shift;;
shift;;
-o) chowncmd="$chownprog $2" -o) chowncmd="$chownprog $2"
shift;; shift;;
-s) stripcmd=$stripprog;; -s) stripcmd=$stripprog;;
-t) dst_arg=$2 -t)
# Protect names problematic for 'test' and other utilities. is_target_a_directory=always
case $dst_arg in dst_arg=$2
-* | [=\(\)!]) dst_arg=./$dst_arg;; # Protect names problematic for 'test' and other utilities.
esac case $dst_arg in
shift;; -* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
shift;;
-T) no_target_directory=true;; -T) is_target_a_directory=never;;
--version) echo "$0 $scriptversion"; exit $?;; --version) echo "$0 $scriptversion"; exit $?;;
--) shift --) shift
break;; break;;
-*) echo "$0: invalid option: $1" >&2 -*) echo "$0: invalid option: $1" >&2
exit 1;; exit 1;;
*) break;; *) break;;
esac esac
shift shift
done done
# We allow the use of options -d and -T together, by making -d
# take the precedence; this is for compatibility with GNU install.
if test -n "$dir_arg"; then
if test -n "$dst_arg"; then
echo "$0: target directory not allowed when installing a directory." >&2
exit 1
fi
fi
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
# When -d is used, all remaining arguments are directories to create. # When -d is used, all remaining arguments are directories to create.
# When -t is used, the destination is already specified. # When -t is used, the destination is already specified.
@ -207,6 +203,15 @@ if test $# -eq 0; then
exit 0 exit 0
fi fi
if test -z "$dir_arg"; then
if test $# -gt 1 || test "$is_target_a_directory" = always; then
if test ! -d "$dst_arg"; then
echo "$0: $dst_arg: Is not a directory." >&2
exit 1
fi
fi
fi
if test -z "$dir_arg"; then if test -z "$dir_arg"; then
do_exit='(exit $ret); exit $ret' do_exit='(exit $ret); exit $ret'
trap "ret=129; $do_exit" 1 trap "ret=129; $do_exit" 1
@ -223,16 +228,16 @@ if test -z "$dir_arg"; then
*[0-7]) *[0-7])
if test -z "$stripcmd"; then if test -z "$stripcmd"; then
u_plus_rw= u_plus_rw=
else else
u_plus_rw='% 200' u_plus_rw='% 200'
fi fi
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
*) *)
if test -z "$stripcmd"; then if test -z "$stripcmd"; then
u_plus_rw= u_plus_rw=
else else
u_plus_rw=,u+rw u_plus_rw=,u+rw
fi fi
cp_umask=$mode$u_plus_rw;; cp_umask=$mode$u_plus_rw;;
esac esac
@ -269,41 +274,15 @@ do
# If destination is a directory, append the input filename; won't work # If destination is a directory, append the input filename; won't work
# if double slashes aren't ignored. # if double slashes aren't ignored.
if test -d "$dst"; then if test -d "$dst"; then
if test -n "$no_target_directory"; then if test "$is_target_a_directory" = never; then
echo "$0: $dst_arg: Is a directory" >&2 echo "$0: $dst_arg: Is a directory" >&2
exit 1 exit 1
fi fi
dstdir=$dst dstdir=$dst
dst=$dstdir/`basename "$src"` dst=$dstdir/`basename "$src"`
dstdir_status=0 dstdir_status=0
else else
# Prefer dirname, but fall back on a substitute if dirname fails. dstdir=`dirname "$dst"`
dstdir=`
(dirname "$dst") 2>/dev/null ||
expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$dst" : 'X\(//\)[^/]' \| \
X"$dst" : 'X\(//\)$' \| \
X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
echo X"$dst" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/
q
}
s/.*/./; q'
`
test -d "$dstdir" test -d "$dstdir"
dstdir_status=$? dstdir_status=$?
fi fi
@ -314,74 +293,74 @@ do
if test $dstdir_status != 0; then if test $dstdir_status != 0; then
case $posix_mkdir in case $posix_mkdir in
'') '')
# Create intermediate dirs using mode 755 as modified by the umask. # Create intermediate dirs using mode 755 as modified by the umask.
# This is like FreeBSD 'install' as of 1997-10-28. # This is like FreeBSD 'install' as of 1997-10-28.
umask=`umask` umask=`umask`
case $stripcmd.$umask in case $stripcmd.$umask in
# Optimize common cases. # Optimize common cases.
*[2367][2367]) mkdir_umask=$umask;; *[2367][2367]) mkdir_umask=$umask;;
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
*[0-7]) *[0-7])
mkdir_umask=`expr $umask + 22 \ mkdir_umask=`expr $umask + 22 \
- $umask % 100 % 40 + $umask % 20 \ - $umask % 100 % 40 + $umask % 20 \
- $umask % 10 % 4 + $umask % 2 - $umask % 10 % 4 + $umask % 2
`;; `;;
*) mkdir_umask=$umask,go-w;; *) mkdir_umask=$umask,go-w;;
esac esac
# With -d, create the new directory with the user-specified mode. # With -d, create the new directory with the user-specified mode.
# Otherwise, rely on $mkdir_umask. # Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then if test -n "$dir_arg"; then
mkdir_mode=-m$mode mkdir_mode=-m$mode
else else
mkdir_mode= mkdir_mode=
fi fi
posix_mkdir=false posix_mkdir=false
case $umask in case $umask in
*[123567][0-7][0-7]) *[123567][0-7][0-7])
# POSIX mkdir -p sets u+wx bits regardless of umask, which # POSIX mkdir -p sets u+wx bits regardless of umask, which
# is incompatible with FreeBSD 'install' when (umask & 300) != 0. # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
;; ;;
*) *)
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
if (umask $mkdir_umask && if (umask $mkdir_umask &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
then then
if test -z "$dir_arg" || { if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m. # Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writable bit of parent directory when it shouldn't. # other-writable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
ls_ld_tmpdir=`ls -ld "$tmpdir"` ls_ld_tmpdir=`ls -ld "$tmpdir"`
case $ls_ld_tmpdir in case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;; d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;; d????-?--*) different_mode=755;;
*) false;; *) false;;
esac && esac &&
$mkdirprog -m$different_mode -p -- "$tmpdir" && { $mkdirprog -m$different_mode -p -- "$tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$tmpdir"` ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
} }
} }
then posix_mkdir=: then posix_mkdir=:
fi fi
rmdir "$tmpdir/d" "$tmpdir" rmdir "$tmpdir/d" "$tmpdir"
else else
# Remove any dirs left behind by ancient mkdir implementations. # Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
fi fi
trap '' 0;; trap '' 0;;
esac;; esac;;
esac esac
if if
$posix_mkdir && ( $posix_mkdir && (
umask $mkdir_umask && umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
) )
then : then :
else else
@ -391,53 +370,51 @@ do
# directory the slow way, step by step, checking for races as we go. # directory the slow way, step by step, checking for races as we go.
case $dstdir in case $dstdir in
/*) prefix='/';; /*) prefix='/';;
[-=\(\)!]*) prefix='./';; [-=\(\)!]*) prefix='./';;
*) prefix='';; *) prefix='';;
esac esac
eval "$initialize_posix_glob"
oIFS=$IFS oIFS=$IFS
IFS=/ IFS=/
$posix_glob set -f set -f
set fnord $dstdir set fnord $dstdir
shift shift
$posix_glob set +f set +f
IFS=$oIFS IFS=$oIFS
prefixes= prefixes=
for d for d
do do
test X"$d" = X && continue test X"$d" = X && continue
prefix=$prefix$d prefix=$prefix$d
if test -d "$prefix"; then if test -d "$prefix"; then
prefixes= prefixes=
else else
if $posix_mkdir; then if $posix_mkdir; then
(umask=$mkdir_umask && (umask=$mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently. # Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1 test -d "$prefix" || exit 1
else else
case $prefix in case $prefix in
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
*) qprefix=$prefix;; *) qprefix=$prefix;;
esac esac
prefixes="$prefixes '$qprefix'" prefixes="$prefixes '$qprefix'"
fi fi
fi fi
prefix=$prefix/ prefix=$prefix/
done done
if test -n "$prefixes"; then if test -n "$prefixes"; then
# Don't fail if two instances are running concurrently. # Don't fail if two instances are running concurrently.
(umask $mkdir_umask && (umask $mkdir_umask &&
eval "\$doit_exec \$mkdirprog $prefixes") || eval "\$doit_exec \$mkdirprog $prefixes") ||
test -d "$dstdir" || exit 1 test -d "$dstdir" || exit 1
obsolete_mkdir_used=true obsolete_mkdir_used=true
fi fi
fi fi
fi fi
@ -472,15 +449,12 @@ do
# If -C, don't bother to copy if it wouldn't change the file. # If -C, don't bother to copy if it wouldn't change the file.
if $copy_on_change && if $copy_on_change &&
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
set -f &&
eval "$initialize_posix_glob" &&
$posix_glob set -f &&
set X $old && old=:$2:$4:$5:$6 && set X $old && old=:$2:$4:$5:$6 &&
set X $new && new=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 &&
$posix_glob set +f && set +f &&
test "$old" = "$new" && test "$old" = "$new" &&
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
then then
@ -493,24 +467,24 @@ do
# to itself, or perhaps because mv is so ancient that it does not # to itself, or perhaps because mv is so ancient that it does not
# support -f. # support -f.
{ {
# Now remove or move aside any old file at destination location. # Now remove or move aside any old file at destination location.
# We try this two ways since rm can't unlink itself on some # We try this two ways since rm can't unlink itself on some
# systems and the destination file might be busy for other # systems and the destination file might be busy for other
# reasons. In this case, the final cleanup might fail but the new # reasons. In this case, the final cleanup might fail but the new
# file should still install successfully. # file should still install successfully.
{ {
test ! -f "$dst" || test ! -f "$dst" ||
$doit $rmcmd -f "$dst" 2>/dev/null || $doit $rmcmd -f "$dst" 2>/dev/null ||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
} || } ||
{ echo "$0: cannot unlink or rename $dst" >&2 { echo "$0: cannot unlink or rename $dst" >&2
(exit 1); exit 1 (exit 1); exit 1
} }
} && } &&
# Now rename the file to the real destination. # Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dst" $doit $mvcmd "$dsttmp" "$dst"
} }
fi || exit 1 fi || exit 1

View file

@ -1,524 +0,0 @@
@echo off
@rem
@rem MS Windows batch file to run pcre2test on testfiles with the correct
@rem options. This file must use CRLF linebreaks to function properly,
@rem and requires both pcre2test and pcre2grep.
@rem
@rem ------------------------ HISTORY ----------------------------------
@rem This file was originally contributed to PCRE1 by Ralf Junker, and touched
@rem up by Daniel Richard G. Tests 10-12 added by Philip H.
@rem Philip H also changed test 3 to use "wintest" files.
@rem
@rem Updated by Tom Fortmann to support explicit test numbers on the command
@rem line. Added argument validation and added error reporting.
@rem
@rem Sheri Pierce added logic to skip feature dependent tests
@rem tests 4 5 7 10 12 14 19 and 22 require Unicode support
@rem 8 requires Unicode and link size 2
@rem 16 requires absence of jit support
@rem 17 requires presence of jit support
@rem Sheri P also added override tests for study and jit testing
@rem Zoltan Herczeg added libpcre16 support
@rem Zoltan Herczeg added libpcre32 support
@rem -------------------------------------------------------------------
@rem
@rem The file was converted for PCRE2 by PH, February 2015.
@rem Updated for new test 14 (moving others up a number), August 2015.
@rem Tidied and updated for new tests 21, 22, 23 by PH, October 2015.
setlocal enabledelayedexpansion
if [%srcdir%]==[] (
if exist testdata\ set srcdir=.)
if [%srcdir%]==[] (
if exist ..\testdata\ set srcdir=..)
if [%srcdir%]==[] (
if exist ..\..\testdata\ set srcdir=..\..)
if NOT exist %srcdir%\testdata\ (
Error: echo distribution testdata folder not found!
call :conferror
exit /b 1
goto :eof
)
if [%pcre2test%]==[] set pcre2test=.\pcre2test.exe
echo source dir is %srcdir%
echo pcre2test=%pcre2test%
if NOT exist %pcre2test% (
echo Error: %pcre2test% not found!
echo.
call :conferror
exit /b 1
)
%pcre2test% -C linksize >NUL
set link_size=%ERRORLEVEL%
%pcre2test% -C pcre2-8 >NUL
set support8=%ERRORLEVEL%
%pcre2test% -C pcre2-16 >NUL
set support16=%ERRORLEVEL%
%pcre2test% -C pcre2-32 >NUL
set support32=%ERRORLEVEL%
%pcre2test% -C unicode >NUL
set unicode=%ERRORLEVEL%
%pcre2test% -C jit >NUL
set jit=%ERRORLEVEL%
%pcre2test% -C backslash-C >NUL
set supportBSC=%ERRORLEVEL%
if %support8% EQU 1 (
if not exist testout8 md testout8
if not exist testoutjit8 md testoutjit8
)
if %support16% EQU 1 (
if not exist testout16 md testout16
if not exist testoutjit16 md testoutjit16
)
if %support16% EQU 1 (
if not exist testout32 md testout32
if not exist testoutjit32 md testoutjit32
)
set do1=no
set do2=no
set do3=no
set do4=no
set do5=no
set do6=no
set do7=no
set do8=no
set do9=no
set do10=no
set do11=no
set do12=no
set do13=no
set do14=no
set do15=no
set do16=no
set do17=no
set do18=no
set do19=no
set do20=no
set do21=no
set do22=no
set do23=no
set all=yes
for %%a in (%*) do (
set valid=no
for %%v in (1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23) do if %%v == %%a set valid=yes
if "!valid!" == "yes" (
set do%%a=yes
set all=no
) else (
echo Invalid test number - %%a!
echo Usage %0 [ test_number ] ...
echo Where test_number is one or more optional test numbers 1 through 23, default is all tests.
exit /b 1
)
)
set failed="no"
if "%all%" == "yes" (
set do1=yes
set do2=yes
set do3=yes
set do4=yes
set do5=yes
set do6=yes
set do7=yes
set do8=yes
set do9=yes
set do10=yes
set do11=yes
set do12=yes
set do13=yes
set do14=yes
set do15=yes
set do16=yes
set do17=yes
set do18=yes
set do19=yes
set do20=yes
set do21=yes
set do22=yes
set do23=yes
)
@echo RunTest.bat's pcre2test output is written to newly created subfolders
@echo named testout{8,16,32} and testoutjit{8,16,32}.
@echo.
set mode=
set bits=8
:nextMode
if "%mode%" == "" (
if %support8% EQU 0 goto modeSkip
echo.
echo ---- Testing 8-bit library ----
echo.
)
if "%mode%" == "-16" (
if %support16% EQU 0 goto modeSkip
echo.
echo ---- Testing 16-bit library ----
echo.
)
if "%mode%" == "-32" (
if %support32% EQU 0 goto modeSkip
echo.
echo ---- Testing 32-bit library ----
echo.
)
if "%do1%" == "yes" call :do1
if "%do2%" == "yes" call :do2
if "%do3%" == "yes" call :do3
if "%do4%" == "yes" call :do4
if "%do5%" == "yes" call :do5
if "%do6%" == "yes" call :do6
if "%do7%" == "yes" call :do7
if "%do8%" == "yes" call :do8
if "%do9%" == "yes" call :do9
if "%do10%" == "yes" call :do10
if "%do11%" == "yes" call :do11
if "%do12%" == "yes" call :do12
if "%do13%" == "yes" call :do13
if "%do14%" == "yes" call :do14
if "%do15%" == "yes" call :do15
if "%do16%" == "yes" call :do16
if "%do17%" == "yes" call :do17
if "%do18%" == "yes" call :do18
if "%do19%" == "yes" call :do19
if "%do20%" == "yes" call :do20
if "%do21%" == "yes" call :do21
if "%do22%" == "yes" call :do22
if "%do23%" == "yes" call :do23
:modeSkip
if "%mode%" == "" (
set mode=-16
set bits=16
goto nextMode
)
if "%mode%" == "-16" (
set mode=-32
set bits=32
goto nextMode
)
@rem If mode is -32, testing is finished
if %failed% == "yes" (
echo In above output, one or more of the various tests failed!
exit /b 1
)
echo All OK
goto :eof
:runsub
@rem Function to execute pcre2test and compare the output
@rem Arguments are as follows:
@rem
@rem 1 = test number
@rem 2 = outputdir
@rem 3 = test name use double quotes
@rem 4 - 9 = pcre2test options
if [%1] == [] (
echo Missing test number argument!
exit /b 1
)
if [%2] == [] (
echo Missing outputdir!
exit /b 1
)
if [%3] == [] (
echo Missing test name argument!
exit /b 1
)
set testinput=testinput%1
set testoutput=testoutput%1
if exist %srcdir%\testdata\win%testinput% (
set testinput=wintestinput%1
set testoutput=wintestoutput%1
)
echo Test %1: %3
%pcre2test% %mode% %4 %5 %6 %7 %8 %9 %srcdir%\testdata\%testinput% >%2%bits%\%testoutput%
if errorlevel 1 (
echo. failed executing command-line:
echo. %pcre2test% %mode% %4 %5 %6 %7 %8 %9 %srcdir%\testdata\%testinput% ^>%2%bits%\%testoutput%
set failed="yes"
goto :eof
)
set type=
if [%1]==[8] (
set type=-%bits%
)
if [%1]==[11] (
set type=-%bits%
)
if [%1]==[12] (
set type=-%bits%
)
if [%1]==[14] (
set type=-%bits%
)
fc /n %srcdir%\testdata\%testoutput%%type% %2%bits%\%testoutput% >NUL
if errorlevel 1 (
echo. failed comparison: fc /n %srcdir%\testdata\%testoutput% %2%bits%\%testoutput%
if [%1]==[2] (
echo.
echo ** Test 2 requires a lot of stack. PCRE2 can be configured to
echo ** use heap for recursion. Otherwise, to pass Test 2
echo ** you generally need to allocate 8 mb stack to PCRE2.
echo ** See the 'pcre2stack' page for a discussion of PCRE2's
echo ** stack usage.
echo.
)
if [%1]==[3] (
echo.
echo ** Test 3 failure usually means french locale is not
echo ** available on the system, rather than a bug or problem with PCRE2.
echo.
goto :eof
)
set failed="yes"
goto :eof
)
echo. Passed.
goto :eof
:do1
call :runsub 1 testout "Main non-UTF, non-UCP functionality (Compatible with Perl >= 5.10)" -q
if %jit% EQU 1 call :runsub 1 testoutjit "Test with JIT Override" -q -jit
goto :eof
:do2
call :runsub 2 testout "API, errors, internals, and non-Perl stuff" -q
if %jit% EQU 1 call :runsub 2 testoutjit "Test with JIT Override" -q -jit
goto :eof
:do3
call :runsub 3 testout "Locale-specific features" -q
if %jit% EQU 1 call :runsub 3 testoutjit "Test with JIT Override" -q -jit
goto :eof
:do4
if %unicode% EQU 0 (
echo Test 4 Skipped due to absence of Unicode support.
goto :eof
)
call :runsub 4 testout "UTF-%bits% and Unicode property support - (Compatible with Perl >= 5.10)" -q
if %jit% EQU 1 call :runsub 4 testoutjit "Test with JIT Override" -q -jit
goto :eof
:do5
if %unicode% EQU 0 (
echo Test 5 Skipped due to absence of Unicode support.
goto :eof
)
call :runsub 5 testout "API, internals, and non-Perl stuff for UTF-%bits% and UCP" -q
if %jit% EQU 1 call :runsub 5 testoutjit "Test with JIT Override" -q -jit
goto :eof
:do6
call :runsub 6 testout "DFA matching main non-UTF, non-UCP functionality" -q
goto :eof
:do7
if %unicode% EQU 0 (
echo Test 7 Skipped due to absence of Unicode support.
goto :eof
)
call :runsub 7 testout "DFA matching with UTF-%bits% and Unicode property support" -q
goto :eof
:do8
if NOT %link_size% EQU 2 (
echo Test 8 Skipped because link size is not 2.
goto :eof
)
if %unicode% EQU 0 (
echo Test 8 Skipped due to absence of Unicode support.
goto :eof
)
call :runsub 8 testout "Internal offsets and code size tests" -q
goto :eof
:do9
if NOT %bits% EQU 8 (
echo Test 9 Skipped when running 16/32-bit tests.
goto :eof
)
call :runsub 9 testout "Specials for the basic 8-bit library" -q
if %jit% EQU 1 call :runsub 9 testoutjit "Test with JIT Override" -q -jit
goto :eof
:do10
if NOT %bits% EQU 8 (
echo Test 10 Skipped when running 16/32-bit tests.
goto :eof
)
if %unicode% EQU 0 (
echo Test 10 Skipped due to absence of Unicode support.
goto :eof
)
call :runsub 10 testout "Specials for the 8-bit library with Unicode support" -q
if %jit% EQU 1 call :runsub 10 testoutjit "Test with JIT Override" -q -jit
goto :eof
:do11
if %bits% EQU 8 (
echo Test 11 Skipped when running 8-bit tests.
goto :eof
)
call :runsub 11 testout "Specials for the basic 16/32-bit library" -q
if %jit% EQU 1 call :runsub 11 testoutjit "Test with JIT Override" -q -jit
goto :eof
:do12
if %bits% EQU 8 (
echo Test 12 Skipped when running 8-bit tests.
goto :eof
)
if %unicode% EQU 0 (
echo Test 12 Skipped due to absence of Unicode support.
goto :eof
)
call :runsub 12 testout "Specials for the 16/32-bit library with Unicode support" -q
if %jit% EQU 1 call :runsub 12 testoutjit "Test with JIT Override" -q -jit
goto :eof
:do13
if %bits% EQU 8 (
echo Test 13 Skipped when running 8-bit tests.
goto :eof
)
call :runsub 13 testout "DFA specials for the basic 16/32-bit library" -q
goto :eof
:do14
if %unicode% EQU 0 (
echo Test 14 Skipped due to absence of Unicode support.
goto :eof
)
call :runsub 14 testout "DFA specials for UTF and UCP support" -q
goto :eof
:do15
call :runsub 15 testout "Non-JIT limits and other non_JIT tests" -q
goto :eof
:do16
if %jit% EQU 1 (
echo Test 16 Skipped due to presence of JIT support.
goto :eof
)
call :runsub 16 testout "JIT-specific features when JIT is not available" -q
goto :eof
:do17
if %jit% EQU 0 (
echo Test 17 Skipped due to absence of JIT support.
goto :eof
)
call :runsub 17 testout "JIT-specific features when JIT is available" -q
goto :eof
:do18
if %bits% EQU 16 (
echo Test 18 Skipped when running 16-bit tests.
goto :eof
)
if %bits% EQU 32 (
echo Test 18 Skipped when running 32-bit tests.
goto :eof
)
call :runsub 18 testout "POSIX interface, excluding UTF-8 and UCP" -q
goto :eof
:do19
if %bits% EQU 16 (
echo Test 19 Skipped when running 16-bit tests.
goto :eof
)
if %bits% EQU 32 (
echo Test 19 Skipped when running 32-bit tests.
goto :eof
)
if %unicode% EQU 0 (
echo Test 19 Skipped due to absence of Unicode support.
goto :eof
)
call :runsub 19 testout "POSIX interface with UTF-8 and UCP" -q
goto :eof
:do20
call :runsub 20 testout "Serialization tests" -q
goto :eof
:do21
if %supportBSC% EQU 0 (
echo Test 21 Skipped due to absence of backslash-C support.
goto :eof
)
call :runsub 21 testout "Backslash-C tests without UTF" -q
call :runsub 21 testout "Backslash-C tests without UTF (DFA)" -q -dfa
if %jit% EQU 1 call :runsub 21 testoutjit "Test with JIT Override" -q -jit
goto :eof
:do22
if %supportBSC% EQU 0 (
echo Test 22 Skipped due to absence of backslash-C support.
goto :eof
)
if %unicode% EQU 0 (
echo Test 22 Skipped due to absence of Unicode support.
goto :eof
)
call :runsub 22 testout "Backslash-C tests with UTF" -q
if %jit% EQU 1 call :runsub 22 testoutjit "Test with JIT Override" -q -jit
goto :eof
:do23
if %supportBSC% EQU 1 (
echo Test 23 Skipped due to presence of backslash-C support.
goto :eof
)
call :runsub 23 testout "Backslash-C disabled test" -q
goto :eof
:conferror
@echo.
@echo Either your build is incomplete or you have a configuration error.
@echo.
@echo If configured with cmake and executed via "make test" or the MSVC "RUN_TESTS"
@echo project, pcre2_test.bat defines variables and automatically calls RunTest.bat.
@echo For manual testing of all available features, after configuring with cmake
@echo and building, you can run the built pcre2_test.bat. For best results with
@echo cmake builds and tests avoid directories with full path names that include
@echo spaces for source or build.
@echo.
@echo Otherwise, if the build dir is in a subdir of the source dir, testdata needed
@echo for input and verification should be found automatically when (from the
@echo location of the the built exes) you call RunTest.bat. By default RunTest.bat
@echo runs all tests compatible with the linked pcre2 library but it can be given
@echo a test number as an argument.
@echo.
@echo If the build dir is not under the source dir you can either copy your exes
@echo to the source folder or copy RunTest.bat and the testdata folder to the
@echo location of your built exes and then run RunTest.bat.
@echo.
goto :eof

View file

@ -1291,8 +1291,8 @@ msgstr ""
#: reader.cpp:4115 #: reader.cpp:4115
#, c-format #, c-format
msgid "Unknown keybinding %d" msgid "Unknown key binding 0x%X"
msgstr "Unbekannte Tastenkombination %d" msgstr "Unbekannte Tastenkombination 0x%X"
#: reader.cpp:4226 #: reader.cpp:4226
#, fuzzy #, fuzzy

View file

@ -1284,8 +1284,8 @@ msgstr ""
#: reader.cpp:4115 #: reader.cpp:4115
#, c-format #, c-format
msgid "Unknown keybinding %d" msgid "Unknown key binding 0x%X"
msgstr "Unknown keybinding %d" msgstr "Unknown key binding 0x%X"
#: reader.cpp:4226 #: reader.cpp:4226
msgid "Error while reading from file descriptor" msgid "Error while reading from file descriptor"

View file

@ -1306,8 +1306,8 @@ msgstr ""
#: reader.cpp:4115 #: reader.cpp:4115
#, c-format #, c-format
msgid "Unknown keybinding %d" msgid "Unknown key binding 0x%X"
msgstr "Raccourci clavier inconnu %d" msgstr "Raccourci clavier inconnu 0x%X"
#: reader.cpp:4226 #: reader.cpp:4226
#, fuzzy #, fuzzy

View file

@ -1306,8 +1306,8 @@ msgstr ""
#: reader.cpp:4115 #: reader.cpp:4115
#, c-format #, c-format
msgid "Unknown keybinding %d" msgid "Unknown key binding 0x%X"
msgstr "Atalho desconhecido %d" msgstr "Atalho desconhecido 0x%X"
#: reader.cpp:4226 #: reader.cpp:4226
msgid "Error while reading from file descriptor" msgid "Error while reading from file descriptor"

View file

@ -1295,8 +1295,8 @@ msgstr ""
#: reader.cpp:4115 #: reader.cpp:4115
#, c-format #, c-format
msgid "Unknown keybinding %d" msgid "Unknown key binding 0x%X"
msgstr "Okänd tangentbordsbindning %d" msgstr "Okänd tangentbords binding 0x%X"
#: reader.cpp:4226 #: reader.cpp:4226
msgid "Error while reading from file descriptor" msgid "Error while reading from file descriptor"

View file

@ -1273,8 +1273,8 @@ msgstr ""
#: reader.cpp:4115 #: reader.cpp:4115
#, c-format #, c-format
msgid "Unknown keybinding %d" msgid "Unknown key binding 0x%X"
msgstr "Unknown keybinding %d" msgstr "Unknown key binding 0x%X"
#: reader.cpp:4226 #: reader.cpp:4226
msgid "Error while reading from file descriptor" msgid "Error while reading from file descriptor"

View file

@ -1,5 +1,7 @@
complete -c abbr -f -s a -l add -d 'Add abbreviation' complete -c abbr -f -s a -l add -d 'Add abbreviation'
complete -c abbr -s e -l erase -d 'Erase abbreviation' -xa '(abbr -s | cut -d" " -f 2- | sed -e "s/ / /")' # Abbr keys can't contain spaces, so we can safely replace the first space with a tab
# `abbr -s` won't work here because that already escapes
complete -c abbr -s e -l erase -d 'Erase abbreviation' -xa '(string replace " " \t -- $fish_user_abbreviations)'
complete -c abbr -f -s s -l show -d 'Print all abbreviations' complete -c abbr -f -s s -l show -d 'Print all abbreviations'
complete -c abbr -f -s l -l list -d 'Print all abbreviation names' complete -c abbr -f -s l -l list -d 'Print all abbreviation names'
complete -c abbr -f -s h -l help -d 'Help' complete -c abbr -f -s h -l help -d 'Help'

306
share/completions/arc.fish Normal file
View file

@ -0,0 +1,306 @@
# fish completion for arc
function __fish_arc_needs_command
set cmd (commandline -opc)
if not set -q cmd[2]
return 0
else
set -l skip_next 1
# Skip first word because it's "arc" or a wrapper
for c in $cmd[2..-1]
switch $c
# General options that can still take a command
case "--trace" "--no-ansi" "--ansi" "--load-phutil-library" "config" "skip-arcconfig" "arcrc-file" --conduit-{uri,token,version,timeout}
continue
case "*"
echo $c
return 1
end
end
return 0
end
return 1
end
function __fish_arc_using_command
set -l cmd (__fish_arc_needs_command)
test -z "$cmd"
and return 1
contains -- $cmd $argv
and return 0
end
### Global options
complete -f -c arc -n '__fish_arc_needs_command' -l trace -d 'Debugging command'
complete -f -c arc -n '__fish_arc_needs_command' -l no-ansi -d 'Don\'t use color or style for output'
complete -f -c arc -n '__fish_arc_needs_command' -l ansi -d 'Always use fromatting'
complete -f -c arc -n '__fish_arc_needs_command' -l no-ansi -d 'Don\'t use color or style for output'
complete -f -c arc -n '__fish_arc_needs_command' -l load-phutil-library -d 'Specify which libraies to load'
complete -f -c arc -n '__fish_arc_needs_command' -l conduit-uri -d 'Specify the Conduit URI'
complete -f -c arc -n '__fish_arc_needs_command' -l conduit-token -d 'Specify the Conduit token'
complete -f -c arc -n '__fish_arc_needs_command' -l conduit-version -d 'Force a version'
complete -f -c arc -n '__fish_arc_needs_command' -l conduit-timeout -d 'Sets the timeout'
complete -f -c arc -n '__fish_arc_needs_command' -l config -d 'Sets a config'
complete -f -c arc -n '__fish_arc_needs_command' -l skip-arcconfig -d 'Skip the working copy configuration file'
complete -c arc -n '__fish_arc_needs_command' -l arcrc-file -d 'Use provided file instead of ~/.arcrc'
### shell-complete
complete -f -c arc -n '__fish_arc_needs_command' -a shell-complete -d 'Implements shell completion'
complete -f -c arc -n '__fish_arc_using_command shell-complete' -l current -d 'Current term in the argument list being completed'
### get-config
complete -f -c arc -n '__fish_arc_needs_command' -a get-config -d 'Reads an arc configuration option'
complete -f -c arc -n '__fish_arc_using_command get-config' -l verbose -d 'Show detailed information about options'
### download
complete -f -c arc -n '__fish_arc_needs_command' -a download -d 'Download a file to local disk'
complete -c arc -n '__fish_arc_using_command download' -l as -d 'Save the file with a specific name rather than the default'
complete -f -c arc -n '__fish_arc_using_command download' -l show -d 'Write file to stdout instead of to disk'
### list
complete -f -c arc -n '__fish_arc_needs_command' -a list -d 'List your open Differential revisions'
### lint
complete -f -c arc -n '__fish_arc_needs_command' -a lint -d 'Run static analysis on changes to check for mistakes'
complete -f -c arc -n '__fish_arc_using_command lint' -l engine -d 'Override configured lint engine for this project'
complete -f -c arc -n '__fish_arc_using_command lint' -l apply-patches -d 'Apply patches suggested by lint to the working copy'
complete -f -c arc -n '__fish_arc_using_command lint' -l severity -d 'Set minimum message severity'
complete -f -c arc -n '__fish_arc_using_command lint' -l never-apply-patches -d 'Never apply patches suggested by lint'
complete -f -c arc -n '__fish_arc_using_command lint' -l rev -d 'Lint changes since a specific revision'
complete -c arc -n '__fish_arc_using_command lint' -l outfile -d 'Output the linter results to a file'
complete -f -c arc -n '__fish_arc_using_command lint' -l lintall -d 'Show all lint warnings, not just those on changed lines'
complete -f -c arc -n '__fish_arc_using_command lint' -l amend-all -d 'When linting git repositories, amend HEAD with all patches'
complete -f -c arc -n '__fish_arc_using_command lint' -l everything -d 'Lint all files in the project'
complete -f -c arc -n '__fish_arc_using_command lint' -l output -d 'Specify how results will be displayed'
complete -f -c arc -n '__fish_arc_using_command lint' -l only-new -d 'Display only messages not present in the original code'
complete -f -c arc -n '__fish_arc_using_command lint' -l only-changed -d 'Show lint warnings just on changed lines'
complete -f -c arc -n '__fish_arc_using_command lint' -l amend-autofixes -d 'When linting git repositories, amend HEAD with autofix'
### flag
complete -f -c arc -n '__fish_arc_needs_command' -a flag -d 'In the first form, list objects you\'ve flagged'
complete -f -c arc -n '__fish_arc_using_command flag' -l edit -d 'Edit the flag on an object'
complete -f -c arc -n '__fish_arc_using_command flag' -l color -d 'Set the color of a flag'
complete -f -c arc -n '__fish_arc_using_command flag' -l clear -d 'Delete the flag on an object'
complete -f -c arc -n '__fish_arc_using_command flag' -l note -d 'Set the note on a flag'
### export
complete -c arc -n '__fish_arc_needs_command' -a export -d 'Export the local changeset to a file'
complete -f -c arc -n '__fish_arc_using_command export' -l unified -d 'Export change as a unified patch'
complete -f -c arc -n '__fish_arc_using_command export' -l git -d 'Export change as a git patch'
complete -f -c arc -n '__fish_arc_using_command export' -l encoding -d 'Attempt to convert non UTF-8 patch into specified encoding'
complete -f -c arc -n '__fish_arc_using_command export' -l arcbundle -d 'Export change as an arc bundle'
complete -f -c arc -n '__fish_arc_using_command export' -l diff -d 'Export from Differential diff'
complete -f -c arc -n '__fish_arc_using_command export' -l revision -d 'Export from a Differential revision'
### browse
complete -c arc -n '__fish_arc_needs_command' -a browse -d 'Open a file or object in your web browser'
complete -f -c arc -n '__fish_arc_using_command browse' -l force -d 'Open arguments as paths, even if they do not exist in the working copy'
complete -f -c arc -n '__fish_arc_using_command browse' -l branch -d 'Default branch name to view on server'
### todo
complete -f -c arc -n '__fish_arc_needs_command' -a todo -d 'Quickly create a task for yourself'
complete -f -c arc -n '__fish_arc_using_command todo' -l cc -d 'Other users to CC on the new task'
complete -f -c arc -n '__fish_arc_using_command todo' -l project -d 'Projects to assign to the task'
complete -f -c arc -n '__fish_arc_using_command todo' -l browse -d 'After creating the task, open it in a web browser'
### linters
complete -f -c arc -n '__fish_arc_needs_command' -a linters -d 'what they do and which versions are installed'
complete -f -c arc -n '__fish_arc_using_command linters' -l search -d 'Search for linters'
complete -f -c arc -n '__fish_arc_using_command linters' -l verbose -d 'Show detailed information, including options'
### time
complete -f -c arc -n '__fish_arc_needs_command' -a time -d 'Show what you\'re currently tracking in Phrequent'
### stop
complete -f -c arc -n '__fish_arc_needs_command' -a stop -d 'Stop tracking work in Phrequent'
complete -f -c arc -n '__fish_arc_using_command stop' -l note -d 'A note to attach to the tracked time'
### alias
complete -f -c arc -n '__fish_arc_needs_command' -a alias -d 'Create an alias'
### set-config
complete -f -c arc -n '__fish_arc_needs_command' -a set-config -d 'Sets an arc configuration option'
complete -f -c arc -n '__fish_arc_using_command set-config' -l local -d 'Set a local config value instead of a user one'
### start
complete -f -c arc -n '__fish_arc_needs_command' -a start -d 'Start tracking work in Phrequent'
### close
complete -f -c arc -n '__fish_arc_needs_command' -a close -d 'Close a task or otherwise update its status'
complete -f -c arc -n '__fish_arc_using_command close' -l message -d 'Provide a comment with your status change'
complete -f -c arc -n '__fish_arc_using_command close' -l list-statuses -d 'Show available status options and exit'
### land
complete -f -c arc -n '__fish_arc_needs_command' -a land -d 'Publish an accepted revision after review'
complete -f -c arc -n '__fish_arc_using_command land' -l preview -d 'Prints the commits that would be landed'
complete -f -c arc -n '__fish_arc_using_command land' -l remote -d 'Push to a remote other than the default'
complete -f -c arc -n '__fish_arc_using_command land' -l delete-remote -d 'Delete the feature branch in the remote after landing it'
complete -f -c arc -n '__fish_arc_using_command land' -l update-with-rebase -d 'When updating the feature branch, use rebase instead of merge'
complete -f -c arc -n '__fish_arc_using_command land' -l squash -d 'Use squash strategy'
complete -f -c arc -n '__fish_arc_using_command land' -l keep-branch -d 'Keep the feature branch'
complete -f -c arc -n '__fish_arc_using_command land' -l merge -d 'Use merge strategy'
complete -f -c arc -n '__fish_arc_using_command land' -l update-with-merge -d 'When updating the feature branch, use merge instead of rebase'
complete -f -c arc -n '__fish_arc_using_command land' -l hold -d 'Prepare the change to be pushed, but do not actually push it'
complete -f -c arc -n '__fish_arc_using_command land' -l onto -d 'Land feature branch onto a branch other than the default'
complete -f -c arc -n '__fish_arc_using_command land' -l revision -d 'Use the message from a specific revision'
### which
complete -f -c arc -n '__fish_arc_needs_command' -a which -d 'Show which commits will be selected'
complete -f -c arc -n '__fish_arc_using_command which' -l show-base -d 'Print base commit only and exit'
complete -f -c arc -n '__fish_arc_using_command which' -l base -d 'Additional rules for determining base revision'
complete -f -c arc -n '__fish_arc_using_command which' -l head -d 'Specify the end of the commit range to select'
complete -f -c arc -n '__fish_arc_using_command which' -l any-status -d 'Show committed and abandoned revisions'
### bookmark
complete -f -c arc -n '__fish_arc_needs_command' -a bookmark -d 'Alias for arc feature'
### amend
complete -f -c arc -n '__fish_arc_needs_command' -a amend -d 'Amend the working copy'
complete -f -c arc -n '__fish_arc_using_command amend' -l revision -d 'Use the message from a specific revision'
complete -f -c arc -n '__fish_arc_using_command amend' -l show -d 'Show the amended commit message'
### upgrade
complete -f -c arc -n '__fish_arc_needs_command' -a upgrade -d 'Upgrade arcanist and libphutil to the latest versions'
### help
complete -f -c arc -n '__fish_arc_needs_command' -a help -d 'Shows the help'
complete -f -c arc -n '__fish_arc_using_command help' -l full -d 'Print detailed information about each command'
### paste
complete -f -c arc -n '__fish_arc_needs_command' -a paste -d 'Share and grab text using the Paste application'
complete -f -c arc -n '__fish_arc_using_command paste' -l lang -d 'Language for syntax highlighting'
complete -f -c arc -n '__fish_arc_using_command paste' -l json -d 'Output in JSON format'
complete -f -c arc -n '__fish_arc_using_command paste' -l title -d 'Title for the paste'
### commit
complete -f -c arc -n '__fish_arc_needs_command' -a commit -d 'Commit a revision which has been accepted by a reviewer'
complete -f -c arc -n '__fish_arc_using_command commit' -l revision -d 'Commit a specific revision'
complete -f -c arc -n '__fish_arc_using_command commit' -l show -d 'Show the command which would be issued'
### patch
complete -f -c arc -n '__fish_arc_needs_command' -a patch -d 'Apply changes to the working copy'
complete -f -c arc -n '__fish_arc_using_command patch' -l force -d 'Do not run any sanity checks'
complete -f -c arc -n '__fish_arc_using_command patch' -l encoding -d 'Attempt to convert non UTF-8 patch into specified encoding'
complete -f -c arc -n '__fish_arc_using_command patch' -l nocommit -d 'Do not commit the changes'
complete -f -c arc -n '__fish_arc_using_command patch' -l update -d 'Update the local working copy before applying the patch'
complete -c arc -n '__fish_arc_using_command patch' -l patch -d 'Apply changes from a git patch file or unified patch file'
complete -f -c arc -n '__fish_arc_using_command patch' -l arcbundle -d 'Apply changes from an arc bundlej'
complete -f -c arc -n '__fish_arc_using_command patch' -l skip-dependencies -d 'Do not apply dependencies'
complete -f -c arc -n '__fish_arc_using_command patch' -l diff -d 'Apply changes from a Differential diff'
complete -f -c arc -n '__fish_arc_using_command patch' -l nobranch -d 'Do not create a branch'
complete -f -c arc -n '__fish_arc_using_command patch' -l revision -d 'Apply changes from a Differential revision'
### install-certificate
complete -f -c arc -n '__fish_arc_needs_command' -a install-certificate -d 'Installs Conduit credentials into your ~/.arcc'
### revert
complete -f -c arc -n '__fish_arc_needs_command' -a revert -d 'Please use backout instead'
### upload
complete -c arc -n '__fish_arc_needs_command' -a upload -d 'Upload a file from local disk'
complete -f -c arc -n '__fish_arc_using_command upload' -l json -d 'Output upload information in JSON format'
complete -f -c arc -n '__fish_arc_using_command upload' -l temporary -d 'Mark the file as temporary'
### branch
complete -f -c arc -n '__fish_arc_needs_command' -a branch -d 'Alias for arc feature'
### anoid
complete -f -c arc -n '__fish_arc_needs_command' -a anoid -d 'There\'s only one way to find out'
### cover
complete -f -c arc -n '__fish_arc_needs_command' -a cover -d 'Show blame for the lines you changed'
complete -f -c arc -n '__fish_arc_using_command cover' -l rev -d 'Cover changes since a specific revision'
### close-revision
complete -f -c arc -n '__fish_arc_needs_command' -a close-revision -d 'Close a revision'
complete -f -c arc -n '__fish_arc_using_command close-revision' -l quiet -d 'Do not print a success message'
complete -f -c arc -n '__fish_arc_using_command close-revision' -l finalize -d 'Close only if the repository is untracked and the revision is accepted'
### tasks
complete -f -c arc -n '__fish_arc_needs_command' -a tasks -d 'View all assigned tasks'
complete -f -c arc -n '__fish_arc_using_command tasks' -l status -d 'Show tasks that are open or closed, default is open'
complete -f -c arc -n '__fish_arc_using_command tasks' -l owner -d 'Only show tasks assigned to the given username,'
complete -f -c arc -n '__fish_arc_using_command tasks' -l unassigned -d 'Only show tasks that are not assigned'
complete -f -c arc -n '__fish_arc_using_command tasks' -l limit -d 'Limit the amount of tasks outputted, default is all'
complete -f -c arc -n '__fish_arc_using_command tasks' -l order -d 'Arrange tasks based on priority, created, or modified,'
### feature
complete -f -c arc -n '__fish_arc_needs_command' -a feature -d 'A wrapper on \'git branch\' or \'hg bookmark'
complete -f -c arc -n '__fish_arc_using_command feature' -l output -d 'Specify the output format'
complete -f -c arc -n '__fish_arc_using_command feature' -l view-all -d 'Include closed and abandoned revisions'
complete -f -c arc -n '__fish_arc_using_command feature' -l by-status -d 'Sort branches by status instead of time'
### unit
complete -f -c arc -n '__fish_arc_needs_command' -a unit -d 'Run unit tests that cover specified paths'
complete -f -c arc -n '__fish_arc_using_command unit' -l engine -d 'Override configured unit engine for this project'
complete -f -c arc -n '__fish_arc_using_command unit' -l detailed-coverage -d 'Show a detailed coverage report on the CLI'
complete -f -c arc -n '__fish_arc_using_command unit' -l target -d 'Record a copy of the test results on the specified build target'
complete -f -c arc -n '__fish_arc_using_command unit' -l ugly -d 'Use uglier formatting'
complete -f -c arc -n '__fish_arc_using_command unit' -l rev -d 'Run unit tests covering changes since a specific revision'
complete -f -c arc -n '__fish_arc_using_command unit' -l everything -d 'Run every test'
complete -f -c arc -n '__fish_arc_using_command unit' -l json -d 'Report results in JSON format'
complete -f -c arc -n '__fish_arc_using_command unit' -l coverage -d 'Always enable coverage information'
complete -f -c arc -n '__fish_arc_using_command unit' -l output -d 'Specify the output format'
complete -f -c arc -n '__fish_arc_using_command unit' -l no-coverage -d 'Always disable coverage information'
### backout
complete -f -c arc -n '__fish_arc_needs_command' -a backout -d 'Backouts on a previous commit'
### call-conduit
complete -f -c arc -n '__fish_arc_needs_command' -a call-conduit -d 'Make a raw Conduit method call'
### diff
complete -f -c arc -n '__fish_arc_needs_command' -a diff -d 'Generate a Differential diff or revision from local changes'
complete -f -c arc -n '__fish_arc_using_command diff' -l raw-command -d 'Generate diff by executing a specified command'
complete -f -c arc -n '__fish_arc_using_command diff' -l encoding -d 'Attempt to convert non UTF-8 hunks into specified encoding'
complete -f -c arc -n '__fish_arc_using_command diff' -l cc -d 'When creating a revision, add CCs'
complete -f -c arc -n '__fish_arc_using_command diff' -l reviewers -d 'When creating a revision, add reviewers'
complete -f -c arc -n '__fish_arc_using_command diff' -l skip-staging -d 'Do not copy changes to the staging area'
complete -f -c arc -n '__fish_arc_using_command diff' -l raw -d 'Read diff from stdin'
complete -f -c arc -n '__fish_arc_using_command diff' -l uncommitted -d 'Suppress warning about uncommitted changes'
complete -c arc -n '__fish_arc_using_command diff' -l message-file -d 'Read revision information from file'
complete -f -c arc -n '__fish_arc_using_command diff' -l nolint -d 'Do not run lint'
complete -f -c arc -n '__fish_arc_using_command diff' -l message -d 'Use the specified message when updating a revision'
complete -f -c arc -n '__fish_arc_using_command diff' -l plan-changes -d 'Create or update a revision without requesting a code review'
complete -f -c arc -n '__fish_arc_using_command diff' -l browse -d 'After creating a diff or revision, open it in a web browser'
complete -f -c arc -n '__fish_arc_using_command diff' -l create -d 'Always create a new revision'
complete -f -c arc -n '__fish_arc_using_command diff' -l cache -d 'Disable lint cache'
complete -f -c arc -n '__fish_arc_using_command diff' -l use-commit-message -d 'Read revision information from a specific commit'
complete -f -c arc -n '__fish_arc_using_command diff' -l only -d 'Only generate a diff, without running lint, unit tests, or other'
complete -f -c arc -n '__fish_arc_using_command diff' -l skip-binaries -d 'Do not upload binaries'
complete -f -c arc -n '__fish_arc_using_command diff' -l preview -d 'only create a diff'
complete -f -c arc -n '__fish_arc_using_command diff' -l amend-autofixes -d 'When linting git repositories, amend HEAD with autofix'
complete -f -c arc -n '__fish_arc_using_command diff' -l apply-patches -d 'Apply patches suggested by lint'
complete -f -c arc -n '__fish_arc_using_command diff' -l head -d 'Specify the end of the commit range'
complete -f -c arc -n '__fish_arc_using_command diff' -l verbatim -d 'When creating a revision, try to use the working copy commit'
complete -f -c arc -n '__fish_arc_using_command diff' -l less-context -d 'Create a diff with a few lines of context.'
complete -f -c arc -n '__fish_arc_using_command diff' -l advice -d 'Require excuse for lint advice in addition to lint warnings and errors'
complete -f -c arc -n '__fish_arc_using_command diff' -l json -d 'Emit machine-readable JSON'
complete -f -c arc -n '__fish_arc_using_command diff' -l update -d 'Always update a specific revision'
complete -f -c arc -n '__fish_arc_using_command diff' -l ignore-unsound-tests -d 'Ignore unsound test failures without prompting'
complete -f -c arc -n '__fish_arc_using_command diff' -l excuse -d 'Provide a prepared in advance excuse for any lints/tests'
complete -f -c arc -n '__fish_arc_using_command diff' -l base -d 'Additional rules for determining base revision'
complete -f -c arc -n '__fish_arc_using_command diff' -l no-amend -d 'Never amend commits in the working copy with lint patches'
complete -f -c arc -n '__fish_arc_using_command diff' -l add-all -d 'Automatically add all unstaged and uncommitted'
complete -f -c arc -n '__fish_arc_using_command diff' -l never-apply-patches -d 'Never apply patches suggested by lint'
complete -f -c arc -n '__fish_arc_using_command diff' -l edit -d 'Edit revision information'
complete -f -c arc -n '__fish_arc_using_command diff' -l nounit -d 'Do not run unit tests'
complete -f -c arc -n '__fish_arc_using_command diff' -l lintall -d 'Raise all lint warnings'
complete -f -c arc -n '__fish_arc_using_command diff' -l amend-all -d 'When linting git repositories, amend HEAD with all patches'
complete -f -c arc -n '__fish_arc_using_command diff' -l no-diff -d 'Only run lint and unit tests'
complete -f -c arc -n '__fish_arc_using_command diff' -l allow-untracked -d 'Skip checks for untracked files in the working copy'
complete -f -c arc -n '__fish_arc_using_command diff' -l only-new -d 'Display only new lint messages'
complete -f -c arc -n '__fish_arc_using_command diff' -l no-coverage -d 'Always disable coverage information'
### liberate
complete -f -c arc -n '__fish_arc_needs_command' -a liberate -d 'Create or update a libphutil library'
complete -f -c arc -n '__fish_arc_using_command liberate' -l remap -d 'Run the remap step of liberation'
complete -f -c arc -n '__fish_arc_using_command liberate' -l upgrade -d 'Upgrade library to v2'
complete -f -c arc -n '__fish_arc_using_command liberate' -l verify -d 'Run the verify step of liberation'
complete -f -c arc -n '__fish_arc_using_command liberate' -l all -d 'Drop the module cache before liberating'
complete -f -c arc -n '__fish_arc_using_command liberate' -l force-update -d 'Force the library map to be updated'
complete -f -c arc -n '__fish_arc_using_command liberate' -l library-name -d 'Set the library name'
### version
complete -f -c arc -n '__fish_arc_needs_command' -a version -d 'Shows the current version of arcanist'

View file

@ -156,7 +156,7 @@ complete -c aura -n $remove -s c -l cascade -d 'Also remove packages depending o
complete -c aura -n $remove -s n -l nosave -d 'Ignore file backup designations' complete -c aura -n $remove -s n -l nosave -d 'Ignore file backup designations'
complete -c aura -n $remove -s s -l recursive -d 'Also remove dependencies of PACKAGE' complete -c aura -n $remove -s s -l recursive -d 'Also remove dependencies of PACKAGE'
complete -c aura -n $remove -s u -l unneeded -d 'Only remove targets not required by PACKAGE' complete -c aura -n $remove -s u -l unneeded -d 'Only remove targets not required by PACKAGE'
complete -c aura -n "$remove; and $argument" -xa $listinstalled -d 'Installed package'
# Sync options # Sync options
complete -c aura -n $sync -s c -l clean -d 'Remove [all] packages from cache' complete -c aura -n $sync -s c -l clean -d 'Remove [all] packages from cache'
@ -164,7 +164,7 @@ complete -c aura -n $sync -s l -l list -xa "$listrepos" -d 'List all packages in
complete -c aura -n $sync -s u -l sysupgrade -d 'Upgrade all packages that are out of date' complete -c aura -n $sync -s u -l sysupgrade -d 'Upgrade all packages that are out of date'
complete -c aura -n $sync -s w -l downloadonly -d 'Only download the target packages' complete -c aura -n $sync -s w -l downloadonly -d 'Only download the target packages'
complete -c aura -n $sync -s y -l refresh -d 'Download fresh copy of the package list' complete -c aura -n $sync -s y -l refresh -d 'Download fresh copy of the package list'
complete -c aura -n "$argument; and $sync" -xa "$listall $listgroups" complete -c aura -n "$sync; and $argument" -xa "$listall $listgroups"
# Upgrade options # Upgrade options
complete -c aura -n "$upgrade; and $argument" -xa '(__fish_complete_suffix pkg.tar.xz)' -d 'Package file' complete -c aura -n "$upgrade; and $argument" -xa '(__fish_complete_suffix pkg.tar.xz)' -d 'Package file'

View file

@ -17,9 +17,16 @@ function __fish_brew_using_command
end end
function __fish_brew_formulae function __fish_brew_formulae
set -l formuladir (brew --repository)/Library/Formula/ # list all local formula, do not use `brew search some_text` against searching online
# __fish_complete_suffix .rb # TODO fix the problem with `tap-pin`, tap-pin will modify the priority
ls $formuladir/*.rb | sed 's/.rb$//' | sed "s|^$formuladir||" # If you pin your custom tap for VIM, you should
# `brew install homebrew/core/vim` to install VIM from `core` repo
# `brew install vim` to install VIM from more prior repo
# but `brew search` won't change display for custom VIM and core VIM
# 'vim' for core VIM
# 'custUser/custRepo/vim' for more prior VIM
# more info: https://github.com/Homebrew/brew/blob/master/share/doc/homebrew/brew-tap.md#formula-duplicate-names
brew search
end end
function __fish_brew_installed_formulas function __fish_brew_installed_formulas

View file

@ -6,18 +6,29 @@ function __fish_git_commits
# This allows filtering by subject with the new pager! # This allows filtering by subject with the new pager!
# Because even subject lines can be quite long, # Because even subject lines can be quite long,
# trim them (abbrev'd hash+tab+subject) to 73 characters # trim them (abbrev'd hash+tab+subject) to 73 characters
command git log --pretty=tformat:"%h"\t"%s" --all ^/dev/null \ command git log --pretty=tformat:"%h"\t"%s" --all --max-count=1000 ^/dev/null \
| string replace -r '(.{73}).+' '$1…'
end
function __fish_git_recent_commits
# Like __fish_git_commits, but not on all branches and limited to
# the last 50 commits. Used for fixup, where only the current branch
# and the latest commits make sense.
command git log --pretty=tformat:"%h"\t"%s" --max-count=50 ^/dev/null \
| string replace -r '(.{73}).+' '$1…' | string replace -r '(.{73}).+' '$1…'
end end
function __fish_git_branches function __fish_git_branches
command git branch --no-color -a $argv ^/dev/null | string match -r -v ' -> ' | string trim -c "* " | string replace -r "^remotes/" "" # In some cases, git can end up on no branch - e.g. with a detached head
# This will result in output like `* (no branch)` or a localized `* (HEAD detached at SHA)`
# The first `string match -v` filters it out because it's not useful as a branch argument
command git branch --no-color -a $argv ^/dev/null | string match -v '\* (*)' | string match -r -v ' -> ' | string trim -c "* " | string replace -r "^remotes/" ""
end end
function __fish_git_unique_remote_branches function __fish_git_unique_remote_branches
# Allow all remote branches with one remote without the remote part # Allow all remote branches with one remote without the remote part
# This is useful for `git checkout` to automatically create a remote-tracking branch # This is useful for `git checkout` to automatically create a remote-tracking branch
command git branch --no-color -a $argv ^/dev/null | string match -r -v ' -> ' | string trim -c "* " | string replace -r "^remotes/[^/]*/" "" | sort | uniq -u command git branch --no-color -a $argv ^/dev/null | string match -v '\* (*)' | string match -r -v ' -> ' | string trim -c "* " | string replace -r "^remotes/[^/]*/" "" | sort | uniq -u
end end
function __fish_git_tags function __fish_git_tags
@ -393,7 +404,7 @@ complete -c git -n '__fish_git_needs_command' -a commit -d 'Record changes to th
complete -c git -n '__fish_git_using_command commit' -l amend -d 'Amend the log message of the last commit' complete -c git -n '__fish_git_using_command commit' -l amend -d 'Amend the log message of the last commit'
complete -f -c git -n '__fish_git_using_command commit' -a '(__fish_git_modified_files)' complete -f -c git -n '__fish_git_using_command commit' -a '(__fish_git_modified_files)'
complete -f -c git -n '__fish_git_using_command commit' -l fixup -d 'Fixup commit to be used with rebase --autosquash' complete -f -c git -n '__fish_git_using_command commit' -l fixup -d 'Fixup commit to be used with rebase --autosquash'
complete -f -c git -n '__fish_git_using_command commit; and __fish_contains_opt fixup' -a '(__fish_git_commits)' complete -f -c git -n '__fish_git_using_command commit; and __fish_contains_opt fixup' -a '(__fish_git_recent_commits)'
# TODO options # TODO options
### diff ### diff
@ -421,6 +432,7 @@ complete -f -c git -n '__fish_git_needs_command' -a init -d 'Create an empty git
### log ### log
complete -c git -n '__fish_git_needs_command' -a log -d 'Show commit logs' complete -c git -n '__fish_git_needs_command' -a log -d 'Show commit logs'
complete -c git -n '__fish_git_using_command log' -a '(__fish_git_refs) (__fish_git_ranges)' -d 'Branch' complete -c git -n '__fish_git_using_command log' -a '(__fish_git_refs) (__fish_git_ranges)' -d 'Branch'
complete -c git -n '__fish_git_needs_command' -a shortlog -d 'Show commit shortlog'
# TODO options # TODO options
### merge ### merge

View file

@ -1,7 +1,10 @@
complete -c history -r -l prefix --description "Match history items that start with the given prefix" complete -c history -r -l prefix --description "Match items starting with prefix"
complete -c history -r -l contains --description "Match history items that contain the given string" complete -c history -r -l contains --description "Match items containing string"
complete -c history -l search --description "Print matching history items, which is the default behavior" complete -c history -l search -s s --description "Prints commands from history matching query"
complete -c history -l delete --description "Interactively delete matching history items" complete -c history -l delete -s d --description "Deletes commands from history matching query"
complete -c history -l clear --description "Clear your entire history" complete -c history -l clear --description "Clears history file"
complete -c history -l merge --description "Incorporate history changes from other sessions" complete -c history -l merge -s m --description "Incorporate history changes from other sessions"
complete -c history -l exact -s e --description "Match items in the history that are identicial"
complete -c history -l with-time -s t --description "Output with timestamps"
# --save is not completed; it is for internal use # --save is not completed; it is for internal use

778
share/completions/p4.fish Normal file
View file

@ -0,0 +1,778 @@
# Fish completions for Perforce (p4) SCM
# Based on the list of commands from
# https://www.perforce.com/perforce/r16.1/manuals/cmdref/
# Author: Boris Aranovich https://github.com/nomaed
#########################################################
### p4 command parsing
#########################################################
function __fish_print_p4_client_name -d "Use `p4 info` output to query for current client name"
set -l p4info (p4 info -s 2> /dev/null)
if string match -qr '^Client unknown' $p4info
return
end
string match -r '^Client name: .+' $p4info | string replace 'Client name: ' ''
end
#########################################################
function __fish_print_p4_user_name -d "Use `p4 info` output to query for current client name"
string match -r '^User name: .+' (p4 info 2> /dev/null) | string replace 'User name: ' ''
end
#########################################################
function __fish_print_p4_changelists -d "Reformat output from `p4 changes` to simple format. Specify 'detailed!' as first argument to use username@workspace prefix"
set -l detailed
if test -n "$argv"
and test $argv[1] = "detailed!"
set detailed true
set -e argv[1]
end
# The format of `p4 changes -L` is as follows, for each changelist:
# Change 1234 on YYYY/MM/DD by user@workspace *status*\n
# \n
# \t Description text line\n
# \t Description text another line\n
# \n
set -l changes (p4 changes -L $argv)
set -l result
for line in (string trim -- $changes)
if test -z "$line"
continue
end
# see output format ^^^
set -l change_match (string match -ar '^Change ([0-9]+) on [0-9/]+ by (\S+).*$' $line)
if test -n "$change_match"
if test -n "$result"
echo $result
set result
end
set result $change_match[2]\t
if test -n "$detailed"
set result $result $change_match[3]:
end
else
set result $result $line
end
end
if test -n "$result"
echo $result
end
end
#########################################################
function __fish_print_p4_opened_files -d "Use `p4 diff` to output the names of all opened files"
# p4 opened -s | sed 's/#.*//' | p4 -x - where | awk '/^\// {print $3}'
# p4 opened -s | string replace -ar '(^\S+).*$' '$1' | p4 -x - where | string replace -ar '\S+\s\S+\s(\S+)' '$1'
string replace -a "$PWD/" '' (p4 diff -sa -sb -sr)
end
#########################################################
function __fish_print_p4_branches -d "Prints the list of all defined branches on the server"
set -l branches (p4 branches)
for branch in $branches
# "Branch branch-name YYYY/MM/DD 'description text'"
set -l matches (string match -ar '^Branch\s+(\S+)[^\']+\'(.+)\'$' $branch)
if not set -q matches[2]
# skip $branch if no match for branch name with description
continue
end
# matches[2] = branch name; matches[3] = description
echo -n $matches[2]
if not set -q matches[3]
echo -n \t$matches[3]
end
echo
end
end
#########################################################
function __fish_print_p4_streams
# I do not have an example of p4 streams output
#p4 streams 2> /dev/null
end
#########################################################
function __fish_print_p4_users -d "Lists perforce users suitable for list of completions"
# `p4 users` output format:
# "username <email@address> (Full Name) accessed YYYY/MM/DD"
# function will output it as:
# username[TAB]Full Name <email@address>
string replace -ar '(^\S+) <([^>]+)> \(([^\)]+)\).*$' '$1'\t'$3 <$2>' (p4 users)
end
#########################################################
function __fish_print_p4_workspaces -d "Lists current user's workspaces"
set -l user (__fish_print_p4_user_name)
if test -z "$user"
return
end
# "Client clientname YYYY/MM/DD root /home/user/workspace/path 'description text'"
string replace -ar '^Client (\S+) \S+ root (\S+) \'(.+)\'$' '$1'\t'$3' (p4 clients -u $user)
end
#########################################################
function __fish_print_p4_workspace_changelists -d "Lists all changelists for current user"
set -l client (__fish_print_p4_client_name)
if test -n "$client"
__fish_print_p4_changelists -c $client $argv
end
end
#########################################################
function __fish_print_p4_pending_changelists -d "Lists all *pending* changelists. If 'default' argument is provided, default changelist will also be listed"
if set -q argv[1]
and test $argv[1] = "default"
echo default\tDefault changelist
end
__fish_print_p4_workspace_changelists -s pending
end
#########################################################
function __fish_print_p4_shelved_changelists -d "Lists all changelists with *shelved* files"
__fish_print_p4_workspace_changelists -s shelved
end
#########################################################
### completion helpers
#########################################################
function __fish_print_p4_commands_list -d "Lists p4 commands"
set -l commands add annotate attribute branch branches change changes changelist changelists clean client clients copy counter counters cstat delete depot depots describe diff diff2 dirs edit filelog files fix fixes flush fstat grep group groups have help info integ integrate integrated interchanges istat job jobs key keys label labels labelsync list lock logger login logout merge move opened passwd populate print protect protects prune rec reconcile rename reopen resolve resolved revert review reviews set shelve status sizes stream streams submit sync tag tickets unlock unshelve update user users where workspace workspaces
for i in $commands
echo $i
end
end
#########################################################
function __fish_print_p4_env_vars -d "Lists environment variables that can be consumed by perforce"
set -l env_vars P4CLIENT P4PORT P4PASSWD P4USER P4CONFIG P4DIFF P4EDITOR P4MERGE P4CHARSET P4TRUST P4PAGER PWD TMP TEMP P4TICKETS P4LANGUAGE P4LOGINSSO P4COMMANDCHARSET P4DIFFUNICODE P4MERGEUNICODE P4CLIENTPATH P4AUDIT P4JOURNAL P4LOG P4PORT P4ROOT P4DEBUG P4NAME P4SSLDIR
for var in $env_vars
echo $var
end
end
#########################################################
function __fish_print_p4_file_types -d "Lists all of available file modes"
set -l base_types text binary symlink apple resource unicode utf16
for type in $base_types
printf '%s\t%s\n' $type+m 'always set modtime' $type+w 'always writeable' $type+x 'exec bit set' $type+k '$Keyword$ expansion of Id, Header, Author, Date, DateUTC, DateTime, DateTimeUTC, DateTimeTZ, Change, File, Revision' $type+ko '$Keyword$ expansion of Id, Header only' $type+l 'exclusive open: disallow multiple opens' $type+C 'server stores compressed file per revision' $type+D 'server stores deltas in RCS format' $type+F 'server stores full file per revision' $type+S 'server stores only single head rev., or specify number to <n> of revisions' $type+X 'server runs archive trigger to access files'
end
end
#########################################################
function __fish_print_p4_help_keywords -d "Keywords for `p4 help`"
echo administration\t"Help on specialized administration topics"
echo charset\t"Describes how to control Unicode translation"
echo commands\t"Lists all the Perforce commands"
echo configurables\t"Describes all of the server configuration variables"
echo dvcs\t"Describes decentralized version control with Perforce"
echo environment\t"Lists the Perforce environment variables and their meanings"
echo filetypes\t"Lists the Perforce filetypes and their meanings"
echo jobview\t"Describes Perforce jobviews"
echo legal\t"Legal and license information"
echo networkaddress\t"Help on network address syntax"
echo replication\t"Describes specialized replication topics"
echo revisions\t"Describes Perforce revision specifiers"
echo simple\t"Provides short descriptions of the eight most basic Perforce commands"
echo usage\t"Lists the six options available with all Perforce commands"
echo views\t"Describes the meaning of Perforce views"
end
#########################################################
function __fish_print_p4_diff_options -d "Options for `p4 diff -d`"
echo n\t"RCS output format, showing additions and deletions made to the file and associated line ranges"
echo c\t"context output format, showing line number ranges and N lines of context around the changes" #
echo s\t"summary output format, showing only the number of chunks and lines added, deleted, or changed"
echo u\t"unified output format, showing added and deleted lines with N lines of context, in a form compatible with the patch(1) utility" #
echo l\t"ignore line-ending (CR/LF) convention when finding diffs"
echo b\t"ignore changes made within whitespace; this option implies -dl"
echo w\t"ignore whitespace altogether; this option implies -dl"
end
#########################################################
function __fish_print_p4_resolve_options -d "Options for `p4 merge` using -a, -A and -d"
switch "$argv[1]"
case a
echo m\t"Automatic: accept the Perforce-recommended file revision (yours, their, merge)"
echo y\t"Accept Yours, ignore theirs"
echo t\t"Accept Theirs"
echo s\t"Safe Accept: merge if no conflict, ignore file otherwise"
echo f\t"Force Accept: conflicted changes will leave conflict markers in the file"
case A
echo b\t"Resolve attributes set by p4 attribute"
echo b\t"Resolve file branching; that is, integrations where the source is edited and the target is deleted"
echo c\t"Resolve file content changes"
echo d\t"Integrations where the source is deleted and target is deleted"
echo t\t"Filetype changes"
echo m\t"Move and renames"
case d
echo b\t"Ignore whitespace-only changes (for instance, a tab replaced by eight spaces)"
echo w\t"Ignore whitespace altogether (for instance, deletion of tabs or other whitespace)"
echo l\t"Ignore differences in line-ending convention"
end
end
#########################################################
function __fish_print_p4_parallel_options -d "Values for --parallel option in various commands"
set -l mode
if test -n "$argv"
set mode $argv[1]
end
# for now only looks that mode is set, later it will need to have a specific setting
echo 'threads='\t"sends files concurrently using N independent network connections"
echo 'batch='\t"specifies the number of files in a batch"
test "$mode"
or echo 'batchsize='\t"specifies the number of bytes in a batch"
echo 'min='\t"specifies the minimum number of files in a parallel sync"
test "$mode"
or echo 'minsize='\t"specifies the minimum number of bytes in a parallel sync"
end
#########################################################
function __fish_print_p4_submit_options -d "Options for `p4 submit`"
echo 'submitunchanged'\t"Submit all open files (default behavior)"
echo 'submitunchanged+reopen'\t"Submit all open files + reopen to default changelist"
echo 'revertunchanged'\t"Revert unmodified files, submit all the rest"
echo 'revertunchanged+reopen'\t"Revert unmodified files, submit all the rest + reopen them in default changelist"
echo 'leaveunchanged'\t"Move unchanged files to default changelist, submit all the rest"
echo 'leaveunchanged+reopen'\t"Submit only modified files + reopen all (modified and unmodified) in default changelist"
end
#########################################################
function __fish_print_p4_noretransfer_options -d "Options for `p4 submit --noretransfer`"
echo 1\t"server avoids re-transferring files that have already been archived after a failed submit operation"
echo 0\t"server re-transfers all files after a failed submit operation"
end
#########################################################
function __fish_print_p4_integrate_output_options -d "Options for `p4 resolve -O`"
echo b\t"outputs the base revision for the merge (if any)"
echo r\t"outputs the resolves that are being scheduled"
end
#########################################################
function __fish_print_p4_integrate_resolve_options -d "Options for `p4 resolve -R`"
echo b\t"schedules a branch resolve instead of branching the target files automatically"
echo d\t"schedules a delete resolve instead of deleting the target files automatically"
echo s\t"skips cherry-picked revisions that have already been integrated"
end
#########################################################
function __fish_p4_not_in_command -d "Checks that prompt is not inside of p4 command"
for i in (commandline -opc)
if contains -- $i (__fish_print_p4_commands_list)
return 1
end
end
return 0
end
#########################################################
# Perforce command is a single word that comes either as first argument
# or directly after global options.
# To test whether we're in command, it's enough that a command will appear
# in the arguments, even though if more than a single command is specified,
# p4 will complain.
function __fish_p4_is_using_command -d "Checks if prompt is in a specific command"
if contains -- $argv[1] (commandline -opc)
return 0
end
return 1
end
#########################################################
function __fish_p4_register_command -d "Adds a completion for a specific command"
complete -c p4 -n "__fish_p4_not_in_command" -a $argv[1] $argv[2..-1]
end
#########################################################
function __fish_p4_register_command_option -d "Adds a specific option for a command"
complete -c p4 -n "__fish_p4_is_using_command $argv[1]" $argv[2..-1]
end
#########################################################
### global options -- can be used before any command
#########################################################
complete -c p4 -n __fish_p4_not_in_command -s b -x -d 'Specifies a batch size (number of arguments) to use when processing a command from a file with the -x argfile option'
complete -c p4 -n __fish_p4_not_in_command -s c -x -d 'Overrides any P4CLIENT setting with the specified client name'
complete -c p4 -n __fish_p4_not_in_command -s d -r -d 'Overrides any PWD setting (current working directory) and replaces it with the specified directory'
complete -c p4 -n __fish_p4_not_in_command -s I -d 'Specify that progress indicators, if available, are desired. This option is not compatible with the -s and -G options'
complete -c p4 -n __fish_p4_not_in_command -s G -d 'Causes all output (and batch input for form commands with -i) to be formatted as marshalled Python dictionary objects'
complete -c p4 -n __fish_p4_not_in_command -s H -x -a '(__fish_print_hostnames)' -d 'Overrides any P4HOST setting and replaces it with the specified hostname'
complete -c p4 -n __fish_p4_not_in_command -s p -x -d 'Overrides any P4PORT setting with the specified protocol:host:port'
complete -c p4 -n __fish_p4_not_in_command -s P -x -d 'Overrides any P4PASSWD setting with the specified password.'
complete -c p4 -n __fish_p4_not_in_command -s r -x -d 'Specifies the number of times to retry a command (notably, p4 sync) if the network times out.'
complete -c p4 -n __fish_p4_not_in_command -s s -d 'Prepends a descriptive field (for example, text:, info:, error:, exit:) to each line of output produced by a Perforce command. This is most often used when scripting.'
complete -c p4 -n __fish_p4_not_in_command -s u -x -a '(__fish_print_p4_users)' -d 'Overrides any P4USER, USER, or USERNAME setting with the specified user name.'
complete -c p4 -n __fish_p4_not_in_command -s x -r -d 'Instructs Perforce to read arguments, one per line, from the specified file. If file is a single hyphen (-), then standard input is read.'
complete -c p4 -n __fish_p4_not_in_command -s C -x -a '(__fish_print_encodings)' -d 'Overrides any P4CHARSET setting with the specified character set.'
complete -c p4 -n __fish_p4_not_in_command -s Q -x -a '(__fish_print_encodings)' -d 'Overrides any P4COMMANDCHARSET setting with the specified character set.'
complete -c p4 -n __fish_p4_not_in_command -s L -x -d 'This feature is reserved for system integrators.'
complete -c p4 -n __fish_p4_not_in_command -s z -x -d 'Causes output of many reporting commands to be in the same tagged format as that generated by p4 fstat.'
complete -c p4 -n __fish_p4_not_in_command -s q -d 'Quiet mode; suppress all informational message and report only warnings or errors.'
complete -c p4 -n __fish_p4_not_in_command -s V -d 'Displays the version of the p4 application and exits.'
complete -c p4 -n __fish_p4_not_in_command -s h -d 'Displays basic usage information and exits.'
#########################################################
### sub-commands
#########################################################
__fish_p4_register_command add -d "Open a new file to add it to the depot"
__fish_p4_register_command annotate -d "Print file lines along with their revisions"
__fish_p4_register_command attribute -f -d "Set per-revision attributes on revisions"
__fish_p4_register_command branch -f -d "Create or edit a branch specification"
__fish_p4_register_command branches -f -d "Display list of branches"
__fish_p4_register_command change -f -d "Create or edit a changelist description"
__fish_p4_register_command changes -f -d "Display list of pending and submitted changelists"
__fish_p4_register_command changelist -f -d "Create or edit a changelist description"
__fish_p4_register_command changelists -f -d "Display list of pending and submitted changelists"
__fish_p4_register_command clean -d "Delete or refresh local files to match depot state"
__fish_p4_register_command client -f -d "Create or edit a client specification and its view"
__fish_p4_register_command clients -f -d "Display list of known clients"
__fish_p4_register_command copy -d "Schedule copy of latest rev from one file to another"
__fish_p4_register_command counter -f -d "Display, set, or delete a counter"
__fish_p4_register_command counters -f -d "Display list of known counters"
__fish_p4_register_command cstat -f -d "Dump change/sync status for current client"
__fish_p4_register_command delete -d "Open an existing file to delete it from the depot"
__fish_p4_register_command depot -f -d "Create or edit a depot specification"
__fish_p4_register_command depots -f -d "Display list of depots"
__fish_p4_register_command describe -x -d "Display a changelist description"
__fish_p4_register_command diff -d "Display diff of client file with depot file"
__fish_p4_register_command diff2 -d "Display diff of two depot files"
__fish_p4_register_command dirs -f -d "List subdirectories of a given depot directory"
__fish_p4_register_command edit -d "Open an existing file for edit"
__fish_p4_register_command filelog -d "List revision history of files"
__fish_p4_register_command files -d "List files in the depot"
__fish_p4_register_command fix -f -d "Mark jobs as being fixed by named changelists"
__fish_p4_register_command fixes -f -d "List what changelists fix what job"
__fish_p4_register_command flush -d "Fake a 'p4 sync' by not moving files"
__fish_p4_register_command fstat -d "Dump file info"
__fish_p4_register_command grep -d "Print lines from text files matching a pattern"
__fish_p4_register_command group -f -d "Change members of a user group"
__fish_p4_register_command groups -f -d "List groups (of users)"
__fish_p4_register_command have -f -d "List revisions last synced"
__fish_p4_register_command help -f -d "Print the requested help message"
__fish_p4_register_command info -f -d "Print out client/server information"
__fish_p4_register_command integ -d "Schedule integration from one file to another"
__fish_p4_register_command integrate -d "Schedule integration from one file to another"
__fish_p4_register_command integrated -f -d "Show integrations that have been submitted"
__fish_p4_register_command interchanges -f -d "Report changes that have not yet been integrated"
__fish_p4_register_command istat -f -d "Show integrations needed for a stream"
__fish_p4_register_command job -f -d "Create or edit a job (defect) specification"
__fish_p4_register_command jobs -f -d "Display list of jobs"
__fish_p4_register_command key -f -d "Display, set, or delete a key/value pair"
__fish_p4_register_command keys -f -d "Display list of known keys and their values"
__fish_p4_register_command label -f -d "Create or edit a label specification and its view"
__fish_p4_register_command labels -f -d "Display list of labels"
__fish_p4_register_command labelsync -f -d "Synchronize label with the current client contents"
__fish_p4_register_command list -d "Create an in-memory (label) list of depot files"
__fish_p4_register_command lock -d "Lock an opened file against changelist submission"
__fish_p4_register_command logger -f -d "Report what jobs and changelists have changed"
__fish_p4_register_command login -f -d "Login to Perforce by obtaining a session ticket"
__fish_p4_register_command logout -f -d "Logout of Perforce by removing or invalidating a ticket"
__fish_p4_register_command merge -d "Schedule merge (integration) from one file to another"
__fish_p4_register_command move -d "Moves files from one location to another"
__fish_p4_register_command opened -d "Display list of files opened for pending changelist"
__fish_p4_register_command passwd -f -d "Set the user's password on the server (and Windows client)"
__fish_p4_register_command populate -d "Populate a branch or stream with files"
__fish_p4_register_command print -d "Retrieve a depot file to the standard output"
__fish_p4_register_command protect -f -d "Modify protections in the server namespace"
__fish_p4_register_command protects -f -d "Display protections in place for a given user/path"
__fish_p4_register_command prune -d "Remove unmodified branched files from a stream"
__fish_p4_register_command rec -f -d "Reconcile client to offline workspace changes"
__fish_p4_register_command reconcile -f -d "Reconcile client to offline workspace changes"
__fish_p4_register_command rename -d "Moves files from one location to another"
__fish_p4_register_command reopen -d "Change the type or changelist number of an opened file"
__fish_p4_register_command resolve -d "Merge open files with other revisions or files"
__fish_p4_register_command resolved -d "Show files that have been merged but not submitted"
__fish_p4_register_command revert -d "Discard changes from an opened file"
__fish_p4_register_command review -f -d "List and track changelists (for the review daemon)"
__fish_p4_register_command reviews -d "Show what users are subscribed to review files"
__fish_p4_register_command set -x -d "Set variables in the registry (Windows only)"
__fish_p4_register_command shelve -x -d "Store files from a pending changelist into the depot"
__fish_p4_register_command status -f -d "Preview reconcile of client to offline workspace changes"
__fish_p4_register_command sizes -d "Display size information for files in the depot"
__fish_p4_register_command stream -f -d "Create or edit a stream specification"
__fish_p4_register_command streams -f -d "Display list of streams"
__fish_p4_register_command submit -d "Submit open files to the depot"
__fish_p4_register_command sync -f -d "Synchronize the client with its view of the depot"
__fish_p4_register_command tag -d "Tag files with a label"
__fish_p4_register_command tickets -f -d "Display list of session tickets for this user"
__fish_p4_register_command unlock -d "Release a locked file but leave it open"
__fish_p4_register_command unshelve -d "Restore shelved files from a pending changelist"
__fish_p4_register_command update -f -d "Update the client with its view of the depot"
__fish_p4_register_command user -f -d "Create or edit a user specification"
__fish_p4_register_command users -f -d "Display list of known users"
__fish_p4_register_command where -d "Show how file names map through the client view"
__fish_p4_register_command workspace -f -d "Create or edit a client specification and its view"
__fish_p4_register_command workspaces -f -d "Display list of known clients"
#########################################################
### sub-command options
#########################################################
#-----------------------------------------------------
#--> Help
#-----------------------------------------------------
# help
__fish_p4_register_command_option help -f -a '(__fish_print_p4_help_keywords)'
# info
__fish_p4_register_command_option info -s s -d "Short output (removes information that requires DB search)"
#-----------------------------------------------------
#--> Client workspace
#-----------------------------------------------------
# clean
__fish_p4_register_command_option clean -a '(__fish_print_p4_opened_files)'
__fish_p4_register_command_option clean -s a -d "Added files: Find files in the workspace that have no corresponding files in the depot and delete them"
__fish_p4_register_command_option clean -s d -d "Deleted files: Find those files in the depot that do not exist in your workspace and add them to the workspace"
__fish_p4_register_command_option clean -s e -d "Edited files: Find files in the workspace that have been modified and restore them to the last file version that has synced from the depot"
__fish_p4_register_command_option clean -s I -d "Do not perform any ignore checking; ignore any settings specified by P4IGNORE for added files"
__fish_p4_register_command_option clean -s l -d "Display output in local file syntax with relative paths, similar to the workspace-centric view of p4 status"
__fish_p4_register_command_option clean -s n -d "Preview the results of the operation without performing any action"
# client, workspace @TODO: -Fs (only in -f), -c (only in -S stream)
for a in 'client' 'workspace'
__fish_p4_register_command_option $a -x -a '(__fish_print_p4_workspaces)'
__fish_p4_register_command_option $a -s f -d "Allows the last modification date, which is normally read-only, to be set"
__fish_p4_register_command_option $a -s d -f -a '(__fish_print_p4_workspaces)' -d "Delete the specified client workspace whether or not the workspace is owned by the user"
# __fish_p4_register_command_option $a -a '-Fs' -d 'Deletes client with shelves (must follow -f)'
__fish_p4_register_command_option $a -s F -a 's' -d 'Deletes client with shelves (must follow -f)'
__fish_p4_register_command_option $a -s o -d "Write the client workspace spec to standard output"
__fish_p4_register_command_option $a -s i -d "Read the client workspace spec from standard input"
__fish_p4_register_command_option $a -s c -x -a '(__fish_print_p4_workspace_changelists)' -d "When used with -S stream, displays the workspace spec that would have been created for a stream at the moment the change was submitted"
__fish_p4_register_command_option $a -s s -d "Switch workspace view"
__fish_p4_register_command_option $a -s t -x -d "Specify a client workspace Template"
__fish_p4_register_command_option $a -l serverid -x -d "Forcefully delete workspace that is bound to another server"
__fish_p4_register_command_option $a -s S -x -a '(__fish_print_p4_streams)' -d "Associates the workspace with the specified stream"
end
# clients, workspaces @TODO -U and others are mutually exclusive
for a in 'clients' 'workspaces'
__fish_p4_register_command_option $a -s a -d "List all client workspaces, not just workspaces bound to this server"
__fish_p4_register_command_option $a -s e -x -d "List only client workspaces matching filter (case-sensitive)"
__fish_p4_register_command_option $a -s E -x -d "List only client workspaces matching filter (case-insensitive)"
__fish_p4_register_command_option $a -s m -x -d "List only the first max client workspaces"
__fish_p4_register_command_option $a -s s -x -d "List only client workspaces bound to the specified serverID. On an edge server, the -s option defaults to the edge servers serverID"
__fish_p4_register_command_option $a -s S -x -a '(__fish_print_p4_streams)' -d "List client workspaces associated with the specified stream"
__fish_p4_register_command_option $a -s t -d "Display the time as well as the date of the last update to the workspace"
__fish_p4_register_command_option $a -s u -x -a '(__fish_print_p4_users)' -d "List only client workspaces owned by user"
__fish_p4_register_command_option $a -s U -d "List only client workspaces unloaded with p4 unload"
end
# flush @TODO
# have @TODO
# ignores @TODO
# sync @TODO --parallel has unique key-value pair syntax: --parallel=optq1=n,opt2=n,opt3=n,opt4=n
__fish_p4_register_command_option sync -s f -d "Force sync, overwrite all unopened files"
__fish_p4_register_command_option sync -s k -d "Keep existing workspace files, alias for p4 flush"
__fish_p4_register_command_option sync -s L -d "perform the sync on a list of valid file arguments in full depot syntax with a valid revision number"
__fish_p4_register_command_option sync -s m -x -d "Sync only the first max files specified"
__fish_p4_register_command_option sync -s n -d "Preview mode: Display the results of the sync without actually syncing"
__fish_p4_register_command_option sync -s N -d "Preview mode: Display network traffic estimates, don't actually sync"
__fish_p4_register_command_option sync -s p -d "Populate a client workspace, but do not update the have list"
__fish_p4_register_command_option sync -l parallel -x -a '(__fish_print_p4_parallel_options)' -d "Specify options for parallel file transfer"
__fish_p4_register_command_option sync -s q -d "Quiet operation: suppress normal output messages"
__fish_p4_register_command_option sync -s r -d "Reopen files that are mapped to new locations in the depot, in the new location"
__fish_p4_register_command_option sync -s s -d "Safe sync: Compare the content in your client workspace against what was last synced"
# update @TODO
# where @TODO
#-----------------------------------------------------
#--> Files
#-----------------------------------------------------
# add
__fish_p4_register_command_option add -s c -x -a '(__fish_print_p4_pending_changelists default)' -d "Changelist number"
__fish_p4_register_command_option add -s d -d "Revert and re-add"
__fish_p4_register_command_option add -s f -d "Use wildcard characters for files"
__fish_p4_register_command_option add -s I -d "Do not use P4IGNORE"
__fish_p4_register_command_option add -s n -d "Preview operation, don't change files"
__fish_p4_register_command_option add -s t -x -a '(__fish_print_p4_file_types)' -d "File type"
# attribute @TODO
# copy @TODO
# delete @TODO
# diff @TODO
# diff2 @TODO
# dirs @TODO
# edit
__fish_p4_register_command_option edit -s c -x -a '(__fish_print_p4_pending_changelists default)' -d "Changelist number"
__fish_p4_register_command_option edit -s k -d "Keep existing workspace files; mark the file as open for edit even if the file is not in the client view"
__fish_p4_register_command_option edit -s n -d "Preview operation, don't change files"
__fish_p4_register_command_option edit -s t -x -a '(__fish_print_p4_file_types)' -d "File type"
# files @TODO
# fstat @TODO
# grep @TODO
# move @TODO
# lock @TODO
# print @TODO
# reconcile @TODO
# rename @TODO
# revert @TODO
# status @TODO
# sizes @TODO
# unlock @TODO
#-----------------------------------------------------
#--> Changelists
#-----------------------------------------------------
# change, changelist
for a in 'change' 'changelist'
__fish_p4_register_command_option $a -x -a '(__fish_print_p4_pending_changelists)'
__fish_p4_register_command_option $a -s s -d "Allows jobs to be assigned arbitrary status values on submission of the changelist, rather than the default status of closed"
__fish_p4_register_command_option $a -s f -d "Force operation (The -u and the -f options are mutually exclusive)"
__fish_p4_register_command_option $a -s u -d "Update a submitted changelist (The -u and the -f options are mutually exclusive)"
__fish_p4_register_command_option $a -s O -x -a '(__fish_print_p4_pending_changelists)' -d "Changelist number"
__fish_p4_register_command_option $a -s d -x -a '(__fish_print_p4_pending_changelists)' -d "Delete a changelist"
__fish_p4_register_command_option $a -s o -d "Writes the changelist spec to standard output"
__fish_p4_register_command_option $a -s i -d "Read the changelist spec from standard input"
__fish_p4_register_command_option $a -s t -x -a "restricted public" -d "Modifies the 'Type' of the change"
__fish_p4_register_command_option $a -s U -x -a '(__fish_print_p4_users)' -d "Changes the 'User' of the change"
end
# changes, changelists
for a in 'changes' 'changelists'
__fish_p4_register_command_option $a -s i -d "Include changelists that affected files that were integrated with the specified files"
__fish_p4_register_command_option $a -s t -d "Display the time as well as the date of each change"
__fish_p4_register_command_option $a -s l -d "List long output, with the full text of each changelist description"
__fish_p4_register_command_option $a -s L -d "List long output, with the full text of each changelist description truncated at 250 characters"
__fish_p4_register_command_option $a -s f -d "View restricted changes (requires admin permission)"
__fish_p4_register_command_option $a -c c -x -a '(__fish_print_p4_workspace_changelists)' -d "List only changes made from the named client workspace"
__fish_p4_register_command_option $a -c m -x -d "List only the highest numbered max changes"
__fish_p4_register_command_option $a -c s -x -a 'pending submitted shelved' -d "Limit the list to the changelists with the given status"
__fish_p4_register_command_option $a -c u -x -a '(__fish_print_p4_users)' -d "List only changes made from the named user"
end
# describe @TODO: -dc<n>, -du<n>
__fish_p4_register_command_option describe -x -a '(__fish_print_p4_workspace_changelists)'
__fish_p4_register_command_option describe -s f -d 'Force the display of descriptions for restricted changelists'
__fish_p4_register_command_option describe -s O -d 'Specify the original changelist number'
__fish_p4_register_command_option describe -s s -d 'Short output without diffs'
__fish_p4_register_command_option describe -s S -d 'Display shelved files with diffs'
__fish_p4_register_command_option describe -s d -x -a '(__fish_print_p4_diff_options)' -d 'Diff'
# filelog @TODO
# opened
__fish_p4_register_command_option opened -s a -d "List opened files in all client workspaces"
__fish_p4_register_command_option opened -s c -x -a '(__fish_print_p4_pending_changelists default)' -d "List the files in a pending changelist"
__fish_p4_register_command_option opened -s C -x -a '(__fish_print_p4_workspaces)' -d "List only files that are open in the specified client workspace"
__fish_p4_register_command_option opened -s m -x -d "List only the first max open files"
__fish_p4_register_command_option opened -s s -d "Short output; do not output the revision number or file type"
__fish_p4_register_command_option opened -s u -x -a '(__fish_print_p4_users)' -d "List only those files that were opened by user"
__fish_p4_register_command_option opened -s x -d "List all files that have the +l filetype over all servers"
# reopen
__fish_p4_register_command_option reopen -x -a '(__fish_print_p4_opened_files)' -d "Select opened files"
__fish_p4_register_command_option reopen -s c -x -a '(__fish_print_p4_pending_changelists default)' -d "Move files to changelist"
__fish_p4_register_command_option reopen -s t -x -a '(__fish_print_p4_file_types)' -d "Change file type"
# review @TODO
# shelve
__fish_p4_register_command_option shelve -a '(__fish_print_p4_opened_files)'
__fish_p4_register_command_option shelve -s a -x -a 'submitunchanged leaveunchanged' -d "Options: 'submitunchanged' shelves all files, 'leaveunchanged' shelves only changed files"
__fish_p4_register_command_option shelve -s c -x -a '(__fish_print_p4_pending_changelists)' -d "Changelist number"
__fish_p4_register_command_option shelve -s d -d 'Discard the shelved files'
__fish_p4_register_command_option shelve -s f -d 'Force overwrite of shelved files'
__fish_p4_register_command_option shelve -s i -d 'Read a changelist description from standard input'
__fish_p4_register_command_option shelve -s p -d "Promote a shelved change from an Edge server to a Commit server"
__fish_p4_register_command_option shelve -s r -d 'Replace all shelved files in the changelist with the files that are opened in your workspace'
# submit @TODO: parallel syntax
__fish_p4_register_command_option submit -a '(__fish_print_p4_opened_files)'
__fish_p4_register_command_option submit -s c -x -a '(__fish_print_p4_pending_changelists)' -d "Submit specific changelist"
__fish_p4_register_command_option submit -s d -x -d "Immediately submit the changelist with supplied description and bypass the interactive form"
__fish_p4_register_command_option submit -s e -x -a '(__fish_print_p4_shelved_changelists)' -d "Submit specific shelved changelist"
__fish_p4_register_command_option submit -s f -x -a '(__fish_print_p4_submit_options)' -d "Override the SubmitOptions setting in the p4 client form"
__fish_p4_register_command_option submit -s i -d "Read a changelist specification from standard input"
__fish_p4_register_command_option submit -l noretransfer -x -a '(__fish_print_p4_noretransfer_options)'
__fish_p4_register_command_option submit -l parallel -x -a '(__fish_print_p4_parallel_options "submit")' -d "Specify options for parallel file transfer"
__fish_p4_register_command_option submit -s r -d "Reopen files for edit in the default changelist after submission"
__fish_p4_register_command_option submit -s s -d "Allows jobs to be assigned arbitrary status values on submission of the changelist"
# unshelve @TODO: Streams
__fish_p4_register_command_option unshelve -s b -x -a '(__fish_print_p4_branches)' -d "Specifies a branch spec for unshelving from"
__fish_p4_register_command_option unshelve -s c -x -a '(__fish_print_p4_pending_changelists)' -d "Changelist number into which to unshelve"
__fish_p4_register_command_option unshelve -s f -d 'Force the overwriting of writable (but unopened) files'
__fish_p4_register_command_option unshelve -s n -d "Preview result of unshelve operation without restoring files to workspace"
__fish_p4_register_command_option unshelve -s P -x -a '(__fish_print_p4_streams)' -d "Unshelve to the specified parent stream"
__fish_p4_register_command_option unshelve -s s -x -a '(__fish_print_p4_shelved_changelists)' -d "Specify the source shelved pending changelist number"
__fish_p4_register_command_option unshelve -s S -x -a '(__fish_print_p4_streams)' -d "Specifies a stream spec for unshelving from"
#-----------------------------------------------------
#--> Jobs
#-----------------------------------------------------
# fix @TODO
# fixes @TODO
# job @TODO
# jobs @TODO
# jobspec @TODO
#-----------------------------------------------------
#--> Branching and Merging
#-----------------------------------------------------
# branch @TODO
# branches @TODO
# copy @TODO
# cstat @TODO
# integ, integrate @TODO -s fromFile is based on -b branchname, try resolving
for a in 'integ' 'integrate'
__fish_p4_register_command_option $a -s b -x -a '(__fish_print_p4_branches)' -d "Integrate the files using the sourceFile/targetFile mappings included in the branch view of branchname. If the toFiles argument is included, include only those target files in the branch view that match the pattern specified by toFiles"
__fish_p4_register_command_option $a -s n -d "Display the integrations this command would perform without actually performing them"
__fish_p4_register_command_option $a -s v -d "Open files for branching without copying toFiles into the client workspace"
__fish_p4_register_command_option $a -s c -x -a '(__fish_print_p4_pending_changelists)' -d "Open the toFiles for branch, integrate, or delete in the specified pending changelist"
__fish_p4_register_command_option $a -s q -d "Quiet mode"
__fish_p4_register_command_option $a -a '-Di' -d "f the source file has been deleted and re-added, revisions that precede the deletion will be considered to be part of the same source file"
__fish_p4_register_command_option $a -s f -d "Force the integration on all revisions of fromFile and toFile, even if some revisions have been integrated in the past"
__fish_p4_register_command_option $a -s h -d "Use the have revision"
__fish_p4_register_command_option $a -s O -x -a '(__fish_print_p4_integrate_output_options)' -d "Specify output options"
__fish_p4_register_command_option $a -s m -x -d "Limit the command to integrating only the first N files"
__fish_p4_register_command_option $a -s R -x -a '(__fish_print_p4_integrate_resolve_options)' -d "Specify resolve options"
__fish_p4_register_command_option $a -s s -r -d "Source file and revision"
__fish_p4_register_command_option $a -s r -r -d "Reverse the mappings in the branch view, integrating from the target files to the source files"
__fish_p4_register_command_option $a -s S -x -a '(__fish_print_p4_streams)' -d "Source stream"
__fish_p4_register_command_option $a -s P -x -a '(__fish_print_p4_streams)' -d "Custom parent stream"
end
# integrated @TODO
# interchanges @TODO
# istat @TODO
# label @TODO
# labels @TODO
# labelsync @TODO
# list @TODO
# merge @TODO
# populate @TODO
# tag @TODO
# resolve
__fish_p4_register_command_option resolve -s a -x -a '(__fish_print_p4_resolve_options a)' -d "Resolve automatically"
__fish_p4_register_command_option resolve -s A -x -a '(__fish_print_p4_resolve_options A)' -d "Constrain the type of resolve to branching, deletion, file type change, or move/rename"
__fish_p4_register_command_option resolve -s d -x -a '(__fish_print_p4_resolve_options d)' -d "Ignore specified differences in whitespace or line-ending convention"
__fish_p4_register_command_option resolve -s f -d "Allow already resolved, but not yet submitted, files to be resolved again"
__fish_p4_register_command_option resolve -s n -d "List the files that need resolving without actually performing the resolve"
__fish_p4_register_command_option resolve -s N -d "Preview the operation with additional information about any non-content resolve actions that are scheduled"
__fish_p4_register_command_option resolve -s o -d "Output the base file name and revision to be used during the resolve"
__fish_p4_register_command_option resolve -s t -d "Force a three-way merge, even on binary (non-text) files"
__fish_p4_register_command_option resolve -s v -d "Include conflict markers in the file for all changes between yours and base, and between theirs and base"
__fish_p4_register_command_option resolve -s c -x -a '(__fish_print_p4_workspace_changelists)' -d "Limit the scope of the resolve operation to the files opened in the specified changelist number"
# resolved @TODO
# stream @TODO
# streams @TODO
#-----------------------------------------------------
#--> Administration
#-----------------------------------------------------
# admin @TODO
# archive @TODO
# cachepurge @TODO
# configure @TODO
# counter @TODO
# counters @TODO
# dbschema @TODO
# dbstat @TODO
# depot @TODO
# depots @TODO
# diskspace @TODO
# journals @TODO
# key @TODO
# keys @TODO
# license @TODO
# lockstat @TODO
# logappend @TODO
# logger @TODO
# logparse @TODO
# logrotate @TODO
# logschema @TODO
# logstat @TODO
# logtail @TODO
# monitor @TODO
# obliterate @TODO
# ping @TODO
# property @TODO
# proxy @TODO
# pull @TODO
# reload @TODO
# renameuser @TODO
# replicate @TODO
# restore @TODO
# reviews @TODO
# server @TODO
# serverid @TODO
# servers @TODO
# triggers @TODO
# typemap @TODO
# unload @TODO
# verify @TODO
#-----------------------------------------------------
#--> Security
#-----------------------------------------------------
# group @TODO
# groups @TODO
# login @TODO
# logout @TODO
# passwd @TODO
# protect @TODO
# protects @TODO
# tickets @TODO
# trust @TODO
# user @TODO
# users @TODO
#-----------------------------------------------------
#--> Environment
#-----------------------------------------------------
# set
__fish_p4_register_command_option set -x -a '(__fish_print_p4_env_vars)'
__fish_p4_register_command_option set -s q -d "Reduce the output"
__fish_p4_register_command_option set -s s -d "Set the value of the registry variable for the local machine"
__fish_p4_register_command_option set -s S -x -d "Set the value of the registry variables as used by the service"

View file

@ -1,14 +1,61 @@
function __fish_complete_screen --description "Print a list of running screen sessions" function __fish_detect_screen_socket_dir --description "Detect which folder screen uses"
screen -list | __fish_sgrep \^\t.\*\(.\*\)|sed -e 's/\t\(.*\)\t(\(.*\))/\1'\t'Screen: \2/' set screen_bin screen
if not set -q __fish_screen_socket_dir
set -g __fish_screen_socket_dir (eval $screen_bin -ls __fish_i_don_t_think_this_will_be_matched | string match -r "(?<=No Sockets found in ).*(?=\.)")
end
end end
function __fish_complete_screen_general_list_mac --description "Get the socket list on mac"
pushd $__fish_screen_socket_dir > /dev/null
set -l sockets (ls)
if test (count $sockets) -ne 0
switch $argv
case "Detached"
stat -f "%Lp %SB %N" -t "%D %T" $sockets | string match -r '^6\d{2} .*$' | string replace -r '^6\d{2} (\S+ \S+) (\S+)' '$2\t$1 Detached'
case "Attached"
stat -f "%Lp %SB %N" -t "%D %T" $sockets | string match -r '^7\d{2} .*$' | string replace -r '^7\d{2} (\S+ \S+) (\S+)' '$2\t$1 Attached'
end
end
popd > /dev/null
end
function __fish_complete_screen_general_list --description "Get the socket list"
screen -list | string match -r '^\t.*\(.*\)\s*\('$argv'\)\s*$'| string replace -r '\t(.*)\s+\((.*)\)\s*\((.*)\)' '$1\t$2 $3'
end
function __fish_complete_screen_detached --description "Print a list of detached screen sessions"
switch (uname)
case Darwin
__fish_complete_screen_general_list_mac Detached
case '*'
__fish_complete_screen_general_list Detached
end
end
function __fish_complete_screen_attached --description "Print a list of attached screen sessions"
switch (uname)
case Darwin
__fish_complete_screen_general_list_mac Attached
case '*'
__fish_complete_screen_general_list Attached
end
end
function __fish_complete_screen --description "Print a list of running screen sessions"
string join \n (__fish_complete_screen_attached) (__fish_complete_screen_detached)
end
# detect socket directory for mac users
__fish_detect_screen_socket_dir
complete -c screen -x complete -c screen -x
complete -c screen -s a -d 'Include all capabilitys' complete -c screen -s a -d 'Include all capabilitys'
complete -c screen -s A -d 'Adapt window size' complete -c screen -s A -d 'Adapt window size'
complete -c screen -s c -r -d 'Specify init file' complete -c screen -s c -r -d 'Specify init file'
complete -c screen -s d -d 'Detach screen' -a '(__fish_complete_screen)' complete -c screen -s d -d 'Detach screen' -a '(__fish_complete_screen)' -x
complete -c screen -s D -d 'Detach screen' -a '(__fish_complete_screen)' complete -c screen -s D -d 'Detach screen' -a '(__fish_complete_screen)' -x
complete -c screen -s r -d 'Reattach session' -a '(__fish_complete_screen)' complete -c screen -s r -d 'Reattach session' -a '(__fish_complete_screen)' -x
complete -c screen -s R -d 'Reattach/create session' complete -c screen -s R -d 'Reattach/create session'
complete -c screen -o RR -d 'Reattach/create any session' complete -c screen -o RR -d 'Reattach/create any session'
complete -c screen -s e -x -d 'Escape character' complete -c screen -s e -x -d 'Escape character'
@ -32,6 +79,6 @@ complete -c screen -s t -x -d 'Session title'
complete -c screen -s U -d 'UTF-8 mode' complete -c screen -s U -d 'UTF-8 mode'
complete -c screen -s v -d 'Display version and exit' complete -c screen -s v -d 'Display version and exit'
complete -c screen -o wipe -d 'Wipe dead sessions' complete -c screen -o wipe -d 'Wipe dead sessions'
complete -c screen -s x -d 'Multi attach' complete -c screen -s x -d 'Multi attach' -a '(__fish_complete_screen_attached)' -x
complete -c screen -s X -r -d 'Send command' complete -c screen -s X -r -d 'Send command'

View file

@ -3,22 +3,23 @@
# -wn : Set the default window size to n # -wn : Set the default window size to n
# +command : same as -c command # +command : same as -c command
# Check if vi exists at all ( needed for vi --version )
# Check if vi is really vim if type -q vi
if vi --version > /dev/null ^ /dev/null # Check if vi is really vim
complete -c vi -w vim if vi --version > /dev/null ^ /dev/null
else complete -c vi -w vim
complete -c vi -s s --description 'Suppress all interactive user feedback' else
complete -c vi -s C --description 'Encrypt/decrypt text' complete -c vi -s s --description 'Suppress all interactive user feedback'
complete -c vi -s l --description 'Set up for editing LISP programs' complete -c vi -s C --description 'Encrypt/decrypt text'
complete -c vi -s L --description 'List saved file names after crash' complete -c vi -s l --description 'Set up for editing LISP programs'
complete -c vi -s R --description 'Read-only mode' complete -c vi -s L --description 'List saved file names after crash'
complete -c vi -s S --description 'Use linear search for tags if tag file not sorted' complete -c vi -s R --description 'Read-only mode'
complete -c vi -s v --description 'Start in display editing state' complete -c vi -s S --description 'Use linear search for tags if tag file not sorted'
complete -c vi -s V --description 'Verbose mode' complete -c vi -s v --description 'Start in display editing state'
complete -c vi -s x --description 'Encrypt/decrypt text' complete -c vi -s V --description 'Verbose mode'
complete -c vi -r -s r --description 'Recover file after crash' complete -c vi -s x --description 'Encrypt/decrypt text'
complete -c vi -r -s t --description 'Edit the file containing a tag' complete -c vi -r -s r --description 'Recover file after crash'
complete -c vi -r -c t --description 'Begin editing by executing the specified editor command' complete -c vi -r -s t --description 'Edit the file containing a tag'
complete -c vi -r -c t --description 'Begin editing by executing the specified editor command'
end
end end

View file

@ -1,4 +1,3 @@
#
# Main file for fish command completions. This file contains various # Main file for fish command completions. This file contains various
# common helper functions for the command completions. All actual # common helper functions for the command completions. All actual
# completions are located in the completions subdirectory. # completions are located in the completions subdirectory.
@ -7,7 +6,6 @@
# #
# Set default field separators # Set default field separators
# #
set -g IFS \n\ \t set -g IFS \n\ \t
# #
@ -18,8 +16,7 @@ function __fish_default_command_not_found_handler
end end
if status --is-interactive if status --is-interactive
# The user has seemingly explicitly launched an old fish with # The user has seemingly explicitly launched an old fish with too-new scripts installed.
# too-new scripts installed.
if not contains "string" (builtin -n) if not contains "string" (builtin -n)
set -g __is_launched_without_string 1 set -g __is_launched_without_string 1
# XXX nostring - fix old fish binaries with no `string' builtin. # XXX nostring - fix old fish binaries with no `string' builtin.
@ -37,7 +34,10 @@ if status --is-interactive
# Remove this code when we've made it safer to upgrade fish. # Remove this code when we've made it safer to upgrade fish.
else else
# Enable truecolor/24-bit support for select terminals # Enable truecolor/24-bit support for select terminals
if not set -q NVIM_LISTEN_ADDRESS # (Neovim will swallow the 24bit sequences, rendering text white) # Ignore Neovim (in 0.1.4 at least), Screen and emacs' ansi-term as they swallow the sequences, rendering the text white.
if not set -q NVIM_LISTEN_ADDRESS
and not set -q STY
and not string match -q -- 'eterm*' $TERM
and begin and begin
set -q KONSOLE_PROFILE_NAME # KDE's konsole set -q KONSOLE_PROFILE_NAME # KDE's konsole
or string match -q -- "*:*" $ITERM_SESSION_ID # Supporting versions of iTerm2 will include a colon here or string match -q -- "*:*" $ITERM_SESSION_ID # Supporting versions of iTerm2 will include a colon here
@ -195,6 +195,11 @@ function . --description 'Evaluate contents of file (deprecated, see "source")'
end end
end end
# Set the locale if it isn't explicitly set. Allowing the lack of locale env vars to imply the
# C/POSIX locale causes too many problems. Do this before reading the snippets because they might be
# in UTF-8 (with non-ASCII characters).
__fish_set_locale
# As last part of initialization, source the conf directories # As last part of initialization, source the conf directories
# Implement precedence (User > Admin > Extra (e.g. vendors) > Fish) by basically doing "basename" # Implement precedence (User > Admin > Extra (e.g. vendors) > Fish) by basically doing "basename"
set -l sourcelist set -l sourcelist
@ -225,15 +230,6 @@ end
if status --is-login if status --is-login
# Check for i18n information in
# /etc/sysconfig/i18n
if test -f /etc/sysconfig/i18n
string match -r '^[a-zA-Z]*=.*' < /etc/sysconfig/i18n | while read -l line
set -gx (string split '=' -m 1 -- $line | string replace -ra '"([^"]+)"' '$1' | string replace -ra "'([^']+)'" '$1')
end
end
# #
# Put linux consoles in unicode mode. # Put linux consoles in unicode mode.
# #

View file

@ -1,16 +1,13 @@
# #
# Alias for gettext (or a fallback if gettext isn't installed) # Alias for gettext or a fallback if gettext isn't installed.
# #
if command -s gettext >/dev/null
set -l path (which gettext ^/dev/null) function _ --description "Alias for the gettext command"
if test -x (echo $path) command gettext fish $argv
function _ --description "Alias for the gettext command" end
gettext fish $argv
end
else else
function _ --description "Alias for the gettext command" function _ --description "Fallback alias for the gettext command"
echo -n $argv echo -n $argv
end end
end end

View file

@ -9,7 +9,11 @@ function __fish_cancel_commandline
# #
# Set reverse fg/bg color mode, output ^C, restore normal mode, clear to EOL (to erase any # Set reverse fg/bg color mode, output ^C, restore normal mode, clear to EOL (to erase any
# autosuggestion). # autosuggestion).
echo -n (tput smso)"^C"(tput rmso)(tput el) if command -v tput >/dev/null
echo -ns (tput smso; or tput so) "^C" (tput rmso; or tput se) (tput el; or tput ce)
else
echo -n "^C"
end
for i in (seq (commandline -L)) for i in (seq (commandline -L))
echo "" echo ""
end end

View file

@ -111,15 +111,13 @@ function __fish_config_interactive -d "Initializations that should be performed
# fish_greeting can be a function (preferred) or a variable. # fish_greeting can be a function (preferred) or a variable.
# #
if status --is-interactive if status --is-interactive
if status --is-login if functions -q fish_greeting
if functions -q fish_greeting fish_greeting
fish_greeting else
else # The greeting used to be skipped when fish_greeting was empty (not just undefined)
# The greeting used to be skipped when fish_greeting was empty (not just undefined) # Keep it that way to not print superfluous newlines on old configuration
# Keep it that way to not print superfluous newlines on old configuration test -n "$fish_greeting"
test -n "$fish_greeting" and echo $fish_greeting
and echo $fish_greeting
end
end end
end end
@ -176,11 +174,18 @@ function __fish_config_interactive -d "Initializations that should be performed
if set -q __fish_active_key_bindings if set -q __fish_active_key_bindings
echo "Keeping $__fish_active_key_bindings" >&2 echo "Keeping $__fish_active_key_bindings" >&2
return 1 return 1
else else if functions -q fish_default_key_bindings
echo "Reverting to default bindings" >&2 echo "Reverting to default bindings" >&2
set fish_key_bindings fish_default_key_bindings set fish_key_bindings fish_default_key_bindings
# Return because we are called again # Return because we are called again
return 0 return 0
else
# If we can't even find the default bindings, something is broken.
# Without it, we would eventually run into the stack size limit, but that'd print hundreds of duplicate lines
# so we should give up earlier.
echo "Cannot find fish_default_key_bindings, falling back to very simple bindings." >&2
echo "Most likely something is wrong with your installation." >&2
return 0
end end
end end
set -g __fish_active_key_bindings "$fish_key_bindings" set -g __fish_active_key_bindings "$fish_key_bindings"

View file

@ -475,14 +475,16 @@ function __fish_git_prompt_informative_status
set -l changedFiles (command git diff --name-status | cut -c 1-2) set -l changedFiles (command git diff --name-status | cut -c 1-2)
set -l stagedFiles (command git diff --staged --name-status | cut -c 1-2) set -l stagedFiles (command git diff --staged --name-status | cut -c 1-2)
set -l dirtystate (math (count $changedFiles) - (count (echo $changedFiles | grep "U"))) set -l dirtystate (math (count $changedFiles) - (count (echo $changedFiles | grep "U")) ^/dev/null)
set -l invalidstate (count (echo $stagedFiles | grep "U")) set -l invalidstate (count (echo $stagedFiles | grep "U"))
set -l stagedstate (math (count $stagedFiles) - $invalidstate) set -l stagedstate (math (count $stagedFiles) - $invalidstate ^/dev/null)
set -l untrackedfiles (count (command git ls-files --others --exclude-standard)) set -l untrackedfiles (command git ls-files --others --exclude-standard | wc -l | string trim)
set -l info set -l info
if [ (math $dirtystate + $invalidstate + $stagedstate + $untrackedfiles) = 0 ] # If `math` fails for some reason, assume the state is clean - it's the simpler path
set -l state (math $dirtystate + $invalidstate + $stagedstate + $untrackedfiles ^/dev/null)
if test -z "$state"; or test "$state" = 0
set info $___fish_git_prompt_color_cleanstate$___fish_git_prompt_char_cleanstate$___fish_git_prompt_color_cleanstate_done set info $___fish_git_prompt_color_cleanstate$___fish_git_prompt_char_cleanstate$___fish_git_prompt_color_cleanstate_done
else else
for i in $___fish_git_prompt_status_order for i in $___fish_git_prompt_status_order

View file

@ -0,0 +1,78 @@
# Try to set the locale from the system configuration if we did not inherit any. One case where this
# can happen is a linux with systemd where the user logs in via getty (e.g., on the system console).
# See https://github.com/fish-shell/fish-shell/issues/3092. This isn't actually our job, so there's
# a bunch of edge-cases we are unlikely to handle properly. If we get a value for _any_ language
# variable, we assume we've inherited something sensible so we skip this to allow the user to set it
# at runtime without mucking with config files.
#
# NOTE: This breaks the expectation that an empty LANG will be the same as LANG=POSIX, but an empty
# LANG seems more likely to be caused by a missing or misconfigured locale configuration.
function __fish_set_locale
set -l LOCALE_VARS
set LOCALE_VARS $LOCALE_VARS LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE
set LOCALE_VARS $LOCALE_VARS LC_MONETARY LC_MESSAGES LC_PAPER LC_NAME LC_ADDRESS
set LOCALE_VARS $LOCALE_VARS LC_TELEPHONE LC_MEASUREMENT LC_IDENTIFICATION
# We check LC_ALL to figure out if we have a locale but we don't set it later. That is because
# locale.conf doesn't allow it so we should not set it.
if string length -q -- $$LOCALE_VARS $LC_ALL
return 0
end
# Unset all variables - they are empty anyway and this makes merging easier.
for locale_var in $LOCALE_VARS
set -e $locale_var
end
# Try to extract the locale from the kernel boot commandline. The splitting here is a bit weird,
# but we operate under the assumption that the locale can't include whitespace. Other whitespace
# shouldn't concern us, but a quoted "locale.LANG=SOMETHING" as a value to something else might.
# Here the last definition of a variable takes precedence.
if test -r /proc/cmdline
for var in (string match -ra 'locale.[^=]+=\S+' < /proc/cmdline)
set -l kv (string replace 'locale.' '' -- $var | string split '=')
# Only set locale variables, not other stuff contained in these files - this also
# automatically ignores comments.
if contains -- $kv[1] $LOCALE_VARS
and set -q kv[2]
set -gx $kv[1] (string trim -c '\'"' -- $kv[2])
end
end
end
# Now read the config files we know are used by various OS distros.
#
# /etc/sysconfig/i18n is for old Red Hat derivatives (and possibly of no use anymore).
#
# /etc/env.d/02locale is from OpenRC.
#
# The rest are systemd inventions but also used elsewhere (e.g. Void Linux). systemd's
# documentation is a bit unclear on this. We merge all the config files (and the commandline),
# which seems to be what systemd itself does. (I.e. the value for a variable will be taken from
# the highest-precedence source) We read the systemd files first since they are a newer
# invention and therefore the rest are likely to be accumulated cruft.
#
# NOTE: Slackware puts the locale in /etc/profile.d/lang.sh, which we can't use because it's a
# full POSIX-shell script.
set -l user_cfg_dir (set -q XDG_CONFIG_HOME; and echo $XDG_CONFIG_HOME; or echo ~/.config)
for f in $user_cfg_dir/locale.conf /etc/locale.conf /etc/env.d/02locale /etc/sysconfig/i18n
if test -r $f
while read -l kv
set kv (string split '=' -- $kv)
if contains -- $kv[1] $LOCALE_VARS
and set -q kv[2]
# Do not set already set variables again - this makes the merging happen.
if not set -q $kv[1]
set -gx $kv[1] (string trim -c '\'"' -- $kv[2])
end
end
end <$f
end
end
# If we really cannot get anything, at least set character encoding to UTF-8.
if not string length -q -- $$LOCALE_VARS $LC_ALL
set -gx LC_CTYPE en_US.UTF-8
end
end

View file

@ -0,0 +1,91 @@
function __fish_shared_key_bindings -d "Bindings shared between emacs and vi mode"
# These are some bindings that are supposed to be shared between vi mode and default mode.
# They are supposed to be unrelated to text-editing (or movement).
# This takes $argv so the vi-bindings can pass the mode they are valid in.
bind $argv \cy yank
bind $argv \ey yank-pop
# Left/Right arrow
bind $argv -k right forward-char
bind $argv -k left backward-char
bind $argv \e\[C forward-char
bind $argv \e\[D backward-char
# Some terminals output these when they're in in keypad mode.
bind $argv \eOC forward-char
bind $argv \eOD backward-char
# Interaction with the system clipboard.
bind $argv \cx fish_clipboard_copy
bind $argv \cv fish_clipboard_paste
bind $argv \e cancel
bind $argv \t complete
# shift-tab does a tab complete followed by a search.
bind $argv --key btab complete-and-search
bind $argv \e\n "commandline -i \n"
bind $argv \e\r "commandline -i \n"
bind $argv -k down down-or-search
bind $argv -k up up-or-search
bind $argv \e\[A up-or-search
bind $argv \e\[B down-or-search
bind $argv \eOA up-or-search
bind $argv \eOB down-or-search
# Alt-left/Alt-right
bind $argv \e\eOC nextd-or-forward-word
bind $argv \e\eOD prevd-or-backward-word
bind $argv \e\e\[C nextd-or-forward-word
bind $argv \e\e\[D prevd-or-backward-word
bind $argv \eO3C nextd-or-forward-word
bind $argv \eO3D prevd-or-backward-word
bind $argv \e\[3C nextd-or-forward-word
bind $argv \e\[3D prevd-or-backward-word
bind $argv \e\[1\;3C nextd-or-forward-word
bind $argv \e\[1\;3D prevd-or-backward-word
bind $argv \e\[1\;9C nextd-or-forward-word #iTerm2
bind $argv \e\[1\;9D prevd-or-backward-word #iTerm2
# Alt-up/Alt-down
bind $argv \e\eOA history-token-search-backward
bind $argv \e\eOB history-token-search-forward
bind $argv \e\e\[A history-token-search-backward
bind $argv \e\e\[B history-token-search-forward
bind $argv \eO3A history-token-search-backward
bind $argv \eO3B history-token-search-forward
bind $argv \e\[3A history-token-search-backward
bind $argv \e\[3B history-token-search-forward
bind $argv \e\[1\;3A history-token-search-backward
bind $argv \e\[1\;3B history-token-search-forward
bind $argv \e\[1\;9A history-token-search-backward # iTerm2
bind $argv \e\[1\;9B history-token-search-forward # iTerm2
# Bash compatibility
# https://github.com/fish-shell/fish-shell/issues/89
bind $argv \e. history-token-search-backward
bind $argv \el __fish_list_current_token
bind $argv \ew 'set tok (commandline -pt); if test $tok[1]; echo; whatis $tok[1]; commandline -f repaint; end'
bind $argv \cl 'clear; commandline -f repaint'
bind $argv \cc __fish_cancel_commandline
bind $argv \cu backward-kill-line
bind $argv \cw backward-kill-path-component
bind $argv \e\[F end-of-line
bind $argv \e\[H beginning-of-line
bind $argv \ed 'set -l cmd (commandline); if test -z "$cmd"; echo; dirh; commandline -f repaint; else; commandline -f kill-word; end'
bind $argv \cd delete-or-exit
# Allow reading manpages by pressing F1 (many GUI applications) or Alt+h (like in zsh).
bind $argv -k f1 __fish_man_page
bind $argv \eh __fish_man_page
# This will make sure the output of the current command is paged using the default pager when you press Meta-p.
# If none is set, less will be used.
bind $argv \ep '__fish_paginate'
# Make it easy to turn an unexecuted command into a comment in the shell history. Also,
# remove the commenting chars so the command can be further edited then executed.
bind $argv \e\# __fish_toggle_comment_commandline
end

View file

@ -40,9 +40,9 @@ function alias --description 'Legacy function for creating shellscript functions
end end
# Extract the first command from the body # Extract the first command from the body
# This is supposed to replace all non-escaped (i.e. preceded by an odd number of `\`) spaces with a newline # This is supposed to replace all non-escaped (i.e. preceded by an odd number of `\`) spaces with a newline
# so it splits on them # so it splits on them
set -l tmp (string replace -ra "([^\\\ ])((\\\\\\\)*) " '$1\n' $body) set -l tmp (string replace -ra "([^\\\ ])((\\\\\\\)*) " '$1\n' $body)
set first_word (string trim $tmp[1]) set first_word (string trim $tmp[1])
if set -q tmp[2] if set -q tmp[2]
set body $tmp[2..-1] set body $tmp[2..-1]
@ -60,6 +60,5 @@ function alias --description 'Legacy function for creating shellscript functions
set prefix command set prefix command
end end
end end
eval "function $name --wraps $first_word; $prefix $first_word $body \$argv; end" echo "function $name --wraps $first_word; $prefix $first_word $body \$argv; end" | source
end end

View file

@ -1,7 +1,7 @@
# #
# Wrap the builtin cd command to maintain directory history. # Wrap the builtin cd command to maintain directory history.
# #
function cd --shadow-builtin --description "Change directory" function cd --description "Change directory"
set -l MAX_DIR_HIST 25 set -l MAX_DIR_HIST 25
if test (count $argv) -gt 1 if test (count $argv) -gt 1

View file

@ -9,7 +9,9 @@ function dirh --description "Print the current directory history (the prev and n
set -l dirc (count $dirprev) set -l dirc (count $dirprev)
set -l dirprev_rev $dirprev[-1..1] set -l dirprev_rev $dirprev[-1..1]
for i in (seq $dirc -1 1) # This can't be (seq $dirc -1 1) because of BSD.
set -l dirnum (seq 1 $dirc)
for i in $dirnum[-1..1]
printf '%2d) %s\n' $i $dirprev_rev[$i] printf '%2d) %s\n' $i $dirprev_rev[$i]
end end

View file

@ -1,160 +1,86 @@
function fish_default_key_bindings -d "Default (Emacs-like) key bindings for fish" function fish_default_key_bindings -d "Default (Emacs-like) key bindings for fish"
if not set -q argv[1] if not set -q argv[1]
if test "$fish_key_bindings" != "fish_default_key_bindings" # Clear earlier bindings, if any
# Allow the user to set the variable universally bind --erase --all
set -q fish_key_bindings if test "$fish_key_bindings" != "fish_default_key_bindings"
or set -g fish_key_bindings # Allow the user to set the variable universally
set fish_key_bindings fish_default_key_bindings # This triggers the handler, which calls us again and ensures the user_key_bindings are executed set -q fish_key_bindings; or set -g fish_key_bindings
return set fish_key_bindings fish_default_key_bindings # This triggers the handler, which calls us again and ensures the user_key_bindings are executed
end return
# Clear earlier bindings, if any end
bind --erase --all end
end
# This is the default binding, i.e. the one used if no other binding matches # These are shell-specific bindings that we share with vi mode.
bind $argv "" self-insert __fish_shared_key_bindings $argv
bind $argv \n execute # This is the default binding, i.e. the one used if no other binding matches
bind $argv \r execute bind $argv "" self-insert
bind $argv \ck kill-line bind $argv \n execute
bind $argv \cy yank bind $argv \r execute
bind $argv \cx fish_clipboard_copy
bind $argv \cv fish_clipboard_paste
bind $argv \t complete
bind $argv \e\n "commandline -i \n" bind $argv \ck kill-line
bind $argv \e\r "commandline -i \n"
bind $argv \e\[A up-or-search bind $argv \eOC forward-char
bind $argv \e\[B down-or-search bind $argv \eOD backward-char
bind $argv -k down down-or-search bind $argv \e\[C forward-char
bind $argv -k up up-or-search bind $argv \e\[D backward-char
bind $argv -k right forward-char
bind $argv -k left backward-char
# Some linux VTs output these (why?) bind $argv -k dc delete-char
bind $argv \eOA up-or-search bind $argv -k backspace backward-delete-char
bind $argv \eOB down-or-search bind $argv \x7f backward-delete-char
bind $argv \eOC forward-char
bind $argv \eOD backward-char
bind $argv \e\[C forward-char # for PuTTY
bind $argv \e\[D backward-char # https://github.com/fish-shell/fish-shell/issues/180
bind $argv -k right forward-char bind $argv \e\[1~ beginning-of-line
bind $argv -k left backward-char bind $argv \e\[3~ delete-char
bind $argv \e\[4~ end-of-line
bind $argv -k dc delete-char # OS X SnowLeopard doesn't have these keys. Don't show an annoying error message.
bind $argv -k backspace backward-delete-char bind $argv -k home beginning-of-line 2> /dev/null
bind $argv \x7f backward-delete-char bind $argv -k end end-of-line 2> /dev/null
bind $argv \e\[3\;2~ backward-delete-char # Mavericks Terminal.app shift-delete
bind $argv \e\[H beginning-of-line bind $argv \ca beginning-of-line
bind $argv \e\[F end-of-line bind $argv \ce end-of-line
bind $argv \ch backward-delete-char
bind $argv \cp up-or-search
bind $argv \cn down-or-search
bind $argv \cf forward-char
bind $argv \cb backward-char
bind $argv \ct transpose-chars
bind $argv \et transpose-words
bind $argv \eu upcase-word
# for PuTTY # This clashes with __fish_list_current_token
# https://github.com/fish-shell/fish-shell/issues/180 # bind $argv \el downcase-word
bind $argv \e\[1~ beginning-of-line bind $argv \ec capitalize-word
bind $argv \e\[3~ delete-char bind $argv \e\x7f backward-kill-word
bind $argv \e\[4~ end-of-line bind $argv \eb backward-word
bind $argv \ef forward-word
bind $argv \e\[1\;5C forward-word
bind $argv \e\[1\;5D backward-word
bind $argv -k ppage beginning-of-history
bind $argv -k npage end-of-history
bind $argv \e\< beginning-of-buffer
bind $argv \e\> end-of-buffer
# OS X SnowLeopard doesn't have these keys. Don't show an annoying error message. bind \ed forward-kill-word
bind $argv -k home beginning-of-line 2>/dev/null bind \ed kill-word
bind $argv -k end end-of-line 2>/dev/null
bind $argv \e\[3\;2~ backward-delete-char # Mavericks Terminal.app shift-delete
bind $argv \e\eOC nextd-or-forward-word # Ignore some known-bad control sequences
bind $argv \e\eOD prevd-or-backward-word # https://github.com/fish-shell/fish-shell/issues/1917
bind $argv \e\e\[C nextd-or-forward-word bind \e\[I 'begin;end'
bind $argv \e\e\[D prevd-or-backward-word bind \e\[O 'begin;end'
bind $argv \eO3C nextd-or-forward-word
bind $argv \eO3D prevd-or-backward-word
bind $argv \e\[3C nextd-or-forward-word
bind $argv \e\[3D prevd-or-backward-word
bind $argv \e\[1\;3C nextd-or-forward-word
bind $argv \e\[1\;3D prevd-or-backward-word
bind $argv \e\eOA history-token-search-backward # term-specific special bindings
bind $argv \e\eOB history-token-search-forward switch "$TERM"
bind $argv \e\e\[A history-token-search-backward case 'rxvt*'
bind $argv \e\e\[B history-token-search-forward bind $argv \e\[8~ end-of-line
bind $argv \eO3A history-token-search-backward bind $argv \eOc forward-word
bind $argv \eO3B history-token-search-forward bind $argv \eOd backward-word
bind $argv \e\[3A history-token-search-backward end
bind $argv \e\[3B history-token-search-forward
bind $argv \e\[1\;3A history-token-search-backward
bind $argv \e\[1\;3B history-token-search-forward
bind $argv \ca beginning-of-line
bind $argv \ce end-of-line
bind $argv \ey yank-pop
bind $argv \ch backward-delete-char
bind $argv \cp up-or-search
bind $argv \cn down-or-search
bind $argv \cf forward-char
bind $argv \cb backward-char
bind $argv \ct transpose-chars
bind $argv \et transpose-words
bind $argv \eu upcase-word
# This clashes with __fish_list_current_token
# bind $argv \el downcase-word
bind $argv \ec capitalize-word
bind $argv \e\x7f backward-kill-word
bind $argv \eb backward-word
bind $argv \ef forward-word
bind $argv \e\[1\;5C forward-word
bind $argv \e\[1\;5D backward-word
bind $argv \e\[1\;9A history-token-search-backward # iTerm2
bind $argv \e\[1\;9B history-token-search-forward # iTerm2
bind $argv \e\[1\;9C nextd-or-forward-word #iTerm2
bind $argv \e\[1\;9D prevd-or-backward-word #iTerm2
# Bash compatibility
# https://github.com/fish-shell/fish-shell/issues/89
bind $argv \e. history-token-search-backward
bind $argv -k ppage beginning-of-history
bind $argv -k npage end-of-history
bind $argv \e\< beginning-of-buffer
bind $argv \e\> end-of-buffer
bind $argv \el __fish_list_current_token
bind $argv \ew 'set tok (commandline -pt); if test $tok[1]; echo; whatis $tok[1]; commandline -f repaint; end'
bind $argv \cl 'clear; commandline -f repaint'
bind $argv \cc __fish_cancel_commandline
bind $argv \cu backward-kill-line
bind $argv \cw backward-kill-path-component
bind $argv \ed 'set -l cmd (commandline); if test -z "$cmd"; echo; dirh; commandline -f repaint; else; commandline -f kill-word; end'
bind $argv \cd delete-or-exit
bind \ed forward-kill-word
bind \ed kill-word
# Allow reading manpages by pressing F1 (many GUI applications) or Alt+h (like in zsh)
bind $argv -k f1 __fish_man_page
bind $argv \eh __fish_man_page
# This will make sure the output of the current command is paged using the default pager when you press Meta-p
# If none is set, less will be used
bind $argv \ep '__fish_paginate'
# shift-tab does a tab complete followed by a search
bind $argv --key btab complete-and-search
# escape cancels stuff
bind \e cancel
# Ignore some known-bad control sequences
# https://github.com/fish-shell/fish-shell/issues/1917
bind \e\[I 'begin;end'
bind \e\[O 'begin;end'
# term-specific special bindings
switch "$TERM"
case 'rxvt*'
bind $argv \e\[8~ end-of-line
bind $argv \eOc forward-word
bind $argv \eOd backward-word
end
# Make it easy to turn an unexecuted command into a comment in the shell history. Also,
# remove the commenting chars so the command can be further edited then executed.
bind \e\# __fish_toggle_comment_commandline
end end

View file

@ -1,4 +1,11 @@
function fish_vi_cursor -d 'Set cursor shape for different vi modes' function fish_vi_cursor -d 'Set cursor shape for different vi modes'
# Since we read exported variables (KONSOLE_PROFILE_NAME and ITERM_PROFILE)
# we need to check harder if we're actually in a supported terminal,
# because we might be in a term-in-a-term (emacs ansi-term).
if not contains -- $TERM xterm konsole xterm-256color konsole-256color
and not set -q TMUX
return
end
set -l terminal $argv[1] set -l terminal $argv[1]
set -q terminal[1] set -q terminal[1]
or set terminal auto or set terminal auto
@ -37,7 +44,7 @@ function fish_vi_cursor -d 'Set cursor shape for different vi modes'
or set -g fish_cursor_unknown block blink or set -g fish_cursor_unknown block blink
echo " echo "
function fish_vi_cursor_handle --on-variable fish_bind_mode function fish_vi_cursor_handle --on-variable fish_bind_mode --on-event fish_postexec
set -l varname fish_cursor_\$fish_bind_mode set -l varname fish_cursor_\$fish_bind_mode
if not set -q \$varname if not set -q \$varname
set varname fish_cursor_unknown set varname fish_cursor_unknown
@ -47,5 +54,17 @@ function fish_vi_cursor -d 'Set cursor shape for different vi modes'
$tmux_postfix $tmux_postfix
end end
" | source " | source
echo "
function fish_vi_cursor_handle_preexec --on-event fish_preexec
set -l varname fish_cursor_default
if not set -q \$varname
set varname fish_cursor_unknown
end
$tmux_prefix
$function \$\$varname
$tmux_postfix
end
" | source
end end

View file

@ -1,30 +1,54 @@
function fish_vi_key_bindings --description 'vi-like key bindings for fish' function fish_vi_key_bindings --description 'vi-like key bindings for fish'
if test "$fish_key_bindings" != "fish_vi_key_bindings" # Erase all bindings if not explicitly requested otherwise to
# Allow the user to set the variable universally # allow for hybrid bindings.
set -q fish_key_bindings; or set -g fish_key_bindings # This needs to be checked here because if we are called again
set fish_key_bindings fish_vi_key_bindings # This triggers the handler, which calls us again and ensures the user_key_bindings are executed # via the variable handler the argument will be gone.
return if not contains -- $argv[1] --no-erase
end bind --erase --all
else if set -q argv[1]
set -e argv[1]
end
# Allow just calling this function to correctly set the bindings.
# Because it's a rather discoverable name, users will execute it
# and without this would then have subtly broken bindings.
if test "$fish_key_bindings" != "fish_vi_key_bindings"
# Allow the user to set the variable universally
set -q fish_key_bindings
or set -g fish_key_bindings
set fish_key_bindings fish_vi_key_bindings # This triggers the handler, which calls us again and ensures the user_key_bindings are executed
return
end
# The default escape timeout is 300ms. But for users of Vi bindings that can be slightly # The default escape timeout is 300ms. But for users of Vi bindings that can be slightly
# annoying when trying to switch to Vi "normal" mode. So set a shorter timeout in this case # annoying when trying to switch to Vi "normal" mode. So set a shorter timeout in this case
# unless the user has explicitly set the delay. # unless the user has explicitly set the delay.
set -q fish_escape_delay_ms; or set -g fish_escape_delay_ms 100 set -q fish_escape_delay_ms; or set -g fish_escape_delay_ms 100
set -l init_mode insert set -l init_mode insert
set -l eol_keys \$ g\$ \e\[F # These are only the special vi-style keys
set -l bol_keys \^ 0 g\^ \e\[H # not end/home, we share those.
if set -q argv[1] set -l eol_keys \$ g\$
set -l bol_keys \^ 0 g\^
if contains -- $argv[1] insert default visual
set init_mode $argv[1] set init_mode $argv[1]
else if set -q argv[1]
# We should still go on so the bindings still get set.
echo "Unknown argument $argv" >&2
end end
# Inherit default key bindings. # Inherit shared key bindings.
# Do this first so vi-bindings win over default. # Do this first so vi-bindings win over default.
bind --erase --all for mode in insert default visual
fish_default_key_bindings -M insert __fish_shared_key_bindings -M $mode
fish_default_key_bindings -M default end
bind -M insert \r execute
bind -M insert \n execute
bind -M insert "" self-insert
# Remove the default self-insert bindings in default mode
bind -e "" -M default
# Add way to kill current command line while in insert mode. # Add way to kill current command line while in insert mode.
bind -M insert \cc __fish_cancel_commandline bind -M insert \cc __fish_cancel_commandline
# Add a way to switch from insert to normal (command) mode. # Add a way to switch from insert to normal (command) mode.
@ -34,17 +58,8 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish'
bind :q exit bind :q exit
bind \cd exit bind \cd exit
bind -m insert \cc __fish_cancel_commandline bind -m insert \cc __fish_cancel_commandline
bind h backward-char bind -M default h backward-char
bind l forward-char bind -M default l forward-char
bind \e\[C forward-char
bind \e\[D backward-char
# Some terminals output these when they're in in keypad mode.
bind \eOC forward-char
bind \eOD backward-char
bind -k right forward-char
bind -k left backward-char
bind -m insert \n execute bind -m insert \n execute
bind -m insert \r execute bind -m insert \r execute
bind -m insert i force-repaint bind -m insert i force-repaint
@ -74,13 +89,6 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish'
bind k up-or-search bind k up-or-search
bind j down-or-search bind j down-or-search
bind \e\[A up-or-search
bind \e\[B down-or-search
bind -k down down-or-search
bind -k up up-or-search
bind \eOA up-or-search
bind \eOB down-or-search
bind b backward-word bind b backward-word
bind B backward-bigword bind B backward-bigword
bind ge backward-word bind ge backward-word
@ -95,8 +103,11 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish'
bind -k dc delete-char bind -k dc delete-char
bind -k backspace backward-delete-char # Backspace deletes a char in insert mode, but not in normal/default mode.
bind \x7f backward-delete-char bind -M insert -k backspace backward-delete-char
bind -M default -k backspace backward-char
bind -M insert \x7f backward-delete-char
bind -M default \x7f backward-char
bind \e\[3\;2~ backward-delete-char # Mavericks Terminal.app shift-delete bind \e\[3\;2~ backward-delete-char # Mavericks Terminal.app shift-delete
bind dd kill-whole-line bind dd kill-whole-line
@ -169,10 +180,6 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish'
bind P backward-char yank bind P backward-char yank
bind gp yank-pop bind gp yank-pop
### Overrides
# This is complete in vim
bind -M insert \cx end-of-line
bind '"*p' "commandline -i ( xsel -p; echo )[1]" bind '"*p' "commandline -i ( xsel -p; echo )[1]"
bind '"*P' backward-char "commandline -i ( xsel -p; echo )[1]" bind '"*P' backward-char "commandline -i ( xsel -p; echo )[1]"
@ -186,12 +193,6 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish'
# #
# visual mode # visual mode
# #
bind -M visual \e\[C forward-char
bind -M visual \e\[D backward-char
bind -M visual -k right forward-char
bind -M visual -k left backward-char
bind -M insert \eOC forward-char
bind -M insert \eOD backward-char
bind -M visual h backward-char bind -M visual h backward-char
bind -M visual l forward-char bind -M visual l forward-char
@ -225,13 +226,16 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish'
bind -M visual -m default \cc end-selection force-repaint bind -M visual -m default \cc end-selection force-repaint
bind -M visual -m default \e end-selection force-repaint bind -M visual -m default \e end-selection force-repaint
set fish_bind_mode $init_mode
# Make it easy to turn an unexecuted command into a comment in the shell history. Also, remove # Make it easy to turn an unexecuted command into a comment in the shell history. Also, remove
# the commenting chars so the command can be further edited then executed. # the commenting chars so the command can be further edited then executed.
bind -M default \# __fish_toggle_comment_commandline bind -M default \# __fish_toggle_comment_commandline
bind -M visual \# __fish_toggle_comment_commandline bind -M visual \# __fish_toggle_comment_commandline
bind -M default \e\# __fish_toggle_comment_commandline
bind -M insert \e\# __fish_toggle_comment_commandline # Set the cursor shape
bind -M visual \e\# __fish_toggle_comment_commandline # After executing once, this will have defined functions listening for the variable.
# Therefore it needs to be before setting fish_bind_mode.
fish_vi_cursor
set fish_bind_mode $init_mode
end end

View file

@ -1,9 +1,9 @@
# #
# Wrap the builtin history command to provide additional functionality. # Wrap the builtin history command to provide additional functionality.
# #
function history --shadow-builtin --description "display or manipulate interactive command history" function history --description "display or manipulate interactive command history"
set -l cmd set -l cmd
set -l search_mode --contains set -l search_mode
set -l with_time set -l with_time
# The "set cmd $cmd xyz" lines are to make it easy to detect if the user specifies more than one # The "set cmd $cmd xyz" lines are to make it easy to detect if the user specifies more than one
@ -28,6 +28,8 @@ function history --shadow-builtin --description "display or manipulate interacti
set search_mode --prefix set search_mode --prefix
case -c --contains case -c --contains
set search_mode --contains set search_mode --contains
case -e --exact
set search_mode --exact
case -- case --
set -e argv[1] set -e argv[1]
break break
@ -38,7 +40,7 @@ function history --shadow-builtin --description "display or manipulate interacti
end end
if not set -q cmd[1] if not set -q cmd[1]
set cmd search # default to "search" if the user didn't explicitly specify a command set cmd search # default to "search" if the user didn't explicitly specify a command
else if set -q cmd[2] else if set -q cmd[2]
printf (_ "You cannot specify multiple commands: %s\n") "$cmd" printf (_ "You cannot specify multiple commands: %s\n") "$cmd"
return 1 return 1
@ -46,6 +48,9 @@ function history --shadow-builtin --description "display or manipulate interacti
switch $cmd switch $cmd
case search case search
test -z "$search_mode"
and set search_mode "--contains"
if isatty stdout if isatty stdout
set -l pager less set -l pager less
set -q PAGER set -q PAGER
@ -55,13 +60,21 @@ function history --shadow-builtin --description "display or manipulate interacti
builtin history --search $search_mode $with_time -- $argv builtin history --search $search_mode $with_time -- $argv
end end
case delete # Interactively delete history case delete # Interactively delete history
# TODO: Fix this to deal with history entries that have multiple lines. # TODO: Fix this to deal with history entries that have multiple lines.
if not set -q argv[1] if not set -q argv[1]
printf "You have to specify at least one search term to find entries to delete" >&2 printf (_ "You must specify at least one search term when deleting entries\n") >&2
return 1 return 1
end end
test -z "$search_mode"
and set search_mode "--exact"
if test $search_mode = "--exact"
builtin history --delete $search_mode $argv
return
end
# TODO: Fix this so that requesting history entries with a timestamp works: # TODO: Fix this so that requesting history entries with a timestamp works:
# set -l found_items (builtin history --search $search_mode $with_time -- $argv) # set -l found_items (builtin history --search $search_mode $with_time -- $argv)
set -l found_items (builtin history --search $search_mode -- $argv) set -l found_items (builtin history --search $search_mode -- $argv)
@ -92,8 +105,8 @@ function history --shadow-builtin --description "display or manipulate interacti
for i in (string split " " -- $choice) for i in (string split " " -- $choice)
if test -z "$i" if test -z "$i"
or not string match -qr '^[1-9][0-9]*$' -- $i or not string match -qr '^[1-9][0-9]*$' -- $i
or test $i -gt $found_items_count or test $i -gt $found_items_count
printf "Ignoring invalid history entry ID \"%s\"\n" $i printf "Ignoring invalid history entry ID \"%s\"\n" $i
continue continue
end end
@ -105,9 +118,19 @@ function history --shadow-builtin --description "display or manipulate interacti
end end
case save case save
if test -n "$search_mode"
or test -n "$with_time"
printf (_ "history: you cannot use any options with %s command\n") save >&2
return 1
end
builtin history --save -- $argv builtin history --save -- $argv
case merge case merge
if test -n "$search_mode"
or test -n "$with_time"
printf (_ "history: you cannot use any options with %s command\n") merge >&2
return 1
end
builtin history --merge -- $argv builtin history --merge -- $argv
case help case help
@ -115,11 +138,19 @@ function history --shadow-builtin --description "display or manipulate interacti
case clear case clear
# Erase the entire history. # Erase the entire history.
read --local --prompt "echo 'Are you sure you want to clear history? (y/n) '" choice if test -n "$search_mode"
if test "$choice" = "y" or test -n "$with_time"
or test "$choice" = "yes" printf (_ "history: you cannot use any options with %s command\n") clear >&2
return 1
end
printf (_ "If you enter 'yes' your entire interactive command history will be erased\n")
read --local --prompt "echo 'Are you sure you want to clear history? (yes/no) '" choice
if test "$choice" = "yes"
builtin history --clear -- $argv builtin history --clear -- $argv
and echo "History cleared!" and printf (_ "Command history cleared!")
else
printf (_ "You did not say 'yes' so I will not clear your command history\n")
end end
end end
end end

View file

@ -1,4 +1,3 @@
function pushd --description 'Push directory to stack' function pushd --description 'Push directory to stack'
if count $argv >/dev/null if count $argv >/dev/null
# check for --help # check for --help
@ -9,8 +8,13 @@ function pushd --description 'Push directory to stack'
end end
# emulate bash by checking if argument of form +n or -n # emulate bash by checking if argument of form +n or -n
set rot_l (echo $argv[1] | sed -n '/^+\([0-9]\)$/ s//\1/g p') set -l rot_r
set rot_r (echo $argv[1] | sed -n '/^-\([0-9]\)$/ s//\1/g p') set -l rot_l
if string match -qr '^-[0-9]+$' -- $argv[1]
set rot_r (string sub -s 2 -- $argv[1])
else if string match -qr '^\+[0-9]+$' -- $argv[1]
set rot_l (string sub -s 2 -- $argv[1])
end
end end
# emulate bash: an empty pushd should switch the top of dirs # emulate bash: an empty pushd should switch the top of dirs
@ -39,7 +43,7 @@ function pushd --description 'Push directory to stack'
# translate a right rotation to a left rotation # translate a right rotation to a left rotation
if test -n "$rot_r" if test -n "$rot_r"
# check the rotation in range # check the rotation in range
if test $rot_r -gt (math (count $stack) - 1) if test $rot_r -ge (count $stack)
echo "pushd: -$rot_r: directory stack index out of range" echo "pushd: -$rot_r: directory stack index out of range"
return 1 return 1
end end
@ -48,7 +52,7 @@ function pushd --description 'Push directory to stack'
end end
# check the rotation in range # check the rotation in range
if test $rot_l -gt (math (count $stack) - 1) if test $rot_l -ge (count $stack)
echo "pushd: +$rot_l: directory stack index out of range" echo "pushd: +$rot_l: directory stack index out of range"
return 1 return 1
else else
@ -67,8 +71,7 @@ function pushd --description 'Push directory to stack'
return return
end end
# Comment to avoid set completions # argv[1] is a directory
set -g dirstack (command pwd) $dirstack set -g dirstack (command pwd) $dirstack
cd $argv[1] cd $argv[1]
end end

View file

@ -129,8 +129,10 @@ def built_command(options, description):
# print "Options are: ", options # print "Options are: ", options
man_optionlist = re.split(" |,|\"|=|[|]", options) man_optionlist = re.split(" |,|\"|=|[|]", options)
fish_options = [] fish_options = []
for option in man_optionlist: for optionstr in man_optionlist:
option = option.strip() option = re.sub(r"(\[.*\])", "", optionstr)
option = option.strip(" \t\n[]()")
# Skip some problematic cases # Skip some problematic cases
if option in ['-', '--']: continue if option in ['-', '--']: continue

View file

@ -220,6 +220,11 @@ body {
word-wrap: break-word; word-wrap: break-word;
} }
.raw_binding {
padding-left: 20px;
font-family: monospace;
}
.history_text { .history_text {
padding-top: 5px; padding-top: 5px;
padding-bottom: 5px; padding-bottom: 5px;

View file

@ -25,8 +25,16 @@ filters.filter("filterBinding", function() {
for(i=0; i<bindings.length; ++i) { for(i=0; i<bindings.length; ++i) {
binding = bindings[i]; binding = bindings[i];
if (binding.command.indexOf(query) != -1 || binding.readable_binding.toLowerCase().indexOf(query.toLowerCase()) != -1) { if (binding.command.indexOf(query) != -1) {
result.push(binding); result.push(binding);
continue;
}
varieties = binding.bindings;
for (j=0; j<varieties.length; ++j) {
if (varieties[j].readable_binding.toLowerCase().indexOf(query.toLowerCase()) != -1) {
result.push(binding);
break;
}
} }
} }

View file

@ -6,8 +6,13 @@
<tbody> <tbody>
<tr class="data_table_row" ng-repeat="binding in bindings | filterBinding:query"> <tr class="data_table_row" ng-repeat="binding in bindings | filterBinding:query">
<td ng-class="{ data_table_cell: true, no_overflow: !binding._is_selected }" style="text-align: right; padding-right: 30px;" ng-click="binding._is_selected = !binding._is_selected">{{ binding.command }}</td> <td ng-class="{ data_table_cell: true, no_overflow: !binding._is_selected }" style="text-align: right; padding-right: 30px;" ng-click="binding._is_selected = !binding._is_selected">{{ binding.command }}</td>
<!-- Some bindings are listed multiple times for e.g. function backward-char is bound to \e\[D as well as key left. Users may want to know why some bindings are listed twice, so the actual binding is shown in next line on a click --> <!-- Raw binding commands are shown in next line on a click -->
<td ng-class="{ data_table_cell: true, no_overflow: !binding._is_selected }" style="text-align: left; padding-right: 30px;" ng-click="binding._is_selected = !binding._is_selected">{{ binding.readable_binding }} <div ng-show="binding._is_selected"> {{ binding.binding }} </div> </td> <td ng-class="{ data_table_cell: true, no_overflow: !binding._is_selected }" style="text-align: left; padding-right: 30px;" ng-click="binding._is_selected = !binding._is_selected">
<div ng-repeat="variety in binding.bindings">
{{ variety.readable_binding }}
<div class="raw_binding" ng-repeat="raw in variety.raw_bindings" ng-show="binding._is_selected" > {{ raw }} </div>
</div>
</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>

View file

@ -88,6 +88,8 @@ named_colors = {
'brwhite' : 'ffffff' 'brwhite' : 'ffffff'
} }
bindings_blacklist = set(["self-insert", "'begin;end'"])
def parse_one_color(comp): def parse_one_color(comp):
""" A basic function to parse a single color value like 'FFA000' """ """ A basic function to parse a single color value like 'FFA000' """
if comp in named_colors: if comp in named_colors:
@ -288,17 +290,23 @@ class FishVar:
class FishBinding: class FishBinding:
"""A class that represents keyboard binding """ """A class that represents keyboard binding """
def __init__(self, command, binding, readable_binding, description=None): def __init__(self, command, raw_binding, readable_binding, description=None):
self.command = command self.command = command
self.binding = binding self.bindings = []
self.readable_binding = readable_binding
self.description = description self.description = description
self.add_binding(raw_binding, readable_binding)
def add_binding(self, raw_binding, readable_binding):
for i in self.bindings:
if i['readable_binding'] == readable_binding:
i['raw_bindings'].append(raw_binding)
break
else:
self.bindings.append({'readable_binding':readable_binding, 'raw_bindings':[raw_binding]})
def get_json_obj(self): def get_json_obj(self):
return {"command" : self.command, "binding": self.binding, "readable_binding": self.readable_binding, "description": self.description } return {"command" : self.command, "bindings": self.bindings, "description": self.description}
def get_readable_binding(command):
return command
class BindingParser: class BindingParser:
""" Class to parse codes for bind command """ """ Class to parse codes for bind command """
@ -308,7 +316,8 @@ class BindingParser:
"sdc": "Shift Delete", "shome": "Shift Home", "sdc": "Shift Delete", "shome": "Shift Home",
"left": "Left Arrow", "right": "Right Arrow", "left": "Left Arrow", "right": "Right Arrow",
"up": "Up Arrow", "down": "Down Arrow", "up": "Up Arrow", "down": "Down Arrow",
"sleft": "Shift Left", "sright": "Shift Right" "sleft": "Shift Left", "sright": "Shift Right",
"btab": "Shift Tab"
} }
def set_buffer(self, buffer): def set_buffer(self, buffer):
@ -347,8 +356,10 @@ class BindingParser:
# \[1\; is start of control sequence # \[1\; is start of control sequence
if c == '1': if c == '1':
self.get_char();c = self.get_char() b = self.get_char(); c = self.get_char()
if c == ";": if b == '\\' and c == '~':
result += "Home"
elif c == ";":
c = self.get_char() c = self.get_char()
# 3 is Alt # 3 is Alt
@ -356,6 +367,12 @@ class BindingParser:
result += "ALT - " result += "ALT - "
c = self.get_char() c = self.get_char()
# \[4\~ is End
if c == '4':
b = self.get_char(); c = self.get_char()
if b == '\\' and c == '~':
result += "End"
# 5 is Ctrl # 5 is Ctrl
if c == '5': if c == '5':
result += "CTRL - " result += "CTRL - "
@ -385,7 +402,7 @@ class BindingParser:
""" Gets a readable representation of binding """ """ Gets a readable representation of binding """
try: try:
result = BindingParser.readable_keys[self.buffer] result = BindingParser.readable_keys[self.buffer.lower()]
except KeyError: except KeyError:
result = self.parse_binding() result = self.parse_binding()
@ -413,6 +430,8 @@ class BindingParser:
self.unget_char() self.unget_char()
self.unget_char() self.unget_char()
alt = True alt = True
elif d == '\0':
result += 'ESC'
else: else:
alt = True alt = True
self.unget_char() self.unget_char()
@ -424,8 +443,12 @@ class BindingParser:
result += 'Tab' result += 'Tab'
elif c == 'b': elif c == 'b':
result += 'Backspace' result += 'Backspace'
elif c.isalpha():
result += '\\' + c
else: else:
result += c result += c
elif c == '\x7f':
result += 'Backspace'
else: else:
result += c result += c
if ctrl: if ctrl:
@ -433,6 +456,9 @@ class BindingParser:
if alt: if alt:
readable_command += 'ALT - ' readable_command += 'ALT - '
if result == '':
return 'unknown-control-sequence'
return readable_command + result return readable_command + result
@ -566,6 +592,7 @@ class FishConfigHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
# Put all the bindings into a list # Put all the bindings into a list
bindings = [] bindings = []
command_to_binding = {}
binding_parser = BindingParser() binding_parser = BindingParser()
for line in out.split('\n'): for line in out.split('\n'):
@ -576,15 +603,23 @@ class FishConfigHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
if comps[1] == '-k': if comps[1] == '-k':
key_name, command = comps[2].split(' ', 1) key_name, command = comps[2].split(' ', 1)
binding_parser.set_buffer(key_name) binding_parser.set_buffer(key_name.capitalize())
else: else:
key_name = None key_name = None
command = comps[2] command = comps[2]
binding_parser.set_buffer(comps[1]) binding_parser.set_buffer(comps[1])
if command in bindings_blacklist:
continue
readable_binding = binding_parser.get_readable_binding() readable_binding = binding_parser.get_readable_binding()
fish_binding = FishBinding(command, key_name, readable_binding) if command in command_to_binding:
bindings.append(fish_binding) fish_binding = command_to_binding[command]
fish_binding.add_binding(line, readable_binding)
else:
fish_binding = FishBinding(command, line, readable_binding)
bindings.append(fish_binding)
command_to_binding[command] = fish_binding
return [ binding.get_json_obj() for binding in bindings ] return [ binding.get_json_obj() for binding in bindings ]

View file

@ -71,28 +71,6 @@
#include "wgetopt.h" #include "wgetopt.h"
#include "wutil.h" // IWYU pragma: keep #include "wutil.h" // IWYU pragma: keep
// The default prompt for the read command.
#define DEFAULT_READ_PROMPT L"set_color green; echo -n read; set_color normal; echo -n \"> \""
// The mode name to pass to history and input.
#define READ_MODE_NAME L"fish_read"
// The send stuff to foreground message.
#define FG_MSG _(L"Send job %d, '%ls' to foreground\n")
/// Data structure to describe a builtin.
struct builtin_data_t {
// Name of the builtin.
const wchar_t *name;
// Function pointer tothe builtin implementation.
int (*func)(parser_t &parser, io_streams_t &streams, wchar_t **argv);
// Description of what the builtin does.
const wchar_t *desc;
bool operator<(const wcstring &) const;
bool operator<(const builtin_data_t *) const;
};
bool builtin_data_t::operator<(const wcstring &other) const { bool builtin_data_t::operator<(const wcstring &other) const {
return wcscmp(this->name, other.c_str()) < 0; return wcscmp(this->name, other.c_str()) < 0;
} }
@ -101,12 +79,18 @@ bool builtin_data_t::operator<(const builtin_data_t *other) const {
return wcscmp(this->name, other->name) < 0; return wcscmp(this->name, other->name) < 0;
} }
/// Counts the number of non null pointers in the specified array. /// Counts the number of arguments in the specified null-terminated array
///
/// @param argv[]: argument list
///
/// @return
/// The numer of non-NULL elements in @param *argv before the first NULL.
///
int builtin_count_args(const wchar_t *const *argv) { int builtin_count_args(const wchar_t *const *argv) {
int argc = 1; int argc;
while (argv[argc] != NULL) { for (argc = 1; argv[argc] != NULL; argc++);
argc++;
} assert(argv[argc] == NULL);
return argc; return argc;
} }
@ -134,6 +118,14 @@ static int count_char(const wchar_t *str, wchar_t c) {
return res; return res;
} }
/// Obtain help/usage information for the specified builtin from manpage in subshell
///
/// @param name
/// builtin name to get up help for
///
/// @return
/// A wcstring with a formatted manpage.
///
wcstring builtin_help_get(parser_t &parser, io_streams_t &streams, const wchar_t *name) { wcstring builtin_help_get(parser_t &parser, io_streams_t &streams, const wchar_t *name) {
// This won't ever work if no_exec is set. // This won't ever work if no_exec is set.
if (no_exec) return wcstring(); if (no_exec) return wcstring();
@ -157,10 +149,12 @@ wcstring builtin_help_get(parser_t &parser, io_streams_t &streams, const wchar_t
return out; return out;
} }
/// Print help for the specified builtin. If \c b is sb_err, also print the line information. /// Process and print for the specified builtin. If @c b is `sb_err`, also print the line
/// information.
/// ///
/// If \c b is the buffer representing standard error, and the help message is about to be printed /// If @c b is the buffer representing standard error, and the help message is about to be printed
/// to an interactive screen, it may be shortened to fit the screen. /// to an interactive screen, it may be shortened to fit the screen.
///
void builtin_print_help(parser_t &parser, io_streams_t &streams, const wchar_t *cmd, void builtin_print_help(parser_t &parser, io_streams_t &streams, const wchar_t *cmd,
output_stream_t &b) { output_stream_t &b) {
bool is_stderr = &b == &streams.err; bool is_stderr = &b == &streams.err;
@ -396,10 +390,16 @@ static int builtin_bind_add(const wchar_t *seq, const wchar_t *const *cmds, size
/// Erase specified key bindings /// Erase specified key bindings
/// ///
/// \param seq an array of all key bindings to erase /// @param seq
/// \param all if specified, _all_ key bindings will be erased /// an array of all key bindings to erase
/// \param mode if specified, only bindings from that mode will be erased. If not given and \c all /// @param all
/// is \c false, \c DEFAULT_BIND_MODE will be used. /// if specified, _all_ key bindings will be erased
/// @param mode
/// if specified, only bindings from that mode will be erased. If not given
/// and @c all is @c false, @c DEFAULT_BIND_MODE will be used.
/// @param use_terminfo
/// Whether to look use terminfo -k name
///
static int builtin_bind_erase(wchar_t **seq, int all, const wchar_t *mode, int use_terminfo, static int builtin_bind_erase(wchar_t **seq, int all, const wchar_t *mode, int use_terminfo,
io_streams_t &streams) { io_streams_t &streams) {
if (all) { if (all) {
@ -920,10 +920,6 @@ static wcstring functions_def(const wcstring &name) {
out.append(esc_desc); out.append(esc_desc);
} }
if (function_get_shadow_builtin(name)) {
out.append(L" --shadow-builtin");
}
if (!function_get_shadow_scope(name)) { if (!function_get_shadow_scope(name)) {
out.append(L" --no-scope-shadowing"); out.append(L" --no-scope-shadowing");
} }
@ -1303,7 +1299,7 @@ static bool builtin_echo_parse_numeric_sequence(const wchar_t *str, size_t *cons
/// Bash only respects -n if it's the first argument. We'll do the same. We also support a new /// Bash only respects -n if it's the first argument. We'll do the same. We also support a new
/// option -s to mean "no spaces" /// option -s to mean "no spaces"
static int builtin_echo(parser_t &parser, io_streams_t &streams, wchar_t **argv) { static int builtin_echo(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
/* Skip first arg */ // Skip first arg
if (!*argv++) return STATUS_BUILTIN_ERROR; if (!*argv++) return STATUS_BUILTIN_ERROR;
// Process options. Options must come at the beginning - the first non-option kicks us out. // Process options. Options must come at the beginning - the first non-option kicks us out.
@ -1464,7 +1460,20 @@ static int builtin_pwd(parser_t &parser, io_streams_t &streams, wchar_t **argv)
return STATUS_BUILTIN_OK; return STATUS_BUILTIN_OK;
} }
/// Adds a function to the function set. It calls into function.cpp to perform any heavy lifting. /// Defines and adds a function to the function set. Calls into `function.cpp`
/// to perform all heavy lifting.
///
/// @param c_args
/// The arguments. Should NOT contain 'function' as the first argument as the
/// parser treats it as a keyword.
/// @param contents
/// The function definition string
/// @param definition_line_offset
/// The definition line offset
///
/// @return
/// Returns 0 on success.
///
int builtin_function(parser_t &parser, io_streams_t &streams, const wcstring_list_t &c_args, int builtin_function(parser_t &parser, io_streams_t &streams, const wcstring_list_t &c_args,
const wcstring &contents, int definition_line_offset, wcstring *out_err) { const wcstring &contents, int definition_line_offset, wcstring *out_err) {
wgetopter_t w; wgetopter_t w;
@ -1479,17 +1488,13 @@ int builtin_function(parser_t &parser, io_streams_t &streams, const wcstring_lis
// Hackish const_cast matches the one in builtin_run. // Hackish const_cast matches the one in builtin_run.
const null_terminated_array_t<wchar_t> argv_array(args); const null_terminated_array_t<wchar_t> argv_array(args);
wchar_t **argv = const_cast<wchar_t **>(argv_array.get()); wchar_t **argv = const_cast<wchar_t **>(argv_array.get());
int argc = builtin_count_args(argv); int argc = builtin_count_args(argv);
int res = STATUS_BUILTIN_OK; int res = STATUS_BUILTIN_OK;
wchar_t *desc = 0; wchar_t *desc = 0;
std::vector<event_t> events; std::vector<event_t> events;
bool has_named_arguments = false; bool has_named_arguments = false;
wcstring_list_t named_arguments; wcstring_list_t named_arguments;
wcstring_list_t inherit_vars; wcstring_list_t inherit_vars;
bool shadow_builtin = false;
bool shadow_scope = true; bool shadow_scope = true;
wcstring_list_t wrap_targets; wcstring_list_t wrap_targets;
@ -1510,7 +1515,6 @@ int builtin_function(parser_t &parser, io_streams_t &streams, const wcstring_lis
{L"wraps", required_argument, 0, 'w'}, {L"wraps", required_argument, 0, 'w'},
{L"help", no_argument, 0, 'h'}, {L"help", no_argument, 0, 'h'},
{L"argument-names", no_argument, 0, 'a'}, {L"argument-names", no_argument, 0, 'a'},
{L"shadow-builtin", no_argument, 0, 'B'},
{L"no-scope-shadowing", no_argument, 0, 'S'}, {L"no-scope-shadowing", no_argument, 0, 'S'},
{L"inherit-variable", required_argument, 0, 'V'}, {L"inherit-variable", required_argument, 0, 'V'},
{0, 0, 0, 0}}; {0, 0, 0, 0}};
@ -1519,7 +1523,7 @@ int builtin_function(parser_t &parser, io_streams_t &streams, const wcstring_lis
int opt_index = 0; int opt_index = 0;
// The leading - here specifies RETURN_IN_ORDER. // The leading - here specifies RETURN_IN_ORDER.
int opt = w.wgetopt_long(argc, argv, L"-d:s:j:p:v:e:w:haBSV:", long_options, &opt_index); int opt = w.wgetopt_long(argc, argv, L"-d:s:j:p:v:e:w:haSV:", long_options, &opt_index);
if (opt == -1) break; if (opt == -1) break;
switch (opt) { switch (opt) {
case 0: { case 0: {
@ -1615,10 +1619,6 @@ int builtin_function(parser_t &parser, io_streams_t &streams, const wcstring_lis
name_is_first_positional = !positionals.empty(); name_is_first_positional = !positionals.empty();
break; break;
} }
case 'B': {
shadow_builtin = true;
break;
}
case 'S': { case 'S': {
shadow_scope = false; shadow_scope = false;
break; break;
@ -1707,30 +1707,6 @@ int builtin_function(parser_t &parser, io_streams_t &streams, const wcstring_lis
} }
} }
if (!res) {
bool function_name_shadows_builtin = false;
wcstring_list_t builtin_names = builtin_get_names();
for (size_t i = 0; i < builtin_names.size(); i++) {
const wchar_t *el = builtin_names.at(i).c_str();
if (el == function_name) {
function_name_shadows_builtin = true;
break;
}
}
if (function_name_shadows_builtin && !shadow_builtin) {
append_format(
*out_err,
_(L"%ls: function name shadows a builtin so you must use '--shadow-builtin'"),
argv[0]);
res = STATUS_BUILTIN_ERROR;
} else if (!function_name_shadows_builtin && shadow_builtin) {
append_format(*out_err, _(L"%ls: function name does not shadow a builtin so you "
L"must not use '--shadow-builtin'"),
argv[0]);
res = STATUS_BUILTIN_ERROR;
}
}
if (!res) { if (!res) {
// Here we actually define the function! // Here we actually define the function!
function_data_t d; function_data_t d;
@ -1738,7 +1714,6 @@ int builtin_function(parser_t &parser, io_streams_t &streams, const wcstring_lis
d.name = function_name; d.name = function_name;
if (desc) d.description = desc; if (desc) d.description = desc;
d.events.swap(events); d.events.swap(events);
d.shadow_builtin = shadow_builtin;
d.shadow_scope = shadow_scope; d.shadow_scope = shadow_scope;
d.named_arguments.swap(named_arguments); d.named_arguments.swap(named_arguments);
d.inherit_vars.swap(inherit_vars); d.inherit_vars.swap(inherit_vars);
@ -2097,7 +2072,7 @@ static int builtin_read(parser_t &parser, io_streams_t &streams, wchar_t **argv)
} }
if (buff.empty() && eof) { if (buff.empty() && eof) {
exit_res = 1; exit_res = STATUS_BUILTIN_ERROR;
} }
} }
@ -2119,7 +2094,7 @@ static int builtin_read(parser_t &parser, io_streams_t &streams, wchar_t **argv)
} else { } else {
env_set(argv[i], NULL, place); env_set(argv[i], NULL, place);
} }
} else { } else { // not array
size_t j = 0; size_t j = 0;
for (; i + 1 < argc; ++i) { for (; i + 1 < argc; ++i) {
if (j < bufflen) { if (j < bufflen) {
@ -2143,14 +2118,13 @@ static int builtin_read(parser_t &parser, io_streams_t &streams, wchar_t **argv)
empty = false; empty = false;
} }
env_set(argv[i], empty ? NULL : tokens.c_str(), place); env_set(argv[i], empty ? NULL : tokens.c_str(), place);
} else { } else { // not array
wcstring_range loc = wcstring_range(0, 0); wcstring_range loc = wcstring_range(0, 0);
while (i < argc) { while (i < argc) {
loc = wcstring_tok(buff, (i + 1 < argc) ? ifs : wcstring(), loc); loc = wcstring_tok(buff, (i + 1 < argc) ? ifs : wcstring(), loc);
env_set(argv[i], loc.first == wcstring::npos ? L"" : &buff.c_str()[loc.first], env_set(argv[i], loc.first == wcstring::npos ? L"" : &buff.c_str()[loc.first],
place); place);
++i; ++i;
} }
} }
@ -2831,7 +2805,8 @@ static const wcstring hist_cmd_to_string(hist_cmd_t hist_cmd) {
case HIST_SAVE: case HIST_SAVE:
return L"save"; return L"save";
default: default:
DIE("Unhandled history command"); assert(0 && "Unhandled hist_cmd_t constant!");
abort();
} }
} }
@ -2851,7 +2826,15 @@ static bool set_hist_cmd(wchar_t *const cmd, hist_cmd_t *hist_cmd, hist_cmd_t su
return true; return true;
} }
#define CHECK_FOR_UNEXPECTED_HIST_ARGS() \ #define CHECK_FOR_UNEXPECTED_HIST_OPTIONS(hist_cmd) \
if (history_search_type_defined || with_time) { \
streams.err.append_format(_(L"history: you cannot use any options with %ls command\n"), \
hist_cmd_to_string(hist_cmd).c_str()); \
status = STATUS_BUILTIN_ERROR; \
break; \
}
#define CHECK_FOR_UNEXPECTED_HIST_ARGS(hist_cmd) \
if (args.size() != 0) { \ if (args.size() != 0) { \
streams.err.append_format(BUILTIN_ERR_ARG_COUNT, cmd, \ streams.err.append_format(BUILTIN_ERR_ARG_COUNT, cmd, \
hist_cmd_to_string(hist_cmd).c_str(), 0, args.size()); \ hist_cmd_to_string(hist_cmd).c_str(), 0, args.size()); \
@ -2862,18 +2845,23 @@ static bool set_hist_cmd(wchar_t *const cmd, hist_cmd_t *hist_cmd, hist_cmd_t su
/// Manipulate history of interactive commands executed by the user. /// Manipulate history of interactive commands executed by the user.
static int builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **argv) { static int builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
wchar_t *cmd = argv[0]; wchar_t *cmd = argv[0];
;
int argc = builtin_count_args(argv); int argc = builtin_count_args(argv);
hist_cmd_t hist_cmd = HIST_NOOP; hist_cmd_t hist_cmd = HIST_NOOP;
history_search_type_t search_type = HISTORY_SEARCH_TYPE_CONTAINS; history_search_type_t search_type = (history_search_type_t)-1;
bool history_search_type_defined = false;
bool with_time = false; bool with_time = false;
static const struct woption long_options[] = { static const struct woption long_options[] = {{L"delete", no_argument, 0, 'd'},
{L"delete", no_argument, 0, 'd'}, {L"search", no_argument, 0, 's'}, {L"search", no_argument, 0, 's'},
{L"prefix", no_argument, 0, 'p'}, {L"contains", no_argument, 0, 'c'}, {L"prefix", no_argument, 0, 'p'},
{L"save", no_argument, 0, 'v'}, {L"clear", no_argument, 0, 'l'}, {L"contains", no_argument, 0, 'c'},
{L"merge", no_argument, 0, 'm'}, {L"help", no_argument, 0, 'h'}, {L"save", no_argument, 0, 'v'},
{L"with-time", no_argument, 0, 't'}, {0, 0, 0, 0}}; {L"clear", no_argument, 0, 'l'},
{L"merge", no_argument, 0, 'm'},
{L"help", no_argument, 0, 'h'},
{L"with-time", no_argument, 0, 't'},
{L"exact", no_argument, 0, 'e'},
{0, 0, 0, 0}};
history_t *history = reader_get_history(); history_t *history = reader_get_history();
// Use the default history if we have none (which happens if invoked non-interactively, e.g. // Use the default history if we have none (which happens if invoked non-interactively, e.g.
@ -2883,7 +2871,7 @@ static int builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **ar
int opt = 0; int opt = 0;
int opt_index = 0; int opt_index = 0;
wgetopter_t w; wgetopter_t w;
while ((opt = w.wgetopt_long(argc, argv, L"+dspcvlmht", long_options, &opt_index)) != EOF) { while ((opt = w.wgetopt_long(argc, argv, L"+despcvlmht", long_options, &opt_index)) != EOF) {
switch (opt) { switch (opt) {
case 's': { case 's': {
if (!set_hist_cmd(cmd, &hist_cmd, HIST_SEARCH, streams)) { if (!set_hist_cmd(cmd, &hist_cmd, HIST_SEARCH, streams)) {
@ -2917,10 +2905,17 @@ static int builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **ar
} }
case 'p': { case 'p': {
search_type = HISTORY_SEARCH_TYPE_PREFIX; search_type = HISTORY_SEARCH_TYPE_PREFIX;
history_search_type_defined = true;
break; break;
} }
case 'c': { case 'c': {
search_type = HISTORY_SEARCH_TYPE_CONTAINS; search_type = HISTORY_SEARCH_TYPE_CONTAINS;
history_search_type_defined = true;
break;
}
case 'e': {
search_type = HISTORY_SEARCH_TYPE_EXACT;
history_search_type_defined = true;
break; break;
} }
case 't': { case 't': {
@ -2945,7 +2940,12 @@ static int builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **ar
// Everything after the flags is an argument for a subcommand (e.g., a search term). // Everything after the flags is an argument for a subcommand (e.g., a search term).
const wcstring_list_t args(argv + w.woptind, argv + argc); const wcstring_list_t args(argv + w.woptind, argv + argc);
// Establish appropriate defaults for unspecified options.
if (hist_cmd == HIST_NOOP) hist_cmd = HIST_SEARCH; if (hist_cmd == HIST_NOOP) hist_cmd = HIST_SEARCH;
if (!history_search_type_defined) {
if (hist_cmd == HIST_SEARCH) search_type = HISTORY_SEARCH_TYPE_CONTAINS;
if (hist_cmd == HIST_DELETE) search_type = HISTORY_SEARCH_TYPE_EXACT;
}
int status = STATUS_BUILTIN_OK; int status = STATUS_BUILTIN_OK;
switch (hist_cmd) { switch (hist_cmd) {
@ -2956,33 +2956,44 @@ static int builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **ar
break; break;
} }
case HIST_DELETE: { case HIST_DELETE: {
// TODO: Move this code to the history module and support the other search types. At
// this time we expect the non-exact deletions to be handled only by the history
// function's interactive delete feature.
if (search_type != HISTORY_SEARCH_TYPE_EXACT) {
streams.err.append_format(_(L"builtin history --delete only supports --exact\n"));
status = STATUS_BUILTIN_ERROR;
break;
}
for (wcstring_list_t::const_iterator iter = args.begin(); iter != args.end(); ++iter) { for (wcstring_list_t::const_iterator iter = args.begin(); iter != args.end(); ++iter) {
wcstring delete_string = *iter; wcstring delete_string = *iter;
if (delete_string[0] == '"' && delete_string[delete_string.length() - 1] == '"') if (delete_string[0] == '"' && delete_string[delete_string.length() - 1] == '"') {
delete_string = delete_string.substr(1, delete_string.length() - 2); delete_string = delete_string.substr(1, delete_string.length() - 2);
}
history->remove(delete_string); history->remove(delete_string);
} }
break; break;
} }
case HIST_CLEAR: { case HIST_CLEAR: {
CHECK_FOR_UNEXPECTED_HIST_ARGS(); CHECK_FOR_UNEXPECTED_HIST_OPTIONS(hist_cmd)
CHECK_FOR_UNEXPECTED_HIST_ARGS(hist_cmd)
history->clear(); history->clear();
history->save(); history->save();
break; break;
} }
case HIST_MERGE: { case HIST_MERGE: {
CHECK_FOR_UNEXPECTED_HIST_ARGS(); CHECK_FOR_UNEXPECTED_HIST_OPTIONS(hist_cmd)
CHECK_FOR_UNEXPECTED_HIST_ARGS(hist_cmd)
history->incorporate_external_changes(); history->incorporate_external_changes();
break; break;
} }
case HIST_SAVE: { case HIST_SAVE: {
CHECK_FOR_UNEXPECTED_HIST_ARGS(); CHECK_FOR_UNEXPECTED_HIST_OPTIONS(hist_cmd)
CHECK_FOR_UNEXPECTED_HIST_ARGS(hist_cmd)
history->save(); history->save();
break; break;
} }
default: { case HIST_NOOP: {
DIE("Unhandled history command"); DIE("Unexpected HIST_NOOP seen");
break; break;
} }
} }
@ -3052,7 +3063,7 @@ int builtin_fish_realpath(parser_t &parser, io_streams_t &streams, wchar_t **arg
int argc = builtin_count_args(argv); int argc = builtin_count_args(argv);
if (argc != 2) { if (argc != 2) {
streams.err.append_format(_(L"%ls: Expected one argument, got %d\n"), argv[0], argc - 1); builtin_print_help(parser, streams, argv[0], streams.out);
return STATUS_BUILTIN_ERROR; return STATUS_BUILTIN_ERROR;
} }
@ -3062,7 +3073,7 @@ int builtin_fish_realpath(parser_t &parser, io_streams_t &streams, wchar_t **arg
streams.out.append(real_path); streams.out.append(real_path);
free((void *)real_path); free((void *)real_path);
} else { } else {
// The path isn't a simple filename and couldn't be resolved to an absolute path. // We don't actually know why it failed. We should check errno
streams.err.append_format(_(L"%ls: Invalid path: %ls\n"), argv[0], argv[1]); streams.err.append_format(_(L"%ls: Invalid path: %ls\n"), argv[0], argv[1]);
return STATUS_BUILTIN_ERROR; return STATUS_BUILTIN_ERROR;
} }
@ -3081,7 +3092,7 @@ static const builtin_data_t builtin_datas[] = {
{L"[", &builtin_test, N_(L"Test a condition")}, {L"[", &builtin_test, N_(L"Test a condition")},
#if 0 #if 0
// Disabled for the 2.2.0 release: https://github.com/fish-shell/fish-shell/issues/1809. // Disabled for the 2.2.0 release: https://github.com/fish-shell/fish-shell/issues/1809.
{ L"__fish_parse", &builtin_parse, N_(L"Try out the new parser") }, { L"__fish_parse", &builtin_parse, N_(L"Try out the new parser") },
#endif #endif
{L"and", &builtin_generic, N_(L"Execute command if previous command suceeded")}, {L"and", &builtin_generic, N_(L"Execute command if previous command suceeded")},
{L"begin", &builtin_generic, N_(L"Create a block of code")}, {L"begin", &builtin_generic, N_(L"Create a block of code")},
@ -3137,6 +3148,14 @@ static const builtin_data_t builtin_datas[] = {
#define BUILTIN_COUNT (sizeof builtin_datas / sizeof *builtin_datas) #define BUILTIN_COUNT (sizeof builtin_datas / sizeof *builtin_datas)
/// Look up a builtin_data_t for a specified builtin
///
/// @param name
/// Name of the builtin
///
/// @return
/// Pointer to a builtin_data_t
///
static const builtin_data_t *builtin_lookup(const wcstring &name) { static const builtin_data_t *builtin_lookup(const wcstring &name) {
const builtin_data_t *array_end = builtin_datas + BUILTIN_COUNT; const builtin_data_t *array_end = builtin_datas + BUILTIN_COUNT;
const builtin_data_t *found = std::lower_bound(builtin_datas, array_end, name); const builtin_data_t *found = std::lower_bound(builtin_datas, array_end, name);
@ -3146,35 +3165,37 @@ static const builtin_data_t *builtin_lookup(const wcstring &name) {
return NULL; return NULL;
} }
/// Initialize builtin data.
void builtin_init() { void builtin_init() {
for (size_t i = 0; i < BUILTIN_COUNT; i++) { for (size_t i = 0; i < BUILTIN_COUNT; i++) {
intern_static(builtin_datas[i].name); intern_static(builtin_datas[i].name);
} }
} }
/// Destroy builtin data.
void builtin_destroy() {} void builtin_destroy() {}
int builtin_exists(const wcstring &cmd) { return !!builtin_lookup(cmd); } /// Is there a builtin command with the given name?
bool builtin_exists(const wcstring &cmd) { return !!builtin_lookup(cmd); }
/// Return true if the specified builtin should handle it's own help, false otherwise. /// If builtin takes care of printing help itself
static int internal_help(const wchar_t *cmd) { static bool builtin_handles_help(const wchar_t *cmd) {
CHECK(cmd, 0); CHECK(cmd, 0);
return contains(cmd, L"for", L"while", L"function", L"if", L"end", L"switch", L"case", L"count", return contains(cmd, L"for", L"while", L"function", L"if", L"end", L"switch", L"case", L"count",
L"printf"); L"printf");
} }
/// Execute a builtin command
int builtin_run(parser_t &parser, const wchar_t *const *argv, io_streams_t &streams) { int builtin_run(parser_t &parser, const wchar_t *const *argv, io_streams_t &streams) {
int (*cmd)(parser_t & parser, io_streams_t & streams, const wchar_t *const *argv) = NULL; int (*cmd)(parser_t & parser, io_streams_t & streams, const wchar_t *const *argv) = NULL;
if (argv == NULL || argv[0] == NULL) return STATUS_BUILTIN_ERROR;
CHECK(argv, STATUS_BUILTIN_ERROR);
CHECK(argv[0], STATUS_BUILTIN_ERROR);
const builtin_data_t *data = builtin_lookup(argv[0]); const builtin_data_t *data = builtin_lookup(argv[0]);
cmd = (int (*)(parser_t & parser, io_streams_t & streams, const wchar_t *const *))( cmd = (int (*)(parser_t & parser, io_streams_t & streams, const wchar_t *const *))(
data ? data->func : NULL); data ? data->func : NULL);
if (argv[1] != 0 && !internal_help(argv[0])) { if (argv[1] != NULL && !builtin_handles_help(argv[0])) {
if (argv[2] == 0 && (parse_util_argument_is_help(argv[1], 0))) { if (argv[2] == NULL && (parse_util_argument_is_help(argv[1], 0))) {
builtin_print_help(parser, streams, argv[0], streams.out); builtin_print_help(parser, streams, argv[0], streams.out);
return STATUS_BUILTIN_OK; return STATUS_BUILTIN_OK;
} }
@ -3188,6 +3209,7 @@ int builtin_run(parser_t &parser, const wchar_t *const *argv, io_streams_t &stre
return STATUS_BUILTIN_ERROR; return STATUS_BUILTIN_ERROR;
} }
/// Returns a list of all builtin names.
wcstring_list_t builtin_get_names(void) { wcstring_list_t builtin_get_names(void) {
wcstring_list_t result; wcstring_list_t result;
result.reserve(BUILTIN_COUNT); result.reserve(BUILTIN_COUNT);
@ -3197,6 +3219,7 @@ wcstring_list_t builtin_get_names(void) {
return result; return result;
} }
/// Insert all builtin names into list.
void builtin_get_names(std::vector<completion_t> *list) { void builtin_get_names(std::vector<completion_t> *list) {
assert(list != NULL); assert(list != NULL);
list->reserve(list->size() + BUILTIN_COUNT); list->reserve(list->size() + BUILTIN_COUNT);
@ -3205,6 +3228,7 @@ void builtin_get_names(std::vector<completion_t> *list) {
} }
} }
/// Return a one-line description of the specified builtin.
wcstring builtin_get_desc(const wcstring &name) { wcstring builtin_get_desc(const wcstring &name) {
wcstring result; wcstring result;
const builtin_data_t *builtin = builtin_lookup(name); const builtin_data_t *builtin = builtin_lookup(name);

View file

@ -12,79 +12,86 @@ class parser_t;
class output_stream_t; class output_stream_t;
struct io_streams_t; struct io_streams_t;
/// Data structure to describe a builtin.
struct builtin_data_t {
// Name of the builtin.
const wchar_t *name;
// Function pointer tothe builtin implementation.
int (*func)(parser_t &parser, io_streams_t &streams, wchar_t **argv);
// Description of what the builtin does.
const wchar_t *desc;
bool operator<(const wcstring &) const;
bool operator<(const builtin_data_t *) const;
};
/// The default prompt for the read command.
#define DEFAULT_READ_PROMPT L"set_color green; echo -n read; set_color normal; echo -n \"> \""
/// The mode name to pass to history and input.
#define READ_MODE_NAME L"fish_read"
enum { COMMAND_NOT_BUILTIN, BUILTIN_REGULAR, BUILTIN_FUNCTION }; enum { COMMAND_NOT_BUILTIN, BUILTIN_REGULAR, BUILTIN_FUNCTION };
// Error message on missing argument. /// Error message on missing argument.
#define BUILTIN_ERR_MISSING _(L"%ls: Expected argument for option %ls\n") #define BUILTIN_ERR_MISSING _(L"%ls: Expected argument for option %ls\n")
// Error message on invalid combination of options. /// Error message on invalid combination of options.
#define BUILTIN_ERR_COMBO _(L"%ls: Invalid combination of options\n") #define BUILTIN_ERR_COMBO _(L"%ls: Invalid combination of options\n")
// Error message on invalid combination of options. /// Error message on invalid combination of options.
#define BUILTIN_ERR_COMBO2 _(L"%ls: Invalid combination of options,\n%ls\n") #define BUILTIN_ERR_COMBO2 _(L"%ls: Invalid combination of options,\n%ls\n")
// Error message on multiple scope levels for variables. /// Error message on multiple scope levels for variables.
#define BUILTIN_ERR_GLOCAL \ #define BUILTIN_ERR_GLOCAL \
_(L"%ls: Variable scope can only be one of universal, global and local\n") _(L"%ls: Variable scope can only be one of universal, global and local\n")
// Error message for specifying both export and unexport to set/read. /// Error message for specifying both export and unexport to set/read.
#define BUILTIN_ERR_EXPUNEXP _(L"%ls: Variable can't be both exported and unexported\n") #define BUILTIN_ERR_EXPUNEXP _(L"%ls: Variable can't be both exported and unexported\n")
// Error message for unknown switch. /// Error message for unknown switch.
#define BUILTIN_ERR_UNKNOWN _(L"%ls: Unknown option '%ls'\n") #define BUILTIN_ERR_UNKNOWN _(L"%ls: Unknown option '%ls'\n")
// Error message for unexpected args. /// Error message for unexpected args.
#define BUILTIN_ERR_ARG_COUNT _(L"%ls: %ls command expected %d args, got %d\n") #define BUILTIN_ERR_ARG_COUNT _(L"%ls: %ls command expected %d args, got %d\n")
// Error message for invalid character in variable name. /// Error message for invalid character in variable name.
#define BUILTIN_ERR_VARCHAR \ #define BUILTIN_ERR_VARCHAR \
_(L"%ls: Invalid character '%lc' in variable name. Only alphanumerical characters and " \ _(L"%ls: Invalid character '%lc' in variable name. Only alphanumerical characters and " \
L"underscores are valid in a variable name.\n") L"underscores are valid in a variable name.\n")
// Error message for invalid (empty) variable name. /// Error message for invalid (empty) variable name.
#define BUILTIN_ERR_VARNAME_ZERO _(L"%ls: Variable name can not be the empty string\n") #define BUILTIN_ERR_VARNAME_ZERO _(L"%ls: Variable name can not be the empty string\n")
// Error message when too many arguments are supplied to a builtin. /// Error message when too many arguments are supplied to a builtin.
#define BUILTIN_ERR_TOO_MANY_ARGUMENTS _(L"%ls: Too many arguments\n") #define BUILTIN_ERR_TOO_MANY_ARGUMENTS _(L"%ls: Too many arguments\n")
/// Error message when number expected
#define BUILTIN_ERR_NOT_NUMBER _(L"%ls: Argument '%ls' is not a number\n") #define BUILTIN_ERR_NOT_NUMBER _(L"%ls: Argument '%ls' is not a number\n")
// Initialize builtin data. /// The send stuff to foreground message.
#define FG_MSG _(L"Send job %d, '%ls' to foreground\n")
void builtin_init(); void builtin_init();
// Destroy builtin data.
void builtin_destroy(); void builtin_destroy();
bool builtin_exists(const wcstring &cmd);
// Is there a builtin command with the given name?
int builtin_exists(const wcstring &cmd);
// Execute a builtin command
//
// \param parser The parser being used
// \param argv Array containing the command and parameters of the builtin. The list is terminated
// by a null pointer. This syntax resembles the syntax for exec.
// \param io the io redirections to perform on this builtin.
//
// \return the exit status of the builtin command
int builtin_run(parser_t &parser, const wchar_t *const *argv, io_streams_t &streams); int builtin_run(parser_t &parser, const wchar_t *const *argv, io_streams_t &streams);
// Returns a list of all builtin names.
wcstring_list_t builtin_get_names(); wcstring_list_t builtin_get_names();
// Insert all builtin names into list.
void builtin_get_names(std::vector<completion_t> *list); void builtin_get_names(std::vector<completion_t> *list);
// Return a one-line description of the specified builtin.
wcstring builtin_get_desc(const wcstring &b); wcstring builtin_get_desc(const wcstring &b);
// Support for setting and removing transient command lines. This is used by 'complete -C' in order /// Support for setting and removing transient command lines. This is used by
// to make the commandline builtin operate on the string to complete instead of operating on /// 'complete -C' in order to make the commandline builtin operate on the string
// whatever is to be completed. It's also used by completion wrappers, to allow a command to appear /// to complete instead of operating on whatever is to be completed. It's also
// as the command being wrapped for the purposes of completion. /// used by completion wrappers, to allow a command to appear as the command
// /// being wrapped for the purposes of completion.
// Instantiating an instance of builtin_commandline_scoped_transient_t pushes the command as the new ///
// transient commandline. The destructor removes it. It will assert if construction/destruction does /// Instantiating an instance of builtin_commandline_scoped_transient_t pushes
// not happen in a stack-like (LIFO) order. /// the command as the new transient commandline. The destructor removes it. It
/// will assert if construction/destruction does not happen in a stack-like
/// (LIFO) order.
class builtin_commandline_scoped_transient_t { class builtin_commandline_scoped_transient_t {
size_t token; size_t token;
@ -93,30 +100,20 @@ class builtin_commandline_scoped_transient_t {
~builtin_commandline_scoped_transient_t(); ~builtin_commandline_scoped_transient_t();
}; };
// Run the __fish_print_help function to obtain the help information for the specified command.
wcstring builtin_help_get(parser_t &parser, const wchar_t *cmd); wcstring builtin_help_get(parser_t &parser, const wchar_t *cmd);
// Defines a function. Returns 0 on success. args should NOT contain 'function' as the first
// argument as the parser treats it as a keyword.
int builtin_function(parser_t &parser, io_streams_t &streams, const wcstring_list_t &c_args, int builtin_function(parser_t &parser, io_streams_t &streams, const wcstring_list_t &c_args,
const wcstring &contents, int definition_line_offset, wcstring *out_err); const wcstring &contents, int definition_line_offset, wcstring *out_err);
// Print help for the specified builtin. If \c b is sb_err, also print the line information.
void builtin_print_help(parser_t &parser, io_streams_t &streams, const wchar_t *cmd, void builtin_print_help(parser_t &parser, io_streams_t &streams, const wchar_t *cmd,
output_stream_t &b); output_stream_t &b);
// Counts the number of non null pointers in the specified array.
int builtin_count_args(const wchar_t *const *argv); int builtin_count_args(const wchar_t *const *argv);
// Perform error reporting for encounter with unknown option.
void builtin_unknown_option(parser_t &parser, io_streams_t &streams, const wchar_t *cmd, void builtin_unknown_option(parser_t &parser, io_streams_t &streams, const wchar_t *cmd,
const wchar_t *opt); const wchar_t *opt);
// Perform error reporting for encounter with missing argument.
void builtin_missing_argument(parser_t &parser, io_streams_t &streams, const wchar_t *cmd, void builtin_missing_argument(parser_t &parser, io_streams_t &streams, const wchar_t *cmd,
const wchar_t *opt); const wchar_t *opt);
// This function works like wperror, but it prints its result into the streams.err string instead
// to stderr. Used by the builtin commands.
void builtin_wperror(const wchar_t *s, io_streams_t &streams); void builtin_wperror(const wchar_t *s, io_streams_t &streams);
#endif #endif

View file

@ -264,11 +264,20 @@ uintmax_t raw_string_to_scalar_type(const wchar_t *s, wchar_t **end) {
template <> template <>
long double raw_string_to_scalar_type(const wchar_t *s, wchar_t **end) { long double raw_string_to_scalar_type(const wchar_t *s, wchar_t **end) {
// Forcing the locale to C is questionable but it's what the old C_STRTOD() that I inlined here
// as part of changing how locale management is done by fish.
char *old_locale = setlocale(LC_NUMERIC, "C");
double val = wcstod(s, end); double val = wcstod(s, end);
setlocale(LC_NUMERIC, old_locale); if (**end == L'\0') return val;
// The conversion using the user's locale failed. That may be due to the string not being a
// valid floating point value. It could also be due to the locale using different separator
// characters than the normal english convention. So try again by forcing the use of a locale
// that employs the english convention for writing floating point numbers.
//
// TODO: switch to the wcstod_l() function to avoid changing the global locale.
char *saved_locale = strdup(setlocale(LC_NUMERIC, NULL));
setlocale(LC_NUMERIC, "C");
val = wcstod(s, end);
setlocale(LC_NUMERIC, saved_locale);
free(saved_locale);
return val; return val;
} }

View file

@ -189,7 +189,7 @@ static wcstring str2wcs_internal(const char *in, const size_t in_len) {
mbstate_t state = {}; mbstate_t state = {};
while (in_pos < in_len) { while (in_pos < in_len) {
bool use_encode_direct = false; bool use_encode_direct = false;
size_t ret; size_t ret = 0;
wchar_t wc = 0; wchar_t wc = 0;
if ((in[in_pos] & 0xF8) == 0xF8) { if ((in[in_pos] & 0xF8) == 0xF8) {

View file

@ -27,10 +27,6 @@
#define OS_IS_CYGWIN #define OS_IS_CYGWIN
#endif #endif
/// Avoid writing the type name twice in a common "static_cast-initialization". Caveat: This doesn't
/// work with type names containing commas!
#define CAST_INIT(type, dst, src) type dst = static_cast<type>(src)
// Common string type. // Common string type.
typedef std::wstring wcstring; typedef std::wstring wcstring;
typedef std::vector<wcstring> wcstring_list_t; typedef std::vector<wcstring> wcstring_list_t;
@ -131,14 +127,19 @@ enum selection_direction_t {
inline bool selection_direction_is_cardinal(selection_direction_t dir) { inline bool selection_direction_is_cardinal(selection_direction_t dir) {
switch (dir) { switch (dir) {
case direction_north: case direction_north:
case direction_page_north:
case direction_east: case direction_east:
case direction_page_south:
case direction_south: case direction_south:
case direction_west: { case direction_west:
case direction_page_north:
case direction_page_south: {
return true; return true;
} }
default: { return false; } case direction_next:
case direction_prev:
case direction_deselect: {
return false;
}
default: { abort(); }
} }
} }

View file

@ -123,8 +123,7 @@ typedef struct complete_entry_opt {
} }
} complete_entry_opt_t; } complete_entry_opt_t;
/// Last value used in the order field of completion_entry_t.
// Last value used in the order field of completion_entry_t.
static unsigned int kCompleteOrder = 0; static unsigned int kCompleteOrder = 0;
/// Struct describing a command completion. /// Struct describing a command completion.
@ -170,7 +169,7 @@ struct completion_entry_set_comparer {
typedef std::set<completion_entry_t, completion_entry_set_comparer> completion_entry_set_t; typedef std::set<completion_entry_t, completion_entry_set_comparer> completion_entry_set_t;
static completion_entry_set_t completion_set; static completion_entry_set_t completion_set;
// Comparison function to sort completions by their order field. /// Comparison function to sort completions by their order field.
static bool compare_completions_by_order(const completion_entry_t *p1, static bool compare_completions_by_order(const completion_entry_t *p1,
const completion_entry_t *p2) { const completion_entry_t *p2) {
return p1->order < p2->order; return p1->order < p2->order;
@ -203,7 +202,7 @@ static complete_flags_t resolve_auto_space(const wcstring &comp, complete_flags_
return new_flags; return new_flags;
} }
// completion_t functions. Note that the constructor resolves flags! /// completion_t functions. Note that the constructor resolves flags!
completion_t::completion_t(const wcstring &comp, const wcstring &desc, string_fuzzy_match_t mat, completion_t::completion_t(const wcstring &comp, const wcstring &desc, string_fuzzy_match_t mat,
complete_flags_t flags_val) complete_flags_t flags_val)
: completion(comp), description(desc), match(mat), flags(resolve_auto_space(comp, flags_val)) {} : completion(comp), description(desc), match(mat), flags(resolve_auto_space(comp, flags_val)) {}
@ -517,21 +516,31 @@ static void parse_cmd_string(const wcstring &str, wcstring &path, wcstring &cmd)
} }
} }
/// Copy any strings in possible_comp which have the specified prefix to the completer's completion /// Copy any strings in possible_comp which have the specified prefix to the
/// array. The prefix may contain wildcards. The output will consist of completion_t structs. /// completer's completion array. The prefix may contain wildcards. The output
/// will consist of completion_t structs.
/// ///
/// There are three ways to specify descriptions for each completion. Firstly, if a description has /// There are three ways to specify descriptions for each completion. Firstly,
/// already been added to the completion, it is _not_ replaced. Secondly, if the desc_func function /// if a description has already been added to the completion, it is _not_
/// is specified, use it to determine a dynamic completion. Thirdly, if none of the above are /// replaced. Secondly, if the desc_func function is specified, use it to
/// available, the desc string is used as a description. /// determine a dynamic completion. Thirdly, if none of the above are available,
/// the desc string is used as a description.
/// ///
/// \param wc_escaped the prefix, possibly containing wildcards. The wildcard should not have been /// @param wc_escaped
/// unescaped, i.e. '*' should be used for any string, not the ANY_STRING character. /// the prefix, possibly containing wildcards. The wildcard should not have
/// \param desc the default description, used for completions with no embedded description. The /// been unescaped, i.e. '*' should be used for any string, not the
/// description _may_ contain a COMPLETE_SEP character, if not, one will be prefixed to it /// ANY_STRING character.
/// \param desc_func the function that generates a description for those completions witout an /// @param desc
/// embedded description /// the default description, used for completions with no embedded
/// \param possible_comp the list of possible completions to iterate over /// description. The description _may_ contain a COMPLETE_SEP character, if
/// not, one will be prefixed to it
/// @param desc_func
/// the function that generates a description for those completions witout an
/// embedded description
/// @param possible_comp
/// the list of possible completions to iterate over
/// @param flags
/// The flags
void completer_t::complete_strings(const wcstring &wc_escaped, const wchar_t *desc, void completer_t::complete_strings(const wcstring &wc_escaped, const wchar_t *desc,
wcstring (*desc_func)(const wcstring &), wcstring (*desc_func)(const wcstring &),
std::vector<completion_t> &possible_comp, std::vector<completion_t> &possible_comp,
@ -821,7 +830,7 @@ static bool short_ok(const wcstring &arg, const complete_entry_opt_t *entry,
return result; return result;
} }
// Load command-specific completions for the specified command. /// Load command-specific completions for the specified command.
static void complete_load(const wcstring &name, bool reload) { static void complete_load(const wcstring &name, bool reload) {
// We have to load this as a function, since it may define a --wraps or signature. // We have to load this as a function, since it may define a --wraps or signature.
// See issue #2466. // See issue #2466.
@ -829,7 +838,7 @@ static void complete_load(const wcstring &name, bool reload) {
completion_autoloader.load(name, reload); completion_autoloader.load(name, reload);
} }
// Performed on main thread, from background thread. Return type is ignored. /// Performed on main thread, from background thread. Return type is ignored.
static int complete_load_no_reload(wcstring *name) { static int complete_load_no_reload(wcstring *name) {
assert(name != NULL); assert(name != NULL);
ASSERT_IS_MAIN_THREAD(); ASSERT_IS_MAIN_THREAD();
@ -1543,7 +1552,7 @@ wcstring complete_print() {
return out; return out;
} }
// Completion "wrapper" support. The map goes from wrapping-command to wrapped-command-list. /// Completion "wrapper" support. The map goes from wrapping-command to wrapped-command-list.
static pthread_mutex_t wrapper_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t wrapper_lock = PTHREAD_MUTEX_INITIALIZER;
typedef std::map<wcstring, wcstring_list_t> wrapper_map_t; typedef std::map<wcstring, wcstring_list_t> wrapper_map_t;
static wrapper_map_t &wrap_map() { static wrapper_map_t &wrap_map() {
@ -1557,7 +1566,8 @@ static wrapper_map_t &wrap_map() {
return *wrapper_map; return *wrapper_map;
} }
// Add a new target that is wrapped by command. Example: __fish_sgrep (command) wraps grep (target). /// Add a new target that is wrapped by command. Example: __fish_sgrep (command) wraps grep
/// (target).
bool complete_add_wrapper(const wcstring &command, const wcstring &new_target) { bool complete_add_wrapper(const wcstring &command, const wcstring &new_target) {
if (command.empty() || new_target.empty()) { if (command.empty() || new_target.empty()) {
return false; return false;

View file

@ -280,7 +280,10 @@ static void universal_callback(fish_message_type_t type, const wchar_t *name, co
str = L"ERASE"; str = L"ERASE";
break; break;
} }
default: { break; } default: {
assert(0 && "Unhandled fish_message_type_t constant!");
abort();
}
} }
if (str) { if (str) {

View file

@ -570,18 +570,16 @@ bool env_universal_t::open_temporary_file(const wcstring &directory, wcstring *o
assert(!string_suffixes_string(L"/", directory)); assert(!string_suffixes_string(L"/", directory));
bool success = false; bool success = false;
int saved_errno; int saved_errno = 0;
const wcstring tmp_name_template = directory + L"/fishd.tmp.XXXXXX"; const wcstring tmp_name_template = directory + L"/fishd.tmp.XXXXXX";
wcstring tmp_name; wcstring tmp_name;
for (size_t attempt = 0; attempt < 10 && !success; attempt++) { for (size_t attempt = 0; attempt < 10 && !success; attempt++) {
int result_fd = -1;
char *narrow_str = wcs2str(tmp_name_template.c_str()); char *narrow_str = wcs2str(tmp_name_template.c_str());
#if HAVE_MKOSTEMP #if HAVE_MKOSTEMP
result_fd = mkostemp(narrow_str, O_CLOEXEC); int result_fd = mkostemp(narrow_str, O_CLOEXEC);
#else #else
// cppcheck-suppress redundantAssignment int result_fd = mkstemp(narrow_str);
result_fd = mkstemp(narrow_str);
if (result_fd != -1) { if (result_fd != -1) {
fcntl(result_fd, F_SETFD, FD_CLOEXEC); fcntl(result_fd, F_SETFD, FD_CLOEXEC);
} }
@ -595,7 +593,7 @@ bool env_universal_t::open_temporary_file(const wcstring &directory, wcstring *o
} }
if (!success) { if (!success) {
report_error(saved_errno, L"Unable to open file '%ls'", out_path->c_str()); report_error(saved_errno, L"Unable to open temporary file '%ls'", out_path->c_str());
} }
return success; return success;
} }
@ -623,9 +621,10 @@ bool env_universal_t::open_and_acquire_lock(const wcstring &path, int *out_fd) {
continue; continue;
} }
#ifdef O_EXLOCK #ifdef O_EXLOCK
else if (err == EOPNOTSUPP) { else if (err == ENOTSUP || err == EOPNOTSUPP) {
// Filesystem probably does not support locking. Clear the flag and try again. Note // Filesystem probably does not support locking. Clear the flag and try again. Note
// that we try taking the lock via flock anyways. // that we try taking the lock via flock anyways. Note that on Linux the two errno
// symbols have the same value but on BSD they're different.
flags &= ~O_EXLOCK; flags &= ~O_EXLOCK;
needs_lock = true; needs_lock = true;
continue; continue;
@ -933,10 +932,10 @@ static bool get_mac_address(unsigned char macaddr[MAC_ADDRESS_MAX_LEN],
if (getifaddrs(&ifap) == 0) { if (getifaddrs(&ifap) == 0) {
for (const ifaddrs *p = ifap; p; p = p->ifa_next) { for (const ifaddrs *p = ifap; p; p = p->ifa_next) {
if (p->ifa_addr->sa_family == AF_LINK) { if (p->ifa_addr && p->ifa_addr->sa_family == AF_LINK) {
if (p->ifa_name && p->ifa_name[0] && if (p->ifa_name && p->ifa_name[0] &&
!strcmp((const char *)p->ifa_name, interface)) { !strcmp((const char *)p->ifa_name, interface)) {
const sockaddr_dl &sdl = *(sockaddr_dl *)p->ifa_addr; const sockaddr_dl &sdl = *reinterpret_cast<sockaddr_dl *>(p->ifa_addr);
size_t alen = sdl.sdl_alen; size_t alen = sdl.sdl_alen;
if (alen > MAC_ADDRESS_MAX_LEN) alen = MAC_ADDRESS_MAX_LEN; if (alen > MAC_ADDRESS_MAX_LEN) alen = MAC_ADDRESS_MAX_LEN;
@ -1045,7 +1044,7 @@ class universal_notifier_shmem_poller_t : public universal_notifier_t {
// Memory map the region. // Memory map the region.
if (!errored) { if (!errored) {
void *addr = mmap(NULL, sizeof(universal_notifier_shmem_t), PROT_READ | PROT_WRITE, void *addr = mmap(NULL, sizeof(universal_notifier_shmem_t), PROT_READ | PROT_WRITE,
MAP_FILE | MAP_SHARED, fd, 0); MAP_SHARED, fd, 0);
if (addr == MAP_FAILED) { if (addr == MAP_FAILED) {
int err = errno; int err = errno;
report_error(err, L"Unable to memory map shared memory object with path '%s'", report_error(err, L"Unable to memory map shared memory object with path '%s'",

View file

@ -105,7 +105,7 @@ static bool redirection_is_to_real_file(const io_data_t *io) {
bool result = false; bool result = false;
if (io != NULL && io->io_mode == IO_FILE) { if (io != NULL && io->io_mode == IO_FILE) {
// It's a file redirection. Compare the path to /dev/null. // It's a file redirection. Compare the path to /dev/null.
CAST_INIT(const io_file_t *, io_file, io); const io_file_t *io_file = static_cast<const io_file_t *>(io);
const char *path = io_file->filename_cstr; const char *path = io_file->filename_cstr;
if (strcmp(path, "/dev/null") != 0) { if (strcmp(path, "/dev/null") != 0) {
// It's not /dev/null. // It's not /dev/null.
@ -268,7 +268,7 @@ static bool io_transmogrify(const io_chain_t &in_chain, io_chain_t *out_chain,
case IO_FILE: { case IO_FILE: {
// Transmogrify file redirections. // Transmogrify file redirections.
int fd; int fd;
CAST_INIT(io_file_t *, in_file, in.get()); io_file_t *in_file = static_cast<io_file_t *>(in.get());
if ((fd = open(in_file->filename_cstr, in_file->flags, OPEN_MASK)) == -1) { if ((fd = open(in_file->filename_cstr, in_file->flags, OPEN_MASK)) == -1) {
debug(1, FILE_ERROR, in_file->filename_cstr); debug(1, FILE_ERROR, in_file->filename_cstr);
@ -283,9 +283,8 @@ static bool io_transmogrify(const io_chain_t &in_chain, io_chain_t *out_chain,
} }
default: { default: {
// Unknown type, should never happen. // Unknown type, should never happen.
fprintf(stderr, "Unknown io_mode %ld\n", (long)in->io_mode); assert(0 && "Unhandled io_mode constant");
abort(); abort();
break;
} }
} }
@ -405,7 +404,7 @@ void exec_job(parser_t &parser, job_t *j) {
const shared_ptr<io_data_t> &io = all_ios.at(idx); const shared_ptr<io_data_t> &io = all_ios.at(idx);
if ((io->io_mode == IO_BUFFER)) { if ((io->io_mode == IO_BUFFER)) {
CAST_INIT(io_buffer_t *, io_buffer, io.get()); io_buffer_t *io_buffer = static_cast<io_buffer_t *>(io.get());
assert(!io_buffer->is_input); assert(!io_buffer->is_input);
} }
} }
@ -451,7 +450,7 @@ void exec_job(parser_t &parser, job_t *j) {
for (size_t i = 0; i < all_ios.size(); i++) { for (size_t i = 0; i < all_ios.size(); i++) {
io_data_t *io = all_ios.at(i).get(); io_data_t *io = all_ios.at(i).get();
if (io->io_mode == IO_BUFFER) { if (io->io_mode == IO_BUFFER) {
CAST_INIT(io_buffer_t *, io_buffer, io); io_buffer_t *io_buffer = static_cast<io_buffer_t *>(io);
if (!io_buffer->avoid_conflicts_with_io_chain(all_ios)) { if (!io_buffer->avoid_conflicts_with_io_chain(all_ios)) {
// We could not avoid conflicts, probably due to fd exhaustion. Mark an error. // We could not avoid conflicts, probably due to fd exhaustion. Mark an error.
exec_error = true; exec_error = true;
@ -634,7 +633,6 @@ void exec_job(parser_t &parser, job_t *j) {
const wcstring func_name = p->argv0(); const wcstring func_name = p->argv0();
wcstring def; wcstring def;
bool function_exists = function_get_definition(func_name, &def); bool function_exists = function_get_definition(func_name, &def);
bool shadow_scope = function_get_shadow_scope(func_name); bool shadow_scope = function_get_shadow_scope(func_name);
const std::map<wcstring, env_var_t> inherit_vars = const std::map<wcstring, env_var_t> inherit_vars =
function_get_inherit_vars(func_name); function_get_inherit_vars(func_name);
@ -716,7 +714,7 @@ void exec_job(parser_t &parser, job_t *j) {
if (in) { if (in) {
switch (in->io_mode) { switch (in->io_mode) {
case IO_FD: { case IO_FD: {
CAST_INIT(const io_fd_t *, in_fd, in.get()); const io_fd_t *in_fd = static_cast<const io_fd_t *>(in.get());
// Ignore user-supplied fd redirections from an fd other than the // Ignore user-supplied fd redirections from an fd other than the
// standard ones. e.g. in source <&3 don't actually read from fd 3, // standard ones. e.g. in source <&3 don't actually read from fd 3,
// which is internal to fish. We still respect this redirection in // which is internal to fish. We still respect this redirection in
@ -731,13 +729,13 @@ void exec_job(parser_t &parser, job_t *j) {
break; break;
} }
case IO_PIPE: { case IO_PIPE: {
CAST_INIT(const io_pipe_t *, in_pipe, in.get()); const io_pipe_t *in_pipe = static_cast<const io_pipe_t *>(in.get());
local_builtin_stdin = in_pipe->pipe_fd[0]; local_builtin_stdin = in_pipe->pipe_fd[0];
break; break;
} }
case IO_FILE: { case IO_FILE: {
// Do not set CLO_EXEC because child needs access. // Do not set CLO_EXEC because child needs access.
CAST_INIT(const io_file_t *, in_file, in.get()); const io_file_t *in_file = static_cast<const io_file_t *>(in.get());
local_builtin_stdin = local_builtin_stdin =
open(in_file->filename_cstr, in_file->flags, OPEN_MASK); open(in_file->filename_cstr, in_file->flags, OPEN_MASK);
if (local_builtin_stdin == -1) { if (local_builtin_stdin == -1) {
@ -933,8 +931,10 @@ void exec_job(parser_t &parser, job_t *j) {
// performance quite a bit in complex completion code. // performance quite a bit in complex completion code.
debug(3, L"Skipping fork: buffered output for internal builtin '%ls'", debug(3, L"Skipping fork: buffered output for internal builtin '%ls'",
p->argv0()); p->argv0());
CAST_INIT(io_buffer_t *, io_buffer, stdout_io.get());
io_buffer_t *io_buffer = static_cast<io_buffer_t *>(stdout_io.get());
const std::string res = wcs2string(builtin_io_streams->out.buffer()); const std::string res = wcs2string(builtin_io_streams->out.buffer());
io_buffer->out_buffer_append(res.data(), res.size()); io_buffer->out_buffer_append(res.data(), res.size());
fork_was_skipped = true; fork_was_skipped = true;
} else if (stdout_io.get() == NULL && stderr_io.get() == NULL) { } else if (stdout_io.get() == NULL && stderr_io.get() == NULL) {

View file

@ -1603,7 +1603,7 @@ bool expand_abbreviation(const wcstring &src, wcstring *output) {
// See if this command matches. // See if this command matches.
if (line.compare(0, cmd_end, src) == 0) { if (line.compare(0, cmd_end, src) == 0) {
// Success. Set output to everythign past the end of the string. // Success. Set output to everything past the end of the string.
if (output != NULL) output->assign(line, separator + 1, wcstring::npos); if (output != NULL) output->assign(line, separator + 1, wcstring::npos);
result = true; result = true;

View file

@ -451,6 +451,11 @@ int main(int argc, char **argv) {
// struct stat tmp; // struct stat tmp;
// stat("----------FISH_HIT_MAIN----------", &tmp); // stat("----------FISH_HIT_MAIN----------", &tmp);
if (!argv[0]) {
static const char *dummy_argv[2] = {"fish", NULL};
argv = (char **)dummy_argv; //!OCLINT(parameter reassignment)
argc = 1; //!OCLINT(parameter reassignment)
}
std::vector<std::string> cmds; std::vector<std::string> cmds;
my_optind = fish_parse_opt(argc, argv, &cmds); my_optind = fish_parse_opt(argc, argv, &cmds);

View file

@ -16,7 +16,6 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <wchar.h> #include <wchar.h>
#include <wctype.h>
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
@ -124,10 +123,18 @@ static char *char_to_symbol(wchar_t wc, bool bind_friendly) {
} }
} else if (wc == ' ') { } else if (wc == ' ') {
// The "space" character. // The "space" character.
snprintf(buf, sizeof(buf), "\\x%X (aka \"space\")", wc); if (bind_friendly) {
snprintf(buf, sizeof(buf), "\\x%X", wc);
} else {
snprintf(buf, sizeof(buf), "\\x%X (aka \"space\")", wc);
}
} else if (wc == 0x7F) { } else if (wc == 0x7F) {
// The "del" character. // The "del" character.
snprintf(buf, sizeof(buf), "\\x%X (aka \"del\")", wc); if (bind_friendly) {
snprintf(buf, sizeof(buf), "\\x%X", wc);
} else {
snprintf(buf, sizeof(buf), "\\x%X (aka \"del\")", wc);
}
} else if (wc < 0x80) { } else if (wc < 0x80) {
// ASCII characters that are not control characters. // ASCII characters that are not control characters.
if (bind_friendly && must_escape(wc)) { if (bind_friendly && must_escape(wc)) {
@ -195,7 +202,7 @@ static void process_input(bool continuous_mode) {
fprintf(stderr, "Press a key\n\n"); fprintf(stderr, "Press a key\n\n");
while (keep_running) { while (keep_running) {
wchar_t wc = input_common_readch(true); wchar_t wc = input_common_readch(true);
if (wc == WEOF) { if (wc == R_TIMEOUT || wc == R_EOF) {
output_bind_command(bind_chars); output_bind_command(bind_chars);
if (first_char_seen && !continuous_mode) { if (first_char_seen && !continuous_mode) {
return; return;

View file

@ -144,7 +144,6 @@ function_info_t::function_info_t(const function_data_t &data, const wchar_t *fil
named_arguments(data.named_arguments), named_arguments(data.named_arguments),
inherit_vars(snapshot_vars(data.inherit_vars)), inherit_vars(snapshot_vars(data.inherit_vars)),
is_autoload(autoload), is_autoload(autoload),
shadow_builtin(data.shadow_builtin),
shadow_scope(data.shadow_scope) {} shadow_scope(data.shadow_scope) {}
function_info_t::function_info_t(const function_info_t &data, const wchar_t *filename, function_info_t::function_info_t(const function_info_t &data, const wchar_t *filename,
@ -156,7 +155,6 @@ function_info_t::function_info_t(const function_info_t &data, const wchar_t *fil
named_arguments(data.named_arguments), named_arguments(data.named_arguments),
inherit_vars(data.inherit_vars), inherit_vars(data.inherit_vars),
is_autoload(autoload), is_autoload(autoload),
shadow_builtin(data.shadow_builtin),
shadow_scope(data.shadow_scope) {} shadow_scope(data.shadow_scope) {}
void function_add(const function_data_t &data, const parser_t &parser, int definition_line_offset) { void function_add(const function_data_t &data, const parser_t &parser, int definition_line_offset) {
@ -260,12 +258,6 @@ std::map<wcstring, env_var_t> function_get_inherit_vars(const wcstring &name) {
return func ? func->inherit_vars : std::map<wcstring, env_var_t>(); return func ? func->inherit_vars : std::map<wcstring, env_var_t>();
} }
int function_get_shadow_builtin(const wcstring &name) {
scoped_lock locker(functions_lock);
const function_info_t *func = function_get(name);
return func ? func->shadow_builtin : false;
}
int function_get_shadow_scope(const wcstring &name) { int function_get_shadow_scope(const wcstring &name) {
scoped_lock locker(functions_lock); scoped_lock locker(functions_lock);
const function_info_t *func = function_get(name); const function_info_t *func = function_get(name);

View file

@ -32,8 +32,6 @@ struct function_data_t {
wcstring_list_t inherit_vars; wcstring_list_t inherit_vars;
/// Set to true if invoking this function shadows the variables of the underlying function. /// Set to true if invoking this function shadows the variables of the underlying function.
bool shadow_scope; bool shadow_scope;
/// Set to true if this function shadows a builtin.
bool shadow_builtin;
}; };
class function_info_t { class function_info_t {
@ -53,8 +51,6 @@ class function_info_t {
const std::map<wcstring, env_var_t> inherit_vars; const std::map<wcstring, env_var_t> inherit_vars;
/// Flag for specifying that this function was automatically loaded. /// Flag for specifying that this function was automatically loaded.
const bool is_autoload; const bool is_autoload;
/// Set to true if this function shadows a builtin.
const bool shadow_builtin;
/// Set to true if invoking this function shadows the variables of the underlying function. /// Set to true if invoking this function shadows the variables of the underlying function.
const bool shadow_scope; const bool shadow_scope;
@ -129,9 +125,6 @@ std::map<wcstring, env_var_t> function_get_inherit_vars(const wcstring &name);
/// is successful. /// is successful.
bool function_copy(const wcstring &name, const wcstring &new_name); bool function_copy(const wcstring &name, const wcstring &new_name);
/// Returns whether this function shadows a builtin of the same name.
int function_get_shadow_builtin(const wcstring &name);
/// Returns whether this function shadows variables of the underlying function. /// Returns whether this function shadows variables of the underlying function.
int function_get_shadow_scope(const wcstring &name); int function_get_shadow_scope(const wcstring &name);

View file

@ -30,7 +30,6 @@
#include "parse_tree.h" #include "parse_tree.h"
#include "path.h" #include "path.h"
#include "reader.h" #include "reader.h"
#include "sanity.h"
#include "signal.h" #include "signal.h"
#include "wutil.h" // IWYU pragma: keep #include "wutil.h" // IWYU pragma: keep
@ -438,19 +437,17 @@ history_item_t::history_item_t(const wcstring &str, time_t when, history_identif
bool history_item_t::matches_search(const wcstring &term, enum history_search_type_t type) const { bool history_item_t::matches_search(const wcstring &term, enum history_search_type_t type) const {
switch (type) { switch (type) {
case HISTORY_SEARCH_TYPE_CONTAINS: { case HISTORY_SEARCH_TYPE_CONTAINS: {
// We consider equal strings to NOT match a contains search (so that you don't have to return contents.find(term) != wcstring::npos;
// see history equal to what you typed). The length check ensures that.
return contents.size() > term.size() && contents.find(term) != wcstring::npos;
} }
case HISTORY_SEARCH_TYPE_PREFIX: { case HISTORY_SEARCH_TYPE_PREFIX: {
// We consider equal strings to match a prefix search, so that autosuggest will allow // We consider equal strings to match a prefix search, so that autosuggest will allow
// suggesting what you've typed. // suggesting what you've typed.
return string_prefixes_string(term, contents); return string_prefixes_string(term, contents);
} }
default: { case HISTORY_SEARCH_TYPE_EXACT: {
sanity_lose(); return term == contents;
return false;
} }
default: { DIE("unexpected history_search_type_t value"); }
} }
} }
@ -1405,9 +1402,9 @@ static bool format_history_record(const history_item_t &item, const bool with_ti
const time_t seconds = item.timestamp(); const time_t seconds = item.timestamp();
struct tm timestamp; struct tm timestamp;
if (!localtime_r(&seconds, &timestamp)) return false; if (!localtime_r(&seconds, &timestamp)) return false;
char timestamp_string[22]; wchar_t timestamp_string[24];
if (strftime(timestamp_string, 22, "%Y-%m-%d %H:%M:%S ", &timestamp) != 21) return false; if (std::wcsftime(timestamp_string, 23, L"# %Y-%m-%d %H:%M:%S\n", &timestamp) == 0) return false;
streams.out.append(str2wcstring(timestamp_string)); streams.out.append(timestamp_string);
} }
streams.out.append(item.str()); streams.out.append(item.str());
streams.out.append(L"\n"); streams.out.append(L"\n");

View file

@ -40,9 +40,11 @@ struct io_streams_t;
typedef std::vector<wcstring> path_list_t; typedef std::vector<wcstring> path_list_t;
enum history_search_type_t { enum history_search_type_t {
// The history searches for strings containing the given string. // Search for commands exactly matching the given string.
HISTORY_SEARCH_TYPE_EXACT = 1,
// Search for commands containing the given string.
HISTORY_SEARCH_TYPE_CONTAINS, HISTORY_SEARCH_TYPE_CONTAINS,
// The history searches for strings starting with the given string. // Search for commands starting with the given string.
HISTORY_SEARCH_TYPE_PREFIX HISTORY_SEARCH_TYPE_PREFIX
}; };

View file

@ -216,7 +216,10 @@ wcstring input_get_bind_mode() {
/// Set the current bind mode. /// Set the current bind mode.
void input_set_bind_mode(const wcstring &bm) { void input_set_bind_mode(const wcstring &bm) {
env_set(FISH_BIND_MODE_VAR, bm.c_str(), ENV_GLOBAL); // Only set this if it differs to not execute variable handlers all the time.
if (input_get_bind_mode() != bm.c_str()) {
env_set(FISH_BIND_MODE_VAR, bm.c_str(), ENV_GLOBAL);
}
} }
/// Returns the arity of a given input function. /// Returns the arity of a given input function.
@ -419,7 +422,7 @@ void input_function_push_args(int code) {
wchar_t arg; wchar_t arg;
// Skip and queue up any function codes. See issue #2357. // Skip and queue up any function codes. See issue #2357.
while (((arg = input_common_readch(0)) >= R_MIN) && (arg <= R_MAX)) { while ((arg = input_common_readch(0)) >= R_MIN && arg <= R_MAX) {
skipped.push_back(arg); skipped.push_back(arg);
} }
@ -497,7 +500,7 @@ static bool input_mapping_is_match(const input_mapping_t &m) {
wint_t c = 0; wint_t c = 0;
int j; int j;
// debug(0, L"trying mapping %ls\n", escape(m.seq.c_str(), ESCAPE_ALL).c_str()); debug(2, L"trying to match mapping %ls", escape(m.seq.c_str(), ESCAPE_ALL).c_str());
const wchar_t *str = m.seq.c_str(); const wchar_t *str = m.seq.c_str();
for (j = 0; str[j] != L'\0'; j++) { for (j = 0; str[j] != L'\0'; j++) {
bool timed = (j > 0 && iswcntrl(str[0])); bool timed = (j > 0 && iswcntrl(str[0]));
@ -515,7 +518,8 @@ static bool input_mapping_is_match(const input_mapping_t &m) {
return true; return true;
} }
// Return the read characters. // Reinsert the chars we read to be read again since we didn't match the bind sequence (i.e.,
// the input mapping).
input_common_next_ch(c); input_common_next_ch(c);
for (int k = j - 1; k >= 0; k--) { for (int k = j - 1; k >= 0; k--) {
input_common_next_ch(m.seq[k]); input_common_next_ch(m.seq[k]);
@ -554,9 +558,11 @@ static void input_mapping_execute_matching_or_generic(bool allow_commands) {
if (generic) { if (generic) {
input_mapping_execute(*generic, allow_commands); input_mapping_execute(*generic, allow_commands);
} else { } else {
// debug(0, L"no generic found, ignoring..."); debug(2, L"no generic found, ignoring char...");
wchar_t c = input_common_readch(0); wchar_t c = input_common_readch(0);
if (c == R_EOF) input_common_next_ch(c); if (c == R_EOF) {
input_common_next_ch(c);
}
} }
} }

View file

@ -16,8 +16,6 @@
#include <sys/time.h> #include <sys/time.h>
#include <sys/types.h> #include <sys/types.h>
#include <wchar.h> #include <wchar.h>
#include <wctype.h>
#include <cwctype>
#include <memory> #include <memory>
#include "common.h" #include "common.h"
@ -35,7 +33,7 @@
static int wait_on_escape_ms = WAIT_ON_ESCAPE_DEFAULT; static int wait_on_escape_ms = WAIT_ON_ESCAPE_DEFAULT;
/// Characters that have been read and returned by the sequence matching code. /// Characters that have been read and returned by the sequence matching code.
static std::deque<wint_t> lookahead_list; static std::deque<wchar_t> lookahead_list;
// Queue of pairs of (function pointer, argument) to be invoked. Expected to be mostly empty. // Queue of pairs of (function pointer, argument) to be invoked. Expected to be mostly empty.
typedef std::pair<void (*)(void *), void *> callback_info_t; typedef std::pair<void (*)(void *), void *> callback_info_t;
@ -203,7 +201,7 @@ wchar_t input_common_readch(int timed) {
struct timeval tm = {wait_on_escape_ms / 1000, 1000 * (wait_on_escape_ms % 1000)}; struct timeval tm = {wait_on_escape_ms / 1000, 1000 * (wait_on_escape_ms % 1000)};
int count = select(1, &fds, 0, 0, &tm); int count = select(1, &fds, 0, 0, &tm);
if (count <= 0) { if (count <= 0) {
return WEOF; return R_TIMEOUT;
} }
} }
@ -213,12 +211,12 @@ wchar_t input_common_readch(int timed) {
while (1) { while (1) {
wint_t b = readb(); wint_t b = readb();
if (MB_CUR_MAX == 1) // single-byte locale, all values are legal if (b >= R_NULL && b <= R_MAX) return b;
{
return (unsigned char)b;
}
if ((b >= R_NULL) && (b < R_NULL + 1000)) return b; if (MB_CUR_MAX == 1) {
// return (unsigned char)b; // single-byte locale, all values are legal
return b; // single-byte locale, all values are legal
}
char bb = b; char bb = b;
size_t sz = mbrtowc(&res, &bb, 1, &state); size_t sz = mbrtowc(&res, &bb, 1, &state);
@ -240,7 +238,7 @@ wchar_t input_common_readch(int timed) {
} }
} else { } else {
if (!timed) { if (!timed) {
while (has_lookahead() && lookahead_front() == WEOF) lookahead_pop(); while (has_lookahead() && lookahead_front() == R_TIMEOUT) lookahead_pop();
if (!has_lookahead()) return input_common_readch(0); if (!has_lookahead()) return input_common_readch(0);
} }

View file

@ -70,6 +70,7 @@ enum {
R_BACKWARD_JUMP, R_BACKWARD_JUMP,
R_AND, R_AND,
R_CANCEL, R_CANCEL,
R_TIMEOUT, // we didn't get interactive input within wait_on_escape_ms
R_MAX = R_CANCEL, R_MAX = R_CANCEL,
// This is a special psuedo-char that is not used other than to mark the end of the the special // This is a special psuedo-char that is not used other than to mark the end of the the special
// characters so we can sanity check the enum range. // characters so we can sanity check the enum range.
@ -92,7 +93,7 @@ void set_wait_on_escape_ms(int ms);
/// convert them to a wchar_t. Conversion is done using mbrtowc. If a character has previously been /// convert them to a wchar_t. Conversion is done using mbrtowc. If a character has previously been
/// read and then 'unread' using \c input_common_unreadch, that character is returned. If timed is /// read and then 'unread' using \c input_common_unreadch, that character is returned. If timed is
/// true, readch2 will wait at most WAIT_ON_ESCAPE milliseconds for a character to be available for /// true, readch2 will wait at most WAIT_ON_ESCAPE milliseconds for a character to be available for
/// reading before returning with the value WEOF. /// reading before returning with the value R_EOF.
wchar_t input_common_readch(int timed); wchar_t input_common_readch(int timed);
/// Enqueue a character or a readline function to the queue of unread characters that input_readch /// Enqueue a character or a readline function to the queue of unread characters that input_readch

View file

@ -3,6 +3,7 @@
// IWYU pragma: no_include <cstddef> // IWYU pragma: no_include <cstddef>
#include <assert.h> #include <assert.h>
#include <stddef.h> #include <stddef.h>
#include <stdlib.h>
#include <wchar.h> #include <wchar.h>
#include <wctype.h> #include <wctype.h>
#include <map> #include <map>
@ -602,11 +603,14 @@ bool pager_t::select_next_completion_in_direction(selection_direction_t directio
case direction_page_north: case direction_page_north:
case direction_east: case direction_east:
case direction_west: case direction_west:
case direction_deselect: case direction_deselect: {
default: {
// These do nothing. // These do nothing.
return false; return false;
} }
default: {
assert(0 && "Unhandled selection_direction_t constant");
abort();
}
} }
} }

View file

@ -3,6 +3,7 @@
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <wchar.h> #include <wchar.h>
#include <algorithm> #include <algorithm>
#include <memory> #include <memory>
@ -255,7 +256,7 @@ block_t *parser_t::block_at_index(size_t idx) {
return idx < count ? block_stack.at(count - idx - 1) : NULL; return idx < count ? block_stack.at(count - idx - 1) : NULL;
} }
block_t *const parser_t::current_block() { return block_stack.empty() ? NULL : block_stack.back(); } block_t *parser_t::current_block() { return block_stack.empty() ? NULL : block_stack.back(); }
void parser_t::forbid_function(const wcstring &function) { forbidden_function.push_back(function); } void parser_t::forbid_function(const wcstring &function) { forbidden_function.push_back(function); }
@ -869,8 +870,8 @@ wcstring block_t::description() const {
break; break;
} }
default: { default: {
append_format(result, L"unknown type %ld", (long)this->type()); assert(0 && "Unhandled block_type_t constant");
break; abort();
} }
} }

View file

@ -271,7 +271,7 @@ class parser_t {
block_t *block_at_index(size_t idx); block_t *block_at_index(size_t idx);
/// Returns the current (innermost) block. /// Returns the current (innermost) block.
block_t *const current_block(); block_t *current_block();
/// Count of blocks. /// Count of blocks.
size_t block_count() const { return block_stack.size(); } size_t block_count() const { return block_stack.size(); }

View file

@ -137,7 +137,7 @@ static int handle_child_io(const io_chain_t &io_chain) {
case IO_FILE: { case IO_FILE: {
// Here we definitely do not want to set CLO_EXEC because our child needs access. // Here we definitely do not want to set CLO_EXEC because our child needs access.
CAST_INIT(const io_file_t *, io_file, io); const io_file_t *io_file = static_cast<const io_file_t *>(io);
int tmp = open(io_file->filename_cstr, io_file->flags, OPEN_MASK); int tmp = open(io_file->filename_cstr, io_file->flags, OPEN_MASK);
if (tmp < 0) { if (tmp < 0) {
if ((io_file->flags & O_EXCL) && (errno == EEXIST)) { if ((io_file->flags & O_EXCL) && (errno == EEXIST)) {
@ -181,7 +181,7 @@ static int handle_child_io(const io_chain_t &io_chain) {
case IO_BUFFER: case IO_BUFFER:
case IO_PIPE: { case IO_PIPE: {
CAST_INIT(const io_pipe_t *, io_pipe, io); const io_pipe_t *io_pipe = static_cast<const io_pipe_t *>(io);
// If write_pipe_idx is 0, it means we're connecting to the read end (first pipe // If write_pipe_idx is 0, it means we're connecting to the read end (first pipe
// fd). If it's 1, we're connecting to the write end (second pipe fd). // fd). If it's 1, we're connecting to the write end (second pipe fd).
unsigned int write_pipe_idx = (io_pipe->is_input ? 0 : 1); unsigned int write_pipe_idx = (io_pipe->is_input ? 0 : 1);
@ -340,7 +340,7 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr,
const shared_ptr<const io_data_t> io = io_chain.at(idx); const shared_ptr<const io_data_t> io = io_chain.at(idx);
if (io->io_mode == IO_FD) { if (io->io_mode == IO_FD) {
CAST_INIT(const io_fd_t *, io_fd, io.get()); const io_fd_t *io_fd = static_cast<const io_fd_t *>(io.get());
if (io->fd == io_fd->old_fd) continue; if (io->fd == io_fd->old_fd) continue;
} }
@ -351,7 +351,7 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr,
} }
case IO_FILE: { case IO_FILE: {
CAST_INIT(const io_file_t *, io_file, io.get()); const io_file_t *io_file = static_cast<const io_file_t *>(io.get());
if (!err) if (!err)
err = posix_spawn_file_actions_addopen(actions, io->fd, io_file->filename_cstr, err = posix_spawn_file_actions_addopen(actions, io->fd, io_file->filename_cstr,
io_file->flags /* mode */, OPEN_MASK); io_file->flags /* mode */, OPEN_MASK);
@ -359,7 +359,7 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr,
} }
case IO_FD: { case IO_FD: {
CAST_INIT(const io_fd_t *, io_fd, io.get()); const io_fd_t *io_fd = static_cast<const io_fd_t *>(io.get());
if (!err) if (!err)
err = posix_spawn_file_actions_adddup2(actions, io_fd->old_fd /* from */, err = posix_spawn_file_actions_adddup2(actions, io_fd->old_fd /* from */,
io->fd /* to */); io->fd /* to */);
@ -368,7 +368,7 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr,
case IO_BUFFER: case IO_BUFFER:
case IO_PIPE: { case IO_PIPE: {
CAST_INIT(const io_pipe_t *, io_pipe, io.get()); const io_pipe_t *io_pipe = static_cast<const io_pipe_t *>(io.get());
unsigned int write_pipe_idx = (io_pipe->is_input ? 0 : 1); unsigned int write_pipe_idx = (io_pipe->is_input ? 0 : 1);
int from_fd = io_pipe->pipe_fd[write_pipe_idx]; int from_fd = io_pipe->pipe_fd[write_pipe_idx];
int to_fd = io->fd; int to_fd = io->fd;

View file

@ -514,7 +514,7 @@ void proc_fire_event(const wchar_t *msg, int type, pid_t pid, int status) {
event.arguments.resize(0); event.arguments.resize(0);
} }
int job_reap(bool interactive) { int job_reap(bool allow_interactive) {
ASSERT_IS_MAIN_THREAD(); ASSERT_IS_MAIN_THREAD();
job_t *jnext; job_t *jnext;
int found = 0; int found = 0;
@ -527,6 +527,10 @@ int job_reap(bool interactive) {
} }
locked = true; locked = true;
// this may be invoked in an exit handler, after the TERM has been torn down
// don't try to print in that case (#3222)
const bool interactive = allow_interactive && cur_term != NULL;
process_mark_finished_children(false); process_mark_finished_children(false);
// Preserve the exit status. // Preserve the exit status.
@ -711,7 +715,7 @@ static int select_try(job_t *j) {
for (size_t idx = 0; idx < chain.size(); idx++) { for (size_t idx = 0; idx < chain.size(); idx++) {
const io_data_t *io = chain.at(idx).get(); const io_data_t *io = chain.at(idx).get();
if (io->io_mode == IO_BUFFER) { if (io->io_mode == IO_BUFFER) {
CAST_INIT(const io_pipe_t *, io_pipe, io); const io_pipe_t *io_pipe = static_cast<const io_pipe_t *>(io);
int fd = io_pipe->pipe_fd[0]; int fd = io_pipe->pipe_fd[0];
// fwprintf( stderr, L"fd %d on job %ls\n", fd, j->command ); // fwprintf( stderr, L"fd %d on job %ls\n", fd, j->command );
FD_SET(fd, &fds); FD_SET(fd, &fds);

View file

@ -2873,11 +2873,15 @@ const wchar_t *reader_readline(int nchars) {
data->history_search = history_search_t(*data->history, data->search_buff, data->history_search = history_search_t(*data->history, data->search_buff,
HISTORY_SEARCH_TYPE_CONTAINS); HISTORY_SEARCH_TYPE_CONTAINS);
// Skip the autosuggestion as history unless it was truncated. // Always skip history entries that exactly match what has been typed so far.
wcstring_list_t skip_list;
skip_list.push_back(data->command_line.text);
const wcstring &suggest = data->autosuggestion; const wcstring &suggest = data->autosuggestion;
if (!suggest.empty() && !data->screen.autosuggestion_is_truncated) { if (!suggest.empty() && !data->screen.autosuggestion_is_truncated) {
data->history_search.skip_matches(wcstring_list_t(&suggest, 1 + &suggest)); // Also skip the autosuggestion in the history unless it was truncated.
skip_list.push_back(suggest);
} }
data->history_search.skip_matches(skip_list);
} }
switch (data->search_mode) { switch (data->search_mode) {
@ -3246,7 +3250,7 @@ const wchar_t *reader_readline(int nchars) {
} }
default: { default: {
// Other, if a normal character, we add it to the command. // Other, if a normal character, we add it to the command.
if ((!wchar_private(c)) && (((c > 31) || (c == L'\n')) && (c != 127))) { if (!wchar_private(c) && (c >= L' ' || c == L'\n' || c == L'\r') && c != 0x7F) {
bool allow_expand_abbreviations = false; bool allow_expand_abbreviations = false;
if (data->is_navigating_pager_contents()) { if (data->is_navigating_pager_contents()) {
data->pager.set_search_field_shown(true); data->pager.set_search_field_shown(true);
@ -3262,11 +3266,10 @@ const wchar_t *reader_readline(int nchars) {
if (el == &data->command_line) { if (el == &data->command_line) {
clear_pager(); clear_pager();
} }
} else { } else {
// Low priority debug message. These can happen if the user presses an unefined // This can happen if the user presses a control char we don't recognize. No
// control sequnece. No reason to report. // reason to report this to the user unless they've enabled debugging output.
debug(2, _(L"Unknown keybinding %d"), c); debug(2, _(L"Unknown key binding 0x%X"), c);
} }
break; break;
} }

View file

@ -223,9 +223,7 @@ size_t escape_code_length(const wchar_t *code) {
} }
} }
} }
}
if (cur_term != NULL) {
// Detect these semi-common terminfo escapes without any parameter values, all of which // Detect these semi-common terminfo escapes without any parameter values, all of which
// don't move the cursor. // don't move the cursor.
char *const esc2[] = {enter_bold_mode, exit_attribute_mode, enter_underline_mode, char *const esc2[] = {enter_bold_mode, exit_attribute_mode, enter_underline_mode,
@ -1039,7 +1037,6 @@ void s_write(screen_t *s, const wcstring &left_prompt, const wcstring &right_pro
const int *indent, size_t cursor_pos, const page_rendering_t &pager, const int *indent, size_t cursor_pos, const page_rendering_t &pager,
bool cursor_is_within_pager) { bool cursor_is_within_pager) {
screen_data_t::cursor_t cursor_arr; screen_data_t::cursor_t cursor_arr;
CHECK(s, ); CHECK(s, );
CHECK(indent, ); CHECK(indent, );
@ -1126,7 +1123,6 @@ void s_write(screen_t *s, const wcstring &left_prompt, const wcstring &right_pro
s_update(s, layout.left_prompt.c_str(), layout.right_prompt.c_str()); s_update(s, layout.left_prompt.c_str(), layout.right_prompt.c_str());
s_save_status(s); s_save_status(s);
} }
void s_reset(screen_t *s, screen_reset_mode_t mode) { void s_reset(screen_t *s, screen_reset_mode_t mode) {
CHECK(s, ); CHECK(s, );

View file

@ -5,6 +5,7 @@
#include <assert.h> #include <assert.h>
#include <fcntl.h> #include <fcntl.h>
#include <limits.h> #include <limits.h>
#include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <wchar.h> #include <wchar.h>
#include <wctype.h> #include <wctype.h>
@ -759,7 +760,7 @@ bool move_word_state_machine_t::consume_char(wchar_t c) {
case move_word_style_whitespace: { case move_word_style_whitespace: {
return consume_char_whitespace(c); return consume_char_whitespace(c);
} }
default: { return false; } default: { abort(); }
} }
} }

View file

@ -80,18 +80,6 @@ expect_prompt -re {\r\nsuccess: default escape timeout\r\n} {
puts stderr "vi replace line, default timeout: long delay" puts stderr "vi replace line, default timeout: long delay"
} }
# Verify that a human can transpose words using \et (which is an emacs default
# binding but should be valid while in vi insert or normal mode).
send "echo abc def"
send "\033"
sleep 0.010
send "t\r"
expect_prompt -re {\r\ndef abc\r\n} {
puts "vi transpose words, default timeout: short delay"
} unmatched {
puts stderr "vi transpose words, default timeout: short delay"
}
# Test replacing a single character. # Test replacing a single character.
send "echo TEXT" send "echo TEXT"
send "\033" send "\033"

View file

@ -4,7 +4,6 @@ emacs transpose words, default timeout: long delay
prime vi mode, default timeout prime vi mode, default timeout
vi-mode default timeout set correctly vi-mode default timeout set correctly
vi replace line, default timeout: long delay vi replace line, default timeout: long delay
vi transpose words, default timeout: short delay
vi mode replace char, default timeout: long delay vi mode replace char, default timeout: long delay
vi replace line, 100ms timeout: long delay vi replace line, 100ms timeout: long delay
vi replace line, 100ms timeout: short delay vi replace line, 100ms timeout: short delay

View file

@ -1,8 +0,0 @@
function: function name shadows a builtin so you must use '--shadow-builtin'
fish: function pwd; end
^
yes, it failed as expected
function: function name does not shadow a builtin so you must not use '--shadow-builtin'
fish: function not_builtin --shadow-builtin; end
^
yes, it failed as expected

View file

@ -44,16 +44,3 @@ for i in (seq 4)
echo "Function name$i not found, but should have been" echo "Function name$i not found, but should have been"
end end
end end
# Test that we can't define a function that shadows a builtin by accident.
function pwd; end
or echo 'yes, it failed as expected' >&2
# Test that we can define a function that shadows a builtin if we use the
# right flag.
function pwd --shadow-builtin; end
and echo '"function pwd --shadow-builtin" worked'
# Using --shadow-builtin for a non-builtin function name also fails.
function not_builtin --shadow-builtin; end
or echo 'yes, it failed as expected' >&2

View file

@ -22,4 +22,3 @@ Function name1 found
Function name2 found Function name2 found
Function name3 found Function name3 found
Function name4 found Function name4 found
"function pwd --shadow-builtin" worked

7
tests/history.err Normal file
View file

@ -0,0 +1,7 @@
history: you cannot use any options with clear command
history: you cannot use any options with merge command
history: save command expected 0 args, got 1
history: you cannot use any options with save command
history: you cannot use any options with clear command
history: merge command expected 0 args, got 1
history: clear command expected 0 args, got 2

View file

@ -78,8 +78,85 @@ expect_prompt -re {\r\necho start1.*\r\necho start2} {
# ========== # ==========
# Verify implicit searching with a request for timestamps includes the timestamps. # Verify implicit searching with a request for timestamps includes the timestamps.
send "history -t echo start\r" send "history -t echo start\r"
expect_prompt -re {\r\n\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d echo start1; builtin history;.*\r\n\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d echo start2; builtin history} { expect_prompt -re {\r\n# \d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\r\necho start1; builtin history;.*\r\n# \d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d\r\necho start2; builtin history} {
puts "history function implicit search with timestamps succeeded" puts "history function implicit search with timestamps succeeded"
} unmatched { } unmatched {
puts stderr "history function implicit search with timestamps failed" puts stderr "history function implicit search with timestamps failed"
} }
# ==========
# Verify explicit searching for an exact command returns just that command.
# returns the expected results.
send "echo hello\r"
expect_prompt
send "echo goodbye\r"
expect_prompt
send "echo hello again\r"
expect_prompt
send "echo hello AGAIN\r"
expect_prompt
send "history --search --exact 'echo goodbye'\r"
expect_prompt -re {\r\necho goodbye\r\n} {
puts "history function explicit exact search 'echo goodbye' succeeded"
} unmatched {
puts stderr "history function explicit exact search 'echo goodbye' failed"
}
send "history --search --exact 'echo hello'\r"
expect_prompt -re {\r\necho hello\r\n} {
puts "history function explicit exact search 'echo hello' succeeded"
} unmatched {
puts stderr "history function explicit exact search 'echo hello' failed"
}
# This is slightly subtle in that it shouldn't actually match anything between
# the command we sent and the next prompt.
send "history --search --exact 'echo hell'\r"
expect_prompt -re {history --search --exact 'echo hell'\r\n} {
puts "history function explicit exact search 'echo hell' succeeded"
} unmatched {
puts stderr "history function explicit exact search 'echo hell' failed"
}
# ==========
# Delete a single command we recently ran.
send "history --delete 'echo hello'\r"
expect_prompt -re {history --delete 'echo hello'\r\n} {
puts "history function explicit exact delete 'echo hello' succeeded"
} unmatched {
puts stderr "history function explicit exact delete 'echo hello' failed"
}
# ==========
# Interactively delete one of multiple matched commands. This verifies that we
# delete the first entry matched by the prefix search (the most recent command
# sent above that matches).
send "history --delete -p 'echo hello'\r"
expect -re {history --delete -p 'echo hello'\r\n}
expect -re {\[1\] echo hello AGAIN\r\n}
expect -re {\[2\] echo hello again\r\n\r\n}
expect -re {Enter nothing to cancel.*\r\nEnter "all" to delete all the matching entries\.\r\n}
expect -re {Delete which entries\? >}
send "1\r"
expect_prompt -re {Deleting history entry 1: "echo hello AGAIN"\r\n} {
puts "history function explicit prefix delete 'echo hello' succeeded"
} unmatched {
puts stderr "history function explicit prefix delete 'echo hello' failed"
}
# Verify that the deleted history entry is gone and the other one that matched
# the prefix search above is still there.
send "history --search --exact 'echo hello again'\r"
expect_prompt -re {\r\necho hello again\r\n} {
puts "history function explicit exact search 'echo hello again' succeeded"
} unmatched {
puts stderr "history function explicit exact search 'echo hello again' failed"
}
send "history --search --exact 'echo hello AGAIN'\r"
expect_prompt -re {\r\necho hello AGAIN\r\n} {
puts stderr "history function explicit exact search 'echo hello AGAIN' found the entry"
} unmatched {
puts "history function explicit exact search 'echo hello AGAIN' failed to find the entry"
}

View file

@ -4,3 +4,10 @@ invalid attempt at multiple history commands detected
history function explicit search succeeded history function explicit search succeeded
history function implicit search succeeded history function implicit search succeeded
history function implicit search with timestamps succeeded history function implicit search with timestamps succeeded
history function explicit exact search 'echo goodbye' succeeded
history function explicit exact search 'echo hello' succeeded
history function explicit exact search 'echo hell' succeeded
history function explicit exact delete 'echo hello' succeeded
history function explicit prefix delete 'echo hello' succeeded
history function explicit exact search 'echo hello again' succeeded
history function explicit exact search 'echo hello AGAIN' failed to find the entry

13
tests/history.in Normal file
View file

@ -0,0 +1,13 @@
# Verify that specifying unexpected options or arguments results in an error.
# First with the history function.
history --clear --contains
history --merge -t
history --save xyz
# Now with the history builtin.
builtin history --save --prefix
builtin history --clear --with-time
builtin history --merge xyz
builtin history --clear abc def
# Now do a history command that should succeed.
builtin history --merge

0
tests/history.out Normal file
View file

View file

@ -0,0 +1 @@
2,34: value not completely converted

View file

@ -34,4 +34,30 @@ printf "%5" 10 ^ /dev/null
# \376 is 0xFE # \376 is 0xFE
printf '\376' | xxd -p printf '\376' | xxd -p
true # Verify that floating point conversions and output work correctly with
# different combinations of locales and floating point strings. See issue
# #3334. This starts by assuming an locale using english conventions.
printf '%e\n' "1.23" # should succeed, output should be 1.230000e+00
printf '%e\n' "2,34" # should fail
# Try to use one of several locales that use a comma as the decimal mark
# rather than the period used in english speaking locales. If we don't find
# one installed we simply don't run this test.
set -l locales (locale -a)
set -l acceptable_locales bg_BG de_DE es_ES fr_FR ru_RU
set -l numeric_locale
for locale in {$acceptable_locales}.{UTF-8,UTF8}
if string match -i -q $locale $locales
set numeric_locale $locale
break
end
end
if set -q numeric_locale[1]
set -x LC_NUMERIC $numeric_locale
printf '%e\n' "3,45" # should succeed, output should be 3,450000e+00
printf '%e\n' "4.56" # should succeed, output should be 4,560000e+00
else
echo '3,450000e+00'
echo '4,560000e+00'
end

View file

@ -14,3 +14,6 @@ I P Q R
Test escapes Test escapes
a a
fe fe
1.230000e+00
3,450000e+00
4,560000e+00