Emacs: How to disable specific global mode in major-mode hook? - emacs

I use global-autopair-mode, but with Ruby the ruby-electric-mode provides better autopairing.
I'm a n00b to Emacs and Lisp, so I would have thought you could do something like:
(add-hook 'ruby-mode-hook
(lambda ()
(autopair-mode nil)
(ruby-electric-mode t))
This however doesn't work. Is there a way to disable global modes within a major-mode hook?
Currently I'm using the last solution posted here, but it's not very neat and clean.

autopair mode honors autopair-dont-activate, used like so:
(add-hook 'ruby-mode-hook
(lambda ()
(setq autopair-dont-activate t)
(ruby-electric-mode t))

Try replacing (autopair-mode nil) with (autopair-mode -1).

Related

Set variable under specific mode emacs

Looking to set a variable under latex mode. The idea is that the value set under latex mode will override the value of the same variable set in the customise section. I am very new to emacs so these are my attempts:
(add-hook 'LaTeX-mode-hook '(setq line-move-visual t))
(add-hook 'latex-mode-hook (lambda () (setq line-move-visual t)))
Why do these not work? What should I do instead?
Clarification: looking to set the variable (setq line-move-visual t) as I have it as (setq line-move-visual nil) for all other files
If you just setq the variable in your LaTeX-mode-hook it will also have an effect on any other open buffer. It is possible to make the change only effect the current buffer:
(add-hook 'LaTeX-mode-hook
(lambda ()
(make-local-variable 'line-move-visual)
(setq line-move-visual nil)))
Also, please note that the hook for the default mode for LaTeX in Emacs is called latex-mode-hook but the hook when you are using the (far superior) AUCTeX is called LaTeX-mode-hook
EDIT: Changed make-variable-buffer-local to make-local-variable. See comments to this answer.

Setting up AUCTeX: LaTeX-mode-hook does not work

I have a strange problem. When I set up my AUCTeX configuration for Latex like this
(require 'tex)
(TeX-global-PDF-mode t)
it works for me.
But when I alter the code by putting in a lambda function
(add-hook LaTeX-mode-hook (lambda ()
(require 'tex)
(TeX-global-PDF-mode t)
))
it won't work.
Could someone help me? Thank you.
Try adding a ' to the immediate left of LaTeX-mode-hook. Also, you need to (require 'tex) before using the LaTeX-mode-hook.
Because the library AUCTeX defines the variable LaTeX-mode-hook (i.e., brings it into existence), placing (require 'tex) inside a hook that does not yet exist will not work. [See line 5017 of ~/.emacs.d/elpa/auctex-11.87.3/latex.el)
(require 'tex)
(add-hook 'LaTeX-mode-hook (lambda ()
(TeX-global-PDF-mode t)
))
Normally, I see this used: (setq TeX-PDF-mode t). However, the original poster is correct regarding the existence of a function named TeX-global-PDF-mode -- see line 1729 of ~/.emacs.d/elpa/auctex-11.87.3/tex.el.
(source: lawlist.com)
Delete following line if you have in your "init.el".
(load "preview-latex.el" nil t t)
Although the line is suggested in"auctex-reademe.txt", I think
following is more appropriate.
(load "preview" nil t t)

How to remap a function to another in Emacs?

In coffee-mode RET is bound to coffee-newline-and-indent which works fine.
I also use evil-mode to have Vim emulation. evil-mode uses the standard newline-and-indent so the indentation is not correct for some vim commands such as o or O.
What would be the best way to rebind newline-and-indent to coffee-newline-and-indent ?
I'm still a newbie in ELisp and tried the line below but it doesn't work.
(add-hook 'coffee-mode-hook
(lambda ()
(setq newline-and-indent '(funcall coffee-newline-and-indent))))
Here's my attempt. It should work, but I don't really like it.
(add-hook
'coffee-mode-hook
(lambda ()
(defalias
'newline-and-indent
(lambda()
(interactive)
(if (eq major-mode 'coffee-mode)
(coffee-newline-and-indent)
(delete-horizontal-space t)
(newline)
(indent-according-to-mode))))))
I wish I could use something more elegant that just copying the source
of newline-and-indent, but make-variable-buffer-local doesn't work for this case,
and I couldn't get a deep copy for symbol-function either.
I'd be happy to see a better method.
The standard way to accomplish what you seem to be asking for is
(autoload 'coffee-newline-and-indent "coffee-mode") ; (or whatever)
(define-key evil-mode-map (kbd "RET") 'coffee-newline-and-indent)
EDIT: to enable coffee-newline-and-indent only in coffee-mode:
(define-key evil-mode-map (kbd "RET")
(lambda ()
(interactive)
(if (eq major-mode 'coffee-mode)
(coffee-newline-and-indent)
(newline-and-indent))))
Try the following:
(define-key evil-mode-map (kbd "RET") nil)
I know it looks overly simple, but if evil-mode works the way I think it does then it should work.
This will wipe the ret key from your evil-mode-map, which will let the binding of coffee-mode-map shine through.
In non-coffee buffers, the ret key will still work, because it's still bind in the global map.
I found the solution.
Evil-mode actually uses coffee-indent-line. The problem comes from coffee-indent-line which doesn't indent correctly. Evil-mode works correctly after patching it to behave like coffee-newline-and-indent:
(defadvice coffee-indent-line (after wants-indent activate)
(let ((tabs-needed (- (/ (coffee-previous-indent) coffee-tab-width) 1)))
(when (> tabs-needed 0)
(insert-tab tabs-needed)))
(when(coffee-line-wants-indent)
(insert-tab)))
if you want to remap a func, but only if some major mode is active
- create a func which defines an alias
and run the func (A)
- another func (B) calls (A)
- finally, a major mode can advice the func A to set the correct
func. It has to test major mode.
let's say A is define-my-indent-f
then it says (defalias my-indent 'newline-and-indent)
the func b runs A then run command my-indent.
finally coffe mode does defadice A to say
(if eq major mode coffee defalais my-indent 'coffe-newline-and-indent)
of course this is super heavy to define, but then
- each major mode can add its piece
- only loaded major mode will advice

why mode isn't enabled?

I've got an emacs configuration file whatever.el :
(abbrev-mode +1)
(provide 'whatever)
and in my init.el :
(require 'whatever)
but when i start emacs, abbrev-mode isn't enabled. why ?
thank you
Quoting from http://emacswiki.org/emacs/AbbrevMode:
You can also put the following in your ~/.emacs file if you want it
always on:
(setq default-abbrev-mode t)
If you only want it on in text and derived modes, you could do
something like this:
(add-hook 'text-mode-hook (lambda () (abbrev-mode 1)))
For multiple modes, use something like the following:
(dolist (hook '(erc-mode-hook
emacs-lisp-mode-hook
text-mode-hook))
(add-hook hook (lambda () (abbrev-mode 1))))
Abbrev-mode is enabled per-buffer.
One way is to create a hook function that you could add to the major mode hooks you will want to use it in.
For example:
(defun my-enable-abbrev-mode ()
(abbrev-mode 1))
(add-hook 'c-mode-hook 'my-enable-abbrev-hook)
(add-hook 'java-mode-hook 'my-enable-abbrev-hook)
Another approach is to use change-major-mode-hook.
While others explained how to get what you presumably want, I'll just point out that w.r.t to your actual question ("Why?"), the reason is simple: abbrev-mode is a buffer-local minor-mode, so when you run (abbrev-mode +1) at startup it will just enable abbrev-mode in the buffer that happens to be current during evaluation of the ~/.emacs (typically scratch) but not in subsequent buffers.

Conflicting keyboard shortcuts in two Emacs minor modes

I have an ErgoEmacs minor mode turned on globally, which defines many custom keyboard shortcuts for basic editing. However when I open any lisp file, slime-mode turns on automatically and overrides M-p and M-n with its own commands. However I want M-p and M-n to be always defined by ergoemacs-mode. How do I set up order in which minor modes load and define keybindings? Or how do I raise ergoemacs-mode keybindings priority?
How do I set up order in which minor modes load and define keybindings? Or how do I raise ergoemacs-mode keybindings priority?
I think you need to ensure that ErgoEmacs appears before slime-mode in the variable minor-mode-map-alist. There's probably a much better way, but the code below should achieve this. Let me know if it does what you want.
(require 'cl)
(add-hook
'slime-mode-hook
(lambda ()
(let ((elem (first
(remove-if-not
(lambda (item) (equal 'ergoemacs-mode (car item)))
minor-mode-map-alist))))
(setq minor-mode-map-alist (remove elem minor-mode-map-alist))
(add-to-list 'minor-mode-map-alist elem))))
Maybe a simpler solution is to remove Slime's bindings:
(add-hook 'slime-mode-hook
(lambda ()
(define-key slime-mode-map [?\M-p] nil)
(define-key slime-mode-map [?\M-n] nil)))
Beware: guarantedd 100% untested, the variable's name might be different from slime-mode-map (and it probably will only exist after loading slime-mode).