For more than 7 years I have been working professionally as a Software Engineer. During this time I put together a nice developer setup. This article is my attempt to review it, improve it and share it with others.
Most of the time I spend in the command line, writing code in Nvim, executing commands in Zsh shell, switching panes and sessions in Tmux and all that is rendered in Alacritty terminal emulator running on my Mac.
What my developer environment consists of?
Most of the time I spend in the command line, reading and writing code in Nvim
, jumping between terminal sessions in Tmux
and running commands in Zsh
and all that is rendered in Alacritty
terminal emulator.
Command-line Shell
is a program which takes text commands, parses it, executes and prints back result. The shell defines syntax and concepts of the scripting language that you can input in. Different shells have different rules. Examples: Bash
, Zsh
, Fish
.
Terminal
is a program which runs your shell of choice and renders GUI window where you can interact with your CLI shell. Examples: iTerm2
, Alacritty
, Kitty
. Some terminals provide you with features like multiple windows, tabs, splits etc.
Terminal Multiplexer
is a program which orchestrates multiple terminal sessions into a single terminal window. It is command-line window manager, where windows are terminals, each terminal can have multiple windows and windows can be split into panes.
At the start of my career, my terminal usage mostly was to run a script to compile code, run tests or interact with git. For quite a long period of time, I was fun of terminal that is integrated into my editor.
Some forces attracted me into the world of text-based apps and instead of having the terminal in the Editor, I'm having Editor in the terminal.
When you heavily use the command line, especially when you search, move around, or write code in Nvim - you expect your terminal to render text fast. At some point performance of my terminal frustrated me and I found a solution - Alacritty.
Alacritty is just a very fast window with a shell running inside. It is written in Rust and uses GPU acceleration for rendering. There are no GUI features like windows, tabs or splits.
---- name: Make sure alacritty is presenthomebrew_cask:name: alacrittystate: present- name: Make sure config directory is presentfile:path: ~/.config/alacrittystate: directory- name: Make sure the config file is presenttemplate:src: templates/alacritty.yml.j2dest: ~/.config/alacritty/alacritty.yml
Alacritty is configured using a global text file located in ~/.config/alacritty/alacritty.yml
Config line below fixes colours rendering:
env:TERM: xterm-256color
I'm using Fira Code
font, but Alacritty doesn't support font ligatures --> :(
font:normal:family: Fira Codestyle: Regularbold:family: Fira Codestyle: Bolditalic:family: Fira Codestyle: Italicsize: 14.0
Configuring default shell, Zsh
in my case:
shell:program: /usr/local/bin/zshargs:- --login
In order to be able to use ^
, when you type <ctrl>6
, in Nvim to switch between files, I had to configure Alacritty to send \x1e
hex code.
key_bindings:- {key: Key6, mods: Control, chars: "\x1e"}
Full Alacritty configuration is here .alacritty.yml
Tmux is a terminal multiplexer which allows having multiple sessions, windows and splits in one terminal window. Command-line window manager.
Usually, I have session per project open and multiple windows in each session. For example, I can have session work
, with 2 windows open, one for code in Nvim and one window for running build scripts and tests.
Tmux allows to quickly navigate between sessions, windows and panes. With some additional configuration, I was able to get Vim key bindings to be used for jumping between splits, browsing logs and copy-pasting text.
Tmux Plugin Manager (tmp) is used to simplify plugins management. It simplifies the installation process and management of plugins.
It has to be cloned to ~/.tmux/plugins/tpm
.
# predefined settingsset -g @plugin 'tmux-plugins/tmux-sensible'# copy to the system clipboardset -g @plugin 'tmux-plugins/tmux-yank'# regex searchset -g @plugin 'tmux-plugins/tmux-copycat'# open highlighted selectionset -g @plugin 'tmux-plugins/tmux-open'
At some moment I noticed that Nvim colours when it is opened in Tmux are different comparing to Nvim opened outside of Tmux control, to fix that:
# fix terminal colours# set -g default-terminal screen-256colorset -g default-terminal "screen-256color" # colors!# tell Tmux that outside terminal supports true colourset -ga terminal-overrides ",xterm-256color*:Tc"
# starts selection modebind C-[ copy-modebind -T copy-mode-vi 'v' send -X begin-selection# copy with 'enter' or 'y' and send to mac os clipboard: http://goo.gl/2Bfn8unbind -T copy-mode-vi Enterbind -T copy-mode-vi 'y' send -X copy-pipe-and-cancel "reattach-to-user-namespace pbcopy"# pastebind p paste-buffer# paste from system clipboard MacOSbind C-v run \"tmux set-buffer \"$(reattach-to-user-namespace pbpaste)\"; tmux paste-buffer"
To be able to navigate between panes using Vim key-bindings, just install the next plugin:
set -g @plugin 'christoomey/vim-tmux-navigator'
To be able to use the navigation in the fzf window, fzf needs to be added to is_vim check.
is_vim="ps -o state= -o comm= -t '#{pane_tty}' \| grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|fzf|n?vim?x?)(diff)?$'"bind-key -n 'C-h' if-shell "$is_vim" 'send-keys C-h' 'select-pane -L'bind-key -n 'C-j' if-shell "$is_vim" 'send-keys C-j' 'select-pane -D'bind-key -n 'C-k' if-shell "$is_vim" 'send-keys C-k' 'select-pane -U'bind-key -n 'C-l' if-shell "$is_vim" 'send-keys C-l' 'select-pane -R'tmux_version='$(tmux -V | sed -En "s/^tmux ([0-9]+(.[0-9]+)?).*/\1/p")'if-shell -b '[ "$(echo "$tmux_version < 3.0" | bc)" = 1 ]' \"bind-key -n 'C-\\' if-shell \"$is_vim\" 'send-keys C-\\' 'select-pane -l'"if-shell -b '[ "$(echo "$tmux_version >= 3.0" | bc)" = 1 ]' \"bind-key -n 'C-\\' if-shell \"$is_vim\" 'send-keys C-\\\\' 'select-pane -l'"bind-key -T copy-mode-vi 'C-h' select-pane -Lbind-key -T copy-mode-vi 'C-j' select-pane -Dbind-key -T copy-mode-vi 'C-k' select-pane -Ubind-key -T copy-mode-vi 'C-l' select-pane -Rbind-key -T copy-mode-vi 'C-\' select-pane -l
Most of the shortcuts have a prefix key as part of them. My prefix is <ctrl>a
. For example to create new window <prefix> c
, I have to hold <ctrl>a
+ c
.
<c-a> - Prefix<prefix>r - reload config
<prefix>:new -s <session-name> - creates new session<prefix>s - open session list<prefix>w - open session list with tabs
<prefix>c - create new window<prefix>h - toggle window line<prefix>1 - go to window 1<prefix>2 - go to window 2.<prefix><N> - go to window N
<prefix>| - vertical split<prefix>- - horizontal split
<ctrl>h - go to left split<ctrl>l - go to right split<ctrl>k - go to top split<ctrl>j - go to bottom split
<prefix><c-]> - activate copy modev - start copy selectiony - copy selectionp - paste selection
Here you can find full .tmux.config
Nvim - a community-driven, refactored version of vim.
Nvim allows me to edit text faster than anything else. It designed to keep hands always in an optimum position to input text, to scroll, to navigate or to apply commands.
Config files are here: .nvimrc
Vim-plug is used to simplify plugin management. It supports on-demand plugin loading for start time fast, and parallel installation/updates.
The Nerdtree presents filesystem in the form of the tree and allows to browse, navigate and manipulate files and directories using Nvim navigation shortcuts.
Plug 'scrooloose/nerdtree'
Configuration:
let NERDTreeShowHidden=1 " show hidden fileslet g:NERDTreeAutoDeleteBuffer = 1 " delete buffer when delete file
Shortcuts:
While the buffer is in focus:
<leader>fe - toggle file tree<leader>ff - find current file
While the file tree is in focus:
t - open file in new tabi - open file in a hsplits - open file in a vsplito / enter - open file in the main buffer
Vim-airline is a plugin which draws editor status in a bottom line. It shows current vim mode, current git branch, the position of the cursor relative to the beginning of the file.
Plug 'bling/vim-airline'
In addition it can be used to make tabs nice:
let g:airline#extensions#tabline#enabled = 1let g:airline#extensions#tabline#fnamemod = ':t'let g:airline#extensions#tabline#tab_min_count = 2let g:airline#extensions#tabline#show_buffers = 0let g:airline#extensions#tabline#tab_nr_type = 1let g:airline#extensions#tabline#tabs_label = ''let g:airline#extensions#tabline#show_splits = 0let g:airline#extensions#tabline#show_tab_count = 0let g:airline#extensions#tabline#show_close_button = 0
Tabs mappings:
<leader>tt - new tab<leader>tp - go to prev tab<leader>tn - go to next tab<leader>to - close all tabs expect current one<leader>1 - go to 1 tab<leader>2 - go to 2 tab.<leader>n - go to nth tab<leader>0 - go to last tab
Splits mappings:
<c-h> - go to left split<c-j> - go to bottom split<c-k> - go to top split<c-l> - go to left split<c-\> - go between split<c-w>o - close all splits except focused one
Search and navigation is done via fzf. It is a generic command-line fuzzy finder. It can be used to search in any list: files, command history, processes, hostnames, bookmarks, git commits. From the shell it is used to execute commands from command history, to select git branches, to choose npm scripts and so on.
From inside of the editor it is used via fzf.vim to search for files by filename and to quickly jump between buffers. To search by files content, fzf is used in conjunction with ripgrep, which is grep rewritten in rust.
Plug '/usr/local/opt/fzf'Plug 'junegunn/fzf.vim'
Shortcuts:
<ctrl>p - search files by filename<ctrl>f - search files by content<ctrl>b - search buffers by filename
Having an editor to predict what are you going to type is must-have nowadays. So far the experience with autocompletion I had with YouCompleteMe.
Plug 'w0rp/ale'
While writing code automatic formating and linting is must-have. The best vim plugin for that is Ale. It provides integration with most linting, formating tools and to LSP servers.
Reasons to use it:
Shortcuts:
<leader>al - lint<leader>af - fix<leader>ad - error details
Git integration is done by the next plugins:
Plug 'tpope/vim-fugitive' " git commandsPlug 'junegunn/gv.vim' " git commit browserPlug 'airblade/vim-gitgutter' " git diff sign
Shortcuts:
<leader>gpr - git pull -r<leader>gc - git commit<leader>gp - git push<leader>gb - git blame<leader>gl - git log<leader>gd - git diff in vertical split
ZSH - highly customizable shell, supports aliases, completions, custom colour scheme.
zplug - plugin manager used to simplify plugin management. Can manage all types of plugins (git, oh-my-zsh, gist files), parallel installation, lazy loading.
zplug "plugins/vi-mode", from:oh-my-zsh
vi-mode - adds vim keybindings to shell. While you edit text you can exit insert mode and go to command mode where it is possible to navigate and change text the same way like in Vim.
zsh-users/zsh-history-substring-search
Allows to search for command based on typed part. Next bindings are used j
k
to cycle through matches.
bindkey '^[[A' history-substring-search-upbindkey '^[[B' history-substring-search-downbindkey -M vicmd 'k' history-substring-search-upbindkey -M vicmd 'j' history-substring-search-down
zplug "plugins/fzf", from:oh-my-zsh
The plugin allows to quickly search in command history using fuzzy search.
<ctrl><space>
opens fzf fuzzy search with full history.
zplug "zsh-users/zsh-autosuggestions"
While you type, the plugin shows autosuggestion under cursor in grey colour based on your history.
zplug "zsh-users/zsh-completions"
While you type and hit <tab>
, plugins shows possible suggestions for a command if it is present in competition library.
Getting proficient with Vim opened next-level productivity experience for me, allowing having common shortcuts scheme through the whole developer setup.
Working directly with command-line tools, gave me a broad understanding of what is behind fancy buttons people love.
Only with Vim, I learned how actually linters and formatters work, how editors highlight code, what way LSP servers work etc.
Each time returning back to work after long travel and opening laptop with my carefully configured setup, I feel like a kid who just got his new toy.