Centralize Your Command Line with fish shell Functions

Article summary

Developers use a lot of customizable tools, and it’s easy to reason through most of them. While text editors and IDEs come with config files and community standards for customizations, Unix-like shells can feel barren in comparison. However, fish shell acts as a highly configurable alternative to other shells.

(If you’re interested in switching to fish shell, my colleague John can show you how to set it up and use its coolest features.)

The unique part of the fish shell is the way it uses functions to decrease the reliance on monolithic config files. The separation of components into smaller, focused routines is a job that developers do every day.

Functions

A fish function is a list of commands, which may optionally take arguments.

Functions are by far the best reason to try out the fish shell. If you’re like me, you have a bin directory that acts as a catch-all in your $HOME directory. Mine was cluttered with scripts that weren’t really binaries. I struggled to remember whether a command was aliased in my .profile or sitting in bin.

The fish shell does away with both of these problems. For the first issue, all functions live in your home directory under ~/.config/fish/functions. They’re automatically loaded to the list of functions you can access from the fish shell, so there’s no need to add the directory to the path yourself.

Aliases are available in fish, but they’re not recommended for creating functions. The functions directory adds a central location to list wrapped commands. While the alias command still exists in fish, it’s just as easy to create a function file as it is to alias it in the fish config.

An example of a quick override is the fish_greeting. This is presented whenever you start a new shell session. One easy way to override or suppress it is by adding a fish_greeting.fish file to your functions directory. Anything inside the fish_greeting function will now be shown in a new session.

With the greeting modified, it would be a great time to modify fish’s prompt too. But there’s one caveat coming from Z Shell or Bash. There is no PS1 variable.

Prompt

Fish Shell with Default Prompt
fish shell with default prompt

You may notice that fish doesn’t provide a way to customize the command prompt via the PS1 variable. Instead, it executes the fish_prompt function, which can be used to print a prompt. While the prompt defaults to showing the hostname and the current working directory, it can be changed to anything. A simple solution is to print the current working directory followed by a greater-than sign:

function fish_prompt
    printf ' '(prompt_pwd)'> '
end

There are a few fish-specific features to explain in the code. The first is that the custom fish_prompt will override the default fish_prompt, just like fish_greeting did. Next, the parentheses around prompt_pwd represent command substitution. Finally, the result of prompt_pwd is a string, so fish can interpolate it into the first parameter of printf.

Fish Shell with Customized Prompt
fish shell with customized prompt

These are just a few of the ways you can centralize your command-line workflow with fish. Functions replace simple shell scripts, overrides are straightforward, and everything can be found reasonably under the fish config directory. It’s a great way to streamline shell modifications.

For further reading, try out the official fish documentation. There’s an impressive amount of information for current fish users and those looking to dive into a new experience.