Add several functions as hooks in Emacs - emacs

How could I simplify something like the following code in my init.el file?
(add-hook 'org-mode-hook 'turn-on-auto-revert-mode)
(add-hook 'org-mode-hook 'turn-on-org-cdlatex)
(add-hook 'org-mode-hook 'smartparens-mode)
(add-hook 'org-mode-hook 'abbrev-mode)
I have several other rows like this, including some lambda functions added to org-mode-hook...

Personally, I would strongly advice against adding lambda functions to hooks. The main reason is that if you change the content and reevaluate the add-hook expression, the hook contains both the old and new lambda expression. The second reason is that it looks bad when you inspect a hook -- it's better to see a function name compared to a large lambda expression.
Instead, I would suggest using:
(defun my-org-mode-hook ()
(turn-on-auto-revert-mode)
(turn-on-org-cdlatex)
(smartparens-mode 1)
(abbrev-mode 1)))
(add-hook 'org-mode-hook 'my-org-mode-hook)
A side note: You can use global-auto-revert-mode to enable auto-revert on all buffers, that way you don't have to enable it for all major modes.

I use a simple dolist:
(dolist (fn '(turn-on-auto-revert-mode
turn-on-org-cdlatex
smartparens-mode
abbrev-mode))
(add-hook 'org-mode-hook fn))
This let's you still remove individual hooks afterwards, with remove-hook or from the customize interface.

Related

emacs only delete-trailing-whitespace while saving in programming mode

following line removes all training white space while saving.
(add-hook 'write-file-hooks 'delete-trailing-whitespace)
but I want to hook this feature only when i'm in programming mode, so i did
(defun nuke_traling ()
(add-hook 'write-file-hooks 'delete-trailing-whitespace)
)
(add-hook 'prog-mode-hook 'nuke_traling)
which doesn't is not stopping which are not in programming mode.
Making the hook variable buffer-local has been mentioned. Don't do that. Or rather, don't do it using make-local-variable.
The normal hook mechanisms have buffer-local support built in -- that's the purpose of the LOCAL argument to add-hook. When the hook is run, it runs both the global and the buffer-local values.
So taking the example code in the question, you could change it to use:
(add-hook 'write-file-hooks 'delete-trailing-whitespace nil t)
And then delete-trailing-whitespace would be called whenever write-file-hooks was run, but only in the buffers in which prog-mode-hook had run.
However there are better ways to achieve this.
I agree with Drew that you are better to test whether your mode is derived from prog-mode, and with juanleon that before-save-hook is a better hook to use. So you might do something like:
(add-hook 'before-save-hook 'my-prog-nuke-trailing-whitespace)
(defun my-prog-nuke-trailing-whitespace ()
(when (derived-mode-p 'prog-mode)
(delete-trailing-whitespace)))
But what I actually recommend is using either ws-trim or ws-butler to take care of this in a smarter way.
Blindly removing all trailing whitespace from a file is a great way to wind up committing loads of unrelated lines to a version-control repository. Both of the libraries mentioned will ensure that your own commits are free of trailing whitespace, without also introducing unwanted modifications elsewhere in the file.
write-file-hooks is obsolete since Emacs-22, replaced by write-file-functions. But this hook is a bit delicate to use (because it can also be used to perform the write), so I recommend you use before-save-hook instead. And to make it apply only to the current buffer, just pass a non-nil value for the local argument of add-hook, as in:
(defun nuke_traling ()
(add-hook 'before-save-hook #'delete-trailing-whitespace nil t))
(add-hook 'prog-mode-hook #'nuke_traling)
Yes, because as soon as you enter a prog-mode mode, you add the function to write-file-hooks, where it remains. And that hook applies to writing any file, regardless of the mode of its buffer.
Instead of putting that simple function on the hook, you can add a function that tests the mode and only does the whitespace deletion when it is a mode where you want to do that.
Or else you would need to make write-file-hooks buffer-local (which I doubt you would want want to do --- the hook is used more generally).
Bad way:
(add-to-list 'write-file-functions 'delete-trailing-whitespace)
Better way is using ws-butler:
(straight-use-package 'ws-butler)
(add-hook 'prog-mode-hook #'ws-butler-mode)
ws-butler-mode remove spaces only on changed lines.
You would need to make the variable buffer local:
(defun nuke_traling ()
(make-variable-buffer-local 'write-file-hooks)
(add-hook 'write-file-hooks 'delete-trailing-whitespace))
But I would recommend using before-save-hook instead:
(defun nuke_traling ()
(add-to-list 'before-save-hook 'delete-trailing-whitespace))
write-file-hooks may be risky if used as a file-local variable, and documentation recomends using before-save-hook instead for thing like you want to do.
In emacs 21 or later you can add this hook to a perticular mode like this:
(add-hook 'prog-mode-hook
(lambda () (add-to-list 'write-file-functions 'delete-trailing-whitespace)))

add a function with parameters to a hook

I want to run a function according to the programming language when I open a source code file using the following. I have to pass the language-specific str to the foo function. How can do it in the add-hook statement?
(defun foo (str)
(blahblah...))
(add-hook 'prog-mode-hook 'foo)
Use the built-in apply-partially:
(add-hook 'prog-mode-hook (apply-partially #'foo "spam with eggs"))
This is described in the manual (first hit on Google for "emacs add-hook"):
(add-hook 'prog-mode-hook (lambda () (foo "foobarbaz")))
The bad news is that mode hooks usually don't have any arguments. The good news is that here's what (emacs) Hooks section of manual has to say about your situation:
Most major modes run one or more "mode hooks" as the last step of initialization.
So, I didn't test it myself, but I'm pretty sure you can write a generic hook that will inspect major-mode variable and do the mode-specific actions instead.

emacs autoload modes

I am a newbie.
Now I want to
auto start yasnippet auto-complete gtags flymake modes
when I opening a (php/java/el/...) file.
What Should I put in my emacs config file ?
As liu says, you use add-hook to specify that an action be run when a particular mode is started. Documentation here. Hooks are analogous to events in C#, or the observer pattern in OOP.
Every mode should define a hook that is run when that mode is started, eg. for a mode named java-mode there is a corresponding hook called java-mode-hook. add-hook lets you wire an action to this hook:
(add-hook 'java-mode-hook 'my-action)
You can use anonymous lambda functions to define the action in-place, like so:
(add-hook 'java-mode-hook (lambda () (message "hello from java-mode")))
This will print a message whenever you start up java mode.
It is usually better to define a named function for the purpose. If you use named functions, add-hook will ensure the same function is not called multiple times.
(defun hello ()
(message "hello from java-mode"))
(add-hook 'java-mode-hook 'hello)
Language editing modes are derived from prog-mode. If you want to run an action when you start up any programming language mode, you add your function to prog-mode-hook.
You need to manually configure autocomplete mode for each mode you want to use it in. For each mode, add that mode to the ac-modes list:
(add-to-list 'ac-modes 'java-mode)
As a side note, you will want to use flyspell-prog-mode for programming language modes, so you only receive spelling suggestions in comments and string literals.
(defun on-prog-mode ()
(flyspell-prog-mode t))
(add-hook 'prog-mode-hook 'on-prog-mode)
And you will probably want to use flycheck instead of the older flymake. Flycheck is under active development and has checkers for php.
you can add just like below:
(global-auto-complete-mode t)
(yas-global-mode 1)
then update below accordingly:
(add-hook 'php-mode-hook (lambda () (flyspell-mode 1)))
(add-hook 'php-mode-hook (lambda()(gtags-mode 1)))

Auto-complete with go-mode

I'm trying to enable auto-complete-mode whenever a .go file is loaded through go-mode. It works if I invoke auto-complete-mode manually for Go source files, but when I tried adding it to .emacs as below, it doesn't work:
(add-hook 'go-mode-hook auto-complete-mode)
I've tried a few variations around it but none seem to work. Following is what the Go-Mode snippet currently looks like in my .emacs:
;; Load Go Mode
(require 'go-mode-load)
(add-hook 'go-mode-hook 'auto-complete-mode)
I tried creating my own hook function like this:
;; Load Go Mode
(require 'go-mode-load)
(defun auto-complete-for-go ()
(auto-complete-mode 1))
(add-hook 'go-mode-hook 'auto-complete-for-go)
I also tried including the hook in go-mode-load.el and go-mode.el, as well as calling auto-complete-mode like this:
(auto-complete-mode t)
(provide 'go-mode)
Doesn't work either way. I also added the go-mode-hook to auto-complete-default function like so:
(defun ac-config-default ()
(setq-default ac-sources '(ac-source-abbrev ac-source-dictionary ac-source-words-in-same-mode-buffers))
(add-hook 'go-mode-hook 'ac-common-setup)
;; Other hooks
(global-auto-complete-mode t))
That doesn't work either. What's the best way to trigger a command just after a major mode is enabled for a buffer?
Here is workaround for now:
(add-to-list 'ac-modes 'go-mode)
I fixed the problem in v1.4 branch with the following commits.
Add go-mode to ac-modes
Add go-mode dictionary
Which variations have you tried? It should work if you add a single-quote in front of auto-complete-mode:
(add-hook 'go-mode-hook 'auto-complete-mode)
Without this quote, auto-complete-mode is interpreted as a variable and the value of that variable is added to go-mode-hook. For this to make sense, such a variable should contain a function reference as its value. Most likely though there will be no variable named auto-complete-mode and Emacs will complain.
By adding a quote, you tell Emacs that this is not a variable, but the actual function you want the hook to call. See also here and here.

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.