How can I make emacs keyboard macros work properly when pasting the results of clojure evaluation? - emacs

There's a phenomenally useful feature of emacs lisp where you can evaluate the result of an expression and paste the result directly into a buffer.
Say I want to check addition works. Then I type:
(* 3 2)
and I define the keyboard macro:
(setq last-kbd-macro
[down ?\( ?i ?s ?= ? ?\C-\M-f ? ?\C-u ?\C-x ?\C-e ?\) home])
If I then place point above the expression, and press F4 to execute the macro, the expression turns into:
(is= (* 3 2) 6)
Which makes a nice regression test.
Unfortunately the same keyboard macro executed in a clojure/nrepl buffer results in:
(* 8 9)(is= )
and an error from clojure about not being able to resolve the symbol is=
So I think that something weird is happening to the ordering of things, and the macro is trying to evaluate the wrong thing.
Can anyone get this to work with clojure? (And in fact solve the general problem so that arbitrary keyboard macros work OK with C-u C-x C-e like they do with emacs lisp)
Edit since people seem to be misunderstanding:
Doing the keypresses by hand works fine in either an elisp or a clojure buffer. In one C-u C-x C-e evals with emacs lisp and in the other evals in the external clojure process.
The problem comes when trying to run a keyboard macro (recorded in a clojure buffer) which contains C-u C-x C-e
Running the macro in the clojure buffer, things get re-ordered somehow. It looks like the macro may be carrying on executing even though the eval-paste has not completed yet.
I was wondering if there was a way of forcing the keyboard macro (or corresponding function) to execute in the same order as it would by hand.
I'm quite happy to turn the keyboard macro into a proper elisp function if necessary.

Keyboard macros are a quick and dirty way to repeat a certain sequence of actions. They are very fragile because they remember the keys pressed, not the functions they invoke, so they may produce wildly different results depending on the buffer they are invoked in, the current command history, window configuration and what not.
In your case, chances are that one of the keys in the macro invoke a different command in the clojure/nrepl buffer than in the buffer in which you tested the macro. You really need to define the macro in the buffer in which it will be used.
If you are going to re-use the macro, I suggest that you write a emacs
lisp function which does what you want instead of messing with macros.
You might find the output of (format-kbd-macro nil t) useful, but note that you should not use the commands like eval-last-sexp in your function, use a lower-level function which returns the evaluation result instead of inserting it into the current buffer.

Addressing a problem you haven't had yet, but will soon: don't forget to insert a ' character before the result of evaluating the expression: you want (= (cons 1 nil) '(1)), not (= (cons 1 nil) (1)).

Related

In Slime REPL (GNU EMACS), what is the shortcut to clear the current input

