I recently decided to give fish shell a try. I’ve always been reluctant to change my shell: bash has certainly its flaws, but it is widely spread. But lately I’m trying to go easier on embracing new things, since my natural approach is to be (extremely) skeptical about them (although the main reason to start using fish was its funny webpage, to be honest ).
So far the experience has been pretty satisfiying (the documentation is a bit poor, but it’s expected in a your project like this), but one of the weakest points of bash, in my opinion, is the lack of a “dependencies” manager, and it seems that fish lacks that feature too. A shell always comes with a scripting language, but is like if the people behind these languages wouldn’t take them seriously. “Meh, is just for scripts… why complicate them with dependencies?” Well, scripts are extremely powerful and repeating code is The Programmer’s Bane , so I think it would be great to have a mechanism to easily “include libraries” in your config file.
Since I’m trying to be less reluctant to new, non standard things , I decided to start using a custom mechanism in fish, which so far I’ve found to work out fine. Original as I am, I called it fish-modules
.
Getting fish-modules
The first step is to clone the fish-modules project. It can be put anywhere you prefer. In my case, I found convenient to add it as a submodule of my fish config repository, which was already a git project. /usr/local/ or $HOME/local could be suitable choices as well.
Creating the modules
Creating a module is as easy as creating a git repository with a directory functions and, optionally, a directory completions. Using the same conventions defined by the fish shell, the former can contain files where functions are defined (in a one-per-file basis), and the latter will be used to define the auto-completions of those functions. An example of a module would be the gh-issue flow fish module.
Defining the modules as dependencies
The first step would be to create a file in fish home (defaults to $HOME/.config/fish) called modules_config.fish. Each module would consists on a call to the implicit function module followed by the git repository route, the relative path and, optionally, the branch to use (defaults to master). An example of a possible modules config file is:
Updating the modules
Once your modules are defined, and assuming you have fish-modules in $HOME/.config/fish/fish-modules, you can init or update them using the command:
This will create the directory modules and will clone each specified module inside of it. Next time you invoke it, it will just perform a pull.
Making the modules accesible in your shell
Last step is having the functions and completions accesible in each fish shell you open. Assuming again that you have fish-modules in $HOME/.config/fish/fish-modules, that is as easy as adding the following line to your $HOME/.config/fish/config.fish :
If everything goes as expected, when opening a new terminal you will be able to use all the modules functions. An easy way to check if that’s the case is to echo the $fish_function_path to see if each module functions path is defined.
Future
I’d like to support dependencies definitions in the modules themselves, but I didn’t have the time yet. Other than that, I think this mechanism is simple enough and can encourage fish users to share their magic without having to share the whole fish configuration folder (which is not only painful in terms of merging, but can also have privacy issues).
But I also think it would be very neat to have something similar out of the box: it would be optional to have, simple to use and it would not add extra grammar.