fish home | User documentation | API documentation | Screenshots

1.23.0

Fish 1.23.0 is the first release in a very long time and brings many new and exciting features to the table.

Case insensitive completions

If, when performing tab completion, no exact matches are found, fish uses case insensitive matching to find alternative matches.

Improved multiline editing

The up and down arrows now move up and down in the text when editing a multiline command. The still retain their meaning of performing forward/backward history search when used at the top/bottom of the command, though.

1.22.0

Fish 1.22.0 features a large number of new features. These are the most important ones:

Multiline editing

Fish now supports the editing of commands that span multiple lines of input. When pressing the enter key while editing an unterminated block command, such as a for loop, the enter key will only insert a newline, and fish will not attempt to execute the unfinished command. It is also possible to enter a newline that will not cause programexecution by either backslash escaping it or by using Alt-enter.

The new multinline editing also comes with automatic indentation built in.

Decreased memory usage

The memory usage in fish has been significantly decreased. This is mainly caused by two improvements. The first one is that automatically loaded functions and completions are now automatically unloaded when they aren't used. The second one is that instead of loading the history file into memory, fish now uses the mmap function to map the file contents into memory. the advantage of this method of accessing the history file is that a single copy of the history can be shared by all running fish instances.

Incremental updates of the history file

The history file is occasionally saved and reloaded while using fish. This means that in case of a crash or a power failure, the entire fish history will not be lost. It also means that when running multiple simultaneous fish sessions, commands used in one session may be accessed through the history search commands from the other running shells. The history implementation always makes sure that commands entered in the current session are always last in the history list.

Altered syntax for recursive wildcard matching

The '**' wildcard can now be used to match either files or directories. This makes the wildcard more consistent with '*'. To get the old behaviour, simply use '**/'.

Changed directory layout for configuration files

All fish configuration files now reside in $XDG_CONFIG_HOME/fish. If $XDG_CONFIG_HOME is unset, it defaults to ~/.config. This change makes fish conform better with freedesktop.org guidelines, reduces file clutter in the users home directory and means that there is a single location for all user configuration files. The names of various configuration files has also been changed in order to make them more consistent.

When starting an interactive session of fish 1.22.0 for the first time, fish will automatically move the old configuration files to their new location.

1.21.0

The only major syntactical change in fish 1.21.0 is support for dynamically loading shellscript functions when needed. The idea is very simple: To add a shellscript function named foo, simply create the file foo.fish somewhere in the search path defined by the environment variable $fish_function_path. The default value for this variable contains ~/.fish.d/functions, /etc/fish.d/functions and $PREFIX/share/fish/functions, meant to be used for user specific functions, functions installed by the sysadmin, and functions included with the shell itself, respectively. There are some noteworthy details about the implementation of functions:

Fish 1.21.0 also contains advanced new competions for the svn and cvs commands, featuring advanced switch dependencies.

1.20.0

Fish version 1.20.0 contains a new syntax for the short-circut commands 'and' and 'or':

make; and make install; or make clean
	  
will make the program, and if that suceeds, the program will be installed. If either of the previous commands fail, the directory will be cleaned.

1.20.0 is also the first version of fish with i18n support, i.e. support for translations and other localization support. This version only contains translations to swedish, but more translations will hopefully be coming soon. If you are interested in translating fish, see these notes on how to get started.

Version 1.18.0

Fish version 1.18.0 contains no major new features. The most significant change is how wildcards that result in no matches are handled. Just like in csh, if no wildcarded arguments produce matches, the command will not to be executed. 1.18.0 also contains several bugfixes, most notably fixes for installing the configuration files into a location other than /etc.

Version 1.17.0

Fish version 1.17.0 contains two major new features.

Recursive wildcard matching

The ** wildcard can be used to match a directory and all of its subdirectories. For example, given the directories

doc
doc/html
user_doc
user_doc/html
	  
the string **l will match doc/html and user_doc/html. The ** wildcard will only match directory names, not file names. The recursive wildcard matching feature has been borrowed from zsh, but the ability to mix recursive wildcards with other tokens, such as user**/ is unique to fish.

Posix-like double-quotes

Posix-compatible shells have always made a distinction between single and double quotes, i.e. "" vs. '', where double quoted strings are subject to variable expantion and command substitution. In order to make the language smaller and simpler, fish has ignored this difference. Another reason for ignoring this difference is that Posix shells often need to make sure that a variable won't be tokenized on spaces by using code like "$foo", but fish does not tokenize variables on whitespace, so this has not been an issue in fish.

