Reading a character without requiring the Enter button pressed - lisp

read-line and read-char both require you press Enter key after typing something. Is there any mechanism in Common Lisp that would allow the program to continue upon the press of any single character immediately, without requiring the additional step of pressing Enter?
I'm trying to build a quick, dynamic text input interface for a program so users can quickly navigate around and do different things by pressing numbers or letters corresponding to onscreen menus. All the extra presses of the Enter key seriously interrupt the workflow. This would also be similar to a "y/n" type of interrogation from a prompt, where just pressing "y" or "n" is sufficient.
I am using SBCL, if that makes a difference. Perhaps this is implementation specific, as I tried both examples on this page and it does not work (I still need to press Enter); here's the first one:
(defun y-or-n ()
(clear-input *standard-input*)
(loop as dum = (format t "Y or N for yes or no: ")
as c = (read-char)
as q = (and (not (equal c #\n)) (not (equal c #\y)))
when q do (format t "~%Need Y or N~%")
unless q return (if (equal c #\y) 'yes 'no)))

read-char doesn't require you to press enter. E.g.,
CL-USER> (with-input-from-string (x "hello")
(print (read-char x)))
#\h
Similarly, if you send some input into SBCL from the command line, it will be read without a newline:
$ echo -n hello | sbcl --eval "(print (read-char))"
…
#\h
After reading and printing #\h, SBCL saw the ello:
*
debugger invoked on a UNBOUND-VARIABLE in thread #<THREAD
"initial thread" RUNNING
{1002979011}>:
The variable ELLO is unbound.
I think this is enough to confirm that it's not that read-char needs a newline, but rather that the buffering of the input is the problem. I think this is the same problem (or non-problem) that's described in a comp.lang.lisp thread from 2008: Re: A problem with read-char. The user asks:
Is it possible to make read-char behave like getch in С when working
with interactive stream (standard-input)? In SBCL read-char wants
"enter" key to unhang from REPL, in C getchar returns immediately
after user press key on keyboard. Probably is possible to run code
that uses read-char with direct console access, aside REPL?
There were four responses (see the thread index to get to all of them). These explain why this behavior is observed (viz., that the Lisp process isn't getting raw input from the terminal, but rather buffered input). Pascal Bourguignon described the problem, and a way to handle this with CLISP (but doesn't provide all that much help, aside from the usual good advice) about working around this in SBCL:
The difference is that curses puts the terminal in raw mode to be able
to receive the characters from the keyboard one at a time, instead of
leaving the terminal in cooked mode, where the unix driver bufferize
lines and handles backspace, amongst other niceties.
…
Now, I don't know about SBCL, (check the manual of SBCL). I only have
the Implementation Notes of CLISP loaded in my wetware. In CLISP you
can use the EXT:WITH-KEYBOARD macro (while the basic output features
of curses are provided by the SCREEN package).
Rob Warnock's response included some workaround code for CMUCL that might or might not work for SBCL:
I once wrote the following for CMUCL for an application that wanted
to be able to type a single character response to a prompt without
messing up the terminal screen:
(defun read-char-no-echo-cbreak (&optional (stream *query-io*))
(with-alien ((old (struct termios))
(new (struct termios)))
(let ((e0 (unix-tcgetattr 0 old))
(e1 (unix-tcgetattr 0 new))
(bits (logior tty-icanon tty-echo tty-echoe
tty-echok tty-echonl)))
(declare (ignorable e0 e1)) ;[probably should test for error here]
(unwind-protect
(progn
(setf (slot new 'c-lflag) (logandc2 (slot old 'c-lflag) bits))
(setf (deref (slot new 'c-cc) vmin) 1)
(setf (deref (slot new 'c-cc) vtime) 0)
(unix-tcsetattr 0 tcsadrain new)
(read-char stream))
(unix-tcsetattr 0 tcsadrain old)))))
SBCL has probably diverged considerably from CMUCL in this area, but
something similar should be doable with SBCL. Start by looking in the
SB-UNIX or maybe the SB-POSIX packages...
User vippstar's response provided a link to what might be the most portable solution
Since you want to do something that might not be portable to a
microcontroller (but the benifit is the much more enhanced UI), use a
non-standard library, such as CL-ncurses.

Adding another answer to point out the existence of this tutorial: cl-charms crash course, by Daniel "jackdaniel" Kochmański. Disabling buffering is related to how the terminal is configured, and cl-charms is a library that exploit the ncurses C library to configure the terminal for interactive usage.

I found cl-charms, which seems to be a fork of the abandoned cl-curses. However, the included example program charms-paint uses 100 % CPU to run the trivial paint application. The problem seems to be that the main loop busy-waits for input.

You could use the trivial-raw-io library to read a single character without pressing Enter. Usage: (trivial-raw-io:read-char). It works on SBCL, CCL, CMUCL, and CLISP on Linux, and should work on other Unix-like operating systems as well. The library has only one simple dependency (the alexandria library), and it is licensed under the BSD 2-clause license.

I've struggled recently with the same issue and I ended up solving it simply by using FFI to interact with termios and disable canonical mode. Essentially that what's mentioned in #JoshuaTaylor's response. I couldn't get that code to work with SBCL, for whatever reason, so I made a few changes. Here is the complete working code (only tested with SBCL):
(define-alien-type nil
(struct termios
(c_iflag unsigned-long)
(c_oflag unsigned-long)
(c_cflag unsigned-long)
(c_lflag unsigned-long)
(c_cc (array unsigned-char 20))
(c_ispeed unsigned-long)
(c_ospeed unsigned-long)))
(declaim (inline tcgetattr))
(define-alien-routine "tcgetattr" int
(fd int)
(term (* (struct termios))))
(declaim (inline tcsetattr))
(define-alien-routine "tcsetattr" int
(fd int)
(action int)
(term (* (struct termios))))
(defun read-single-byte (&optional (s *standard-input*))
(with-alien ((old (struct termios))
(new (struct termios)))
(let ((e0 (tcgetattr 0 (addr old)))
(e1 (tcgetattr 0 (addr new)))
(n-lflag (slot new 'c_lflag)))
(declare (ignorable e0 e1))
(unwind-protect
(progn
(setf (ldb (byte 1 8) n-lflag) 0) ; disables canonical mode
(setf (ldb (byte 1 3) n-lflag) 0) ; disables echoing input char
(setf (slot new 'c_lflag) n-lflag)
(tcsetattr 0 0 (addr new))
(read-byte s))
(tcsetattr 0 0 (addr old))))))
Simply interfacing with termios should do the trick, there is no need for external libraries. You can find on termios's man page more information (https://man7.org/linux/man-pages/man3/termios.3.html), but essentially it's when the terminal is in canonical mode (ICANON) that it needs to wait for a line delimiter before the contents of the buffer become available. I hope this helps!

Related

How can I run a lisp buffer in slime and see its output in emacs?

I have the following code in a buffer (file ~/firsts.lsp):
(defun firsts (l)
(cond
((null l) ())
(T (cons (car (car l)) (firsts (cdr l))))))
(firsts '((A B) (C D) (E F)))
I would like to "run" this script and see the following output (or a reasonable variant thereof):
(A C E)
My buffer shows this mode:
(Lisp [COMMON-LISP-USER cmucl] adoc)
In trying to run it, I tried C-c C-k, which created a buffer slime-compilation that showed the file was "compiled" without errors, but I do not see a way to get the compiled code to execute or run the entire script through the interpreter.
Slime is installed and running (it's what coordinates the compilation). I know that I can run the forms through the repl, in a form by form manner, but I would like to run the entire script interactively.
Software Environment:
Mac OS X 10.12.3
GNU Emacs 25.1.1
Slime ChangeLog dates 2016-04-19
CMU Common Lisp 21b (21B Unicode) but same result with SBCL 1.3.14
One can imagine various ways how a Lisp source editor and a Listener (a read-eval-print-loop) work together. While SLIME is generally quite good, some of the interaction is slightly clumsy.
In this case there I use three ways to evaluate a buffer with SLIME/Emacs:
select the region, then evaluate the region using SLIME
SLIME eval buffer
save buffer, load buffer or compile-and-load buffer using SLIME
Note that if you evaluate things, results are printed in the mini buffer.
You also want to actually print something, so that you can see what happens.
Compiling things before loading/executing can help find errors. I use that often.
The actual list of key-commands for a buffer is seen on control-h m.
Side notes about interaction when evaluating a buffer
Another interaction style would be to feed each expression to a listener/repl buffer, have the results print there, until an error happens or there are no more expressions. But I don't think SLIME supports that in a direct way.
The LispWorks IDE lets you evaluate a buffer and the output (incl. the evaluation results) is displayed in a corresponding output pane.
The Clozure CL IDE lets you evaluate a buffer and the expressions are evaluated in the top most listener. Printed is the output and the last result.

slime prints my (format ...) calls only when called function ends

I have emacs + sbcl + slime installed. I have this function defined
(defun jugar ()
(let* ((nodoActual *nodo-inicial*)
(estadoActual (nodo-estado nodoActual))
(timeStart nil)
(timeEnd nil)
)
(loop while (not (es-estado-final estadoActual)) do
(setf *hojas* 0)
(setf timeStart (get-universal-time))
(setf nodoActual (decision-minimax nodoActual *profundidad* timeStart))
(setf timeEnd (get-universal-time))
(setf estadoActual (nodo-estado nodoActual))
(imprime-en-fichero estadoActual)
(format t "Hojas analizadas: ~a ~%" *hojas*)
(format t "Tiempo empleado: ~a ~%~%" time))
))
that makes a series of calls and print some variables in a loop.
The problem is when I call (jugar) from the *slime-repl sbcl* buffer, the prompt waits until (jugar) execution ends for showing all the (format …) together. I tried the same from a terminal (running sbcl) and it works well, so I guess it is something related to emacs or slime. How can I fix it?
proksid's answer mentions force-output, which is on the right track, but there are actually a few related possibilities. The documentation for force-output also describes finish-output (and clear-output, which isn't relevant for us):
finish-output, force-output, and clear-output exercise control over
the internal handling of buffered stream output.
finish-output attempts to ensure that any buffered output sent to
output-stream has reached its destination, and then returns.
force-output initiates the emptying of any internal buffers but does
not wait for completion or acknowledgment to return.
clear-output attempts to abort any outstanding output operation in
progress in order to allow as little output as possible to continue to
the destination.
If you want to guarantee that the output from the different iterations doesn't get interleaved (I don't know whether this is likely or not), you might want to consider finish-output instead of force-output. In either case, at least be aware of both options.
Add (force-output) after last (format ) call.

Evaluating Elisp in emacs

I am an hour new into programming in Emacs lisp. I have a little experience with scheme so I understand the big picture of lisps in general. However, I have only used the "pure functional" subset of scheme and do not know how to do practical tasks.
Write now, I know that C-x C-e will evaluate the code enclosed by the parentheses' by the current cursor position.
I wish to loop from i = 1 to 10 and print the values of i out. How is this done? I tried the following:
(defvar i 1)
(while (< i 11)
(print "i: " i)
(setq i (+ i 1)))
Emacs tells me: invalid function 0.
How do I do this correctly?
Why is emacs telling me invalid function 0
Feel free to give me tips about how to use the scratch buffer (all I know is C-x C-e evaluates) in emacs. Thanks for all the help!
EDIT1: Could someone tell me how to print out sequential values of i using a while loop?
EDIT2: When I evaluate the code, it opens up another tiny buffer showing each value of i one at a time. However, it is not a large buffer and only shows values of i from 13 to 19. When I try to get into that buffer, it closes immediately. How do I "scroll" through that tiny buffer? Note that I use emacs 24.3 through the terminal
EDIT3: I figured out that the tiny buffer is the Messages buffer. Is there a better way to view the output of my elisp code? The Messages buffer is full of other junk from evaluating things in emacs.
First and foremost, enable "Enter debugger on error" from the Options menu now and add (setq debug-on-error t) or (custom-set-variables '(debug-on-error t)) to your ~/.emacs.el.
Then you will get a *Backtrace* buffer on C-x C-e:
Debugger entered--Lisp error: (invalid-function 1)
1(10)
print("i: " 1)
(while (< i 11) (print "i: " i) (setq i (+ i 1)))
eval((while (< i 11) (print "i: " i) (setq i (+ i 1))) nil)
eval-last-sexp-1(nil)
eval-last-sexp(nil)
call-interactively(eval-last-sexp nil nil)
command-execute(eval-last-sexp)
which shows that the error comes from print.
C-h f print RET will tell you why, but the upshot is that you want to use insert instead of print here.
Just as an added note, since you mentioned knowing some scheme -- if you like the interactive REPL that you can use in typical scheme environment, you might like ielm -- I think it probably stands for Interactive Emacs Lisp mode. Not sure. Anyway, M-x ielm RET will open up an emacs lisp REPL. Sometimes it is actually useful -- for example, when you want to inspect the content of a variable with a lot of data in it, ielm will print the whole thing out. Ielm is built in to my Emacs. Not sure when it was added to the standard distribution, but the earliest copyright in the source says 1994, so it is probably in your Emacs.
You can evaluate Emacs-Lisp sexps in *scratch* or in any other buffer in the same mode or (my preference) in mode emacs-lisp-mode.
In *scratch* you need only hit C-j (newline) after a sexp to evaluate it. In an emacs-lisp-mode buffer you can, as you said, use C-x C-e after a sexp. Or you can use M-x evaluate-region after selecting one or more sexps. As always, C-h m in any mode tells you about it, and usually lists important key bindings.
You can also check a global variable value using C-h v SOME-VAR. And you can evaluate any sexp on the fly from the minibuffer, using M-:. For example: M-: (setq foo (+ 42 (length bar)))
Wrt the debugger:
As #sds mentioned, debug-on-error puts you in the debugger when an error is raised. You can also set debug-on-quit and then enter the debugger using C-g to quit (e.g., during a loop).
If you know the function you want to debug, you can use M-x debug-on-entry.
Step through the debugger using d, or skip to the end of a step using c. Use q to quit the debugger.
You can also insert calls to function debug in source code, as debugger entry points: (debug).
The backtrace in the debugger is always more informative if you load the relevant source file e.g., foo.el, instead of the byte-compiled file, e.g., foo.elc. So before you use M-x debug-on-entry use C-h f to find out which file the function is defined in, and then load that file using M-x load-file /path/to/the/file.el.
There is also another debugger, besides debug -- look for edebug in the Elisp manual. Some people prefer edebug; I prefer debug.

Expand a macro form completely

I'd like to learn the internals of Lisp, so I want to see how everything is implemented.
For example,
(macroexpand '(loop for i upto 10 collect i))
gives me (in SBCL)
(BLOCK NIL
(LET ((I 0))
(DECLARE (TYPE (AND NUMBER REAL) I))
(SB-LOOP::WITH-LOOP-LIST-COLLECTION-HEAD (#:LOOP-LIST-HEAD-1026
#:LOOP-LIST-TAIL-1027)
(SB-LOOP::LOOP-BODY NIL
(NIL NIL (WHEN (> I '10) (GO SB-LOOP::END-LOOP)) NIL)
((SB-LOOP::LOOP-COLLECT-RPLACD
(#:LOOP-LIST-HEAD-1026 #:LOOP-LIST-TAIL-1027)
(LIST I)))
(NIL (SB-LOOP::LOOP-REALLY-DESETQ I (1+ I))
(WHEN (> I '10) (GO SB-LOOP::END-LOOP)) NIL)
((RETURN-FROM NIL
(SB-LOOP::LOOP-COLLECT-ANSWER
#:LOOP-LIST-HEAD-1026)))))))
But LOOP-BODY, WITH-LOOP-LIST-COLLECTION-HEAD, etc. are still macros. How can I expand a macro form completely?
To see the full expansion one needs to walk the Lisp form on all levels and expand them. For this it is necessary that this so-called code walker understands Lisp syntax (and not just s-expression syntax). For example in (lambda (a b) (setf a b)), the list (a b) is a parameter list and should not be macro expanded.
Various Common Lisp implementations provide such a tool. The answer of 6502 mentions MACROEXPAND-ALL which is provided by SBCL.
If you use a development environment, it is usually provided as a command:
SLIME: M-x slime-macroexpand-all with C-c M-m
LispWorks: menu Expression > Walk or M-x Walk Form, shorter M-Sh-m.
The other answers are excellent for you question but you say you want to see how everything is implemented.
Many macros (as you know already) are implemented using macros and whilst macroexpand-all is very useful but you can lose the context of what macro was responsible for what change.
One nice middle ground (if you are using slime) is to use slime-expand-1 (C-c Enter) which shows the expansion is another buffer. You can then useslime-expand-1 inside this new buffer to expand macros in-place.
This allows you to walk the tree expanding as you read and also to use undo to close the expansions again.
For me this has been a god-send in understanding other people's macros. Hope this helps you too, have fun!
You can try to use MACROEXPAND-ALL but what you may get is not necessarily useful.
In something like LOOP the real meat is the macro itself, not the generated code.
(Note: If you're not interested in portability, SBCL provides macroexpand-all, which will do what you're after. If you're after a portable solution, read on...)
The quick-and-dirty solution would be to macroexpand the form itself, then recursively macroexpand all but the first element of the resulting list. This is an imperfect solution; it will fail completely the moment it attempts to process a let's bindings (the first argument to let, the list of bindings, is not meant to be macroexpanded, but this code will do it anyway).
;;; Quick-and-dirty macroexpand-all
(defun macroexpand* (form)
(let ((form (macroexpand form)))
(cons (car form) (mapcar #'macroexpand (cdr form)))))
A more complete solution would consider special forms specially, not macroexpanding their unevaluated arguments. I could update with such a solution, if desired.

How to break out of an infinite loop in emacs lisp ? (environment: emacs)

I tried using ctrl-c then :a
But It doesn't work here.
My code is like:
(defun game-repl()
(loop (print (eval (read)))))
then I run
(game-repl())
look()
(require 'cl)
(loop (setq x (read))
(if (eq x 'exit)
(return)
(print (eval x))))
Emacs modes often send an interruption signal to the inferior program only when you hit Ctrl-C twice in a row (i.e., the key sequence you are looking for is C-c C-c). In particular, this is true for SLIME.
This is because C-c is a prefix key that is usually combined with other keys to access a whole bunch of mode-specific features.
This question can refer to:
how to programmatically break out of a loop that would otherwise be infinite or
how to manually stop an infinite loop that's already raging.
The 1st has satisfactorily been answered by #fred-foo (and it seems it was OP's actual question). The 2nd has been tackled by #matthias-benkard but his answer is not working for emacs lisp.
The actual answer to manually stop a running infinite emacs-lisp loop is Ctrl+g (C-g in emacs-speak).
There is a documentation page in the emacs lisp manual on this very topic.
Sorry, I don't have the reputation to just amend #matthias-benkard's answer and the question ranks high on search engines...
[Reference http://www.psg.com/~dlamkins/sl/chapter05.html]
Most of the time you write a LOOP form, you'd like to have a way out. Fortunately, a RETURN form anywhere inside will cause control to leave the LOOP; any value you specify becomes the value of the LOOP form:
? (loop
(print "Here I am.")
(return 17)
(print "I never got here."))
"Here I am."
17
RETURN is normally used in a conditional form, like this:
? (let ((n 0))
(loop
(when (> n 10) (return))
(print n) (print (* n n))
(incf n)))
0 0
1 1
2 4
3 9
4 16
5 25
6 36
7 49
8 64
9 81
10 100
NIL
?
This Stack Exchange answer is the first hit on google for "break a never ending loop slime"
C-c C-b
What is missing, is that different lisps handle this break differently. I found this answer because GNU Clisp just doesn't intercept SLIME's C-c C-b. Nor does it do what SBCL does which is intercept both C-c C-b and C-c C-c.