16

I have few Major modes (like: Yaml and NXML) that I don't want electric-indent-mode (I want it for C like languages) but I'm unable to turn if off. To enable I have:

(electric-indent-mode 1)

from documentation (for variable electric-indent-mode)

Non-nil if Electric-Indent mode is enabled. See the command electric-indent-mode' for a description of this minor mode. Setting this variable directly does not take effect; either customize it (see the info nodeEasy Customization') or call the function `electric-indent-mode'.

and for a function

Toggle on-the-fly reindentation (Electric Indent mode). With a prefix argument ARG, enable Electric Indent mode if ARG is positive, and disable it otherwise. If called from Lisp, enable the mode if ARG is omitted or nil.

so I try to turn it off in a hook:

(add-hook 'yaml-mode-hook (lambda ()                        
                             (electric-indent-mode -1)))

(Actualy I use after-change-major-mode-hook and check (memql major-mode '(yaml-mode python-mode nxml-mode)) where I can add more modes to the list).

But it don't work, I've also try:

(set (make-local-variable 'electric-indent-mode) nil)

No joy. But it work when I eval (electric-indent-mode -1) from .emacs files.

Flux
  • 9,805
  • 5
  • 46
  • 92
jcubic
  • 61,973
  • 54
  • 229
  • 402

3 Answers3

17

With a recent Emacs (probably Emacs snapshot only) you can use electric-indent-local-mode, e.g.:

(add-hook 'yaml-mode-hook (lambda () (electric-indent-local-mode -1)))

If your Emacs lacks this function, you can still sort of disable the mode via electric-indent-functions, e.g.

(add-hook 'yaml-mode-hook
          (lambda ()
             (add-hook 'electric-indent-functions
                            (lambda () 'no-indent) nil 'local)))

And in either case, you may probably want to restore C-j, via

(add-hook 'yaml-mode-hook 
          (lambda () (local-set-key (kbd "C-j") #'newline-and-indent)))
jcubic
  • 61,973
  • 54
  • 229
  • 402
  • Thank you, this helped me with the same problem, only with enh-ruby-mode instead of yaml-mode. I'm too used to using the C-j behavior to want to change now, but understand why it might be good for newcomers to have electric-indent on by default. – sockmonk Feb 12 '14 at 14:12
4

electric-indent-mode will be enabled by default in 24.4. To turn it off locally, you will be able to use electric-indent-local-mode as mentioned by lunaryorn. But to turn it off locally in 24.3, you can do:

(add-hook 'foo-mode-hook
          (lambda () (set (make-local-variable 'electric-indent-mode) nil)))

You mentioned that the first form didn't work for you, but it should (i.e. if it doesn't, it's because of the some other problem).

Stefan
  • 27,908
  • 4
  • 53
  • 82
  • What stands against setting `electric-indent-functions` directly, as in my answer? –  Jan 17 '14 at 14:16
  • Oh, right, didn't see that one, sorry, indeed setting `electric-indent-functions` like you did also should do the trick. – Stefan Jan 17 '14 at 14:58
  • Don't work for me, When I hit enter (or run `new-line`) the current line get indent. – jcubic Jan 17 '14 at 15:26
  • My example code will only work for `foo-mode`. "Don't work for me" doesn't give much information about what you've actually done, and my crystal ball is out for repairs. – Stefan Jan 17 '14 at 16:21
2

At least on emacs 24.3 you cannot disable electric indent mode locally, since it is a global-mode. Anyways the issue with yaml-mode is that the electric-indent functionality is built into it i.e. it will be enabled even without electric-indent-mode. The package does not provide a way to turn this behaviour off, maybe you should file an issue on its github repo.

Try this to disable the electric-indent functionality in yaml-mode

(define-key yaml-mode-map "|" nil)
(define-key yaml-mode-map ">" nil)
(define-key yaml-mode-map "-" nil)
(define-key yaml-mode-map "." nil)
(define-key yaml-mode-map [backspace] nil)

To restore the electric-indent behaviour afterwards, you can do

(define-key yaml-mode-map "|" 'yaml-electric-bar-and-angle)
(define-key yaml-mode-map ">" 'yaml-electric-bar-and-angle)
(define-key yaml-mode-map "-" 'yaml-electric-dash-and-dot)
(define-key yaml-mode-map "." 'yaml-electric-dash-and-dot)
(define-key yaml-mode-map [backspace] 'yaml-electric-backspace)
  • I have the same issue with NXML Mode and I can disable electric mode in Yaml mode. But as you said it's global mode and it don't work from hook. – jcubic Jan 17 '14 at 10:54
  • @jcubic For `nxml mode` you can do `(define-key nxml-mode-map "/" nil)`. –  Jan 17 '14 at 14:43
  • Don't work for me, I run in from .emacs and from the nxml buffer and nothing. When I hit enter the current line get indent. – jcubic Jan 17 '14 at 15:23
  • This should stop indenting on hitting `enter`, `(add-hook 'nxml-mode-hook (lambda () (add-hook 'electric-indent-functions (lambda (pos) 'no-indent) nil 'local)))` –  Jan 17 '14 at 15:42
  • Isn't this append new function everytime I turn on nxml-mode? – jcubic Jan 17 '14 at 15:51
  • Yes it would, to turn it off just once you can do `M-: (add-hook 'electric-indent-functions (lambda (pos) 'no-indent) nil 'local) RET`. To again re-enable do `M-: (remove-hook 'electric-indent-functions (lambda (pos) 'no-indent) t) RET`. You may want to wrap this in an interactive function if you are going to this frequently. BTW sorry for the formatting I don't know how to format code in comments. –  Jan 17 '14 at 15:59