In an Emacs/Cider setup (which is build on top of clojure-mode and paredit-mode), tab stops are usually ignored. Or, say they indent just to the second symbol of an s-expression.
Sometimes, e.g for larger configurations, it's desirable to indent also the subsequent symbols:
This would be the default:
(def config [:hello 34 :goodbye
:a 34 :c
:long-word 0 :a])
What is to do, if it should look like:
(def config [:hello 34 :goodbye
:a 34 :c
:long-word 0 :a])
Emacs will not align the elements in vector as you wish, however, you can use M-i (tab-to-tab-stop) to insert tab (or multiple spaces depends on your config). So you can manually align the elements like the way you like.
If you can live with having your config as a map instead of a vector, clojure-mode does the right thing when you switch on clojure-align-forms-automatically:
(def config {:hello 34
:goodbye [something else]
:a [34 :c]
:long-word 0
:a 'b})
=>
(def config {:hello 34
:goodbye [something else]
:a [34 :c]
:long-word 0
:a 'b})
Related
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)
I am looking for the equivalent of c-indent-level and ruby-indent-level, for asm-mode. That is, I want to force the indentation to 4 spaces, and I want them to be replaced with blanks.
What I've seen tells me it does not exist for asm-mode. Could someone please tell me this is wrong?
I tried this also: Set 4 Space Indent in Emacs in Text Mode , to no av.
I have tried:
(setq tab-width 4)
(setq indent-line-function 'insert-tab)
(setq asm-indent-level 4)
This works however:
(custom-set-variables
'(tab-stop-list (quote (4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 72 76 80 84 88 92 96 100 104 108 112 116 120))))
But I wonder if there is a way to define that for asm-mode only. What if I wanted to keep the default tab behaviour for other modes?
asm-mode uses the function tab-to-tab-stop for indentation, that's why tab-stop-list is working. As far I know there is nothing more that you can do. You might consider using some of the "more advanced" asm modes such as - gas-mode or asm86-mode.
Emacs defines hooks for every (?) major mode. If you do H-m in assembly file, you can see at the end of text section that Assembler mode hook is called `asm-mode-hook'. So you can add your code to run when assembler mode is selected for a buffer like this:
(add-hook 'asm-mode-hook (lambda()
(setq tab-width 4)
(setq indent-line-function 'insert-tab)
(setq asm-indent-level 4)))
Note, tab-width and indent-line-function are already buffer local variables, so setting them changes their value only for the current buffer. This is probably what you want. If you setq some other variables, you may want to make them buffer local using (make-variable-buffer-local VARIABLE) function.
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...
What is a more sane, automatic solution to tabbing my code by 4 spaces for a bunch of files? How do I make sure that tabify does not affect perldoc?
Well, you'll need this
(setq-default tab-width 4)
Then
C-x h
M-x indent-region
This sounds very similar to this other stack overflow question.
I had massive issues with this: This is the solution I came up with for a 3-spaces rule.
;;;; Tab settings ;;;;
;Tab width is 3
(setq tab-width 3)
;Tab width is 3 by default..
(setq-default tab-width 3)
;Use spaces always.
(setq indent-tabs-mode nil)
;Jump by 3.
(setq c-basic-offset 3)
;this defaulted to 4 and had to be reset to 3.
(setq perl-indent-level 3)
;Tab stop list out to col 60
;Manually set by x3
(setq tab-stop-list '(3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 57 60))
You should look up the documentation for the mode you are using (e.g. Lisp mode, C mode, Perl mode) for setting up the desired indentation and for reindenting a region (e.g. in SLIME, this is done with C-M-\).
My cperl-mode seems to indent (or rather, not indent) POD fine, as long as it has a newline before the =head1 or =pod. perlpod says:
Without that empty line before the "=head1", many translators wouldn't have recognized the "=head1" as starting a Pod block.
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.