Compare commits

..

1 Commits

Author SHA1 Message Date
David Adam
4110b0b0ee CHANGELOG: start 3.0.3 process
[ci skip]
2019-04-09 22:24:04 +08:00
2121 changed files with 408604 additions and 225119 deletions

View File

@@ -1,25 +0,0 @@
image: alpine/edge
packages:
- cmake
- ninja
- ncurses-dev
- pcre2-dev
- python3
- py-pip
sources:
- https://git.sr.ht/~faho/fish
tasks:
- build: |
pip3 install pexpect
cd fish
mkdir build || :
cd build
cmake -G Ninja .. \
-DCMAKE_INSTALL_PREFIX=/usr \
-DCMAKE_INSTALL_DATADIR=share \
-DCMAKE_INSTALL_DOCDIR=share/doc/fish \
-DCMAKE_INSTALL_SYSCONFDIR=/etc
ninja
- test: |
cd fish/build
env SHOW_INTERACTIVE_LOG=1 ninja test

View File

@@ -1,22 +0,0 @@
image: archlinux
packages:
- cmake
- ninja
- python
- python-pexpect
sources:
- https://git.sr.ht/~faho/fish
tasks:
- build: |
cd fish
mkdir build || :
cd build
cmake -G Ninja .. \
-DCMAKE_INSTALL_PREFIX=/usr \
-DCMAKE_INSTALL_DATADIR=share \
-DCMAKE_INSTALL_DOCDIR=share/doc/fish \
-DCMAKE_INSTALL_SYSCONFDIR=/etc
ninja
- test: |
cd fish/build
env SHOW_INTERACTIVE_LOG=1 ninja test

View File

@@ -1,26 +0,0 @@
image: freebsd/latest
packages:
- ncurses
- gcc
- gettext
- cmake
- gmake
- pcre2
- python
- py38-pexpect
sources:
- https://git.sr.ht/~faho/fish
tasks:
- build: |
cd fish
mkdir build || :
cd build
cmake .. \
-DCMAKE_INSTALL_PREFIX=/usr \
-DCMAKE_INSTALL_DATADIR=share \
-DCMAKE_INSTALL_DOCDIR=share/doc/fish \
-DCMAKE_INSTALL_SYSCONFDIR=/etc
gmake -j2
- test: |
cd fish/build
gmake test SHOW_INTERACTIVE_LOG=1

View File

@@ -6,11 +6,5 @@
BasedOnStyle: Google
ColumnLimit: 100
IndentWidth: 4
# Place config.h first always.
IncludeCategories:
- Regex: '^"config.h"'
Priority: -1
# We don't want OCLint pragmas to be reformatted.
CommentPragmas: '^!OCLINT'

View File

@@ -1,17 +0,0 @@
---
Checks: 'clang-diagnostic-*,clang-analyzer-*,-clang-analyzer-valist.Uninitialized,cert-*,performance-*,portability-*,-modernize-use-auto,modernize-loop-convert,modernize-use-bool-literals,modernize-use-using,hicpp-uppercase-literal-suffix,readability-make-member-function-const,readability-redundant-string-init,readability-inconsistent-declaration-parameter-name,readability-redundant-access-specifiers,-performance-noexcept-move-constructor,-cert-dcl21-cpp,-cert-dcl37-c,-cert-dcl50-cpp,-cert-dcl51-cpp,-cert-str34-c,-cert-env33-c,misc-static-assert,readability-use-anyofallof,readability-simplify-*,readability-redundant-*,modernize-redundant-void-arg,modernize-make-shared,modernize-make-unique,modernize-loop-convert,'
WarningsAsErrors: ''
HeaderFilterRegex: ''
AnalyzeTemporaryDtors: false
FormatStyle: File
CheckOptions:
- key: cert-dcl16-c.NewSuffixes
value: 'L;LL;LU;LLU'
- key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField
value: '0'
- key: modernize-loop-convert.MinConfidence
value: 'risky'
- key: modernize-use-auto.RemoveStars
value: '1'
...

View File

@@ -10,6 +10,3 @@ varFuncNullUB
unmatchedSuppression
// Suppress this one because it reports assert(condition && "message"), which we use all over the place
incorrectStringBooleanError
// This is of very little use and pops up *everywhere*.
useStlAlgorithm

View File

@@ -12,7 +12,7 @@ max_line_length = 100
[{Makefile,*.in}]
indent_style = tab
[*.{md,rst}]
[*.md]
trim_trailing_whitespace = false
[*.{sh,ac}]
@@ -20,9 +20,3 @@ indent_size = 2
[Dockerfile]
indent_size = 2
[share/{completions,functions}/**.fish]
max_line_length = none
[COMMIT_EDITMSG]
max_line_length = 80

15
.gitattributes vendored
View File

@@ -6,7 +6,6 @@
# let git show off diff hunk headers, help git diff -L:
# https://git-scm.com/docs/gitattributes
*.cpp diff=cpp
*.h diff=cpp
*.py diff=py
# add a [diff "fish"] to git config with pattern
*.fish diff=fish
@@ -19,15 +18,13 @@
/debian/* export-ignore
/.github export-ignore
/.github/* export-ignore
/.builds export-ignore
/.builds/* export-ignore
# for linguist; let github identify our project as C++ instead of C due to pcre2
pcre2/** linguist-vendored
/pcre2-10.22/ linguist-vendored
/pcre2-10.22/* linguist-vendored
/muparser-2.2.5/ linguist-vendored
/muparser-2.2.5/* linguist-vendored
angular.js linguist-vendored
angular-*.js linguist-vendored
doc_src/** linguist-documentation
/doc_src/* linguist-documentation
*.fish linguist-language=fish
src/*.h linguist-language=c++
src/builtins/*.h linguist-language=c++
share/completions/*.fish linguist-documentation
tests/*.in linguist-language=fish

View File

@@ -12,5 +12,3 @@ Please tell us if you tried fish without third-party customizations by executing
Tell us how to reproduce the problem. Including an asciinema.org recording is useful for problems that involve the visual display of fish output such as its prompt.
-->
**YOUR TEXT HERE**

View File

@@ -8,4 +8,4 @@ Fixes issue #
<!-- Just check off what what we know been done so far. We can help you with this stuff. -->
- [ ] Changes to fish usage are reflected in user documentation/manpages.
- [ ] Tests have been added for regressions fixed
- [ ] User-visible changes noted in CHANGELOG.rst
- [ ] User-visible changes noted in CHANGELOG.md

View File

@@ -1,43 +0,0 @@
name: "CodeQL"
on:
push:
branches: [ master ]
schedule:
- cron: '18 22 * * 2'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: true
matrix:
language: [ 'cpp', 'javascript', 'python' ]
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

View File

@@ -1,19 +0,0 @@
name: 'Lock threads'
on:
schedule:
- cron: '0 18 * * 1'
# │ │ │ │ │
# min 0-59 ┘ │ │ │ └ weekday 0-6
# hour 0-23 ┘ │ └ month 1-12
# └ day 1-31
jobs:
lock:
runs-on: ubuntu-latest
steps:
- uses: dessant/lock-threads@v2
with:
github-token: ${{ github.token }}
issue-lock-inactive-days: '365'
pr-lock-inactive-days: '365'
issue-exclude-labels: 'question, needs more info'

View File

@@ -1,132 +0,0 @@
name: make test
on: [push, pull_request]
env:
CTEST_PARALLEL_LEVEL: "1"
CMAKE_BUILD_PARALLEL_LEVEL: "4"
jobs:
ubuntu:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install deps
run: |
sudo apt install gettext libncurses5-dev libpcre2-dev python3-pip tmux
sudo pip3 install pexpect
# Generate a locale that uses a comma as decimal separator.
sudo locale-gen fr_FR.UTF-8
- name: cmake
env:
# Some warnings upgraded to errors to match Open Build Service platforms
CXXFLAGS: "-Werror=address -Werror=return-type"
run: |
mkdir build && cd build
cmake ..
- name: make
run: |
make
- name: make test
run: |
make test
ubuntu-32bit-vendored-pcre2:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install deps
run: |
sudo apt update
sudo apt install gettext lib32ncurses5-dev python3-pip g++-multilib tmux
sudo pip3 install pexpect
- name: cmake
env:
CXXFLAGS: "-m32 -Werror=address -Werror=return-type"
CFLAGS: "-m32"
run: |
mkdir build && cd build
cmake -DFISH_USE_SYSTEM_PCRE2=OFF ..
- name: make
run: |
make
- name: make test
run: |
make test
ubuntu-asan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install deps
run: |
sudo apt install gettext libncurses5-dev libpcre2-dev python3-pip tmux
sudo pip3 install pexpect
- name: cmake
env:
CC: clang
CXX: clang++
CXXFLAGS: "-fno-omit-frame-pointer -fsanitize=undefined -fsanitize=address"
ASAN_OPTIONS: check_initialization_order=1:detect_stack_use_after_return=1:detect_leaks=1
UBSAN_OPTIONS: print_stacktrace=1:report_error_type=1
run: |
mkdir build && cd build
cmake ..
- name: make
run: |
make
- name: make test
run: |
make test
ubuntu-threadsan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install deps
run: |
sudo apt install gettext libncurses5-dev libpcre2-dev python3-pip tmux
sudo pip3 install pexpect
- name: cmake
env:
CC: clang
CXX: clang++
CXXFLAGS: "-fsanitize=thread"
run: |
mkdir build && cd build
cmake ..
- name: make
run: |
make
- name: make test
run: |
make test
macos:
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- name: Install deps
run: |
sudo pip3 install pexpect
brew install tmux
- name: cmake
run: |
mkdir build && cd build
cmake -DWITH_GETTEXT=NO ..
- name: make
run: |
make
- name: make test
run: |
make test

15
.gitignore vendored
View File

@@ -38,6 +38,16 @@ Desktop.ini
Thumbs.db
ehthumbs.db
# These file names can appear anywhere in the hierarchy. They tend to be OS
# or build system artifacts.
autom4te.cache
aclocal.m4
Makefile
config.h
config.cache
config.h.in
config.status
messages.pot
.directory
.fuse_hidden*
@@ -45,6 +55,7 @@ messages.pot
# Directories that only contain transitory files from building and testing.
/doc/
/obj/
/share/man/
/share/doc/
/test/
@@ -56,6 +67,8 @@ messages.pot
/command_list.txt
/command_list_toc.txt
/compile_commands.json
/confdefs.h
/configure
/doc.h
/fish
/fish.pc
@@ -67,12 +80,12 @@ messages.pot
/toc.txt
/version
fish-build-version-witness.txt
__pycache__
# File names that can appear below the project root that represent artifacts
# from building and testing.
/doc_src/commands.hdr
/doc_src/index.hdr
/pcre2-*/configure.lineno
/po/*.gmo
/share/__fish_build_paths.fish
/share/pkgconfig

94
.travis.yml Normal file
View File

@@ -0,0 +1,94 @@
language: cpp
dist: trusty
sudo: required
matrix:
include:
- os: linux
compiler: gcc
addons:
apt:
packages:
- bc
- expect
- gettext
- libncurses5-dev
- os: linux
compiler: gcc
addons:
apt:
packages:
- bc
- expect
- gettext
- lib32ncurses5-dev
- g++-multilib
env:
- CXXFLAGS="-g -O2 -m32" CFLAGS="-g -m32"
- os: linux
compiler: clang
addons:
apt:
packages:
- bc
- expect
- gettext
- libncurses5-dev
- cmake
env:
- USE_CMAKE="1" # Dummy value, shows up in the Travis UI only
script:
- cmake -DCMAKE_INSTALL_PREFIX=$HOME/prefix . || cat CMakeFiles/CMakeError.log &&
make -j2 &&
make install &&
make test SHOW_INTERACTIVE_LOG=1
- os: linux
compiler: clang
env:
- CXXFLAGS="-g -O2 -fno-omit-frame-pointer -fsanitize=address" ASAN_OPTIONS=check_initialization_order=1:detect_stack_use_after_return=1:detect_leaks=1
before_install: export CXX=clang++-3.8
addons:
apt:
sources:
- llvm-toolchain-precise-3.8
- ubuntu-toolchain-r-test
packages:
- clang-3.8
- llvm-3.8 # for llvm-symbolizer
- bc
- expect
- gettext
- libncurses5-dev
- os: osx
before_install:
- brew update
- brew install pcre2 # use system PCRE2
- brew outdated xctool || brew upgrade xctool # for xcode... soon.
env:
- CXXFLAGS="-g -O2 -lstdc++"
fast_finish: true
script:
- autoreconf --no-recursive
- ./configure --prefix=$HOME/prefix || cat config.log
- make -j2 &&
make test DESTDIR=$HOME/prefix/ SHOW_INTERACTIVE_LOG=1 &&
make uninstall &&
echo "Checking for leftover files after make uninstall" &&
find $HOME/prefix/ -type f -print -exec false '{}' +
notifications:
# Some items are encrypted so that notifications from other repositories
# don't flood the official repositories.
irc:
channels:
#- "irc.oftc.net#fish"
secure: "eRk9KGZ5+mrlD2SoI8yg2Sp8OYrh7YPyGe3WCDQUwTnNgNDII34rbM9a6UOA/l7AeWSNY8joLq5xVLCU4wpFgUcJ11SYIpMnLosZK29OW4ubDOHmdBDvJ971rLgAVG9cXngZtIxEVVxN/jnS1Qr8GKZx4DjkaTMgz1pemb4WxCc="
template:
- "%{repository}#%{build_number} (%{commit} on %{branch} by %{author}): %{message} Details at %{build_url}"
use_notice: true
skip_join: true
webhooks:
urls:
#- https://webhooks.gitter.im/e/61821cec3015bf0f8bb1
secure: fPfOmxnC3MCsfR1oocVFeWLawGcRZkn+8fNHlSOeZ+SqqoZfcCHgQTvQ22TqmVl1yvkXbNlaXjo6dbVzTOAh7r7H0bRMEKBVh3dQS7wqjB1sKivpXd8PAS3BTj5MQpGeJzdHnDuwVlwDktGtfHfhGeq1Go/4IosOq8u+6RTe28g=

View File

@@ -1,46 +1,35 @@
# This is a very basic `make` wrapper around the CMake build toolchain.
#
# Supported arguments:
# PREFIX: sets the installation prefix
# GENERATOR: explicitly specifies the CMake generator to use
# By default, bmake will try to cd into ./obj before anything else. Don't do that.
# by default bmake will cd into ./obj first
.OBJDIR: ./
CMAKE?=cmake
# Before anything else, test for CMake, which is the only requirement to be able to run
# this Makefile CMake will perform the remaining dependency tests on its own.
.BEGIN:
@which $(CMAKE) >/dev/null 2>/dev/null || \
(echo 'Please install CMake and then re-run the `make` command!' 1>&2 && false)
# test for cmake, which is the only requirement to be able to run this Makefile
# cmake will perform the remaining dependency tests on its own
@which cmake >/dev/null 2>/dev/null || (echo 'Please install cmake and then re-run the `make` command!' 1>&2 && false)
# Prefer to use ninja, if it is installed
_GENERATOR!=which ninja 2>/dev/null >/dev/null && echo Ninja || echo "Unix Makefiles"
# Use ninja, if it is installed
_GENERATOR!=which ninja 2>/dev/null >/dev/null && echo Ninja || echo "'Unix Makefiles'"
GENERATOR?=$(_GENERATOR)
.if $(GENERATOR) == "Ninja"
BUILDFILE=build.ninja
.else
BUILDFILE=Makefile
.endif
PREFIX?=/usr/local
.PHONY: build/fish
build/fish: build/$(BUILDFILE)
$(CMAKE) --build build
.if $(GENERATOR) == "Ninja"
BUILDFILE=build/build.ninja
.else
BUILDFILE=build/Makefile
.endif
# Don't split the mkdir into its own rule because that would cause CMake to regenerate the build
# files after each build (because it adds the mdate of the build directory into the out-of-date
# calculation tree). GNUmake supports order-only dependencies, BSDmake does not seem to.
build/$(BUILDFILE):
.DEFAULT: build/fish
build/fish: build/$(BUILDFILE)
cmake --build build
build:
mkdir -p build
cd build; $(CMAKE) .. -G "$(GENERATOR)" -DCMAKE_INSTALL_PREFIX="$(PREFIX)" -DCMAKE_EXPORT_COMPILE_COMMANDS=1
build/$(BUILDFILE): build
cd build; cmake .. -G $(GENERATOR) -DCMAKE_INSTALL_PREFIX=$(PREFIX) -DCMAKE_EXPORT_COMPILE_COMMANDS=1
.PHONY: install
install: build/fish
$(CMAKE) --build build --target install
cmake --build build --target install
.PHONY: clean
clean:
@@ -48,7 +37,7 @@ clean:
.PHONY: test
test: build/fish
$(CMAKE) --build build --target test
cmake --build build --target test
.PHONY: run
run: build/fish

966
CHANGELOG.md Normal file
View File

@@ -0,0 +1,966 @@
# fish 3.0.3 (released ???)
This release of fish fixes a number of major issues since fish 3.0.2.
If you are upgrading from version 2.7.1 or before, please also review the release notes for 3.0.2, 3.0.1, 3.0.0 and 3.0b1 (included below).
---
# fish 3.0.2 (released February 19, 2019)
This release of fish fixes an issue discovered in fish 3.0.1.
### Fixes and improvements
- The PWD environment variable is now ignored if it does not resolve to the true working directory, fixing strange behaviour in terminals started by editors and IDEs (#5647).
If you are upgrading from version 2.7.1 or before, please also review the release notes for 3.0.1, 3.0.0 and 3.0b1 (included below).
---
# fish 3.0.1 (released February 11, 2019)
This release of fish fixes a number of major issues discovered in fish 3.0.0.
### Fixes and improvements
- `exec` does not complain about running foreground jobs when called (#5449).
- while loops now evaluate to the last executed command in the loop body (or zero if the body was empty), matching POSIX semantics (#4982).
- `read --silent` no longer echoes to the tty when run from a non-interactive script (#5519).
- On macOS, path entries with spaces in `/etc/paths` and `/etc/paths.d` now correctly set path entries with spaces. Likewise, `MANPATH` is correctly set from `/etc/manpaths` and `/etc/manpaths.d` (#5481).
- fish starts correctly under Cygwin/MSYS2 (#5426).
- The `pager-toggle-search` binding (Ctrl-S by default) will now activate the search field, even when the pager is not focused.
- The error when a command is not found is now printed a single time, instead of once per argument (#5588).
- Fixes and improvements to the git completions, including printing correct paths with older git versions, fuzzy matching again, reducing unnecessary offers of root paths (starting with `:/`) (#5578, #5574, #5476), and ignoring shell aliases, so enterprising users can set up the wrapping command (via `set -g __fish_git_alias_$command $whatitwraps`) (#5412).
- Significant performance improvements to core shell functions (#5447) and to the `kill` completions (#5541).
- Starting in symbolically-linked working directories works correctly (#5525).
- The default `fish_title` function no longer contains extra spaces (#5517).
- The `nim` prompt now works correctly when chosen in the Web-based configuration (#5490).
- `string` now prints help to stdout, like other builtins (#5495).
- Killing the terminal while fish is in vi normal mode will no longer send it spinning and eating CPU. (#5528)
- A number of crashes have been fixed (#5550, #5548, #5479, #5453).
- Improvements to the documentation and certain completions.
### Known issues
There is one significant known issue that was not corrected before the release:
- fish does not run correctly under Windows Services for Linux before Windows 10 version 1809/17763, and the message warning of this may not be displayed (#5619).
If you are upgrading from version 2.7.1 or before, please also review the release notes for 3.0.0 and 3.0b1 (included below).
---
# fish 3.0.0 (released December 28, 2018)
fish 3 is a major release, which introduces some breaking changes alongside improved functionality. Although most existing scripts will continue to work, they should be reviewed against the list contained in the 3.0b1 release notes below.
Compared to the beta release of fish 3.0b1, fish version 3.0.0:
- builds correctly against musl libc (#5407)
- handles huge numeric arguments to `test` correctly (#5414)
- removes the history colouring introduced in 3.0b1, which did not always work correctly
There is one significant known issue which was not able to be corrected before the release:
- fish 3.0.0 builds on Cygwin (#5423), but does not run correctly (#5426) and will result in a hanging terminal when started. Cygwin users are encouraged to continue using 2.7.1 until a release which corrects this is available.
If you are upgrading from version 2.7.1 or before, please also review the release notes for 3.0b1 (included below).
---
# fish 3.0b1 (released December 11, 2018)
fish 3 is a major release, which introduces some breaking changes alongside improved functionality. Although most existing scripts will continue to work, they should be reviewed against the list below.
## Notable non-backward compatible changes
- Process and job expansion has largely been removed. `%` will no longer perform these expansions, except for `%self` for the PID of the current shell. Additionally, job management commands (`disown`, `wait`, `bg`, `fg` and `kill`) will expand job specifiers starting with `%` (#4230, #1202).
- `set x[1] x[2] a b`, to set multiple elements of an array at once, is no longer valid syntax (#4236).
- A literal `{}` now expands to itself, rather than nothing. This makes working with `find -exec` easier (#1109, #4632).
- Literally accessing a zero-index is now illegal syntax and is caught by the parser (#4862). (fish indices start at 1)
- Successive commas in brace expansions are handled in less surprising manner. For example, `{,,,}` expands to four empty strings rather than an empty string, a comma and an empty string again (#3002, #4632).
- `for` loop control variables are no longer local to the `for` block (#1935).
- Variables set in `if` and `while` conditions are available outside the block (#4820).
- Local exported (`set -lx`) vars are now visible to functions (#1091).
- The new `math` builtin (see below) does not support logical expressions; `test` should be used instead (#4777).
- Range expansion will now behave sensibly when given a single positive and negative index (`$foo[5..-1]` or `$foo[-1..5]`), clamping to the last valid index without changing direction if the list has fewer elements than expected.
- `read` now uses `-s` as short for `--silent` (à la `bash`); `--shell`'s abbreviation (formerly `-s`) is now `-S` instead (#4490).
- `cd` no longer resolves symlinks. fish now maintains a virtual path, matching other shells (#3350).
- `source` now requires an explicit `-` as the filename to read from the terminal (#2633).
- Arguments to `end` are now errors, instead of being silently ignored.
- The names `argparse`, `read`, `set`, `status`, `test` and `[` are now reserved and not allowed as function names. This prevents users unintentionally breaking stuff (#3000).
- The `fish_user_abbreviations` variable is no longer used; abbreviations will be migrated to the new storage format automatically.
- The `FISH_READ_BYTE_LIMIT` variable is now called `fish_byte_limit` (#4414).
- Environment variables are no longer split into arrays based on the record separator character on startup. Instead, variables are not split, unless their name ends in PATH, in which case they are split on colons (#436).
- The `history` builtin's `--with-time` option has been removed; this has been deprecated in favor of `--show-time` since 2.7.0 (#4403).
- The internal variables `__fish_datadir` and `__fish_sysconfdir` are now known as `__fish_data_dir` and `__fish_sysconf_dir` respectively.
## Deprecations
With the release of fish 3, a number of features have been marked for removal in the future. All users are encouraged to explore alternatives. A small number of these features are currently behind feature flags, which are turned on at present but may be turned off by default in the future.
A new feature flags mechanism is added for staging deprecations and breaking changes. Feature flags may be specified at launch with `fish --features ...` or by setting the universal `fish_features` variable. (#4940)
- The use of the `IFS` variable for `read` is deprecated; `IFS` will be ignored in the future (#4156). Use the `read --delimiter` option instead.
- The `function --on-process-exit` switch will be removed in future (#4700). Use the `fish_exit` event instead: `function --on-event fish_exit`.
- `$_` is deprecated and will removed in the future (#813). Use `status current-command` in a command substitution instead.
- `^` as a redirection deprecated and will be removed in the future. (#4394). Use `2>` to redirect stderr. This is controlled by the `stderr-nocaret` feature flag.
- `?` as a glob (wildcard) is deprecated and will be removed in the future (#4520). This is controlled by the `qmark-noglob` feature flag.
## Notable fixes and improvements
### Syntax changes and new commands
- fish now supports `&&` (like `and`), `||` (like `or`), and `!` (like `not`), for better migration from POSIX-compliant shells (#4620).
- Variables may be used as commands (#154).
- fish may be started in private mode via `fish --private`. Private mode fish sessions do not have access to the history file and any commands evaluated in private mode are not persisted for future sessions. A session variable `$fish_private_mode` can be queried to detect private mode and adjust the behavior of scripts accordingly to respect the user's wish for privacy.
- A new `wait` command for waiting on backgrounded processes (#4498).
- `math` is now a builtin rather than a wrapper around `bc` (#3157). Floating point computations is now used by default, and can be controlled with the new `--scale` option (#4478).
- Setting `$PATH` no longer warns on non-existent directories, allowing for a single $PATH to be shared across machines (eg via dotfiles) (#2969).
- `while` sets `$status` to a non-zero value if the loop is not executed (#4982).
- Command substitution output is now limited to 10 MB by default, controlled by the `fish_read_limit` variable (#3822). Notably, this is larger than most operating systems' argument size limit, so trying to pass argument lists this size to external commands has never worked.
- The machine hostname, where available, is now exposed as the `$hostname` reserved variable. This removes the dependency on the `hostname` executable (#4422).
- Bare `bind` invocations in config.fish now work. The `fish_user_key_bindings` function is no longer necessary, but will still be executed if it exists (#5191).
- `$fish_pid` and `$last_pid` are available as replacements for `%self` and `%last`.
### New features in commands
- `alias` has a new `--save` option to save the generated function immediately (#4878).
- `bind` has a new `--silent` option to ignore bind requests for named keys not available under the current terminal (#4188, #4431).
- `complete` has a new `--keep-order` option to show the provided or dynamically-generated argument list in the same order as specified, rather than alphabetically (#361).
- `exec` prompts for confirmation if background jobs are running.
- `funced` has a new `--save` option to automatically save the edited function after successfully editing (#4668).
- `functions` has a new ` --handlers` option to show functions registered as event handlers (#4694).
- `history search` supports globs for wildcard searching (#3136) and has a new `--reverse` option to show entries from oldest to newest (#4375).
- `jobs` has a new `--quiet` option to silence the output.
- `read` has a new `--delimiter` option for splitting input into arrays (#4256).
- `read` writes directly to stdout if called without arguments (#4407).
- `read` can now read individual lines into separate variables without consuming the input in its entirety via the new `/--line` option.
- `set` has new `--append` and `--prepend` options (#1326).
- `set` has a new `--show` option to show lots of information about variables (#4265).
- `string match` with an empty pattern and `--entire` in glob mode now matches everything instead of nothing (#4971).
- `string split` supports a new `--no-empty` option to exclude empty strings from the result (#4779).
- `string` has new subcommands `split0` and `join0` for working with NUL-delimited output.
- `string` no longer stops processing text after NUL characters (#4605)
- `string escape` has a new `--style regex` option for escaping strings to be matched literally in `string` regex operations.
- `test` now supports floating point values in numeric comparisons.
### Interactive improvements
- A pipe at the end of a line now allows the job to continue on the next line (#1285).
- Italics and dim support out of the box on macOS for Terminal.app and iTerm (#4436).
- `cd` tab completions no longer descend into the deepest unambiguous path (#4649).
- Pager navigation has been improved. Most notably, moving down now wraps around, moving up from the commandline now jumps to the last element and moving right and left now reverse each other even when wrapping around (#4680).
- Typing normal characters while the completion pager is active no longer shows the search field. Instead it enters them into the command line, and ends paging (#2249).
- A new input binding `pager-toggle-search` toggles the search field in the completions pager on and off. By default, this is bound to Ctrl-S.
- Searching in the pager now does a full fuzzy search (#5213).
- The pager will now show the full command instead of just its last line if the number of completions is large (#4702).
- Abbreviations can be tab-completed (#3233).
- Tildes in file names are now properly escaped in completions (#2274).
- Wrapping completions (from `complete --wraps` or `function --wraps`) can now inject arguments. For example, `complete gco --wraps 'git checkout'` now works properly (#1976). The `alias` function has been updated to respect this behavior.
- Path completions now support expansions, meaning expressions like `python ~/<TAB>` now provides file suggestions just like any other relative or absolute path. (This includes support for other expansions, too.)
- Autosuggestions try to avoid arguments that are already present in the command line.
- Notifications about crashed processes are now always shown, even in command substitutions (#4962).
- The screen is no longer reset after a BEL, fixing graphical glitches (#3693).
- vi-mode now supports ';' and ',' motions. This introduces new {forward,backward}-jump-till and repeat-jump{,-reverse} bind functions (#5140).
- The `*y` vi-mode binding now works (#5100).
- True color is now enabled in neovim by default (#2792).
- Terminal size variables (`$COLUMNS`/`$LINES`) are now updated before `fish_prompt` is called, allowing the prompt to react (#904).
- Multi-line prompts no longer repeat when the terminal is resized (#2320).
- `xclip` support has been added to the clipboard integration (#5020).
- The Alt-P keybinding paginates the last command if the command line is empty.
- `$cmd_duration` is no longer reset when no command is executed (#5011).
- Deleting a one-character word no longer erases the next word as well (#4747).
- Token history search (Alt-Up) omits duplicate entries (#4795).
- The `fish_escape_delay_ms` timeout, allowing the use of the escape key both on its own and as part of a control sequence, was applied to all control characters; this has been reduced to just the escape key.
- Completing a function shows the description properly (#5206).
- Added completions for
- `ansible`, including `ansible-galaxy`, `ansible-playbook` and `ansible-vault` (#4697)
- `bb-power` (#4800)
- `bd` (#4472)
- `bower`
- `clang` and `clang++` (#4174)
- `conda` (#4837)
- `configure` (for autoconf-generated files only)
- `curl`
- `doas` (#5196)
- `ebuild` (#4911)
- `emaint` (#4758)
- `eopkg` (#4600)
- `exercism` (#4495)
- `hjson`
- `hugo` (#4529)
- `j` (from autojump #4344)
- `jbake` (#4814)
- `jhipster` (#4472)
- `kitty`
- `kldload`
- `kldunload`
- `makensis` (#5242)
- `meson`
- `mkdocs` (#4906)
- `ngrok` (#4642)
- OpenBSD's `pkg_add`, `pkg_delete`, `pkg_info`, `pfctl`, `rcctl`, `signify`, and `vmctl` (#4584)
- `openocd`
- `optipng`
- `opkg` (#5168)
- `pandoc` (#2937)
- `port` (#4737)
- `powerpill` (#4800)
- `pstack` (#5135)
- `serve` (#5026)
- `ttx`
- `unzip`
- `virsh` (#5113)
- `xclip` (#5126)
- `xsv`
- `zfs` and `zpool` (#4608)
- Lots of improvements to completions (especially `darcs` (#5112), `git`, `hg` and `sudo`).
- Completions for `yarn` and `npm` now require the `all-the-package-names` NPM package for full functionality.
- Completions for `bower` and `yarn` now require the `jq` utility for full functionality.
- Improved French translations.
### Other fixes and improvements
- Significant performance improvements to `abbr` (#4048), setting variables (#4200, #4341), executing functions, globs (#4579), `string` reading from standard input (#4610), and slicing history (in particular, `$history[1]` for the last executed command).
- Fish's internal wcwidth function has been updated to deal with newer Unicode, and the width of some characters can be configured via the `fish_ambiguous_width` (#5149) and `fish_emoji_width` (#2652) variables. Alternatively, a new build-time option INTERNAL_WCWIDTH can be used to use the system's wcwidth instead (#4816).
- `functions` correctly supports `-d` as the short form of `--description`. (#5105)
- `/etc/paths` is now parsed like macOS' bash `path_helper`, fixing $PATH order (#4336, #4852) on macOS.
- Using a read-only variable in a `for` loop produces an error, rather than silently producing incorrect results (#4342).
- The universal variables filename no longer contains the hostname or MAC address. It is now at the fixed location `.config/fish/fish_variables` (#1912).
- Exported variables in the global or universal scope no longer have their exported status affected by local variables (#2611).
- Major rework of terminal and job handling to eliminate bugs (#3805, #3952, #4178, #4235, #4238, #4540, #4929, #5210).
- Improvements to the manual page completion generator (#2937, #4313).
- `suspend --force` now works correctly (#4672).
- Pressing Ctrl-C while running a script now reliably terminates fish (#5253).
### For distributors and developers
- fish ships with a new build system based on CMake. CMake 3.2 is the minimum required version. Although the autotools-based Makefile and the Xcode project are still shipped with this release, they will be removed in the near future. All distributors and developers are encouraged to migrate to the CMake build.
- Build scripts for most platforms no longer require bash, using the standard sh instead.
- The `hostname` command is no longer required for fish to operate.
--
# fish 2.7.1 (released December 23, 2017)
This release of fish fixes an issue where iTerm 2 on macOS would display a warning about paste bracketing being left on when starting a new fish session (#4521).
If you are upgrading from version 2.6.0 or before, please also review the release notes for 2.7.0 and 2.7b1 (included below).
--
# fish 2.7.0 (released November 23, 2017)
There are no major changes between 2.7b1 and 2.7.0. If you are upgrading from version 2.6.0 or before, please also review the release notes for 2.7b1 (included below).
Xcode builds and macOS packages could not be produced with 2.7b1, but this is fixed in 2.7.0.
--
# fish 2.7b1 (released October 31, 2017)
## Notable improvements
- A new `cdh` (change directory using recent history) command provides a more friendly alternative to prevd/nextd and pushd/popd (#2847).
- A new `argparse` command is available to allow fish script to parse arguments with the same behavior as builtin commands. This also includes the `fish_opt` helper command. (#4190).
- Invalid array indexes are now silently ignored (#826, #4127).
- Improvements to the debugging facility, including a prompt specific to the debugger (`fish_breakpoint_prompt`) and a `status is-breakpoint` subcommand (#1310).
- `string` supports new `lower` and `upper` subcommands, for altering the case of strings (#4080). The case changing is not locale-aware yet.- `string escape` has a new `--style=xxx` flag where `xxx` can be `script`, `var`, or `url` (#4150), and can be reversed with `string unescape` (#3543).
- History can now be split into sessions with the `fish_history` variable, or not saved to disk at all (#102).
- Read history is now controlled by the `fish_history` variable rather than the `--mode-name` flag (#1504).
- `command` now supports an `--all` flag to report all directories with the command. `which` is no longer a runtime dependency (#2778).
- fish can run commands before starting an interactive session using the new `--init-command`/`-C` options (#4164).
- `set` has a new `--show` option to show lots of information about variables (#4265).
## Other significant changes
- The `COLUMNS` and `LINES` environment variables are now correctly set the first time `fish_prompt` is run (#4141).
- `complete`'s `--no-files` option works as intended (#112).
- `echo -h` now correctly echoes `-h` in line with other shells (#4120).
- The `export` compatibility function now returns zero on success, rather than always returning 1 (#4435).
- Stop converting empty elements in MANPATH to "." (#4158). The behavior being changed was introduced in fish 2.6.0.
- `count -h` and `count --help` now return 1 rather than produce command help output (#4189).
- An attempt to `read` which stops because too much data is available still defines the variables given as parameters (#4180).
- A regression in fish 2.4.0 which prevented `pushd +1` from working has been fixed (#4091).
- A regression in fish 2.6.0 where multiple `read` commands in non-interactive scripts were broken has been fixed (#4206).
- A regression in fish 2.6.0 involving universal variables with side-effects at startup such as `set -U fish_escape_delay_ms 10` has been fixed (#4196).
- Added completions for:
- `as` (#4130)
- `cdh` (#2847)
- `dhcpd` (#4115)
- `ezjail-admin` (#4324)
- Fabric's `fab` (#4153)
- `grub-file` (#4119)
- `grub-install` (#4119)
- `jest` (#4142)
- `kdeconnect-cli`
- `magneto` (#4043, #4108)
- `mdadm` (#4198)
- `passwd` (#4209)
- `pip` and `pipenv` (#4448)
- `s3cmd` (#4332)
- `sbt` (#4347)
- `snap` (#4215)
- Sublime Text 3's `subl` (#4277)
- Lots of improvements to completions.
- Updated Chinese and French translations.
- Improved completions for:
- `apt`
- `cd` (#4061)
- `composer` (#4295)
- `eopkg`
- `flatpak` (#4456)
- `git` (#4117, #4147, #4329, #4368)
- `gphoto2`
- `killall` (#4052)
- `ln`
- `npm` (#4241)
- `ssh` (#4377)
- `tail`
- `xdg-mime` (#4333)
- `zypper` (#4325)
---
# fish 2.6.0 (released June 3, 2017)
Since the beta release of fish 2.6b1, fish version 2.6.0 contains a number of minor fixes, new completions for `magneto` (#4043), and improvements to the documentation.
## Known issues
- Apple macOS Sierra 10.12.5 introduced a problem with launching web browsers from other programs using AppleScript. This affects the fish Web configuration (`fish_config`); users on these platforms will need to manually open the address displayed in the terminal, such as by copying and pasting it into a browser. This problem will be fixed with macOS 10.12.6.
If you are upgrading from version 2.5.0 or before, please also review the release notes for 2.6b1 (included below).
---
# fish 2.6b1 (released May 14, 2017)
## Notable fixes and improvements
- Jobs running in the background can now be removed from the list of jobs with the new `disown` builtin, which behaves like the same command in other shells (#2810).
- Command substitutions now have access to the terminal, like in other shells. This allows tools like `fzf` to work properly (#1362, #3922).
- In cases where the operating system does not report the size of the terminal, the `COLUMNS` and `LINES` environment variables are used; if they are unset, a default of 80x24 is assumed.
- New French (#3772 & #3788) and improved German (#3834) translations.
- fish no longer depends on the `which` external command.
## Other significant changes
- Performance improvements in launching processes, including major reductions in signal blocking. Although this has been heavily tested, it may cause problems in some circumstances; set the `FISH_NO_SIGNAL_BLOCK` variable to 0 in your fish configuration file to return to the old behaviour (#2007).
- Performance improvements in prompts and functions that set lots of colours (#3793).
- The Delete key no longer deletes backwards (a regression in 2.5.0).
- `functions` supports a new `--details` option, which identifies where the function was loaded from (#3295), and a `--details --verbose` option which includes the function description (#597).
- `read` will read up to 10 MiB by default, leaving the target variable empty and exiting with status 122 if the line is too long. You can set a different limit with the `FISH_READ_BYTE_LIMIT` variable.
- `read` supports a new `--silent` option to hide the characters typed (#838), for when reading sensitive data from the terminal. `read` also now accepts simple strings for the prompt (rather than scripts) with the new `-P` and `--prompt-str` options (#802).
- `export` and `setenv` now understand colon-separated `PATH`, `CDPATH` and `MANPATH` variables.
- `setenv` is no longer a simple alias for `set -gx` and will complain, just like the csh version, if given more than one value (#4103).
- `bind` supports a new `--list-modes` option (#3872).
- `bg` will check all of its arguments before backgrounding any jobs; any invalid arguments will cause a failure, but non-existent (eg recently exited) jobs are ignored (#3909).
- `funced` warns if the function being edited has not been modified (#3961).
- `printf` correctly outputs "long long" integers (#3352).
- `status` supports a new `current-function` subcommand to print the current function name (#1743).
- `string` supports a new `repeat` subcommand (#3864). `string match` supports a new `--entire` option to emit the entire line matched by a pattern (#3957). `string replace` supports a new `--filter` option to only emit lines which underwent a replacement (#3348).
- `test` supports the `-k` option to test for sticky bits (#733).
- `umask` understands symbolic modes (#738).
- Empty components in the `CDPATH`, `MANPATH` and `PATH` variables are now converted to "." (#2106, #3914).
- New versions of ncurses (6.0 and up) wipe terminal scrollback buffers with certain commands; the `C-l` binding tries to avoid this (#2855).
- Some systems' `su` implementations do not set the `USER` environment variable; it is now reset for root users (#3916).
- Under terminals which support it, bracketed paste is enabled, escaping problematic characters for security and convience (#3871). Inside single quotes (`'`), single quotes and backslashes in pasted text are escaped (#967). The `fish_clipboard_paste` function (bound to `C-v` by default) is still the recommended pasting method where possible as it includes this functionality and more.
- Processes in pipelines are no longer signalled as soon as one command in the pipeline has completed (#1926). This behaviour matches other shells mre closely.
- All functions requiring Python work with whichever version of Python is installed (#3970). Python 3 is preferred, but Python 2.6 remains the minimum version required.
- The color of the cancellation character can be controlled by the `fish_color_cancel` variable (#3963).
- Added completions for:
- `caddy` (#4008)
- `castnow` (#3744)
- `climate` (#3760)
- `flatpak`
- `gradle` (#3859)
- `gsettings` (#4001)
- `helm` (#3829)
- `i3-msg` (#3787)
- `ipset` (#3924)
- `jq` (#3804)
- `light` (#3752)
- `minikube` (#3778)
- `mocha` (#3828)
- `mkdosfs` (#4017)
- `pv` (#3773)
- `setsid` (#3791)
- `terraform` (#3960)
- `usermod` (#3775)
- `xinput`
- `yarn` (#3816)
- Improved completions for `adb` (#3853), `apt` (#3771), `bzr` (#3769), `dconf`, `git` (including #3743), `grep` (#3789), `go` (#3789), `help` (#3789), `hg` (#3975), `htop` (#3789), `killall` (#3996), `lua`, `man` (#3762), `mount` (#3764 & #3841), `obnam` (#3924), `perl` (#3856), `portmaster` (#3950), `python` (#3840), `ssh` (#3781), `scp` (#3781), `systemctl` (#3757) and `udisks` (#3764).
---
# fish 2.5.0 (released February 3, 2017)
There are no major changes between 2.5b1 and 2.5.0. If you are upgrading from version 2.4.0 or before, please also review the release notes for 2.5b1 (included below).
## Notable fixes and improvements
- The Home, End, Insert, Delete, Page Up and Page Down keys work in Vi-style key bindings (#3731).
---
# fish 2.5b1 (released January 14, 2017)
## Platform Changes
Starting with version 2.5, fish requires a more up-to-date version of C++, specifically C++11 (from 2011). This affects some older platforms:
### Linux
For users building from source, GCC's g++ 4.8 or later, or LLVM's clang 3.3 or later, are known to work. Older platforms may require a newer compiler installed.
Unfortunately, because of the complexity of the toolchain, binary packages are no longer published by the fish-shell developers for the following platforms:
- Red Hat Enterprise Linux and CentOS 5 & 6 for 64-bit builds
- Ubuntu 12.04 (EoLTS April 2017)
- Debian 7 (EoLTS May 2018)
Installing newer version of fish on these systems will require building from source.
### OS X SnowLeopard
Starting with version 2.5, fish requires a C++11 standard library on OS X 10.6 ("SnowLeopard"). If this library is not installed, you will see this error: `dyld: Library not loaded: /usr/lib/libc++.1.dylib`
MacPorts is the easiest way to obtain this library. After installing the SnowLeopard MacPorts release from the install page, run:
```
sudo port -v install libcxx
```
Now fish should launch successfully. (Please open an issue if it does not.)
This is only necessary on 10.6. OS X 10.7 and later include the required library by default.
## Other significant changes
- Attempting to exit with running processes in the background produces a warning, then signals them to terminate if a second attempt to exit is made. This brings the behaviour for running background processes into line with stopped processes. (#3497)
- `random` can now have start, stop and step values specified, or the new `choice` subcommand can be used to pick an argument from a list (#3619).
- A new key bindings preset, `fish_hybrid_key_bindings`, including all the Emacs-style and Vi-style bindings, which behaves like `fish_vi_key_bindings` in fish 2.3.0 (#3556).
- `function` now returns an error when called with invalid options, rather than defining the function anyway (#3574). This was a regression present in fish 2.3 and 2.4.0.
- fish no longer prints a warning when it identifies a running instance of an old version (2.1.0 and earlier). Changes to universal variables may not propagate between these old versions and 2.5b1.
- Improved compatiblity with Android (#3585), MSYS/mingw (#2360), and Solaris (#3456, #3340).
- Like other shells, the `test` builting now returns an error for numeric operations on invalid integers (#3346, #3581).
- `complete` no longer recognises `--authoritative` and `--unauthoritative` options, and they are marked as obsolete.
- `status` accepts subcommands, and should be used like `status is-interactive`. The old options continue to be supported for the foreseeable future (#3526), although only one subcommand or option can be specified at a time.
- Selection mode (used with "begin-selection") no longer selects a character the cursor does not move over (#3684).
- List indexes are handled better, and a bit more liberally in some cases (`echo $PATH[1 .. 3]` is now valid) (#3579).
- The `fish_mode_prompt` function is now simply a stub around `fish_default_mode_prompt`, which allows the mode prompt to be included more easily in customised prompt functions (#3641).
## Notable fixes and improvements
- `alias`, run without options or arguments, lists all defined aliases, and aliases now include a description in the function signature that identifies them.
- `complete` accepts empty strings as descriptions (#3557).
- `command` accepts `-q`/`--quiet` in combination with `--search` (#3591), providing a simple way of checking whether a command exists in scripts.
- Abbreviations can now be renamed with `abbr --rename OLD_KEY NEW_KEY` (#3610).
- The command synopses printed by `--help` options work better with copying and pasting (#2673).
- `help` launches the browser specified by the `$fish_help_browser variable` if it is set (#3131).
- History merging could lose items under certain circumstances and is now fixed (#3496).
- The `$status` variable is now set to 123 when a syntactically invalid command is entered (#3616).
- Exiting fish now signals all background processes to terminate, not just stopped jobs (#3497).
- A new `prompt_hostname` function which prints a hostname suitable for use in prompts (#3482).
- The `__fish_man_page` function (bound to Alt-h by default) now tries to recognize subcommands (e.g. `git add` will now open the "git-add" man page) (#3678).
- A new function `edit_command_buffer` (bound to Alt-e & Alt-v by default) to edit the command buffer in an external editor (#1215, #3627).
- `set_color` now supports italics (`--italics`), dim (`--dim`) and reverse (`--reverse`) modes (#3650).
- Filesystems with very slow locking (eg incorrectly-configured NFS) will no longer slow fish down (#685).
- Improved completions for `apt` (#3695), `fusermount` (#3642), `make` (#3628), `netctl-auto` (#3378), `nmcli` (#3648), `pygmentize` (#3378), and `tar` (#3719).
- Added completions for:
- `VBoxHeadless` (#3378)
- `VBoxSDL` (#3378)
- `base64` (#3378)
- `caffeinate` (#3524)
- `dconf` (#3638)
- `dig` (#3495)
- `dpkg-reconfigure` (#3521 & #3522)
- `feh` (#3378)
- `launchctl` (#3682)
- `lxc` (#3554 & #3564),
- `mddiagnose` (#3524)
- `mdfind` (#3524)
- `mdimport` (#3524)
- `mdls` (#3524)
- `mdutil` (#3524)
- `mkvextract` (#3492)
- `nvram` (#3524)
- `objdump` (#3378)
- `sysbench` (#3491)
- `tmutil` (#3524)
---
# fish 2.4.0 (released November 8, 2016)
There are no major changes between 2.4b1 and 2.4.0.
## Notable fixes and improvements
- The documentation is now generated properly and with the correct version identifier.
- Automatic cursor changes are now only enabled on the subset of XTerm versions known to support them, resolving a problem where older versions printed garbage to the terminal before and after every prompt (#3499).
- Improved the title set in Apple Terminal.app.
- Added completions for `defaults` and improved completions for `diskutil` (#3478).
---
# fish 2.4b1 (released October 18, 2016)
## Significant changes
- The clipboard integration has been revamped with explicit bindings. The killring commands no longer copy from, or paste to, the X11 clipboard - use the new copy (`C-x`) and paste (`C-v`) bindings instead. The clipboard is now available on OS X as well as systems using X11 (e.g. Linux). (#3061)
- `history` uses subcommands (`history delete`) rather than options (`history --delete`) for its actions (#3367). You can no longer specify multiple actions via flags (e.g., `history --delete --save something`).
- New `history` options have been added, including `--max=n` to limit the number of history entries, `--show-time` option to show timestamps (#3175, #3244), and `--null` to null terminate history entries in the search output.
- `history search` is now case-insensitive by default (which also affects `history delete`) (#3236).
- `history delete` now correctly handles multiline commands (#31).
- Vi-style bindings no longer include all of the default emacs-style bindings; instead, they share some definitions (#3068).
- If there is no locale set in the environment, various known system configuration files will be checked for a default. If no locale can be found, `en_US-UTF.8` will be used (#277).
- A number followed by a caret (e.g. `5^`) is no longer treated as a redirection (#1873).
- The `$version` special variable can be overwritten, so that it can be used for other purposes if required.
## Notable fixes and improvements
- The `fish_realpath` builtin has been renamed to `realpath` and made compatible with GNU `realpath` when run without arguments (#3400). It is used only for systems without a `realpath` or `grealpath` utility (#3374).
- Improved color handling on terminals/consoles with 8-16 colors, particularly the use of bright named color (#3176, #3260).
- `fish_indent` can now read from files given as arguments, rather than just standard input (#3037).
- Fuzzy tab completions behave in a less surprising manner (#3090, #3211).
- `jobs` should only print its header line once (#3127).
- Wildcards in redirections are highlighted appropriately (#2789).
- Suggestions will be offered more often, like after removing characters (#3069).
- `history --merge` now correctly interleaves items in chronological order (#2312).
- Options for `fish_indent` have been aligned with the other binaries - in particular, `-d` now means `--debug`. The `--dump` option has been renamed to `--dump-parse-tree` (#3191).
- The display of bindings in the Web-based configuration has been greatly improved (#3325), as has the rendering of prompts (#2924).
- fish should no longer hang using 100% CPU in the C locale (#3214).
- A bug in FreeBSD 11 & 12, Dragonfly BSD & illumos prevented fish from working correctly on these platforms under UTF-8 locales; fish now avoids the buggy behaviour (#3050).
- Prompts which show git repository information (via `__fish_git_prompt`) are faster in large repositories (#3294) and slow filesystems (#3083).
- fish 2.3.0 reintroduced a problem where the greeting was printed even when using `read`; this has been corrected again (#3261).
- Vi mode changes the cursor depending on the current mode (#3215).
- Command lines with escaped space characters at the end tab-complete correctly (#2447).
- Added completions for:
- `arcanist` (#3256)
- `connmanctl` (#3419)
- `figlet` (#3378)
- `mdbook` (#3378)
- `ninja` (#3415)
- `p4`, the Perforce client (#3314)
- `pygmentize` (#3378)
- `ranger` (#3378)
- Improved completions for `aura` (#3297), `abbr` (#3267), `brew` (#3309), `chown` (#3380, #3383),`cygport` (#3392), `git` (#3274, #3226, #3225, #3094, #3087, #3035, #3021, #2982, #3230), `kill` & `pkill` (#3200), `screen` (#3271), `wget` (#3470), and `xz` (#3378).
- Distributors, packagers and developers will notice that the build process produces more succinct output by default; use `make V=1` to get verbose output (#3248).
- Improved compatibility with minor platforms including musl (#2988), Cygwin (#2993), Android (#3441, #3442), Haiku (#3322) and Solaris .
---
# fish 2.3.1 (released July 3, 2016)
This is a functionality and bugfix release. This release does not contain all the changes to fish since the last release, but fixes a number of issues directly affecting users at present and includes a small number of new features.
## Significant changes
- A new `fish_key_reader` binary for decoding interactive keypresses (#2991).
- `fish_mode_prompt` has been updated to reflect the changes in the way the Vi input mode is set up (#3067), making this more reliable.
- `fish_config` can now properly be launched from the OS X app bundle (#3140).
## Notable fixes and improvements
- Extra lines were sometimes inserted into the output under Windows (Cygwin and Microsoft Windows Subsystem for Linux) due to TTY timestamps not being updated (#2859).
- The `string` builtin's `match` mode now handles the combination of `-rnv` (match, invert and count) correctly (#3098).
- Improvements to TTY special character handling (#3064), locale handling (#3124) and terminal environment variable handling (#3060).
- Work towards handling the terminal modes for external commands launched from initialisation files (#2980).
- Ease the upgrade path from fish 2.2.0 and before by warning users to restart fish if the `string` builtin is not available (#3057).
- `type -a` now syntax-colorizes function source output.
- Added completions for `alsamixer`, `godoc`, `gofmt`, `goimports`, `gorename`, `lscpu`, `mkdir`, `modinfo`, `netctl-auto`, `poweroff`, `termite`, `udisksctl` and `xz` (#3123).
- Improved completions for `apt` (#3097), `aura` (#3102),`git` (#3114), `npm` (#3158), `string` and `suspend` (#3154).
---
# fish 2.3.0 (released May 20, 2016)
There are no significant changes between 2.3.0 and 2.3b2.
## Other notable fixes and improvements
- `abbr` now allows non-letter keys (#2996).
- Define a few extra colours on first start (#2987).
- Multiple documentation updates.
- Added completions for rmmod (#3007).
- Improved completions for git (#2998).
## Known issues
- Interactive commands started from fish configuration files or from the `-c` option may, under certain circumstances, be started with incorrect terminal modes and fail to behave as expected. A fix is planned but requires further testing (#2619).
---
# fish 2.3b2 (released May 5, 2016)
## Significant changes
- A new `fish_realpath` builtin and associated function to allow the use of `realpath` even on those platforms that don't ship an appropriate command (#2932).
- Alt-# toggles the current command line between commented and uncommented states, making it easy to save a command in history without executing it.
- The `fish_vi_mode` function is now deprecated in favour of `fish_vi_key_bindings`.
## Other notable fixes and improvements
- Fix the build on Cygwin (#2952) and RedHat Enterprise Linux/CentOS 5 (#2955).
- Avoid confusing the terminal line driver with non-printing characters in `fish_title` (#2453).
- Improved completions for busctl, git (#2585, #2879, #2984), and netctl.
---
# fish 2.3b1 (released April 19, 2016)
## Significant Changes
- A new `string` builtin to handle... strings! This builtin will measure, split, search and replace text strings, including using regular expressions. It can also be used to turn lists into plain strings using `join`. `string` can be used in place of `sed`, `grep`, `tr`, `cut`, and `awk` in many situations. (#2296)
- Allow using escape as the Meta modifier key, by waiting after seeing an escape character wait up to 300ms for an additional character. This is consistent with readline (e.g. bash) and can be configured via the `fish_escape_delay_ms variable`. This allows using escape as the Meta modifier. (#1356)
- Add new directories for vendor functions and configuration snippets (#2500)
- A new `fish_realpath` builtin and associated `realpath` function should allow scripts to resolve path names via `realpath` regardless of whether there is an external command of that name; albeit with some limitations. See the associated documentation.
## Backward-incompatible changes
- Unmatched globs will now cause an error, except when used with `for`, `set` or `count` (#2719)
- `and` and `or` will now bind to the closest `if` or `while`, allowing compound conditions without `begin` and `end` (#1428)
- `set -ql` now searches up to function scope for variables (#2502)
- `status -f` will now behave the same when run as the main script or using `source` (#2643)
- `source` no longer puts the file name in `$argv` if no arguments are given (#139)
- History files are stored under the `XDG_DATA_HOME` hierarchy (by default, in `~/.local/share`), and existing history will be moved on first use (#744)
## Other notable fixes and improvements
- Fish no longer silences errors in config.fish (#2702)
- Directory autosuggestions will now descend as far as possible if there is only one child directory (#2531)
- Add support for bright colors (#1464)
- Allow Ctrl-J (\cj) to be bound separately from Ctrl-M (\cm) (#217)
- psub now has a "-s"/"&#x2013;suffix" option to name the temporary file with that suffix
- Enable 24-bit colors on select terminals (#2495)
- Support for SVN status in the prompt (#2582)
- Mercurial and SVN support have been added to the Classic + Git (now Classic + VCS) prompt (via the new \__fish_vcs_prompt function) (#2592)
- export now handles variables with a "=" in the value (#2403)
- New completions for:
- alsactl
- Archlinux's asp, makepkg
- Atom's apm (#2390)
- entr - the "Event Notify Test Runner" (#2265)
- Fedora's dnf (#2638)
- OSX diskutil (#2738)
- pkgng (#2395)
- pulseaudio's pacmd and pactl
- rust's rustc and cargo (#2409)
- sysctl (#2214)
- systemd's machinectl (#2158), busctl (#2144), systemd-nspawn, systemd-analyze, localectl, timedatectl
- and more
- Fish no longer has a function called sgrep, freeing it for user customization (#2245)
- A rewrite of the completions for cd, fixing a few bugs (#2299, #2300, #562)
- Linux VTs now run in a simplified mode to avoid issues (#2311)
- The vi-bindings now inherit from the emacs bindings
- Fish will also execute `fish_user_key_bindings` when in vi-mode
- `funced` will now also check $VISUAL (#2268)
- A new `suspend` function (#2269)
- Subcommand completion now works better with split /usr (#2141)
- The command-not-found-handler can now be overridden by defining a function called `__fish_command_not_found_handler` in config.fish (#2332)
- A few fixes to the Sorin theme
- PWD shortening in the prompt can now be configured via the `fish_prompt_pwd_dir_length` variable, set to the length per path component (#2473)
- fish no longer requires `/etc/fish/config.fish` to correctly start, and now ships a skeleton file that only contains some documentation (#2799)
---
# fish 2.2.0 (released July 12, 2015)
### Significant changes ###
* Abbreviations: the new `abbr` command allows for interactively-expanded abbreviations, allowing quick access to frequently-used commands (#731).
* Vi mode: run `fish_vi_mode` to switch fish into the key bindings and prompt familiar to users of the Vi editor (#65).
* New inline and interactive pager, which will be familiar to users of zsh (#291).
* Underlying architectural changes: the `fishd` universal variable server has been removed as it was a source of many bugs and security problems. Notably, old fish sessions will not be able to communicate universal variable changes with new fish sessions. For best results, restart all running instances of `fish`.
* The web-based configuration tool has been redesigned, featuring a prompt theme chooser and other improvements.
* New German, Brazilian Portuguese, and Chinese translations.
### Backward-incompatible changes ###
These are kept to a minimum, but either change undocumented features or are too hard to use in their existing forms. These changes may break existing scripts.
* `commandline` no longer interprets functions "in reverse", instead behaving as expected (#1567).
* The previously-undocumented `CMD_DURATION` variable is now set for all commands and contains the execution time of the last command in milliseconds (#1585). It is no longer exported to other commands (#1896).
* `if` / `else` conditional statements now return values consistent with the Single Unix Specification, like other shells (#1443).
* A new "top-level" local scope has been added, allowing local variables declared on the commandline to be visible to subsequent commands. (#1908)
### Other notable fixes and improvements ###
* New documentation design (#1662), which requires a Doxygen version 1.8.7 or newer to build.
* Fish now defines a default directory for other packages to provide completions. By default this is `/usr/share/fish/vendor-completions.d`; on systems with `pkgconfig` installed this path is discoverable with `pkg-config --variable completionsdir fish`.
* A new parser removes many bugs; all existing syntax should keep working.
* New `fish_preexec` and `fish_postexec` events are fired before and after job execution respectively (#1549).
* Unmatched wildcards no longer prevent a job from running. Wildcards used interactively will still print an error, but the job will proceed and the wildcard will expand to zero arguments (#1482).
* The `.` command is deprecated and the `source` command is preferred (#310).
* `bind` supports "bind modes", which allows bindings to be set for a particular named mode, to support the implementation of Vi mode.
* A new `export` alias, which behaves like other shells (#1833).
* `command` has a new `--search` option to print the name of the disk file that would be executed, like other shells' `command -v` (#1540).
* `commandline` has a new `--paging-mode` option to support the new pager.
* `complete` has a new `--wraps` option, which allows a command to (recursively) inherit the completions of a wrapped command (#393), and `complete -e` now correctly erases completions (#380).
* Completions are now generated from manual pages by default on the first run of fish (#997).
* `fish_indent` can now produce colorized (`--ansi`) and HTML (`--html`) output (#1827).
* `functions --erase` now prevents autoloaded functions from being reloaded in the current session.
* `history` has a new `--merge` option, to incorporate history from other sessions into the current session (#825).
* `jobs` returns 1 if there are no active jobs (#1484).
* `read` has several new options:
* `--array` to break input into an array (#1540)
* `--null` to break lines on NUL characters rather than newlines (#1694)
* `--nchars` to read a specific number of characters (#1616)
* `--right-prompt` to display a right-hand-side prompt during interactive read (#1698).
* `type` has a new `-q` option to suppress output (#1540 and, like other shells, `type -a` now prints all matches for a command (#261).
* Pressing F1 now shows the manual page for the current command (#1063).
* `fish_title` functions have access to the arguments of the currently running argument as `$argv[1]` (#1542).
* The OS command-not-found handler is used on Arch Linux (#1925), nixOS (#1852), openSUSE and Fedora (#1280).
* `Alt`+`.` searches backwards in the token history, mapping to the same behavior as inserting the last argument of the previous command, like other shells (#89).
* The `SHLVL` environment variable is incremented correctly (#1634 & #1693).
* Added completions for `adb` (#1165 & #1211), `apt` (#2018), `aura` (#1292), `composer` (#1607), `cygport` (#1841), `dropbox` (#1533), `elixir` (#1167), `fossil`, `heroku` (#1790), `iex` (#1167), `kitchen` (#2000), `nix` (#1167), `node`/`npm` (#1566), `opam` (#1615), `setfacl` (#1752), `tmuxinator` (#1863), and `yast2` (#1739).
* Improved completions for `brew` (#1090 & #1810), `bundler` (#1779), `cd` (#1135), `emerge` (#1840),`git` (#1680, #1834 & #1951), `man` (#960), `modprobe` (#1124), `pacman` (#1292), `rpm` (#1236), `rsync` (#1872), `scp` (#1145), `ssh` (#1234), `sshfs` (#1268), `systemctl` (#1462, #1950 & #1972), `tmux` (#1853), `vagrant` (#1748), `yum` (#1269), and `zypper` (#1787).
---
# fish 2.1.2 (released Feb 24, 2015)
fish 2.1.2 contains a workaround for a filesystem bug in Mac OS X Yosemite. #1859
Specifically, after installing fish 2.1.1 and then rebooting, "Verify Disk" in Disk Utility will report "Invalid number of hard links." We don't have any reports of data loss or other adverse consequences. fish 2.1.2 avoids triggering the bug, but does not repair an already affected filesystem. To repair the filesystem, you can boot into Recovery Mode and use Repair Disk from Disk Utility. Linux and versions of OS X prior to Yosemite are believed to be unaffected.
There are no other changes in this release.
---
# fish 2.1.1 (released September 26, 2014)
__Important:__ if you are upgrading, stop all running instances of `fishd` as soon as possible after installing this release; it will be restarted automatically. On most systems, there will be no further action required. Note that some environments (where `XDG_RUNTIME_DIR` is set), such as Fedora 20, will require a restart of all running fish processes before universal variables work as intended.
Distributors are highly encouraged to call `killall fishd`, `pkill fishd` or similar in installation scripts, or to warn their users to do so.
### Security fixes
* The fish_config web interface now uses an authentication token to protect requests and only responds to requests from the local machine with this token, preventing a remote code execution attack. (closing CVE-2014-2914). #1438
* `psub` and `funced` are no longer vulnerable to attacks which allow local privilege escalation and data tampering (closing CVE-2014-2906 and CVE-2014-3856). #1437
* `fishd` uses a secure path for its socket, preventing a local privilege escalation attack (closing CVE-2014-2905). #1436
* `__fish_print_packages` is no longer vulnerable to attacks which would allow local privilege escalation and data tampering (closing CVE-2014-3219). #1440
### Other fixes
* `fishd` now ignores SIGPIPE, fixing crashes using tools like GNU Parallel and which occurred more often as a result of the other `fishd` changes. #1084 & #1690
---
# fish 2.1.0
Significant Changes
-------------------
* **Tab completions will fuzzy-match files.** #568
When tab-completing a file, fish will first attempt prefix matches (`foo` matches `foobar`), then substring matches (`ooba` matches `foobar`), and lastly subsequence matches (`fbr` matches `foobar`). For example, in a directory with files foo1.txt, foo2.txt, foo3.txt…, you can type only the numeric part and hit tab to fill in the rest.
This feature is implemented for files and executables. It is not yet implemented for options (like `--foobar`), and not yet implemented across path components (like `/u/l/b` to match `/usr/local/bin`).
* **Redirections now work better across pipelines.** #110, #877
In particular, you can pipe stderr and stdout together, for example, with `cmd ^&1 | tee log.txt`, or the more familiar `cmd 2>&1 | tee log.txt`.
* **A single `%` now expands to the last job backgrounded.** #1008
Previously, a single `%` would pid-expand to either all backgrounded jobs, or all jobs owned by your user. Now it expands to the last job backgrounded. If no job is in the background, it will fail to expand. In particular, `fg %` can be used to put the most recent background job in the foreground.
Other Notable Fixes
-------------------
* alt-U and alt+C now uppercase and capitalize words, respectively. #995
* VTE based terminals should now know the working directory. #906
* The autotools build now works on Mavericks. #968
* The end-of-line binding (ctrl+E) now accepts autosuggestions. #932
* Directories in `/etc/paths` (used on OS X) are now prepended instead of appended, similar to other shells. #927
* Option-right-arrow (used for partial autosuggestion completion) now works on iTerm2. #920
* Tab completions now work properly within nested subcommands. #913
* `printf` supports \e, the escape character. #910
* `fish_config history` no longer shows duplicate items. #900
* `$fish_user_paths` is now prepended to $PATH instead of appended. #888
* Jobs complete when all processes complete. #876
For example, in previous versions of fish, `sleep 10 | echo Done` returns control immediately, because echo does not read from stdin. Now it does not complete until sleep exits (presumably after 10 seconds).
* Better error reporting for square brackets. #875
* fish no longer tries to add `/bin` to `$PATH` unless PATH is totally empty. #852
* History token substitution (alt-up) now works correctly inside subshells. #833
* Flow control is now disabled, freeing up ctrl-S and ctrl-Q for other uses. #814
* sh-style variable setting like `foo=bar` now produces better error messages. #809
* Commands with wildcards no longer produce autosuggestions. #785
* funced no longer freaks out when supplied with no arguments. #780
* fish.app now works correctly in a directory containing spaces. #774
* Tab completion cycling no longer occasionally fails to repaint. #765
* Comments now work in eval'd strings. #684
* History search (up-arrow) now shows the item matching the autosuggestion, if that autosuggestion was truncated. #650
* Ctrl-T now transposes characters, as in other shells. #128
---
# fish 2.0.0
Significant Changes
-------------------
* **Command substitutions now modify `$status` #547.**
Previously the exit status of command substitutions (like `(pwd)`) was ignored; however now it modifies $status. Furthermore, the `set` command now only sets $status on failure; it is untouched on success. This allows for the following pattern:
```sh
if set python_path (which python)
...
end
```
Because set does not modify $status on success, the if branch effectively tests whether `which` succeeded, and if so, whether the `set` also succeeded.
* **Improvements to $PATH handling.**
* There is a new variable, `$fish_user_paths`, which can be set universally, and whose contents are appended to $PATH #527
* /etc/paths and /etc/paths.d are now respected on OS X
* fish no longer modifies $PATH to find its own binaries
* **Long lines no longer use ellipsis for line breaks**, and copy and paste
should no longer include a newline even if the line was broken #300
* **New syntax for index ranges** (sometimes known as "slices") #212
* **fish now supports an `else if` statement** #134
* **Process and pid completion now works on OS X** #129
* **fish is now relocatable**, and no longer depends on compiled-in paths #125
* **fish now supports a right prompt (RPROMPT)** through the fish_right_prompt function #80
* **fish now uses posix_spawn instead of fork when possible**, which is much faster on BSD and OS X #11
Other Notable Fixes
-------------------
* Updated VCS completions (darcs, cvs, svn, etc.)
* Avoid calling getcwd on the main thread, as it can hang #696
* Control-D (forward delete) no longer stops at a period #667
* Completions for many new commands
* fish now respects rxvt's unique keybindings #657
* xsel is no longer built as part of fish. It will still be invoked if installed separately #633
* __fish_filter_mime no longer spews #628
* The --no-execute option to fish no longer falls over when reaching the end of a block #624
* fish_config knows how to find fish even if it's not in the $PATH #621
* A leading space now prevents writing to history, as is done in bash and zsh #615
* Hitting enter after a backslash only goes to a new line if it is followed by whitespace or the end of the line #613
* printf is now a builtin #611
* Event handlers should no longer fire if signals are blocked #608
* set_color is now a builtin #578
* man page completions are now located in a new generated_completions directory, instead of your completions directory #576
* tab now clears autosuggestions #561
* tab completion from within a pair of quotes now attempts to "appropriate" the closing quote #552
* $EDITOR can now be a list: for example, `set EDITOR gvim -f`) #541
* `case` bodies are now indented #530
* The profile switch `-p` no longer crashes #517
* You can now control-C out of `read` #516
* `umask` is now functional on OS X #515
* Avoid calling getpwnam on the main thread, as it can hang #512
* Alt-F or Alt-right-arrow (Option-F or option-right-arrow) now accepts one word of an autosuggestion #435
* Setting fish as your login shell no longer kills OpenSUSE #367
* Backslashes now join lines, instead of creating multiple commands #347
* echo now implements the -e flag to interpret escapes #337
* When the last token in the user's input contains capital letters, use its case in preference to that of the autosuggestion #335
* Descriptions now have their own muted color #279
* Wildcards beginning with a . (for example, `ls .*`) no longer match . and .. #270
* Recursive wildcards now handle symlink loops #268
* You can now delete history items from the fish_config web interface #250
* The OS X build now weak links `wcsdup` and `wcscasecmp` #240
* fish now saves and restores the process group, which prevents certain processes from being erroneously reported as stopped #197
* funced now takes an editor option #187
* Alternating row colors are available in fish pager through `fish_pager_color_secondary` #186
* Universal variable values are now stored based on your MAC address, not your hostname #183
* The caret ^ now only does a stderr redirection if it is the first character of a token, making git users happy #168
* Autosuggestions will no longer cause line wrapping #167
* Better handling of Unicode combining characters #155
* fish SIGHUPs processes more often #138
* fish no longer causes `sudo` to ask for a password every time
* fish behaves better under Midnight Commander #121
* `set -e` no longer crashes #100
* fish now will automatically import history from bash, if there is no fish history #66
* Backslashed-newlines inside quoted strings now behave more intuitively #52
* Tab titles should be shown correctly in iTerm2 #47
* scp remote path completion now sometimes works #42
* The `read` builtin no longer shows autosuggestions #29
* Custom key bindings can now be set via the `fish_user_key_bindings` function #21
* All Python scripts now run correctly under both Python 2 and Python 3 #14
* The "accept autosuggestion" key can now be configured #19
* Autosuggestions will no longer suggest invalid commands #6
---
# fishfish Beta r2
Bug Fixes
---------
* **Implicit cd** is back, for paths that start with one or two dots, a slash, or a tilde.
* **Overrides of default functions should be fixed.** The "internalized scripts" feature is disabled for now.
* **Disabled delayed suspend.** This is a strange job-control feature of BSD systems, including OS X. Disabling it frees up Control Y for other purposes; in particular, for yank, which now works on OS X.
* **fish_indent is fixed.** In particular, the `funced` and `funcsave` functions work again.
* A SIGTERM now ends the whole execution stack again (resolving #13).
* Bumped the __fish_config_interactive version number so the default fish_color_autosuggestion kicks in.
* fish_config better handles combined term256 and classic colors like "555 yellow".
New Features
------------
* **A history builtin**, and associated interactive function that enables deleting history items. Example usage:
* Print all history items beginning with echo: `history --prefix echo`
* Print all history items containing foo: `history --contains foo`
* Interactively delete some items containing foo: `history --delete --contains foo`
Credit to @siteshwar for implementation. Thanks @siteshwar!
---
# fishfish Beta r1
## Scripting
* No changes! All existing fish scripts, config files, completions, etc. from trunk should continue to work.
## New Features
* **Autosuggestions**. Think URL fields in browsers. When you type a command, fish will suggest the rest of the command after the cursor, in a muted gray when possible. You can accept the suggestion with the right arrow key or Ctrl-F. Suggestions come from command history, completions, and some custom code for cd; there's a lot of potential for improvement here. The suggestions are computed on a background pthread, so they never slow down your typing. The autosuggestion feature is incredible. I miss it dearly every time I use anything else.
* **term256 support** where available, specifically modern xterms and OS X Lion. You can specify colors the old way ('set_color cyan') or by specifying RGB hex values ('set_color FF3333'); fish will pick the closest supported color. Some xterms do not advertise term256 support either in the $TERM or terminfo max_colors field, but nevertheless support it. For that reason, fish will default into using it on any xterm (but it can be disabled with an environment variable).
* **Web-based configuration** page. There is a new function 'fish_config'. This spins up a simple Python web server and opens a browser window to it. From this web page, you can set your shell colors and view your functions, variables, and history; all changes apply immediately to all running shells. Eventually all configuration ought to be supported via this mechanism (but in addition to, not instead of, command line mechanisms).
* **Man page completions**. There is a new function 'fish_update_completions'. This function reads all the man1 files from your manpath, removes the roff formatting, parses them to find the commands and options, and outputs fish completions into ~/.config/fish/completions. It won't overwrite existing completion files (except ones that it generated itself).
## Programmatic Changes
* fish is now entirely in C++. I have no particular love for C++, but it provides a ready memory-model to replace halloc. We've made an effort to keep it to a sane and portable subset (no C++11, no boost, no going crazy with templates or smart pointers), but we do use the STL and a little tr1.
* halloc is entirely gone, replaced by normal C++ ownership semantics. If you don't know what halloc is, well, now you have two reasons to be happy.
* All the crufty C data structures are entirely gone. array_list_t, priority_queue_t, hash_table_t, string_buffer_t have been removed and replaced by STL equivalents like std::vector, std::map, and std::wstring. A lot of the string handling now uses std::wstring instead of wchar_t *
* fish now spawns pthreads for tasks like syntax highlighting that require blocking I/O.
* History has been completely rewritten. History files now use an extensible YAML-style syntax. History "merging" (multiple shells writing to the same history file) now works better. There is now a maximum history length of about 250k items (256 * 1024).
* The parser has been "instanced," so you can now create more than one.
* Total #LoC has shrunk slightly even with the new features.
## Performance
* fish now runs syntax highlighting in a background thread, so typing commands is always responsive even on slow filesystems.
* echo, test, and pwd are now builtins, which eliminates many forks.
* The files in share/functions and share/completions now get 'internalized' into C strings that get compiled in with fish. This substantially reduces the number of files touched at startup. A consequence is that you cannot change these functions without recompiling, but often other functions depend on these "standard" functions, so changing them is perhaps not a good idea anyways.
Here are some system call counts for launching and then exiting fish with the default configuration, on OS X. The first column is fish trunk, the next column is with our changes, and the last column is bash for comparison. This data was collected via dtrace.
<table>
<tr> <th> <th> before <th> after <th> bash
<tr> <th> open <td> 9 <td> 4 <td> 5
<tr> <th> fork <td> 28 <td> 14 <td> 0
<tr> <th> stat <td> 131 <td> 85 <td> 11
<tr> <th> lstat <td> 670 <td> 0 <td> 0
<tr> <th> read <td> 332 <td> 80 <td> 4
<tr> <th> write <td> 172 <td> 149 <td> 0
</table>
The large number of forks relative to bash are due to fish's insanely expensive default prompt, which is unchanged in my version. If we switch to a prompt comparable to bash's (lame) default, the forks drop to 16 with trunk, 4 after our changes.
The large reduction in lstat() numbers is due to fish no longer needing to call ttyname() on OS X.
We've got some work to do to be as lean as bash, but we're on the right track.

File diff suppressed because it is too large Load Diff

View File

@@ -1,33 +1,25 @@
cmake_minimum_required(VERSION 3.5)
CMAKE_MINIMUM_REQUIRED(VERSION 3.2)
if(POLICY CMP0066)
cmake_policy(SET CMP0066 OLD)
endif()
if(POLICY CMP0067)
cmake_policy(SET CMP0067 NEW)
endif()
IF(POLICY CMP0066)
CMAKE_POLICY(SET CMP0066 OLD)
ENDIF()
IF(POLICY CMP0067)
CMAKE_POLICY(SET CMP0067 OLD)
ENDIF()
include(cmake/Mac.cmake)
project(fish)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
PROJECT(fish)
# We are C++11.
set(CMAKE_CXX_STANDARD 11)
set(DEFAULT_BUILD_TYPE "RelWithDebInfo")
SET(CMAKE_CXX_STANDARD 11)
SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")
SET(CMAKE_CXX_FLAGS_RELEASE "-O2")
SET(DEFAULT_BUILD_TYPE "RelWithDebInfo")
# Generate Xcode schemas (but not for tests).
set(CMAKE_XCODE_GENERATE_SCHEME 1)
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to default '${DEFAULT_BUILD_TYPE}'")
set(CMAKE_BUILD_TYPE "${DEFAULT_BUILD_TYPE}")
endif()
# Error out when linking statically, it doesn't work.
if (CMAKE_EXE_LINKER_FLAGS MATCHES ".*-static.*")
message(FATAL_ERROR "Fish does not support static linking")
endif()
IF(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
MESSAGE(STATUS "Setting build type to default '${DEFAULT_BUILD_TYPE}'")
SET(CMAKE_BUILD_TYPE "${DEFAULT_BUILD_TYPE}")
ENDIF()
# Force colored warnings in Ninja's output, if the compiler has -fdiagnostics-color support.
# Rationale in https://github.com/ninja-build/ninja/issues/814
@@ -35,101 +27,72 @@ if (CMAKE_GENERATOR STREQUAL "Ninja" AND
((CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) OR
(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5) OR
(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.0)))
add_compile_options(-fdiagnostics-color=always)
endif()
# Enable a whole bunch of warnings, but turn off:
# - comment because we use a bunch of those, and they're not really all that harmful.
# - address, because that occurs for our mkostemp check (weak-linking requires us to compare `&mkostemp == nullptr`).
add_compile_options(-Wall -Wextra -Wno-comment -Wno-address)
if ((CMAKE_CXX_COMPILER_ID STREQUAL "Clang") OR (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang"))
add_compile_options(-Wunused-template -Wunused-local-typedef -Wunused-macros)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdiagnostics-color=always")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=always")
endif()
# Disable exception handling.
add_compile_options(-fno-exceptions)
# Undefine NDEBUG to keep assert() in release builds.
add_definitions(-UNDEBUG)
ADD_COMPILE_OPTIONS(-fno-exceptions)
# Hide the CMake Rules directories in Xcode projects.
source_group("CMake Rules" REGULAR_EXPRESSION "^$")
SOURCE_GROUP("CMake Rules" REGULAR_EXPRESSION "^$")
# Put source and header files at top level under targets.
source_group("Source Files" REGULAR_EXPRESSION ".*\\.cpp")
source_group("Header Files" REGULAR_EXPRESSION ".*\\.h")
source_group("Builtins" "builtins/")
SOURCE_GROUP("Source Files" REGULAR_EXPRESSION "^$")
SOURCE_GROUP("Header Files" REGULAR_EXPRESSION "^$")
SOURCE_GROUP("Builtins" REGULAR_EXPRESSION "builtin_.*")
# Support folders.
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# Work around issue where archive-built libs go in the wrong place.
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
set(FISH_IN_TREE_BUILD TRUE)
else()
set(FISH_IN_TREE_BUILD FALSE)
endif()
IF(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
SET(FISH_IN_TREE_BUILD TRUE)
ELSE()
SET(FISH_IN_TREE_BUILD FALSE)
ENDIF()
# NetBSD does weird things with finding libraries,
# making the tests fail by failing to find pcre.
#
# Keep the rpath used to build.
if(CMAKE_SYSTEM_NAME STREQUAL NetBSD)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
endif()
# List of sources for builtin functions.
set(FISH_BUILTIN_SRCS
src/builtin.cpp src/builtins/argparse.cpp
src/builtins/bg.cpp src/builtins/bind.cpp src/builtins/block.cpp
src/builtins/builtin.cpp src/builtins/cd.cpp src/builtins/command.cpp
src/builtins/commandline.cpp src/builtins/complete.cpp src/builtins/contains.cpp
src/builtins/disown.cpp src/builtins/echo.cpp src/builtins/emit.cpp
src/builtins/eval.cpp src/builtins/exit.cpp src/builtins/fg.cpp
src/builtins/function.cpp src/builtins/functions.cpp src/builtins/history.cpp
src/builtins/jobs.cpp src/builtins/math.cpp src/builtins/printf.cpp
src/builtins/pwd.cpp src/builtins/random.cpp src/builtins/read.cpp
src/builtins/realpath.cpp src/builtins/return.cpp src/builtins/set.cpp
src/builtins/set_color.cpp src/builtins/source.cpp src/builtins/status.cpp
src/builtins/string.cpp src/builtins/test.cpp src/builtins/type.cpp src/builtins/ulimit.cpp
src/builtins/wait.cpp)
# List of other sources.
set(FISH_SRCS
src/ast.cpp src/autoload.cpp src/color.cpp src/common.cpp src/complete.cpp src/env.cpp
src/env_dispatch.cpp src/env_universal_common.cpp src/event.cpp src/exec.cpp
src/expand.cpp src/fallback.cpp src/fd_monitor.cpp src/fish_version.cpp
src/flog.cpp src/function.cpp src/future_feature_flags.cpp src/highlight.cpp
src/history.cpp src/history_file.cpp src/input.cpp src/input_common.cpp
src/intern.cpp src/io.cpp src/iothread.cpp src/job_group.cpp src/kill.cpp
src/null_terminated_array.cpp src/operation_context.cpp src/output.cpp
src/pager.cpp src/parse_execution.cpp src/parse_tree.cpp src/parse_util.cpp
src/parser.cpp src/parser_keywords.cpp src/path.cpp src/postfork.cpp
src/proc.cpp src/reader.cpp src/redirection.cpp src/screen.cpp
src/signal.cpp src/termsize.cpp src/timer.cpp src/tinyexpr.cpp
src/tokenizer.cpp src/topic_monitor.cpp src/trace.cpp src/utf8.cpp src/util.cpp
src/wait_handle.cpp src/wcstringutil.cpp src/wgetopt.cpp src/wildcard.cpp
src/wutil.cpp src/fds.cpp
# All objects that the system needs to build fish, except fish.cpp
SET(FISH_SRCS
src/autoload.cpp src/builtin.cpp src/builtin_bg.cpp src/builtin_bind.cpp
src/builtin_block.cpp src/builtin_builtin.cpp src/builtin_cd.cpp
src/builtin_command.cpp src/builtin_commandline.cpp
src/builtin_complete.cpp src/builtin_contains.cpp src/builtin_disown.cpp
src/builtin_echo.cpp src/builtin_emit.cpp src/builtin_exit.cpp
src/builtin_fg.cpp src/builtin_function.cpp src/builtin_functions.cpp
src/builtin_argparse.cpp src/builtin_history.cpp src/builtin_jobs.cpp
src/builtin_math.cpp src/builtin_printf.cpp src/builtin_pwd.cpp
src/builtin_random.cpp src/builtin_read.cpp src/builtin_realpath.cpp
src/builtin_return.cpp src/builtin_set.cpp src/builtin_set_color.cpp
src/builtin_source.cpp src/builtin_status.cpp src/builtin_string.cpp
src/builtin_test.cpp src/builtin_ulimit.cpp src/builtin_wait.cpp
src/color.cpp src/common.cpp src/complete.cpp src/env.cpp
src/env_universal_common.cpp src/event.cpp src/exec.cpp src/expand.cpp
src/fallback.cpp src/fish_version.cpp src/function.cpp src/highlight.cpp
src/history.cpp src/input.cpp src/input_common.cpp src/intern.cpp src/io.cpp
src/iothread.cpp src/kill.cpp src/output.cpp src/pager.cpp
src/parse_execution.cpp src/parse_productions.cpp src/parse_tree.cpp
src/parse_util.cpp src/parser.cpp src/parser_keywords.cpp src/path.cpp
src/postfork.cpp src/proc.cpp src/reader.cpp src/sanity.cpp src/screen.cpp
src/signal.cpp src/tinyexpr.c src/tnode.cpp src/tokenizer.cpp src/utf8.cpp src/util.cpp
src/wcstringutil.cpp src/wgetopt.cpp src/wildcard.cpp src/wutil.cpp
src/future_feature_flags.cpp
)
# Header files are just globbed.
file(GLOB FISH_HEADERS src/*.h)
FILE(GLOB FISH_HEADERS src/*.h)
# Set up config.h
include(cmake/ConfigureChecks.cmake)
include(cmake/gettext.cmake)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config_cmake.h.in
INCLUDE(cmake/ConfigureChecks.cmake)
INCLUDE(cmake/gettext.cmake)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/config_cmake.h.in
${CMAKE_CURRENT_BINARY_DIR}/config.h)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
# Set up standard directories.
include(GNUInstallDirs)
add_definitions(-D_UNICODE=1
INCLUDE(GNUInstallDirs)
ADD_DEFINITIONS(-D_UNICODE=1
-DLOCALEDIR="${CMAKE_INSTALL_FULL_LOCALEDIR}"
-DPREFIX=L"${CMAKE_INSTALL_PREFIX}"
-DDATADIR=L"${CMAKE_INSTALL_FULL_DATADIR}"
@@ -139,96 +102,62 @@ add_definitions(-D_UNICODE=1
# Set up the machinery around FISH-BUILD-VERSION-FILE
# This defines the FBVF variable.
include(Version)
INCLUDE(Version)
# Let fish pick up when we're running out of the build directory without installing
get_filename_component(REAL_CMAKE_BINARY_DIR "${CMAKE_BINARY_DIR}" REALPATH)
get_filename_component(REAL_CMAKE_SOURCE_DIR "${CMAKE_SOURCE_DIR}" REALPATH)
add_definitions(-DCMAKE_BINARY_DIR="${REAL_CMAKE_BINARY_DIR}")
add_definitions(-DCMAKE_SOURCE_DIR="${REAL_CMAKE_SOURCE_DIR}")
ADD_DEFINITIONS(-DCMAKE_BINARY_DIR="${CMAKE_BINARY_DIR}")
ADD_DEFINITIONS(-DCMAKE_SOURCE_DIR="${CMAKE_SOURCE_DIR}")
# Teach fish_version.o to rebuild when FBVF changes.
# The standard C++ include detection machinery misses this.
set_source_files_properties(src/fish_version.cpp
SET_SOURCE_FILES_PROPERTIES(src/fish_version.cpp
PROPERTIES OBJECT_DEPENDS
${CMAKE_CURRENT_BINARY_DIR}/${FBVF})
# Enable thread-safe errno on Solaris (#5611)
add_definitions(-D_REENTRANT)
OPTION(INTERNAL_WCWIDTH "use fallback wcwidth" ON)
IF(INTERNAL_WCWIDTH)
add_definitions(-DHAVE_BROKEN_WCWIDTH=1)
ELSE()
add_definitions(-DHAVE_BROKEN_WCWIDTH=0)
ENDIF()
# Set up PCRE2
include(cmake/PCRE2.cmake)
# Define a function to link dependencies.
function(FISH_LINK_DEPS_AND_SIGN target)
target_link_libraries(${target} fishlib)
codesign_on_mac(${target})
endfunction(FISH_LINK_DEPS_AND_SIGN)
# Define libfish.a.
add_library(fishlib STATIC ${FISH_SRCS} ${FISH_BUILTIN_SRCS})
target_sources(fishlib PRIVATE ${FISH_HEADERS})
target_link_libraries(fishlib
${CURSES_LIBRARY} ${CURSES_EXTRA_LIBRARY} Threads::Threads ${CMAKE_DL_LIBS}
${PCRE2_LIB} ${Intl_LIBRARIES} ${ATOMIC_LIBRARY})
target_include_directories(fishlib PRIVATE
${CURSES_INCLUDE_DIRS})
# Define fish.
add_executable(fish src/fish.cpp)
fish_link_deps_and_sign(fish)
# Define fish_indent.
add_executable(fish_indent
src/fish_indent.cpp src/print_help.cpp)
fish_link_deps_and_sign(fish_indent)
# Define fish_key_reader.
add_executable(fish_key_reader
src/fish_key_reader.cpp src/print_help.cpp)
fish_link_deps_and_sign(fish_key_reader)
INCLUDE(cmake/PCRE2.cmake)
# Set up the docs.
include(cmake/Docs.cmake)
INCLUDE(cmake/Docs.cmake)
# A helper for running tests.
add_executable(fish_test_helper src/fish_test_helper.cpp)
# Define a function to link dependencies.
FUNCTION(FISH_LINK_DEPS target)
TARGET_LINK_LIBRARIES(${target} fishlib)
ENDFUNCTION(FISH_LINK_DEPS)
# Define libfish.a.
ADD_LIBRARY(fishlib STATIC ${FISH_SRCS})
TARGET_SOURCES(fishlib PRIVATE ${FISH_HEADERS})
TARGET_LINK_LIBRARIES(fishlib
${CURSES_LIBRARY} ${CURSES_EXTRA_LIBRARY} Threads::Threads ${CMAKE_DL_LIBS}
${PCRE2_LIB} ${Intl_LIBRARIES})
# Define fish.
ADD_EXECUTABLE(fish src/fish.cpp)
FISH_LINK_DEPS(fish)
# Define fish_indent.
ADD_EXECUTABLE(fish_indent
src/fish_indent.cpp src/print_help.cpp)
FISH_LINK_DEPS(fish_indent)
# Define fish_key_reader.
ADD_EXECUTABLE(fish_key_reader
src/fish_key_reader.cpp src/print_help.cpp)
FISH_LINK_DEPS(fish_key_reader)
# Set up tests.
include(cmake/Tests.cmake)
# Benchmarking support.
include(cmake/Benchmark.cmake)
INCLUDE(cmake/Tests.cmake)
# Set up install.
include(cmake/Install.cmake)
INCLUDE(cmake/Install.cmake)
# Mac app.
include(cmake/MacApp.cmake)
# ThreadSanitizer likes to muck with signal handlers, which interferes
# with fish_test_helper printing the ignored signal mask.
# Ensure fish_test_helper does not use TSan.
# Note the environment var is CXXFLAGS, but the CMake var is CMAKE_CXX_FLAGS.
if (CMAKE_CXX_FLAGS MATCHES ".*-fsanitize=thread.*")
target_compile_options(fish_test_helper PRIVATE "-fno-sanitize=all")
target_link_libraries(fish_test_helper "-fno-sanitize=all")
endif()
# Lint targets
# This could be implemented as target properties, but the script has the useful feature of only
# checking the currently-staged commands
# The generator expressions below rebuild the command line for the fishlib targets
# CMake does not support the "iquote" flag - https://gitlab.kitware.com/cmake/cmake/issues/15491
set(LINT_ARGS "-D$<JOIN:$<TARGET_PROPERTY:fishlib,COMPILE_DEFINITIONS>, -D>" "-I$<JOIN:$<TARGET_PROPERTY:fishlib,INCLUDE_DIRECTORIES>, -I>")
add_custom_target(lint
COMMAND build_tools/lint.fish -p ${CMAKE_BINARY_DIR} -- ${LINT_ARGS}
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
)
add_custom_target(lint-all
COMMAND build_tools/lint.fish --all -p ${CMAKE_BINARY_DIR} -- ${LINT_ARGS}
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
)
include(FeatureSummary)
feature_summary(WHAT ALL)
INCLUDE(FeatureSummary)
FEATURE_SUMMARY(WHAT ALL)

View File

@@ -1,129 +0,0 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.

308
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,308 @@
# Guidelines For Developers
This document provides guidelines for making changes to the fish-shell project. This includes rules for how to format the code, naming conventions, et cetera. Generally known as the style of the code. It also includes recommended best practices such as creating a Travis CI account so you can verify that your changes pass all the tests before making a pull request.
See the bottom of this document for help on installing the linting and style reformatting tools discussed in the following sections.
Fish source should limit the C++ features it uses to those available in C++11. It should not use exceptions.
Before introducing a new dependency, please make it optional with graceful failure if possible. Add
any new dependencies to the README.md under the *Running* and/or *Building* sections.
## Versioning
The fish version is constructed by the *build_tools/git_version_gen.sh* script. For developers the version is the branch name plus the output of `git describe --always --dirty`. Normally the main part of the version will be the closest annotated tag. Which itself is usually the most recent release number (e.g., `2.6.0`).
## Include What You Use
You should not depend on symbols being visible to a `*.cpp` module from `#include` statements inside another header file. In other words if your module does `#include "common.h"` and that header does `#include "signal.h"` your module should not assume the sub-include is present. It should instead directly `#include "signal.h"` if it needs any symbol from that header. That makes the actual dependencies much clearer. It also makes it easy to modify the headers included by a specific header file without having to worry that will break any module (or header) that includes a particular header.
To help enforce this rule the `make lint` (and `make lint-all`) command will run the [include-what-you-use](https://include-what-you-use.org/) tool. You can find the IWYU project on [github](https://github.com/include-what-you-use/include-what-you-use).
To install the tool on OS X you'll need to add a [formula](https://github.com/jasonmp85/homebrew-iwyu) then install it:
```
brew tap jasonmp85/iwyu
brew install iwyu
```
On Ubuntu you can install it via `apt-get`:
```
sudo apt-get install iwyu
```
## Lint Free Code
Automated analysis tools like cppcheck and oclint can point out potential bugs or code that is extremely hard to understand. They also help ensure the code has a consistent style and that it avoids patterns that tend to confuse people.
Ultimately we want lint free code. However, at the moment a lot of cleanup is required to reach that goal. For now simply try to avoid introducing new lint.
To make linting the code easy there are two make targets: `lint` and `lint-all`. The latter does exactly what the name implies. The former will lint any modified but not committed `*.cpp` files. If there is no uncommitted work it will lint the files in the most recent commit.
Fish has custom cppcheck rules in the file `.cppcheck.rule`. These help catch mistakes such as using `wcwidth()` rather than `fish_wcwidth()`. Please add a new rule if you find similar mistakes being made.
Fish also depends on `diff` and `expect` for its tests.
### Dealing With Lint Warnings
You are strongly encouraged to address a lint warning by refactoring the code, changing variable names, or whatever action is implied by the warning.
### Suppressing Lint Warnings
Once in a while the lint tools emit a false positive warning. For example, cppcheck might suggest a memory leak is present when that is not the case. To suppress that cppcheck warning you should insert a line like the following immediately prior to the line cppcheck warned about:
```
// cppcheck-suppress memleak // addr not really leaked
```
The explanatory portion of the suppression comment is optional. For other types of warnings replace "memleak" with the value inside the parenthesis (e.g., "nullPointerRedundantCheck") from a warning like the following:
```
[src/complete.cpp:1727]: warning (nullPointerRedundantCheck): Either the condition 'cmd_node' is redundant or there is possible null pointer dereference: cmd_node.
```
Suppressing oclint warnings is more complicated to describe so I'll refer you to the [OCLint HowTo](http://docs.oclint.org/en/latest/howto/suppress.html#annotations) on the topic.
## Ensuring Your Changes Conform to the Style Guides
The following sections discuss the specific rules for the style that should be used when writing fish code. To ensure your changes conform to the style rules you simply need to run
```
make style
```
before committing your change. That will run `git-clang-format` to rewrite only the lines you're modifying.
If you've already committed your changes that's okay since it will then check the files in the most recent commit. This can be useful after you've merged another person's change and want to check that it's style is acceptable. However, in that case it will run `clang-format` to ensure the entire file, not just the lines modified by the commit, conform to the style.
If you want to check the style of the entire code base run
```
make style-all
```
That command will refuse to restyle any files if you have uncommitted changes.
### Configuring Your Editor for Fish C++ Code
#### ViM
As of ViM 7.4 it does not recognize triple-slash comments as used by Doxygen and the OS X Xcode IDE to flag comments that explain the following C symbol. This means the `gq` key binding to reformat such comments doesn't behave as expected. You can fix that by adding the following to your vimrc:
```
autocmd Filetype c,cpp setlocal comments^=:///
```
If you use ViM I recommend the [vim-clang-format plugin](https://github.com/rhysd/vim-clang-format) by [@rhysd](https://github.com/rhysd).
You can also get ViM to provide reasonably correct behavior by installing
http://www.vim.org/scripts/script.php?script_id=2636
#### Emacs
If you use Emacs: TBD
### Configuring Your Editor for Fish Scripts
If you use ViM: Install [vim-fish](https://github.com/dag/vim-fish), make sure you have syntax and filetype functionality in `~/.vimrc`:
```
syntax enable
filetype plugin indent on
```
Then turn on some options for nicer display of fish scripts in `~/.vim/ftplugin/fish.vim`:
```
" Set up :make to use fish for syntax checking.
compiler fish
" Set this to have long lines wrap inside comments.
setlocal textwidth=79
" Enable folding of block structures in fish.
setlocal foldmethod=expr
```
If you use Emacs: Install [fish-mode](https://github.com/wwwjfy/emacs-fish) (also available in melpa and melpa-stable) and `(setq-default indent-tabs-mode nil)` for it (via a hook or in `use-package`s ":init" block). It can also be made to run fish_indent via e.g.
```elisp
(add-hook 'fish-mode-hook (lambda ()
(add-hook 'before-save-hook 'fish_indent-before-save)))
```
### Suppressing Reformatting of C++ Code
If you have a good reason for doing so you can tell `clang-format` to not reformat a block of code by enclosing it in comments like this:
```
// clang-format off
code to ignore
// clang-format on
```
However, as I write this there are no places in the code where we use this and I can't think of any legitimate reasons for exempting blocks of code from clang-format.
## Fish Script Style Guide
1. All fish scripts, such as those in the *share/functions* and *tests* directories, should be formatted using the `fish_indent` command.
1. Function names should be in all lowercase with words separated by underscores. Private functions should begin with an underscore. The first word should be `fish` if the function is unique to fish.
1. The first word of global variable names should generally be `fish` for public vars or `_fish` for private vars to minimize the possibility of name clashes with user defined vars.
## C++ Style Guide
1. The [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) forms the basis of the fish C++ style guide. There are two major deviations for the fish project. First, a four, rather than two, space indent. Second, line lengths up to 100, rather than 80, characters.
1. The `clang-format` command is authoritative with respect to indentation, whitespace around operators, etc.
1. All names in code should be `small_snake_case`. No Hungarian notation is used. The names for classes and structs should be followed by `_t`.
1. Always attach braces to the surrounding context.
1. Indent with spaces, not tabs and use four spaces per indent.
1. Comments should always use the C++ style; i.e., each line of the comment should begin with a `//` and should be limited to 100 characters. Comments that do not begin a line should be separated from the previous text by two spaces.
1. Comments that document the purpose of a function or class should begin with three slashes, `///`, so that OS X Xcode (and possibly other IDEs) will extract the comment and show it in the "Quick Help" window when the cursor is on the symbol.
## Testing
The source code for fish includes a large collection of tests. If you are making any changes to fish, running these tests is mandatory to make sure the behaviour remains consistent and regressions are not introduced. Even if you don't run the tests on your machine, they will still be run via the [Travis CI](https://travis-ci.org/fish-shell/fish-shell) service.
You are strongly encouraged to add tests when changing the functionality of fish, especially if you are fixing a bug to help ensure there are no regressions in the future (i.e., we don't reintroduce the bug).
### Local testing
The tests can be run on your local computer on all operating systems.
Running the tests is only supported from the autotools build and not xcodebuild. On OS X, you will need to install autoconf &mdash; we suggest using [Homebrew](https://brew.sh/) to install these tools.
```
autoconf
./configure
make test # or "gmake test" on BSD
```
### Travis CI Build and Test
The Travis Continuous Integration services can be used to test your changes using multiple configurations. This is the same service that the fish-shell project uses to ensure new changes haven't broken anything. Thus it is a really good idea that you leverage Travis CI before making a pull request to avoid potential embarrassment at breaking the build.
You will need to [fork the fish-shell repository on GitHub](https://help.github.com/articles/fork-a-repo/), then setup Travis to test your changes before making a pull request.
1. [Sign in to Travis CI](https://travis-ci.org/auth) with your GitHub account, accepting the GitHub access permissions confirmation.
1. Once you're signed in and your repositories are synchronized, go to your [profile page](https://travis-ci.org/profile) and enable the fish-shell repository.
1. Push your changes to GitHub.
You'll receive an email when the tests are complete telling you whether or not any tests failed.
You'll find the configuration used to control Travis in the `.travis.yml` file.
### Git hooks
Since developers sometimes forget to run the tests, it can be helpful to use git hooks (see githooks(5)) to automate it.
One possibility is a pre-push hook script like this one:
```sh
#!/bin/sh
#### A pre-push hook for the fish-shell project
# This will run the tests when a push to master is detected, and will stop that if the tests fail
# Save this as .git/hooks/pre-push and make it executable
protected_branch='master'
# Git gives us lines like "refs/heads/frombranch SOMESHA1 refs/heads/tobranch SOMESHA1"
# We're only interested in the branches
while read from _ to _; do
if [ "x$to" = "xrefs/heads/$protected_branch" ]; then
isprotected=1
fi
done
if [ "x$isprotected" = x1 ]; then
echo "Running tests before push to master"
make test
RESULT=$?
if [ $RESULT -ne 0 ]; then
echo "Tests failed for a push to master, we can't let you do that" >&2
exit 1
fi
fi
exit 0
```
This will check if the push is to the master branch and, if it is, only allow the push if running `make test` succeeds. In some circumstances it may be advisable to circumvent this check with `git push --no-verify`, but usually that isn't necessary.
To install the hook, place the code in a new file `.git/hooks/pre-push` and make it executable.
### Coverity Scan
We use Coverity's static analysis tool which offers free access to open source projects. While access to the tool itself is restricted, fish-shell organization members should know that they can login [here](https://scan.coverity.com/projects/fish-shell-fish-shell?tab=overview) with their GitHub account. Currently, tests are triggered upon merging the `master` branch into `coverity_scan_master`. Even if you are not a fish developer, you can keep an eye on our statistics there.
## Installing the Required Tools
### Installing the Linting Tools
To install the lint checkers on Mac OS X using Homebrew:
```
brew tap oclint/formulae
brew install oclint
brew install cppcheck
```
To install the lint checkers on Debian-based Linux distributions:
```
sudo apt-get install clang
sudo apt-get install oclint
sudo apt-get install cppcheck
```
### Installing the Reformatting Tools
Mac OS X:
```
brew install clang-format
```
Debian-based:
```
apt-cache search clang-format
```
Above will list all the versions available. Pick the newest one available (3.9 for Ubuntu 16.10 as I write this) and install it:
```
sudo apt-get install clang-format-3.9
sudo ln -s /usr/bin/clang-format-3.9 /usr/bin/clang-format
```
## Message Translations
Fish uses the GNU gettext library to translate messages from English to other languages. To create or update a translation run `make po/[LANGUAGE CODE].po` where `LANGUAGE CODE` is the two letter ISO 639-1 language code of the language you are translating to (e.g. `de` for German). Make sure that you have the `xgettext`, `msgfmt` and `msgmerge` commands installed in order to do this.
All messages in fish script must be enclosed in single or double quote characters. They must also be translated via a subcommand. This means that the following are **not** valid:
```
echo (_ hello)
_ "goodbye"
```
Above should be written like this instead:
```
echo (_ "hello")
echo (_ "goodbye")
```
Note that you can use either single or double quotes to enclose the message to be translated. You can also optionally include spaces after the opening parentheses and once again before the closing parentheses.
Be cautious about blindly updating an existing translation file. Trivial changes to an existing message (e.g., changing the punctuation) will cause existing translations to be removed, since the tools do literal string matching. Therefore, in general, you need to carefully review any recommended deletions.
Read the [translations wiki](https://github.com/fish-shell/fish-shell/wiki/Translations) for more information.

View File

@@ -1,475 +0,0 @@
Guidelines For Developers
=========================
This document provides guidelines for making changes to the fish-shell
project. This includes rules for how to format the code, naming
conventions, et cetera.
In short:
- Be conservative in what you need (``C++11``, few dependencies)
- Use automated tools to help you (including ``make test``, ``build_tools/style.fish`` and ``make lint``)
General
-------
Fish uses C++11. Newer C++ features should not be used to make it possible to use on older systems.
It does not use exceptions, they are disabled at build time with ``-fno-exceptions``.
Don't introduce new dependencies unless absolutely necessary, and if you do,
please make it optional with graceful failure if possible.
Add any new dependencies to the README.rst under the *Running* and/or *Building* sections.
This also goes for completion scripts and functions - if at all possible, they should only use
POSIX-compatible invocations of any tools, and no superfluous dependencies.
E.g. some completions deal with JSON data. In those it's preferable to use python to handle it,
as opposed to ``jq``, because fish already optionally uses python elsewhere. (It also happens to be quite a bit *faster*)
Lint Free Code
--------------
Automated analysis tools like cppcheck and oclint can point out
potential bugs or code that is extremely hard to understand. They also
help ensure the code has a consistent style and that it avoids patterns
that tend to confuse people.
To make linting the code easy there are two make targets: ``lint`` and
``lint-all``. The latter does exactly what the name implies. The former
will lint any modified but not committed ``*.cpp`` files. If there is no
uncommitted work it will lint the files in the most recent commit.
Fish has custom cppcheck rules in the file ``.cppcheck.rule``. These
help catch mistakes such as using ``wcwidth()`` rather than
``fish_wcwidth()``. Please add a new rule if you find similar mistakes
being made.
Dealing With Lint Warnings
~~~~~~~~~~~~~~~~~~~~~~~~~~
You are strongly encouraged to address a lint warning by refactoring the
code, changing variable names, or whatever action is implied by the
warning.
Suppressing Lint Warnings
~~~~~~~~~~~~~~~~~~~~~~~~~
Once in a while the lint tools emit a false positive warning. For
example, cppcheck might suggest a memory leak is present when that is
not the case. To suppress that cppcheck warning you should insert a line
like the following immediately prior to the line cppcheck warned about:
::
// cppcheck-suppress memleak // addr not really leaked
The explanatory portion of the suppression comment is optional. For
other types of warnings replace “memleak” with the value inside the
parenthesis (e.g., “nullPointerRedundantCheck”) from a warning like the
following:
::
[src/complete.cpp:1727]: warning (nullPointerRedundantCheck): Either the condition 'cmd_node' is redundant or there is possible null pointer dereference: cmd_node.
Suppressing oclint warnings is more complicated to describe so Ill
refer you to the `OCLint
HowTo <http://docs.oclint.org/en/latest/howto/suppress.html#annotations>`__
on the topic.
Ensuring Your Changes Conform to the Style Guides
-------------------------------------------------
The following sections discuss the specific rules for the style that
should be used when writing fish code. To ensure your changes conform to
the style rules you simply need to run
::
build_tools/style.fish
before committing your change. That will run ``git-clang-format`` to
rewrite only the lines youre modifying.
If youve already committed your changes thats okay since it will then
check the files in the most recent commit. This can be useful after
youve merged another persons change and want to check that its style
is acceptable. However, in that case it will run ``clang-format`` to
ensure the entire file, not just the lines modified by the commit,
conform to the style.
If you want to check the style of the entire code base run
::
build_tools/style.fish --all
That command will refuse to restyle any files if you have uncommitted
changes.
Configuring Your Editor for Fish C++ Code
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Vim
^^^
As of Vim 7.4 it does not recognize triple-slash comments as used by
Doxygen and the OS X Xcode IDE to flag comments that explain the
following C symbol. This means the ``gq`` key binding to reformat such
comments doesnt behave as expected. You can fix that by adding the
following to your vimrc:
::
autocmd Filetype c,cpp setlocal comments^=:///
If you use Vim I recommend the `vim-clang-format
plugin <https://github.com/rhysd/vim-clang-format>`__ by
[@rhysd](https://github.com/rhysd).
Emacs
^^^^^
If you use Emacs: TBD
Configuring Your Editor for Fish Scripts
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you use Vim: Install `vim-fish <https://github.com/dag/vim-fish>`__,
make sure you have syntax and filetype functionality in ``~/.vimrc``:
::
syntax enable
filetype plugin indent on
Then turn on some options for nicer display of fish scripts in
``~/.vim/ftplugin/fish.vim``:
::
" Set up :make to use fish for syntax checking.
compiler fish
" Set this to have long lines wrap inside comments.
setlocal textwidth=79
" Enable folding of block structures in fish.
setlocal foldmethod=expr
If you use Emacs: Install
`fish-mode <https://github.com/wwwjfy/emacs-fish>`__ (also available in
melpa and melpa-stable) and ``(setq-default indent-tabs-mode nil)`` for
it (via a hook or in ``use-package``\ s “:init” block). It can also be
made to run fish_indent via e.g.
.. code:: elisp
(add-hook 'fish-mode-hook (lambda ()
(add-hook 'before-save-hook 'fish_indent-before-save)))
Suppressing Reformatting of C++ Code
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can tell ``clang-format`` to not reformat a block by enclosing it in
comments like this:
::
// clang-format off
code to ignore
// clang-format on
Fish Script Style Guide
-----------------------
1. All fish scripts, such as those in the *share/functions* and *tests*
directories, should be formatted using the ``fish_indent`` command.
2. Function names should be in all lowercase with words separated by
underscores. Private functions should begin with an underscore. The
first word should be ``fish`` if the function is unique to fish.
3. The first word of global variable names should generally be ``fish``
for public vars or ``_fish`` for private vars to minimize the
possibility of name clashes with user defined vars.
C++ Style Guide
---------------
1. The `Google C++ Style
Guide <https://google.github.io/styleguide/cppguide.html>`__ forms
the basis of the fish C++ style guide. There are two major deviations
for the fish project. First, a four, rather than two, space indent.
Second, line lengths up to 100, rather than 80, characters.
2. The ``clang-format`` command is authoritative with respect to
indentation, whitespace around operators, etc.
3. All names in code should be ``small_snake_case``. No Hungarian
notation is used. The names for classes and structs should be
followed by ``_t``.
4. Always attach braces to the surrounding context.
5. Indent with spaces, not tabs and use four spaces per indent.
6. Document the purpose of a function or class with doxygen-style
comment blocks. e.g.:
::
/**
* Sum numbers in a vector.
*
* @param values Container whose values are summed.
* @return sum of `values`, or 0.0 if `values` is empty.
*/
double sum(std::vector<double> & const values) {
...
}
*/
or
::
/// brief description of somefunction()
void somefunction() {
Testing
-------
The source code for fish includes a large collection of tests. If you
are making any changes to fish, running these tests is a good way to make
sure the behaviour remains consistent and regressions are not
introduced. Even if you dont run the tests on your machine, they will
still be run via Github Actions.
You are strongly encouraged to add tests when changing the functionality
of fish, especially if you are fixing a bug to help ensure there are no
regressions in the future (i.e., we dont reintroduce the bug).
The tests can be found in three places:
- src/fish_tests.cpp for tests to the core C++ code
- tests/checks for script tests, run by `littlecheck <https://github.com/ridiculousfish/littlecheck>`__
- tests/pexpects for interactive tests using `pexpect <https://pexpect.readthedocs.io/en/stable/>`__
When in doubt, the bulk of the tests should be added as a littlecheck test in tests/checks, as they are the easiest to modify and run, and much faster and more dependable than pexpect tests. The syntax is fairly self-explanatory. It's a fish script with the expected output in ``# CHECK:`` or ``# CHECKERR:`` (for stderr) comments.
fish_tests.cpp is mostly useful for unit tests - if you wish to test that a function does the correct thing for given input, use it.
The pexpects are written in python and can simulate input and output to/from a terminal, so they are needed for anything that needs actual interactivity. The runner is in build_tools/pexpect_helper.py, in case you need to modify something there.
Local testing
~~~~~~~~~~~~~
The tests can be run on your local computer on all operating systems.
::
cmake path/to/fish-shell
make test
Git hooks
~~~~~~~~~
Since developers sometimes forget to run the tests, it can be helpful to
use git hooks (see githooks(5)) to automate it.
One possibility is a pre-push hook script like this one:
.. code:: sh
#!/bin/sh
#### A pre-push hook for the fish-shell project
# This will run the tests when a push to master is detected, and will stop that if the tests fail
# Save this as .git/hooks/pre-push and make it executable
protected_branch='master'
# Git gives us lines like "refs/heads/frombranch SOMESHA1 refs/heads/tobranch SOMESHA1"
# We're only interested in the branches
while read from _ to _; do
if [ "x$to" = "xrefs/heads/$protected_branch" ]; then
isprotected=1
fi
done
if [ "x$isprotected" = x1 ]; then
echo "Running tests before push to master"
make test
RESULT=$?
if [ $RESULT -ne 0 ]; then
echo "Tests failed for a push to master, we can't let you do that" >&2
exit 1
fi
fi
exit 0
This will check if the push is to the master branch and, if it is, only
allow the push if running ``make test`` succeeds. In some circumstances
it may be advisable to circumvent this check with
``git push --no-verify``, but usually that isnt necessary.
To install the hook, place the code in a new file
``.git/hooks/pre-push`` and make it executable.
Coverity Scan
~~~~~~~~~~~~~
We use Coveritys static analysis tool which offers free access to open
source projects. While access to the tool itself is restricted,
fish-shell organization members should know that they can login
`here <https://scan.coverity.com/projects/fish-shell-fish-shell?tab=overview>`__
with their GitHub account. Currently, tests are triggered upon merging
the ``master`` branch into ``coverity_scan_master``. Even if you are not
a fish developer, you can keep an eye on our statistics there.
Installing the Required Tools
-----------------------------
Installing the Linting Tools
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To install the lint checkers on Mac OS X using Homebrew:
::
brew tap oclint/formulae
brew install oclint
brew install cppcheck
To install the lint checkers on Debian-based Linux distributions:
::
sudo apt-get install clang
sudo apt-get install oclint
sudo apt-get install cppcheck
Installing the Formatting Tools
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Mac OS X:
::
brew install clang-format
Debian-based:
::
sudo apt-get install clang-format
Message Translations
--------------------
Fish uses the GNU gettext library to translate messages from English to
other languages.
All non-debug messages output for user consumption should be marked for
translation. In C++, this requires the use of the ``_`` (underscore)
macro:
::
streams.out.append_format(_(L"%ls: There are no jobs\n"), argv[0]);
All messages in fish script must be enclosed in single or double quote
characters. They must also be translated via a subcommand. This means
that the following are **not** valid:
::
echo (_ hello)
_ "goodbye"
Above should be written like this instead:
::
echo (_ "hello")
echo (_ "goodbye")
Note that you can use either single or double quotes to enclose the
message to be translated. You can also optionally include spaces after
the opening parentheses and once again before the closing parentheses.
Creating and updating translations requires the Gettext tools, including
``xgettext``, ``msgfmt`` and ``msgmerge``. Translation sources are
stored in the ``po`` directory, named ``LANG.po``, where ``LANG`` is the
two letter ISO 639-1 language code of the target language (eg ``de`` for
German).
To create a new translation, for example for German:
* generate a ``messages.pot`` file by running ``build_tools/fish_xgettext.fish`` from
the source tree
* copy ``messages.pot`` to ``po/LANG.po``
To update a translation:
* generate a ``messages.pot`` file by running
``build_tools/fish_xgettext.fish`` from the source tree
* update the existing translation by running
``msgmerge --update --no-fuzzy-matching po/LANG.po messages.pot``
Many tools are available for editing translation files, including
command-line and graphical user interface programs.
Be cautious about blindly updating an existing translation file. Trivial
changes to an existing message (eg changing the punctuation) will cause
existing translations to be removed, since the tools do literal string
matching. Therefore, in general, you need to carefully review any
recommended deletions.
Read the `translations
wiki <https://github.com/fish-shell/fish-shell/wiki/Translations>`__ for
more information.
Versioning
----------
The fish version is constructed by the *build_tools/git_version_gen.sh*
script. For developers the version is the branch name plus the output of
``git describe --always --dirty``. Normally the main part of the version
will be the closest annotated tag. Which itself is usually the most
recent release number (e.g., ``2.6.0``).
Include What You Use
--------------------
You should not depend on symbols being visible to a ``*.cpp`` module
from ``#include`` statements inside another header file. In other words
if your module does ``#include "common.h"`` and that header does
``#include "signal.h"`` your module should not assume the sub-include is
present. It should instead directly ``#include "signal.h"`` if it needs
any symbol from that header. That makes the actual dependencies much
clearer. It also makes it easy to modify the headers included by a
specific header file without having to worry that will break any module
(or header) that includes a particular header.
To help enforce this rule the ``make lint`` (and ``make lint-all``)
command will run the
`include-what-you-use <https://include-what-you-use.org/>`__ tool. You
can find the IWYU project on
`github <https://github.com/include-what-you-use/include-what-you-use>`__.
To install the tool on OS X youll need to add a
`formula <https://github.com/jasonmp85/homebrew-iwyu>`__ then install
it:
::
brew tap jasonmp85/iwyu
brew install iwyu
On Ubuntu you can install it via ``apt-get``:
::
sudo apt-get install iwyu

View File

@@ -1,7 +1,6 @@
Fish is a smart and user-friendly command line shell.
Copyright (C) 2005-2009 Axel Liljencrantz
Copyright (C) 2009-2022 fish-shell contributors
fish is free software.
@@ -12,7 +11,7 @@ published by the Free Software Foundation.
fish also includes software licensed under the GNU Lesser General Public
License version 2, the OpenBSD license, the ISC license, and the NetBSD license.
Full licensing information is contained in doc_src/license.rst.
Full licensing information is contained in doc_src/license.hdr.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or

View File

@@ -2,8 +2,7 @@ FROM centos:latest
# Build dependency
RUN yum update -y &&\
yum install -y epel-release &&\
yum install -y clang cmake3 gcc-c++ make ncurses-devel &&\
yum install -y autoconf automake bc clang gcc-c++ make ncurses-devel &&\
yum clean all
# Test dependency
@@ -13,7 +12,8 @@ ADD . /src
WORKDIR /src
# Build fish
RUN cmake3 . &&\
RUN autoreconf &&\
./configure &&\
make &&\
make install

2358
Doxyfile Normal file

File diff suppressed because it is too large Load Diff

2357
Doxyfile.help Normal file

File diff suppressed because it is too large Load Diff

2357
Doxyfile.user Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,72 +0,0 @@
# This is a very basic `make` wrapper around the CMake build toolchain.
#
# Supported arguments:
# PREFIX: sets the installation prefix
# GENERATOR: explicitly specifies the CMake generator to use
CMAKE ?= cmake
GENERATOR ?= $(shell (which ninja > /dev/null 2> /dev/null && echo Ninja) || \
echo 'Unix Makefiles')
prefix ?= /usr/local
PREFIX ?= $(prefix)
ifeq ($(GENERATOR), Ninja)
BUILDFILE = build.ninja
else
BUILDFILE = Makefile
endif
# If CMake has generated an in-tree Makefile, use that instead (issue #6264)
MAKE_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
ifeq ($(shell test -f $(MAKE_DIR)/Makefile && echo 1), 1)
all:
@+$(MAKE) -f $(MAKE_DIR)/Makefile $(MAKECMDGOALS) --no-print-directory
%:
@+$(MAKE) -f $(MAKE_DIR)/Makefile $(MAKECMDGOALS) --no-print-directory
else
all: .begin build/fish
.PHONY: .begin
.begin:
@which $(CMAKE) > /dev/null 2> /dev/null || \
(echo 'Please install CMake and then re-run the `make` command!' 1>&2 && false)
.PHONY: build/fish
build/fish: build/$(BUILDFILE)
$(CMAKE) --build build
# Use build as an order-only dependency. This prevents the target from always being outdated
# after a make run, and more importantly, doesn't clobber manually specified CMake options.
build/$(BUILDFILE): | build
cd build; $(CMAKE) .. -G "$(GENERATOR)" \
-DCMAKE_INSTALL_PREFIX="$(PREFIX)" -DCMAKE_EXPORT_COMPILE_COMMANDS=1
build:
mkdir -p build
.PHONY: clean
clean:
rm -rf build
.PHONY: test
test: build/fish
$(CMAKE) --build build --target test
.PHONY: install
install: build/fish
$(CMAKE) --build build --target install
.PHONY: run
run: build/fish
./build/fish || true
.PHONY: exec
exec: build/fish
exec ./build/fish
endif # CMake in-tree build check

1223
Makefile.in Normal file

File diff suppressed because it is too large Load Diff

164
README.md Normal file
View File

@@ -0,0 +1,164 @@
[fish](https://fishshell.com/) - the friendly interactive shell [![Build Status](https://travis-ci.org/fish-shell/fish-shell.svg?branch=master)](https://travis-ci.org/fish-shell/fish-shell)
================================================
fish is a smart and user-friendly command line shell for macOS, Linux, and the rest of the family.
fish includes features like syntax highlighting, autosuggest-as-you-type, and fancy tab completions
that just work, with no configuration required.
For more on fish's design philosophy, see the [design document](https://fishshell.com/docs/current/design.html).
## Quick Start
fish generally works like other shells, like bash or zsh. A few important differences can be found at <https://fishshell.com/docs/current/tutorial.html> by searching for the magic phrase "unlike other shells".
Detailed user documentation is available by running `help` within fish, and also at <https://fishshell.com/docs/current/index.html>
You can quickly play with fish right in your browser by clicking the button below:
[![Try in browser](https://cdn.rawgit.com/rootnroll/library/assets/try.svg)](https://rootnroll.com/d/fish-shell/)
## Getting fish
### macOS
fish can be installed:
* using [Homebrew](http://brew.sh/): `brew install fish`
* using [MacPorts](https://www.macports.org/): `sudo port install fish`
* using the [installer from fishshell.com](https://fishshell.com/)
* as a [standalone app from fishshell.com](https://fishshell.com/)
### Packages for Linux
Packages for Debian, Fedora, openSUSE, and Red Hat Enterprise Linux/CentOS are available from the
[openSUSE Build
Service](https://software.opensuse.org/download.html?project=shells%3Afish%3Arelease%3A2&package=fish).
Packages for Ubuntu are available from the [fish
PPA](https://launchpad.net/~fish-shell/+archive/ubuntu/release-2), and can be installed using the
following commands:
```
sudo apt-add-repository ppa:fish-shell/release-2
sudo apt-get update
sudo apt-get install fish
```
Instructions for other distributions may be found at [fishshell.com](https://fishshell.com).
### Windows
- On Windows 10, fish can be installed under the WSL Windows Subsystem for Linux with `sudo apt install fish` or from source with the instructions below.
- Fish can also be installed on all versions of Windows using [Cygwin](https://cygwin.com/) (from the **Shells** category).
### Building from source
If packages are not available for your platform, GPG-signed tarballs are available from
[fishshell.com](https://fishshell.com/) and [fish-shell on
GitHub](https://github.com/fish-shell/fish-shell/releases). See the *Building* section for instructions.
## Running fish
Once installed, run `fish` from your current shell to try fish out!
### Dependencies
Running fish requires:
* curses or ncurses (preinstalled on most \*nix systems)
* some common \*nix system utilities (currently `mktemp` and `seq`), in addition to the basic POSIX utilities
* gettext (library and `gettext` command), if compiled with translation support
The following optional features also have specific requirements:
* builtin commands that have the `--help` option or print usage messages require `nroff` and `ul`
* automated completion generation from manual pages requires Python (2.7+ or 3.3+) and possibly the
`backports.lzma` module for Python 2.7
* the `fish_config` web configuration tool requires Python (2.7+ or 3.3 +) and a web browser
* system clipboard integration (with the default Ctrl-V and Ctrl-X bindings) require either the
`xsel` or `pbcopy`/`pbpaste` utilities
* full completions for `yarn` and `bower` require the `jq` utility
* full completions for `yarn` and `npm` require the `all-the-package-names` NPM module
### Switching to fish
If you wish to use fish as your default shell, use the following command:
chsh -s /usr/local/bin/fish
`chsh` will prompt you for your password and change your default shell. (Substitute `/usr/local/bin/fish` with whatever path fish was installed to, if it differs.)
Use the following command if fish isn't already added to `/etc/shells` to permit fish to be your login shell:
echo /usr/local/bin/fish | sudo tee -a /etc/shells
To switch your default shell back, you can run `chsh -s /bin/bash` (substituting `/bin/bash` with `/bin/tcsh` or `/bin/zsh` as appropriate).
## Building
### Dependencies
Compiling fish requires:
* a C++11 compiler (g++ 4.8 or later, or clang 3.3 or later)
* any of CMake, GNU Make, or (on macOS only) Xcode
* a curses implementation such as ncurses (headers and libraries)
* PCRE2 (headers and libraries) - a copy is included with fish
* gettext (headers and libraries) - optional, for translation support
Additionally, if compiling fish with GNU Make from git (that is, not from an officially released tarball), `autoconf` 2.60+ and `automake` 1.13+ are required. Doxygen (1.8.7 or later) is also optionally required to build the documentation from a cloned git repository.
### Building from source (all platforms)
#### Using CMake (preferred)
```bash
mkdir build; cd build
cmake ..
make
sudo make install
```
#### Using autotools
```bash
autoreconf --no-recursive #if building from Git
./configure
make
sudo make install
```
### Building from source (macOS only)
* Build the `base` target in Xcode
* Run the fish executable, for example, in `DerivedData/fish/Build/Products/Debug/base/bin/fish`
To build and install fish with Xcode on macOS, execute the following in a terminal:
```bash
xcodebuild install
sudo ditto /tmp/fish.dst /
sudo make install-doc
```
### Help, it didn't build!
If fish reports that it could not find curses, try installing a curses development package and build again.
On Debian or Ubuntu you want:
sudo apt-get install build-essential ncurses-dev libncurses5-dev gettext autoconf
On RedHat, CentOS, or Amazon EC2:
sudo yum install ncurses-devel
## Contributing Changes to the Code
See the [Guide for Developers](CONTRIBUTING.md).
## Contact Us
Questions, comments, rants and raves can be posted to the official fish mailing list at <https://lists.sourceforge.net/lists/listinfo/fish-users> or join us on our [gitter.im channel](https://gitter.im/fish-shell/fish-shell) or IRC channel [#fish at irc.oftc.net](https://webchat.oftc.net/?channels=fish). Or use the [fish tag on Stackoverflow](https://stackoverflow.com/questions/tagged/fish) for questions related to fish script and the [fish tag on Superuser](https://superuser.com/questions/tagged/fish) for all other questions (e.g., customizing colors, changing key bindings).
Found a bug? Have an awesome idea? Please [open an issue](https://github.com/fish-shell/fish-shell/issues/new).

View File

@@ -1,242 +0,0 @@
`fish <https://fishshell.com/>`__ - the friendly interactive shell |Build Status|
=================================================================================
fish is a smart and user-friendly command line shell for macOS, Linux,
and the rest of the family. fish includes features like syntax
highlighting, autosuggest-as-you-type, and fancy tab completions that
just work, with no configuration required.
For more on fishs design philosophy, see the `design
document <https://fishshell.com/docs/current/design.html>`__.
Quick Start
-----------
fish generally works like other shells, like bash or zsh. A few
important differences can be found at
https://fishshell.com/docs/current/tutorial.html by searching for the
magic phrase “unlike other shells”.
Detailed user documentation is available by running ``help`` within
fish, and also at https://fishshell.com/docs/current/index.html
Getting fish
------------
macOS
~~~~~
fish can be installed:
- using `Homebrew <http://brew.sh/>`__: ``brew install fish``
- using `MacPorts <https://www.macports.org/>`__:
``sudo port install fish``
- using the `installer from fishshell.com <https://fishshell.com/>`__
- as a `standalone app from fishshell.com <https://fishshell.com/>`__
Packages for Linux
~~~~~~~~~~~~~~~~~~
Packages for Debian, Fedora, openSUSE, and Red Hat Enterprise
Linux/CentOS are available from the `openSUSE Build
Service <https://software.opensuse.org/download.html?project=shells%3Afish&package=fish>`__.
Packages for Ubuntu are available from the `fish
PPA <https://launchpad.net/~fish-shell/+archive/ubuntu/release-3>`__,
and can be installed using the following commands:
::
sudo apt-add-repository ppa:fish-shell/release-3
sudo apt update
sudo apt install fish
Instructions for other distributions may be found at
`fishshell.com <https://fishshell.com>`__.
Windows
~~~~~~~
- On Windows 10, fish can be installed under the WSL Windows Subsystem
for Linux with the instructions for the appropriate distribution
listed above under “Packages for Linux”, or from source with the
instructions below.
- Fish can also be installed on all versions of Windows using
`Cygwin <https://cygwin.com/>`__ (from the **Shells** category).
Building from source
~~~~~~~~~~~~~~~~~~~~
If packages are not available for your platform, GPG-signed tarballs are
available from `fishshell.com <https://fishshell.com/>`__ and
`fish-shell on
GitHub <https://github.com/fish-shell/fish-shell/releases>`__. See the
`Building <#building>`__ section for instructions.
Running fish
------------
Once installed, run ``fish`` from your current shell to try fish out!
Dependencies
~~~~~~~~~~~~
Running fish requires:
- curses or ncurses (preinstalled on most \*nix systems)
- some common \*nix system utilities (currently ``mktemp``), in
addition to the basic POSIX utilities (``cat``, ``cut``, ``dirname``,
``ls``, ``mkdir``, ``mkfifo``, ``rm``, ``sort``, ``tee``, ``tr``,
``uname`` and ``sed`` at least, but the full coreutils plus ``find`` and
``awk`` is preferred)
- The gettext library, if compiled with
translation support
The following optional features also have specific requirements:
- builtin commands that have the ``--help`` option or print usage
messages require ``ul`` and either ``nroff`` or ``mandoc`` for
display
- automated completion generation from manual pages requires Python 3.5+
- the ``fish_config`` web configuration tool requires Python 3.5+ and a web browser
- system clipboard integration (with the default Ctrl-V and Ctrl-X
bindings) require either the ``xsel``, ``xclip``,
``wl-copy``/``wl-paste`` or ``pbcopy``/``pbpaste`` utilities
- full completions for ``yarn`` and ``npm`` require the
``all-the-package-names`` NPM module
- ``colorls`` is used, if installed, to add color when running ``ls`` on platforms
that do not have color support (such as OpenBSD)
Switching to fish
~~~~~~~~~~~~~~~~~
If you wish to use fish as your default shell, use the following
command:
::
chsh -s /usr/local/bin/fish
``chsh`` will prompt you for your password and change your default
shell. (Substitute ``/usr/local/bin/fish`` with whatever path fish was
installed to, if it differs.) Log out, then log in again for the changes
to take effect.
Use the following command if fish isnt already added to ``/etc/shells``
to permit fish to be your login shell:
::
echo /usr/local/bin/fish | sudo tee -a /etc/shells
To switch your default shell back, you can run ``chsh -s /bin/bash``
(substituting ``/bin/bash`` with ``/bin/tcsh`` or ``/bin/zsh`` as
appropriate).
Building
--------
.. _dependencies-1:
Dependencies
~~~~~~~~~~~~
Compiling fish requires:
- a C++11 compiler (g++ 4.8 or later, or clang 3.3 or later)
- CMake (version 3.5 or later)
- a curses implementation such as ncurses (headers and libraries)
- PCRE2 (headers and libraries) - a copy is included with fish
- gettext (headers and libraries) - optional, for translation support
Sphinx is also optionally required to build the documentation from a
cloned git repository.
Additionally, running the test suite requires Python 3.5+ and the pexpect package.
Building from source (all platforms) - Makefile generator
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To install into ``/usr/local``, run:
.. code:: bash
mkdir build; cd build
cmake ..
make
sudo make install
The install directory can be changed using the
``-DCMAKE_INSTALL_PREFIX`` parameter for ``cmake``.
Building from source (macOS) - Xcode
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: bash
mkdir build; cd build
cmake .. -G Xcode
An Xcode project will now be available in the ``build`` subdirectory.
You can open it with Xcode, or run the following to build and install in
``/usr/local``:
.. code:: bash
xcodebuild
xcodebuild -scheme install
The install directory can be changed using the
``-DCMAKE_INSTALL_PREFIX`` parameter for ``cmake``.
Build options
~~~~~~~~~~~~~
In addition to the normal cmake build options (like ``CMAKE_INSTALL_PREFIX``), fish has some other options available to customize it.
- BUILD_DOCS=ON|OFF - whether to build the documentation. This is automatically set to OFF when sphinx isn't installed.
- INSTALL_DOCS=ON|OFF - whether to install the docs. This is automatically set to on when BUILD_DOCS is or prebuilt documentation is available (like when building in-tree from a tarball).
- FISH_USE_SYSTEM_PCRE2=ON|OFF - whether to use an installed pcre2. This is normally autodetected.
- MAC_CODESIGN_ID=String|OFF - the codesign ID to use on Mac, or "OFF" to disable codesigning.
- WITH_GETTEXT=ON|OFF - whether to build with gettext support for translations.
Note that fish does *not* support static linking and will attempt to error out if it detects it.
Help, it didnt build!
~~~~~~~~~~~~~~~~~~~~~~
If fish reports that it could not find curses, try installing a curses
development package and build again.
On Debian or Ubuntu you want:
::
sudo apt install build-essential cmake ncurses-dev libncurses5-dev libpcre2-dev gettext
On RedHat, CentOS, or Amazon EC2:
::
sudo yum install ncurses-devel
Contributing Changes to the Code
--------------------------------
See the `Guide for Developers <CONTRIBUTING.rst>`__.
Contact Us
----------
Questions, comments, rants and raves can be posted to the official fish
mailing list at https://lists.sourceforge.net/lists/listinfo/fish-users
or join us on our `gitter.im
channel <https://gitter.im/fish-shell/fish-shell>`__. Or use the `fish tag
on Unix & Linux Stackexchange <https://unix.stackexchange.com/questions/tagged/fish>`__.
There is also a fish tag on Stackoverflow, but it is typically a poor fit.
Found a bug? Have an awesome idea? Please `open an
issue <https://github.com/fish-shell/fish-shell/issues/new>`__.
.. |Build Status| image:: https://github.com/fish-shell/fish-shell/workflows/make%20test/badge.svg
:target: https://github.com/fish-shell/fish-shell/actions

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +0,0 @@
for i in (seq 2000)
command true
end

View File

@@ -1,8 +0,0 @@
# Glob fish's source directory.
# This timing is bound to change if the repo does,
# so it's best to build two fishes, check out one version of the repo,
# and then run this script with both.
set -l dir (dirname (status current-filename))
for i in (seq 1 100)
echo $dir/../../**
end

View File

@@ -1,3 +0,0 @@
for i in (seq 100000)
math $i + $i
end

View File

@@ -1,3 +0,0 @@
for i in (seq 10000)
echo $i
end

View File

@@ -1,41 +0,0 @@
#!/bin/sh
if [ "$#" -gt 2 -o "$#" -eq 0 ]; then
echo "Usage: driver.sh /path/to/fish [/path/to/other/fish]"
exit 1
fi
FISH_PATH=$1
FISH2_PATH=$2
BENCHMARKS_DIR=$(dirname "$0")/benchmarks
quote() {
# Single-quote the given string for a POSIX shell, except in common cases that don't need it.
printf %s "$1" |
sed "/[^[:alnum:]\/.-]/ {
s/'/'\\\''/g
s/^/'/
s/\$/'/
}"
}
for benchmark in "$BENCHMARKS_DIR"/*; do
basename "$benchmark"
[ -n "$FISH2_PATH" ] && echo "$FISH_PATH"
"${FISH_PATH}" --print-rusage-self "$benchmark" > /dev/null
if [ -n "$FISH2_PATH" ]; then
echo "$FISH2_PATH"
"${FISH2_PATH}" --print-rusage-self "$benchmark" > /dev/null
fi
if command -v hyperfine >/dev/null 2>&1; then
cmd1="$(quote "${FISH_PATH}") $(quote "$benchmark") > /dev/null"
if [ -n "$FISH2_PATH" ]; then
cmd2="$(quote "${FISH2_PATH}") $(quote "$benchmark") > /dev/null"
hyperfine "$cmd1" "$cmd2"
else
hyperfine "$cmd1"
fi
fi
done

View File

@@ -0,0 +1,20 @@
#!/bin/sh
# Builds the commands.hdr file.
# Usage: build_commands_hdr.sh ${HELP_SRC} < commands_hdr.in > commands.hdr
rm -f command_list.tmp command_list_toc.tmp
for i in `printf "%s\n" $@ | LC_ALL=C.UTF-8 sort`; do
echo "<hr>" >>command_list.tmp;
cat $i >>command_list.tmp;
echo >>command_list.tmp;
echo >>command_list.tmp;
NAME=`basename $i .txt`;
echo '- <a href="#'$NAME'">'$NAME'</a>' >> command_list_toc.tmp;
echo "Back to <a href='index.html#toc-commands'>command index</a>". >>command_list.tmp;
done
mv command_list.tmp command_list.txt
mv command_list_toc.tmp command_list_toc.txt
/usr/bin/env 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;}}'

View File

@@ -0,0 +1,163 @@
#!/bin/sh
# This script is run as part of the build process
if test $# -eq 0
then
# Use fish's defaults
DOXYFILE=Doxyfile.help
INPUTDIR=doc_src
OUTPUTDIR=share
echo "Using defaults: $0 ${DOXYFILE} ${INPUTDIR} ${OUTPUTDIR}"
elif test $# -eq 3
then
DOXYFILE="$1"
INPUTDIR="$2"
OUTPUTDIR="$3"
else
echo "Usage: $0 doxygen_file input_directory output_directory"
exit 1
fi
# Determine which man pages we don't want to generate.
# on OS X, don't make a man page for open, since we defeat fish's open function on OS X.
# This is also done in the Makefile, but the Xcode build doesn't use that
CONDEMNED_PAGES=
if test `uname` = 'Darwin'; then
CONDEMNED_PAGES="$CONDEMNED_PAGES open.1"
fi
# Helper function to turn a relative path into an absolute path
resolve_path()
{
D=`command dirname "$1"`
B=`command basename "$1"`
echo "`cd \"$D\" 2>/dev/null && pwd || echo \"$D\"`/$B"
}
# Expand relative paths
DOXYFILE=`resolve_path "$DOXYFILE"`
INPUTDIR=`resolve_path "$INPUTDIR"`
INPUTFILTER=`resolve_path "$INPUT_FILTER"`
OUTPUTDIR=`resolve_path "$OUTPUTDIR"`
echo " doxygen file: $DOXYFILE"
echo " input directory: $INPUTDIR"
echo " input filter: $INPUTFILTER"
echo " output directory: $OUTPUTDIR"
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
if test ! -d "$INPUTDIR"; then
echo >&2 "Could not find input directory '${INPUTDIR}'"
exit 1
fi
# Make sure doxygen is found
DOXYGENPATH=`command -v doxygen`
if test -z "$DOXYGENPATH" ; then
for i in /usr/local/bin/doxygen /opt/bin/doxygen /Applications/Doxygen.app/Contents/Resources/doxygen ~/Applications/Doxygen.app/Contents/Resources/doxygen ; do
if test -f "$i"; then
DOXYGENPATH="$i"
break
fi
done
fi
if test -z "$DOXYGENPATH"; then
echo >&2 "doxygen is not installed, so documentation will not be built."
exit 0
fi
# Check we have the lexicon filter
if test -z "$INPUT_FILTER"; then
echo >&2 "Lexicon filter is not available. Continuing without."
INPUTFILTER=''
fi
# Determine where our output should go
if ! mkdir -p "${OUTPUTDIR}" ; then
echo "Could not create output directory '${OUTPUTDIR}'"
fi
# Make a temporary directory
TMPLOC=`mktemp -d -t fish_doc_build_XXXXXX` || { echo >&2 "Could not build documentation because mktemp failed"; exit 1; }
# Copy stuff to the temp directory
for i in "$INPUTDIR"/*.txt; do
BASENAME=`basename $i .txt`
INPUTFILE=$TMPLOC/$BASENAME.doxygen
echo "/** \\page" $BASENAME > $INPUTFILE
cat $i | sed "s/\\\section $BASENAME $BASENAME/\\\section $BASENAME-man $BASENAME/" >> $INPUTFILE
echo "*/" >> $INPUTFILE
done
# Make some extra stuff to pass to doxygen
# Input is kept as . because we cd to the input directory beforehand
# This prevents doxygen from generating "documentation" for intermediate directories
PROJECT_NUMBER=$(echo "$FISH_BUILD_VERSION" | env sed "s/-[a-z0-9-]*//")
echo "PROJECT_NUMBER: $FISH_BUILD_VERSION"
DOXYPARAMS=$(cat <<EOF
PROJECT_NUMBER=${PROJECT_NUMBER}
INPUT_FILTER=$INPUTFILTER
INPUT=.
OUTPUT_DIRECTORY=$OUTPUTDIR
QUIET=YES
EOF
);
# echo "$DOXYPARAMS"
# Clear out the output directory first
find "${OUTPUTDIR}" -name "*.1" -delete
# Run doxygen
cd "$TMPLOC"
(cat "${DOXYFILE}" ; echo "$DOXYPARAMS";) | "$DOXYGENPATH" -
# Remember errors
RESULT=$?
cd "${OUTPUTDIR}/man/man1/"
if test "$RESULT" = 0 ; then
# Postprocess the files
for i in "$INPUTDIR"/*.txt; do
# This command turns the following weirdness from Doxygen:
# abbr \-
# .SH "abbr - manage fish abbreviations"
# into
# \fBabbr\fP - manage fish abbreviations
# It would be nice to use -i here for edit in place, but that is not portable
CMD_NAME=`basename "$i" .txt`;
sed -E < ${CMD_NAME}.1 > ${CMD_NAME}.1.tmp \
-e "/^.SH NAME/{
N; N
s/${CMD_NAME} \\\\- \n.SH \"${CMD_NAME} (- .*)\"/\\\fB${CMD_NAME}\\\fP \1/g
}"
mv "${CMD_NAME}.1.tmp" "${CMD_NAME}.1"
done
# Erase condemned pages
rm -f $CONDEMNED_PAGES
fi
# Destroy TMPLOC
if test "$RESULT" -ne 0; then
echo "Cleaning up '$TMPLOC'"
fi
rm -Rf "$TMPLOC"
if test "$RESULT" -ne 0; then
tput smso 2> /dev/null || true
echo "Doxygen failed creating manpages. See the output log for details."
tput sgr0 2> /dev/null || true
else
tput bold 2> /dev/null || true
echo Built manpages
tput sgr0 2> /dev/null || true
fi
exit $RESULT

5
build_tools/build_index_hdr.sh Executable file
View File

@@ -0,0 +1,5 @@
#!/bin/sh
TOC_TXT=$1
env awk "{if (\$0 ~ /@toc@/){ system(\"cat ${TOC_TXT}\");} else{ print \$0;}}"

View File

@@ -0,0 +1,51 @@
#!/bin/sh
# Builds the lexicon filter
# Usage: build_lexicon_filter.sh FUNCTIONS_DIR COMPLETIONS_DIR lexicon_filter.in [SED_BINARY] > lexicon_filter
set -e
# To enable the lexicon filter, we first need to be aware of what fish
# considers to be a command, function, or external binary. We use
# command_list_toc.txt for the base commands. Scan the share/functions
# directory for other functions, some of which are mentioned in the docs, and
# use /share/completions to find a good selection of binaries. Additionally,
# colour defaults from __fish_config_interactive to set the docs colours when
# used in a 'cli' style context.
rm -f lexicon.tmp lexicon_catalog.tmp lexicon_catalog.txt lexicon.txt
FUNCTIONS_DIR=${1}
FUNCTIONS_DIR_FILES=${1}/*.fish
COMPLETIONS_DIR_FILES=${2}/*.fish
LEXICON_FILTER_IN=${3}
SED=${4:-$(command -v sed)}
# 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 \
-e "s|^.*>\([a-z][a-z_]*\)</a>|'\1'|w lexicon_catalog.tmp" \
-e "s|'\(.*\)'|bltn \1|p"; mv lexicon_catalog.tmp lexicon_catalog.txt
printf "%s\n" ${COMPLETIONS_DIR_FILES} | $SED -n \
-e "s|[^ ]*/\([a-z][a-z_-]*\).fish|'\1'|p" | grep -F -vx -f lexicon_catalog.txt | $SED >>lexicon.tmp -n \
-e 'w lexicon_catalog.tmp' \
-e "s|'\(.*\)'|cmnd \1|p"; cat lexicon_catalog.tmp >> lexicon_catalog.txt;
printf "%s\n" ${FUNCTIONS_DIR_FILES} | $SED -n \
-e "s|[^ ]*/\([a-z][a-z_-]*\).fish|'\1'|p" | grep -F -vx -f lexicon_catalog.txt | $SED >>lexicon.tmp -n \
-e 'w lexicon_catalog.tmp' \
-e "s|'\(.*\)'|func \1|p";
$SED < ${FUNCTIONS_DIR}/__fish_config_interactive.fish >>lexicon.tmp -n \
-e '/set_default/s/.*\(fish_[a-z][a-z_]*\).*$$/clrv \1/p'; \
$SED < ${LEXICON_FILTER_IN} >>lexicon.tmp -n \
-e '/^#.!#/s/^#.!# \(.... [a-z][a-z_]*\)/\1/p';
mv lexicon.tmp lexicon.txt; rm -f lexicon_catalog.tmp lexicon_catalog.txt;
# Copy the filter to stdout. We're going to append sed commands to it after.
$SED -e 's|@sed@|'$SED'|' < ${LEXICON_FILTER_IN}
# Scan through the lexicon, transforming each line to something useful to Doxygen.
if echo x | $SED "/[[:<:]]x/d" 2>/dev/null; then
WORDBL='[[:<:]]'; WORDBR='[[:>:]]';
else
WORDBL='\\<'; WORDBR='\\>';
fi;
$SED < lexicon.txt -n -e "s|^\([a-z][a-z][a-z][a-z]\) \([a-z_-]*\)$|s,$WORDBL\2$WORDBR,@\1{\2},g|p" -e '$G;s/.*\n/b tidy/p';

17
build_tools/build_toc_txt.sh Executable file
View File

@@ -0,0 +1,17 @@
#!/bin/sh
# Usage: build_toc_txt.sh $(HDR_FILES:index.hdr=index.hdr.in) > toc.txt
# Ugly hack to set the toc initial title for the main page
echo "- <a href=\"index.html\" id=\"toc-index\">fish shell documentation - ${FISH_BUILD_VERSION}</a>" > toc.txt
# 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
# This is to reduce the size of the TOC in the command listing on the main page
for i in $@; do
NAME=`basename $i .hdr`
NAME=`basename $NAME .hdr.in`
env sed <$i >>toc.txt -n \
-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

16
build_tools/build_user_doc.sh Executable file
View File

@@ -0,0 +1,16 @@
#!/bin/sh
# Usage: Doxyfile.user lexicon_filter
DOXYFILE=$1
LEXICON_FILTER=$2
(cat "${DOXYFILE}" ;\
echo INPUT_FILTER="${LEXICON_FILTER}"; \
echo PROJECT_NUMBER=${FISH_BUILD_VERSION} \
| /usr/bin/env sed "s/-[a-z0-9-]*//") \
| doxygen - && touch user_doc
(cd ./user_doc/html/ && \
rm -f bc_s.png bdwn.png closed.png doc.png folder*.png ftv2*.png \
nav*.png open.png splitbar.png sync_*.png tab*.* doxygen.* \
dynsections.js jquery.js pages.html)

View File

@@ -1,7 +1,3 @@
#!/bin/sh
#!/usr/local/bin/fish
cppcheck --std=c++11 --quiet \
--suppressions-list=build_tools/cppcheck.suppressions --inline-suppr \
--rule-file=build_tools/cppcheck.rules \
--force \
${@:---enable=all ./src/}
cppcheck --enable=all --std=posix --quiet ./src/

View File

@@ -5,42 +5,42 @@
#
# Usage: ./diff_profiles.fish profile1.log profile2.log > profile_diff.log
set -l profile1 (cat $argv[1])
set -l profile2 (cat $argv[2])
set profile1 (cat $argv[1])
set profile2 (cat $argv[2])
set -l line_no 0
while set -l next_line_no (math $line_no + 1) && set -q profile1[$next_line_no] && set -q profile2[$next_line_no]
set line_no $next_line_no
set line_no 0
while set next_line_no (math $line_no + 1) && set -q profile1[$next_line_no] && set -q profile2[$next_line_no]
set line_no $next_line_no
set -l line1 $profile1[$line_no]
set -l line2 $profile2[$line_no]
set line1 $profile1[$line_no]
set line2 $profile2[$line_no]
if not string match -qr '^\d+\t\d+' $line1
echo $line1
continue
end
if not string match -qr '^\d+\t\d+' $line1
echo $line1
continue
end
set -l results1 (string match -r '^(\d+)\t(\d+)\s+(.*)' $line1)
set -l results2 (string match -r '^(\d+)\t(\d+)\s+(.*)' $line2)
set results1 (string match -r '^(\d+)\t(\d+)\s+(.*)' $line1)
set results2 (string match -r '^(\d+)\t(\d+)\s+(.*)' $line2)
# times from both files
set -l time1 $results1[2..3]
set -l time2 $results2[2..3]
# times from both files
set time1 $results1[2..3]
set time2 $results2[2..3]
# leftover from both files
set -l remainder1 $results1[4]
set -l remainder2 $results2[4]
# leftover from both files
set remainder1 $results1[4]
set remainder2 $results2[4]
if not string match -q -- $remainder1 $remainder2
echo Mismatch on line $line_no:
echo - $remainder1
echo + $remainder2
exit 1
end
if not string match -q -- $remainder1 $remainder2
echo Mismatch on line $line_no:
echo - $remainder1
echo + $remainder2
exit 1
end
set -l diff
set diff[1] (math $time1[1] - $time2[1])
set diff[2] (math $time1[2] - $time2[2])
set -l diff
set diff[1] (math $time1[1] - $time2[1])
set diff[2] (math $time1[2] - $time2[2])
echo $diff[1] $diff[2] $remainder1
echo $diff[1] $diff[2] $remainder1
end

View File

@@ -1,23 +0,0 @@
#!/usr/bin/env fish
# Build a list of all sections in the html sphinx docs, separately by page,
# so it can be added to share/functions/help.fish
# Use like
# fish extract_help_sections.fish user_doc/html/{fish_for_bash_users.html,faq.html,interactive.html,language.html,tutorial.html}
# TODO: Currently `help` uses variable names we can't generate, so it needs to be touched up manually.
# Also this could easily be broken by changes in sphinx, ideally we'd have a way to let it print the section titles.
#
for file in $argv
set -l varname (string replace -r '.*/(.*).html' '$1' -- $file | string escape --style=var)pages
# Technically we can use any id in the document as an anchor, but listing them all is probably too much.
# Sphinx stores section titles (in a slug-ized form) in the id,
# and stores explicit section links in a `span` tag like
# `<span id="identifiers"></span>`
# We extract both separately.
set -l sections (string replace -rf '.*class="headerlink" href="#([^"]*)".*' '$1' <$file)
# Sections titled "id5" and such are internal cruft and shouldn't be offered.
set -a sections (string replace -rf '.*span id="([^"]*)".*' '$1' <$file | string match -rv 'id\d+')
set sections (printf '%s\n' $sections | sort -u)
echo set -l $varname $sections
end

View File

@@ -4,105 +4,38 @@
# for object files in this directory.
# This was written for macOS nm.
set -l FISH_SOURCE_DIR $argv[1]
if not test -d "$FISH_SOURCE_DIR"
echo "FISH_SOURCE_DIR not given"
exit 1
end
set -g whitelist \
# unclear what this is \
l_constinit \
# hacks to work around missing ncurses strings on mac \
sitm_esc ritm_esc dim_esc
# In our nm regex, we are interested in data (dD) and bss (bB) segments.
set -g nm_regex '^([^ ]+) ([dDbB])'
set -l total_globals 0
set -l boring_files \
set total_globals 0
set boring_files \
fish_key_reader.cpp.o \
fish_tests.cpp.o \
fish_indent.cpp.o
fish_indent.cpp.o \
# return if we should ignore the given symbol name
function should_ignore
set -l symname $argv[1]
string match -q '*guard variable for*' $symname
and return 0
contains $symname $whitelist
and return 0
return 1
end
# echo a cleaned-up symbol name, e.g. replacing template gunk
function cleanup_syname
set -l symname $argv[1]
set symname (string replace --all 'std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >' 'wcstring' $symname)
set symname (string replace --all 'std::__1::vector<wcstring, std::__1::allocator<wcstring > >' 'wcstring_list_t' $symname)
echo $symname
end
set whitelist \
termsize_lock termsize \
initial_pid initial_fg_process_group \
_debug_level \
sitm_esc ritm_esc dim_esc \
iothread_init()::inited \
s_result_queue s_main_thread_request_queue s_read_pipe s_write_pipe \
s_main_thread_performer_lock s_main_thread_performer_cond s_main_thread_request_q_lock \
locked_consumed_job_ids \
env_initialized \
# Output the declaration for a symbol name in a given file.
function print_decl -a FISH_SOURCE_DIR objfile symname
set -l varname (string split '::' $symname)[-1]
set -l srcfile (basename $objfile .o)
set -l srcpath $FISH_SOURCE_DIR/src/$srcfile
# A leading underscore indicates a global, strip it.
set varname (string replace --regex '^_' '' $varname)
if not test -f "$srcpath"
echo "Could not find $srcpath"
end
# Guess the variable as the first usage of the name.
# Strip everything after the first =.
set -l vardecl (egrep -m 1 " $varname\\b" $srcpath | cut -f -1 -d '=' | string trim)
if test -z "$vardecl"
echo "COULD_NOT_FIND_$varname"
return 1
end
echo $vardecl
return 0
end
# Return if a variable declaration is "thread safe".
function decl_is_threadsafe
set -l vardecl $argv[1]
# decls starting with 'const ' or containing ' const ' are assumed safe.
string match -q --regex '(^|\\*| )const ' $vardecl
and return 0
# Ordinary types indicating a safe variable.
set -l safes relaxed_atomic_bool_t std::mutex std::condition_variable std::once_flag sig_atomic_t
for safe in $safes
string match -q "*$safe*" $vardecl
and return 0
end
# Template types indicate a safe variable.
set safes owning_lock mainthread_t std::atomic relaxed_atomic_t latch_t
for safe in $safes
string match -q "*$safe<*" $vardecl
and return 0
end
end
for file in ./**.o
set -l filename (basename $file)
set filename (basename $file)
# Skip boring files.
contains $filename $boring_files
and continue
for line in (nm -p -P -U $file | egrep $nm_regex)
set -l matches (string match --regex $nm_regex -- $line)
for line in (nm -p -P -U $file)
# Look in data (dD) and bss (bB) segments.
set matches (string match --regex '^([^ ]+) ([dDbB])' -- $line)
or continue
set -l symname (cleanup_syname (echo $matches[2] | c++filt))
should_ignore $symname
set symname (echo $matches[2] | c++filt)
contains $symname $whitelist
and continue
set -l vardecl (print_decl $FISH_SOURCE_DIR $filename $symname)
decl_is_threadsafe $vardecl
and continue
echo $filename $symname $matches[3] ":" $vardecl
echo $filename $symname $matches[3]
set total_globals (math $total_globals + 1)
end
end

View File

@@ -1,63 +0,0 @@
#!/usr/bin/env python3
# Finds potential ODR violations due to weak symbols.
# For example, if you have two different structs with the same name in different files,
# their inline constructors may collide.
# This works only on Linux. It is designed to be run from the cmake build directory.
# clang seems more willing to emit non-inlined ctors. Of course perform a Debug build.
import re
import subprocess
output = subprocess.check_output(
"nm --radix=d -g --demangle -l --print-size CMakeFiles/fishlib.dir/src/*.o",
shell=True,
universal_newlines=True,
)
files_by_name = {} # Symbol to set of paths
sizes_by_name = {} # Symbol to set of int sizes
for line in output.split("\n"):
# Keep only weak symbols with default values (e.g. emitted inline functions).
# Example line: "0000000000000000 0000000000000107 W symbol_name"
# First number is offset, second is size.
# Note this is decimal because of radix=d.
m = re.match(r"\d+ (\d+) W (.*)\t(.*)", line)
if not m:
continue
size, name, filename = m.groups()
files_by_name.setdefault(name, set()).add(filename)
sizes_by_name.setdefault(name, set()).add(int(size))
odr_violations = 0
for name, sizes in sizes_by_name.items():
if len(sizes) == 1:
continue
files = files_by_name[name]
# Ignore symbols that only appear in one file.
# These are typically headers - unclear why they get different sizes but it appears benign.
if len(files) == 1:
continue
# Multiple sizes for this symbol name.
odr_violations += 1
print("Multiple sizes for symbol: " + name)
print("\t%s" % ", ".join([str(x) for x in sizes]))
print("\tFound in files:")
for filename in files:
print("\t\t%s" % filename)
if odr_violations == 0:
print("No ODR violations found, hooray\n")
# Show potential weak symbols.
suspicious_odrs = 0
for (name, files) in files_by_name.items():
if len(files) != 1:
continue
(filename,) = files
if ".cpp" in filename:
if suspicious_odrs == 0:
print("Some suspicious singles:")
suspicious_odrs += 1
print("\t%s" % name)
print("\t\tIn file %s" % filename)

View File

@@ -1,8 +1,5 @@
#!/usr/bin/env fish
#
# Tool to generate messages.pot
# Extended to replace the old Makefile rule which did not port easily to CMake
# This script was originally motivated to work around a quirk (or bug depending on your viewpoint)
# of the xgettext command. See https://lists.gnu.org/archive/html/bug-gettext/2014-11/msg00006.html.
# However, it turns out that even if that quirk did not exist we would still need something like
@@ -11,50 +8,35 @@
# all the strings we want translated. So we extract and normalize all such strings into a format
# that `xgettext` can handle.
# Start with the C++ source
xgettext -k -k_ -kN_ -LC++ --no-wrap -o messages.pot src/*.cpp src/*.h
# This regex handles descriptions for `complete` and `function` statements. These messages are not
# particularly important to translate. Hence the "implicit" label.
set -l implicit_regex '(?:^| +)(?:complete|function).*? (?:-d|--description) (([\'"]).+?(?<!\\\\)\\2).*'
set implicit_regex '(?:^| +)(?:complete|function) .*? (?:-d|--description) (([\'"]).+?(?<!\\\\)\\2).*'
# This regex handles explicit requests to translate a message. These are more important to translate
# than messages which should be implicitly translated.
set -l explicit_regex '.*\( *_ (([\'"]).+?(?<!\\\\)\\2) *\).*'
set explicit_regex '.*\( *_ (([\'"]).+?(?<!\\\\)\\2) *\).*'
# Create temporary directory for these operations. OS X `mktemp` is somewhat restricted, so this block
# works around that - based on share/functions/funced.fish.
set -q TMPDIR
or set -l TMPDIR /tmp
set -l tmpdir (mktemp -d $TMPDIR/fish.XXXXXX)
or exit 1
mkdir -p $tmpdir/implicit/share/completions $tmpdir/implicit/share/functions
mkdir -p $tmpdir/explicit/share/completions $tmpdir/explicit/share/functions
mkdir -p /tmp/fish/implicit/share/completions /tmp/fish/implicit/share/functions
mkdir -p /tmp/fish/explicit/share/completions /tmp/fish/explicit/share/functions
for f in share/config.fish share/completions/*.fish share/functions/*.fish
# Extract explicit attempts to translate a message. That is, those that are of the form
# `(_ "message")`.
string replace --filter --regex $explicit_regex 'echo $1' <$f | fish >$tmpdir/explicit/$f.tmp 2>/dev/null
string replace --filter --regex $explicit_regex 'echo $1' <$f | fish >/tmp/fish/explicit/$f.tmp ^/dev/null
while read description
echo 'N_ "'(string replace --all '"' '\\"' -- $description)'"'
end <$tmpdir/explicit/$f.tmp >$tmpdir/explicit/$f
rm $tmpdir/explicit/$f.tmp
end </tmp/fish/explicit/$f.tmp >/tmp/fish/explicit/$f
rm /tmp/fish/explicit/$f.tmp
# Handle `complete` / `function` description messages. The `| fish` is subtle. It basically
# avoids the need to use `source` with a command substitution that could affect the current
# avoids the need to use `source` with a command substituion that could affect the current
# shell.
string replace --filter --regex $implicit_regex 'echo $1' <$f | fish >$tmpdir/implicit/$f.tmp 2>/dev/null
string replace --filter --regex $implicit_regex 'echo $1' <$f | fish >/tmp/fish/implicit/$f.tmp ^/dev/null
while read description
# We don't use `string escape` as shown in the next comment because it produces output that
# is not parsed correctly by xgettext. Instead just escape double-quotes and quote the
# resulting string.
echo 'N_ "'(string replace --all '"' '\\"' -- $description)'"'
end <$tmpdir/implicit/$f.tmp >$tmpdir/implicit/$f
rm $tmpdir/implicit/$f.tmp
end </tmp/fish/implicit/$f.tmp >/tmp/fish/implicit/$f
rm /tmp/fish/implicit/$f.tmp
end
xgettext -j -k -kN_ -LShell --from-code=UTF-8 -cDescription --no-wrap -o messages.pot $tmpdir/explicit/share/*/*.fish
xgettext -j -k -kN_ -LShell --from-code=UTF-8 -cDescription --no-wrap -o messages.pot $tmpdir/implicit/share/*/*.fish
rm -r $tmpdir

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!/usr/bin/env sh
# Originally from the git sources (GIT-VERSION-GEN)
# Presumably (C) Junio C Hamano <junkio@cox.net>
# Reused under GPL v2.0
@@ -6,8 +6,12 @@
set -e
# Find the fish directory as two levels up from script directory.
FISH_BASE_DIR="$( cd "$( dirname "$( dirname "$0" )" )" && pwd )"
# Find the fish git directory as two levels up from script directory.
GIT_DIR="$( cd "$( dirname $( dirname "$0" ) )" && pwd )"
# Set the output directory as either the first param or cwd.
test -n "$1" && OUTPUT_DIR=$1/ || OUTPUT_DIR=
FBVF=${OUTPUT_DIR}FISH-BUILD-VERSION-FILE
DEF_VER=unknown
# First see if there is a version file (included in release tarballs),
@@ -15,33 +19,22 @@ DEF_VER=unknown
if test -f version
then
VN=$(cat version) || VN="$DEF_VER"
elif ! VN=$(git -C "$FISH_BASE_DIR" describe --always --dirty 2>/dev/null); then
elif ! VN=$(git -C "$GIT_DIR" describe --always --dirty 2>/dev/null); then
VN="$DEF_VER"
fi
# If the first param is --stdout, then output to stdout and exit.
if test "$1" = '--stdout'
if test -r $FBVF
then
echo $VN
exit 0
fi
# Set the output directory as either the first param or cwd.
test -n "$1" && OUTPUT_DIR=$1/ || OUTPUT_DIR=
FBVF="${OUTPUT_DIR}FISH-BUILD-VERSION-FILE"
if test -r "$FBVF"
then
VC=$(grep -v '^#' "$FBVF" | tr -d '"' | sed -e 's/^FISH_BUILD_VERSION=//')
VC=$(grep -v '^#' $FBVF | tr -d '"' | sed -e 's/^FISH_BUILD_VERSION=//')
else
VC="unset"
VC=unset
fi
# Maybe output the FBVF
# It looks like FISH_BUILD_VERSION="2.7.1-621-ga2f065e6"
test "$VN" = "$VC" || {
echo >&2 "FISH_BUILD_VERSION=$VN"
echo "FISH_BUILD_VERSION=\"$VN\"" >"$FBVF"
echo "FISH_BUILD_VERSION=\"$VN\"" >${FBVF}
}
# Output the fish-build-version-witness.txt

View File

@@ -3,26 +3,40 @@
# This is meant to be run by "make lint" or "make lint-all". It is not meant to
# be run directly from a shell prompt.
#
set cppchecks warning,performance,portability,information,missingInclude
set cppcheck_args
set c_files
set all no
set kernel_name (uname -s)
set machine_type (uname -m)
# We don't include "missingInclude" as that doesn't find our config.h.
# Missing includes will quickly be found by... compiling the thing anyway.
set -l cppchecks warning,performance,portability,information #,missingInclude
set -l cppcheck_args
set -l c_files
set -l all no
set -l kernel_name (uname -s)
set -l machine_type (uname -m)
set -gx CXX $argv[1]
set -e argv[1]
argparse a/all p/project= -- $argv
if test "$argv[1]" = "--all"
set all yes
set cppchecks "$cppchecks,unusedFunction"
set -e argv[1]
end
if test $kernel_name = Linux
# This is an awful hack. However, the include-what-you-use program spews lots of errors like
# /usr/include/unistd.h:226:10: fatal error: 'stddef.h' file not found
# if we don't explicitly tell it where to find the system headers on Linux. See
# http://stackoverflow.com/questions/19642590/libtooling-cant-find-stddef-h-nor-other-headers/
set -l sys_includes (eval $CXX -v -c src/builtin.cpp 2>&1 | \
sed -n -e '/^#include <...> search/,/^End of search list/s/^ *//p')[2..-2]
set -x CPLUS_INCLUDE_PATH (string join ':' $sys_includes)
end
# We only want -D and -I options to be passed thru to cppcheck.
for arg in $argv
if string match -q -- '-D*' $arg
set -a cppcheck_args (string split -- ' ' $arg)
set cppcheck_args $cppcheck_args $arg
else if string match -q -- '-I*' $arg
set -a cppcheck_args (string split -- ' ' $arg)
set cppcheck_args $cppcheck_args $arg
else if string match -q -- '-iquote*' $arg
set -a cppcheck_args (string split -- ' ' $arg)
set cppcheck_args $cppcheck_args $arg
end
end
@@ -31,18 +45,17 @@ end
# be harmless everywhere else.
set cppcheck_args $cppcheck_args -I /usr/include -I .
if test "$machine_type" = x86_64
if test "$machine_type" = "x86_64"
set cppcheck_args -D__x86_64__ -D__LP64__ $cppcheck_args
end
if set -q _flag_all
if test $all = yes
set c_files src/*.cpp
set cppchecks "$cppchecks,unusedFunction"
else
# We haven't been asked to lint all the source. If there are uncommitted
# changes lint those, else lint the files in the most recent commit.
# Select (cached files) (modified but not cached, and untracked files)
set -l files (git diff-index --cached HEAD --name-only)
set files (git diff-index --cached HEAD --name-only)
set files $files (git ls-files --exclude-standard --others --modified)
if not set -q files[1]
# No pending changes so lint the files in the most recent commit.
@@ -83,7 +96,20 @@ if set -q c_files[1]
echo ========================================
echo Running cppcheck
echo ========================================
build_tools/cppcheck.sh --enable=$cppchecks $c_files 2>&1
# The stderr to stdout redirection is because cppcheck, incorrectly IMHO, writes its
# diagnostic messages to stderr. Anyone running this who wants to capture its output will
# expect those messages to be written to stdout.
set -l cn (set_color normal)
set -l cb (set_color --bold)
set -l cu (set_color --underline)
set -l cm (set_color magenta)
set -l cbrm (set_color brmagenta)
set -l template "[$cb$cu{file}$cn$cb:{line}$cn] $cbrm{severity}$cm ({id}):$cn\n {message}"
set cppcheck_args -q --verbose --std=c++11 --std=posix --language=c++ --template $template \
--suppress=missingIncludeSystem --inline-suppr --enable=$cppchecks \
--rule-file=.cppcheck.rules --suppressions-list=.cppcheck.suppressions $cppcheck_args
cppcheck $cppcheck_args $c_files 2>&1
echo
echo ========================================
@@ -102,15 +128,26 @@ if set -q c_files[1]
# The stderr to stdout redirection is because oclint, incorrectly writes its final summary
# counts of the errors detected to stderr. Anyone running this who wants to capture its
# output will expect those messages to be written to stdout.
oclint $c_files -- $argv 2>&1
end
if type -q clang-tidy; and set -q _flag_project
echo
echo ========================================
echo Running clang-tidy
echo ========================================
clang-tidy -p $_flag_project $c_files
if test "$kernel_name" = "Darwin"
if not test -f compile_commands.json
xcodebuild -alltargets >xcodebuild.log
oclint-xcodebuild xcodebuild.log >/dev/null
end
if test $all = yes
oclint-json-compilation-database -e '/pcre2-10.22/' -- -enable-global-analysis 2>&1
else
set i_files
for f in $c_files
set i_files $i_files -i $f
end
echo oclint-json-compilation-database -e '/pcre2-10.22/' $i_files
oclint-json-compilation-database -e '/pcre2-10.22/' $i_files 2>&1
end
else
# Presumably we're on Linux or other platform not requiring special
# handling for oclint to work.
oclint $c_files -- $argv 2>&1
end
end
else
echo

View File

@@ -1,6 +1,6 @@
#! /usr/bin/env fish
set -l TAG $argv[1]
set TAG $argv[1]
if test -z "$TAG"
echo "Tag name required."
@@ -12,18 +12,16 @@ if not contains -- $TAG (git tag)
exit 1
end
set -l committers_to_tag (mktemp)
or exit 1
set -l committers_from_tag (mktemp)
or exit 1
set committers_to_tag (mktemp)
set committers_from_tag (mktemp)
# You might think it would be better to case-insensitively sort/compare the names
# to produce a more natural-looking list.
# Unicode collation tables mean that this is fraught with danger; for example, the
# "“" character will not case-fold in UTF-8 locales. sort suggests using the C locale!
git log "$TAG" --format="%aN" --reverse | sort -u >$committers_to_tag
git log "$TAG".. --format="%aN" --reverse | sort -u >$committers_from_tag
git log "$TAG" --format="%aN" --reverse | sort -u > $committers_to_tag
git log "$TAG".. --format="%aN" --reverse | sort -u > $committers_from_tag
echo New committers:
echo (comm -13 $committers_to_tag $committers_from_tag)','

View File

@@ -1,754 +0,0 @@
#!/usr/bin/env python
""" Command line test driver. """
from __future__ import unicode_literals
from __future__ import print_function
import argparse
import datetime
import io
import re
import shlex
import subprocess
import sys
try:
from itertools import zip_longest
except ImportError:
from itertools import izip_longest as zip_longest
from difflib import SequenceMatcher
# Directives can occur at the beginning of a line, or anywhere in a line that does not start with #.
COMMENT_RE = r"^(?:[^#].*)?#\s*"
# A regex showing how to run the file.
RUN_RE = re.compile(COMMENT_RE + r"RUN:\s+(.*)\n")
REQUIRES_RE = re.compile(COMMENT_RE + r"REQUIRES:\s+(.*)\n")
# A regex capturing lines that should be checked against stdout.
CHECK_STDOUT_RE = re.compile(COMMENT_RE + r"CHECK:\s+(.*)\n")
# A regex capturing lines that should be checked against stderr.
CHECK_STDERR_RE = re.compile(COMMENT_RE + r"CHECKERR:\s+(.*)\n")
SKIP = object()
def find_command(program):
import os
path, name = os.path.split(program)
if path:
return os.path.isfile(program) and os.access(program, os.X_OK)
for path in os.environ["PATH"].split(os.pathsep):
exe = os.path.join(path, program)
if os.path.isfile(exe) and os.access(exe, os.X_OK):
return exe
return None
class Config(object):
def __init__(self):
# Whether to have verbose output.
self.verbose = False
# Whether output gets ANSI colorization.
self.colorize = False
# Whether to show which file was tested.
self.progress = False
def colors(self):
""" Return a dictionary mapping color names to ANSI escapes """
def ansic(n):
return "\033[%dm" % n if self.colorize else ""
return {
"RESET": ansic(0),
"BOLD": ansic(1),
"NORMAL": ansic(39),
"BLACK": ansic(30),
"RED": ansic(31),
"GREEN": ansic(32),
"YELLOW": ansic(33),
"BLUE": ansic(34),
"MAGENTA": ansic(35),
"CYAN": ansic(36),
"LIGHTGRAY": ansic(37),
"DARKGRAY": ansic(90),
"LIGHTRED": ansic(91),
"LIGHTGREEN": ansic(92),
"LIGHTYELLOW": ansic(93),
"LIGHTBLUE": ansic(94),
"LIGHTMAGENTA": ansic(95),
"LIGHTCYAN": ansic(96),
"WHITE": ansic(97),
}
def output(*args):
print("".join(args) + "\n")
import unicodedata
def esc(m):
map = {
"\n": "\\n",
"\\": "\\\\",
"'": "\\'",
'"': '\\"',
"\a": "\\a",
"\b": "\\b",
"\f": "\\f",
"\r": "\\r",
"\t": "\\t",
"\v": "\\v",
}
if m in map:
return map[m]
if unicodedata.category(m)[0] == "C":
return "\\x{:02x}".format(ord(m))
else:
return m
def escape_string(s):
return "".join(esc(ch) for ch in s)
class CheckerError(Exception):
"""Exception subclass for check line parsing.
Attributes:
line: the Line object on which the exception occurred.
"""
def __init__(self, message, line=None):
super(CheckerError, self).__init__(message)
self.line = line
class Line(object):
""" A line that remembers where it came from. """
def __init__(self, text, number, file):
self.text = text
self.number = number
self.file = file
def __hash__(self):
# Chosen by fair diceroll
# No, just kidding.
# HACK: We pass this to the Sequencematcher, which puts the Checks into a dict.
# To force it to match the regexes, we return a hash collision intentionally,
# so it falls back on __eq__().
#
# CheckCmd has the same thing.
return 0
def __eq__(self, other):
if other is None:
return False
if isinstance(other, CheckCmd):
return other.regex.match(self.text)
if isinstance(other, Line):
# We only compare the text here so SequenceMatcher can reshuffle these
return self.text == other.text
raise NotImplementedError
def subline(self, text):
""" Return a substring of our line with the given text, preserving number and file. """
return Line(text, self.number, self.file)
@staticmethod
def readfile(file, name):
return [Line(text, idx + 1, name) for idx, text in enumerate(file)]
def is_empty_space(self):
return not self.text or self.text.isspace()
def escaped_text(self, for_formatting=False):
ret = escape_string(self.text.rstrip("\n"))
if for_formatting:
ret = ret.replace("{", "{{").replace("}", "}}")
return ret
class RunCmd(object):
"""A command to run on a given Checker.
Attributes:
args: Unexpanded shell command as a string.
"""
def __init__(self, args, line):
self.args = args
self.line = line
@staticmethod
def parse(line):
if not shlex.split(line.text):
raise CheckerError("Invalid RUN command", line)
return RunCmd(line.text, line)
class TestFailure(object):
def __init__(self, line, check, testrun, diff=None, lines=[], checks=[]):
self.line = line
self.check = check
self.testrun = testrun
self.error_annotation_lines = None
self.diff = diff
self.lines = lines
self.checks = checks
def message(self):
fields = self.testrun.config.colors()
fields["name"] = self.testrun.name
fields["subbed_command"] = self.testrun.subbed_command
if self.line:
fields.update(
{
"output_file": self.line.file,
"output_lineno": self.line.number,
"output_line": self.line.escaped_text(),
}
)
if self.check:
fields.update(
{
"input_file": self.check.line.file,
"input_lineno": self.check.line.number,
"input_line": self.check.line.escaped_text(),
"check_type": self.check.type,
}
)
filemsg = "" if self.testrun.config.progress else " in {name}"
fmtstrs = ["{RED}Failure{RESET}" + filemsg + ":", ""]
if self.line and self.check:
fmtstrs += [
" The {check_type} on line {input_lineno} wants:",
" {BOLD}{input_line}{RESET}",
"",
" which failed to match line {output_file}:{output_lineno}:",
" {BOLD}{output_line}{RESET}",
"",
]
elif self.check:
fmtstrs += [
" The {check_type} on line {input_lineno} wants:",
" {BOLD}{input_line}{RESET}",
"",
" but there was no remaining output to match.",
"",
]
else:
fmtstrs += [
" There were no remaining checks left to match {output_file}:{output_lineno}:",
" {BOLD}{output_line}{RESET}",
"",
]
if self.error_annotation_lines:
fields["error_annotation"] = " ".join(
[x.text for x in self.error_annotation_lines]
)
fields["error_annotation_lineno"] = str(
self.error_annotation_lines[0].number
)
if len(self.error_annotation_lines) > 1:
fields["error_annotation_lineno"] += ":" + str(
self.error_annotation_lines[-1].number
)
fmtstrs += [
" additional output on stderr:{error_annotation_lineno}:",
" {BOLD}{error_annotation}{RESET}",
]
if self.diff:
fmtstrs += [" Context:"]
lasthi = 0
lastcheckline = None
for d in self.diff.get_grouped_opcodes():
for op, alo, ahi, blo, bhi in d:
color = "{BOLD}"
if op == "replace" or op == "delete":
color = "{RED}"
# We got a new chunk, so we print a marker.
if alo > lasthi:
fmtstrs += [
" [...] from line "
+ str(self.checks[blo].line.number)
+ " ("
+ self.lines[alo].file
+ ":"
+ str(self.lines[alo].number)
+ "):"
]
lasthi = ahi
# We print one "no more checks" after the last check and then skip any markers
lastcheck = False
for a, b in zip_longest(self.lines[alo:ahi], self.checks[blo:bhi]):
# Clean up strings for use in a format string - double up the curlies.
astr = (
color + a.escaped_text(for_formatting=True) + "{RESET}"
if a
else ""
)
if b:
bstr = (
"'{BLUE}"
+ b.line.escaped_text(for_formatting=True)
+ "{RESET}'"
+ " on line "
+ str(b.line.number)
)
lastcheckline = b.line.number
if op == "equal":
fmtstrs += [" " + astr]
elif b and a:
fmtstrs += [
" "
+ astr
+ " <= does not match "
+ b.type
+ " "
+ bstr
]
elif b:
fmtstrs += [
" "
+ astr
+ " <= nothing to match "
+ b.type
+ " "
+ bstr
]
elif not b:
string = " " + astr
if bhi == len(self.checks):
if not lastcheck:
string += " <= no more checks"
lastcheck = True
elif lastcheckline is not None:
string += (
" <= no check matches this, previous check on line "
+ str(lastcheckline)
)
else:
string += " <= no check matches"
fmtstrs.append(string)
fmtstrs.append("")
fmtstrs += [" when running command:", " {subbed_command}"]
return "\n".join(fmtstrs).format(**fields)
def print_message(self):
""" Print our message to stdout. """
print(self.message())
def perform_substitution(input_str, subs):
"""Perform the substitutions described by subs to str
Return the substituted string.
"""
# Sort our substitutions into a list of tuples (key, value), descending by length.
# It needs to be descending because we need to try longer substitutions first.
subs_ordered = sorted(subs.items(), key=lambda s: len(s[0]), reverse=True)
def subber(m):
# We get the entire sequence of characters.
# Replace just the prefix and return it.
text = m.group(1)
for key, replacement in subs_ordered:
if text.startswith(key):
return replacement + text[len(key) :]
# No substitution found, so we default to running it as-is,
# which will end up running it via $PATH.
return text
return re.sub(r"%(%|[a-zA-Z0-9_-]+)", subber, input_str)
def runproc(cmd):
""" Wrapper around subprocess.Popen to save typing """
PIPE = subprocess.PIPE
proc = subprocess.Popen(
cmd,
stdin=PIPE,
stdout=PIPE,
stderr=PIPE,
shell=True,
close_fds=True, # For Python 2.6 as shipped on RHEL 6
)
return proc
class TestRun(object):
def __init__(self, name, runcmd, checker, subs, config):
self.name = name
self.runcmd = runcmd
self.subbed_command = perform_substitution(runcmd.args, subs)
self.checker = checker
self.subs = subs
self.config = config
def check(self, lines, checks):
# Reverse our lines and checks so we can pop off the end.
lineq = lines[::-1]
checkq = checks[::-1]
usedlines = []
usedchecks = []
mismatches = []
while lineq and checkq:
line = lineq[-1]
check = checkq[-1]
if check == line:
# This line matched this checker, continue on.
usedlines.append(line)
usedchecks.append(check)
lineq.pop()
checkq.pop()
elif line.is_empty_space():
# Skip all whitespace input lines.
lineq.pop()
else:
usedlines.append(line)
usedchecks.append(check)
mismatches.append((line, check))
# Failed to match.
lineq.pop()
checkq.pop()
# Drain empties
while lineq and lineq[-1].is_empty_space():
lineq.pop()
# Store the remaining lines for the diff
for i in lineq[::-1]:
if not i.is_empty_space():
usedlines.append(i)
# Store remaining checks for the diff
for i in checkq[::-1]:
usedchecks.append(i)
# Do a SequenceMatch! This gives us a diff-like thing.
diff = SequenceMatcher(a=usedlines, b=usedchecks, autojunk=False)
# If there's a mismatch or still lines or checkers, we have a failure.
# Otherwise it's success.
if mismatches:
return TestFailure(
mismatches[0][0],
mismatches[0][1],
self,
diff=diff,
lines=usedlines,
checks=usedchecks,
)
elif lineq:
return TestFailure(
lineq[-1], None, self, diff=diff, lines=usedlines, checks=usedchecks
)
elif checkq:
return TestFailure(
None, checkq[-1], self, diff=diff, lines=usedlines, checks=usedchecks
)
else:
# Success!
return None
def run(self):
""" Run the command. Return a TestFailure, or None. """
def split_by_newlines(s):
"""Decode a string and split it by newlines only,
retaining the newlines.
"""
return [s + "\n" for s in s.decode("utf-8").split("\n")]
if self.config.verbose:
print(self.subbed_command)
proc = runproc(self.subbed_command)
stdout, stderr = proc.communicate()
# HACK: This is quite cheesy: POSIX specifies that sh should return 127 for a missing command.
# It's also possible that it'll be returned in other situations,
# most likely when the last command in a shell script doesn't exist.
# So we check if the command *we execute* exists, and complain then.
status = proc.returncode
cmd = shlex.split(self.subbed_command)[0]
if status == 127 and not find_command(cmd):
raise CheckerError("Command could not be found: " + cmd)
if status == 126 and not find_command(cmd):
raise CheckerError("Command is not executable: " + cmd)
outlines = [
Line(text, idx + 1, "stdout")
for idx, text in enumerate(split_by_newlines(stdout))
]
errlines = [
Line(text, idx + 1, "stderr")
for idx, text in enumerate(split_by_newlines(stderr))
]
outfail = self.check(outlines, self.checker.outchecks)
errfail = self.check(errlines, self.checker.errchecks)
# It's possible that something going wrong on stdout resulted in new
# text being printed on stderr. If we have an outfailure, and either
# non-matching or unmatched stderr text, then annotate the outfail
# with it.
if outfail and errfail and errfail.line:
outfail.error_annotation_lines = errlines[errfail.line.number - 1 :]
# Trim a trailing newline
if outfail.error_annotation_lines[-1].text == "\n":
del outfail.error_annotation_lines[-1]
return outfail if outfail else errfail
class CheckCmd(object):
def __init__(self, line, checktype, regex):
self.line = line
self.type = checktype
self.regex = regex
def __hash__(self):
# HACK: We pass this to the Sequencematcher, which puts the Checks into a dict.
# To force it to match the regexes, we return a hash collision intentionally,
# so it falls back on __eq__().
#
# Line has the same thing.
return 0
def __eq__(self, other):
# "Magical" comparison with lines and strings.
# Typically I wouldn't use this, but it allows us to check if a line matches any check in a dict or list via
# the `in` operator.
if other is None:
return False
if isinstance(other, CheckCmd):
return self.regex == other.regex
if isinstance(other, Line):
return self.regex.match(other.text)
if isinstance(other, str):
return self.regex.match(other)
raise NotImplementedError
@staticmethod
def parse(line, checktype):
# type: (Line) -> CheckCmd
# Everything inside {{}} is a regular expression.
# Everything outside of it is a literal string.
# Split around {{...}}. Then every odd index will be a regex, and
# evens will be literals.
# Note that if {{...}} appears first we will get an empty string in
# the split array, so the {{...}} matches are always at odd indexes.
bracket_re = re.compile(
r"""
\{\{ # Two open brackets
(.*?) # Nongreedy capture
\}\} # Two close brackets
""",
re.VERBOSE,
)
pieces = bracket_re.split(line.text)
even = True
re_strings = []
for piece in pieces:
if even:
# piece is a literal string.
re_strings.append(re.escape(piece))
else:
# piece is a regex (found inside {{...}}).
# Verify the regex can be compiled.
try:
re.compile(piece)
except re.error:
raise CheckerError("Invalid regular expression: '%s'" % piece, line)
re_strings.append(piece)
even = not even
# Enclose each piece in a non-capturing group.
# This ensures that lower-precedence operators don't trip up catenation.
# For example: {{b|c}}d would result in /b|cd/ which is different.
# Backreferences are assumed to match across the entire string.
re_strings = ["(?:%s)" % s for s in re_strings]
# Anchor at beginning and end (allowing arbitrary whitespace), and maybe
# a terminating newline.
# We need the anchors because Python's match() matches an arbitrary prefix,
# not the entire string.
re_strings = [r"^\s*"] + re_strings + [r"\s*\n?$"]
full_re = re.compile("".join(re_strings))
return CheckCmd(line, checktype, full_re)
class Checker(object):
def __init__(self, name, lines):
self.name = name
# Helper to yield subline containing group1 from all matching lines.
def group1s(regex):
for line in lines:
m = regex.match(line.text)
if m:
yield line.subline(m.group(1))
# Find run commands.
self.runcmds = [RunCmd.parse(sl) for sl in group1s(RUN_RE)]
self.shebang_cmd = None
if not self.runcmds:
# If no RUN command has been given, fall back to the shebang.
if lines[0].text.startswith("#!"):
# Remove the "#!" at the beginning, and the newline at the end.
cmd = lines[0].text[2:-1]
self.shebang_cmd = cmd
self.runcmds = [RunCmd(cmd + " %s", lines[0])]
else:
raise CheckerError("No runlines ('# RUN') found")
self.requirecmds = [RunCmd.parse(sl) for sl in group1s(REQUIRES_RE)]
# Find check cmds.
self.outchecks = [
CheckCmd.parse(sl, "CHECK") for sl in group1s(CHECK_STDOUT_RE)
]
self.errchecks = [
CheckCmd.parse(sl, "CHECKERR") for sl in group1s(CHECK_STDERR_RE)
]
def check_file(input_file, name, subs, config, failure_handler):
""" Check a single file. Return a True on success, False on error. """
success = True
lines = Line.readfile(input_file, name)
checker = Checker(name, lines)
# Run all the REQUIRES lines first,
# if any of them fail it's a SKIP
for reqcmd in checker.requirecmds:
proc = runproc(
perform_substitution(reqcmd.args, subs)
)
proc.communicate()
if proc.returncode > 0:
return SKIP
if checker.shebang_cmd is not None and not find_command(checker.shebang_cmd):
raise CheckerError("Command could not be found: " + checker.shebang_cmd)
# Only then run the RUN lines.
for runcmd in checker.runcmds:
failure = TestRun(name, runcmd, checker, subs, config).run()
if failure:
failure_handler(failure)
success = False
return success
def check_path(path, subs, config, failure_handler):
with io.open(path, encoding="utf-8") as fd:
return check_file(fd, path, subs, config, failure_handler)
def parse_subs(subs):
"""Given a list of input substitutions like 'foo=bar',
return a dictionary like {foo:bar}, or exit if invalid.
"""
result = {}
for sub in subs:
try:
key, val = sub.split("=", 1)
if not key:
print("Invalid substitution %s: empty key" % sub)
sys.exit(1)
if not val:
print("Invalid substitution %s: empty value" % sub)
sys.exit(1)
result[key] = val
except ValueError:
print("Invalid substitution %s: equal sign not found" % sub)
sys.exit(1)
return result
def get_argparse():
""" Return a littlecheck argument parser. """
parser = argparse.ArgumentParser(
description="littlecheck: command line tool tester."
)
parser.add_argument(
"-s",
"--substitute",
type=str,
help="Add a new substitution for RUN lines. Example: bash=/bin/bash",
action="append",
default=[],
)
parser.add_argument(
"-p",
"--progress",
action="store_true",
dest="progress",
help="Show the files to be checked",
default=False,
)
parser.add_argument(
"--force-color",
action="store_true",
dest="force_color",
help="Force usage of color even if not connected to a terminal",
default=False,
)
parser.add_argument("file", nargs="+", help="File to check")
return parser
def main():
args = get_argparse().parse_args()
# Default substitution is %% -> %
def_subs = {"%": "%"}
def_subs.update(parse_subs(args.substitute))
tests_count = 0
failed = False
skip_count = 0
config = Config()
config.colorize = args.force_color or sys.stdout.isatty()
config.progress = args.progress
fields = config.colors()
for path in args.file:
tests_count += 1
fields["path"] = path
if config.progress:
print("Testing file {path} ... ".format(**fields), end="")
sys.stdout.flush()
subs = def_subs.copy()
subs["s"] = path
starttime = datetime.datetime.now()
ret = check_path(path, subs, config, TestFailure.print_message)
if not ret:
failed = True
elif config.progress:
endtime = datetime.datetime.now()
duration_ms = round((endtime - starttime).total_seconds() * 1000)
reason = "ok"
color = "{GREEN}"
if ret is SKIP:
skip_count += 1
reason = "SKIPPED"
color = "{BLUE}"
print(
(color + "{reason}{RESET} ({duration} ms)").format(
duration=duration_ms, reason=reason, **fields
)
)
# To facilitate integration with testing frameworks, use exit code 125 to indicate that all
# tests have been skipped (primarily for use when tests are run one at a time). Exit code 125 is
# used to indicate to automated `git bisect` runs that a revision has been skipped; we use it
# for the same reasons git does.
if skip_count > 0 and skip_count == tests_count:
sys.exit(125)
sys.exit(1 if failed else 0)
if __name__ == "__main__":
main()

View File

@@ -1,103 +0,0 @@
#!/usr/bin/env bash
# Helper to notarize an .app.zip or .pkg file.
# Based on https://www.logcg.com/en/archives/3222.html
set -e
die() { echo "$*" 1>&2 ; exit 1; }
check_status() {
echo "STATUS" $1
}
get_req_uuid() {
RESPONSE=$(</dev/stdin)
if echo "$RESPONSE" | egrep -q "RequestUUID"; then
echo "$RESPONSE" | egrep RequestUUID | awk '{print $3'}
elif echo "$RESPONSE" | egrep -q "The upload ID is "; then
echo "$RESPONSE" | egrep -p "The upload ID is [-a-z0-9]+" | awk '{print $5}'
else
die "Could not get Request UUID"
fi
}
INPUT=$1
AC_USER=$2
test -z "$AC_USER" && die "AC_USER not specified as second param"
test -z "$INPUT" && die "No path specified"
test -f "$INPUT" || die "Not a file: $INPUT"
ext="${INPUT##*.}"
(test "$ext" = "zip" || test "$ext" = "pkg") || die "Unrecognized extension: $ext"
LOGFILE=$(mktemp -t mac_notarize_log)
AC_PASS="@keychain:AC_PASSWORD"
echo "Logs at $LOGFILE"
NOTARIZE_UUID=$(xcrun altool --notarize-app \
--primary-bundle-id "com.ridiculousfish.fish-shell" \
--username "$AC_USER" \
--password "$AC_PASS" \
--file "$INPUT" 2>&1 |
tee -a "$LOGFILE" |
get_req_uuid)
test -z "$NOTARIZE_UUID" && cat "$LOGFILE" && die "Could not get RequestUUID"
echo "RequestUUID: $NOTARIZE_UUID"
# notarization-info doesn't always know about our request immediately.
echo "Giving notarization-info a chance to catch up..."
sleep 15
success=0
for i in $(seq 20); do
echo "Checking progress..."
PROGRESS=$(xcrun altool --notarization-info "${NOTARIZE_UUID}" \
-u "$AC_USER" \
-p "$AC_PASS" 2>&1 |
tee -a "$LOGFILE")
echo "${PROGRESS}" | tail -n 1
if [ $? -ne 0 ] || [[ "${PROGRESS}" =~ "Invalid" ]] ; then
echo "Error with notarization. Exiting"
break
fi
if ! [[ "${PROGRESS}" =~ "in progress" ]]; then
success=1
break
else
echo "Not completed yet. Sleeping for 30 seconds."
fi
sleep 30
done
if [ $success -eq 1 ] ; then
if test "$ext" = "zip"; then
TMPDIR=$(mktemp -d)
echo "Extracting to $TMPDIR"
unzip -q "$INPUT" -d "$TMPDIR"
# Force glob expansion.
STAPLE_TARGET="$TMPDIR"/*
STAPLE_TARGET=$(echo $STAPLE_TARGET)
else
STAPLE_TARGET="$INPUT"
fi
echo "Stapling $STAPLE_TARGET"
xcrun stapler staple "$STAPLE_TARGET"
if test "$ext" = "zip"; then
# Zip it back up.
INPUT_FULL=$(realpath "$INPUT")
rm -f "$INPUT"
cd "$(dirname "$STAPLE_TARGET")"
zip -r -q "$INPUT_FULL" $(basename "$STAPLE_TARGET")
fi
fi
echo "Processed $INPUT"
if test "$ext" = "zip"; then
spctl -a -v "$STAPLE_TARGET"
fi

View File

@@ -1,12 +1,14 @@
#!/usr/bin/env bash
#!/bin/sh
# Script to produce an OS X installer .pkg and .app(.zip)
VERSION=$(git describe --always --dirty 2>/dev/null)
VERSION=`git describe --always --dirty 2>/dev/null`
if test -z "$VERSION" ; then
echo "Could not get version from git"
if test -f version; then
VERSION=$(cat version)
VERSION=`sed -E -n 's/^.*PACKAGE_VERSION "([0-9a-z.\-]+)"/\1/p' osx/config.h`
if test -z "$VERSION"; then
echo "Could not get version from osx/config.h"
exit 1
fi
fi
@@ -14,27 +16,26 @@ echo "Version is $VERSION"
set -x
make distclean
#Exit on error
set -e
# Respect MAC_CODESIGN_ID, or default for ad-hoc.
# Note the :- means "or default" and the following - is the value.
MAC_CODESIGN_ID=${MAC_CODESIGN_ID:--}
PKGDIR=`mktemp -d`
PKGDIR=$(mktemp -d)
SRC_DIR=$PWD
OUTPUT_PATH=${FISH_ARTEFACT_PATH:-~/fish_built}
mkdir -p "$PKGDIR/build" "$PKGDIR/root" "$PKGDIR/intermediates" "$PKGDIR/dst"
{ cd "$PKGDIR/build" && cmake -DMAC_INJECT_GET_TASK_ALLOW=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo -DWITH_GETTEXT=OFF -DCMAKE_OSX_ARCHITECTURES='arm64;x86_64' -DMAC_CODESIGN_ID="${MAC_CODESIGN_ID}" "$SRC_DIR" && make VERBOSE=1 -j 12 && env DESTDIR="$PKGDIR/root/" make install; }
pkgbuild --scripts "$SRC_DIR/build_tools/osx_package_scripts" --root "$PKGDIR/root/" --identifier 'com.ridiculousfish.fish-shell-pkg' --version "$VERSION" "$PKGDIR/intermediates/fish.pkg"
productbuild --package-path "$PKGDIR/intermediates" --distribution "$SRC_DIR/build_tools/osx_distribution.xml" --resources "$SRC_DIR/build_tools/osx_package_resources/" "$OUTPUT_PATH/fish-$VERSION.pkg"
mkdir -p $PKGDIR/root $PKGDIR/intermediates $PKGDIR/dst
xcodebuild install -scheme install_tree -configuration Release DSTROOT=$PKGDIR/root/
pkgbuild --scripts build_tools/osx_package_scripts --root $PKGDIR/root/ --identifier 'com.ridiculousfish.fish-shell-pkg' --version "$VERSION" $PKGDIR/intermediates/fish.pkg
productbuild --package-path $PKGDIR/intermediates --distribution build_tools/osx_distribution.xml --resources build_tools/osx_package_resources/ $OUTPUT_PATH/fish-$VERSION.pkg
MAC_PRODUCTSIGN_ID=${MAC_PRODUCTSIGN_ID:--}
productsign --sign "${MAC_PRODUCTSIGN_ID}" "$OUTPUT_PATH/fish-$VERSION.pkg" "$OUTPUT_PATH/fish-$VERSION-signed.pkg" && mv "$OUTPUT_PATH/fish-$VERSION-signed.pkg" "$OUTPUT_PATH/fish-$VERSION.pkg"
# Make the app
{ cd "$PKGDIR/build" && make -j 12 signed_fish_macapp && zip -r "$OUTPUT_PATH/fish-$VERSION.app.zip" fish.app; }
xcodebuild -scheme fish.app -configuration Release DSTROOT=/tmp/fish_app/ SYMROOT=DerivedData/fish/Build/Products
rm -r "$PKGDIR"
cd DerivedData/fish/Build/Products/Release/
zip -r $OUTPUT_PATH/fish-$VERSION.app.zip fish.app
rm -r $PKGDIR

View File

@@ -2,7 +2,7 @@
# Script to generate a tarball
# We use git to output a tree. But we also want to build the user documentation
# and put that in the tarball, so that nobody needs to have sphinx installed
# and put that in the tarball, so that nobody needs to have doxygen installed
# to build it.
# Outputs to $FISH_ARTEFACT_PATH or ~/fish_built by default
@@ -14,7 +14,8 @@ set -e
# but to get the documentation in, we need to make a symlink called "fish-VERSION"
# and tar from that, so that the documentation gets the right prefix
# We need GNU tar as that supports the --mtime and --transform options
# We need GNU tar as that supports the --mtime option
# BSD tar supports --mtree but keeping them in sync sounds too hard
TAR=notfound
for try in tar gtar gnutar; do
if $try -Pcf /dev/null --mtime now /dev/null >/dev/null 2>&1; then
@@ -32,7 +33,7 @@ fi
wd="$PWD"
# Get the version from git-describe
VERSION=$(git describe --dirty 2>/dev/null)
VERSION=`git describe --dirty 2>/dev/null`
# The name of the prefix, which is the directory that you get when you untar
prefix="fish-$VERSION"
@@ -42,30 +43,35 @@ prefix="fish-$VERSION"
path=${FISH_ARTEFACT_PATH:-~/fish_built}/$prefix.tar
# Clean up stuff we've written before
rm -f "$path" "$path".xz
rm -f "$path" "$path".gz
# git starts the archive
git archive --format=tar --prefix="$prefix"/ HEAD > "$path"
# tarball out the documentation, generate a version file
PREFIX_TMPDIR=$(mktemp -d)
cd "$PREFIX_TMPDIR"
echo "$VERSION" > version
cmake "$wd"
make doc
# tarball out the documentation, generate a configure script and version file
autoreconf --no-recursive
./configure --with-doxygen
make doc share/man
echo $VERSION > version
TAR_APPEND="$TAR --append --file=$path --mtime=now --owner=0 --group=0 \
--mode=g+w,a+rX --transform s/^/$prefix\//"
$TAR_APPEND --no-recursion user_doc
$TAR_APPEND user_doc/html user_doc/man
$TAR_APPEND version
PREFIX_TMPDIR=`mktemp -d`
cd $PREFIX_TMPDIR
ln -s "$wd" "$prefix"
TAR_APPEND="$TAR --append --file=$path --mtime=now --owner=0 --group=0 --mode=g+w,a+rX"
$TAR_APPEND --no-recursion "$prefix"/user_doc
$TAR_APPEND "$prefix"/user_doc/html "$prefix"/share/man
$TAR_APPEND "$prefix"/version
$TAR_APPEND "$prefix"/configure "$prefix"/config.h.in
rm "$prefix"/version
unlink "$prefix"
cd -
rm -r "$PREFIX_TMPDIR"
rmdir $PREFIX_TMPDIR
# xz it
xz "$path"
# gzip it
gzip "$path"
# Output what we did, and the sha1 hash
echo "Tarball written to $path".xz
openssl dgst -sha256 "$path".xz
echo "Tarball written to $path".gz
openssl dgst -sha256 "$path".gz

View File

@@ -1,11 +1,10 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<installer-gui-script minSpecVersion="1">
<title>fish shell</title>
<welcome file="welcome.html" mime-type="text/html"/>
<welcome file="welcome.rtf"/>
<background file="terminal_logo.png" scaling="proportional" alignment="bottomleft"/>
<pkg-ref id="com.ridiculousfish.fish-shell-pkg"/>
<options hostArchitectures="arm64,x86_64" rootVolumeOnly="true"/>
<options customize="never" require-scripts="true"/>
<options customize="never" require-scripts="false"/>
<choices-outline>
<line choice="default">
<line choice="com.ridiculousfish.fish-shell-pkg"/>

View File

@@ -1,29 +0,0 @@
<html>
<head>
<style>
body {
font-family: system-ui, -apple-system, "Helvetica Neue", sans-serif;
font-size: 10pt;
}
code, tt {
font-family: ui-monospace, Menlo, monospace;
}
</style>
</head>
<body>
<p>
<strong>fish</strong> is a smart and user-friendly command line shell. For more information, visit <a href="https://fishshell.com">fishshell.com</a>.
</p>
<p>
<strong>fish</strong> will be installed into <tt>/usr/local/</tt>, and its path will be added to <wbr><tt>/etc/shells</tt> if necessary.
</p>
<p>
Your default shell will <em>not</em> be changed. To make <strong>fish</strong> your login shell after the installation, run:
</p>
<p>
<code>chsh -s /usr/local/bin/fish</code>
</p>
<p>Enjoy! Bugs can be reported on <a href="https://github.org/fish-shell/fish-shell/">GitHub</a>.</p>
</body>
</html>

View File

@@ -0,0 +1,26 @@
{\rtf1\ansi\ansicpg1252\cocoartf1485\cocoasubrtf410
{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;\f1\fnil\fcharset0 Menlo-Regular;}
{\colortbl;\red255\green255\blue255;}
{\*\expandedcolortbl;\csgenericrgb\c100000\c100000\c100000;}
{\info
{\author dlkfjslfjsfdlkfk}}\margl1440\margr1440\vieww10800\viewh8400\viewkind0
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
\f0\fs30 \cf0 Fish is a smart and user friendly command line shell. For more information, visit {\field{\*\fldinst{HYPERLINK "https://fishshell.com"}}{\fldrslt https://fishshell.com}}\
\
fish will be installed into
\f1\fs26 /usr/local/
\f0\fs30 , and fish will be added to
\f1\fs26 /etc/shells
\f0\fs30 if necessary.\
\
Your default shell will
\i not
\i0 be changed. To make fish your default, run:\
\
\f1 chsh -s /usr/local/bin/fish
\f0 \
\
Enjoy!\
}

View File

@@ -1,3 +1,3 @@
#!/bin/sh -x
./add-shell ${DSTVOLUME}usr/local/bin/fish
./add-shell /usr/local/bin/fish > /tmp/fish_postinstall_output.log

View File

@@ -1,7 +0,0 @@
#!/bin/sh -x
echo "Removing any previous installation"
pkgutil --pkg-info ${INSTALL_PKG_SESSION_ID} && pkgutil --only-files --files ${INSTALL_PKG_SESSION_ID} | while read installed
do rm -v ${DSTVOLUME}${installed}
done
echo "... removed"

View File

@@ -1,338 +0,0 @@
"""pexpect_helper provides a wrapper around the pexpect module.
This module exposes a single class SpawnedProc, which wraps pexpect.spawn().
This exposes a pseudo-tty, which fish or another process may talk to.
The send() function may be used to send data to fish, and the expect_* family
of functions may be used to match what is output to the tty.
Example usage:
sp = SpawnedProc() # this launches fish
sp.expect_prompt() # wait for a prompt
sp.sendline("echo hello world")
sp.expect_prompt("hello world")
"""
from __future__ import print_function
import inspect
import os
import os.path
import re
import sys
import time
import pexpect
# Default timeout for failing to match.
TIMEOUT_SECS = 5
UNEXPECTED_SUCCESS = object()
def get_prompt_re(counter):
"""Return a regular expression for matching a with a given prompt counter."""
return re.compile(
r"""(?:\r\n?|^) # beginning of line
(?:\x1b[\d\[KB(m]*)* # optional colors
(?:\[.\]\ )? # optional vi mode prompt
"""
+ (r"prompt\ %d>" % counter) # prompt with counter
+ r"""
(?:\x1b[\d\[KB(m]*)* # optional colors
""",
re.VERBOSE,
)
def get_callsite():
"""Return a triple (filename, line_number, line_text) of the call site location."""
callstack = inspect.getouterframes(inspect.currentframe())
for f in callstack:
if inspect.getmodule(f.frame) is not Message.MODULE:
return (os.path.basename(f.filename), f.lineno, f.code_context)
return ("Unknown", -1, "")
def escape(s):
"""Escape the string 's' to make it human-understandable."""
res = []
for c in s:
if c == "\n":
res.append("\\n")
elif c == "\r":
res.append("\\r")
elif c == "\t":
res.append("\\t")
elif c.isprintable():
res.append(c)
else:
res.append("\\x{:02x}".format(ord(c)))
return "".join(res)
def pexpect_error_type(err):
"""Return a human-readable description of a pexpect error type."""
if isinstance(err, pexpect.EOF):
return "EOF"
elif isinstance(err, pexpect.TIMEOUT):
return "timeout"
elif err is UNEXPECTED_SUCCESS:
return "unexpected success"
else:
return "unknown error"
class Message(object):
"""Some text either sent-to or received-from the spawned proc.
Attributes:
dir: the message direction, either DIR_INPUT or DIR_OUTPUT
filename: the name of the file from which the message was sent
text: the text of the messages
when: a timestamp of when the message was sent
"""
# Input is input into fish shell ("sent data").
DIR_INPUT = " INPUT"
# Output means output from fish shell ("received data").
DIR_OUTPUT = "OUTPUT"
MODULE = sys.modules[__name__]
def __init__(self, dir, text, when):
"""Construct from a direction, message text and timestamp."""
self.dir = dir
self.filename, self.lineno, _ = get_callsite()
self.text = text
self.when = when
@staticmethod
def sent_input(text, when):
"""Return an input message with the given text."""
return Message(Message.DIR_INPUT, text, when)
@staticmethod
def received_output(text, when):
"""Return a output message with the given text."""
return Message(Message.DIR_OUTPUT, text, when)
class SpawnedProc(object):
"""A process, talking to our ptty. This wraps pexpect.spawn.
Attributes:
colorize: whether error messages should have ANSI color escapes
messages: list of Message sent and received, in-order
start_time: the timestamp of the first message, or None if none yet
spawn: the pexpect.spawn value
prompt_counter: the index of the prompt. This cooperates with the fish_prompt
function to ensure that each printed prompt is distinct.
"""
def __init__(
self, name="fish", timeout=TIMEOUT_SECS, env=os.environ.copy(), **kwargs
):
"""Construct from a name, timeout, and environment.
Args:
name: the name of the executable to launch, as a key into the
environment dictionary. By default this is 'fish' but may be
other executables.
timeout: A timeout to pass to pexpect. This indicates how long to wait
before giving up on some expected output.
env: a string->string dictionary, describing the environment variables.
"""
if name not in env:
raise ValueError("'%s' variable not found in environment" % name)
exe_path = env.get(name)
self.colorize = sys.stdout.isatty() or env.get("FISH_FORCE_COLOR", "0") == "1"
self.messages = []
self.start_time = None
self.spawn = pexpect.spawn(
exe_path, env=env, encoding="utf-8", timeout=timeout, **kwargs
)
self.spawn.delaybeforesend = None
self.prompt_counter = 0
def time_since_first_message(self):
"""Return a delta in seconds since the first message, or 0 if this is the first."""
now = time.monotonic()
if not self.start_time:
self.start_time = now
return now - self.start_time
def send(self, s):
"""Cover over pexpect.spawn.send().
Send the given string to the tty, returning the number of bytes written.
"""
res = self.spawn.send(s)
when = self.time_since_first_message()
self.messages.append(Message.sent_input(s, when))
return res
def sendline(self, s):
"""Cover over pexpect.spawn.sendline().
Send the given string + linesep to the tty, returning the number of bytes written.
"""
return self.send(s + os.linesep)
def expect_re(self, pat, pat_desc=None, unmatched=None, shouldfail=False, **kwargs):
"""Cover over pexpect.spawn.expect().
Consume all "new" output of self.spawn until the given pattern is matched, or
the timeout is reached.
Note that output between the current position and the location of the match is
consumed as well.
The pattern is typically a regular expression in string form, but may also be
any of the types accepted by pexpect.spawn.expect().
If the 'unmatched' parameter is given, it is printed as part of the error message
of any failure.
On failure, this prints an error and exits.
"""
try:
self.spawn.expect(pat, **kwargs)
when = self.time_since_first_message()
self.messages.append(
Message.received_output(self.spawn.match.group(), when)
)
# When a match is found,
# spawn.match is the MatchObject that produced it.
# This can be used to check what exactly was matched.
if shouldfail:
err = UNEXPECTED_SUCCESS
if not pat_desc:
pat_desc = str(pat)
self.report_exception_and_exit(pat_desc, unmatched, err)
return self.spawn.match
except pexpect.ExceptionPexpect as err:
if shouldfail:
return True
if not pat_desc:
pat_desc = str(pat)
self.report_exception_and_exit(pat_desc, unmatched, err)
def expect_str(self, s, **kwargs):
"""Cover over expect_re() which accepts a literal string."""
return self.expect_re(re.escape(s), **kwargs)
def expect_prompt(self, *args, increment=True, **kwargs):
"""Convenience function which matches some text and then a prompt.
Match the given positional arguments as expect_re, and then look
for a prompt.
If increment is set, then this should be a new prompt and the prompt counter
should be bumped; otherwise this is not a new prompt.
Returns None on success, and exits on failure.
Example:
sp.sendline("echo hello world")
sp.expect_prompt("hello world")
"""
if args:
self.expect_re(*args, **kwargs)
if increment:
self.prompt_counter += 1
self.expect_re(
get_prompt_re(self.prompt_counter),
pat_desc="prompt %d" % self.prompt_counter,
)
def report_exception_and_exit(self, pat, unmatched, err):
"""Things have gone badly.
We have an exception 'err', some pexpect.ExceptionPexpect.
Report it to stdout, along with the offending call site.
If 'unmatched' is set, print it to stdout.
"""
colors = self.colors()
failtype = pexpect_error_type(err)
fmtkeys = {"failtype": failtype, "pat": escape(pat)}
fmtkeys.update(**colors)
filename, lineno, code_context = get_callsite()
fmtkeys["filename"] = filename
fmtkeys["lineno"] = lineno
fmtkeys["code"] = "\n".join(code_context)
if unmatched:
print(
"{RED}Error: {NORMAL}{BOLD}{unmatched}{RESET}".format(
unmatched=unmatched, **fmtkeys
)
)
print(
"{RED}Failed to match pattern:{NORMAL} {BOLD}{pat}{RESET}".format(**fmtkeys)
)
print(
"{filename}:{lineno}: {BOLD}{failtype}{RESET} from {code}".format(**fmtkeys)
)
print("")
print("{CYAN}Escaped buffer:{RESET}".format(**colors))
print(escape(self.spawn.before))
print("")
print("{CYAN}When written to the tty, this looks like:{RESET}".format(**colors))
print("{CYAN}<-------{RESET}".format(**colors))
sys.stdout.write(self.spawn.before)
sys.stdout.flush()
print("{RESET}\n{CYAN}------->{RESET}".format(**colors))
print("")
# Show the last 10 messages.
print("Last 10 messages:")
delta = None
for m in self.messages[-10:]:
etext = escape(m.text)
timestamp = m.when * 1000.0
# Use relative timestamps and add a sign.
# This assumes a max length of 10^10 milliseconds (115 days) for the initial timestamp,
# and 11.5 days for the delta.
if delta:
timestamp -= delta
timestampstr = "{timestamp:+10.2f} ms".format(timestamp=timestamp)
else:
timestampstr = "{timestamp:10.2f} ms".format(timestamp=timestamp)
delta = m.when * 1000.0
print(
"{dir} {timestampstr} (Line {lineno}): {BOLD}{etext}{RESET}".format(
dir=m.dir,
timestampstr=timestampstr,
filename=m.filename,
lineno=m.lineno,
etext=etext,
**colors
)
)
print("")
sys.exit(1)
def sleep(self, secs):
"""Cover over time.sleep()."""
time.sleep(secs)
def colors(self):
"""Return a dictionary mapping color names to ANSI escapes"""
def ansic(n):
"""Return either an ANSI escape sequence for a color, or empty string."""
return "\033[%dm" % n if self.colorize else ""
return {
"RESET": ansic(0),
"BOLD": ansic(1),
"NORMAL": ansic(39),
"BLACK": ansic(30),
"RED": ansic(31),
"GREEN": ansic(32),
"YELLOW": ansic(33),
"BLUE": ansic(34),
"MAGENTA": ansic(35),
"CYAN": ansic(36),
"LIGHTGRAY": ansic(37),
"DARKGRAY": ansic(90),
"LIGHTRED": ansic(91),
"LIGHTGREEN": ansic(92),
"LIGHTYELLOW": ansic(93),
"LIGHTBLUE": ansic(94),
"LIGHTMAGENTA": ansic(95),
"LIGHTCYAN": ansic(96),
"WHITE": ansic(97),
}

View File

@@ -1,15 +1,17 @@
#!/usr/bin/env fish
#
# This is meant to be run by "make style" or "make style-all". It is not meant to
# be run directly from a shell prompt although it can be.
#
# This runs C++ files and fish scripts (*.fish) through their respective code
# formatting programs.
#
set -l git_clang_format no
set -l c_files
set -l fish_files
set -l python_files
set -l all no
set git_clang_format no
set c_files
set f_files
set all no
if test "$argv[1]" = --all
if test "$argv[1]" = "--all"
set all yes
set -e argv[1]
end
@@ -20,21 +22,23 @@ if set -q argv[1]
end
if test $all = yes
set -l 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]
echo
echo You have uncommitted changes. Cowardly refusing to restyle the entire code base.
echo You have uncommited changes. Cowardly refusing to restyle the entire code base.
echo
exit 1
end
set c_files src/*.h src/*.cpp src/*.c
set fish_files share/**.fish
set python_files {doc_src,share,tests}/**.py
# For now we don't restyle all fish scripts other than completion scripts. That's because people
# really like to vertically align the elements of the `complete` command and fish_indent
# currently does not honor that whitespace.
set f_files (printf '%s\n' share/***.fish | grep -v /completions/)
else
# 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.
# Select (cached files) (modified but not cached, and untracked files)
set -l files (git diff-index --cached HEAD --name-only) (git ls-files --exclude-standard --others --modified)
set files (git diff-index --cached HEAD --name-only) (git ls-files --exclude-standard --others --modified)
if set -q files[1]
set git_clang_format yes
else
@@ -48,20 +52,17 @@ else
test -f $file; and set c_files $c_files $file
end
# Extract just the fish files.
set fish_files (string match -r '^.*\.fish$' -- $files)
set python_files (string match -r '^.*\.py$' -- $files)
set f_files (string match -r '^.*\.fish$' -- $files)
end
set -l red (set_color red)
set -l green (set_color green)
set -l blue (set_color blue)
set -l normal (set_color normal)
# Run the C++ reformatter if we have any C++ files.
if set -q c_files[1]
if test $git_clang_format = yes
if type -q git-clang-format
echo === Running "$red"git-clang-format"$normal"
echo
echo ========================================
echo Running git-clang-format
echo ========================================
git add $c_files
git-clang-format
else
@@ -70,7 +71,10 @@ if set -q c_files[1]
echo
end
else if type -q clang-format
echo === Running "$red"clang-format"$normal"
echo
echo ========================================
echo Running clang-format
echo ========================================
for file in $c_files
cp $file $file.new # preserves mode bits
clang-format $file >$file.new
@@ -89,22 +93,23 @@ if set -q c_files[1]
end
# Run the fish reformatter if we have any fish files.
if set -q fish_files[1]
if set -q f_files[1]
if not type -q fish_indent
make fish_indent
set PATH . $PATH
end
echo === Running "$green"fish_indent"$normal"
fish_indent -w -- $fish_files
end
if set -q python_files[1]
if not type -q black
echo
echo Please install "`black`" to style python
echo
else
echo === Running "$blue"black"$normal"
black $python_files
echo
echo ========================================
echo Running fish_indent
echo ========================================
for file in $f_files
cp $file $file.new # preserves mode bits
fish_indent <$file >$file.new
if cmp --quiet $file $file.new
rm $file.new
else
echo $file was NOT correctly formatted
mv $file.new $file
end
end
end

View File

@@ -0,0 +1,12 @@
#!/bin/bash
# Expects to be called from Xcode (Run Script build phase),
# write version number C preprocessor macro to header file.
ver="$SCRIPT_OUTPUT_FILE_0"
./build_tools/git_version_gen.sh
cmp --quiet "FISH-BUILD-VERSION-FILE" "$ver"
if [ $? -ne 0 ]; then
/bin/cp FISH-BUILD-VERSION-FILE "$ver"
fi

View File

@@ -1,6 +0,0 @@
# Support for benchmarking fish.
add_custom_target(benchmark
COMMAND ${CMAKE_SOURCE_DIR}/benchmarks/driver.sh $<TARGET_FILE:fish>
USES_TERMINAL
)

View File

@@ -56,9 +56,9 @@ macro(CHECK_INCLUDE_FILES INCLUDE VARIABLE)
endif()
if(_lang STREQUAL "C")
set(src ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckIncludeFiles/${VARIABLE}.c)
set(src ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckIncludeFiles/${var}.c)
elseif(_lang STREQUAL "CXX")
set(src ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckIncludeFiles/${VARIABLE}.cpp)
set(src ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckIncludeFiles/${var}.cpp)
else()
message(FATAL_ERROR "Unknown language:\n ${_lang}\nSupported languages: C, CXX.\n")
endif()

View File

@@ -1,191 +1,126 @@
# The following defines affect the environment configuration tests are run in:
# CMAKE_REQUIRED_DEFINITIONS, CMAKE_REQUIRED_FLAGS, CMAKE_REQUIRED_LIBRARIES,
# and CMAKE_REQUIRED_INCLUDES
# `wcstod_l` is a GNU-extension, sometimes hidden behind GNU-related defines.
# This is the case for at least Cygwin and Newlib.
list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE=1)
include(CheckCXXCompilerFlag)
if(APPLE)
check_cxx_compiler_flag("-Werror=unguarded-availability" REQUIRES_UNGUARDED_AVAILABILITY)
if(REQUIRES_UNGUARDED_AVAILABILITY)
list(APPEND CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} "-Werror=unguarded-availability")
endif()
endif()
# An unrecognized flag is usually a warning and not an error, which CMake apparently does
# not pick up on. Combine it with -Werror to determine if it's actually supported.
# This is not bulletproof; old versions of GCC only emit a warning about unrecognized warning
# options when there are other warnings to emit :rolleyes:
# See https://github.com/fish-shell/fish-shell/commit/fe2da0a9#commitcomment-47431659
# GCC supports -Wno-redundant-move from GCC9 onwards
check_cxx_compiler_flag("-Werror=no-redundant-move" HAS_NO_REDUNDANT_MOVE)
if (HAS_NO_REDUNDANT_MOVE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-redundant-move")
endif()
# Clang once supported -Wno-redundant-move but replaced it with a Wredundant-move option instead
# (and it is functionally different from its older version of GCC's Wno-redundant-move).
check_cxx_compiler_flag("-Werror=redundant-move" HAS_REDUNDANT_MOVE)
if (HAS_REDUNDANT_MOVE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wredundant-move")
endif()
# Try using CMake's own logic to locate curses/ncurses
find_package(Curses)
if(NOT ${CURSES_FOUND})
# CMake has trouble finding platform-specific system libraries
# installed to multiarch paths (e.g. /usr/lib/x86_64-linux-gnu)
# if not symlinked or passed in as a manual define.
message("Falling back to pkg-config for (n)curses detection")
include(FindPkgConfig)
pkg_search_module(CURSES REQUIRED ncurses curses)
set(CURSES_CURSES_LIBRARY ${CURSES_LIBRARIES})
set(CURSES_LIBRARY ${CURSES_LIBRARIES})
endif()
# Set up extra include directories for CheckIncludeFile
list(APPEND CMAKE_REQUIRED_INCLUDES ${CURSES_INCLUDE_DIRS})
# Fix undefined reference to tparm on RHEL 6 and potentially others
# If curses is found via CMake, it also links against tinfo if it exists. But if we use our
# fallback pkg-config logic above, we need to do this manually.
find_library(CURSES_TINFO tinfo)
if (CURSES_TINFO)
set(CURSES_LIBRARY ${CURSES_LIBRARY} ${CURSES_TINFO})
endif()
# Detect curses.
FIND_PACKAGE(Curses REQUIRED)
# Get threads.
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
# FindThreads < 3.4.0 doesn't work for C++-only projects
IF(CMAKE_VERSION VERSION_LESS 3.4.0)
ENABLE_LANGUAGE(C)
ENDIF()
FIND_PACKAGE(Threads REQUIRED)
IF(APPLE)
# 10.7+ only.
SET(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} "-Werror=unguarded-availability")
ENDIF()
# Detect WSL. Does not match against native Windows/WIN32.
if (CMAKE_HOST_SYSTEM_VERSION MATCHES ".*-Microsoft")
set(WSL 1)
SET(WSL 1)
endif()
# Set up the config.h file.
set(PACKAGE_NAME "fish")
set(PACKAGE_TARNAME "fish")
include(CheckCXXSymbolExists)
include(CheckIncludeFileCXX)
include(CheckIncludeFiles)
include(CheckStructHasMember)
include(CheckCXXSourceCompiles)
include(CheckTypeSize)
include(CMakePushCheckState)
check_cxx_symbol_exists(backtrace_symbols execinfo.h HAVE_BACKTRACE_SYMBOLS)
# workaround for lousy mtime precision on a Linux kernel
if (CMAKE_SYSTEM_NAME MATCHES "Linux|Android")
check_cxx_symbol_exists(clock_gettime time.h HAVE_CLOCK_GETTIME)
check_cxx_symbol_exists(futimens sys/stat.h HAVE_FUTIMENS)
if ((HAVE_CLOCK_GETTIME) AND (HAVE_FUTIMENS))
set(UVAR_FILE_SET_MTIME_HACK 1)
endif()
endif()
check_cxx_symbol_exists(ctermid_r stdio.h HAVE_CTERMID_R)
check_struct_has_member("struct dirent" d_type dirent.h HAVE_STRUCT_DIRENT_D_TYPE LANGUAGE CXX)
check_cxx_symbol_exists(dirfd "sys/types.h;dirent.h" HAVE_DIRFD)
check_include_file_cxx(execinfo.h HAVE_EXECINFO_H)
check_cxx_symbol_exists(flock sys/file.h HAVE_FLOCK)
check_cxx_symbol_exists(getifaddrs ifaddrs.h HAVE_GETIFADDRS)
check_cxx_symbol_exists(getpwent pwd.h HAVE_GETPWENT)
check_cxx_symbol_exists(getrusage sys/resource.h HAVE_GETRUSAGE)
check_cxx_symbol_exists(gettext libintl.h HAVE_GETTEXT)
check_cxx_symbol_exists(killpg "sys/types.h;signal.h" HAVE_KILLPG)
SET(PACKAGE_NAME "fish")
SET(PACKAGE_TARNAME "fish")
INCLUDE(CheckCXXSymbolExists)
INCLUDE(CheckIncludeFileCXX)
INCLUDE(CheckIncludeFiles)
INCLUDE(CheckStructHasMember)
INCLUDE(CheckCXXSourceCompiles)
INCLUDE(CheckTypeSize)
INCLUDE(CMakePushCheckState)
CHECK_CXX_SYMBOL_EXISTS(backtrace_symbols execinfo.h HAVE_BACKTRACE_SYMBOLS)
CHECK_CXX_SYMBOL_EXISTS(clock_gettime time.h HAVE_CLOCK_GETTIME)
CHECK_CXX_SYMBOL_EXISTS(ctermid_r stdio.h HAVE_CTERMID_R)
CHECK_STRUCT_HAS_MEMBER("struct dirent" d_type dirent.h HAVE_STRUCT_DIRENT_D_TYPE LANGUAGE CXX)
CHECK_CXX_SYMBOL_EXISTS(dirfd "sys/types.h;dirent.h" HAVE_DIRFD)
CHECK_INCLUDE_FILE_CXX(execinfo.h HAVE_EXECINFO_H)
CHECK_CXX_SYMBOL_EXISTS(flock sys/file.h HAVE_FLOCK)
# futimens is new in OS X 10.13 but is a weak symbol.
# Don't assume it exists just because we can link - it may be null.
CHECK_CXX_SYMBOL_EXISTS(futimens sys/stat.h HAVE_FUTIMENS)
CHECK_CXX_SYMBOL_EXISTS(futimes sys/time.h HAVE_FUTIMES)
CHECK_CXX_SYMBOL_EXISTS(getifaddrs ifaddrs.h HAVE_GETIFADDRS)
CHECK_CXX_SYMBOL_EXISTS(getpwent pwd.h HAVE_GETPWENT)
CHECK_CXX_SYMBOL_EXISTS(gettext libintl.h HAVE_GETTEXT)
CHECK_CXX_SYMBOL_EXISTS(killpg "sys/types.h;signal.h" HAVE_KILLPG)
CHECK_CXX_SYMBOL_EXISTS(lrand48_r stdlib.h HAVE_LRAND48_R)
# mkostemp is in stdlib in glibc and FreeBSD, but unistd on macOS
check_cxx_symbol_exists(mkostemp "stdlib.h;unistd.h" HAVE_MKOSTEMP)
set(HAVE_CURSES_H ${CURSES_HAVE_CURSES_H})
set(HAVE_NCURSES_CURSES_H ${CURSES_HAVE_NCURSES_CURSES_H})
set(HAVE_NCURSES_H ${CURSES_HAVE_NCURSES_H})
if(HAVE_CURSES_H)
check_include_files("curses.h;term.h" HAVE_TERM_H)
endif()
if(NOT HAVE_TERM_H)
check_include_file_cxx("ncurses/term.h" HAVE_NCURSES_TERM_H)
endif()
check_include_file_cxx(siginfo.h HAVE_SIGINFO_H)
check_include_file_cxx(spawn.h HAVE_SPAWN_H)
check_struct_has_member("struct stat" st_ctime_nsec "sys/stat.h" HAVE_STRUCT_STAT_ST_CTIME_NSEC
CHECK_CXX_SYMBOL_EXISTS(mkostemp "stdlib.h;unistd.h" HAVE_MKOSTEMP)
SET(HAVE_CURSES_H ${CURSES_HAVE_CURSES_H})
SET(HAVE_NCURSES_CURSES_H ${CURSES_HAVE_NCURSES_CURSES_H})
SET(HAVE_NCURSES_H ${CURSES_HAVE_NCURSES_H})
CHECK_INCLUDE_FILES("curses.h;term.h" HAVE_TERM_H)
CHECK_INCLUDE_FILE_CXX("ncurses/term.h" HAVE_NCURSES_TERM_H)
CHECK_INCLUDE_FILE_CXX(siginfo.h HAVE_SIGINFO_H)
CHECK_INCLUDE_FILE_CXX(spawn.h HAVE_SPAWN_H)
CHECK_CXX_SYMBOL_EXISTS(std::wcscasecmp wchar.h HAVE_STD__WCSCASECMP)
CHECK_CXX_SYMBOL_EXISTS(std::wcsdup wchar.h HAVE_STD__WCSDUP)
CHECK_CXX_SYMBOL_EXISTS(std::wcsncasecmp wchar.h HAVE_STD__WCSNCASECMP)
CHECK_STRUCT_HAS_MEMBER("struct stat" st_ctime_nsec "sys/stat.h" HAVE_STRUCT_STAT_ST_CTIME_NSEC
LANGUAGE CXX)
check_struct_has_member("struct stat" st_mtimespec.tv_nsec "sys/stat.h"
CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtimespec.tv_nsec "sys/stat.h"
HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC LANGUAGE CXX)
check_struct_has_member("struct stat" st_mtim.tv_nsec "sys/stat.h" HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtim.tv_nsec "sys/stat.h" HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
LANGUAGE CXX)
check_include_file_cxx(sys/ioctl.h HAVE_SYS_IOCTL_H)
check_include_file_cxx(sys/select.h HAVE_SYS_SELECT_H)
CHECK_CXX_SYMBOL_EXISTS(sys_errlist stdio.h HAVE_SYS_ERRLIST)
CHECK_INCLUDE_FILE_CXX(sys/ioctl.h HAVE_SYS_IOCTL_H)
CHECK_INCLUDE_FILE_CXX(sys/select.h HAVE_SYS_SELECT_H)
CHECK_INCLUDE_FILES("sys/types.h;sys/sysctl.h" HAVE_SYS_SYSCTL_H)
CHECK_INCLUDE_FILE_CXX(termios.h HAVE_TERMIOS_H) # Needed for TIOCGWINSZ
CHECK_CXX_SYMBOL_EXISTS(wcscasecmp wchar.h HAVE_WCSCASECMP)
CHECK_CXX_SYMBOL_EXISTS(wcsdup wchar.h HAVE_WCSDUP)
CHECK_CXX_SYMBOL_EXISTS(wcslcpy wchar.h HAVE_WCSLCPY)
CHECK_CXX_SYMBOL_EXISTS(wcsncasecmp wchar.h HAVE_WCSNCASECMP)
CHECK_CXX_SYMBOL_EXISTS(wcsndup wchar.h HAVE_WCSNDUP)
# glibc 2.30 deprecated <sys/sysctl.h> because that's what glibc does.
# Checking for that here rather than hardcoding a check on the glibc
# version in the C++ sources at point of use makes more sense.
SET(OLD_CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
check_include_files("sys/types.h;sys/sysctl.h" HAVE_SYS_SYSCTL_H)
SET(CMAKE_C_FLAGS "${OLD_CMAKE_C_FLAGS}")
CMAKE_PUSH_CHECK_STATE(RESET)
# `wcstod_l` is a GNU-extension, sometimes hidden behind the following define
LIST(APPEND CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE=1)
# `xlocale.h` is required to find `wcstod_l` in `wchar.h` under FreeBSD, but
# it's not present under Linux.
SET(WCSTOD_L_INCLUDES "")
CHECK_INCLUDE_FILES("xlocale.h" HAVE_XLOCALE_H)
IF(HAVE_XLOCALE_H)
LIST(APPEND WCSTOD_L_INCLUDES "xlocale.h")
ENDIF()
LIST(APPEND WCSTOD_L_INCLUDES "wchar.h")
CHECK_CXX_SYMBOL_EXISTS(wcstod_l "${WCSTOD_L_INCLUDES}" HAVE_WCSTOD_L)
CMAKE_POP_CHECK_STATE()
check_cxx_symbol_exists(eventfd sys/eventfd.h HAVE_EVENTFD)
check_cxx_symbol_exists(pipe2 unistd.h HAVE_PIPE2)
check_cxx_symbol_exists(wcscasecmp wchar.h HAVE_WCSCASECMP)
check_cxx_symbol_exists(wcsdup wchar.h HAVE_WCSDUP)
check_cxx_symbol_exists(wcslcpy wchar.h HAVE_WCSLCPY)
check_cxx_symbol_exists(wcsncasecmp wchar.h HAVE_WCSNCASECMP)
check_cxx_symbol_exists(wcsndup wchar.h HAVE_WCSNDUP)
CHECK_CXX_SYMBOL_EXISTS(_sys_errs stdlib.h HAVE__SYS__ERRS)
# These are for compatibility with Solaris 10, which places the following
# in the std namespace.
if(NOT HAVE_WCSNCASECMP)
check_cxx_symbol_exists(std::wcscasecmp wchar.h HAVE_STD__WCSCASECMP)
endif()
if(NOT HAVE_WCSDUP)
check_cxx_symbol_exists(std::wcsdup wchar.h HAVE_STD__WCSDUP)
endif()
if(NOT HAVE_WCSNCASECMP)
check_cxx_symbol_exists(std::wcsncasecmp wchar.h HAVE_STD__WCSNCASECMP)
endif()
SET(CMAKE_EXTRA_INCLUDE_FILES termios.h sys/ioctl.h)
CHECK_TYPE_SIZE("struct winsize" STRUCT_WINSIZE LANGUAGE CXX)
CHECK_CXX_SYMBOL_EXISTS("TIOCGWINSZ" "termios.h;sys/ioctl.h" HAVE_TIOCGWINSZ)
IF(STRUCT_WINSIZE GREATER -1 AND HAVE_TIOCGWINSZ EQUAL 1)
SET(HAVE_WINSIZE 1)
ENDIF()
SET(CMAKE_EXTRA_INCLUDE_FILES)
# `xlocale.h` is required to find `wcstod_l` in `wchar.h` under FreeBSD,
# but it's not present under Linux.
check_include_files("xlocale.h" HAVE_XLOCALE_H)
if(HAVE_XLOCALE_H)
list(APPEND WCSTOD_L_INCLUDES "xlocale.h")
endif()
list(APPEND WCSTOD_L_INCLUDES "wchar.h")
check_cxx_symbol_exists(wcstod_l "${WCSTOD_L_INCLUDES}" HAVE_WCSTOD_L)
IF(EXISTS "/proc/self/stat")
SET(HAVE__PROC_SELF_STAT 1)
ENDIF()
CHECK_TYPE_SIZE("wchar_t[8]" WCHAR_T_BITS LANGUAGE CXX)
check_cxx_symbol_exists(uselocale "locale.h;xlocale.h" HAVE_USELOCALE)
# Solaris, NetBSD and X/Open-conforming systems have a fixed-args tparm
SET(TPARM_INCLUDES)
IF(HAVE_NCURSES_H)
SET(TPARM_INCLUDES "${TPARM_INCLUDES}#include <ncurses.h>\n")
ELSEIF(HAVE_NCURSES_CURSES_H)
SET(TPARM_INCLUDES "${TPARM_INCLUDES}#include <ncurses/curses.h>\n")
ELSE()
SET(TPARM_INCLUDES "${TPARM_INCLUDES}#include <curses.h>\n")
ENDIF()
cmake_push_check_state()
set(CMAKE_EXTRA_INCLUDE_FILES termios.h sys/ioctl.h)
check_type_size("struct winsize" STRUCT_WINSIZE LANGUAGE CXX)
check_cxx_symbol_exists("TIOCGWINSZ" "termios.h;sys/ioctl.h" HAVE_TIOCGWINSZ)
if(STRUCT_WINSIZE GREATER -1 AND HAVE_TIOCGWINSZ EQUAL 1)
set(HAVE_WINSIZE 1)
endif()
cmake_pop_check_state()
IF(HAVE_TERM_H)
SET(TPARM_INCLUDES "${TPARM_INCLUDES}#include <term.h>\n")
ELSEIF(HAVE_NCURSES_TERM_H)
SET(TPARM_INCLUDES "${TPARM_INCLUDES}#include <ncurses/term.h>\n")
ENDIF()
check_type_size("wchar_t[8]" WCHAR_T_BITS LANGUAGE CXX)
set(TPARM_INCLUDES)
if(HAVE_NCURSES_H)
set(TPARM_INCLUDES "${TPARM_INCLUDES}#include <ncurses.h>\n")
elseif(HAVE_NCURSES_CURSES_H)
set(TPARM_INCLUDES "${TPARM_INCLUDES}#include <ncurses/curses.h>\n")
else()
set(TPARM_INCLUDES "${TPARM_INCLUDES}#include <curses.h>\n")
endif()
if(HAVE_TERM_H)
set(TPARM_INCLUDES "${TPARM_INCLUDES}#include <term.h>\n")
elseif(HAVE_NCURSES_TERM_H)
set(TPARM_INCLUDES "${TPARM_INCLUDES}#include <ncurses/term.h>\n")
endif()
cmake_push_check_state()
list(APPEND CMAKE_REQUIRED_LIBRARIES ${CURSES_LIBRARY})
# Solaris and X/Open-conforming systems have a fixed-args tparm
check_cxx_source_compiles("
#define TPARM_VARARGS
SET(CMAKE_REQUIRED_LIBRARIES ${CURSES_LIBRARY})
CHECK_CXX_SOURCE_COMPILES("
${TPARM_INCLUDES}
int main () {
@@ -194,41 +129,12 @@ int main () {
"
TPARM_TAKES_VARARGS
)
SET(CMAKE_REQUIRED_LIBRARIES)
IF(NOT TPARM_TAKES_VARARGS)
SET(TPARM_SOLARIS_KLUDGE 1)
ENDIF()
# Check if tputs needs a function reading an int or char.
# The only curses I can find that needs a char is OpenIndiana.
check_cxx_source_compiles("
#include <curses.h>
#include <term.h>
static int writer(int b) {
return b;
}
int main() {
return tputs(\"foo\", 5, writer);
}"
TPUTS_USES_INT_ARG
)
if(TPARM_TAKES_VARARGS)
set(TPARM_VARARGS 1)
else()
set(TPARM_SOLARIS_KLUDGE 1)
endif()
cmake_pop_check_state()
# Work around the fact that cmake does not propagate the language standard flag into
# the CHECK_CXX_SOURCE_COMPILES function. See CMake issue #16456.
# Ensure we do this after the FIND_PACKAGE calls which use C, and will error on a C++
# standards flag.
# Also see https://github.com/fish-shell/fish-shell/issues/5865
if(NOT POLICY CMP0067)
list(APPEND CMAKE_REQUIRED_FLAGS "${CMAKE_CXX${CMAKE_CXX_STANDARD}_EXTENSION_COMPILE_OPTION}")
endif()
check_cxx_source_compiles("
CHECK_CXX_SOURCE_COMPILES("
#include <memory>
int main () {
@@ -238,36 +144,4 @@ int main () {
HAVE_STD__MAKE_UNIQUE
)
# Detect support for thread_local.
check_cxx_source_compiles("
int main () {
static thread_local int x = 3;
(void)x;
}
"
HAVE_CX11_THREAD_LOCAL
)
check_cxx_source_compiles("
#include <atomic>
#include <cstdint>
std::atomic<uint64_t> x (0);
int main() {
uint64_t i = x.load(std::memory_order_relaxed);
return std::atomic_is_lock_free(&x);
}"
LIBATOMIC_NOT_NEEDED)
IF (NOT LIBATOMIC_NOT_NEEDED)
set(ATOMIC_LIBRARY "atomic")
endif()
IF (APPLE)
# Check if mbrtowc implementation attempts to encode invalid UTF-8 sequences
# Known culprits: at least some versions of macOS (confirmed Snow Leopard and Yosemite)
try_run(mbrtowc_invalid_utf8_exit mbrtowc_invalid_utf8_compiles ${CMAKE_CURRENT_BINARY_DIR}
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/checks/mbrtowc_invalid_utf8.cpp")
IF ("${mbrtowc_invalid_utf8_compiles}" AND ("${mbrtowc_invalid_utf8_exit}" EQUAL 1))
SET(HAVE_BROKEN_MBRTOWC_UTF8 1)
ENDIF()
ENDIF()
FIND_PROGRAM(SED sed)

View File

@@ -1,86 +1,150 @@
find_program(SPHINX_EXECUTABLE NAMES sphinx-build
HINTS
$ENV{SPHINX_DIR}
PATH_SUFFIXES bin
DOC "Sphinx documentation generator")
FIND_PACKAGE(Doxygen 1.8.7)
include(FeatureSummary)
INCLUDE(FeatureSummary)
set(SPHINX_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/doc_src")
set(SPHINX_ROOT_DIR "${CMAKE_CURRENT_BINARY_DIR}/user_doc")
set(SPHINX_BUILD_DIR "${SPHINX_ROOT_DIR}/build")
set(SPHINX_HTML_DIR "${SPHINX_ROOT_DIR}/html")
set(SPHINX_MANPAGE_DIR "${SPHINX_ROOT_DIR}/man")
IF(DOXYGEN_FOUND)
OPTION(BUILD_DOCS "build documentation (requires Doxygen)" ON)
ELSE(DOXYGEN_FOUND)
OPTION(BUILD_DOCS "build documentation (requires Doxygen)" OFF)
ENDIF(DOXYGEN_FOUND)
# sphinx-docs uses fish_indent for highlighting.
# Prepend the output dir of fish_indent to PATH.
add_custom_target(sphinx-docs
mkdir -p ${SPHINX_HTML_DIR}/_static/
COMMAND env PATH="$<TARGET_FILE_DIR:fish_indent>:$$PATH"
${SPHINX_EXECUTABLE}
-j auto
-q -b html
-c "${SPHINX_SRC_DIR}"
-d "${SPHINX_ROOT_DIR}/.doctrees-html"
"${SPHINX_SRC_DIR}"
"${SPHINX_HTML_DIR}"
DEPENDS ${SPHINX_SRC_DIR}/fish_indent_lexer.py fish_indent
COMMENT "Building HTML documentation with Sphinx")
IF(BUILD_DOCS AND NOT DOXYGEN_FOUND)
MESSAGE(FATAL_ERROR "build documentation selected, but Doxygen could not be found")
ENDIF()
# sphinx-manpages needs the fish_indent binary for the version number
add_custom_target(sphinx-manpages
env PATH="$<TARGET_FILE_DIR:fish_indent>:$$PATH"
${SPHINX_EXECUTABLE}
-j auto
-q -b man
-c "${SPHINX_SRC_DIR}"
-d "${SPHINX_ROOT_DIR}/.doctrees-man"
"${SPHINX_SRC_DIR}"
# TODO: This only works if we only have section 1 manpages.
"${SPHINX_MANPAGE_DIR}/man1"
DEPENDS fish_indent
COMMENT "Building man pages with Sphinx")
IF(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/user_doc/html
AND IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/share/man/man1)
SET(HAVE_PREBUILT_DOCS TRUE)
ELSE()
SET(HAVE_PREBUILT_DOCS FALSE)
ENDIF()
if(SPHINX_EXECUTABLE)
option(BUILD_DOCS "build documentation (requires Sphinx)" ON)
else(SPHINX_EXECUTABLE)
option(BUILD_DOCS "build documentation (requires Sphinx)" OFF)
endif(SPHINX_EXECUTABLE)
IF(BUILD_DOCS OR HAVE_PREBUILT_DOCS)
SET(INSTALL_DOCS ON)
ELSE()
SET(INSTALL_DOCS OFF)
ENDIF()
if(BUILD_DOCS AND NOT SPHINX_EXECUTABLE)
message(FATAL_ERROR "build documentation selected, but sphinx-build could not be found")
endif()
ADD_FEATURE_INFO(Documentation INSTALL_DOCS "user manual and documentation")
if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/user_doc/html
AND IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/user_doc/man)
set(HAVE_PREBUILT_DOCS TRUE)
else()
set(HAVE_PREBUILT_DOCS FALSE)
endif()
IF(BUILD_DOCS)
# Files in ./share/completions/
FILE(GLOB COMPLETIONS_DIR_FILES share/completions/*.fish)
if(BUILD_DOCS OR HAVE_PREBUILT_DOCS)
set(INSTALL_DOCS ON)
else()
set(INSTALL_DOCS OFF)
endif()
# Files in ./share/functions/
FILE(GLOB FUNCTIONS_DIR_FILES share/functions/*.fish)
add_feature_info(Documentation INSTALL_DOCS "user manual and documentation")
# Files in doc_src
FILE(GLOB DOC_SRC_FILES doc_src/*)
if(BUILD_DOCS)
configure_file("${SPHINX_SRC_DIR}/conf.py" "${SPHINX_BUILD_DIR}/conf.py" @ONLY)
add_custom_target(doc ALL
DEPENDS sphinx-docs sphinx-manpages)
# .txt files in doc_src
FILE(GLOB HELP_SRC doc_src/*.txt)
# These files are the source files, they contain a few @FOO@-style substitutions.
# Note that this order defines the order that they appear in the documentation.
SET(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)
# These are the generated result files.
STRING(REPLACE ".in" "" HDR_FILES "${HDR_FILES_SRC}")
# Header files except for index.hdr
SET(HDR_FILES_NO_INDEX ${HDR_FILES})
LIST(REMOVE_ITEM HDR_FILES_NO_INDEX doc_src/index.hdr)
# Copy doc_src files
FILE(COPY ${DOC_SRC_FILES} DESTINATION doc_src)
# Build lexicon_filter.
ADD_CUSTOM_COMMAND(OUTPUT lexicon_filter
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build_tools/build_lexicon_filter.sh
${CMAKE_CURRENT_SOURCE_DIR}/share/functions/
${CMAKE_CURRENT_SOURCE_DIR}/share/completions/
${CMAKE_CURRENT_SOURCE_DIR}/lexicon_filter.in
${SED}
> ${CMAKE_CURRENT_BINARY_DIR}/lexicon_filter
&& chmod a+x ${CMAKE_CURRENT_BINARY_DIR}/lexicon_filter
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
DEPENDS ${FUNCTIONS_DIR_FILES} ${COMPLETIONS_DIR_FILES}
doc_src/commands.hdr ${CMAKE_CURRENT_SOURCE_DIR}/lexicon_filter.in
share/functions/__fish_config_interactive.fish
build_tools/build_lexicon_filter.sh command_list_toc.txt)
# Other targets should depend on this target, otherwise the lexicon
# filter can be built twice.
ADD_CUSTOM_TARGET(build_lexicon_filter DEPENDS lexicon_filter)
#
# commands.hdr collects documentation on all commands, functions and
# builtins
#
FILE(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc_src)
ADD_CUSTOM_COMMAND(OUTPUT doc_src/commands.hdr command_list_toc.txt
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build_tools/build_commands_hdr.sh ${HELP_SRC}
< doc_src/commands.hdr.in
> ${CMAKE_CURRENT_BINARY_DIR}/doc_src/commands.hdr
DEPENDS ${HELP_SRC}
${CMAKE_CURRENT_SOURCE_DIR}/doc_src/commands.hdr.in
${CMAKE_CURRENT_SOURCE_DIR}/build_tools/build_commands_hdr.sh)
# doc.h is a compilation of the various snippets of text used both for
# the user documentation and for internal help functions into a single
# file that can be parsed by Doxygen to generate the user
# documentation.
ADD_CUSTOM_COMMAND(OUTPUT doc.h
COMMAND cat ${HDR_FILES} > ${CMAKE_CURRENT_BINARY_DIR}/doc.h
DEPENDS ${HDR_FILES})
# toc.txt: $(HDR_FILES:index.hdr=index.hdr.in) build_tools/build_toc_txt.sh | show-SED
# FISH_BUILD_VERSION=${FISH_BUILD_VERSION} build_tools/build_toc_txt.sh \
# $(HDR_FILES:index.hdr=index.hdr.in) > toc.txt
# Note we would like to add doc_src/index.hdr.in as a dependency but CMake replaces this with
# doc_src/index.hdr; CMake bug?
ADD_CUSTOM_COMMAND(OUTPUT toc.txt
COMMAND env `cat ${FBVF} | tr -d '\"'` ${CMAKE_CURRENT_SOURCE_DIR}/build_tools/build_toc_txt.sh
doc_src/index.hdr.in ${HDR_FILES_NO_INDEX}
> ${CMAKE_CURRENT_BINARY_DIR}/toc.txt
DEPENDS ${CFBVF} ${HDR_FILES_NO_INDEX})
# doc_src/index.hdr: toc.txt doc_src/index.hdr.in | show-AWK
# @echo " AWK CAT $(em)$@$(sgr0)"
# $v cat $@.in | $(AWK) '{if ($$0 ~ /@toc@/){ system("cat toc.txt");} else{ print $$0;}}' >$@
ADD_CUSTOM_COMMAND(OUTPUT doc_src/index.hdr
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build_tools/build_index_hdr.sh toc.txt
< doc_src/index.hdr.in
> ${CMAKE_CURRENT_BINARY_DIR}/doc_src/index.hdr
DEPENDS toc.txt)
# doc: $(HDR_FILES_SRC) Doxyfile.user $(HTML_SRC) $(HELP_SRC) doc.h $(HDR_FILES) lexicon_filter
# @echo " doxygen $(em)user_doc$(sgr0)"
# $v (cat Doxyfile.user; echo INPUT_FILTER=./lexicon_filter; echo PROJECT_NUMBER=$(FISH_BUILD_VERSION) | $(SED) "s/-.*//") | doxygen - && touch user_doc
# $v rm -f $(wildcard $(addprefix ./user_doc/html/,arrow*.png bc_s.png bdwn.png closed.png doc.png folder*.png ftv2*.png nav*.png open.png splitbar.png sync_*.png tab*.* doxygen.* dynsections.js jquery.js pages.html))
ADD_CUSTOM_TARGET(doc ALL
COMMAND env `cat ${FBVF}`
${CMAKE_CURRENT_SOURCE_DIR}/build_tools/build_user_doc.sh
${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.user ./lexicon_filter
DEPENDS ${CFBVF} Doxyfile.user ${DOC_SRC_FILES} doc.h ${HDR_FILES} build_lexicon_filter command_list_toc.txt)
ADD_CUSTOM_COMMAND(OUTPUT share/man/
COMMAND env `cat ${FBVF} | tr -d '\"' `
INPUT_FILTER=lexicon_filter ${CMAKE_CURRENT_SOURCE_DIR}/build_tools/build_documentation.sh ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.help doc_src ./share
DEPENDS ${CFBVF} ${HELP_SRC} build_lexicon_filter)
ADD_CUSTOM_TARGET(BUILD_MANUALS ALL DEPENDS share/man/)
# Group docs targets into a DocsTargets folder
set_property(TARGET doc sphinx-docs sphinx-manpages
SET_PROPERTY(TARGET doc BUILD_MANUALS build_lexicon_filter
PROPERTY FOLDER cmake/DocTargets)
elseif(HAVE_PREBUILT_DOCS)
if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
ELSEIF(HAVE_PREBUILT_DOCS)
IF(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
# Out of tree build - link the prebuilt documentation to the build tree
add_custom_target(link_doc ALL)
add_custom_command(TARGET link_doc
ADD_CUSTOM_TARGET(link_doc ALL)
ADD_CUSTOM_COMMAND(TARGET link_doc
COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_CURRENT_SOURCE_DIR}/share/man ${CMAKE_CURRENT_BINARY_DIR}/share/man
POST_BUILD)
ADD_CUSTOM_COMMAND(TARGET link_doc
COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_CURRENT_SOURCE_DIR}/user_doc ${CMAKE_CURRENT_BINARY_DIR}/user_doc
POST_BUILD)
endif()
endif(BUILD_DOCS)
ENDIF()
ENDIF(BUILD_DOCS)

View File

@@ -5,143 +5,173 @@
# -DBINDIR=L"${CMAKE_INSTALL_FULL_BINDIR}"
# -DDOCDIR=L"${CMAKE_INSTALL_FULL_DOCDIR}")
set(CMAKE_INSTALL_MESSAGE NEVER)
SET(CMAKE_INSTALL_MESSAGE NEVER)
set(PROGRAMS fish fish_indent fish_key_reader)
SET(PROGRAMS fish fish_indent fish_key_reader)
set(prefix ${CMAKE_INSTALL_PREFIX})
set(bindir ${CMAKE_INSTALL_BINDIR})
set(sysconfdir ${CMAKE_INSTALL_SYSCONFDIR})
set(mandir ${CMAKE_INSTALL_MANDIR})
SET(prefix ${CMAKE_INSTALL_PREFIX})
SET(bindir ${CMAKE_INSTALL_BINDIR})
SET(sysconfdir ${CMAKE_INSTALL_SYSCONFDIR})
SET(mandir ${CMAKE_INSTALL_MANDIR})
set(datadir ${CMAKE_INSTALL_FULL_DATADIR})
file(RELATIVE_PATH rel_datadir ${CMAKE_INSTALL_PREFIX} ${datadir})
SET(rel_datadir ${CMAKE_INSTALL_DATADIR})
SET(datadir ${CMAKE_INSTALL_FULL_DATADIR})
set(docdir ${CMAKE_INSTALL_DOCDIR})
SET(docdir ${CMAKE_INSTALL_DOCDIR})
# Comment at the top of some .in files
set(configure_input
SET(configure_input
"This file was generated from a corresponding .in file.\
DO NOT MANUALLY EDIT THIS FILE!")
set(rel_completionsdir "fish/vendor_completions.d")
set(rel_functionsdir "fish/vendor_functions.d")
set(rel_confdir "fish/vendor_conf.d")
set(extra_completionsdir
"${datadir}/${rel_completionsdir}"
SET(extra_completionsdir
${datadir}/fish/vendor_completions.d
CACHE STRING "Path for extra completions")
set(extra_functionsdir
"${datadir}/${rel_functionsdir}"
CACHE STRING "Path for extra functions")
SET(extra_functionsdir
${datadir}/fish/vendor_functions.d
CACHE STRING "Path for extra completions")
set(extra_confdir
"${datadir}/${rel_confdir}"
SET(extra_confdir
${datadir}/fish/vendor_conf.d
CACHE STRING "Path for extra configuration")
# These are the man pages that go in system manpath; all manpages go in the fish-specific manpath.
set(MANUALS ${CMAKE_CURRENT_BINARY_DIR}/user_doc/man/man1/fish.1
${CMAKE_CURRENT_BINARY_DIR}/user_doc/man/man1/fish_indent.1
${CMAKE_CURRENT_BINARY_DIR}/user_doc/man/man1/fish_key_reader.1)
SET(MANUALS ${CMAKE_CURRENT_BINARY_DIR}/share/man/man1/fish.1
${CMAKE_CURRENT_BINARY_DIR}/share/man/man1/fish_indent.1
${CMAKE_CURRENT_BINARY_DIR}/share/man/man1/fish_key_reader.1)
# Determine which man page we don't want to install.
# On OS X, don't install a man page for open, since we defeat fish's open
# function on OS X.
# On other operating systems, don't install a realpath man page, as they almost all have a realpath
# command, while macOS does not.
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(CONDEMNED_PAGE "open.1")
else()
set(CONDEMNED_PAGE "realpath.1")
endif()
IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
SET(CONDEMNED_PAGE "open.1")
ELSE()
SET(CONDEMNED_PAGE "none")
ENDIF()
# Define a function to help us create directories.
function(FISH_CREATE_DIRS)
foreach(dir ${ARGV})
install(DIRECTORY DESTINATION ${dir})
endforeach(dir)
endfunction(FISH_CREATE_DIRS)
FUNCTION(FISH_CREATE_DIRS)
FOREACH(dir ${ARGV})
IF(NOT EXISTS ${CMAKE_INSTALL_PREFIX}/${dir})
INSTALL(DIRECTORY DESTINATION ${dir})
ENDIF()
ENDFOREACH(dir)
ENDFUNCTION(FISH_CREATE_DIRS)
function(FISH_TRY_CREATE_DIRS)
foreach(dir ${ARGV})
if(NOT IS_ABSOLUTE ${dir})
set(abs_dir "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${dir}")
else()
set(abs_dir "\$ENV{DESTDIR}${dir}")
endif()
install(SCRIPT CODE "EXECUTE_PROCESS(COMMAND mkdir -p ${abs_dir} OUTPUT_QUIET ERROR_QUIET)
execute_process(COMMAND chmod 755 ${abs_dir} OUTPUT_QUIET ERROR_QUIET)
FUNCTION(FISH_TRY_CREATE_DIRS)
FOREACH(dir ${ARGV})
IF(NOT IS_ABSOLUTE ${dir})
SET(abs_dir "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${dir}")
ELSE()
SET(abs_dir "\$ENV{DESTDIR}${dir}")
ENDIF()
INSTALL(SCRIPT CODE "EXECUTE_PROCESS(COMMAND mkdir -p ${abs_dir} OUTPUT_QUIET ERROR_QUIET)
EXECUTE_PROCESS(COMMAND chmod 755 ${abs_dir} OUTPUT_QUIET ERROR_QUIET)
")
endforeach()
endfunction(FISH_TRY_CREATE_DIRS)
ENDFOREACH()
ENDFUNCTION(FISH_TRY_CREATE_DIRS)
install(TARGETS ${PROGRAMS}
# $v $(INSTALL) -m 755 -d $(DESTDIR)$(bindir)
# $v for i in $(PROGRAMS); do\
# $(INSTALL) -m 755 $$i $(DESTDIR)$(bindir);\
# echo " Installing $(bo)$$i$(sgr0)";\
# true ;\
# done;
INSTALL(TARGETS ${PROGRAMS}
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ
GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
DESTINATION ${bindir})
fish_create_dirs(${sysconfdir}/fish/conf.d ${sysconfdir}/fish/completions
# $v $(INSTALL) -m 755 -d $(DESTDIR)$(sysconfdir)/fish
# $v $(INSTALL) -m 755 -d $(DESTDIR)$(sysconfdir)/fish/conf.d
# $v $(INSTALL) -m 755 -d $(DESTDIR)$(sysconfdir)/fish/completions
# $v $(INSTALL) -m 755 -d $(DESTDIR)$(sysconfdir)/fish/functions
# $v $(INSTALL) -m 644 etc/config.fish $(DESTDIR)$(sysconfdir)/fish/
FISH_CREATE_DIRS(${sysconfdir}/fish/conf.d ${sysconfdir}/fish/completions
${sysconfdir}/fish/functions)
install(FILES etc/config.fish DESTINATION ${sysconfdir}/fish/)
INSTALL(FILES etc/config.fish DESTINATION ${sysconfdir}/fish/)
fish_create_dirs(${rel_datadir}/fish ${rel_datadir}/fish/completions
FISH_CREATE_DIRS(${rel_datadir}/fish ${rel_datadir}/fish/completions
${rel_datadir}/fish/functions ${rel_datadir}/fish/groff
${rel_datadir}/fish/man/man1 ${rel_datadir}/fish/tools
${rel_datadir}/fish/tools/web_config
${rel_datadir}/fish/tools/web_config/js
${rel_datadir}/fish/tools/web_config/partials
${rel_datadir}/fish/tools/web_config/sample_prompts
${rel_datadir}/fish/tools/web_config/themes
)
${rel_datadir}/fish/tools/web_config/sample_prompts)
configure_file(share/__fish_build_paths.fish.in share/__fish_build_paths.fish)
install(FILES share/config.fish
# $v $(INSTALL) -m 644 share/config.fish $(DESTDIR)$(datadir)/fish/
# $v $(INSTALL) -m 644 share/__fish_build_paths.fish $(DESTDIR)$(datadir)/fish/
CONFIGURE_FILE(share/__fish_build_paths.fish.in share/__fish_build_paths.fish)
INSTALL(FILES share/config.fish
${CMAKE_CURRENT_BINARY_DIR}/share/__fish_build_paths.fish
DESTINATION ${rel_datadir}/fish)
# Create only the vendor directories inside the prefix (#5029 / #6508)
fish_create_dirs(${rel_datadir}/fish/vendor_completions.d ${rel_datadir}/fish/vendor_functions.d
${rel_datadir}/fish/vendor_conf.d)
# $v $(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/pkgconfig
# @echo "Creating placeholder vendor/'extra_' directories"
# -$v $(INSTALL) -m 755 -d $(DESTDIR)$(extra_completionsdir)
# -$v $(INSTALL) -m 755 -d $(DESTDIR)$(extra_functionsdir)
# -$v $(INSTALL) -m 755 -d $(DESTDIR)$(extra_confdir)
FISH_CREATE_DIRS(${rel_datadir}/pkgconfig)
# Don't try too hard to create these directories as they may be outside our writeable area
# https://github.com/Homebrew/homebrew-core/pull/2813
FISH_TRY_CREATE_DIRS(${extra_completionsdir} ${extra_functionsdir} ${extra_confdir})
fish_try_create_dirs(${rel_datadir}/pkgconfig)
configure_file(fish.pc.in fish.pc.noversion @ONLY)
# @echo "Installing pkgconfig file"
# $v $(INSTALL) -m 644 fish.pc $(DESTDIR)$(datadir)/pkgconfig
CONFIGURE_FILE(fish.pc.in fish.pc.noversion)
add_custom_command(OUTPUT fish.pc
ADD_CUSTOM_COMMAND(OUTPUT fish.pc
COMMAND sed '/Version/d' fish.pc.noversion > fish.pc
COMMAND printf "Version: " >> fish.pc
COMMAND sed 's/FISH_BUILD_VERSION=//\;s/\"//g' ${FBVF} >> fish.pc
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
DEPENDS CHECK-FISH-BUILD-VERSION-FILE ${CMAKE_CURRENT_BINARY_DIR}/fish.pc.noversion)
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${FBVF} ${CMAKE_CURRENT_BINARY_DIR}/fish.pc.noversion)
add_custom_target(build_fish_pc ALL DEPENDS fish.pc)
ADD_CUSTOM_TARGET(build_fish_pc ALL DEPENDS fish.pc)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/fish.pc
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/fish.pc
DESTINATION ${rel_datadir}/pkgconfig)
install(DIRECTORY share/completions/
# @echo "Installing the $(bo)fish completion library$(sgr0)...";
# $v $(INSTALL) -m 644 $(COMPLETIONS_DIR_FILES:%='%') $(DESTDIR)$(datadir)/fish/completions/
INSTALL(DIRECTORY share/completions/
DESTINATION ${rel_datadir}/fish/completions
FILES_MATCHING PATTERN "*.fish")
install(DIRECTORY share/functions/
# @echo "Installing $(bo)fish functions$(sgr0)";
# $v $(INSTALL) -m 644 $(FUNCTIONS_DIR_FILES:%='%') $(DESTDIR)$(datadir)/fish/functions/
INSTALL(DIRECTORY share/functions/
DESTINATION ${rel_datadir}/fish/functions
FILES_MATCHING PATTERN "*.fish")
install(DIRECTORY share/groff
# @echo "Installing $(bo)man pages$(sgr0)";
# $v $(INSTALL) -m 644 share/groff/* $(DESTDIR)$(datadir)/fish/groff/
INSTALL(DIRECTORY share/groff
DESTINATION ${rel_datadir}/fish)
# $v test -z "$(wildcard share/man/man1/*.1)" || $(INSTALL) -m 644 $(filter-out $(addprefix share/man/man1/, $(CONDEMNED_PAGES)), $(wildcard share/man/man1/*.1)) $(DESTDIR)$(datadir)/fish/man/man1/
# CONDEMNED_PAGE is managed by the conditional above
# Building the man pages is optional: if sphinx isn't installed, they're not built
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/user_doc/man/man1/
# Building the man pages is optional: if doxygen isn't installed, they're not built
INSTALL(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/share/man/man1/
DESTINATION ${rel_datadir}/fish/man/man1
FILES_MATCHING
PATTERN "*.1"
PATTERN ${CONDEMNED_PAGE} EXCLUDE)
install(PROGRAMS share/tools/create_manpage_completions.py share/tools/deroff.py
# @echo "Installing helper tools";
# $v $(INSTALL) -m 755 share/tools/*.py $(DESTDIR)$(datadir)/fish/tools/
INSTALL(PROGRAMS share/tools/create_manpage_completions.py share/tools/deroff.py
DESTINATION ${rel_datadir}/fish/tools/)
install(DIRECTORY share/tools/web_config
# $v $(INSTALL) -m 644 share/tools/web_config/*.* $(DESTDIR)$(datadir)/fish/tools/web_config/
# $v $(INSTALL) -m 644 share/tools/web_config/js/*.* $(DESTDIR)$(datadir)/fish/tools/web_config/js/
# $v $(INSTALL) -m 644 share/tools/web_config/partials/* $(DESTDIR)$(datadir)/fish/tools/web_config/partials/
# $v $(INSTALL) -m 644 share/tools/web_config/sample_prompts/*.fish $(DESTDIR)$(datadir)/fish/tools/web_config/sample_prompts/
# $v $(INSTALL) -m 755 share/tools/web_config/*.py $(DESTDIR)$(datadir)/fish/tools/web_config/
INSTALL(DIRECTORY share/tools/web_config
DESTINATION ${rel_datadir}/fish/tools/
FILES_MATCHING
PATTERN "*.png"
@@ -149,39 +179,51 @@ install(DIRECTORY share/tools/web_config
PATTERN "*.html"
PATTERN "*.py"
PATTERN "*.js"
PATTERN "*.theme"
PATTERN "*.fish")
# Building the man pages is optional: if Sphinx isn't installed, they're not built
install(FILES ${MANUALS} DESTINATION ${mandir}/man1/ OPTIONAL)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/user_doc/html/ # Trailing slash is important!
DESTINATION ${docdir} OPTIONAL)
install(FILES CHANGELOG.rst DESTINATION ${docdir})
# @echo "Installing more man pages";
# $v $(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man1;
# $v for i in $(MANUALS); do \
# $(INSTALL) -m 644 $$i $(DESTDIR)$(mandir)/man1/; \
# true; \
# done;
# Building the man pages is optional: if doxygen isn't installed, they're not built
INSTALL(FILES ${MANUALS} DESTINATION ${mandir}/man1/ OPTIONAL)
install(FILES share/lynx.lss DESTINATION ${rel_datadir}/fish/)
#install-doc: $(user_doc)
# @echo "Installing online user documentation";
# $v $(INSTALL) -m 755 -d $(DESTDIR)$(docdir)
# $v for i in user_doc/html/* CHANGELOG.md; do \
# if test -f $$i; then \
# $(INSTALL) -m 644 $$i $(DESTDIR)$(docdir); \
# fi; \
# done;
# Building the manual is optional
INSTALL(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/user_doc/html/ # Trailing slash is important!
DESTINATION ${docdir} OPTIONAL)
INSTALL(FILES CHANGELOG.md DESTINATION ${docdir})
# $v $(INSTALL) -m 644 share/lynx.lss $(DESTDIR)$(datadir)/fish/
INSTALL(FILES share/lynx.lss DESTINATION ${rel_datadir}/fish/)
# These files are built by cmake/gettext.cmake, but using GETTEXT_PROCESS_PO_FILES's
# INSTALL_DESTINATION leads to them being installed as ${lang}.gmo, not fish.mo
# The ${languages} array comes from cmake/gettext.cmake
if(GETTEXT_FOUND)
foreach(lang ${languages})
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${lang}.gmo DESTINATION
IF(GETTEXT_FOUND)
FOREACH(lang ${languages})
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${lang}.gmo DESTINATION
${CMAKE_INSTALL_LOCALEDIR}/${lang}/LC_MESSAGES/ RENAME fish.mo)
endforeach()
endif()
if (NOT APPLE)
install(FILES fish.desktop DESTINATION ${rel_datadir}/applications)
install(FILES ${SPHINX_SRC_DIR}/python_docs_theme/static/fish.png DESTINATION ${rel_datadir}/pixmaps)
endif()
ENDFOREACH()
ENDIF()
# Group install targets into a InstallTargets folder
set_property(TARGET build_fish_pc CHECK-FISH-BUILD-VERSION-FILE
tests_buildroot_target
SET_PROPERTY(TARGET build_fish_pc CHECK-FISH-BUILD-VERSION-FILE
test_invocation test_fishscript
test_prep tests_buildroot_target
PROPERTY FOLDER cmake/InstallTargets)
# Make a target build_root that installs into the buildroot directory, for testing.
set(BUILDROOT_DIR ${CMAKE_CURRENT_BINARY_DIR}/buildroot)
add_custom_target(build_root
SET(BUILDROOT_DIR ${CMAKE_CURRENT_BINARY_DIR}/buildroot)
ADD_CUSTOM_TARGET(build_root
COMMAND DESTDIR=${BUILDROOT_DIR} ${CMAKE_COMMAND}
--build ${CMAKE_CURRENT_BINARY_DIR} --target install)

View File

@@ -1,44 +0,0 @@
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.10" CACHE STRING "Minimum OS X deployment version")
# Code signing ID on Mac.
# If this is falsey, codesigning is disabled.
# '-' is ad-hoc codesign.
set(MAC_CODESIGN_ID "" CACHE STRING "Mac code-signing identity")
# Whether to inject the "get-task-allow" entitlement, which permits debugging
# on the Mac.
set(MAC_INJECT_GET_TASK_ALLOW ON CACHE BOOL "Inject get-task-allow on Mac")
# When building a Mac build, it is common for fish to link against a
# pcre2 built for the host platform (e.g. macOS 10.15) while fish wants
# to link for macOS 10.9. This warning would be of interest for releases,
# but is just noise for daily development. Unfortunately it has no flag
# of its own, so suppress all linker warnings in debug builds.
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -w")
function(CODESIGN_ON_MAC target)
if((APPLE) AND (MAC_CODESIGN_ID))
execute_process(COMMAND sw_vers "-productVersion" OUTPUT_VARIABLE OSX_VERSION)
if(MAC_INJECT_GET_TASK_ALLOW)
set(ENTITLEMENTS "--entitlements" "${CMAKE_SOURCE_DIR}/osx/fish_debug.entitlements")
else()
set(ENTITLEMENTS "")
endif(MAC_INJECT_GET_TASK_ALLOW)
if(OSX_VERSION VERSION_LESS "10.13.6")
# `-options runtime` is only available in OS X from 10.13.6 and up
add_custom_command(
TARGET ${target}
POST_BUILD
COMMAND codesign --force --deep ${ENTITLEMENTS} --sign "${MAC_CODESIGN_ID}" $<TARGET_FILE:${target}>
VERBATIM
)
else()
add_custom_command(
TARGET ${target}
POST_BUILD
COMMAND codesign --force --deep --options runtime ${ENTITLEMENTS} --sign "${MAC_CODESIGN_ID}" $<TARGET_FILE:${target}>
VERBATIM
)
endif()
endif()
endfunction(CODESIGN_ON_MAC target)

View File

@@ -1,78 +0,0 @@
# This is Mac-only.
if (NOT APPLE)
return()
endif (NOT APPLE)
# The source tree containing certain macOS resources.
set(OSX_DIR ${CMAKE_CURRENT_SOURCE_DIR}/osx)
set(RESOURCE_FILES
${OSX_DIR}/launch_fish.scpt
${OSX_DIR}/fish_term_icon.icns
${CMAKE_CURRENT_SOURCE_DIR}/build_tools/osx_package_scripts/add-shell
${OSX_DIR}/install.sh
)
# Resource files must be present in the source list.
add_executable(fish_macapp EXCLUDE_FROM_ALL
${OSX_DIR}/osx_fish_launcher.m
${RESOURCE_FILES}
)
# Compute the version. Note this is done at generation time, not build time,
# so cmake must be re-run after version changes for the app to be updated. But
# generally this will be run by make_pkg.sh which always re-runs cmake.
execute_process(
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build_tools/git_version_gen.sh --stdout
COMMAND cut -d- -f1
OUTPUT_VARIABLE FISH_SHORT_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE)
# Note CMake appends .app, so the real output name will be fish.app.
# This target does not include the 'base' resource.
set_target_properties(fish_macapp PROPERTIES OUTPUT_NAME "fish")
find_library(FOUNDATION_LIB Foundation)
target_link_libraries(fish_macapp ${FOUNDATION_LIB})
set_target_properties(fish_macapp PROPERTIES
MACOSX_BUNDLE TRUE
MACOSX_BUNDLE_INFO_PLIST ${OSX_DIR}/CMakeMacAppInfo.plist.in
MACOSX_BUNDLE_GUI_IDENTIFIER "com.ridiculousfish.fish-shell"
MACOSX_BUNDLE_SHORT_VERSION_STRING ${FISH_SHORT_VERSION}
RESOURCE "${RESOURCE_FILES}"
)
# The fish Mac app contains a fish installation inside the package.
# Here is where it gets built.
# Copy into the fish mac app after.
set(MACAPP_FISH_BUILDROOT ${CMAKE_CURRENT_BINARY_DIR}/macapp_buildroot/base)
add_custom_command(TARGET fish_macapp POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory ${MACAPP_FISH_BUILDROOT}
COMMAND DESTDIR=${MACAPP_FISH_BUILDROOT} ${CMAKE_COMMAND}
--build ${CMAKE_CURRENT_BINARY_DIR} --target install
COMMAND ${CMAKE_COMMAND} -E copy_directory ${MACAPP_FISH_BUILDROOT}/..
$<TARGET_BUNDLE_CONTENT_DIR:fish_macapp>/Resources/
VERBATIM
)
# The entitlements file.
set(MACAPP_ENTITLEMENTS "${CMAKE_SOURCE_DIR}/osx/MacApp.entitlements")
# Target to sign the macapp.
# Note that a POST_BUILD step happens before resources are copied,
# and therefore would be too early.
add_custom_target(signed_fish_macapp
DEPENDS fish_macapp "${MACAPP_ENTITLEMENTS}"
COMMAND codesign --force --deep
--options runtime
--entitlements "${MACAPP_ENTITLEMENTS}"
--sign "${MAC_CODESIGN_ID}"
$<TARGET_BUNDLE_DIR:fish_macapp>
VERBATIM
)
# Group our targets in a folder.
set_property(TARGET fish_macapp signed_fish_macapp PROPERTY FOLDER macapp)

View File

@@ -1,49 +1,20 @@
# PCRE2 needs some settings.
set(PCRE2_WIDTH ${WCHAR_T_BITS})
set(PCRE2_BUILD_PCRE2_8 OFF CACHE BOOL "Build 8bit PCRE2 library")
set(PCRE2_BUILD_PCRE2_${PCRE2_WIDTH} ON CACHE BOOL "Build ${PCRE2_WIDTH}bit PCRE2 library")
set(PCRE2_SHOW_REPORT OFF CACHE BOOL "Show the final configuration report")
set(PCRE2_BUILD_TESTS OFF CACHE BOOL "Build tests")
set(PCRE2_BUILD_PCRE2GREP OFF CACHE BOOL "Build pcre2grep")
SET(PCRE2_WIDTH ${WCHAR_T_BITS})
SET(PCRE2_BUILD_PCRE2_8 OFF CACHE BOOL "Build 8bit PCRE2 library")
SET(PCRE2_BUILD_PCRE2_${PCRE2_WIDTH} ON CACHE BOOL "Build ${PCRE2_WIDTH}bit PCRE2 library")
SET(PCRE2_SHOW_REPORT OFF CACHE BOOL "Show the final configuration report")
SET(PCRE2_BUILD_PCRE2GREP OFF CACHE BOOL "Build pcre2grep")
set(PCRE2_MIN_VERSION 10.21)
# Look for a system-installed PCRE2.
find_library(SYS_PCRE2_LIB pcre2-${PCRE2_WIDTH})
find_path(SYS_PCRE2_INCLUDE_DIR pcre2.h)
# We can either use the system-installed PCRE or our bundled version.
# This is controlled by the cache variable FISH_USE_SYSTEM_PCRE2.
# Here we compute the default value for that variable.
if ((APPLE) AND (MAC_CODESIGN_ID))
# On Mac, a codesigned fish will refuse to load a non-codesigned PCRE2
# (e.g. from Homebrew) so default to bundled PCRE2.
set(USE_SYS_PCRE2_DEFAULT OFF)
elseif((NOT SYS_PCRE2_LIB) OR (NOT SYS_PCRE2_INCLUDE_DIR))
# We did not find system PCRE2, so default to bundled.
set(USE_SYS_PCRE2_DEFAULT OFF)
else()
# Default to using the system PCRE2, which was found.
set(USE_SYS_PCRE2_DEFAULT ON)
endif()
set(FISH_USE_SYSTEM_PCRE2 ${USE_SYS_PCRE2_DEFAULT} CACHE BOOL
"Use PCRE2 from the system, instead of bundled with fish")
if(FISH_USE_SYSTEM_PCRE2)
set(PCRE2_LIB "${SYS_PCRE2_LIB}")
set(PCRE2_INCLUDE_DIR "${SYS_PCRE2_INCLUDE_DIR}")
message(STATUS "Using system PCRE2 library ${PCRE2_INCLUDE_DIR}")
else()
message(STATUS "Using bundled PCRE2 library")
add_subdirectory(pcre2 EXCLUDE_FROM_ALL)
set(PCRE2_INCLUDE_DIR ${CMAKE_BINARY_DIR}/pcre2)
set(PCRE2_LIB pcre2-${PCRE2_WIDTH})
# Disable -Wunused-macros inside PCRE2, as it is noisy.
get_target_property(PCRE2_COMPILE_OPTIONS ${PCRE2_LIB} COMPILE_OPTIONS)
list(REMOVE_ITEM PCRE2_COMPILE_OPTIONS "-Wunused-macros")
set_property(TARGET ${PCRE2_LIB} PROPERTY COMPILE_OPTIONS ${PCRE2_COMPILE_OPTIONS})
endif(FISH_USE_SYSTEM_PCRE2)
include_directories(${PCRE2_INCLUDE_DIR})
SET(PCRE2_MIN_VERSION 10.21)
FIND_LIBRARY(PCRE2_LIB pcre2-${PCRE2_WIDTH})
FIND_PATH(PCRE2_INCLUDE_DIR pcre2.h)
IF (PCRE2_LIB AND PCRE2_INCLUDE_DIR)
MESSAGE(STATUS "Found system PCRE2 library ${PCRE2_INCLUDE_DIR}")
ELSE()
MESSAGE(STATUS "Using bundled PCRE2 library")
ADD_SUBDIRECTORY(pcre2-10.22 EXCLUDE_FROM_ALL)
SET(PCRE2_INCLUDE_DIR ${CMAKE_BINARY_DIR}/pcre2-10.22/)
SET(PCRE2_LIB pcre2-${PCRE2_WIDTH})
endif(PCRE2_LIB AND PCRE2_INCLUDE_DIR)
INCLUDE_DIRECTORIES(${PCRE2_INCLUDE_DIR})

View File

@@ -1,175 +1,131 @@
# This adds ctest support to the project
enable_testing()
# By default, ctest runs tests serially
if(NOT CTEST_PARALLEL_LEVEL)
include(ProcessorCount)
ProcessorCount(CORES)
set(CTEST_PARALLEL_LEVEL ${CORES})
endif()
# Put in a tests folder to reduce the top level targets in IDEs.
set(CMAKE_FOLDER tests)
# We will use 125 as a reserved exit code to indicate that a test has been skipped, i.e. it did not
# pass but it should not be considered a failed test run, either.
set(SKIP_RETURN_CODE 125)
# Even though we are using CMake's ctest for testing, we still define our own `make test` target
# rather than use its default for many reasons:
# * CMake doesn't run tests in-proc or even add each tests as an individual node in the ninja
# dependency tree, instead it just bundles all tests into a target called `test` that always just
# shells out to `ctest`, so there are no build-related benefits to not doing that ourselves.
# * CMake devs insist that it is appropriate for `make test` to never depend on `make all`, i.e.
# running `make test` does not require any of the binaries to be built before testing.
# * The only way to have a test depend on a binary is to add a fake test with a name like
# "build_fish" that executes CMake recursively to build the `fish` target.
# * It is not possible to set top-level CTest options/settings such as CTEST_PARALLEL_LEVEL from
# within the CMake configuration file.
# * Circling back to the point about individual tests not being actual Makefile targets, CMake does
# not offer any way to execute a named test via the `make`/`ninja`/whatever interface; the only
# way to manually invoke test `foo` is to to manually run `ctest` and specify a regex matching
# `foo` as an argument, e.g. `ctest -R ^foo$`... which is really crazy.
# The top-level test target is "fish_run_tests".
add_custom_target(fish_run_tests
COMMAND env CTEST_PARALLEL_LEVEL=${CTEST_PARALLEL_LEVEL} FISH_FORCE_COLOR=1
FISH_SOURCE_DIR=${CMAKE_SOURCE_DIR}
${CMAKE_CTEST_COMMAND} --force-new-ctest-process # --verbose
--output-on-failure --progress
DEPENDS fish_tests tests_buildroot_target
USES_TERMINAL
)
# If CMP0037 is available, also make an alias "test" target.
# Note that this policy may not be available, in which case definining such a target silently fails.
cmake_policy(PUSH)
if(POLICY CMP0037)
cmake_policy(SET CMP0037 OLD)
add_custom_target(test DEPENDS fish_run_tests)
endif()
cmake_policy(POP)
# Build the low-level tests code
add_executable(fish_tests EXCLUDE_FROM_ALL
# Define fish_tests.
ADD_EXECUTABLE(fish_tests EXCLUDE_FROM_ALL
src/fish_tests.cpp)
fish_link_deps_and_sign(fish_tests)
FISH_LINK_DEPS(fish_tests)
# The "test" directory.
set(TEST_DIR ${CMAKE_CURRENT_BINARY_DIR}/test)
# CMake doesn't really support dynamic test discovery where a test harness is executed to list the
# tests it contains, making fish_tests.cpp's tests opaque to CMake (whereas littlecheck tests can be
# enumerated from the filesystem). We used to compile fish_tests.cpp without linking against
# anything (-Wl,-undefined,dynamic_lookup,--unresolved-symbols=ignore-all) to get it to print its
# tests at configuration time, but that's a little too much dark CMake magic.
#
# We now identify tests by checking against a magic regex that's #define'd as a no-op C-side.
file(READ "${CMAKE_SOURCE_DIR}/src/fish_tests.cpp" FISH_TESTS_CPP)
string(REGEX MATCHALL "TEST_GROUP\\( *\"([^\"]+)\"" "LOW_LEVEL_TESTS" "${FISH_TESTS_CPP}")
string(REGEX REPLACE "TEST_GROUP\\( *\"([^\"]+)\"" "\\1" "LOW_LEVEL_TESTS" "${LOW_LEVEL_TESTS}")
list(REMOVE_DUPLICATES LOW_LEVEL_TESTS)
SET(TEST_DIR ${CMAKE_CURRENT_BINARY_DIR}/test)
# The directory into which fish is installed.
set(TEST_INSTALL_DIR ${TEST_DIR}/buildroot)
SET(TEST_INSTALL_DIR ${TEST_DIR}/buildroot)
# The directory where the tests expect to find the fish root (./bin, etc)
set(TEST_ROOT_DIR ${TEST_DIR}/root)
SET(TEST_ROOT_DIR ${TEST_DIR}/root)
# Copy needed directories for out-of-tree builds
if(NOT FISH_IN_TREE_BUILD)
add_custom_target(funcs_dir)
add_custom_command(TARGET funcs_dir
COMMAND mkdir -p ${CMAKE_BINARY_DIR}/share
# Don't run ln twice or it will create a new link in the link.
COMMAND test -e ${CMAKE_BINARY_DIR}/share/functions || ln -sf
${CMAKE_SOURCE_DIR}/share/functions/ ${CMAKE_BINARY_DIR}/share/functions
COMMENT "Symlinking fish functions to binary dir"
VERBATIM)
# Copy tests files.
FILE(GLOB TESTS_FILES tests/*)
ADD_CUSTOM_TARGET(tests_dir DEPENDS tests)
add_custom_target(tests_dir DEPENDS tests)
add_custom_command(TARGET tests_dir
IF(NOT FISH_IN_TREE_BUILD)
ADD_CUSTOM_COMMAND(TARGET tests_dir
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_SOURCE_DIR}/tests/ ${CMAKE_BINARY_DIR}/tests/
COMMENT "Copying test files to binary dir"
VERBATIM)
add_dependencies(fish_tests tests_dir funcs_dir)
endif()
ADD_DEPENDENCIES(fish_tests tests_dir)
ENDIF()
# Copy littlecheck.py
configure_file(build_tools/littlecheck.py littlecheck.py COPYONLY)
# Create the 'test' target.
# Set a policy so CMake stops complaining about the name 'test'.
CMAKE_POLICY(PUSH)
IF(POLICY CMP0037)
CMAKE_POLICY(SET CMP0037 OLD)
ENDIF()
ADD_CUSTOM_TARGET(test)
CMAKE_POLICY(POP)
# Copy pexpect_helper.py
configure_file(build_tools/pexpect_helper.py pexpect_helper.py COPYONLY)
ADD_CUSTOM_TARGET(test_low_level
COMMAND env XDG_DATA_HOME=test/data XDG_CONFIG_HOME=test/home ./fish_tests
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
DEPENDS fish_tests
USES_TERMINAL)
ADD_DEPENDENCIES(test test_low_level tests_dir)
# Suppress generating Xcode schemes for all tests, there's too many.
set(CMAKE_XCODE_GENERATE_SCHEME 0)
# CMake being CMake, you can't just add a DEPENDS argument to add_test to make it depend on any of
# your binaries actually being built before `make test` is executed (requiring `make all` first),
# and the only dependency a test can have is on another test. So we make building fish and
# `fish_tests` prerequisites to our entire top-level `test` target.
function(add_test_target NAME)
string(REPLACE "/" "-" NAME ${NAME})
add_custom_target("test_${NAME}" COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -R "^${NAME}$$"
DEPENDS fish_tests tests_buildroot_target USES_TERMINAL )
endfunction()
add_custom_target(tests_buildroot_target
# Make the directory in which to run tests:
# Make the directory in which to run tests.
# Also symlink fish to where the tests expect it to be.
ADD_CUSTOM_TARGET(tests_buildroot_target
COMMAND ${CMAKE_COMMAND} -E make_directory ${TEST_INSTALL_DIR}
COMMAND env DESTDIR=${TEST_INSTALL_DIR} ${CMAKE_COMMAND}
COMMAND DESTDIR=${TEST_INSTALL_DIR} ${CMAKE_COMMAND}
--build ${CMAKE_CURRENT_BINARY_DIR} --target install
# Put fish_test_helper there too:
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/fish_test_helper
${TEST_INSTALL_DIR}/${CMAKE_INSTALL_PREFIX}/bin
# Also symlink fish to where the tests expect it to be:
COMMAND ${CMAKE_COMMAND} -E create_symlink
${TEST_INSTALL_DIR}/${CMAKE_INSTALL_PREFIX}
${TEST_ROOT_DIR}
DEPENDS fish fish_test_helper)
DEPENDS fish)
# CMake less than 3.9.0 "fully supports" setting an exit code to denote a skipped test, but then
# it just goes ahead and reports it as failed. Really?
if(${CMAKE_VERSION} VERSION_LESS "3.9.0")
set(CMAKE_SKIPPED_HACK "env" "CMAKE_SKIPPED_HACK=1")
else()
set(CMAKE_SKIPPED_HACK)
endif()
IF(NOT FISH_IN_TREE_BUILD)
# We need to symlink share/functions for the tests.
# This should be simplified.
ADD_CUSTOM_TARGET(symlink_functions
COMMAND ${CMAKE_COMMAND} -E create_symlink
${CMAKE_CURRENT_SOURCE_DIR}/share/functions
${CMAKE_CURRENT_BINARY_DIR}/share/functions)
ADD_DEPENDENCIES(tests_buildroot_target symlink_functions)
ELSE()
ADD_CUSTOM_TARGET(symlink_functions)
ENDIF()
foreach(LTEST ${LOW_LEVEL_TESTS})
add_test(
NAME ${LTEST}
COMMAND sh ${CMAKE_CURRENT_BINARY_DIR}/tests/test_env.sh
${CMAKE_BINARY_DIR}/fish_tests ${LTEST}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
set_tests_properties(${LTEST} PROPERTIES SKIP_RETURN_CODE ${SKIP_RETURN_CODE})
add_test_target("${LTEST}")
endforeach(LTEST)
#
# Prep the environment for running the unit tests.
# test-prep: show-DESTDIR show-LN_S show-FISH_VERSION
# $v rm -rf test
# $v $(MKDIR_P) test/data test/home test/temp
# ifdef DESTDIR
# $v $(LN_S) $(DESTDIR) test/root
# else
# $v $(MKDIR_P) test/root
# endif
ADD_CUSTOM_TARGET(test_prep
COMMAND ${CMAKE_COMMAND} -E remove_directory ${TEST_DIR}/data
COMMAND ${CMAKE_COMMAND} -E remove_directory ${TEST_DIR}/home
COMMAND ${CMAKE_COMMAND} -E remove_directory ${TEST_DIR}/temp
COMMAND ${CMAKE_COMMAND} -E make_directory
${TEST_DIR}/data ${TEST_DIR}/home ${TEST_DIR}/temp
DEPENDS tests_buildroot_target
USES_TERMINAL)
FILE(GLOB FISH_CHECKS CONFIGURE_DEPENDS ${CMAKE_SOURCE_DIR}/tests/checks/*.fish)
foreach(CHECK ${FISH_CHECKS})
get_filename_component(CHECK_NAME ${CHECK} NAME)
get_filename_component(CHECK ${CHECK} NAME_WE)
add_test(NAME ${CHECK_NAME}
COMMAND ${CMAKE_SKIPPED_HACK} sh ${CMAKE_CURRENT_BINARY_DIR}/tests/test_driver.sh
${CMAKE_CURRENT_BINARY_DIR}/tests/test.fish ${CHECK}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/tests
)
set_tests_properties(${CHECK_NAME} PROPERTIES SKIP_RETURN_CODE ${SKIP_RETURN_CODE})
add_test_target("${CHECK_NAME}")
endforeach(CHECK)
FILE(GLOB PEXPECTS CONFIGURE_DEPENDS ${CMAKE_SOURCE_DIR}/tests/pexpects/*.py)
foreach(PEXPECT ${PEXPECTS})
get_filename_component(PEXPECT ${PEXPECT} NAME)
add_test(NAME ${PEXPECT}
COMMAND ${CMAKE_SKIPPED_HACK} sh ${CMAKE_CURRENT_BINARY_DIR}/tests/test_driver.sh
${CMAKE_CURRENT_BINARY_DIR}/tests/interactive.fish ${PEXPECT}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/tests
)
set_tests_properties(${PEXPECT} PROPERTIES SKIP_RETURN_CODE ${SKIP_RETURN_CODE})
add_test_target("${PEXPECT}")
endforeach(PEXPECT)
# test_high_level_test_deps = test_fishscript test_interactive test_invocation
# test_high_level: DESTDIR = $(PWD)/test/root/
# test_high_level: prefix = .
# test_high_level: test-prep install-force test_fishscript test_interactive test_invocation
# .PHONY: test_high_level
#
# test_invocation: $(call filter_up_to,test_invocation,$(active_test_goals))
# cd tests; ./invocation.sh
# .PHONY: test_invocation
ADD_CUSTOM_TARGET(test_invocation
COMMAND ./invocation.sh
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/tests/
DEPENDS test_prep test_low_level
USES_TERMINAL)
#
# test_fishscript: $(call filter_up_to,test_fishscript,$(active_test_goals))
# cd tests; ../test/root/bin/fish test.fish
# .PHONY: test_fishscript
ADD_CUSTOM_TARGET(test_fishscript
COMMAND cd tests && ${TEST_ROOT_DIR}/bin/fish test.fish
DEPENDS test_prep test_invocation
USES_TERMINAL)
#
# test_interactive: $(call filter_up_to,test_interactive,$(active_test_goals))
# cd tests; ../test/root/bin/fish interactive.fish
# .PHONY: test_interactive
ADD_CUSTOM_TARGET(test_interactive
COMMAND cd tests && ${TEST_ROOT_DIR}/bin/fish interactive.fish
DEPENDS test_prep test_invocation test_fishscript
USES_TERMINAL)
ADD_CUSTOM_TARGET(test_high_level
DEPENDS test_invocation test_fishscript test_interactive)
ADD_DEPENDENCIES(test test_high_level)
# Group test targets into a TestTargets folder
SET_PROPERTY(TARGET test test_low_level test_high_level tests_dir
test_invocation test_fishscript test_prep
tests_buildroot_target
symlink_functions
PROPERTY FOLDER cmake/TestTargets)

View File

@@ -31,25 +31,25 @@
# stays the same (incremental builds must be fast).
# Just a handy abbreviation.
set(FBVF FISH-BUILD-VERSION-FILE)
SET(FBVF FISH-BUILD-VERSION-FILE)
# TODO: find a cleaner way to do this.
IF (${CMAKE_GENERATOR} STREQUAL Ninja)
set(FBVF-OUTPUT fish-build-version-witness.txt)
set(CFBVF-BYPRODUCTS ${FBVF})
else(${CMAKE_GENERATOR} STREQUAL Ninja)
set(FBVF-OUTPUT ${FBVF})
set(CFBVF-BYPRODUCTS)
endif(${CMAKE_GENERATOR} STREQUAL Ninja)
SET(FBVF-OUTPUT fish-build-version-witness.txt)
SET(CFBVF-BYPRODUCTS ${FBVF})
ELSE(${CMAKE_GENERATOR} STREQUAL Ninja)
SET(FBVF-OUTPUT ${FBVF})
SET(CFBVF-BYPRODUCTS)
ENDIF(${CMAKE_GENERATOR} STREQUAL Ninja)
# Set up the version targets
add_custom_target(CHECK-FISH-BUILD-VERSION-FILE
ADD_CUSTOM_TARGET(CHECK-FISH-BUILD-VERSION-FILE
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build_tools/git_version_gen.sh ${CMAKE_CURRENT_BINARY_DIR}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
BYPRODUCTS ${CFBVF-BYPRODUCTS})
add_custom_command(OUTPUT ${FBVF-OUTPUT}
ADD_CUSTOM_COMMAND(OUTPUT ${FBVF-OUTPUT}
DEPENDS CHECK-FISH-BUILD-VERSION-FILE)
# Abbreviation for the target.
set(CFBVF CHECK-FISH-BUILD-VERSION-FILE)
SET(CFBVF CHECK-FISH-BUILD-VERSION-FILE)

View File

@@ -1,18 +0,0 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cwchar>
// Check whether the runtime mbrtowc implementation attempts to encode
// invalid UTF-8 values.
int main() {
// TODO: I'm not sure how to enforce a UTF-8 locale without overriding the language
char sample[] = "hello world";
sample[0] |= 0xF8;
wchar_t wsample[100] {};
std::mbstate_t state = std::mbstate_t();
int res = std::mbrtowc(wsample, sample, strlen(sample), &state);
return res < 0 ? 0 : 1;
}

View File

@@ -1,39 +1,36 @@
set(languages de en fr pl pt_BR sv zh_CN)
SET(languages de en fr nb nn pl pt_BR sv zh_CN)
include(FeatureSummary)
INCLUDE(FeatureSummary)
option(WITH_GETTEXT "translate messages if gettext is available" ON)
if(WITH_GETTEXT)
find_package(Intl QUIET)
find_package(Gettext)
if(GETTEXT_FOUND)
set(HAVE_GETTEXT 1)
include_directories(${Intl_INCLUDE_DIR})
endif()
endif()
add_feature_info(gettext GETTEXT_FOUND "translate messages with gettext")
OPTION(WITH_GETTEXT "translate messages if gettext is available" ON)
IF(WITH_GETTEXT)
FIND_PACKAGE(Intl)
FIND_PACKAGE(Gettext)
IF(GETTEXT_FOUND)
SET(HAVE_GETTEXT 1)
INCLUDE_DIRECTORIES(${Intl_INCLUDE_DIR})
ENDIF()
ENDIF()
ADD_FEATURE_INFO(gettext GETTEXT_FOUND "translate messages with gettext")
# Define translations
if(GETTEXT_FOUND)
# Group pofile targets into their own folder, as there's a lot of them.
set(CMAKE_FOLDER pofiles)
foreach(lang ${languages})
IF(GETTEXT_FOUND)
FOREACH(lang ${languages})
# Our translations aren't set up entirely as CMake expects, so installation is done in
# cmake/Install.cmake instead of using INSTALL_DESTINATION
gettext_process_po_files(${lang} ALL
GETTEXT_PROCESS_PO_FILES(${lang} ALL
PO_FILES po/${lang}.po)
endforeach()
set(CMAKE_FOLDER)
endif()
ENDFOREACH()
ENDIF()
cmake_push_check_state()
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${Intl_INCLUDE_DIR})
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${Intl_LIBRARIES})
# libintl.h can be compiled into the stdlib on some GLibC systems
if(Intl_FOUND AND Intl_LIBRARIES)
set(LIBINTL_INCLUDE "#include <libintl.h>")
endif()
check_cxx_source_compiles("
IF(Intl_FOUND AND Intl_LIBRARIES)
SET(LIBINTL_INCLUDE "#include <libintl.h>")
SET(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${Intl_INCLUDE_DIR})
SET(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${Intl_LIBRARIES})
ENDIF()
CHECK_CXX_SOURCE_COMPILES("
${LIBINTL_INCLUDE}
#include <stdlib.h>
int main () {
@@ -43,4 +40,3 @@ int main () {
}
"
HAVE__NL_MSG_CAT_CNTR)
cmake_pop_check_state()

File diff suppressed because it is too large Load Diff

1810
config.sub vendored Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -4,12 +4,12 @@
/* Define to 1 if compiled on WSL */
#cmakedefine WSL 1
/* Define to 1 if you have the `clock_gettime' function. */
#cmakedefine HAVE_CLOCK_GETTIME 1
/* Define to 1 if you have the `ctermid_r' function. */
#cmakedefine HAVE_CTERMID_R 1
/* Define to 1 if C++11 thread_local is supported. */
#cmakedefine HAVE_CX11_THREAD_LOCAL 1
/* Define to 1 if you have the `dirfd' function. */
#cmakedefine HAVE_DIRFD 1
@@ -19,21 +19,27 @@
/* Define to 1 if you have the `flock' function. */
#cmakedefine HAVE_FLOCK 1
/* Define to 1 if you have the `futimens' function. */
#cmakedefine HAVE_FUTIMENS 1
/* Define to 1 if you have the `futimes' function. */
#cmakedefine HAVE_FUTIMES 1
/* Define to 1 if you have the `getifaddrs' function. */
#cmakedefine HAVE_GETIFADDRS 1
/* Define to 1 if you have the `getpwent' function. */
#cmakedefine HAVE_GETPWENT 1
/* Define to 1 if you have the 'getrusage' function. */
#cmakedefine HAVE_GETRUSAGE 1
/* Define to 1 if you have the `gettext' function. */
#cmakedefine HAVE_GETTEXT 1
/* Define to 1 if you have the `killpg' function. */
#cmakedefine HAVE_KILLPG 1
/* Define to 1 if you have the `lrand48_r' function. */
#cmakedefine HAVE_LRAND48_R 1
/* Define to 1 if you have the `mkostemp' function. */
#cmakedefine HAVE_MKOSTEMP 1
@@ -49,12 +55,6 @@
/* Define to 1 if you have the <ncurses/term.h> header file. */
#cmakedefine HAVE_NCURSES_TERM_H 1
/* Define to 1 if you have the 'eventfd' function. */
#cmakedefine HAVE_EVENTFD 1
/* Define to 1 if you have the 'pipe2' function. */
#cmakedefine HAVE_PIPE2 1
/* Define to 1 if you have the <siginfo.h> header file. */
#cmakedefine HAVE_SIGINFO_H 1
@@ -82,6 +82,9 @@
/* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */
#cmakedefine HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 1
/* Define to 1 if the sys_errlist array is available. */
#cmakedefine HAVE_SYS_ERRLIST 1
/* Define to 1 if you have the <sys/ioctl.h> header file. */
#cmakedefine HAVE_SYS_IOCTL_H 1
@@ -91,6 +94,9 @@
/* Define to 1 if you have the <sys/sysctl.h> header file. */
#cmakedefine HAVE_SYS_SYSCTL_H 1
/* Define to 1 if you have the <termios.h> header file. */
#cmakedefine HAVE_TERMIOS_H 1
/* Define to 1 if you have the <term.h> header file. */
#cmakedefine HAVE_TERM_H 1
@@ -118,11 +124,11 @@
/* Define to 1 if the _nl_msg_cat_cntr symbol is exported. */
#cmakedefine HAVE__NL_MSG_CAT_CNTR 1
/* Define to 1 if std::make_unique is available. */
#cmakedefine HAVE_STD__MAKE_UNIQUE 1
/* Define to 1 if you have the file `/proc/self/stat'. */
#cmakedefine HAVE__PROC_SELF_STAT 1
/* Define to use clock_gettime and futimens to hack around Linux mtime issue */
#cmakedefine UVAR_FILE_SET_MTIME_HACK 1
/* Define to 1 if the _sys_errs array is available. */
#cmakedefine HAVE__SYS__ERRS 1
/* Define to 1 to disable ncurses macros that conflict with the STL */
#define NCURSES_NOMACROS 1
@@ -136,13 +142,7 @@
/* Define to the full name of this package. */
#define PACKAGE_NAME "fish"
/* Use a variadic tparm on NetBSD curses. */
#cmakedefine TPARM_VARARGS 1
/* The parameter type for the last tputs parameter */
#cmakedefine TPUTS_USES_INT_ARG 1
/* Define to 1 if tparm accepts a fixed amount of parameters. */
/* Define to 1 if tparm accepts a fixed amount of paramters. */
#cmakedefine TPARM_SOLARIS_KLUDGE 1
/* Enable GNU extensions on systems that have them. */
@@ -156,45 +156,23 @@
/* Define if xlocale.h is required for locale_t or wide character support */
#cmakedefine HAVE_XLOCALE_H 1
/* Define if uselocale is available */
#cmakedefine HAVE_USELOCALE 1
/* Enable large inode numbers on Mac OS X 10.5. */
#ifndef _DARWIN_USE_64_BIT_INODE
# define _DARWIN_USE_64_BIT_INODE 1
#endif
/* Define to 1 if mbrtowc attempts to convert invalid UTF-8 sequences */
#cmakedefine HAVE_BROKEN_MBRTOWC_UTF8 1
/* Support __warn_unused on function return values. */
#if __GNUC__ >= 3
#ifndef __warn_unused
#define __warn_unused __attribute__ ((warn_unused_result))
#endif
#ifndef __sentinel
#define __sentinel __attribute__ ((sentinel))
#endif
#ifndef __packed
#define __packed __attribute__ ((packed))
#endif
#else
#define __warn_unused
#endif
/* Like __warn_unused, but applies to a type.
At the moment only clang supports this as a type attribute.
We need to check for __has_attribute being a thing before or old gcc fails - #7554.
*/
#ifndef __has_attribute
#define __has_attribute(x) 0 // Compatibility with non-clang and old gcc compilers.
#endif
#if defined(__clang__) && __has_attribute(warn_unused_result)
#ifndef __warn_unused_type
#define __warn_unused_type __attribute__ ((warn_unused_result))
#endif
#else
#define __warn_unused_type
#endif
#if __has_attribute(fallthrough)
#define __fallthrough__ __attribute__ ((fallthrough));
#else
#define __fallthrough__
#define __sentinel
#define __packed
#endif

726
configure.ac Normal file
View File

@@ -0,0 +1,726 @@
#
# This file is the main build configuration file for fish. It is used
# to determine your systems capabilities, and tries to adapt fish to
# take maximum advantage of the services your system offers.
#
# Process this file using the 'autoconf' command to produce a working
# configure script, which should in turn be executed in order to
# configure the build process.
#
m4_syscmd([build_tools/git_version_gen.sh 2>/dev/null])
AC_PREREQ([2.60])
AC_INIT(fish,
m4_esyscmd([cut -f 2 -d '=' FISH-BUILD-VERSION-FILE | tr -d '"\n']),
https://github.com/fish-shell/fish-shell/issues)
ac_clean_files=a.out.dSYM
#
# List of output variables produced by this configure script
#
AC_SUBST(HAVE_GETTEXT)
AC_SUBST(HAVE_DOXYGEN)
AC_SUBST(LDFLAGS_FISH)
AC_SUBST(WCHAR_T_BITS)
AC_SUBST(EXTRA_PCRE2)
AC_SUBST(HAVE_BROKEN_WCWIDTH)
#
# If needed, run autoconf to regenerate the configure file
#
# This makes sure that after running autoconf once to create the first
# version of configure, we never again need to worry about manually
# running autoconf to handle an updates configure.ac.
#
AC_MSG_CHECKING([if autoreconf needs to be run])
if test configure -ot configure.ac; then
AC_MSG_RESULT([yes])
if command -v autoreconf >/dev/null; then
# No need to provide any error messages if autoreconf fails, the
# shell and autconf should take care of that themselves
AC_MSG_NOTICE([running autoreconf --no-recursive])
if autoreconf --no-recursive; then
./configure "$@"
exit
fi
exit 1
else
AC_MSG_ERROR(
[cannot find the autoreconf program in your path.
This program needs to be run whenever the configure.ac file is modified.
Please install autoreconf and try again.]
)
fi
else
AC_MSG_RESULT([no])
fi
#
# If needed, run autoheader to regenerate config.h.in
#
# This makes sure we never ever have to run autoheader manually. It
# will be run whenever needed automatically.
#
AC_MSG_CHECKING([if autoheader needs to be run])
if test ! -f ./config.h.in -o config.h.in -ot configure.ac; then
AC_MSG_RESULT([yes])
if command -v autoheader >/dev/null; then
AC_MSG_NOTICE([running autoheader])
autoheader || exit 1
else
AC_MSG_ERROR(
[cannot find the autoheader program in your path.
This program needs to be run whenever the configure.ac file is modified.
Please install autotools and try again.]
)
fi
else
AC_MSG_RESULT([no])
fi
#
# Include the autoconf macros directory
#
AC_CONFIG_MACRO_DIRS([m4])
#
# Set up various programs needed for install
# Note AC_PROG_CXX sets CXXFLAGS if not set, which we want
# So ensure this happens before we modify CXXFLAGS below
# Do CC also, because PCRE2 will use it.
AC_PROG_CC
AC_PROG_CC_STDC # c99
AC_PROG_CXX
AC_LANG(C++)
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_MKDIR_P
AC_PROG_AWK
AC_PROG_FGREP
AC_PROG_SED
AC_USE_SYSTEM_EXTENSIONS
AX_CXX_COMPILE_STDCXX_11(noext,mandatory)
#
# Tell autoconf to create config.h header
#
AC_CONFIG_HEADERS(config.h)
AC_CANONICAL_HOST
#
# This adds markup to the code that results in a few extra compile
# time checks on recent GCC versions. It helps stop a few common bugs.
#
AH_BOTTOM([#if __GNUC__ >= 3
#ifndef __warn_unused
#define __warn_unused __attribute__ ((warn_unused_result))
#endif
#ifndef __sentinel
#define __sentinel __attribute__ ((sentinel))
#endif
#ifndef __packed
#define __packed __attribute__ ((packed))
#endif
#else
#define __warn_unused
#define __sentinel
#define __packed
#endif])
#
# Optionally drop gettext support
#
AC_ARG_WITH(
gettext,
AS_HELP_STRING(
[--without-gettext],
[do not translate messages, even if gettext is available]
),
[local_gettext=$withval],
[local_gettext=check]
)
AS_IF([test x$local_gettext != xno],
[ AC_CHECK_PROGS( [found_msgfmt], [msgfmt], [no] )
if test x$found_msgfmt != xno; then
AC_DEFINE([USE_GETTEXT],[1],[Perform string translations with gettext])
elif test "x$local_gettext" != "xcheck" ; then
AC_MSG_FAILURE([--with-gettext was given, but the msgfmt program could not be found])
else
local_gettext=no
fi
],
)
#
# Build/clean the documentation only if Doxygen is available
#
doxygen_minimum=1.8.7
AC_ARG_WITH(
doxygen,
AS_HELP_STRING(
[--with-doxygen],
[use Doxygen to regenerate documentation]
),
[use_doxygen=$withval],
[use_doxygen=auto]
)
AS_IF([test "$use_doxygen" != "no"],
[
AC_CHECK_PROGS([found_doxygen], [doxygen], [no])
if test "$found_doxygen" != no; then
# test version
AC_MSG_CHECKING([the doxygen version])
doxygen_version=`doxygen --version 2>/dev/null`
AC_MSG_RESULT([$doxygen_version])
dnl This requires autoconf 2.60 or newer
AS_VERSION_COMPARE([$doxygen_version], [$doxygen_minimum],
[ if test "$use_doxygen" = auto; then
AC_MSG_WARN([doxygen version $doxygen_version found, but $doxygen_minimum required])
HAVE_DOXYGEN=0
else
AC_MSG_FAILURE([doxygen version $doxygen_version found, but $doxygen_minimum required])
fi
],
[HAVE_DOXYGEN=1], [HAVE_DOXYGEN=1])
elif test "$use_doxygen" != auto; then
AC_MSG_FAILURE([--with-doxygen was given, but the doxygen program could not be found])
else
HAVE_DOXYGEN=0
fi
],
)
#
# Try to enable large file support. This will make sure that on systems
# where off_t can be either 32 or 64 bit, the latter size is used. On
# other systems, this should do nothing. (Hopefully)
#
AC_SYS_LARGEFILE
# Fish does not use exceptions.
CXXFLAGS="$CXXFLAGS -fno-exceptions"
#
# Set some warning flags
# Don't warn about missing field initializers, it has too many
# false positives for code like `struct termios tmodes = {};`
#
CXXFLAGS="$CXXFLAGS -Wextra -Wno-missing-field-initializers"
#
# This is needed in order to get the really cool backtraces on Linux
#
AC_MSG_CHECKING([for -rdynamic linker flag])
prev_LDFLAGS="$LDFLAGS"
LDFLAGS="$LDFLAGS -rdynamic"
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],
[
AC_MSG_RESULT([yes])
LDFLAGS_FISH="$LDFLAGS_FISH -rdynamic"
], [
AC_MSG_RESULT([no])
LDFLAGS_FISH="$LDFLAGS_FISH"
])
LDFLAGS="$prev_LDFLAGS"
#
# See if Linux procfs is present. This is used to get extra
# information about running processes.
#
AC_CHECK_FILES([/proc/self/stat])
# Disable curses macros that conflict with the STL
AC_DEFINE([NCURSES_NOMACROS], [1], [Define to 1 to disable ncurses macros that conflict with the STL])
AC_DEFINE([NOMACROS], [1], [Define to 1 to disable curses macros that conflict with the STL])
# Threading is excitingly broken on Solaris without adding -pthread to CXXFLAGS
# Only support GCC for now
dnl Ideally we would use the AX_PTHREAD macro here, but it's GPL3-licensed
dnl ACX_PTHREAD is way too old and seems to break the OS X build
dnl Both only check with AC_LANG(C) in any case
case $host_os in
solaris*)
CXXFLAGS="$CXXFLAGS -pthread"
CFLAGS="$CFLAGS -pthread"
;;
esac
#
# Check presense of various libraries. This is done on a per-binary
# level, since including various extra libraries in all binaries only
# because thay are used by some of them can cause extra bloat and
# slower compiles when developing fish.
#
# Check for os dependant libraries for all binaries.
AC_SEARCH_LIBS( nanosleep, rt, , [AC_MSG_ERROR([Cannot find the rt library, needed to build this package.] )] )
AC_SEARCH_LIBS( shm_open, rt, [AC_DEFINE([HAVE_SHM_OPEN], [1], [Define to 1 if the shm_open() function exists])] )
AC_SEARCH_LIBS( pthread_create, pthread, , [AC_MSG_ERROR([Cannot find the pthread library, needed to build this package.] )] )
AC_SEARCH_LIBS( setupterm, [ncurses tinfo curses], , [AC_MSG_ERROR([Could not find a curses implementation, needed to build fish. If this is Linux, try running 'sudo apt-get install libncurses5-dev' or 'sudo yum install ncurses-devel'])] )
AC_SEARCH_LIBS( [dladdr], [dl] )
if test x$local_gettext != xno; then
AC_SEARCH_LIBS( gettext, intl,,)
fi
#
# Check presense of various header files
#
AC_CHECK_HEADERS([getopt.h termios.h sys/resource.h term.h ncurses/term.h ncurses.h ncurses/curses.h curses.h stropts.h siginfo.h sys/select.h sys/ioctl.h execinfo.h spawn.h sys/sysctl.h])
if test x$local_gettext != xno; then
AC_CHECK_HEADERS([libintl.h])
fi
#
# Get the size in bits of wchar_t, needed for configuring the pcre2 build
# and for code that #includes pcre2.h
#
AC_CHECK_SIZEOF(wchar_t)
WCHAR_T_BITS=`expr 8 \* $ac_cv_sizeof_wchar_t`
AC_DEFINE_UNQUOTED([WCHAR_T_BITS], [$WCHAR_T_BITS], [The size of wchar_t in bits.])
#
# Detect nanoseconds fields in struct stat
#
AC_CHECK_MEMBERS([struct stat.st_ctime_nsec])
AC_CHECK_MEMBERS([struct stat.st_mtimespec.tv_nsec])
AC_CHECK_MEMBERS([struct stat.st_mtim.tv_nsec])
#
# Check for D_TYPE in dirent, only on BSD and Linux
#
AC_STRUCT_DIRENT_D_TYPE
#
# Check for presence of various functions used by fish
#
AC_CHECK_FUNCS( wcsndup )
AC_CHECK_FUNCS( wcstod_l )
AC_CHECK_FUNCS( futimes )
AC_CHECK_FUNCS( wcslcpy lrand48_r killpg )
AC_CHECK_FUNCS( backtrace_symbols getifaddrs )
AC_CHECK_FUNCS( futimens clock_gettime )
AC_CHECK_FUNCS( getpwent flock )
AC_CHECK_FUNCS( dirfd )
AC_CHECK_DECL( [mkostemp], [ AC_CHECK_FUNCS([mkostemp]) ] )
#
# Although setupterm is linkable thanks to SEARCH_LIBS above, some
# builds of ncurses include the actual headers in a different package
#
AC_CHECK_DECL( [setupterm], , [AC_MSG_ERROR([Could not find a curses implementation, needed to build fish. If this is Linux, try running 'sudo apt-get install libncurses5-dev' or 'sudo yum install ncurses-devel'])], [
#if HAVE_NCURSES_H
#include <ncurses.h>
#elif HAVE_NCURSES_CURSES_H
#include <ncurses/curses.h>
#else
#include <curses.h>
#endif
#if HAVE_TERM_H
#include <term.h>
#elif HAVE_NCURSES_TERM_H
#include <ncurses/term.h>
#endif
] )
dnl AC_CHECK_FUNCS uses C linkage, but sometimes (Solaris!) the behaviour is
dnl different with C++.
AC_MSG_CHECKING([for wcsdup])
AC_TRY_LINK( [ #include <wchar.h> ],
[ wchar_t* foo = wcsdup(L""); ],
[ AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_WCSDUP, 1, Define to 1 if you have the `wcsdup' function.)
],
[AC_MSG_RESULT(no)],
)
AC_MSG_CHECKING([for std::wcsdup])
AC_TRY_LINK( [ #include <wchar.h> ],
[ wchar_t* foo = std::wcsdup(L""); ],
[ AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_STD__WCSDUP, 1, Define to 1 if you have the `std::wcsdup' function.)
],
[AC_MSG_RESULT(no)],
)
AC_MSG_CHECKING([for wcscasecmp])
AC_TRY_LINK( [ #include <wchar.h> ],
[ int foo = wcscasecmp(L"", L""); ],
[ AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_WCSCASECMP, 1, Define to 1 if you have the `wcscasecmp' function.)
],
[AC_MSG_RESULT(no)],
)
AC_MSG_CHECKING([for std::wcscasecmp])
AC_TRY_LINK( [ #include <wchar.h> ],
[ int foo = std::wcscasecmp(L"", L""); ],
[ AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_STD__WCSCASECMP, 1, Define to 1 if you have the `std::wcscasecmp' function.)
],
[AC_MSG_RESULT(no)],
)
AC_MSG_CHECKING([for wcsncasecmp])
AC_TRY_LINK( [ #include <wchar.h> ],
[ int foo = wcsncasecmp(L"", L"", 0); ],
[ AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_WCSNCASECMP, 1, Define to 1 if you have the `wcsncasecmp' function.)
],
[AC_MSG_RESULT(no)],
)
AC_MSG_CHECKING([for std::wcsncasecmp])
AC_TRY_LINK( [ #include <wchar.h> ],
[ int foo = std::wcsncasecmp(L"", L"", 0); ],
[ AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_STD__WCSNCASECMP, 1, Define to 1 if you have the `std::wcsncasecmp' function.)
],
[AC_MSG_RESULT(no)],
)
AC_MSG_CHECKING([for std::make_unique])
AC_TRY_LINK( [ #include <memory> ],
[ std::unique_ptr<int> foo = std::make_unique<int>(); ],
[ AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_STD__MAKE_UNIQUE, 1, Define to 1 if you have the `std::make_unique' function.)
],
[AC_MSG_RESULT(no)],
)
if test x$local_gettext != xno; then
AC_CHECK_FUNCS( gettext )
#
# The Makefile also needs to know if we have gettext, so it knows if
# the translations should be installed.
#
AC_CHECK_FUNC( gettext, HAVE_GETTEXT=1, HAVE_GETTEXT=0 )
fi
#
# Here follows a list of small programs used to test for various
# features that Autoconf doesn't tell us about
#
dnl AC_CHECK_FUNCS uses C linkage, but sometimes (Solaris!) the behaviour is
dnl different with C++.
AC_MSG_CHECKING([if ctermid_r() available])
AC_TRY_LINK( [ #include <stdio.h> ],
[ char buf[L_ctermid]; char *foo = ctermid_r(buf); ],
[ AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_CTERMID_R, 1, Define to 1 if you have the `ctermid_r' function.)
],
[AC_MSG_RESULT(no)],
)
#
# Check if struct winsize and TIOCGWINSZ exist
#
AC_MSG_CHECKING([if struct winsize and TIOCGWINSZ exist])
AC_LINK_IFELSE(
[
AC_LANG_PROGRAM(
[
#ifdef HAVE_TERMIOS_H
#include <termios.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
],
[
struct winsize termsize = {0};
TIOCGWINSZ;
]
)
],
[
AC_MSG_RESULT(yes);
AC_DEFINE([HAVE_WINSIZE], [1], [Define to 1 if the winsize struct and TIOCGWINSZ macro exist])
],
[
AC_MSG_RESULT(no)
]
)
# Check for _nl_msg_cat_cntr symbol
AC_MSG_CHECKING([for _nl_msg_cat_cntr symbol])
AC_TRY_LINK(
[
#if HAVE_LIBINTL_H
#include <libintl.h>
#endif
#include <stdlib.h>
],
[
extern int _nl_msg_cat_cntr;
int tmp = _nl_msg_cat_cntr;
exit(tmp);
],
have__nl_msg_cat_cntr=yes,
have__nl_msg_cat_cntr=no
)
if test "$have__nl_msg_cat_cntr" = yes; then
AC_MSG_RESULT(yes)
AC_DEFINE(
[HAVE__NL_MSG_CAT_CNTR],
[1],
[Define to 1 if the _nl_msg_cat_cntr symbol is exported.]
)
else
AC_MSG_RESULT(no)
fi
# Check for sys_errlist
AC_MSG_CHECKING([for sys_errlist array])
AC_TRY_LINK(
[
#include <stdio.h>
],
[
const char *p;
p = sys_errlist[sys_nerr];
],
have_sys_errlist=yes,
have_sys_errlist=no
)
if test "$have_sys_errlist" = yes; then
AC_MSG_RESULT(yes)
AC_DEFINE(
[HAVE_SYS_ERRLIST],
[1],
[Define to 1 if the sys_errlist array is available.]
)
else
AC_MSG_RESULT(no)
fi
# Check for _sys_errs
AC_MSG_CHECKING([for _sys_errs array])
AC_TRY_LINK(
[
#include <string>
],
[
std::string p;
extern const char _sys_errs[];
extern const int _sys_index[];
p = _sys_errs[_sys_index[0]];
],
have__sys__errs=yes,
have__sys__errs=no
)
if test "$have__sys__errs" = yes; then
AC_MSG_RESULT(yes)
AC_DEFINE(
[HAVE__SYS__ERRS],
[1],
[Define to 1 if the _sys_errs array is available.]
)
else
AC_MSG_RESULT(no)
fi
# Check for Solaris curses tputs having fixed length parameter list.
AC_MSG_CHECKING([if we are using non varargs tparm.])
AC_COMPILE_IFELSE(
[
AC_LANG_PROGRAM(
[
#if HAVE_NCURSES_H
#include <ncurses.h>
#elif HAVE_NCURSES_CURSES_H
#include <ncurses/curses.h>
#else
#include <curses.h>
#endif
#if HAVE_TERM_H
#include <term.h>
#elif HAVE_NCURSES_TERM_H
#include <ncurses/term.h>
#endif
],
[
tparm( "" );
]
)
],
[tparm_solaris_kludge=no],
[tparm_solaris_kludge=yes]
)
if test "x$tparm_solaris_kludge" = "xyes"; then
AC_MSG_RESULT(yes)
AC_DEFINE(
[TPARM_SOLARIS_KLUDGE],
[1],
[Define to 1 if tparm accepts a fixed amount of paramters.]
)
else
AC_MSG_RESULT(no)
fi
# ========
# PCRE2 library configuration.
pcre2_min_version=10.21
EXTRA_PCRE2=
AC_ARG_WITH(
included-pcre2,
AS_HELP_STRING(
[--without-included-pcre2],
[build against the system PCRE2 library instead of the bundled version]
),
[included_pcre2=$withval],
[included_pcre2=auto]
)
HAVE_BROKEN_WCWIDTH=
AC_ARG_ENABLE(
[wcwidth],
AS_HELP_STRING(
[--disable-internal-wcwidth],
[use system wcwidth instead of the bundled version]
))
if test "x$enable_wcwidth" != "xno"; then
AC_DEFINE([HAVE_BROKEN_WCWIDTH], [1], [banana])
else
AC_DEFINE([HAVE_BROKEN_WCWIDTH], [0], [banana])
fi
if test "x$included_pcre2" != "xyes"; then
# test for pcre2-config
# can use either pcre2-config or pkgconfig here but only implement the former for now
AC_CHECK_PROG(PCRE2_CONFIG, pcre2-config, pcre2-config)
if test "x$PCRE2_CONFIG" != "x"; then
dnl AC_MSG_CHECKING([for $WCHAR_T_BITS-bit PCRE2])
XLIBS="$LIBS"
LIBS="$LIBS "`$PCRE2_CONFIG --libs$WCHAR_T_BITS 2>/dev/null`
XCXXFLAGS="$CXXFLAGS"
CXXFLAGS="$CXXFLAGS "`$PCRE2_CONFIG --cflags`
# cheat a bit here. the exact library is determined by $WCHAR_T_BITS,
# and so AC_CHECK_LIB won't work (can't use a variable as library name)
# AC_SEARCH_LIBS will use the existing $LIBS flags with no additional library first
AC_SEARCH_LIBS([pcre2_compile_$WCHAR_T_BITS], [],
[ # pcre2 lib found, check for minimum version
pcre2_version=`$PCRE2_CONFIG --version`
AS_VERSION_COMPARE([$pcre2_version], [$pcre2_min_version],
[ # version < minimum
AC_MSG_NOTICE([system PCRE2 library version $pcre2_version, need $pcre2_min_version or later])
if test "x$included_pcre2" = "xno"; then
# complain about pcre2 version
AC_MSG_ERROR([system PCRE2 library is too old, but --without-included-pcre2 was given.])
else
# use the internal version; undo changes to LIBS/CXXFLAGS
included_pcre2=yes
LIBS="$XLIBS"
CXXFLAGS="$XCXXFLAGS"
fi
],
[ # version == minimum
working_pcre2=yes
],
[ # version > minimum
working_pcre2=yes
]
)
],
[ # fail case; undo the changes to LIBS/CXXFLAGS
working_pcre2=no
LIBS="$XLIBS"
CXXFLAGS="$XCXXFLAGS"
]
)
fi
if test "x$working_pcre2" = "xyes"; then
AC_MSG_NOTICE([using system PCRE2 library])
else
# pcre2 size wrong or pcre2-config not found
# is it OK to use the included version?
if test "x$included_pcre2" = "xno"; then
# complain
AC_MSG_ERROR([cannot find system pcre2-config, but --without-included-pcre2 was given.
Make sure pcre2-config is installed and available in PATH.
You may need to install the PCRE2 development library for your system.])
else
# use the internal version
included_pcre2=yes
fi
fi
fi
# Re-test as value may have changed.
if test "x$included_pcre2" = "xyes"; then
# Build configure/Makefile for pcre2
AC_MSG_NOTICE([using included PCRE2 library])
# unfortunately these get added to the global configuration
ac_configure_args="$ac_configure_args --disable-pcre2-8 --enable-pcre2-$WCHAR_T_BITS --disable-shared"
AC_CONFIG_SUBDIRS([pcre2-10.22])
PCRE2_CXXFLAGS='-I$(PCRE2_DIR)/src'
PCRE2_LIBS='-L$(PCRE2_LIBDIR) -lpcre2-$(PCRE2_WIDTH)'
# Make the binary depend on the PCRE2 libraries so they get built
EXTRA_PCRE2='$(PCRE2_LIB)'
CXXFLAGS="$CXXFLAGS $PCRE2_CXXFLAGS"
LIBS="$LIBS $PCRE2_LIBS"
fi
# Allow configurable extra directories.
AC_SUBST(extra_completionsdir)
AC_ARG_WITH([extra-completionsdir],
AS_HELP_STRING([--with-extra-completionsdir=DIR],
[path for extra completions]),
[extra_completionsdir=$withval],
[extra_completionsdir='${datadir}/fish/vendor_completions.d'])
AC_SUBST(extra_functionsdir)
AC_ARG_WITH([extra_functionsdir],
AS_HELP_STRING([--with-extra-functionsdir=DIR],
[path for extra functions]),
[extra_functionsdir=$withval],
[extra_functionsdir='${datadir}/fish/vendor_functions.d'])
AC_SUBST(extra_confdir)
AC_ARG_WITH([extra-confdir],
AS_HELP_STRING([--with-extra-confdir=DIR],
[path for extra conf]),
[extra_confdir=$withval],
[extra_confdir='${datadir}/fish/vendor_conf.d'])
# Tell the world what we know.
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
echo "fish is now configured."

2
debian/compat vendored
View File

@@ -1 +1 @@
10
9

40
debian/control vendored
View File

@@ -1,25 +1,45 @@
Source: fish
Section: shells
Priority: optional
Priority: extra
Maintainer: ridiculous_fish <corydoras@ridiculousfish.com>
Uploaders: David Adam <zanchey@ucc.gu.uwa.edu.au>
# Debhelper should be bumped to >= 10 once Ubuntu Xenial is no longer supported
Build-Depends: debhelper (>= 9.20160115), libncurses5-dev, cmake (>= 3.5.0), gettext, libpcre2-dev,
# Test dependencies
locales-all, python3
Standards-Version: 4.1.5
Build-Depends: debhelper (>= 9.0.0), libncurses5-dev, cmake3 (>= 3.2.0) | cmake (>= 3.2.0), gettext
# When libpcre2-dev is available on all supported Debian versions, add a dependency on that.
Standards-Version: 3.9.4
Homepage: https://fishshell.com/
Vcs-Git: https://github.com/fish-shell/fish-shell.git
Vcs-Browser: https://github.com/fish-shell/fish-shell
Package: fish
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}, passwd (>= 4.0.3-10), gettext-base, man-db,
python3 (>=3.5)
Conflicts: fish-common
Depends: ${shlibs:Depends}, ${misc:Depends}, fish-common (= ${source:Version}), passwd (>= 4.0.3-10), bc, gettext-base, man-db
Recommends: xsel (>=1.2.0)
Suggests: xdg-utils
Description: friendly interactive shell
Fish is a command-line shell for modern systems, focusing on user-friendliness,
sensibility and discoverability in interactive use. The syntax is simple, but
not POSIX compliant.
Package: fish-common
Architecture: all
Depends: ${misc:Depends}
Recommends: fish, python3 (>= 3.3) | python (>=2.7)
Suggests: xdg-utils
Replaces: fish (<= 2.1.1.dfsg-2)
Description: friendly interactive shell (architecture-independent files)
Fish is a command-line shell for modern systems, focusing on user-friendliness,
sensibility and discoverability in interactive use. The syntax is simple, but
not POSIX compliant.
.
This package contains the common fish files shared by all architectures.
Package: fish-dbg
Architecture: any
Section: debug
Priority: extra
Depends: fish (= ${binary:Version}), ${misc:Depends}
Description: debugging symbols for friendly interactive shell
Fish is a command-line shell for modern systems, focusing on user-friendliness,
sensibility and discoverability in interactive use. The syntax is simple, but
not POSIX compliant.
.
This package contains the debugging symbols for fish.

1
debian/docs vendored
View File

@@ -1 +0,0 @@
README.rst

1
debian/fish-common.docs vendored Normal file
View File

@@ -0,0 +1 @@
README.md

2
debian/fish-common.install vendored Normal file
View File

@@ -0,0 +1,2 @@
debian/tmp/etc
debian/tmp/usr/share

4
debian/fish-common.lintian-overrides vendored Normal file
View File

@@ -0,0 +1,4 @@
# These directories are intentionally empty.
fish-common: package-contains-empty-directory usr/share/fish/vendor_completions.d/
fish-common: package-contains-empty-directory usr/share/fish/vendor_conf.d/
fish-common: package-contains-empty-directory usr/share/fish/vendor_functions.d/

1
debian/fish.install vendored Normal file
View File

@@ -0,0 +1 @@
debian/tmp/usr/bin

37
debian/fish.postrm vendored Normal file
View File

@@ -0,0 +1,37 @@
#!/bin/sh
# postrm script for fish
#
# see: dh_installdeb(1)
set -e
# summary of how this script can be called:
# * <postrm> `remove'
# * <postrm> `purge'
# * <old-postrm> `upgrade' <new-version>
# * <new-postrm> `failed-upgrade' <old-version>
# * <new-postrm> `abort-install'
# * <new-postrm> `abort-install' <old-version>
# * <new-postrm> `abort-upgrade' <old-version>
# * <disappearer's-postrm> `disappear' <overwriter>
# <overwriter-version>
# for details, see http://www.debian.org/doc/debian-policy/ or
# the debian-policy package
case "$1" in
purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
;;
*)
echo "postrm called with unknown argument \`$1'" >&2
exit 1
;;
esac
# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#
exit 0

View File

View File

@@ -1,4 +0,0 @@
# These directories are intentionally empty.
fish: package-contains-empty-directory usr/share/fish/vendor_completions.d/
fish: package-contains-empty-directory usr/share/fish/vendor_conf.d/
fish: package-contains-empty-directory usr/share/fish/vendor_functions.d/

2
debian/menu vendored Normal file
View File

@@ -0,0 +1,2 @@
?package(fish):needs="text" section="Applications/Shells"\
title="fish" command="/usr/bin/fish"

18
debian/rules vendored
View File

@@ -7,11 +7,17 @@ export DH_VERBOSE=1
%:
dh $@
# Setting the build system is still required, because otherwise the GNUmakefile gets picked up
override_dh_auto_configure:
dh_auto_configure --buildsystem=cmake
# Until all platforms have debhelper 9.20151004, Debian bug 719148 needs to be worked around
dh_auto_configure --buildsystem=cmake --parallel -- -DCMAKE_INSTALL_SYSCONFDIR=/etc
# On CMake 3.5 (and possibly 3.6), the test target does not pick up its dependencies properly
# Build fish_tests/tests_buildroot_target by hand (remove this once Ubuntu Xenial is out of support)
override_dh_auto_build:
dh_auto_build -- all fish_tests tests_buildroot_target
override_dh_installdocs:
dh_installdocs --link-doc=fish
# Still needed until all platforms have debhelper 9.20151219
# Consider transitioning https://wiki.debian.org/DebugPackage
override_dh_strip:
dh_strip --dbg-package=fish-dbg
# Don't run tests; they don't work until fish is installed
override_dh_auto_test:

253
doc_src/FORMATTING.md Normal file
View File

@@ -0,0 +1,253 @@
# Formatting guide for fish docs
The fish documentation has been updated to support Doxygen 1.8.7+, and while the main benefit of this change is extensive Markdown support, the addition of a fish lexicon and syntax filter, combined with semantic markup rules allows for automatic formatting enhancements across the HTML user_docs and man pages.
Initially my motivation was to fix a problem with long options ([Issue #1557](https://github.com/fish-shell/fish-shell/issues/1557) on GitHub), but as I worked on fixing the issue I realised there was an opportunity to simplify, reinforce and clarify the current documentation, hopefully making further contribution easier and cleaner, while allowing the documentation examples to presented more clearly with less author effort.
While the documentation is pretty robust to variations in the documentation source, adherence to the following style guide will help keep the already excellent documentation in good shape moving forward.
## Line breaks and wrapping
Contrary to the rest of the fish source code, the documentation greatly benefits from the use of long lines and soft wrapping. Doxygen is able to treat paragraphs as complete blocks. The semantic filter can see complete lines when deciding on how to apply syntax highlighting. In advanced pagers, such as 'most', man pages will consistently wrap to the width of the user's console.
## Doxygen special commands and aliases
While Markdown syntax forms the basis of the documentation content, there are some exceptions that require the use of Doxygen special commands. On the whole, Doxygen commands should be avoided, especially inline word formatting such as \\c as this would allow Doxygen to make unhelpful assumptions, such as converting double dashes (\--) to n-dashes ().
### Structure: \\page, \\section and \\subsection
Use of Doxygen sections markers are important, as these determine what will be eventually output as a web page, man page or included in the developer docs.
Currently the make process for the documentation is quite convoluted, but basically the HTML docs are produced from a single, compiled file, doc.h. This contains a number of \\page markers that produce the various pages used in the documentation. The format of a \\page mark is:
\page universally_unique_page_id Page title
The source files that contain the page markers are currently:
- __index.hdr.in__: Core documentation
- __commands.hdr.in__: Individual commands
- __tutorial.hdr__: Tutorial
- __design.hdr__: Design document
- __faq.hdr__: Frequently Asked Questions
- __license.hdr__: Fish and 3rd party licences
Unless there is a _VERY_ good reason and developer consensus, new pages should never be added.
The rest of the documentation is structured using \\section and \\subsection markers. Most of the source files (listed above) contain their full content, the exception being commands, which are separated out into source text files in the doc_src directory. These files are concatenated into one file, so each one starts with a \\section declaration. The synopsis, description and examples (if present) are declared as \\subsections. The format of these marks is practically identical to the page mark.
\section universally_unique_section_id Section title
\subsection universally_unique_subsection_id Subsection title
Each page, section and subsection id _must_ be unique across the whole of the documentation, otherwise Doxygen will issue a warning.
### Semantic markup: the \\fish .. \\endfish block
While Doxygen has support for \\code..\\endcode blocks with enhanced markup and syntax colouring, it only understands the core Doxygen languages: C, C++, Objective C, Java, PHP, Python, Tcl and Fortran. To enhance Fish's syntax presentation, use the special \\fish..\\endfish blocks instead.
Text placed in this block will be parsed by Doxygen using the included lexicon filter (see lexicon_filter.in) as a Doxygen input filter. The filter is built during make so that it can pick up information on builtins, functions and shell commands mentioned in completions and apply markup to keywords found inside the \\fish block.
Basically, preformatted plain text inside the \\fish block is fed through the filter and is returned marked up so that Doxygen aliases can convert it back to a presentable form, according to the output document type.
For instance:
`echo hello world`
is transformed into:
`@cmnd{echo} @args{hello} @args{world}`
which is then transformed by Doxygen into an HTML version (`make doc`):
`<span class="command">echo</span> <span class="argument">hello</span> <span class="argument">world</span>`
And a man page version (`make share/man`):
__echo__ hello world
### Fonts
In older browsers, it was easy to set the fonts used for the three basic type styles (serif, sans-serif and monospace). Modern browsers have removed these options in their respective quests for simplification, assuming the content author will provide suitable styles for the content in the site's CSS, or the end user will provide overriding styles manually. Doxygen's default styling is very simple and most users will just accept this default.
I've tried to use a sensible set of fonts in the documentation's CSS based on 'good' terminal fonts and as a result the first preference font used throughout the documentation is '[DejaVu](https://dejavu-fonts.github.io)'. The rationale behind this is that while DejaVu is getting a little long in the tooth, it still provides the most complete support across serif, sans-serif and monospace styles (giving a well balanced feel and consistent [x-height](https://en.wikipedia.org/wiki/X-height)), has the widest support for extended Unicode characters and has a free, permissive licenses (though it's still incompatible with GPLv2, though arguably less so than the SIL Open Font license, though this is a moot point when using it solely in the docs).
#### Fonts inside \\fish blocks and \`backticks\`
As the point of these constructs is to make fish's syntax clearer to the user, it makes sense to mimic what the user will see in the console, therefore any content is formatted using the monospaced style, specifically monospaced fonts are chosen in the following order:
1. __DejaVu Sans Mono__: Explained above. [[&darr;](https://dejavu-fonts.github.io)]
2. __Source Code Pro__: Monospaced code font, part of Adobe's free Edge Web Fonts. [[&darr;](https://edgewebfonts.adobe.com)]
3. __Menlo__: Apple supplied variant of DejaVu.
4. __Ubuntu Mono__: Ubuntu Linux's default monospaced font. [[&darr;](http://font.ubuntu.com)]
5. __Consolas__: Modern Microsoft supplied console font.
6. __Monaco__: Apple supplied console font since 1984!
7. __Lucida Console__: Generic mono terminal font, standard in many OS's and distros.
8. __monospace__: Catchall style. Chooses default monospaced font, often Courier.
9. __fixed__: As above, more often used on mobile devices.
#### General Fonts
1. __DejaVu Sans__: As above.[[&darr;](https://dejavu-fonts.github.io)]
2. __Roboto__: Elegant Google free font and is Doxygen's default [[&darr;](https://fonts.google.com/specimen/Roboto)]
3. __Lucida Grande__: Default Apple OS X content font.
4. __Calibri__: Default Microsoft Office font (since 2007).
5. __Verdana__: Good general font found in a lot of OSs.
6. __Helvetica Neue__: Better spaced and balanced Helvetica/Arial variant.
7. __Helvetica__: Standard humanist typeface found almost everywhere.
8. __Arial__: Microsoft's Helvetica.
9. __sans-serif__: Catchall style. Chooses default sans-serif typeface, often Helvetica.
The ordering of the fonts is important as it's designed to allow the documentation to settle into a number of different identities according to the fonts available. If you have the complete DejaVu family installed, then the docs are presented using that, and if your Console is set up to use the same fonts, presentation will be completely consistent.
On OS X, with nothing extra installed, the docs will default to Menlo and Lucida Grande giving a Mac feel. Under Windows, it will default to using Consolas and Calibri on recent versions, giving a modern Windows style.
#### Other sources:
- [Font Squirrel](https://www.fontsquirrel.com): Good source of open source font packages.
### Choosing a CLI style: using a \\fish{style} block
By default, when output as HTML, a \\fish block uses syntax colouring suited to the style of the documentation rather than trying to mimic the terminal. The block has a light, bordered background and a colour scheme that 'suggests' what the user would see in a console.
Additional stying can be applied adding a style declaration:
\fish{additional_style [another_style...]}
...
\endfish
This will translate to classes applied to the `<div>` tag, like so:
<div class="fish additional_style another_style">
...
</div>
The various classes are defined in `doc_src/user_doc.css` and new style can be simply added
The documentation currently defines a couple of additional styles:
- __cli-dark__: Used in the _tutorial_ and _FAQ_ to simulate a dark background terminal, with fish's default colours (slightly tweaked for legibility in the browser).
- __synopsis__: A simple colour theme helpful for displaying the logical 'summary' of a command's syntax, options and structure.
## Markdown
Apart from the exceptions discussed above, the rest of the documentation now supports the use of Markdown. As such the use of Doxygen special commands for HTML tags is unnecessary.
There are a few exceptions and extensions to the Markdown [standard](https://daringfireball.net/projects/markdown/) that are documented in the Doxygen [documentation](https://www.stack.nl/~dimitri/doxygen/manual/markdown.html).
### \`Backticks\`
As is standard in Markdown and 'Github Flavoured Markdown' (GFM), backticks can be used to denote inline technical terms in the documentation, `like so`. In the documentation this will set the font to the monospaced 'console' typeface and will cause the enclosed term to stand out.
However, fenced code blocks using 4 spaces or 3 backticks (\`\`\`) should be avoided as Doxygen will interpret these as \\code blocks and try to apply standard syntax colouring, which doesn't work so well for fish examples. Use `\fish..\endfish` blocks instead.
### Lists
Standard Markdown list rules apply, but as Doxygen will collapse white space on output, combined with the use of long lines, it's a good idea to include an extra new line between long list items to assist future editing.
## Special cases
The following can be used in \\fish blocks to render some fish scenarios. These are mostly used in the tutorial when an interactive situation needs to be displayed.
### Custom formatting tags
```html
<u>: <u>These words are underlined.</u>
<s>: auto<s>suggestion</s>.
<m>: <m>Matched</m> items, such as tab completions.
<sm>: Matched items <sm>searched</sm> for, like grep results.
<bs>: Render the contents with a preceding backslash. Useful when presenting output.
<eror>: <eror>This would be shown as an error. (Note eror, not error).</eror>
<asis>: <asis>This text will not be parsed for fish markup.</asis>
<outp>: <outp>This would be rendered as command/script output.</outp>
{{ and }}: Required when wanting curly braces in regular expression example.
```
### Prompts and cursors
```html
>_: Display a basic prompt.
~>_: Display a prompt with a the home directory as the current working directory.
___ (3 underscores): Display a cursor.
```
### Keyboard shortcuts: @key{} and @cursor_key{}
Graphical keyboard shortcuts can be defined using the following special commands. These allow for the different text requirements across the html and man pages. The HTML uses CSS to create a keyboard style, whereas the man page would display the key as text.
- `@key{lable}`
Displays a key with a purely textual lable, such as: 'Tab', 'Page Up', 'Page Down', 'Home', 'End', 'F1', 'F19' and so on.
- `@key{modifier,lable}`
Displays a keystroke requiring the use of a 'modifier' key, such as 'Control-A', 'Shift-X', 'Alt-Tab' etc.
- `@key{modifier,entity,lable}`
Displays a keystroke using a graphical entity, such as an arrow symbol for cursor key based shortcuts.
- `@cursor_key{entity,lable}`
A special case for cursor keys, when no modifier is needed. i.e. `@cursor_key{&uarr;,up}` for the up arrow key.
Some useful Unicode/HTML5 entities:
- Up arrow: `&uarr;`
- Down arrow: `&darr;`
- Left arrow: `&larr;`
- Right arrow `&rarr;`
- Shift: `&#8679;`
- Tab: `&rarrb;`
- Mac option: `&#8997;`
- Mac command: `&#8984;`
## Notes
### Doxygen
Tested on:
- Ubuntu 14.04 with Doxygen 1.8.8, built from [GitHub source](https://github.com/doxygen/doxygen.git).
- CentOS 6.5 with Doxygen 1.8.8, built from [GitHub source](https://github.com/doxygen/doxygen.git).
- Mac OS X 10.9 with Homebrew install Doxygen 1.8.7 and 1.8.8.
Graphviz was also installed in all the above testing.
Doxygen 1.8.6 and lower do not have the \\htmlonly[block] directive which fixes a multitude of problems in the rendering of the docs. In Doxygen 1.8.7 the list of understood HTML entities was greatly increased. I tested earlier versions and many little issues returned.
As fish ships with pre-built documentation, I don't see this as an issue.
### Updated Configure/Makefile
- Tested on Ubuntu 14.04, CentOS 6.5 and Mac OS X 10.9.
- Makefile has GNU/BSD sed/grep detection.
### HTML output
- The output HTML is HTML5 compliant, but should quickly and elegantly degrade on older browsers without losing basic structure.
- The CSS avoids the use or browser specific extensions (i.e. -webkit, -moz etc), using the W3C HTML5 standard instead.
- It's been tested in Chrome 37.0 and Firefox 32.0 on Mac OS X 10.9 (+Safari 7), Windows 8.1 (+Internet Explorer 11) and Ubuntu Desktop 14.04.
- My assumption is basically that if someone cares enough to want to install fish, they'll be keeping a browser current.
### Man page output
- Tested on Ubuntu 14.04, CentOS 6.5 and Mac OS X 10.9.
- Output is substantially cleaner.
- Tested in cat, less, more and most pagers using the following fish script:
```
function manTest --description 'Test manpage' --argument page
set -l pager
for i in $argv
switch $i
case "-l"
set pager -P '/usr/bin/less -is'
case "-m"
set pager -P '/usr/bin/more -s'
case "-c"
set pager -P '/bin/cat'
end
end
man $pager ~/Projects/OpenSource/fish-shell/share/man/man1/$page.1
end
# Assumes 'most' is the default system pager.
# NOT PORTABLE! Paths would be need to be updated on other systems.
```
#### Author: Mark Griffiths [@GitHub](https://github.com/MarkGriffiths)

80
doc_src/abbr.txt Normal file
View File

@@ -0,0 +1,80 @@
\section abbr abbr - manage fish abbreviations
\subsection abbr-synopsis Synopsis
\fish{synopsis}
abbr --add [SCOPE] WORD EXPANSION
abbr --erase word
abbr --rename [SCOPE] OLD_WORD NEW_WORD
abbr --show
abbr --list
\endfish
\subsection abbr-description Description
`abbr` manages abbreviations - user-defined words that are replaced with longer phrases after they are entered.
For example, a frequently-run command like `git checkout` can be abbreviated to `gco`. After entering `gco` and pressing @key{Space} or @key{Enter}, the full text `git checkout` will appear in the command line.
\subsection abbr-options Options
The following options are available:
- `-a WORD EXPANSION` or `--add WORD EXPANSION` Adds a new abbreviation, causing WORD to be expanded to PHRASE.
- `-r OLD_WORD NEW_WORD` or `--rename OLD_WORD NEW_WORD` Renames an abbreviation, from OLD_WORD to NEW_WORD.
- `-s` or `--show` Show all abbreviations in a manner suitable for export and import.
- `-l` or `--list` Lists all abbreviated words.
- `-e WORD` or `--erase WORD` Erase the abbreviation WORD.
In addition, when adding abbreviations:
- `-g` or `--global` to use a global variable.
- `-U` or `--universal` to use a universal variable (default).
See the "Internals" section for more on them.
\subsection abbr-example Examples
\fish
abbr -a -g gco git checkout
\endfish
Add a new abbreviation where `gco` will be replaced with `git checkout` global to the current shell. This abbreviation will not be automatically visible to other shells unless the same command is run in those shells (such as when executing the commands in config.fish).
\fish
abbr -a -U l less
\endfish
Add a new abbreviation where `l` will be replaced with `less` universal so all shells. Note that you omit the `-U` since it is the default.
\fish
abbr -r gco gch
\endfish
Renames an existing abbreviation from `gco` to `gch`.
\fish
abbr -e gco
\endfish
Erase the `gco` abbreviation.
\fish
ssh another_host abbr -s | source
\endfish
Import the abbreviations defined on another_host over SSH.
\subsection abbr-internals Internals
Each abbreviation is stored in its own global or universal variable. The name consists of the prefix `_fish_abbr_` followed by the WORD after being transformed by `string escape style=var`. The WORD cannot contain a space but all other characters are legal.
Defining an abbreviation with global scope is slightly faster than universal scope (which is the default). But in general you'll only want to use the global scope when defining abbreviations in a startup script like `~/.config/fish/config.fish` like this:
\fish
if status --is-interactive
abbr --add --global first 'echo my first abbreviation'
abbr --add --global second 'echo my second abbreviation'
abbr --add --global gco git checkout
# etcetera
end
\endfish
You can create abbreviations interactively and they will be visible to other fish sessions if you use the `-U` or `--universal` flag or don't explicitly specify the scope and the abbreviation isn't already defined with global scope. If you want it to be visible only to the current shell use the `-g` or `--global` flag.

41
doc_src/alias.txt Normal file
View File

@@ -0,0 +1,41 @@
\section alias alias - create a function
\subsection alias-synopsis Synopsis
\fish{synopsis}
alias
alias [OPTIONS] NAME DEFINITION
alias [OPTIONS] NAME=DEFINITION
\endfish
\subsection alias-description Description
`alias` is a simple wrapper for the `function` builtin, which creates a function wrapping a command. It has similar syntax to POSIX shell `alias`. For other uses, it is recommended to define a <a href='#function'>function</a>.
`fish` marks functions that have been created by `alias` by including the command used to create them in the function description. You can list `alias`-created functions by running `alias` without arguments. They must be erased using `functions -e`.
- `NAME` is the name of the alias
- `DEFINITION` is the actual command to execute. The string `$argv` will be appended.
You cannot create an alias to a function with the same name. Note that spaces need to be escaped in the call to `alias` just like at the command line, _even inside quoted parts_.
The following options are available:
- `-h` or `--help` displays help about using this command.
- `-s` or `--save` Automatically save the function created by the alias into your fish configuration directory using <a href='#funcsave'>funcsave</a>.
\subsection alias-example Example
The following code will create `rmi`, which runs `rm` with additional arguments on every invocation.
\fish
alias rmi="rm -i"
# This is equivalent to entering the following function:
function rmi --wraps rm --description 'alias rmi=rm -i'
rm -i $argv
end
# This needs to have the spaces escaped or "Chrome.app..." will be seen as an argument to "/Applications/Google":
alias chrome='/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome banana'
\endfish

23
doc_src/and.txt Normal file
View File

@@ -0,0 +1,23 @@
\section and and - conditionally execute a command
\subsection and-synopsis Synopsis
\fish{synopsis}
COMMAND1; and COMMAND2
\endfish
\subsection and-description Description
`and` is used to execute a command if the previous command was successful (returned a status of 0).
`and` statements may be used as part of the condition in an <a href="#if">`if`</a> or <a href="#while">`while`</a> block. See the documentation for <a href="#if">`if`</a> and <a href="#while">`while`</a> for examples.
`and` does not change the current exit status itself, but the command it runs most likely will. The exit status of the last foreground command to exit can always be accessed using the <a href="index.html#variables-status">$status</a> variable.
\subsection and-example Example
The following code runs the `make` command to build a program. If the build succeeds, `make`'s exit status is 0, and the program is installed. If either step fails, the exit status is 1, and `make clean` is run, which removes the files created by the build process.
\fish
make; and make install; or make clean
\endfish

131
doc_src/argparse.txt Normal file
View File

@@ -0,0 +1,131 @@
\section argparse argparse - parse options passed to a fish script or function
\subsection argparse-synopsis Synopsis
\fish{synopsis}
argparse [OPTIONS] OPTION_SPEC... -- [ARG...]
\endfish
\subsection argparse-description Description
This command makes it easy for fish scripts and functions to handle arguments in a manner 100% identical to how fish builtin commands handle their arguments. You pass a sequence of arguments that define the options recognized, followed by a literal `--`, then the arguments to be parsed (which might also include a literal `--`). More on this in the <a href="#argparse-usage">usage</a> section below.
Each OPTION_SPEC can be written in the domain specific language <a href="#argparse-option-specs">described below</a> or created using the companion <a href="#fish-opt">`fish_opt`</a> command. All OPTION_SPECs must appear after any argparse flags and before the `--` that separates them from the arguments to be parsed.
Each option that is seen in the ARG list will result in a var name of the form `_flag_X`, where `X` is the short flag letter and the long flag name. The OPTION_SPEC always requires a short flag even if it can't be used. So there will always be `_flag_X` var set using the short flag letter if the corresponding short or long flag is seen. The long flag name var (e.g., `_flag_help`) will only be defined, obviously, if the OPTION_SPEC includes a long flag name.
For example `_flag_h` and `_flag_help` if `-h` or `--help` is seen. The var will be set with local scope (i.e., as if the script had done `set -l _flag_X`). If the flag is a boolean (that is, does not have an associated value) the values are the short and long flags seen. If the option is not a boolean flag the values will be zero or more values corresponding to the values collected when the ARG list is processed. If the flag was not seen the flag var will not be set.
\subsection argparse-options Options
The following `argparse` options are available. They must appear before all OPTION_SPECs:
- `-n` or `--name` is the command name to insert into any error messages. If you don't provide this value `argparse` will be used.
- `-x` or `--exclusive` should be followed by a comma separated list of short of long options that are mutually exclusive. You can use this option more than once to define multiple sets of mutually exclusive options.
- `-N` or `--min-args` is followed by an integer that defines the minimum number of acceptable non-option arguments. The default is zero.
- `-X` or `--max-args` is followed by an integer that defines the maximum number of acceptable non-option arguments. The default is infinity.
- `-s` or `--stop-nonopt` causes scanning the arguments to stop as soon as the first non-option argument is seen. Using this arg is equivalent to calling the C function `getopt_long()` with the short options starting with a `+` symbol. This is sometimes known as "POSIXLY CORRECT". If this flag is not used then arguments are reordered (i.e., permuted) so that all non-option arguments are moved after option arguments. This mode has several uses but the main one is to implement a command that has subcommands.
- `-h` or `--help` displays help about using this command.
\subsection argparse-usage Usage
Using this command involves passing two sets of arguments separated by `--`. The first set consists of one or more option specifications (`OPTION_SPEC` above) and options that modify the behavior of `argparse`. These must be listed before the `--` argument. The second set are the arguments to be parsed in accordance with the option specifications. They occur after the `--` argument and can be empty. More about this below but here is a simple example that might be used in a function named `my_function`:
\fish
argparse --name=my_function 'h/help' 'n/name=' -- $argv
or return
\endfish
If `$argv` is empty then there is nothing to parse and `argparse` returns zero to indicate success. If `$argv` is not empty then it is checked for flags `-h`, `--help`, `-n` and `--name`. If they are found they are removed from the arguments and local variables (more on this <a href="argparse-local-variables">below</a>) are set so the script can determine which options were seen. Assuming `$argv` doesn't have any errors, such as a missing mandatory value for an option, then `argparse` exits with status zero. Otherwise it writes appropriate error messages to stderr and exits with a status of one.
The `--` argument is required. You do not have to include any arguments after the `--` but you must include the `--`. For example, this is acceptable:
\fish
set -l argv
argparse 'h/help' 'n/name' -- $argv
\endfish
But this is not:
\fish
set -l argv
argparse 'h/help' 'n/name' $argv
\endfish
The first `--` seen is what allows the `argparse` command to reliably separate the option specifications from the command arguments.
\subsection argparse-option-specs Option Specifications
Each option specification is a string composed of
- A short flag letter (which is mandatory). It must be an alphanumeric or "#". The "#" character is special and means that a flag of the form `-123` is valid. The short flag "#" must be followed by "-" (since the short name isn't otherwise valid since `_flag_#` is not a valid var name) and must be followed by a long flag name with no modifiers.
- A `/` if the short flag can be used by someone invoking your command else `-` if it should not be exposed as a valid short flag. If there is no long flag name these characters should be omitted. You can also specify a '#' to indicate the short and long flag names can be used and the value can be specified as an implicit int; i.e., a flag of the form `-NNN`.
- A long flag name which is optional. If not present then only the short flag letter can be used.
- Nothing if the flag is a boolean that takes no argument or is an implicit int flag, else
- `=` if it requires a value and only the last instance of the flag is saved, else
- `=?` it takes an optional value and only the last instance of the flag is saved, else
- `=+` if it requires a value and each instance of the flag is saved.
- Optionally a `!` followed by fish script to validate the value. Typically this will be a function to run. If the return status is zero the value for the flag is valid. If non-zero the value is invalid. Any error messages should be written to stdout (not stderr). See the section on <a href="#arparse-validation">Flag Value Validation</a> for more information.
See the <a href="#fish-opt">`fish_opt`</a> command for a friendlier but more verbose way to create option specifications.
In the following examples if a flag is not seen when parsing the arguments then the corresponding _flag_X var(s) will not be set.
\subsection argparse-validation Flag Value Validation
It is common to want to validate the the value provided for an option satisfies some criteria. For example, that it is a valid integer within a specific range. You can always do this after `argparse` returns but you can also request that `argparse` perform the validation by executing arbitrary fish script. To do so simply append an `!` (exclamation-mark) then the fish script to be run. When that code is executed three vars will be defined:
- `_argparse_cmd` will be set to the value of the value of the `argparse --name` value.
- `_flag_name` will be set to the short or long flag that being processed.
- `_flag_value` will be set to the value associated with the flag being processed.
If you do this via a function it should be defined with the `--no-scope-shadowing` flag. Otherwise it won't have access to those variables.
The script should write any error messages to stdout, not stderr. It should return a status of zero if the flag value is valid otherwise a non-zero status to indicate it is invalid.
Fish ships with a `_validate_int` function that accepts a `--min` and `--max` flag. Let's say your command accepts a `-m` or `--max` flag and the minimum allowable value is zero and the maximum is 5. You would define the option like this: `m/max=!_validate_int --min 0 --max 5`. The default if you just call `_validate_int` without those flags is to simply check that the value is a valid integer with no limits on the min or max value allowed.
\subsection argparse-optspec-examples Example OPTION_SPECs
Some OPTION_SPEC examples:
- `h/help` means that both `-h` and `--help` are valid. The flag is a boolean and can be used more than once. If either flag is used then `_flag_h` and `_flag_help` will be set to the count of how many times either flag was seen.
- `h-help` means that only `--help` is valid. The flag is a boolean and can be used more than once. If the long flag is used then `_flag_h` and `_flag_help` will be set to the count of how many times the long flag was seen.
- `n/name=` means that both `-n` and `--name` are valid. It requires a value and can be used at most once. If the flag is seen then `_flag_n` and `_flag_name` will be set with the single mandatory value associated with the flag.
- `n/name=?` means that both `-n` and `--name` are valid. It accepts an optional value and can be used at most once. If the flag is seen then `_flag_n` and `_flag_name` will be set with the value associated with the flag if one was provided else it will be set with no values.
- `n-name=+` means that only `--name` is valid. It requires a value and can be used more than once. If the flag is seen then `_flag_n` and `_flag_name` will be set with the values associated with each occurrence of the flag.
- `x` means that only `-x` is valid. It is a boolean can can be used more than once. If it is seen then `_flag_x` will be set to the count of how many times the flag was seen.
- `x=`, `x=?`, and `x=+` are similar to the n/name examples above but there is no long flag alternative to the short flag `-x`.
- `x-` is not valid since there is no long flag name and therefore the short flag, `-x`, has to be usable.
- `#-max` means that flags matching the regex "^--?\d+$" are valid. When seen they are assigned to the variable `_flag_max`. This allows any valid positive or negative integer to be specified by prefixing it with a single "-". Many commands support this idiom. For example `head -3 /a/file` to emit only the first three lines of /a/file.
- `n#max` means that flags matching the regex "^--?\d+$" are valid. When seen they are assigned to the variables `_flag_n` and `_flag_max`. This allows any valid positive or negative integer to be specified by prefixing it with a single "-". Many commands support this idiom. For example `head -3 /a/file` to emit only the first three lines of /a/file. You can also specify the value using either flag: `-n NNN` or `--max NNN` in this example.
After parsing the arguments the `argv` var is set with local scope to any values not already consumed during flag processing. If there are not unbound values the var is set but `count $argv` will be zero.
If an error occurs during argparse processing it will exit with a non-zero status and print error messages to stderr.
\subsection argparse-notes Notes
Prior to the addition of this builtin command in the 2.7.0 release there were two main ways to parse the arguments passed to a fish script or function. One way was to use the OS provided `getopt` command. The problem with that is that the GNU and BSD implementations are not compatible. Which makes using that external command difficult other than in trivial situations. The other way is to iterate over `$argv` and use the fish `switch` statement to decide how to handle the argument. That, however, involves a huge amount of boilerplate code. It is also borderline impossible to implement the same behavior as builtin commands.

Some files were not shown because too many files have changed in this diff Show More