As developers, we all want to be efficient with each keystrokes. I have always found that most of my keystrokes were not optimized. From going from one directory to another, from searching occurrences of a word in files recursively or just writing code and navigating between files and folder. If you ever felt this situation before, you might find some of the following tools useful.

In this article, I will be referencing my implementation and usage of these tools using config files that you can find here.

tmux

"iTerm update"

Nooooo, I've spent so long customizing my tile layout inside my terminal, are you telling me I'm going to have to redo it all? 😭

I have been there. Spending time to have a proper tile split just to end up having to update iTerm to lose it all.

tmux stands for terminal multiplexer. If you ever used the command screen you know what it is ; if not, it is basically a terminal inside a terminal. It gives you the ability to have multiple sessions (which are shell-like) in the background or not. A very useful tool when connecting on a remote server where you want to run a script and inspect its code at the same time for example.

tmux is highly customizable and there are some very nice plugins that extend its default functionalities.

I personally chose to have my window tabs at the bottom and a custom color scheme that highlights my current window as well as the border of my active pane using the same colors.

https://i.imgur.com/imrL3K4.png

The navigation is done with a "leader key" which is <Ctrl-A> for me. Something to note is that my <Tab> key is remapped to <Ctrl> so that it is really easy to press and close to my left pinky. You can navigate between panes, split panes, resize panes, create new windows and so on, all this from the keyboard.

A couple of plugins worth mentioning:

  • tmux-ressurect
    This plugin is a life saver when it comes to random crashes of your computer. Together with tmux-continuum it enables a seamless and foolproof periodic save of your current sessions so that when you restart your tmux it automatically loads back the configuration that you had before the crash.
  • tmux-sensible
    This plugin facilitates the configuration of the tmux.conf file by making it more user- and novice-friendly.

z

Where was that folder again...?

"cd ../../../../<TAB>"

Are you tired of using super long commands to navigate between folders?

What if I told you that there is a tool that, based on the frequency (frequency + recency) of your navigation, enables you to go directly to a folder?

Well... here it is  it is called z and works in zsh. Every time you navigate between folders, it stores an entry inside a file and increments it based on the two parameters mentioned above.

After building your custom registry of navigation, you can start using commands like z last where last is a folder called lastFolder: it will fuzzy match last with lastFolder and do a cd to that path.

Another pretty cool trick using z is when you want to do commands from a directory to another directory, you can use the flag -e which will only echo the matched path instead of using cd on it. You can for example do commands like these without having to know the complete path of the folders : cp -r $(z -e folder1)/xxx $(z -e folder2)

fzf

"Hum... What was that command again? Something like kubeclt or something..."

I always found myself struggling to find a command I wrote 3 weeks ago that I copy pasted from Stack Overflow. Well, fzf has helped me greatly with that.

What is fzf ? It's an interactive Unix filter for command-line that can be used with any list, files, command history, processes, hostnames, bookmarks, git commits, etc.

Let's demonstrate a few use cases of the tool.

Command history

One of my favorite use of fzf is with the command history. I always found it very daunting to use the built-in recursive search of bash. Why? Only one result at the time and the search in itself is not very intuitive.

When you plug your shell with fzf (zsh in my case), the built-in <Ctrl+r> command history opens up the history through the interactive fuzzy finder of fzf which looks like this.

You can then type words that refer to the command you were looking for.

File manipulations

Another cool use of fzf is when you want to search for files. You can mix different matching patterns to achieve most of what are you trying to do. For example, you can open in vim all the JSON files in a folder but only the ones that are not packages.json. This query would translate in something quite complex using normal shell filtering, but thanks to fzf we can do something like this :

Git

The same way fzf can be used for command history or file manipulations (and many more), it can also be used in the context of git. You might not always remember what branch you were working on or the exact version of the release tag: fzf is here for you again.

Binary flag options

A useful trick is to combine fzf with flags when executing commands. It is really powerful because you are able to find the option you were looking for by fuzzy matching its name or its description when it has one. A good example of this is Git.

You can easily find all the commands that related to repositories or commits. Once you found the git commit command, you can use git commit - and press <Tab> when you have the fzf-tab plugin activated in zsh. It will then display the list of flags first the subcommand commit which can be pretty handy.

rg

I can't remember where we instantiate that class...

** Goes on GitHub search **

You like Visual Studio Code global search but you don't know how you could have it inside your terminal as well? Here is where ripgrep comes in handy.

Using the definition on the GitHub repository of the project, ripgrep is the fastest line-oriented search tool that recursively searches the current directory for a regex pattern.

Is it very useful when you are looking for a specific pattern inside a big codebase, like all the versions of a package or all the references to a specific method.

For example, using a combination of rg, fzf and vim you could find all the files that have a reference to a specific term, filter that list of file on another term and open them in vim. When coding in JS, a good use case of this is when you want to open all the files that reference a specific module, but not the reference inside the package.json, the documentation or the tests. It would look like this:

vim

"git commit"

How do you exit this thing????? 🤯

We all know Vim and a large chunk of us have used it at least a little bit, whether it is to edit a commit or to actually use as a text editor to create production ready code. You may be wondering how and why this kind of people exist and I will try to give you some of my reasons as to why I use it all the time.

