15

I want to define two key-bindings to indent/unindent region by 4 spaces.


Before:

hello
world
foo
bar
  • Visually select world and foo.
  • Type >

After:

hello
    world
    foo
bar

I also want to bind < to unindent region.
I'm not familiar with emacs, please help.

kev
  • 155,172
  • 47
  • 273
  • 272
  • Point out your actual work. ie.. the mode/language that you are working in. It is possible that it may have already this functionality. – aartist Jul 25 '12 at 02:03
  • I made functions for tabbing / untabbing regions in this answer: http://stackoverflow.com/questions/2249955/emacs-shift-tab-to-left-shift-the-block/35183657#35183657 – Stanley Bak Feb 03 '16 at 17:27

4 Answers4

26

There are already keyboard shortcuts for that:

Indent: C-u 4 C-x TAB

Unindent C-u - 4 C-x TAB

If you find that too long to type, you could put the following in your .emacs file:

(defun my-indent-region (N)
  (interactive "p")
  (if (use-region-p)
      (progn (indent-rigidly (region-beginning) (region-end) (* N 4))
             (setq deactivate-mark nil))
    (self-insert-command N)))

(defun my-unindent-region (N)
  (interactive "p")
  (if (use-region-p)
      (progn (indent-rigidly (region-beginning) (region-end) (* N -4))
             (setq deactivate-mark nil))
    (self-insert-command N)))

(global-set-key ">" 'my-indent-region)
(global-set-key "<" 'my-unindent-region)

With this code the greater than (>) and less than (<) keys will indent/unindent a marked region by 4 spaces each.

Thomas
  • 17,016
  • 4
  • 46
  • 70
  • Thanks. Can I re-select previous region? So that I can indent several times. – kev Jul 24 '12 at 05:47
  • 1
    I just edited the code to keep the region active. But you can generally reselect by typing `C-x C-x`. And then you could also use a prefix argument: `C-u 2 >` will indent by 8 spaces, for example. – Thomas Jul 24 '12 at 05:55
  • @kev You can also always repeat the previous command in Emacs by typing `C-x z`. If you want to repeat it more than once, keep typing `z` multiple times. – Thomas Jul 15 '13 at 17:59
  • I added this code to .emacs file but its still showing `C-c >` undefined, I restarted emacs btw – pahnin Jul 23 '13 at 04:30
  • Just to note here that to indent and unindent the first line of your region, you need to select one row extra at the start of the marked region. But pretty awesome! – Mauricio A. Cinelli Nov 13 '13 at 11:52
  • See @seth2810's answer for the Emacs way to get the beginning and end of region (`region-beginning` and `region-end` instead of taking min and max of `point` and `mark`). And it has a bit of "DWIM": if the region is not active, it operates on the current line. – Davor Cubranic Dec 11 '13 at 21:22
  • @DavorCubranic Thanks for that, I've updated my answer accordingly. – Thomas Dec 12 '13 at 09:27
  • How would I write the key combination for `ctrl + >` or `ctrl + <`? Simply writing `"C->"` and `"C-<"` doesn't work. (`global-set-key: Key sequence C - > starts with non-prefix key C`) Nevermind, I fugured it out, will write an answer. – Zelphir Kaltstahl Nov 22 '15 at 19:23
2
(defun keyboard-indent (&optional arg)
  (interactive)
  (let ((deactivate-mark nil)
        (beg (or (and mark-active (region-beginning))
                 (line-beginning-position)))
        (end (or (and mark-active (region-end)) (line-end-position))))
    (indent-rigidly beg end (* (or arg 1) tab-width))))

(defun keyboard-unindent (&optional arg)
  (interactive)
  (keyboard-indent (* -1 (or arg 1))))
elemakil
  • 3,681
  • 28
  • 53
seth2810
  • 257
  • 2
  • 5
1

In addition to what @Thomas already wrote, you might not want to use the keys < and > for indenting or unindenting. Just image you need to write some HTML and can't enter those characters anymore. This is why I inserted the following in my init file, as key settings:

(global-set-key (kbd "C-<") 'my-indent-region)
(global-set-key (kbd "C->") 'my-unindent-region)

Note: It doesn't work without the (kbd ...). You will get an error:

global-set-key: Key sequence C - > starts with non-prefix key C
Zelphir Kaltstahl
  • 5,722
  • 10
  • 57
  • 86
  • It's not true that you cannot use the `<` or `>` keys anymore in my answer above; rather, the code checks if some part of the buffer is currently selected and only then (un-)indents when you press the appropriate key. If you want to simply insert `<` or `>`, you can so whenever nothing is selected. – Thomas Nov 22 '15 at 22:34
1

You can use replace 4 with tab-width as

(defun indent-region-shift-right-n (N)
  (interactive "p")
  (if (use-region-p)
      (progn (indent-rigidly (region-beginning) (region-end) (* N tab-width))
             (setq deactivate-mark nil))
    (self-insert-command N)))
(defun unindent-region-shift-left-n (N)
  (interactive "p")
  (if (use-region-p)
      (progn (indent-rigidly (region-beginning) (region-end) (* N (- tab-width)))
             (setq deactivate-mark nil))
    (self-insert-command N)))
(global-set-key ">" 'indent-region-shift-right-n)
(global-set-key "<" 'unindent-region-shift-left-n)
Nordlöw
  • 11,838
  • 10
  • 52
  • 99