|
|
Subscribe / Log in / New account

Fish shell 2.1

By Nathan Willis
November 27, 2013

Version 2.1 of the fish shell has been released, complete with a string of new features and fixes sure to hook users.

We first looked at fish all the way back in 2005. In keeping with longstanding tradition for shell-naming, fish is an abbreviation, for "friendly interactive shell." In the early days, fish's friendliness was visible through features like automatic syntax highlighting, feature-rich tab-completion behavior, and context-aware help. In subsequent years, it is clear that fish has had an influence on other shells, as older projects like Bash have added and enhanced their own takes on some of those features.

[The fish shell]

Naturally, fish itself has continued to evolve over the same time period, too. The project still advertises its friendlier implementations of well-known shell features, however—among them syntax highlighting and tab completion, plus command history, prompts, and even common built-in commands like cd. In addition, there are unique features like a web-based configuration tool (which runs on a local Python-powered HTTP server).

The fish source code is hosted at GitHub, while the project's web site offers binary packages for a wide range of Linux distributions, Windows, and Mac OS X. Version 2.1.0, the latest release, was released on October 28. The release notes page provides an overview of the changes in 2.1 and a handful of previous releases, though not for the entire history of the project.

Less is more

Many shells offer tab-completion for commands and filenames, so that users only need to type enough letters to uniquely identify what follows—and, when there are multiple possibilities, the shell usually writes them to the terminal window to help. Fish takes this concept considerably further. First, its tab-completion feature expands not only commands and filenames, but usernames, environment variables, job IDs, and process names. The filename-completion also supports strings with wildcard characters; so typing "b??t" would correctly bring up "bait" as a tab-completion match.

Second, fish includes several command-specific completions, allowing manpage completion for man and whatis, Makefile target completion for make, mount-point completion for mount, package-name completion for apt-get, rpm, and yum, hostname completion for ssh, and username completion for su. For other programs, fish offers tab-completion for each program's command-line switches and options. Each of the program-specific completions is tailor-made for the specific command; for example, ssh hostname completion draws on the list of hosts in the user's known_hosts file. It is also possible to write custom completion options for any command.

The 2.1 release adds another factor to fish's tab-completion effort: fuzzy matching of filenames and commands. The shell first attempts to find a prefix match (that is, "fo" matches "foo"), but if it does not find one it will look for substring matches in the middle and at the end of filenames, and, as a last resort, it will look for true fuzzy matches. Thus, typing "far" could match "foobar," if there are no better matches.

On the other hand, tab completion requires the user to actually hit the tab key; those who find even that effort to be too strenuous will be relieved that fish also makes a best-guess attempt at predicting what the user will type next, in the form of autosuggestions that appear after the text cursor while the user is typing. To accept an autosuggestion, one only needs to hit the right-arrow key on the keyboard. The upshot is predictive typing not unlike the text-prediction on mobile phones or in web browser location bars, and like those autosuggestions, fish provides suggestions that are weighted to the most-recently-typed input, rather than simple string matching. Furthermore, while tab completion works one token at a time, fish's autosuggestions can match entire commands, and are thus—potentially—faster.

Fish also features a number of other expansions, such as numeric ranges (e.g., [1..9]), sets (e.g., {a,b,d}), and process IDs (using the percent sign %). The PID expansion will match process names and expand them to the appropriate PID, so typing kill %jav will match a running java process, allowing the user to kill it without looking up the PID first. A change in fish 2.1 is that % by itself expands to the last command backgrounded, so fg % will put the last backgrounded process back into the foreground.

Going off script

Fish is scriptable, and in most cases uses familiar syntax, but here too it adds its own twist on the feature. There are some special environment variables, the most notable of which is status, which stores the exit status of the last process. In addition to 0 for success and 1 for an error, fish will attempt to provide more information with some specific values that begin with 12. An status value of 126, for example, means that the last command exited with an error because the filename provided was not executable; 127 means that no matching command or function was found. A process that exits with a signal will set status to 128N, where N is the signal number. In these cases, of course, the value of the status variable is treated like a string, which could trip up shell scripts if not handled properly.

Fish also treats the shell history differently than many of its competitors. First, there is a history variable that is an array of the previous commands; among other possibilities, that makes the history available to scripts. But the built-in history command is different, too. Simply hitting the up arrow will step back through previous commands (as it does in other shells), but typing a few letters and then hitting the up arrow performs a history search for the typed characters.