A large number of users have complained about this difference, and preferring the Posix syntax, since it allows for easier concatenation of strings with variable contents. There are also some situations where the fish method of handling variable expantion is not ideal. Simply writing $foo will expand $foo to the same number of arguments as there are array elements in the $foo variable. A non-array variable in this context is the same thing as an array with one element, and an undefined variable is the same as a variable with zero elements. This is very often convenient, but in some cases, it would be better if the expantion always resulted in exactly one argument. One example of such a situation is the test command. The code test $LANG = en_US might give unexpected results if $LANG is undefined, or if it is defined to be an array. Because of this, the syntax "$LANG", as seen in Posix, is now supported in fish. A variable expantion within double quotes will always expand to exactly one argument. If the variable does not exist, the argument will be the empty string, if the variable is an array, the elements will be separated by spaces.

Version 1.16.0

Fish version 1.16.0 contains several major new features. Here is a summary:

Event triggers

Fish 1.16.0 features a generic event delivery framework, which can be used to run a set of commands on a specified signal, on a variable update or on job exit. Future Fish versions will probably copntain additional event triggers.

A simple example of how to write an event handler, namely printing a notification message every time the variable $some_var changes:

function some_function --on-variable some_var
	echo \$some_var changed to $some_var
end
	  
For more information on how to define event handlers, see the function documentation.

Process substitution

Posix shells feature a syntax that is a mix between command substitution and piping, called process substitution. It is used to send the output of a command into the calling command, much like command substitution, but with the difference that the output is not sent through commandline arguments but through a named pipe, with the filename of the named pipe sent as an argument to the calling program. I do not wish to add such a feature to fish, since I feel that it is far to similar to already existing fish concepts to warrant inclusion. But there are still many use-cases where it might be desirable to have some form of process substitution workalike. Therefore, fish 1.16.0 contains a psub shellscript function, which when combined with a regular command substitution provides the same functionality.

bash syntax
diff <(sort foo.txt) <(sort bar.txt)
fish syntax
diff (sort foo.txt|psub) (sort bar.txt|psub)

The vital difference is that the fish implementation is done entirely as a shellscript function. It is also worth noting that the bash syntax is whitespace sensitive, < (...) is not interpreted as a process substitution.

Improved pipes

When a command outputs large amounts of information, like make often does on failiure, it is convenient to use a pager to search out the useful parts. When the output is directed to stdout, this is not a problem, since you can use a pipe to page the input through your pager of choice. But such output is often written to another file descriptor, such as standard error. For this reason, fish now allows you to specify which file descriptor should be used to send output to a pipe. The syntax is the same as the one used for regular io redirection:

		make fish 2>|less
	  

ulimit and umask

Two builtin functions from bash have been implemented in fish, ulimit and umask. ulimit is a fish builtin function, while umask has been implemented as a shellscript function, in order to keep the shell as small as possible. The functions behave identically to the bash versions, except they support GNU-style long switches, and ulimit does not support some

Version 1.15.0

Fish version 1.15.0 contains several smaller changes that to make fish more consistent and makes fish handle rare corner cases correctly. The largest internal changes come from attempts to better deal with concurrency issues and error handling.

Changes to the language

Two changes to how variable scope is resolved have taken place.

The first change is that if a variable is set with an explicit scope, and another variable with the same name already exists in a different scope, the second variables value will not change. The reasoning behind this is that it is often desirable to use variable in a function scope and be sure that global variables with the same name won't be accidentally overwritten.

For an example of what this change means, consider the code

set foo global
begin
	set -l foo local
end
echo $foo
	 
The output in previous versions of fish would have been an empty line, since the local foo variable would have overwritten the global foo, and once the local foo went out of scope, there would be no variable called foo left. The new behaviour is to output global, since the global value for foo is not overwritten.