In Slime, I would like to clear the input I have currently typed into the REPL topline. What is the shortcut?
For example, if I type the below, it is missing one parenthesis and will not execute. How do I simply clear the whole text from my input line? I.e. instead of having to manually press delete on each character
(let* ((x 5) (y (+ x x))
(print y))
I could not find anything here:
https://common-lisp.net/project/slime/doc/html/REPL-commands.html
These solutions seem to be different (but please correct me if I'm wrong) and relate to the whole screen, while I'm interested in clearing what I have typed but not yet evaluated:
emacs cider clear REPL buffer
In emacs, how do I bind C-l to clear screen in slime?
It's C-c C-u, which is slime-repl-kill-input. A good trick is to use C-h b which will cause Emacs to show you the current bindings in a help buffer: you can then search through them looking for likely candidates. C-h m is also useful to show help on the current mode, which should show you the bindings as well (but may not: I'm not sure if it always does). The advantage of these things is that they show you what actually exists rather than what the manual thinks exists which may not be the same thing (even when there is a manual...).

Emacs - slime - save current functions to file

I'm starting to play with CLisp, and therefore Emacs too, including the "SLIME" plugin (or whatever it's called. How is it called?)
So I've been playing with the REPL for quite some time now, and defined a lot of functions in there with (defun).
Unfortunately, none of these functions have been written in a text file, and I don't fancy retyping all that. Is there a way I could dump or otherwise save the work that has been done in the REPL to a file? (bonus points if the file is Lisp source code :) )
SLIME is an elisp program for interacting with Lisp.
There's no simple option to recover functions you've typed only into the repl into a file. function-lambda-expression can sometimes return code, but it often does not.
If the repl is still in a buffer, you could copy the whole thing into a file and then use string or regexp replacement to isolate the function definitions.
It's not too hard to avoid this problem in the future.
Most people work by writing definitions into a file, and then using a key combination to send them to Lisp, bypassing the REPL. I use the C-c C-c combination when the cursor is on a function to compile and load the expression. C-x C-e also works. Then I switch the the REPL to actually use the function.
See also the function DRIBBLE, which makes sure a log is written.
foo:~$ clisp
...
[1]> (dribble "foo.text")
#<OUTPUT BUFFERED FILE-STREAM CHARACTER #P"foo.text">
[2]> (+ 3 4)
7
[3]> (defun bar (baz) (* baz baz))
BAR
[4]> (bar 10)
100
[5]> (quit)
Bye.
Let's look at the file:
foo:~$ more foo.text
;; Dribble of #<IO TERMINAL-STREAM> started on 2015-05-08 21:38:48.
#<OUTPUT BUFFERED FILE-STREAM CHARACTER #P"foo.text">
[2]> (+ 3 4)
7
[3]> (defun bar (baz) (* baz baz))
BAR
[4]> (bar 10)
100
[5]> (quit)
Bye.
The last paragraph in Xach's answer is what it is all about.
When programming in Lisp, typing function definitions directly into the REPL is the wrong way to do it. The right way is to set up your text editor (emacs) so that with certain keystrokes, the expression at the cursor (the entire function definition) is sent to the REPL. Then to invoke a function, you switch to the REPL. This is what SLIME is for.
Strictly speaking, the text in your emacs buffer doesn't have to be written to a disk file, in which case it will be gone after you close the editor. But normally you save it to a file.
You can search through your REPL history for the function definitions. If you have the beginning of an expression already typed in, then SLIME will only cycle through previous entries that begin with the same thing:
CL-USER> (defun
Press M-P from there, and you'll cycle through all the defuns you've typed in.

Can I bind some macro-postprocessing to an Emacs abbreviation?

I'm trying to create "smart" abbreviations that expand to some text and then move the cursor. E.g., in C mode I'd like INC to expand to #include <> with the cursor between the <> signs. Or, in HTML mode: BF expanded to <b></b> with the cursor at the right spot.
What's a smart way of going about this (short of defining functions for all this and binding them to a key, which I don't want to do, because I'd prefer abbreviations)?
I would heartily recommend Yasnippets. It seems to be designed to do exactly what you want.
EmacsWiki: Yasnippet
ErgoEmacs summary of Yasnippet
Yasnippet on GitHub
You can install it through Elpa as well.
I think what you are looking for is this:
hippie-expand is an interactive compiled Lisp function in
`hippie-exp.el'. It is bound to M-pause. (hippie-expand arg)
Try to expand text before point, using multiple methods. The expansion
functions in hippie-expand-try-functions-list' are tried in order,
until a possible expansion is found. Repeated application of
hippie-expand' inserts successively possible expansions. With a
positive numeric argument, jumps directly to the arg next function in
this list. With a negative argument or just C-u, undoes the
expansion.
[back]
It is bound to M-pause on my system, probably not on yours yet.
Define abbrev. Than
M-x edit-abbrevs RET
Fourth slot receives a function. For example write:
(lambda nil (forward-char -1))
in order to move backwards one char after expansion.

Emacs Macro to Start in Shell Mode and Run a Command

I have a confession: I don't know Lisp. Despite that fact, with a bit of help from some co-workers, I managed to write an emacs macro/script which:
switched to shell mode (ie. M-x shell-mode)
disabled truncating lines (ie. M-x toggle-truncate-lines)
started a database console (ie. "mysql")
I was then able to start emacs with that macro using the --script option, and suddenly I had a way to start mysql in a much friendlier environment with a single command :-)
But here's the problem: I changed jobs and left that script behind. Now I'd very much like to re-create that script at my new job, but I no longer have any emacs experts to help me write it like I did at the old job.
Now, I really hate SO posts where someone basically says "please write my code for me", so I don't want to do that. However, if any emacs macro experts could at least give me some pointers (like "here's how you invoke a M-x command in a macro"), or point me to an emacs-macro-writing guide, or otherwise "teach me to fish" on this issue, I would greatly appreciate it.
... and if someone just happened to have a similar script already lying around that they wanted to post, I certainly wouldn't complain ;-)
Most emacs commands (i.e., M-x toggle-truncate-lines) can be translated directly to elisp by wrapping them in parentheses:
(toggle-truncate-lines)
The rumours are true, in lisp you just scatter parentheses around and they make magic.
Now in this case, you can do better. Toggling makes sense for an interactive function, but in a program you don't really want to toggle truncate-lines, you want to turn on truncate-lines. Its the same thing if truncate-lines was turned off to begin with, but you don't know when your program will be run next. Anyways, in Emacs, features are often controlled by a variable. In this case, the variable is truncate-lines, and to turn that feature on, you set the variable to t (which means true).
To do this, use:
(setq truncate-lines t)
We use setq instead of = for assignment, because they made lisp before = had been invented.
For the real scoop you should take a look at Robert Chassel's excellent "An introduction to to Programming in Emacs Lisp". It comes built-in with your emacs, you can get to it with C-h i m Emacs Lisp Intro.
A good way (I think) to start writing elisp functions is to record keyboard macros, and then to analyse them using edit-kbd-macro
For example, if you start recording a keyboard macro using f3, then do interactively all the things you want and terminate the macro using f4, you can see the underlying emacs-lisp commands using M-xedit-kbd-macrof4 (this last f4 is the key binding you'd have used to execute the keyboard macro)
<<shell>> ;; shell
<<toggle-truncate-lines>> ;; toggle-truncate-lines
mysql ;; self-insert-command * 5
RET ;; comint-send-input
Now you can write a script using these functions, looking up the documentation (e.g. C-h ftoggle-truncate-lines) to see if you should call them with special arguments in non-interactive mode.
You should also replace self-insert-command by calls to insert.
This should give you something like the following script, which you can call using emacs --load myscript.el
(shell)
(toggle-truncate-lines 1)
(insert "mysql")
(comint-send-input)
Of course, this might not work as expected the first time, so you might have to eval (setq debug-on-error t) to get debugging information.
What version of Emacs are you using?
In Emacs 24, I have M-x sql-mysql, which does everything you ask and has font-locking.

how to write scheme program fast in emacs

(define (cube guess x)
(if (good-enough? guess x)
guess
(improve guess x)))
I'm using emacs+Racket, but when I write in Racket,it doesn't auto-complete.
I also can't write the Anti-brackets in the same line,like this
(define (cube guess x) ). I want to use the 'return' key to make the anti-brackets next line, however the scheme interpreter will compute the expression,then it will be wrong.
then if we write the code in the scheme-mode buffer,it may be some bother, we have to
select the region,then compute in another buffer
Anyone tell me some better ways? sorry for my poor English!
It looks to me like you're using an interactive interpreter, and when you hit the "return" key in the middle of a line, it sends the expression to be evaluated rather than allowing you to edit it further. Is this correct? If so, I would encourage you to take a look at Neil Van Dyke's "Quack" package, which (IIRC) is designed to allow you to edit Racket code using emacs.
If you're not married to emacs, then of course I would also suggest trying to use DrRacket.
It sounds like you're using the scheme interpreter from within Emacs. This is a good start for writing small functions, but you really want to use a REPL (Read-Eval-Print Loop) workflow. Thankfully, Emacs has a ready-made scheme REPL built-in, and has been mentioned elsewhere, there are additional modes (like Quack) that enhance the experience.
In the REPL model, you can freely type expressions in the interpreter if you want to try them out, but most of your coding should take place in the file you're writing. From within that buffer, if you have a scheme interpreter running (M-x run-scheme), then you can send sexps to the interpreter for evaluation without copying manually with C-c C-e. You can use C-M-x to do the same thing.
You can compile the entire file with C-c C-k, and if you have several expression you want to send together, grab them in a region and use C-c C-r to send the region to the interpreter.
There are several other commands that make transferring your code to interpreter easy; you can read more about them in your REPL session by pressing C-h m to describe the keybindings for your current mode.
What does this code even do ? Are you missing the "if" ? That could be part of the reason the interpreter isn't working.?
(if (good-enough? guess x) guess (improve guess x))
Sorry if I just don't understand what you are trying to achieve.