views:

114

answers:

4

I'm attempting to switch from Vim to Emacs, but I'm tearing my hair out trying to configure it to treat tabs how I wish. I require:

  • Inserted "tabs" to be expanded into two spaces. Emacs stubbornly sticks to eight, no matter what I do.
  • Tabs (i.e. real \t characters) to be represented on screen by two spaces.
  • Pressing TAB should insert a tab at the cursor rather than indent the entire line. Currently, I press TAB anywhere and Emacs destroys all whitespace at the start of the line; this is the most infuriating thing so far.

My current ~/.emacs reads

(setq standard-indent 2)
(setq-default indent-tabs-mode nil)

but I have tried no end of suggested configurations from the web, none of which have done what they said they would. (Does the API constantly change? I'm using GNU Emacs 23.1.1, apparently.)

A: 

OK, after much sweat and toil, I've found the answer: switch back to Vim. Turns out that Emacs' tab logic is as follows:

  1. If it's a new line: If it's f*cking obvious where the line should be indented to, set the indent to 0. Otherwise, keep it the same as before and disable the user from indenting it manually.
  2. Otherwise, the user has inserted a character other than a new line. To prevent this line being handled smoothly, indent the line to Math.random().

Presumably, this is the preferred style of indentation for Emacs users, but it's not mine.

eegg
You're not getting Emacs's approach to <tab> in programming modes.In Emacs, <tab> is not "insert \t char at point". It's "apply automated indent rules to current line". What the rules are depends on the language. In c/java/perl the line will be indented according to syntax analysis (sometimes broken in perl). In Python, emacs will cycle between multiple indents so that the line belongs to various blocks. Not sure about other languages.To control indent, you need to control the rules. If you just want to insert tab, press ctrl-q <tab>, but that's rarely what you want.
Arkadiy
It's depressing seeing IRC-style answers on SO. Both Emacs and Vim are so infinitely customizable that there is pretty much no behavior you couldn't change if you really wanted to; abandoning one because you don't like the default tab behavior is just silly
Michael Mrozek
+4  A: 

Emacs has extremely flexible support for handling indentation. Generally the mode that you are in dictates how they work - so if you're working on a C file then the way that pressing tab works will be different than if you're working on a Python file.

So it does depend which mode you're working in, which will limit the answers you get. In most cases I would recommend that you don't fight against it - for me the indentation behaviour is one of the best features of emacs. However, you do need to spend the time to customize it for yourself.

To change the way that tabs are displayed you need to set tab-width to 2. If you're editing Java or C style code then it sounds like you want to turn off all the nice indentation features by these to NIL:

  • c-tab-always-indent
  • c-syntactic-indentation
  • indent-tabs-mode

I suggest you set these through the customization interface. If you use "M-x customize-group RET C" then you can see the various settings for C mode.

If you're editting different types of files then the instructions will be different.

Perhaps emacs is in the wrong mode for your file. You could try doing "M-x fundamental-mode" to see if you prefer the behaviour there.

Damyan
+1  A: 

This should get you most of what you want. You'll probably have to customize some other programming modes you commonly use.

(defun insert-tab ()
  "self-insert-command doesn't seem to work for tab"
  (interactive)
  (insert "\t"))
(setq indent-line-function 'insert-tab)  ;# for many modes
(define-key c-mode-base-map [tab] 'insert-tab) ;# for c/c++/java/etc.
(setq-default tab-width 2)
Trey Jackson
+1  A: 
;; * Inserted "tabs" to be expanded into two spaces. Emacs stubbornly
;;   sticks to eight, no matter what I do.

;; * Tabs (i.e. real \t characters) to be represented on screen by two
;;   spaces.

(setq-default tab-width 2)


;; * Pressing TAB should insert a tab at the cursor rather than indent
;;   the entire line. Currently, I press TAB anywhere and Emacs
;;   destroys all whitespace at the start of the line; this is the
;;   most infuriating thing so far.

(setq-default indent-tabs-mode t)

(mapcar (lambda (hooksym)
          (add-hook hooksym
                    (lambda ()
                      (kill-local-variable 'indent-tabs-mode)
                      (kill-local-variable 'tab-width)
                      (local-set-key (kbd "TAB") 'self-insert-command))))

        '(
          c-mode-common-hook

          ;; add other hook functions here, one for each mode you use :-(
          ))

;; How to know the name of the hook function?  Well ... visit a file
;; in that mode, and then type C-h v major-mode RET.  You'll see the
;; mode's name in the *Help* buffer (probably on the second line).

;; Then type (e.g.) C-h f python-mode; you'll see blather about the
;; mode, and (hopefully) somewhere in there you'll see (again e.g.)
;; "This mode runs the hook `python-mode-hook', as the final step
;; during initialization."
offby1