Though daunting at first, the command line has proven its reliability and operability time after time with utilities like Homebrew and Git. Even the lower-level, out-of-the-box utilities like
grep are incredibly useful. If you're not the type of person that prefers point-and-click operations to do something as monotonous copying a file or peeking into a file's contents then you may already know the value bash functions provide to drastically improve your existing workflow. But utilities don't have to be intense to be useful in the smallest regards.
Typing commands such as
yarn workspace someWorkspace run someScript can get tedious when you're in the middle of debugging an application. Or even specifying a configuration file in ESLint using
eslint --config ~/.config/.eslintrc.js someDirectory if you're using a global config file. Some commands or words can be easily fumbled when typing (e.g. "components" and "workspace"). This is where functions come in to play.
Here we will be exploring functions in fish shell, specifically how we can use its functions to shorten our everyday commands such as the two noted above. The syntax is different compared to traditional bash aliases, but I hope to get you up and running in no time by guiding you through a few examples.
Let's start with
yarn workspaces by using an alias that is as fluid to type as it is short. Open your Fish configuration file via
code ~/.config/fish/config.fish and input the following:
function ywrs command yarn workspaces $argv end
That's it! You have just created your first function! Let's break this down:
function: declaration keyword
ywrs: our alias, this is what we will be able to type in our terminal
command yarn workspaces $argv
command: keyword needed to tell the shell to "execute" the following command, just as how you would normally type into the terminal
yarn workspaces: the command we are wrapping
$argv: pass the remaining arguments to the defined command
ywrs infowill thus execute
yarn workspaces info
To test out your new function you will need to reload the fish configuration by reevaluating the
config.fish file (this is also done when a new shell session is created):
Now that you've got your feet wet, let's try a few more examples.
function ywr command yarn workspace $argv end
Similar to the initial example, this will allow us to easily execute commands in a workspace via a keyword that is both short and easy to type.
function eslint command eslint --config ~/.eslintrc.js $argv end
Here we are extending the existing, global
eslint command by specifying a configuration file that can now be used throughout your projects without setting up a project-level ESLint dotfile. For additional learning regarding global ESLint and VSCode, check out my other blog post.
An Intense Example
The ESLint example above allows you to use the
eslint command with a single configuration file, but what about automating the project-level install? Below we will discover how we can leverage functions, internal functions, and a bit of bash logic to install all of our ESLint dependencies and copy our global configuration file to the working directory.
function yawn if test (count $argv) -lt 1; or test $argv = "--help" printf "Don't yawn too loud now, I need a package name" else if test (count $argv) -eq 1 switch $argv case 'eslint' _install_eslint case '*' echo "Doesn't look like I have that package, try again." end else echo $argv end end function _install_eslint yarn add -D \ eslint babel-eslint eslint-loader \ prettier eslint-config-prettier eslint-plugin-prettier \ eslint-config-standard eslint-plugin-standard \ eslint-plugin-node \ eslint-plugin-jsx-a11y \ eslint-plugin-promise \ eslint-plugin-import \ eslint-plugin-react \ ;and cp ~/.config/.eslintrc.js . end
Though we won't dive too deep into this example, let's briefly go over what value this example brings to the workflow:
function yawn...: high-level alias that acts as a cli utility to route a subcommand (passed as an argument) and call its respective internal alias
function _install_eslint...: internal alias that will be called from
yawngiven the input is
- installs ESLint dependencies
- copies global ESLint config file
- NOTE: often times commands used internally (not directly called by the user) will be prepended with an underscore, here we utilize this nomenclature to make our
config.fishfile more readable
With these new functions you are now able to dive into a new project and call
yawn eslint to set up ESLint. Personally I use this all the time and love to automate monotonous tasks just like this example.
So far we've covered:
- Fish functions
- Editing and using the Fish dotfile:
- Reloading the dotfile
- Using functions to shorten commands
- Using functions to extend commands
- Using functions to automate tasks
I hope I was able to convince you to start using this functionality, whether you use the examples provided or by creating your own. Speaking of, in the last example I provided the skeleton to add more subcommands to the
yawn function, try setting up your own internal function that helps automate the tedious aspects of your workflow! I'd love to hear how Fish functions have enhanced your workflow, Tweet @garlicbred with your story!