Composability

One of the great features of Vim is the composability of the commands the editor provides. Let's take a quick example. Using w you can jump a word, f you can jump to the next occurence of the character you are searching for. d can be used to delete and y to copy. Combining all these, you are able to do a lot of things like deleting all the characters up to the next occurence of a character with dfX or copy the next word yw. This is just a really simple example to illustrate this idea of composability but there is a very vaste range of keybinds that can be composed to create very powerful text manipulations.

You are probably familiar to this: you start typing because you want to write some text but instead a lot of weird stuff is happening in your buffer. This is probably because you thought you were in INSERT mode, when in fact you were in COMMAND mode.

The difference between the two is pretty straight forward: in INSERT mode you can freely type text in the buffer that you are in. In COMMAND mode you can move around, execute command and so on.

There is a third mode called VISUAL mode which occurs when you highlight text pressing v.

The division between the COMMAND mode and the INSERT mode enables features like ., which is able to replay the last sequence of keystrokes that applied a change on the buffer. The last part is important: for example, if you want to insert a character and move to the left using ., you will only be able to insert that character, and that's where macros come into play.

Macros

In Vim, there is a neat feature which consists of recording a sequence of actions and being able to replay the sequence. This sounds like the . feature, except that it includes all of the changes that are not included in the latter like movements for example.

This feature is super useful when a typical search-and-replace could become complex with regex. For example, when you have to change only the name of the first parameter of a function in an interface, you could record it and apply the macro over the following lines. The feature looks like this (q is the keybind to start and stop the recording of a macro):

Keyboard first citizen

Everything (almost) in Vim has a keyboard shortcut. There is nothing you can do with your mouse that you can't do with a keyboard.

It is true that you have more flexibility when you move your mouse: you can precisely go wherever you please. But in Vim, there is a plugin that allows you to navigate with your keyboard just like you would with your mouse. It is called vim-sneak. It replaces the s shortcut so that you are able to jump between lines and words very easily (it is an extension of the native f and t command, except it also moves vertically): type s then the first two letters of the word you are looking to jump to. If there are multiples matches, all the matches will be highlighted and you are prompted to type one more letter to move your cursor to the corresponding match.

It looks like the following clip:

Integrations

We talked about two tools that are independent of Vim in the previous parts, but let me show you how well they integrate inside Vim. This is really awesome because it lets you get a deeper understanding of how the underlying system of your editor work. Who knows how VSCode <Ctrl + P> file opener works, or even the full text search?

  • fzf
    It can be a frustrating having to leave Vim to be able to use fzf again to open new buffers. That's where the fzf integration comes into play. Just like the <Ctrl + P> works in VSCode, you now have fzf opening a new pane to open new buffers just like you would do it in the terminal. It has all the same features as the fzf you are used to in the terminal so you can take advantage of it: the same way we were able to filter files in the terminal in the example above, we can also do inside vim.
  • rg (combined with fzf)
    As previously shown, rg enables global search inside text files. The vim integration is able to open all the files buffers that match the requested text and put them inside fzf. You can then see a preview of the file (which uses bat, an improved version of cat) and the line that matched the searched text. Then, you can apply fzf custom filters on top of the previous query, just like before.

Here is a small demo of the integrations of the two tools inside neovim:

Now that we know why I think that vim is cool, I will admit that it is fairly hard to setup, especially for people that are afraid of configuration files. Here comes the savior if you want to pimp your coding experience with LSPs (Language Server Protocols) and IDE-like features without having to spend a huge amount of time configuring your tools.

neovim

The first version of vim has been released in 1991 which was heavily inspired from Vi that was released in BSD in 1976. In 2014, a group of members of the Vim community started a big refactoring which ended up in a fork called neovim.

neovim has opened a lot of doors to bridge the gap with moderns editors by making sure that it would stay in the age of its time (better maintainability, more optimized code, better APIs, ...). One of my favorite feature of neovim are the floating windows, which makes it easy to have quick contextual information. neovim also comes with LSPs support, an API to develop plugins in many languages and many more cool features which enabled members of the community to extend the capabilities that the text editor already provided.

coc.nvim

coc.nvim is my favorite neovim plugin. As its name (Conqueror of Completion) suggests, it provides a great autocompletion framework. Coming from Visual Studio Code, I always found Vim configuration a bit daunting, especially when it came to autocompletion and LSP and I was relieved that CoC brought a VSCode-like configuration to neovim autocompletion.

The setup is very similar using a JSON file for configuration and extensions, just like I was used to in VSCode. There are some pretty cool features built-in such as the Go to definition, inline linting and fixing, hover for documentation and many more.

Conclusion

The quest to optimize the interactions that we, as developers, have with our machines is a journey that follows us all along our careers and is truly personal. I believe that it is nice to make your terminal a friendly place that you feel confortable working in and I hope these few tools have helped you in any way towards that goal.

And no, using Vim in 2021 is not being old-fashioned. Thanks for your attention!

If you want to go further


Article by Dylan Djian, Software Engineer @PayFit

Photo by Mohammad Rahmani on Unsplash, free to use under the Unsplash License