I don’t like taking away my hands from the keyboard when I’m working. I do like it when everything is “just a click away”, or a keystroke away.
I do lots of stuff on CLI, - logs, process monitoring, creating pull requests, writing code and all it entails (debugging, refactoring, running tests, etc).
As such, my terminal is the app I’m using the most. Inside of it I’m running the rest of my setup which consists primarily of tmux, vim, fish, git, some other cli programs, and a bunch of scripts and aliases.
When working I can usually get by with only 2 apps open - terminal and browser. Nothing else is essential.
Terminal
Needless to say terminal is crucial in my setup, so it has to be the best I can get.
Criteria to satisfy my needs
A good terminal emulator has to be fast since this is the app I’m spending most of my time in. As such it has to be GPU-accelerated. It has to work on both Mac and Linux (Windows, I’m sorry, not a fan of yours), so it has to have some cross-platformability. It also needs to be open source.
Choices
I’ve tried quite a few terminal emulators.
iTerm2
and Hyper
are notoriously slow. Hyper, being Electron-based, is also a CPU/RAM devourer. Default MacOS Terminal app I just don’t like, and it’s kinda slow-ish as well, not to mention I probably can’t get it on Linux and I doubt it’s open source.
If I were to use a terminal app for once-off tasks, I’d be fine with either iTerm2 or Hyper, but as a terminal is my ultimate workhorse I need it to be performant.
Next up I’ve tried Alacritty
and kitty
and they are pretty close in terms of performance with kitty having a bit of an edge over Alacritty (which seemed weird to be because Alacritty is written in rust whereas kitty is in python). When I’ve been choosing, Alacritty claimed to be “the fastest” on their github page. Never trust the writing on the wall, on some setups it may be “the fastest”, check on your own setup with the tasks that you are usually performing. Measuring terminal emulator performance is monkey business anyway. It turned out that on my setup (on my machine) alactritty is tad bit slower than kitty. As they are pretty neck-to-neck, speed is no longer the selling point for me.
kitty
is the winner
Ultimately, I fell in love with kitty
, and I would’ve chosen kitty even if it wasn’t faster (provided it’s not slow, of course) than Alacritty. The look and feel felt right, so did the configuration options (colors, font, opening URLs with a mouse click, ability to disable all the “husk” such as window title, and others).
Don’t get me wrong, alacritty is very decent and you can give it a shot, but choosing what’s right for me is not solely based on numbers, popularity, or features, it’s also a matter of personal preference.
Tmux
Terminal multiplexor is something that I’ve been staying away from for a long time. I only had experience running GNU screen on remote servers for long tasks. I’d just ssh
into a remote server and run my bin/long-process
in a screen
and then put it in background.
In the past, while working, I would use tabs in iTerm2
(when I was using it) and I didn’t think a terminal multiplexor would improve my workflow all that much. I was totally wrong. Once I got into a habit of using tmux there was no way back. It simply allows you to slice and dice your terminal screen exactly the way you want it. No need for tabs, or built-in split-screens as you get finer control. New session is my new workspace, windows are my tabs, and within a single window I can have multiple panes. With some fish
scripts I can enhance tmux experience even further.
For a new task (project, or JIRA ticket) I always start a new session (prefix+:
followed by :new -s <session-name>
, or if tmux session is not running yet, use tmux new -s <session-name>
CLI command). From there on, the first window will usually be designated for the editor (vim in my case), and all the other windows will be created as needed (for logs, monitoring, testing, etc).
Inside a single window I can have multiple panes as needed
VIM
I already told my story of why I chose vim as a my go-to editor. In another article I have also described how to make a universal IDE out of vim. TL;DR: VIM can do most of the stuff modern IDEs can do, it has support for most of the programming languages so I don’t have to do IDE hopping, it’s ran inside a terminal and I have a habit of not leaving my terminal while working. It’s also very fast (if you keep the number of plugins to a minimum).
My whole vim configuration can be found in my dotfiles. You already have seen screenshots of what it looks like previously in this article. I’m going only quickly describe what my vim is capable of (aka plugins overview).
Autocomplete, refactoring, jump to definition, etc
I use coc.nvim for LSP support. It adds IDE-like features into vim such as:
- Code autocompletion
- Refactoring (rename symbol, class, etc)
- Go-to definition
- Go-to references
- Method signature tooltip
Searching
fzf, fd, and rg makes wonders when it comes to searching for anything.
Ctrl+P
is my fuzzy file search (it works just like you’d expect it to work in any IDE)<leader>+bb
lists me all the open buffers<leader>+/
gives me a history of commands<leader>+FF
searches for a string in all the project’s files (the search is excluding everything that is excluded in.gitignore
)
Other capabilities
For files explorer I’m using NERDTree (quite famous in vim community). I don’t like it all that much to be honest and looking to replace it, but it does the job and I’m lazy.
gitgutter is super useful as it shows a git diff in the sign column as well as a bunch of other useful things it does.
And I’m also using fugitive, mainly to do git blame
right inside the editor. Most of the time for any other git commands I put my vim to background, do git stuff, and then return back to vim
using fg
command. Or, in some cases, I will make a horizontal tmux pane if I want to have git diff on top and compose a git commit message on the bottom (very useful!).
For debugging, I’m using vdebug.
Most useful built-in capabilities
- Macros! This is something that is lacking in most IDEs and usually doesn’t exist in those IDEs’ “vimification” plugins (IdeaVim is pretty good though).
- General navigation (
hjkl
,f+<symbol>
, etc) and editing (dd
,cw
, etc) in a file. - Splits (either using
:sp
,:vs
or a keystrokeCtrl+W+s
,Ctrl+W+v
)
Fish shell
I was a zsh user for many years. And then I’ve found fish.
Why, Kirill, why? zsh is perfect!
Yeah, zsh is good, but fish is better (for ME! I don’t want to put words in your mouth). You can read why I decided to switch to fish and maybe it will make you want to try fish.
I’m not going to say much in this section. It’s just a preface for the next one.
Scripts
You can find my scripts, again, in my dotfiles. There are fish scripts, and some other scripts in a ~/bin directory. I will not go through all of them, only the ones which I use the most.
p.fish
THE most used script.
It allows jumping between projects in no time. All you need is to type the project’s name part and it will take you there (provided you have zoxide
installed). Two conditions though - your project has to be a git repo (this is how p
knows it’s a project, not a regular directory). Second condition, - you have to add all the projects’ roots to $PROJECTS_DIRS
env var (i.e. set -x PROJECTS_DIRS ~/Projects $GOPATH/src
)
If a project can not be found by partial name, p
will show a list of projects via fzf
(if it’s installed) and you can auto-complete the project’s name from there. Next time p
will “remember” your choice, and, provided the same search term, will take you to the selected project.
@.fish
A shortcut for docker exec -it <container id>
. To “ssh” into a container, I just type @ elasticsearch bash
.
bin/prview
Under the hood, it uses the official GitHub cli tool gh to fetch a list of my PRs and pipe them into FZF for fuzzy find.
Browser openers scripts
There is a bunch of scripts that open browser links for me (not committed to my public git repo).
In the past, I used Alfred to have my custom searches, so I could open up links that follow a particular pattern easily. Now I’ve replaced Alfred with a bunch of scripts. When I need to open up a JIRA ticket, for instance, I simply type j
on console and j
takes me to the JIRA ticket that (how does it know the name? Don’t you remember? It’s my tmux sessions name). j
can also accept the argument of the ticket number, so I can do j TICKET-123
.
It’s really easy to do, by the way. Let me quickly “fish it up” for ya:
function google open "https://google.com/?q=$argv"end
Now
google coffeeaddict dev
will take you to https://www.google.com/?q=coffeeaddict%20dev
Gotta be super easy to script it up in bash too, I’m just too lazy to try it.
Honorable mentions
dns
to quickly add or remove a dns serverproxy
to enable proxy (useful with something likemitmproxy
)t
(alias for taskwarrior which “scopes” to the current tmux session using the session name):
That’s it, folks!
Terminal, tmux, vim, and a bunch of scripts is all it takes to almost never lift up hands from the keyboard. Not that it’s an ultimate goal, but it does add up to effectiveness hour by hour, day by day, month by month, year by year…