Indenting with tabs in emacs


01.09.2019

For the last few days I have been trying out emacs. It is quite different to my usual editor, vim, but it can get rather comfortable after a few hours of configuration.

Most things were easiely changable to my linkings (the "evil" package introduces vim-like keybinds and editing modes to emacs). But indentations were not so easy. Emacs by default uses a weird mix of tabs and spaces: It basically indents everything by either 4 or 2 spaces and replaces these with tabs when there are 8 spaces in sequence. That is so far from sanity, that it would make more sense to write my code on paper and compile it by hand.

Any sane person who was ever involved in some semi-serious programming will agree that you either indent with tabs or with spaces. They should never be mixed (with the sole exeption of using spaces for alignment when otherwise indenting with tabs).

I personally prefer indenting with tabs over indenting with spaces. The problem is, that emacs by default does not support that. You can easiely disable tabs and indent spaces, but not the other way around. I searched for hours and tried multiple solution without much success.

The solution I finally found comes from this website (and is quite well explained there, so go check it out). It basically consist of a few set variables as well as two functions which also modify some variables (and one creates a keybind). It works, but you do have to adjust the *-indent-level and *-basic-offset variables for all languages you want to edit with tab indentations.


;; Some variables
(setq custom-tab-width 8)
(setq-default tab-width custom-tab-width
              evil-shift-width custom-tab-width
              backward-delete-char-untabify-method 'hungry
              c-default-style "leonplickat"
              c-indent-tabs-mode nil
              c-indent-level custom-tab-width
              c-argdecl-indent 0
              c-tab-always-indent t
              js-indent-level custom-tab-width
              css-indent-offset custom-tab-width
              sgml-basic-offset custom-tab-width    ;; This is for html
              python-indent-offset custom-tab-width
              indent-tabs-mode nil)

;; The functions
(defun disable-tabs ()
  (setq indent-tabs-mode nil))
(defun enable-tabs  ()
  (local-set-key (kbd "TAB") 'tab-to-tab-stop)
  (setq indent-tabs-mode t)
  (setq tab-width custom-tab-width)
  (smart-tabs-mode))

;; The hooks
(add-hook 'prog-mode-hook 'enable-tabs)
(add-hook 'css-mode-hook 'enable-tabs)
(add-hook 'lisp-mode-hook 'disable-tabs)
(add-hook 'emacs-lisp-mode-hook 'disable-tabs)

I did change the enable-tabs function: I added a call to smart-tabs-mode (which can be found here and on Melpa), which does some magic to help with automatically alligning stuff. This luckily works really well, even with electric-indent-mode and aggressive-indent-mode.

Did you notice the c-default-style "leonplickat"? That's right, I had to create my own identation style for C and C-like code. I will write about that in a future blogpost.

[Top]