For example, typing make followed by the up arrow will let the user step back through all the previous matches against make. Holding down the Alt key while using the up and down arrows allows the user to search only for the word beneath the text cursor; that could be useful for narrowing down a search with a lot of matches or particularly long commands. Users can also delete items from the history, and can prevent any command from being recorded in the history (by preceding the command with a space character).

The fish project also prides itself on its extensive built-in help, which certainly could come in handy for those who find all of the differences with Bash and other shells daunting. The documentation is provided as both manpages and HTML, and all of fish's built-in commands support the -h switch.

Looking good

Fish's syntax highlighting is another area where the project attempts to provide more functionality than other shells. Although many standard Unix commands are available with their own color-coding (ls perhaps being the most popular), fish color-codes all commands as the user types. Commands, filenames, autosuggestions, tab-completion matches, quoted strings, parameters, comments, and error messages are all colored differently. Color overload is perhaps an understandable fear, but the color values are user-selectable.

[fish web configuration]

The best way to modify the color values is to use fish's web-based configuration tool. The tool is launched with fish_config, and starts up a web server running on localhost:8000, which it opens using the user's default browser. The configuration page lets users graphically select colors (foreground and background) for all of the syntax options, as well as whether each option is underlined. Most of the syntax options are used in the command line and output, but some (such as the current working directory) are also used in the shell prompt.

The shell prompt itself is also configurable within the web configuration tool; version 2.1 includes 14 presets, some of which are tailored toward specific use cases (there are two Git-specific prompts, for example). A right-side prompt (i.e., a prompt-like informational area that sits in the right-hand side of the command line), which is a feature also found in Zsh, is also supported. The configuration tool also lets the user browse through any functions and aliases defined in the current session, view the history array, and look at the environment variables.

Fish also supports many of the same configuration options expected by shell users, such as setting the terminal window title or setting a greeting message. There are a few differences, of course; for example, the fish equivalent to .bashrc is ~/.config/fish/config.fish, so it may take a few minutes of looking through the documentation to get up to speed. But on the whole, fish does a good job of adding its layer of friendliness onto the standard shell experience without introducing major disruptions to how users work. True, people with a significant standing investment in Bash scripts may not find migrating them to fish (or any other shell) an appealing prospect, but for more casual shell usage, it could be quite a good catch.


to post comments

Fish shell 2.1

