How do you trap Ctrl-C in the Leiningen REPL? - clojure

How can you trap Ctrl-C in the Leiningen REPL?
set-break-handler! seems to have no effect:
user=> (set-break-handler! (fn [sig] (println "HERE!" sig)))
#object[clojure.repl.proxy$java.lang.Object$SignalHandler$d8c00ec7 0x22e61b57
"clojure.repl.proxy$java.lang.Object$SignalHandler$d8c00ec7#22e61b57"]
user=>
That funny character after the second prompt (if you can see it) is ASCII 3. That's what appeared when I hit Ctrl-C. It appears that Leiningen has disabled the connection between Ctrl-C and the SIGINT signal. (This is on a Linux system.) Leiningen treats the Ctrl-C as just another character. If I hit Enter, the Clojure compiler complains that it can't resolve the symbol . (Again, you might not be able to see it; Ctrl-C is not a printable glyph in most fonts.)
The reason I want this is so I can run some code that I'm experimenting with as an infinite loop, see what it does for a while, stop it, change it a bit, try it again, and so on. I don't actually want to set the INT-handler by calling set-break-handler directly at the REPL. I want to put it into my code so it cleans up its threads and kills its subprocess.
By the way, I thought I'd see if Leiningen is messing with my stty settings, so I typed this:
user=> (clojure.java.shell/sh "stty" "-a")
{:exit 1, :out "", :err "stty: standard input: Invalid argument\n"}
What?? stty -a works fine if I type it at the shell prompt. Is this a clue to the problem?

Related

calva - how to stop the repl?

I'm using vs code with calva on Ubuntu. My clojure app listens on a port and I find that if I exit vs code, it leaves a java process bound to that port which I have to locate and kill before I can start again.
Is there any calva command to stop the repl?, or better still, a way of stopping the repl automatically when I exit vs code?
You are right to expect that the process (if started by Calva) should be owned by Calva/VS Code and that exiting VS Code should kill it. Please report this as a bug on Calva: https://github.com/BetterThanTomorrow/calva This works on MacOS (and I think on Windows too) so please report this from VS Code's help menu so that your system info gets attached.
As for how to kill the REPL. You can press Ctrl+C in the terminal where the process is started. We should add a proper command for it as well, but that's for another day. 😀 (That it gets killed when you disconnect the REPL is a also a bug, I would say.)
From the comments I've figured out that I was really asking the wrong question. I was under the impression that the repl was "owned by" to the vs code process that started it and that not terminating it when you quit vs code was a bug, but really my understanding wasn't right.
So to solve my original problem of leaving a process bound to the port, there are 3 options:
Terminate the repl using clojure (System/exit 0)
Use the calva command to reconnect to the existing repl after restarting vs code
Use calva to disconnect from the repl, then you have the choice of
starting a new one (which automatically will kill the old one) or re-connecting later

Controlling emacs dumb-terminal

I am writing my own lisp interpreter in C++ using emacs as editor and for debugging with gdb. I use termios and escape sequence, to have control about input, so that it is possible to edit a lisp-command in a terminal. My aim is, that my lisp-interpreter should also run in emacs with "M-x run-lisp" and in an ansi-terminal. The problem I have, when I use the debugger, emacs use his own dumb-terminal which don't work with escape-sequences, so debugging becomes difficulty.
I want to know, how it it possible to get control to the dumb-terminal or eterm, or if it is not possible, how can I temporarily control emacs from my program? Maybe if the dumb-terminal is started to run, that I can switch to another terminal like ansi-term in emacs without changing the .emacs file.
If I use the lisp-interpreter sbcl or gcl in emacs with
(setq inferior-lisp-program "sbcl");
or
(setq inferior-lisp-program "gcl");
in .emacs and invoke it in emacs with M-x run-lisp
it seems, that emacs use the dumb-terminal.
and sbcl it is able to edit a lisp-command like
* (* 3
4 )
also you can do this in gcl
> (+ 8
5
7
6
)
over any lines using arrow-keys, backspace and del to edit and Carriage Return evaluate the lisp-command only, until the round brackets "(" and ")" are correctly set.
If sbcl or gcl can do this, there must be a way to control the dumb-terminal of emacs, using arrow-keys, backspace and maybe changing the input after using Carriage-Return when the lisp-command is not finished.
I also recognised, that sbcl are not editible in ansi-terminals but in emacs dumb-terminal. When I experimented with this dumb-terminal, I was also able to edit a line, until Carriage-Return is pressed. After it is pressed, the input-buffer is empty. Maybe the solution is, if the line is after Carriage-Return not finished, I must find a way, to refill this buffer with the old information again. Maybe if I have success with it, I can edit the line until to the next Carriage-Return. But there is another problem! The unfinished line is printed at the next line position. It must be printed at his old position, where I started the input.
Now I can do this only in ansi-terminal with escape sequences and run into troubles during debugging in emacs.
If I want to force to use escape-sequences or ncurses, there I am looking for a way, temporarily without changing the .emacs-file to start another terminal in emacs. Especially if I am debugging. Maybe the dumb-terminal must be killed and an ansi-term-terminal begin to start. This is generally useful, if you debug code, which uses ncurses or escape-sequences in different terminal-programs.

