Malvineous
Malvineous

Reputation: 27340

Emacs: how to toggle between two tab widths via hotkey

I'm editing two different codebases in Emacs, one uses tabs set to two spaces and one uses tabs set to eight spaces (the Linux kernel). Since the kernel uses tabs for alignment, I would like to adjust my tab size on the fly when I am working on kernel files.

I would like to be able to press M-2 to set the tab width to two, and M-8 to set the tab width to eight. I would like these keys to work in all modes, whether I am working on C code, in a Makefile or even just a normal text file. I want the rest of my active Emacs coding style to remain unchanged.

I'm a bit stuck because you use "setq" in the config files but this isn't a valid command with M-x, and trying to assign a function to the global key M-2 doesn't override the default function assigned to this key, and it seems I may have to use a hook or something for every type of file I want to edit, and this is very quickly getting way over my head!

Upvotes: 0

Views: 268

Answers (3)

Malvineous
Malvineous

Reputation: 27340

I ended up using a combination of immerrr and camdez's answers to achieve what I was after:

(defun set-tab-width (len)
    (interactive "p")
    (setq tab-width len)
    (force-window-update)  ; Required or tabs are only updated line-by-line during editing
    (message "Tab width set to %d." len)
)
(global-set-key (kbd "C-c t") 'set-tab-width)

This allows me to press C-8 C-c t to set a tab width of 8, or C-2 C-c t to set a tab width of two, or any other number to set different tab widths.

Upvotes: 1

camdez
camdez

Reputation: 1644

I know this isn't precisely what you asked for but this is something I actually use in my .emacs to accomplish the same task:

(defun camdez/toggle-tab-width ()
  "Toggles `tab-width' between 8 and 2."
  (interactive)
  (setq tab-width
        (if (= tab-width 2)
            8
          2))
  (message "Tab width set to %d." tab-width))

(global-set-key (kbd "C-c TAB") 'camdez/toggle-tab-width)

It has a fairly logical mnemonic and doesn't clobber any other bindings.

Upvotes: 1

immerrr
immerrr

Reputation: 1273

To bind something to a key, it must be a command, which is Emacs name for function meant to be used interactively, so this is a function:

(defun set-c-basic-offset-2 ()
  (setq c-basic-offset 2))

and this is a command:

(defun set-c-basic-offset-2-command ()
  (interactive)
  (setq c-basic-offset 2))

Now you can do

(global-set-key (kbd "M-2") 'set-c-basic-offset-2-command)

Or, alternatively, you could do

(defun set-c-basic-offset-command (offset)
  (interactive "p")
  (setq c-basic-offset offset))
(global-set-key (kbd "C-c o") 'set-c-basic-offset-command)

And you could use M-2 C-c o and M-8 C-c o to set c-basic-offset to 2 or 8 respectively. Try reading docs for interactive function, it has a lot more to offer.

Upvotes: 4

Related Questions