The second change is to the default scope of variables. Previously, when creating a new variable without setting the scope, the innermost block scope was used. The new rule is that the innermost function scope is used instead. (Or global scope if not in function scope.

To demonstrate this change, consider the following code:

function foo
	begin
		set bar 'defined'
		echo Inner function scope, \$bar is $bar
	end
	echo Outer function scope, \$bar is $bar
end

foo
echo External scope, \$bar is $bar
	  
The old behaviour would be to print
Inner function scope, $bar is defined
Outer function scope, $bar is
External scope, $bar is
	  
but with the new behaviour, the output is
Inner function scope, $bar is defined
Outer function scope, $bar is defined
External scope, $bar is
	  

It is now possible to create variables which have no value. Previously, when attempting to create such values, the value was changed to the empty string. This may seem to be the same things, but the empty string as an argument string of length 0, it will be sent to subprograms as an argument, whereas an empty variable is nothing at all. This difference is important in many situations, and the previous syntax lead to awkward syntax problems in some situations.

The begin and else commands no longer require a semicolon before the next command.

Changes to keybinding parsing

The keybinding parser has gotten several improvements.

Other changes

Version 1.14.0

Universal variables

The main new feature in this release is the addition of universal variables. Universal variables are shared between all running fish instances of a given user. They are also automatically saved on exit. Universal variables have mainly two uses:

To define a universal variable, use the -U or --universal switch for set, as in set -U EDITOR ed.

To see universal variables in action, start two fish sessions side by side, and issue the following command in one of them set fish_color_cwd blue. Since fish_color_cwd is a universal variable, the color of the current working directory listing in the prompt will instantly change to blue on both terminals.

New builtins and functions

Several new builtins have been added in this release. Most significant are the or and and builtins. These commands operate on the two commands directly following them. The first one is executed, and on sucess (and) or failiure (or), the second command is also executed. This allows much terser error handling than using conditional blocks.

		#If test fails, call exit
		or test $status = 0; exit 1

		#If setup suceeds, call do_stuff
		and setup; do_stuff
	  
Multiple or and and commands can be stacked together, resulting in so called 'reverse Polish notation' semantics.

The not and begin builtins are convenience functions. not negates the exit status of the command following it, and begin opens up a new block, which makes begin equivalent to if true.

The type shellscript for determining the type of a command is identical to the Posix builtin with the same name, except it also supports GNU style long options.

Other improvements

Version 1.13.0

There are quite a few new features in this release, here is a rundown of a few of them:

IO redirection improvements

Fish now allows you to redirect IO from blocks and functions without any restrictions.

		# Read one line at a time from a file in a loop
		cat foo.txt | while true; read line; ...; end

		# Pipe output of function into another function
		function foo; ...; end
		function bar; ...; end
		foo|bar

		# Pipe output of block through another process
		for i in *; ...; end | grep ... 	
	  

Most of these have always been possible to do in other shells, but as far as I know, no other shell allows you to have multiple functions in the same job (Piping through aliases is possible, but aliases are very limited).

Improved command completions

Users of systems with deb- or rpm-based package management can now complete package names using apt-get, rpm and yum.

Several new commands have gotten new or updated command specific completions. These include diff, top, kill, ps, apropos and wget.

It is now much easier to specify that some completions should only be used when some special criteria is met, such as the presence of a specified switch. Among the command-specific completions that take advantage of this are:

Improved performance

Fish 1.13.0 uses approximately half the memory and half the CPU time at start up compared to previous releases. Most of this improvement comes from the fact that fish no longer loads the entire database of command-specific completions on startup. Completions for a command are instead loaded whenever the user first uses a command.

Completing command names is also faster, since fewer files are stat:ed, and the command description lookup implementation is much faster.

Other improvements

The commands pushd and popd, well known to users of bash and other shells, are now available in fish. Also, a directory history, accessible through the nextd, prevd and dirh commands have been introduced. These commands are all implemented as shellscript functions, not as builtins, so as not to bloat the core shell.

It is now possible to erase elements from an array. Use the command set -e foo[1 3 7] to erase the first, third and seventh element of the array foo.

Keyboard shortcuts the move or erase one word now consider any non-alphanumeric characters to be word-delemiters.

Fish no longer forks when running subshells. This means that fish never ever uses a subprocess to parse any of its commands or execute builtins, resulting in that builtins and shellscript functions that change the state of fish, such as set, can be safely used in subshells.

Specifying arguments containg characters not on a standard keyboard is now much easier, since fish supports the standard C escape sequences for octal and hexadecimal ascii characters and hexadecimal unicode characters. For example, to write out an ellipsis to the screen, simply write echo \u2026.

This page was last updated on October 3, 2005. If you have comments on this page, please contact the webmaster.