aboutsummaryrefslogtreecommitdiff
path: root/content/posts/2022-06-23-fish_command.md
blob: 697ba0764d12025098b28a248a76f8a28109ddac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
---
title:  "Shortcutting with fish shell"
date:   2022-06-23
tags: ['fish', 'linux', 'shell']
---

For some time now I have been using fish shell[^1] as my default shell and it
has been a great experience. It has sane defaults and with almost no work I
have a perfectly function shell with a great auto completion engine. I have
also tried zsh before and although it is great shell it require some work to
come to same level of fish, even after you include oh-my-zsh[^2] (which I'd
highly recommend to use if you are starting with zsh). One thing to keep in
mind is that  fish is far from sh or bash compatible, so if you have something
built in sh or bash it won't work with fish (as you can't source it). Anyhow,
what I want to show here is how much you can optimize your workflow with just a
couple lines of shell.

## The use case

As an assiduous user of terminal I constantly need to jump from folder to
folder between projects I’m working on whether to run an editor or to use git.

Normally I'd just type `cd ~/Git/gabrielgio` and from there to another folder,
but we can do better with fish (or any other shell actually) by assigning this
action to a keystroke. However before we can add the shortcut itself lets first
create a function to jump into the folder, to do so we will be using the `fzf`
where the man page states:

> a command-line fuzzy finder

That will provide a nice way to search and pick from arbitrary list. You can
get quick glance of how it work just type `find . | fzf` and it will open the
fuzzy finder buffer interactively search for input keyword. To expose this
functions of ours we are going to use a nice feature from fish which autoloads
function[^3]  from all the `.fish` files from all folders listed in
`$fish_function_path`. So we will be using the `~/.config/fish/functions`
folder. Add a new file called `jumpin.fish` with the following content:

```fish
# ~/.config/fish/functions/jumpin.fish
function jumpin
end
```

Now lets plug `fzf` into that function.


```fish
# ~/.config/fish/functions/jumpin.fish
function jumpin
    set selected (ls ~/Git | fzf)
    pushd ~/Git/$selected
end
```

We are going to pip `ls` result into `fzf` then `set`[^4]  result of `fzf` into
a variable. The return value of `fzf` is the value you have selected. As you
can infer from the script I'm listing all my folder from `Git` folder where I
store all my projects which are the folder I, most of the time, want to jump
right in. It can be literally anything you may find useful, you may want to try
to search using a broader scope by:

```sh
find ~/ -type d | fzf
```

Whatever fits you better, the end goal here is to get start customizing and
optimizing your workflow so you can more comfortably move around.

Now, it is almost done we just need the check if the `selected` has value. The
user can cancel the selection (e.g.: by pressing esc) and then the `selected`
variable would be empty. To check that we just need an if:

```fish
# ~/.config/fish/functions/jumpin.fish
function jumpin
    set selected (ls ~/Git | fzf)
    if [ "$selected" ]
        cd ~/Git/$selected
    end
end
```

You will need to  reopen your terminal emulator or if you source it so the
function become available.

```fish
# how to source it
source ~/.config/fish/functions/jumpin.fish
```

Then type `jumpin` and let `fzf` do the work.

Now we can jump to a folder even faster by assigning a shortcut to a function
and again fish comes to rescue to make our life easier. It provider a bind[^5]
function to bind (duh) sequence of characters to a function. Inside of your
`~/.config/fish/` there will be a `config.fish` with a function called
`fish_user_key_bindings` which fish automatically executes. We will use
that function (as the name implies) to bind our command to a keystroke. To do
so use the bind function:

```fish
# ~/.config/fish/config.fish
function fish_user_key_bindings
  # ...
  bind \ck 'jumpin'
end
```

Once again reopen the terminal or source the configuration file. Now once you
press `Ctrl+k` it will pop the `fzf` list picker and after you select something
you will jump right into the folder. Due to the fuzzy finder algorithm you
won't need to type more then a couple of char making the whole process really
fast.

This is just a jump start using script to make your life easier. Shell
scripting is a powerful tool for a programmer and it will definitely pay
dividends if you spend time to master it.

[^1]: https://fishshell.com/
[^2]: https://ohmyz.sh
[^3]: https://fishshell.com/docs/current/language.html#autoloading-functions
[^4]: https://fishshell.com/docs/current/cmds/set.html
[^5]: https://fishshell.com/docs/current/cmds/bind.html