"Hot swapping" code with swank clojure, and crash resilience

I've been messing around with developing a game in clojure, and one thing I've been really excited about is hot swapping in code.
I've been using swank clojure and emacs with the lein-swank plugin.
My main problem has been that of typos. Say I update a function, make a small error, and then hit Ctrl-C Ctrl-C to send it off to the REPL:
(if (> (rand) .5) (println "yay") (println "boo"))
(I should have written 0.5, not .5.)
In that case, the entire program will simply crash and burn, and I'll need to restart the whole thing. Hot swapping is great, but if I can't make even a tiny error then what's the point?
So what exactly is the workflow here? Am I missing something? Or is there a way to make swank clojure more resilient to these little errors? (I imagine that the best thing would simply be to reset to a previous working state, although that may be a little difficult.)
Thanks!
The program shouldn't “crash and burn”—it should raise an exception and throw you into the debugger, which you can dismiss by hitting Q (sldb-quit). After dismissing the debugger, the program is supposed to continue running normally. If this is not what happens, your SLIME configuration is probably broken somehow.
Personally I recommend C-M-x over C-c C-c. I don't think either one should have the problem you're experiencing, though, so switching may not fix it.

read-line not working in clojure REPL

Whenever I call a clojure function that gets a users' console input using (read-line) through SLIME or a normal REPL, the function returns immediately. I've resorted to jar'ing up my project and running it to test but this obviously isn't quick or sustainable.
Is there some trick to getting console interaction through a REPL working or is it not possible? If not are there any good workarounds?
This will work now with swank-clojure 1.4.0-SNAPSHOT if you wrap the call to read-line in swank.core/with-read-line-support like this
(with-read-line-support (println "a line from Emacs:" (read-line))
https://github.com/technomancy/swank-clojure/commit/f4a1eebc4d34f2ff473c4e5350f889ec356f5168
Currently there doesn't seem to be any way of reading console input through swank-clojure; calling (read-line) simply returns nil in 1.4.0-SNAPSHOT and hangs in earlier versions. Installing 1.4.0 as a user-level leiningen plugin seems to be the best bet right now. At least the REPL will return to your control at some point.

How to capture stdout/log output of an agent in SLIME?

I send a task to an agent, but can't see the output of any print statements I've put into the function. How do I trace code execution on agents?
EDIT: Turns out I do get the output in the console, but not in SLIME. The question now is, how to see the output in SLIME?
The key is to start swank from emacs as the inferior lisp process instead of calling lein swank from the shell. One way to do this is to use elein (the command is M-x elein-swank). Then you can either inspect the output in the inferior lisp buffer (which is called *elein-swank* in the example of using elein), or execute slime-redirect-inferior-output and have the output inline in the repl. Clojure.contrib.logging is a useful tool for sending log output.
You could wrap the calls in your repl in (with-out-str (def result (my-code))) to capture the output as a string. this way you can do it for just the code you're working on and you dont have to restart your repl to start getting your output.