"Hot" Debug and Swap in Common LISP - lisp

One of the features that are unique to Common Lisp that is frequently mentioned is that of the "hot" debug. That is, it is the ability to debug, edit and recompile the production code without stopping or taking the latter off line.
While I see this mentioned all the time, I have yet to see a tutorial on how to do it.
How does one do it in, say, Emacs? Are there some simple examples? Is the feature truly as magical as it seems?

The typical way to do this is to enable SWANK in the application that you want to debug. That way you can use M-x slime-connect from Emacs to connect to the running server. From there, you can do anything you can do with a normal SLIME session. You can even set up the way file names re resolved so that when you use M-. to jump to the source of a function, it will be opened on the remote machine using Tramp.
I think the reason you haven't seen a tutorial on it is because it's a natural thing to do, and there really isn't much of a difference between doing local debugging and working on a remote system.
There is a video of a lecture I did once where I demonstrated some of this, so there definitely are videos out there. However, I think linking to external videos is frowned upon on Stackoverflow.

Some notes I took for myself. I largely agree we should have a tutorial out there. In the CL Cookbook ?
(edit: there's now a more complete example here)
Reading http://readevalprint.tumblr.com/post/101841449553/its-alive-the-path-from-library-to-web-app
Another option is hot swapping all the changes. For this purpose my hunchentoot server also starts a swank server like this:
(defun start-app (&optional (port 8080))
(handler-case (swank:create-server :dont-close t)
(error ()))
…
Swank is, of course, the server-side component of SLIME. It runs on a port that is not accessible remotely and can only be connected to locally or via SSH tunnel. I use the latter to connect SLIME on my PC to Swank running on my server, which allows me to apply various fixes without restarting, either from the REPL or by using C-c C-c to recompile some function.
Connect to a remote Slime server:
Install a Common Lisp implementation on the server. (E.g. sbcl, clisp, etc...)
Install quicklisp on the server.
Load SWANK with (ql:quickload :swank)
Start the server with (swank:create-server). The default port is 4005. [On your local machine] Create a SSH tunnel with ssh -L4005:127.0.0.1:4005 [remote machine]
Connect to the running remote swank server with M-x slime-connect.
The host should be 127.0.0.1 and the port 4005.
(reading an old SO doc page, impossible to link to now).

Related

connect multiple different terminals to the same slime instance

I am still a novice when it comes to working with emacs and slime.
I was wondering if there is a way to start a lisp (say SBCL) on a local port and then connect multiple different slime sessions to it?
For example, if I am using tmux/screen and want to have different emacs sessions between each window, would I be able to connect all the slime instances to the same lisp so that all the emacs sessions were sharing a repl allowing me to compile in any of the emacs sessions and the one running repl will have those changes?
I am using LispWorks 6.1 32 bit Professional Edition. I prefer to use (Spac)emacs for my editing in multiple tmux sessions, one session for each project that I work on.
These are the steps I follow:
Start LispWorks Listener REPL.
Load swank without going through the emacs route:
(load "/path/to/swank-loader.lisp")
(swank-loader:init)
(setf swank:*use-dedicated-output-stream* nil)
(swank:create-server :port 4005 :dont-close t)
Then in my iTerm tab with tmux session for some project 1, I do M-x slime-
connect and connect to host and port as in step 2.
Repeat step 3 for another tmux session with another lisp project code.
With this setup I can load code from multiple projects I am working on in the same lisp image. So far I have not found any major problems while doing so.
This depends on the lisp system you're using, on the features it supports, i.e. whether your SBCL has multi-threading enabled (cf. (member :sb-thread *features*) and on the setting of SWANK:*COMMUNICATION-STYLE*, cf. the Slime docs.

What is the correct way to use emacs/cider while developing a compojure/ring-based application?

What is the correct workflow/pathway of usage of emacs/cider while developing
a compojure/ring-based clojure application?
I feel that I can "attach" to my running compojure/ring-process,
change its code, read/change its data, but I can't understand how do I do it right?
What is the correct way?
What I do?
lein new compojure my-project
cd my-project
lein ring server-headless
The development server runs now. If I change files in the projects they will be automatically reloaded. That is good. But what I'd like to have is that I attach
direct to the process and change its functions for example.
I understand that it is possible, but I can't understand how.
I don't know about correct but I'll throw in my 2 cents.
I start my ring project using immutant which starts a REPL at a specified port. I start cider with M-x cider and connect to the previously specified port. From there I can modify things from the REPL.
I've also seen other people start jetty from inside the REPL though I've never tried this.
There are two main ways of doing what you want. None of them are specific to ring servers, or even to webservers, they'll apply to any Clojure Project.
Both of the methods below should give you a fully functional REPL, with complete control to redefine the functions in your running server, and full CIDER functionality (like being able to debug web-requests to the server).
As usually with CIDER, you can reload changed files with C-c C-k, which will redefine any functions you've changed. There are plenty of other keys for more fine-tuned evaluations as well.
M-x cider-jack-in (or C-c M-j)
As documented on the manual this starts a process with your project and connects a REPL to it. This won't call any functions for you (CIDER doesn't do that), but you can easily start your webserver by calling the corresponding function in the REPL. If the function in question is the -main function, you can do M-x cider-run to call it (bind that to a key if you'd like).
M-x cider-connect
Also as documented on the manual, you can start your webserver from the terminal like you normally would, and then call M-x cider-connect to open a REPL in it. (This is what I used to do a while back).
A bit late to the party. But as I have just to deal with the same issue and found this unanswered question. The answer could be found at:
lein ring server with nrepl doesn't honour cider-nrepl
Basically, use the plugin version 0.9.2 of lein-ring and add to the :ring configuration on project.clj :nrepl {:start? true} and it works

Swank server startup failure

Emacs SLIME can't connect to swank, because apparently swank cannot initialize correctly.
It says some back end function not implemented. However, my swamp backend is SBCL, which is supported. I am using windows xp os.
A similar issue was found posted at the following link, but no solution.Link to similar issue
Am I missing any configuration file for Swank? Or perhaps emacs and SBCL versions I am using have compatibility issues? In that case, where can I get the correct compatibility matrix for windows?
I'm mostly using Linux, but it's very easy to run into conflicts if you have multiple versions of slime/swank code installed.
The best method is to use quicklisp and make sbcl/emacs not use any other code (at least in your first attempt):
sbcl --no-userinit --no-sysinit --load ~/quicklisp/setup.lisp
(asdf:initialize-source-registry '(:source-registry :ignore-inherited-configuration))
(ql:quickload "quicklisp-slime-helper")
(swank:create-server :port 4545 :dont-close t :coding-system "utf-8-unix")
Then start emacs as:
emacs -q -name SLIME -eval '(progn (load (expand-file-name "~/quicklisp/slime-helper.el")) (slime-connect "localhost" 4545))'
http://www.pchristensen.com/blog/articles/installing-sbcl-emacs-and-slime-on-windows-xp
Use this or any other manual, which describes how to install Emacs, sbcl and slime separately. But using the latest releases. Then it will be easier to find the problem than it is now.
This is not exactly an answer to the problem, more of an alternative.
I think some interfaces/ method definitions that Swank expects, need to be implemented by SBCL. I shifted the lisp implementation to CLisp from SBCL, and after some setup tweaking, got it to work. So, I think Swank is fine but SBCL is not.
Just for information, CLisp cannot work with short windows path, the ones that look like "Progra~1", while SBCL expects short paths. CLisp also gave some problem with the temp folder in Windows, for which a variable had to be added to the .emacs file, but after that was setup quickly.
There seem to be lots of differences between the various Lisp implementations' ports to Windows, which would not be a problem had better documentation been present. All this had to be gleaned from different blogs and mailing list.
As soon as a better answer to the original problem comes along, I'll accept that.

What does the 'swank-clojure' do exactly, and do we have 'swank-SOMETHING_ELSE'?

My superficial understanding is that 'swank-clojure' makes 'M-x slime-connect' possible. I mean, it gives a connection to a clojure server something like 'lein swank'. Is my understanding correct? If not, what's the purpose of swank?
Then, is there any 'swank-SOMETHING_ELSE' for other lisp like implementations? For example, swank-clisp?
Do I need 'swank-clojure' for using SLIME/Clojure with 'M-x slime'?
ADDED
I found this link pretty useful.
SLIME and swank form a client server architecture to run and debug lisp programs. SLIME is the emacs frontend and swank is the backend. In between they create a network socket and communicate by sending across messages (S-expressions). In short it is just an RPC mechanism between emacs and the actual lisp backend.
The fact that the slime and swank are separate, are connected over a network and communicate via rpc messages means that they can be anywhere. So, slime can connect to a remote host/port to swank. All other forms you see (lein swank etc etc) do the same. They start swank on a port allowing for a remote connection of slime.
swank-clojure is the clojure port of swank. originally swank-clojure came with a helper elisp file called swank-clojure.el. The job of this file was to enable manual setup of swank parameters like the classpaths, jvm parameters etc. Since other tools like lein came along later, swank-clojure.el was deprecated. But it still lives on at: http://github.com/vu3rdd/swank-clojure-extra and provides the M-x swank-clojure-project which enables starting swank on a lein project.
It should be noted that SLIME originated in (and is still being actively developed for) Common Lisp. Infact, the clojure port of swank only has a subset of the features enjoyed by the original SLIME/swank versions. SLIME exists for all major variants of Common Lisp. There is a partial port of it for Scheme48. There are some partial implementations available under the contrib directory.
If you know that swank is already running on a port, use slime-connect. If you just want to use slime on a project, swank-clojure-project and lein swank seem to be the way to go.
swank-clojure.el is deprecated. Don't use it.
You need slime.el and you need to have swank-clojure "1.2.1" in your dev-dependcies in your project.clj file.
Swank is basically a server that you use slime to connect to from emacs. It it passed, from emacs, what you want run by the Lisp process that it's running.
You should use M-x slime-connect to connect to a swank server after starting with with lein swank.
Swank is the server counterpart to swank clients like emacs SLIME and the MCLIDE lisp development environment for Macintosh. Swank servers exist for many Common Lisp implementations and Lisp dialects such as Clojure and Gambit/scheme.
My understanding is that slime is the emacs part(the client), swank is the common lisp part(the server), swank-clojure is the clojure implementation of the swank server, not the original.

Running Emacs Remotely between several machines

I use Emacs remotely using X-Server in a Windows client and Linux server. I noticed that I can halt it using ctrl-z and then type fg 1 to get it working again. Is there some way that I could get it to halt on the machine that I am on, and then log into a different machine and start where I left off? When I start a new ssh session, the emacs job isn't associated to my terminal. There must be someway to "steal" it.
Also, maybe there's an Emacs feature that will do basically the same thing. However, I think closing and re-opening all my files and buffers would take quite a while.
Expanding on the idea of using emacsclient, you can look at what what someone did to solve the problem of editing a file from a different machine than where (s)he started running Emacs.
As of Emacs 23, you can run emacsclient in terminal windows using the -nw option.
Other solutions you might want to try are to use:
gnu screen
vnc
For years I used screen to "attach" and "detach" from a virtual terminal that sounds like your usage model. If you have the ability to use graphics... vnc is really great, just do your work in a vnc session and connect to it any machine.
And your last idea is already implemented by the package desktop (which is bundled with Emacs). Take a look at the wiki page for session management, which includes other alternatives to desktop, as well as add-ons for desktop to lazily load files.
You can run emacs as a server, and use emacsclient to connect to it. You can open multiple connections to the same emacs server, via ttys or X11.
When doing this, C-X C-C will close your connection, and leave the server running.
A simple way to do this by invoking emacs as follows. This will connect to the server if one is running, or create one.
emacsclient --alternate-editor="" -c
Sometimes I will be at work and have to run out the door leaving my Emacs session as it was. Later, I will open an Emacs instance to the same machine (usually using remote SSH) and find that I have files open in Emacs. Now the good news. Emacs allows you to "steal" those files using M-x recover-this-file. I recommend one of Trey's solutions if you can plan ahead. If not, you can use this recover file technique to keep progress moving.