I started reading Practical Common Lisp yesterday. No discussion about Lisp can be complete without talking about Slime. Slime basically turns Emacs into an IDE for Lisp development. Peter Seibel thinks this is important enough to dedicate the second chapter to it. He even repackaged Lisp + Emacs + Slime as Lispbox to help people get started faster. For an excellent book (so far), available for free, and Lispbox, thank you Mr.Seibel.
After actually downloading, installing, and running Lispbox, I can see the advantages. Slime solves the problems you would have with any interactive REPL-type environment.
Let’s take Ruby’s irb as an example more people are going to relate to:
- you start irb
- you start a text editor (vim, textmate, emacs, …)
- you do a few tests in irb
- you copy and paste to a text editor
- you clean things up in the text editor
- you copy and paste back to irb
- you make a mistake
- you fix things up in the text editor
- you hesitate copying and pasting, because it’s painful now
- you write some tests
- you exit irb and run the tests to do your experiments
Let me present the dilemma another way: irb is great to get answers quick but it is also temporary because you know nothing you do in irb will be saved. However, the moment you start living in a text editor, you give up a lot of the power of REPL. Or, at least, your REPL becomes 10 seconds instead of 1 second. That changes the way you work. And that explains why Slime exists.
Slime creates a new interactive session with Lisp and you are able to copy and paste text from a text buffer to the session with one keyboard shortcut. That’s great! Now you can type, organize, pretty-print your code in a text editor, type C-c C-c to “refresh” the interactive session. This does not close and create a new session, the function definitions are reloaded into the current session. So, all your testing objects, those carefully crafted lists and hashes of objects (or whatnots) still exist—the world just changed around them.
Yeah, Slime is great. I’m just not an Emacs fan.
I did some research and Vim has no mode to support asynchronous sessions like Emacs. In essence, all that’s needed is a software that will spawn what you really want to run, say irb, control stdin/stdout/stderr, capture its own stdin/stdout/stderr and tunnel those to the child process. Also, it would be nice if it could open a port to receive external commands to be able to script stdin…
That’s when I remembered an article I read about scripting gnu-screen. To make a long story short, screen does everything we want, and more.
Here’s what we want to accomplish:
- start a named screen
- name the screen window
- start irb
- start another terminal
- start vim
- define a function/class/object
- have it “transported” to irb
Here are the instructions:
- screen -S session01
- C-a A—window01
- irb
- vim
- (type code)
- vip (select paragraph)
- “ry (copy to register r)
- :call system(“screen -S session01 -p window01 -X stuff ’” . @r . ”’”)
And BLAM, you just did some magic!
At this point, you are coming to 2 realizations:
- this is WAY cool
- you want this automated
Thankfully, I can help with the automation. Get slime.vim and put it in ~/.vim/plugin/ .
A few notes:
- the magic key is C-c C-c (like Slime, surprise!)
- the first time, you’ll be prompted for the “session name” and the “window name”
- subsequent times will be automated
- you can reprompt for “session name” and “window name” with C-c v
- by default, C-c C-c will select the current paragraph and copy-paste it
- but you can make your own selection first, and send it over with C-c C-c
…
As a final note, I’d like to drive the point that this can automate ANYTHING running in a screen:
- bash
- top
- irb
- python
- any lisp/scheme REPL
- mysql
- …
One thing is for sure, this will definitely change the way I work.
(For extra points, write your own Textmate plugin … this hack is not limited to Vim!!)
Couldn’t imagine how would a better writer of skill would write.
Awesome. I’ll try it out.
Not work for my environment (vim in Cygwin in Vista); it says “Command terminated”. Please help.
I neither use Cygwin nor Vista, sorry.
You could try to make it work outside of Vim, directly on the command-line. Using 2 terminals and screen, the “stuff” command of screen will let you script a session externally.
You can refer to the article I mentioned (http://www.jerri.de/blog/archives/2006/05/02/scripting_screen_for_fun_and_profit/) for more details.
Thanks for your reply.
Yes, it works outside Vim.
% screen -p 2 -X stuff ‘(+ 1 2)^M’
But not inside Vim!
:echo system(”screen -p 2 -X stuff ‘(+ 1 2)^M’”)
It says: Command terminated
By the way, this works in Vim (under Cygwin):
!screen -p 2 -X stuff ‘(+ 1 2)^M’
But the problem is that the result is not show in Vim status bar. So I must split Screen and use this instead in function Send_to_Screen(text):
silent exe ‘!screen ‘ . b:screen . ‘ -X stuff “‘ . substitute(escape(a:text, ‘”\’), ‘[\r\n]‘, ‘\r’, ‘g’) . ‘”‘ | redraw!
By the way, “screen -X” do not print any output, unlike for example “ls -l”, so I wonder why ‘echo system(”screen …”)’ shows the result (of another screen) in Vim status bar???
Amazing! This is awesome. Thank you!
Hey I modified the script so that it is now fully automated when there’s only one Screen session attached. Should run on any UNIX system. Here it is:
let g:screen_sessionname = “”
let g:screen_windowname = “”
“”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”
function Send_to_Screen(text)
echo system(”screen” . g:screen_sessionname . g:screen_windowname . ” -X stuff ‘” . a:text . “‘”)
endfunction
function Screen_Vars()
let g:screen_sessionname = “”
let g:screen_windowname = “”
” automatically find the session name if there’s only one
if system(”screen -ls | awk ‘/Attached/ {print $1}’ | wc -l”) == 1
let g:screen_sessionname = ” -S ” . system(”screen -ls | awk ‘/Attached/ {printf \”%s\”, $1}’”)
else
let g:screen_sessionname = ” -S ” . input(”Screen session: “, g:screen_sessionname)
endif
let g:screen_windowname = ” -p ” . input(”Screen window: “, g:screen_windowname)
endfunction
“”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”
vmap “ry:call Send_to_Screen(@r)
nmap vip
nmap v :call Screen_Vars()
Excellent!
I tried your modifications and generalized the idea: provide a list of session names for completion. I overwrote the previous version above.
If there’s only one session name, you press TAB and you’re done.
I also changed the window name to 0 … because there will always be a window named 0. It seems like a better default value.
(I realize my changes don’t automate the case for 1 session name, however)
I discovered bug. The script fails on text region containing single quotes (e.g. Common Lisp sharp quote macro #’). Use a escaped double quote solves.
oh looks like you solve that in the newer version as well lol
So… it works, or not?
If not, can you show me an example where it fails? I tried to reproduce but it worked for me.
Sick,
I have been looking something like this for this for a while!
Thanks,
Courtney
[...] Like Slime, for Vim Scripting screen for fun and [...]
Hey all,
If you only want to code Lisp in Vim, I’d advice you to have a look at my plugin, Limp, which does this and then some more.
It’s available at http://mikael.jansson.be/hacking/limp — I hope you find it useful! I’m always open for suggestions.
Thanks!
– Mikael
I agree with the other comments, this is a great addition to Vim which will definitely make my life easier. Would you consider posting your plugin to vim.org? Thanks a lot for sharing this great script.
[...] Like Slime, for Vim – Turn Vim into an IDE for almost anything using GNU screen… [...]
[...] Jonathon Palardy’s suggestion I’ve added a ‘Send to Screen’ command (ctrl-alt-c) that copies selected text (or [...]
Extra points claimed with this Screen Textmate Bundle.
Just wanted to add another tip/request:
If you do this: C-a Shift-S you get screen to split the shell. Press C-a TAB then C-a C-a until you get vim on top and irb in the lower shell… voila! You now don’t need C-a C-a EVER again :D instant results.
Can it be implemented within the plugin? Something like to start a screen session automatically if not started, then start 2 shells then put vim in one and leave the second one alone (or start irb there). is this a good idea?
Hi there,
I don’t see why this couldn’t be implemented in the plugin. However, I must say that I usually run the destination screen on another terminal, so I never go back and forth.
[...] Like Slime for Vim is a solution that relies almost solely on GNU Screen. No Hyperspec lookup or function completion without additional work, though. [...]
Jonathan,
This is just brilliant!
Hmm. I get an error (using vim7.1)
Error detected while processing function Send_to_Screen:
line 5:
E484: Can’t open file /var/tmp/v916421/2
Any known solutions?
(the v916421 directory is empty)
does it work outside VIM (using the “stuff” command)?
refer to the comments above.
[...] big thing? Screencast: Like Slime, for Vim October 17, 2008 A year ago, I posted Like Slime, for Vim. There was a lot of interest in sticking with Vim but having a way to get something similar to [...]
[...] just found this very nice blog article(http://technotales.wordpress.com/2007/10/03/like-slime-for-vim/) which describes howto controll a ruby-repl inside a screen window, which is a perfect solution for a [...]
[...] emacs. I looked for alternatives that would let me stick with my beloved vi. While many were rather clever, they never came close to the full functionality that Slime [...]
[...] How to replicate SLIME in vim [...]
You have typo’d Peter Seibel’s surname.
@Wodin: thanks! fixed.
Hi, you can use buffer’s local variables (b:screen_sessionname) instead of global variables (g:screen_sessionname). In this way one can have many vim’s tab pages working with different interpreters.
Saludos!
@Jose: good point … I’ll patch that.
Hey!
Thanks. I just got this thing working with Python.
Best!
[...] Clarke que en no es posible distiguir una tecnología suficientemente avanzada de la magia. Esto es magia. (Y como feria, más [...]
I just started using this and I wanted to thank you. It’s awesome and I have another reason to love screen.
Cheers!
Hi, I made a vim plugin using this ideas, it’s name is Vicle. It use vim to edit commands that are sent to the Screen session and save and history of that commands. It is simple but helps a lot :-)
http://www.vim.org/scripts/script.php?script_id=2551
Saludos.
[...] big thanx goes to technotales for explanation of REPL-modes for vim, and Renick for ponting me to REPL, and of course the [...]
Jonathan,
This is crazy wild; great job! The only suggestion I would make is that some might change the keystroke mappings since Control-C is used by Vim to revert from insert mode to command mode. I realize it is my bad habit, but there are times when I will tap Control-C multiple times in my PHP / Java programming and I worry that it will fire off especially if I am not in screen.
Anyhow, this is great; I definitely want to post a link on my blog and get my cubemates using this!
A-
[...] [upmod] [downmod] Like Slime, for Vim « Jonathan’s Techno-tales (technotales.wordpress.com) 3 points posted 7 months, 3 weeks ago by jeethu tags python screen [...]