I am working in Haskell and frequently come across code similar to the following:
func i j | i == j = i
| otherwise = j
I want to align on the '=' character using align-regexp but don't have the elisp knowhow. I have tried just doing " = " without the quotes, but this inserts an unwanted space character before each '='. I have found a proposed solution here but I can't seem to get that to do anything at all.
Please help me write a function or hard-coded macro that will allow me to set a keybinding for this.
C-u M-x align-regexp RET \(\s-*\) = RET 1 RET 0 RET n
(n.b. there's a space after the '=', but it's not very obvious.)
Which is to say...
Use a prefix argument to tell align-regexp to ask you for more parameters than it does by default.
See C-h f align-regexp and C-h v align-rules-list for details, but in short:
\(\s-*\) is the default 'group' for deletion/expansion. We append our pattern to the end of that: ' = '. (Note that \s- is Emacs regexp syntax for whitespace.)
1 simply refers to parenthesised group 1 (as above). This is the default.
0 for the spacing to use between the two parts of the line. By default this is 1, and is why you were ending up with an additional space.
n to not align any subsequent pattern matches after the first in each line.
edit: Actually, the Q&A you linked to is near identical, and works fine for me on Emacs 23.2.1, so this is a duplicate, but to continue and answer the key-binding aspect:
You can bind that (or any) sequence via keyboard macros. Here's the end result, which you can probably just add to your init file, although I recommend you go through the process yourself. Use whatever you like in place of C-c a for the key. C-c (letter) and F5-F9 are reserved for end-users to bind as they please, so one of those will be safe from being clobbered by a mode's keymap.
(global-set-key (kbd "C-c a") (lambda (&optional arg) "Keyboard macro." (interactive "p") (kmacro-exec-ring-item (quote ([21 134217848 97 108 105 103 110 45 114 101 103 101 120 112 return 32 61 32 return return backspace 48 return 110] 0 "%d")) arg)))
I did that by:
selecting the text.
F3 to start recording.
performing the align-regexp as above (being careful to type everything verbatim, and not use minibuffer history or yanking).1
F4 to stop recording.
C-x C-k n align-single-equals RET to give the macro a name
M-x insert-kbd-macro RET align-single-equals RET to get the lisp.
Wrapping the (lambda) expression with (global-set-key) to bind it. (Although you could also use the (fset 'align-single-equals ...) code as provided, and then bind the key to that symbol.
1 If you make a mistake when recording a complicated macro, don't fret — Emacs provides a really good macro editor which you can use to fix any mistakes after you finish recording (just type C-x C-k e), so you don't need to be perfect.
edit 2: May as well add an example of a function, as per comments.
(defun my-align-single-equals ()
"Align on a single equals sign (with a space either side)."
(interactive)
(align-regexp
(region-beginning) (region-end)
"\\(\\s-*\\) = " 1 0 nil))
(global-set-key (kbd "C-c a") 'my-align-single-equals)
Related
When in evil-mode, I can make the cursor go down 3 lines by command 'C-u 3 M-x evil-next-line' , but how can I make the cursor go down 3 lines by just pressing J?
1. Short answer
Add this to your .emacs file:
(evil-define-motion evil-next-line-3 (count)
"Move the cursor 3 * COUNT lines down."
:type line
(let (line-move-visual)
(evil-line-move (* 3 (or count 1)))))
Note that J is currently bound to evil-join.
If you are ok to rebind it, just add:
(define-key evil-normal-state-map "J" 'evil-next-line-3)
Now, to join lines, you may either type M-x evil-join RET or bind something else to evil-join (see below).
Note that, if you type 2J, you'll move twice 3 lines down, which is more or less 6 lines down... and C-u J will move 4*3 = 12 lines down.
2. Not so short answer (what I actually did)
I never used evil-mode... so I tried to add this package and enabled the evil-mode (which is ok for me since I know the main vi commands and I know how to disable it with C-- M-x evil-mode RET).
When evil-mode is enabled and I type C-h k J, the Help buffer says:
J runs the command evil-join (found in evil-normal-state-map),
which is an interactive compiled Lisp function in ‘evil-commands.el’.
It is bound to J.
(evil-join BEG END)
Join the selected lines.
Then I typed C-h k j, clicked the evil-commands.el link from the Help buffer and copied and adapted the definition of the evil-next-line function to the evil-next-line-3 function and bound it to J.
In case you want to go back to the previous binding of J (or want to bind it to something else), you can evaluate something like:
(define-key evil-normal-state-map "J" 'evil-join)
I'm just starting to learn emacs (woohoo!) and I've been mucking around in my .emacs quite happily. Unfortunately, I don't know Lisp yet, so I'm having issues with the basics.
I've already remapped a few keys until I fix my muscle memory:
(global-set-key (kbd "<f9>") 'recompile)
That's fine. But how can I tell a key to 'simulate pressing several keys'? For instance, I don't know, make <f1> do the same as C-u 2 C-x } (widen buffer by two chars).
One way is to look up that C-x } calls shrink-window-horizontally, and do some sort of lambda thing. This is of course the neat and elegant way (how do you do this?). But surely there's a way to define <f1> to send the keystrokes C-u 2 C-x }?
Sure there is, and it's the obvious way:
(global-set-key (kbd "<f1>") (kbd "C-u 2 C-x }"))
For anything long-term, I would recommend the approach shown by seh, as that will naturally be more robust in most situations. It requires a little more work and know-how, of course, but it's all worthwhile :)
angus' approach is like a cut-down version of the keyboard macros feature that gives Emacs its name (and slightly simpler to use than macros for the example in question). You should definitely be aware of macros, however -- they can be exceedingly useful, and for anything more complicated it quickly becomes far easier to record one dynamically than to write out all the individual keys manually.
Here's the summary I wrote myself of the most important bits:
;;;; * Keyboard macros
;; C-x ( or F3 Begin recording.
;; F3 Insert counter (if recording has already commenced).
;; C-u <n> C-x ( or F3 Begin recording with an initial counter value <n>.
;; C-x ) or F4 End recording.
;; C-u <n> C-x ) or F4 End recording, then execute the macro <n>-1 times.
;; C-x e or F4 Execute the last recorded keyboard macro.
;; e or F4 Additional e or F4 presses repeat the macro.
;; C-u <n> C-x e or F4 Execute the last recorded keyboard macro <n> times.
;; C-x C-k r Apply the last macro to each line of the region.
;; C-x C-k e Edit a keyboard macro (RET for most recent).
;; C-x C-k b Set a key-binding.
;;
;; If you find yourself using lots of macros, you can even name them
;; for later use, and save them to your init file.
;; M-x name-last-kbd-macro RET (name) RET
;; M-x insert-kbd-macro RET (name) RET
;;
;; For more documentation:
;; C-h k C-x (
;; M-: (info "(emacs) Keyboard Macros") RET
If we play with the example from the question, you'll see how some of these things tie together...
To begin with, you can define the macro with F3C-u2C-x}F4
You could then bind it temporarily to F1 with C-xC-kbF1 (actually that's not true if F1 is currently a prefix key for an existing keymap, as typing it interactively will simply prompt for the remainder. You can circumvent this in code with (global-set-key (kbd "<f1>") ...), but I would suggest sticking to the reserved bindings).
If you then use describe-key (C-hk) to examine what is bound to that key, Emacs will show you a (lambda) expression which you could copy to your init file if you so wished.
Alternatively, you could name the macro and ask Emacs to insert the code into the current buffer:
M-x name-last-kbd-macro RET (name) RET
M-x insert-kbd-macro RETRET
This code will look different to the lambda expression shown by describe-key, but if you evaluate the inserted macro, you'll see the equivalence. You can likewise show that the (kbd "...") expression also evaluates to the same value, and therefore these are all just alternative ways of doing the same thing.
(You can use the *scratch* buffer to evaluate the code by moving point after the end of the expression, and either typing C-xC-e to show the value in the minibuffer, or C-j to insert the value into the buffer).
Note that the 'inserted' code uses fset to assign the macro to a symbol. You could bind the macro to a key either by executing the (fset) and then assigning that symbol to a key with (global-set-key), or you could ignore the (fset) and simply assign the macro value directly. This, of course, is directly equivalent to angus' answer.
Edit: I've just noticed that there's a kmacro-name-last-macro function bound to C-xC-kn which is nearly identical in form to name-last-kbd-macro, but which generates the lambda expression form seen when using kmacro-bind-to-key (C-xC-kb) and describe-key.
I'll use shrink-window-horizontally as the example function, but you can generalize the idea to any bindings you'd like to define.
If you want to use two as the default amount to shrink the window, rather than one, try the following:
(global-set-key [f9]
(lambda (&optional n)
(interactive "P")
(shrink-window-horizontally (or n 2))))
That binds the F9 key to an interactive function accepting a prefix argument. If you just press F9, you'll pass no argument, which summons the default value of 2, as the parameter n will receive nil as an argument. However, if you press, say, C-u 10 F9, you'll pass ten as the argument for n. This allows you to use your binding more flexibly.
general-simulate-key from general.el works better (in my case a sequence with popups and changing keymaps that I couldn't get to work with macros): https://github.com/noctuid/general.el#simulating-keypresses
Imagine I've got the following in a text file opened under Emacs:
some 34
word 30
another 38
thing 59
to 39
say 10
here 47
and I want to turn into this, adding 1 to every number made of 2 digits:
some 35
word 31
another 39
thing 60
to 40
say 11
here 48
(this is a short example, my actual need is on a much bigger list, not my call)
How can I do this from Emacs?
I don't mind calling some external Perl/sed/whatever magic as long as the call is made directly from Emacs and operates only on the marked region I want.
How would you automate this from Emacs?
I think the answer I'm thinking of consist in calling shell-command-on-region and replace the region by the output... But I'm not sure as to how to concretely do this.
This can be solved by using the command query-replace-regexp (bound to C-M-%):
C-M-%
\b[0-9][0-9]\b
return
\,(1+ \#&)
The expression that follows \, would be evaluated as a Lisp expression, the result of which used as the replacement string. In the Lisp expression, \#& would be replaced by the matched string, interpreted as a number.
By default, this works on the whole document, starting from the cursor. To have this work on the region, there are several posibilities:
If transient-mark-mode is turned on, you just need to select the region normally (using point and mark);
If for some reason you don't like transient-mark-mode, you may use narrow-to-region to restrict the changes to a specific region: select a region using point and mark, C-x n n to narrow, perform query-replace-regexp as described above, and finally C-x n w to widen. (Thanks to Justin Smith for this hint.)
Use the mouse to select the region.
See section Regexp Replacement of the Emacs Manual for more details.
Emacs' column editing mode is what you need.
Activate it typing M-x cua-mode.
Go to the beginning of the rectangle (leave cursor on character 3) and press C-RET.
Go to the end of the rectangle (leave cursor on character 7). You will be operating on the highlighted region.
Now press M-i which increments all values in the region.
You're done.! remove dead ImageShack links
It doesn't protect against 99->100.
(defun add-1-to-2-digits (b e)
"add 1 to every 2 digit number in the region"
(interactive "r")
(goto-char b)
(while (re-search-forward "\\b[0-9][0-9]\\b" e t)
(replace-match (number-to-string (+ 1 (string-to-int (match-string 0)))))))
Oh, and it operates on the region. If you want the entire file, then you replace b and e with (point-min) and nil.
Moderately tested; use M-: and issue the following command:
(while (re-search-forward "\\<[0-9][0-9]\\>" nil t) (let ((x (match-string 0))) (delete-backward-char 2) (insert (format "%d" (1+ (string-to-int x))))))
I managed to get it working in a different way using the following (my awk-fu ain't strong so it probably can be done in a simpler way):
C-u M-x shell-command-on-region RET awk '$2>=0&&$2<=99 {$2++} {print}' RET
but I lost my indentation in the process : )
Seeing all these answers, I can't help but have a lot of respect for Emacs...
Is there a way to convert an emacs macro into elisp, not like what M-x insert-kbd-macro does, the actual activity becoming elisp statements.
Thanks for your help.
Nope, sorry. There is no trivial way to convert an emacs macro into elisp.
Update: There's been some work on Emacs to start down this path. See this thread as a starting point. It's still not possible (June 2010), but there's activity.
The first reason I can think of is dealing with interactive commands and translating keystrokes into proper arguments for functions.
Think of the following sequence:
C-x b .em TAB RET
This begins the command to switch to a buffer, types three characters, uses TAB completion to complete it and RET to accept. The equivalent lisp for the end result (in an emacs session where the TAB completion is unique) is:
(switch-to-buffer ".emacs")
Thinking of completion, there are also interactions with expansion of all types (dabbrev, hippie-expand, etc.).
A starting point can be M-x edit-last-kbd-macro which (in my case) shows this:
;; Keyboard Macro Editor. Press C-c C-c to finish; press C-x k RET to cancel.
;; Original keys: C-x b .em <tab> RET
Command: last-kbd-macro
Key: none
Macro:
C-x b ;; switch-to-buffer
.em ;; self-insert-command * 3
<tab> ;; pabbrev-expand-maybe
RET ;; newline-and-indent
Which at least gives you some of the function names. But you'll see that RET is labeled as 'newline-and-indent which is incorrect because at the time of the macro execution, the minibuffer is active and the binding is in fact 'minibuffer-complete-and-exit. Similarly, the proper binding for TAB is 'minibuffer-complete.
I made a package that allows pretty much exactly this at https://github.com/Silex/elmacro
It has some quirks but it works pretty well... for example, the following macro:
F3 C-e M-b M-u C-a C-n F4
Generates the following elisp:
(defun upcase-last-word ()
"Change me!"
(interactive)
(move-end-of-line 1)
(backward-word 1)
(upcase-word 1)
(move-beginning-of-line 1)
(next-line 1 1))
When using insert-kbd-macro to save a named keyboard macro I get "unreadable" Lisp code like
(fset 'ppsql
(lambda (&optional arg) "Keyboard macro." (interactive "p") (kmacro-exec-ring-item (quote ([134217788 134217765 44 return 44 17 10 return 33 134217765 102 102 backspace 114 111 109 return 17 10 102 111 109 backspace backspace 114 111 return 33] 0 "%d")) arg)))
I'd rather have something like the following:
(fset 'move-line-down
[?\C-a ?\C-k delete down ?\C-y return up])
IIRC I used the same method to record, name, and insert both keyboard macros: F3, F4, name-last-kbd-macro.
Is it possible to get the first macro in a readable format?
The keyboard macro functionality in Emacs stands of two modes: macros and kmacros. The former returns the macro in a way you like—the symbol form—, the latter provides the lambda form. So that, if you call name-last-kbd-macro you get a symbol form, if you call kmacro-name-last-macro, you get a lambda form.
Thanks for that!
So the naming of the macro determines the format when inserting?
I've conducted some more experiments and noticed that M-x insert-kbd-macro RET RET would give me the "symbol-form".
Whereas M-x insert-kbd-macro RET pp2sql RET gives the "labmda-form" (after naming with name-last-kbd-macro).
Now I realize that I've all the way used name-last-kbd-macro in my earlier experiments...?
I've never seen the first form. The second form is what I'm used to. Did you try re-recording the first macro to see what happens if you're sure you record, then name, then insert?
The other thing to try is "C-X (", which invokes kmacro-start-macro and "C-X )" kmacro-end-macro, rather than F3/F4,which are doing something extraneous about keeping a counter. Maybe the simpler keyboard macro command will work more straightforwardly.