My New Favourite Terminal Emulator: Vim

4 minute read

I hate having to use the mouse. I do everything I can to change my workflow so that I never have to touch it. That includes using a tiling window manager, using Firefox with VimFx extension so that I can use my browser just the way I use vim and using commandline apps rather than GUI apps for pretty much anything (vim, alpine, musikcube etc.)

However, the one thing that really forced me to use the mouse quite often was my terminal emulator. In most terminal emulators if you want to scroll up to see text, you’ll need to employ some uncomfortable keystrokes (Win + Shift + up/down in gnome-terminal). The most annoying scenario is when you want to select text from a terminal, to copy paste it somewhere else. The hoops you need to jump through in gnome-terminal to do this natively are ridiculous. As of this writing, the only sane way to do this WITHOUT using the mouse is to always run your session via screen. screen is a great piece of software, but I really don’t want to muscle-memorize a whole slew of different shortcuts to change modes and select text when as a vim user, I have put in the effort of ingraining a functional workflow already.

So, that began my next quest: to find a termimal emulator that lets me use the vim workflow. Went through a bunch of terminal emulators trying to get them to fit the workflow I wanted. I hit dead ends repeatedly. I also tried using zsh’s Vi mode. Am probably going to use zsh as my shell, but its vi mode does not let me customize the shortcuts the way I like.

For eg. I use Cntrl+l and Cntrl+h to jump back and forth from start and ends of lines because I don’t like the vim defaults. Another indispensable cusotmization is using a quick double press of ‘j’ key to get out of INSERT mode. I just can’t live without them.

Also, frankly I think the job of managing shortcuts and workflow ought to be the responsibility of my terminal emulator, not my shell.

As is often in life, the perfect solution was always at hand, hiding in plain sight.

If you want Vim, just use Vim!

Neovim is a really great vim fork I have been using for a while now. Turns out that Neovim can open a terminal emulator buffer. I had even been happily using this feature for the past couple months while developing - code in one buffer and the shell in a split buffer. All that time, I was looking for a terminal emulator that I could use to replicate this convenient shell environment I had within nvim.

I feel like kicking myself for not seeing the obvious: why don’t I just use nvim with a single terminal buffer as my primary terminal emulator?

There were a few simple customizations I needed to do:

  • allow nvim to start in insert mode at startup (done with the +startinsert commandline option)
  • make nvim start with a different stripped down configuration file because you don’t want to incur the slowdown at startup of loading heavy vim plugins each time you open a terminal. (done with the -u option)
  • hide the vim status line at the bottom, just for cosmetic purposes so that the result looked like a typical terminal window rather than another vim instance. (Achieved this thanks to a helpful Stackoverflow snippet)

I just had to make the following shell snippet my primary terminal emulator:

nvim +startinsert -u $HOME/.i3/terminal.init.vim term://bash

where my terminal.init.vim file looks like:

set guifont=Monospace\ 12

set t_Co=256
set background=dark
highlight Normal ctermbg=NONE
highlight nonText ctermbg=NONE

" Make vim use X clipboard by default while doing yanks and pastes
set clipboard=unnamedplus

" Prevent vim from clearing out the clipboard on exit
autocmd VimLeave * call system("xsel -ib", getreg('+'))

" Prevent vim from forcing you to save a changed buffer or using ! when
" switching between buffers
set hidden

" Specify a directory for plugins (for Neovim: ~/.local/share/nvim/plugged)
call plug#begin('~/.vim/plugged')

" Make sure you use single quotes
Plug 'junegunn/vim-easy-align'
Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': './install --all' }
Plug 'flazz/vim-colorschemes'
Plug 'xolox/vim-misc'
Plug 'qpkorr/vim-bufkill'

" Add plugins to &runtimepath
call plug#end()

colorscheme molokai

set relativenumber
set number

nnoremap <C-S-tab> :bprevious<CR>
nnoremap <C-tab>   :bnext<CR>

filetype plugin indent on
syntax enable

" Neovim's Python provider
"let g:python_host_prog  = '/usr/local/bin/python3'
"let g:python3_host_prog = '/usr/local/bin/python3'

" Move up and down in autocomplete with <c-j> and <c-k>
inoremap <expr> <c-j> ("\<C-n>")
inoremap <expr> <c-k> ("\<C-p>")

" Map jj to leave insert mode 
inoremap jj <esc>

" Easier jumping to first non-space and 
" last non-space letters in line
inoremap <C-h> <C-o>^
inoremap <C-l> <C-o>g_
vmap <C-h> <Home>
vmap <C-l> <End>

" Easier jumping to home and end
nnoremap <C-h> <Home>
nnoremap <C-l> <End>

" Disable Arrow keys in Escape mode
map <up> <nop>
map <down> <nop>
map <left> <nop>
map <right> <nop>

" Disable Arrow keys in Insert mode
imap <up> <nop>
imap <down> <nop>
imap <left> <nop>

set directory=$HOME/.vim/swapfiles//
set backupdir=$HOME/.vim/backups//
imap <right> <nop>

" Remap terminal mode toggle
tnoremap jj <C-\><C-n>

" Set splitting modes
set splitbelow
set splitright

" Keep mouse disabled
set mouse=c

" Remap bufkill from BD to cntrl-x
map <C-x> :BD<cr>

" Code to hide the status line just for cosmetic purposes
let s:hidden_all = 0
function! ToggleHiddenAll()
    if s:hidden_all  == 0
        let s:hidden_all = 1
        set noshowmode
        set noruler
        set laststatus=0
        set noshowcmd
    else
        let s:hidden_all = 0
        set showmode
        set ruler
        set laststatus=2
        set showcmd
    endif
endfunction

call ToggleHiddenAll()

So what does the end result look like?

nvim as terminal emulator

Yes, I know how ironical it is to take a screenshot of an i3wm workspace with floating windows in it, but I needed the eye-candy for this post. :)

Updated:

Leave a Comment