Posted Nov 27, 2013 21:47 UTC (Wed) by dashesy (guest, #74652) [Link] (3 responses)

typing a few letters and then hitting the up arrow performs a history search for the typed characters.
This is a must have in any reasonable bashrc, I assign it to PgUp/PgDown, but arrows are good too:
bind '"\e[A"':history-search-backward
bind '"\e[B"':history-search-forward

Fish shell 2.1

Posted Nov 28, 2013 5:59 UTC (Thu) by tnoo (subscriber, #20427) [Link] (1 responses)

> This is a must have in any reasonable bashrc, I assign it to PgUp/PgDown, > but arrows are good too:

bash/readline already has standard Emacs key bindings for this: C-r, C-s

Fish shell 2.1

Posted Nov 28, 2013 12:22 UTC (Thu) by henrikb (guest, #58898) [Link]

That is not really the same thing. What the parent uses is more like ctrl-p in tcsh (something I have missed in bash btw, so thanks).

Fish shell 2.1

Posted Nov 29, 2013 9:17 UTC (Fri) by mgedmin (subscriber, #34497) [Link]

Or put the bindings in ~/.inputrc and enjoy them in all readline-using apps.

Fish shell 2.1

Posted Nov 28, 2013 8:06 UTC (Thu) by kleptog (subscriber, #1183) [Link] (2 responses)

Sounds like they've done some good work on input side. What I'm wondering is if there is a shell that has done something with the output side.

That is, a shell that captures the output of each command run and keeps them separate. So you can do things like:

- If the output is really large (for example locate found more than you expected) you can hide it/cut it short/remove it from your screen (rather than blowing away your scrollback buffer).

- You can do things like 'send output of last command to $CMD', easier than repeating the whole pipeline so far.

- Preserve the output as far as possible if the size of the terminal changes.

- Open output of last command in $EDITOR.

Is there a shell which has attempted any of this?

Fish shell 2.1

Posted Nov 29, 2013 12:09 UTC (Fri) by k8to (guest, #15413) [Link]

zsh has some features in this direction, but I'm not a zsh user so my knowledge is very vague.

If you use emacs

Posted Dec 9, 2013 12:59 UTC (Mon) by alex (subscriber, #1355) [Link]

eshell (which is a shell in elisp, rather than emacs access to the shell) can do an lot of this sort of thing. For example I have the following:
(eval-after-load "eshell"
  '(progn
     (defun my-eshell-kill-output ()
       "Really kill (not delete) all output from interpreter since last input.
Does not delete the prompt."
       (interactive)
       (save-excursion
         (goto-char (eshell-beginning-of-output))
         (insert "*** output flushed ***\n")
         (kill-region (point) (eshell-end-of-output))))

     (add-hook 'eshell-mode-hook #'(lambda ()
                                     (define-key eshell-mode-map (kbd "C-c C-o") 'my-eshell-kill-output)))))

Fish shell 2.1

Posted Nov 28, 2013 12:59 UTC (Thu) by mathstuf (subscriber, #69389) [Link] (2 responses)

Maybe it's because fish was last covered in 2005, but a lot of these features seem to also be in zsh. I think the only one I'm not familiar with is the status variable, but the rest is there, just not necessarily built-in.

Personally, the fuzzy match is probably the best feature of all of those covered here (`cd c/o/too/b/u<Tab>` -> `cd code/other/group-tools/group-browsers/uzbl`) and something I really miss when using bash.

Fish shell 2.1

Posted Dec 1, 2013 12:07 UTC (Sun) by zanchey (guest, #94250) [Link] (1 responses)

One of the aims (as described in the 2005 article!) of fish is to make features work well enough that they can be enabled, by default, for all users. There are very few features that are unique to fish; what (we think) is unique is that you don't have to go digging through menus, configuration files and documentation in order to benefit from them.

Fish shell 2.1

Posted Dec 17, 2013 10:30 UTC (Tue) by kov (subscriber, #7423) [Link]

This! I hate messing with configuration files and plugins and scripts. Having great features by default is what brought me to fish.

Fish shell 2.1

Posted Nov 28, 2013 19:57 UTC (Thu) by ballombe (subscriber, #9523) [Link] (2 responses)

> In subsequent years, it is clear that fish has had an influence on other shells, as older projects like Bash have added and enhanced their own takes on some of those features.

The article reads like the author has never heard of Zsh (one of the older shells). Most shell (especially bash) newer features were already in Zsh 10 years ago.

Fish shell 2.1

Posted Nov 29, 2013 3:08 UTC (Fri) by giraffedata (guest, #1954) [Link] (1 responses)

Also, most of the features described are in Bash.

I think every one of the command completion features except the one where you don't have to type tab has been in Bash since about 2005. Bash' command completion facility is fully programmable, so some of the more esoteric things, such as completing a username for 'su', require downloading additional software.

The commmand completion in Bash is really from the Readline library. I often write programs with command shells, and I always use Readline and get all that command completion stuff. I have to write code for the completions that make sense in the particular environment (e.g. the set of command verbs the program recognizes), but it's nice having TAB do what my fingers expect no matter what kind of prompt I'm facing.

Except for the friendly variable name, I thought the status codes for process terminations were standard Bourne shell. They do seem to be identical to Bash. What would be nice is if the information weren't delivered in code at all - have a variable for whose value is "terminated by signal" if the process was terminated by a signal, and another called $signal_number that tells you what class of signal it was.

As far as I know, nothing like the coloring described exists in Bash.

Fish shell 2.1

Posted Dec 1, 2013 12:27 UTC (Sun) by zanchey (guest, #94250) [Link]

$status is of course just a different (arguably better) name for $? from the POSIX shells and you are right about them being 'standard' values. The exit values for the cases of signal termination, inability to find a command and inability to execute a program are defined by SUS and there is no good reason for fish to use different values.

I think the assertion in the article that 0 is success and 1 is error is not quite precise enough; the convention across *nix AFAIK is that non-zero is error, and the exact error code will often have different meanings depending on the program being executed.

Fish shell 2.1

Posted Nov 30, 2013 15:03 UTC (Sat) by MatejLach (guest, #84942) [Link] (1 responses)

The fact that fish is non-compliant with POSIX is a huge problem for me.
Zsh can offer pretty much the same functionality, without breaking with POSIX.

Fish shell 2.1

Posted Dec 1, 2013 12:14 UTC (Sun) by zanchey (guest, #94250) [Link]

I thought too that when I first started using fish, and in fact I was going back to zsh daily at first, then once or twice a week, and then I realised it had been months!

You can still write your scripts in POSIX shells - the main pain point in existing scripts is those that expect to be sourced in. Popular tools such as virtualenv do now have fish equivalents, though.

One useful tip is that many programs expect $SHELL to be POSIX-compliant (or even bash compliant), so I generally leave my login shell as zsh and then exec fish from my .zshrc.

Fish shell 2.1

Posted Dec 1, 2013 12:31 UTC (Sun) by zanchey (guest, #94250) [Link]

I was just thinking the other day that it had been a while since fish was mentioned on LWN, and here we are!

I recommend the tutorial for those looking to quickly get up to speed on the precise differences between fish and more traditional shells: http://fishshell.com/docs/current/tutorial.html

Fish shell 2.1

Posted Dec 5, 2013 10:30 UTC (Thu) by moltonel (guest, #45207) [Link] (3 responses)

IMHO the killer feature of fish (that you'll never see in bash or zsh) is its sane syntax, substitutions, subshells. It was mentioned in the 2005 article but not in this one.

To (mis)quote Douglas Adams, other shells have not so much been designed as congealed. We've all learned that shells are quirky and full of gotchas. After a while we forget how ridiculous and annoying the syntax and sematics are, but they still trip users and programmers regularly. Ignoring POSIX compliance was arguably fish's best design decision.

Fish shell 2.1

Posted Dec 5, 2013 13:54 UTC (Thu) by mathstuf (subscriber, #69389) [Link] (2 responses)

Well, zsh is crazy enough that it might get a fish emulation option. I mean, it already has emulation for sh, bash, and csh[1].

While I do think that the fish syntax is better, I'd rather have POSIX compatibility at my fingertips at all times. I have enough things to context switch on anyways when using a computer, I don't need to add my shell's language to that list (and I do write `for` loops and other constructs at the prompt).

[1]http://www.acm.uiuc.edu/workshops/zsh/emulation.html

Fish shell 2.1

Posted Dec 6, 2013 11:58 UTC (Fri) by moltonel (guest, #45207) [Link] (1 responses)

Crazy indeed, why emulate a shell when you can run it ? You're only going to run scripts with it, so the original shell's nice interface is off-topic. If you're looking to reduce ressource usage, zsh is probably not a good starting point. I'd rather run the original than risk an emulation bug.

POSIX compatibility is good, since there are many scripts that are writen to this lowest common denominator (and many more which aim to be, but unknowingly use modern shell constructs). But POSIX "at your fingertips" ? Restricting yourself to just POSIX in an interactive session is pointless, I'm sure you use zsh constructs all the time.

Use the right tool for each job. Strict POSIX scripts are actually rarely needed. Don't be shy in setting your bangline to bash, zsh, fish, python, etc. Fair enough if you don't want to learn something new today, but don't get too settled in your ways ;)

> I mean, it already has emulation for sh, bash, and csh.

Your link says sh, *ksh* and csh. Emulating a shell that hasn't stoped evolving yet, such as bash or fish, would be even crazyer.

Fish shell 2.1

Posted Dec 6, 2013 12:47 UTC (Fri) by mathstuf (subscriber, #69389) [Link]

> Restricting yourself to just POSIX in an interactive session is pointless, I'm sure you use zsh constructs all the time.

I do use zsh-isms all the time. I also copy/paste code from scripts to test them out into the shell.

> Use the right tool for each job. Strict POSIX scripts are actually rarely needed.

In general, yes, though it can get to the point of having too many tools. I write POSIX scripts because its something everyone has and it causes me to be more careful (I know where the POSIX line is; the bash/zsh line has become fuzzier over the years) which is always good in shell. Really, the worst thing to deal with is usually "sed -i".

I think the thing I'd miss most moving from zsh is one of the extended globbing, zmv, vcs_info, or getting used to some other tab completion's quirks. The last would probably be the most annoying to have to do, but vcs_info is probably what I haven't seen anywhere else (zmv can be replaced by vidir most of the time, but its nice to have it in the history at times).

> Your link says sh, *ksh* and csh

Yeah, that was a typo. Zsh does tend to pick up the bash-isms, but I don't think it follows fish.


Copyright © 2013, Eklektix, Inc.
This article may be redistributed under the terms of the Creative Commons CC BY-SA 4.0 license
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds