IDE in the terminal: meet vim and tmux
Integrated Development Environment. That is, an environment what integrates helper tools to help you with your development activities. Now that our environment variables are set up properly, let's get comfortable with the terminal multiplexer tmux and the main part of a development environment: the editor, in our case: vim.
After reading this post, you will probably be more comfortable using the terminal to carry out the task of editing files and make sure they are at least syntax-checked before committing them into the version control system.
Using multiple terminals with tmux
A terminal multiplexer gives you the ability to use (and easily navigate) multiple virtual terminals within the same terminal or terminal emulator window. Like your browser tabs! An additional advantage of using a multiplexer is that the multiplexed sessions don't exit when your SSH connection is terminated. That's why admins and devops people kinda like it.
Screen is most probably installed on your linux distribution / servers, however, it's kind of limited compared to what tmux offers. Feel free to read through the getting started guide, however, for now, it's enough if you learn the basics.
Install and then start it up by typing tmux
! Create and navigate through tabs and splits. Whenever
you create a new pane, your default shell will start up. As you can see, all the tmux-related
shortcuts have a prefix
, Ctrl
-b
. After pressing it, you type in the next letter and the magic
happens.
Action | Shortcut |
---|---|
Split current tab vertically | Ctrl -b % |
Split current tab horizontally | Ctrl -b " |
Switch to the pane left | Ctrl -b ← |
Switch to the pane below | Ctrl -b ↓ |
Switch to the pane above | Ctrl -b ↑ |
Switch to the pane right | Ctrl -b → |
Create new tab | Ctrl -b c |
Switch to the next tab | Ctrl -b n |
Switch to the previous tab | Ctrl -b p |
Show all shorcuts (help) | Ctrl -b ? |
Search help for the word "resize" | /``resize |
Detach session | Ctrl -b d |
Now check the help for how to resize a pane. Split your terminal horizontally (prefix + "
), resize
until it's comfortable (prefix + C-↓ C-↓ C-↓ ‥
), switch to the pane above (prefix + ↑
), start up
vim, and...
Starts to look like an IDE isn't it? Well, there is a lot more to do and I won't show everything. However, at this stage, you can comfortably have a terminal environment running on your jumphost, server, desktop/laptop. Play around and then read along!
Edit in vim and lint on the command line
Reading this blog post means you already know vim somewhat. At least you can exit vim after editing
a piece of text (:q
). Now instead of q
uitting, press Tab
after the colon. Chances are that you
are presented with a lot of commands vim is capable to offer you. And this is only the tip of the
iceberg.
Make sure you have a basic understanding of how vim is a modal editor, where you mostly spend your
time in "Normal" mode (to navigate and edit files) and rarely go into "Insert" mode (to insert
text). Esc
puts you back in normal mode, i
to insert mode, when you start typing a command with
:
, guess what, you are in command line mode. At any time you are lost, just press Esc
a bunch of
times (optimally you already remapped the useless Caps Lock
key to Esc
). A handy command would
be :help
so that whatever vim-related topic / shortcut / command / setting you are interested in,
you can quickly check its documentation.
Let's start with 'Hello World!' - Press i
for insert mode, and mindlessly type in our hello world
program:
if __name__ == '__main__':
print("Hello World!")
Esc
back into normal mode, and save your work with :w hello.py
. Navigate to your tmux bottom
pane prefix + ↓
and check if your program runs:
$ python hello.py
# Output:
# Hello World!
For linting we are usually not interested in actually running our little program. What we can do is to invoke the compiler only:
$ python -m py_compile hello.py
# No output
Now go back to your vim in the upper pane (prefix + ↑
) and add an erroneous line in the python
file. Press G
to jump to the last line of your file, press o
to o
pen a new like for insertion
and type in an obvious syntax error. Something like this:
if __name__ == '__main__':
print("Hello World!")
prin"This should not pass"
Go back to your shell below and observe the compiler's output:
$ python -m py_compile hello.py
# Output:
# Traceback (most recent call last):
# ...
# File "hello.py", line 3
# prin"This should not pass"
# ^
# SyntaxError: invalid syntax
# ...
Now you can go back to vim, hello.py, 3rd line, and fix your syntax.
Summary
Some of these looks cumbersome at a first glance; however, all you needed is available on the command line, and a week's worth of muscle memory training you are going to be faster than clicking around in other IDEs.
This is NOT how I do daily development though. Of course, both vim and tmux can help you a bit here, and enhancing these tools with macros, plugins, proper configuration, the workflow gets unbeatable.
As a sneak peek, if you feel adventurous, read on!
Optional, advanced stuff: meet :make
and the Quickfix list
Here be dragons!
Vim has built-in "error consoles" to help you navigate syntax errors. The flow is the following:
- Edit and save your code / script / descriptor (
:w
) - Run the compiler or linter (
:make
, that invokesmakeprg
) - Observe and acknowledge the compiler output and return to vim (Press
Enter
. Now vim parses the output according toerrorformat
) - Navigate your file by jumping to the lines with syntax errors (
:cfirst
)
By default, vim can understand and parse gcc's error format. The python compiler's output is different, so, bear with me, we need to teach vim how to parse it.
Now this will sound scary, but let's follow this article on fandom to quickly configure
errorformat
and makeprg
. Don't worry if you don't understand much for now. You can always ask
the built-in :help
if you want to dig deeper; here I only want to show you what vim is capable of.
Set makeprg
to a python compiler. We need to invoke :set
to, well, set some configuration
variables. 🤫 If you are adventuorous, also try the :nmap
command!
set makeprg=python\ -c\ \"import\ py_compile,sys;\ sys.stderr=sys.stdout;\ py_compile.compile(r'%')\"
set efm=%C\ %.%#,%A\ \ File\ \"%f\"\\,\ line\ %l%.%#,%Z%[%^\ ]%\\@=%m
" This is magic
nmap <F5> :!python %<CR>
Ready? Jump to the beginning of the file (gg
). Now type in :make
and press enter. The python
compiler runs, and vim shows you it's output, asking you to press enter to continue. You might need
to press enter again.
Your cursor is on the erroneous line now. That's comfy!
What happened here is that vim populated it's so-called Quickfix list with all the errors the compiler emitted. You can easily navigate this list:
Action | Command |
---|---|
Jump to the first error | :cfirst |
Jump to the last error | :clast |
Jump to the previous error | :cfirst |
Jump to the next error | :cfirst |
Open the Quickfix list | :copen |
Well, this is much less cumbersome than switching terminals there and back, chcking line numbers manually. Also, this is already considered advanced vim features; so if you made it down here, you are an advanced vim user! 😉