Screen, Vim, Ruby, and You.

by stltenny

The Background

Over the course of the last few months, I’ve spent a good portion of time maximizing my workspace efficiency. I am occasionally a fan of IDE’s (A heavy Eclipse user in the past), but haven’t exactly been sold on any of the Ruby ones as yet. This efficiency quest has most recently turned me from a Sublime user to a Vim fanatic.

If you are not familiar with Vim, I will not take the time to brief you. Many others have done a much better job on that than I can. For example, Derek Wyatt has a great series here. Some of his tutorials very much got me up to speed with using Vim as my day to day editor.

What I can show is one way that I use Vim in conjunction with a few plugins to get my edit-run-debug cycle down.

Take this use case for example:

Editing ruby code, not working as intended. Use irb/debugger to test it out.

  1. Make change in IRB/Debugger window.
  2. Copy change back into editor.
  3. Recopy code into irb window to test.
  4. Make another change. Copy everything back over.
  5. Forget to copy one line correctly, start from scratch.
  6. Get frustrated. Browse internet. Look for job as racecar driver.

Sound familiar?

Enter Screens, Slime, and Vim.

What follows is a small brief on unix screens, if you see where this is going feel free to skip ahead to the tutorial itself.

‘Screens’ act as independent, persistent, sessions within a single terminal. The screen command will work on almost any *nix environment and is entirely independent of the terminal program you choose. i.e. while I happen to prefer iTerm 2 over the built in OSX terminal, the screen command will be functional across any terminal program. The basic premise of screen is that you can launch one (think of it as an independent full terminal process) and attach/detach from said screen at will. This gives you the ability to run multiple foreground programs in the same terminal window, achieved by switching between screens.  There are tons of features of screens, and could very easily warrant a post on its own, for example screen instances continue running even if you lose connection to the host (think: ssh). For a more in-depth introduction on screen, check out this article.

A key feature of screens we are interested in however, is their ability to receive input from other sources. Just as if you were manually copying and pasting information into multiple terminal windows, screens achieve that functionality and much more.

Put it all together and what do you get?

The Tutorial

Vim -> Slime -> Screen -> Magic.

Vim is your editor, slime acts as a pipe between Vim and your screen, and screen does the heavy lifting.

Let’s get started by installing slime for Vim. You can find the Vim-Slime repository over at github. I personally use Vundle to maintain my Vim plugins but that will be covered in a later post. Install it however you feel comfortable.

Once its installed go ahead and start up a new instance of Vim in a terminal window. Create a new file called screentest.rb and paste the following in.

In another terminal window, we’re going to get a new named session of screen and attach to it.  You can do this by running the following command in your second terminal window.

screen -S session01

This tells screen to start a new session with the name session01 and attach to it. You’ll notice that you will still be in the same terminal window, but your history has cleared. You are currently running in a screen session. Within this session go ahead and launch irb simply with

irb

Once irb is up and running lets go back to our first terminal window with Vim.  Enter visual mode, and select all of the text in your screentest.rb file. A shortcut from normal mode is gg v G $.

Now its time to start slime. Enter the command, C-c C-c (hold control and press c twice).

Since this is the first time you are running slime for this Vim session, this will bring up a prompt on Vim’s command line asking you for your screen session name. This is so slime where knows to send your Vim editor output. Enter session01 as previously named. Next it will ask for the screen window. Since we only have one window in this screen session go with the default of 0.

Vim-Slime will then attempt to “slurp” the highlighted contents of the file into irb which is running in our screen window. After a little bit of time you should see an output similar to.

Voila!. You’re up and running. Slime just sucked in all the code you were editing, and spits it out to the irb console in the adjacent screen to be evaluated.

Using this technique, you can edit your ruby files in Vim, while still maintaining an interactive environment to test your changes in. Slime’s C-c C-c will now by default “slurp” in either the current Vim ‘paragraph’ (typically defined as any text above and below the cursor bounded by blank lines), or if a selection is made in visual mode, the selection itself.

This eliminates entirely the back and forth between editor and irb. Everything is in one place. KEEP IN MIND HOWEVER: The irb session you are in is long running, so variables set previously will still be set, you are not getting a new environment every time slime executes unless you explicitly manage it. You can get fancy and create scratch files that load and clear the irb environment, call require statements, include other modules, and really quickly tune down on whats happening. This is left for future installments.

As an exercise, try making a few changes and running slime with C-c C-c to get a feel for how the evaluation happens. When you are finished, to destroy your screen session, exit irb and hit Ctrl-D. This kills the screen. You should be returned to your original terminal session and with the message: [screen is terminating]. Now lets make a few changes and clean this up.

The Cleanup

For ease of use, I have aliased a command called screenkill to kill all detatched running screens and open a new one. As powerful as screen is, I find using it with slime is still my main use case, especially on my local machine. Dropped right into my .profile file in my home directory, my alias looks something like this:

alias screenkill="screen -ls | grep Detached | awk -F' ' '{print $1}' | xargs -I{} screen -X -S {} kill && screen -S session01"

Running screenkill will do the following.

screen -ls lists all of the current screen processes
grep searches for all detached instances,
awk gets the screen instance id’s of the screen from the first column
xargs (one of my favorites) treats each line on the list of id’s as an individual argument to be executed. in this case the argument -I{} says to substitute {} in the command that follows with a single ID from the list of screens.
screen -X -S terminates each screen with the corresponding id.
Finally, screen -S session01 opens a new screen with the name session01.

Secondly, if you recall, there was quite a bit of wait time after actually executing the Vim-Slime command. To fix this I have a few configurations in my .screenrc file located in my home directory. Similar to your .vimrc file, screen will load its configuration directives from here. My config simply looks like this:

msgwait 0
msgminwait 0

This drops the message input wait time to zero. Meaning when slime slurps your Vim text, it executes almost instantly.

With these in place, you can severely trim your edit-debug-run time, figuring out why those iterators and enumerators aren’t doing exactly what you want a lot quicker.

Finally make sure to check out the Vim-Slime docs as there are a lot of other options to be had within slime.As usual, we are simply scratching the surface.

Happy Hunting.

About these ads