My Minimal, Terminal-based Work Setup
Table of Contents
Here I describe the various software I use to form a development environment for programming projects.
#
dtach
The basis for my setup is dtach. dtach executes a program in a session which the user can ‘detach’ from, returning them to the shell while the program continues to run. Later, the session can be reattached to. It allows me to, for example, start Neovim in a terminal window, make changes to some files and detach, allowing me to use the terminal window again for some other purpose or even close it entirely without disturbing Neovim. This is useful is because it allows me to attach to an existing session after connecting to the machine it’s running on via SSH. I can open a project and begin working while sitting at my desk, and then later access the same session remotely. dtach will also save you if the connection drops because you just reconnect and attach to the session again. If you want to replicate a setup like mine and you don’t need SSH then you may not need dtach.
#
dvtm
dvtm is a terminal multiplexer I use to construct my development environment user interface. It allows you to open various programs using one terminal window and display them in various layouts. It functions similarly to dwm. I’ll usually have open my text editor and several instances of bash displayed side-by-side, which I can switch between when required. Windows may be closed and new ones opened as necessary.
Window positions are determined by preconfigured layouts which can be cycled between to suit requirements. I almost never use anything other than the default ‘master and stack’ layout displayed above (master window on the left, other windows in ’the stack’ on the right).
#
Neovim
Neovim is my text editor of choice. I dislike the tendency people often have of weighing Vim/Neovim down with loads of useless plugins. However, there are two that I use which contribute well to speedy and efficient development:
##
fzf
fzf is a command-line fuzzy finder and there
is a plugin that allows its usage from
within Vim/Neovim. It can be configured to fuzzy-find any kind of text content,
but I use it for finding files from within Neovim. The two commands I use are
:Files
and :Buffers
mapped to <Leader>f
and <Leader>b
, respectively.
:Files
fuzzy-finds all files from the current directory, whereas :Buffers
fuzzy-finds only opened buffers. I have fzf configured to open inside a split
where results appear as I type. The results can be cycled between and selecting
an entry will open the file. fzf itself is very fast and its incorporation into
Vim/Neovim saves a lot of time spent hunting for files.
##
Fugitive
Fugitive adds Git integration to Vim/Neovim. The key feature for me is the ability to easily add files to staged changes with a keystroke. Fugitive also makes it trivial to add only specific hunks to staged changes and even just specific lines. It allows me to have fine-grained control over what changes are to be committed and a clear view of those changes with its summary window in which I can open diffs. It is very good and if you use Vim/Neovim and Git then I recommend you use Fugitive.
#
The clipboard problem
I use lemonade for clipboard
usage over SSH which works well, but there’s an issue when switching between
between local and remote. A dtach session started in the context of an X server
will contain the DISPLAY
environment variable which Neovim uses to determine
whether to call xclip
. The problem is that this variable is still present if
the session is attached to later over SSH, which means Neovim executes xclip
instead of lemonade.
The solution is to simply remove the variable from Neovim while it’s running
with :unlet $DISPLAY
and then reload the clipboard provider:
:unlet g:loaded_clipboard_provider
:runtime autoload/provider/clipboard.vim
You can assign this to a function which can be called via a key-binding:
function ResetClipboardProvider()
:unlet g:loaded_clipboard_provider
:runtime autoload/provider/clipboard.vim
endfunction
nnoremap <Leader>cr :call ResetClipboardProvider()<CR>
If you have the opposite problem (session created outside of X) then the
solution is the same except you set the variable rather than removing it: :let $DISPLAY=':0'
.
In windows running a shell you’ll need to export DISPLAY=:0
as appropriate.
#
Putting it all together
There are a couple of shell scripts I use to open all the programs. First, my
work
script:
#!/bin/sh
dtach_dir="$HOME/.dtach"
mkdir -p "$dtach_dir"
dtach -c "$dtach_dir/$(echo "$1" | tr / "\n" | tac | sed '/^\s*$/d' | head -n 1)" \
dvtm-work "$1"
This takes a single argument, which is the directory of a project it changes
into, and spawns a dtach session inside which the dvtm-work
script is called:
#!/bin/sh
FIFO="/tmp/dvtm-status.$$"
[ -p "$FIFO" ] || mkfifo -m 600 "$FIFO" || exit 1
STATUS_PID=$!
cd "$1" || exit 1
dvtm -M -t "$(pwd)" -s "$FIFO" nvim "bash -l" "bash -l"
kill $STATUS_PID
wait $STATUS_PID 2> /dev/null
rm -f "$FIFO"
This script is a small modification of dvtm’s
dvtm-status
script,
the only change being the removal of the time in the status bar and a tweak to
the invocation of dvtm itself. dvtm, upon opening, will open three windows:
Neovim and two instances of bash.
Say I have a project located at projects/my-project
which I want to begin
work on, I just call the work
script with the project’s directory:
$ work projects/my-project
A dtach session will spawn, starting dvtm-work
, which then starts Neovim and
bash. I’m then ready to begin working. I can detach using Ctrl+\
and later
reattach with dtach -a .dtach/my-project
, resuming where I left off.
#
Conclusion
There’s not a huge amount to say about this setup. It’s small, simple and only uses a few components. Its simplicity makes modifications easy. It’s powerful. It’s good at staying out of my way so I can just pursue the task of programming. The result is Vim-powered text editing; fast file access; Git integration with concise in-editor diffs and quick, fine-grained file staging; shell access; all displayed neatly in automatically determined layouts.
##
Why don’t you just use VS Code or similar?
With only a handful of components I’ve satisfied all my requirements for programming tasks. VS Code is bloated software that comes with many features that I’ll likely never use. I believe it’s a better choice to go with something smaller and simpler. If I discover a requirement then there will most likely be a way I can work it into my setup.
##
Neovim has terminal support, why don’t you use it?
I find it a bit cumbersome to have to manually open up splits and call the
:term
command. The idea with dvtm is that layouts are handled automatically
by the software, so when a new window is opened it goes where you expect it to
without any extra fiddling.
##
No NERDTree or similar?
I don’t think file-tree-like explorers suit Vim/Neovim. fzf works well for
fuzzy finding files from within Neovim and I have access to a shell with
programs like ls
and find
for file discovery.