I use the following to enable linum-mode for Python buffers:
(defun my-python-mode-hook ()
(linum-mode 1))
(add-hook 'python-mode-hook 'my-python-mode-hook)
However, my understanding of hooks is still quite limited. As far as I understand, the code above adds a function to python-mode-hook so I assume this hook has already been defined, and may even have some code in it already. With this:
Does Emacs define a hook of the form <minor_mode_name>-hook for all minor modes? Or do the modes themshelves define them?
How can I look up the code added to a hook already?
How can I change elements of that hook?
This question is partly motivated by this GitHub issue for elpy where elpy-mode seems to have left a hook for python-mode that doesn't go away after uninstalling elpy.
(1) Emacs does not define a minor mode hook automatically, but you can define one with the :after-hook keyword (as per manual page for defining minor mode). (UPDATE: as per Legoscia's last comment, the minor-mode hook gets defined automatically as of emacs version 24.3.90. Thanks, Legoscia!)
(2) hooks are just variables, so you can inspect them as you would any other variable (e.g., C-h v or M-x describe-variable RET some-hook).
(3) you can use add-hook and remove-hook to change elements of the hook (see the manual on setting hooks), eg:
(add-hook 'python-mode-hook 'my-python-mode-hook)
(remove-hook 'python-mode-hook 'my-python-mode-hook)
(Note, by the way, that it's preferable to use named functions in your hooks rather than anonymous lambdas because you can use remove-hook on your named functions.)
Related
This is a part of my init.el file, which enables one hook to the clojure-mode:
(use-package clojure-mode
:ensure t
:config (add-hook 'clojure-mode-hook #'aggressive-indent-mode))
What is the syntax for enabling multiple hooks (e.g. #'paredit-mode and maybe more)?
As #ArthurUlfeldt points out, you can add multiple add-hook statements, one for each of the hook functions you want to add. However, this can become a little tiresome when you have a common set of things you want to add to multiple modes.
For example, if you use a number of lisp like languages, then you might want to add paredit, aggressive-indent, eldoc, rainbow-delimiters etc to each of these modes. Rather than having to sprinkle lots of add-hook commands all through your init file, you can define your own function i.e. my-lisp-hook which calls all the init functions you were adding with individual add-hook commands. Then you just need to do an add-hook which calls your function.
The other advantage this can have is it makes adding/removing something like a new minor mode much easier. For example, if you had
(defun my-lisp-hook ()
(paredit-mode 1)
(aggressive-indent-mode 1)
(raindbow-delimiter-mode 1))
and then had
(add-hook 'emacs-lisp-mode-hook 'my-lisp-hook)
(add-hook 'lisp-mode-hook 'my-lisp-hook)
(add-hook 'clojure-mode-hook 'my-lisp-hook)
(add-hook 'cider-mode-hook 'my-lisp-hook)
and then after an ELPA package update found the new version of aggressive-indent-mode was causing problems, you could just comment out 1 line in your my-lisp-hook function to stop the call to aggressive-indent-mode and get back to work. On the other hand, if you had added it separately in each mode hook, you would hve to comment out 4 lines. It also keep things consistent. I have run into subtle issues when I've loaded minor modes in one order for one mode and a different order for a different mode. With the use of your own hook function to load common setup requirements, it all happens consistently.
Note that the above code is pseudo code and is not meant to actually run. I don't know if the command to turn on rainbow delimiters is rainbow-delimiters-mode 1 or if the right hook to use for lisp mode is lisp-mode-hook. My examples are merely done to demonstrate the concept.
the way you write your emacs init file is a personal choice, but I think you should apply the same sort of rules we all know should be applied to writing code. Two of which are 'do not repreat yourself' and 'write your code to be clear rather than clever'. I think we shold apply the same logic to our emacs init file.
I also think your off to a great start with use-package. I've just switched to using it and think it is a great way to help structure your init file. However, to get the most out of it, especially with respect to delayed loading of packages so that my startup time is reduced, I did find I had to restructure my init file a fair bit. This could simply be a sign my original structure wasn't that good or it could be a sign of my current interest in trying and tweaking my emacs config as a bit of a hobby/distraction from cutting real code, whih tends to result in a less structure init due to the constant change.
you can add multiple statements after the :config keyword:
(use-package clojure-mode
:ensure t
:config (add-hook 'clojure-mode-hook #'aggressive-indent-mode)
(add-hook 'clojure-mode-hook #'other-thing-here)
(yas-global-mode 1))
Here's a chunk from my config:
(use-package cider
:ensure t
:config
(define-key cider-mode-map (kbd "C-c SPC") 'avy-goto-word-1)
(define-key cider-mode-map (kbd "C-x SPC") 'avy-pop-mark))
Sometimes I copy configuration options from the Internet to my .emacs. Sometimes they don't work.
(add-hook 'laTeX-mode-hook 'turn-on-flyspell)
doesn't work:
(add-hook 'LaTeX-mode-hook 'turn-on-flyspell)
(notice the uppercase in Latex). But,
(add-hook 'flyspell-mode-hook 'flyspell-buffer)
is correct. Although Emacs shows "Fly" in the lower bar and also M-: major-mode shows latex-mode and not Latex-mode.
How do I know how to write emacs modes name?
It sounds like you're actually more interested in the names of modes' hook variables than in the modes themselves.
You have several options. I will suggest some, based around discovering flyspell-mode-hook:
M-x apropos-variable RET flyspell RET, then search the results buffer for hook
C-h v flyspell-, then tab-complete
Any time you are in the minibuffer tab-completion is a good thing to try
M-x find-function flyspell-mode RET will open up the source code for flyspell, you can then search for hook
If you have configured your Emacs to provide completion for Emacs Lisp, you can simply type
(add-hook 'flyspell-
into your .emacs buffer and let Emacs suggest valid completion
Tools like Helm and ido can simplify the process of finding things
Using the find-function technique with latex-mode (which I tab-completed), I discovered that my version of Emacs calls its LaTeX mode function latex-mode. Searching for LaTeX- showed me that LaTeX-mode is an alias for latex-mode.
Your use of M-: major-mode is good, and gives you the correct major mode name (i.e. the symbol name for the mode function).
I don't believe there's a standard function to list the symbol names for the current buffer's enabled minor modes, but you can see all (loaded) minor mode symbols with C-hv minor-mode-list, so it's not hard to verify a name if you find you need to.
The symbol name for a mode's hook is literally the mode's symbol name with the suffix -hook.
Minor modes also have (in addition) an -on-hook and -off-hook.
The hook variables don't necessarily exist when not in use, but this naming is hard-coded in the standard macros for defining modes (and running their hooks at the appropriate times); and the modes which don't use those macros invariably follow the same conventions, to ensure consistency.
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)))
I like using C-j to eval-last-sexp but paredit-mode (which I otherwise like) overrides this to paredit-newline. Looking in the paredit-mode docs I don't see anything like a paredit-mode-hook defined where I can add-hook to call local-set-key or a similar function.
Anyone have a suggestion?
Update
After trying out the two answers below and not having much success, I think the problem may be related to the fact that paredit is getting loaded in a few different contexts? To wit, I am opening both Common Lisp, Clojure and Emacs Lisp files, all of which can use paredit. Sadly, the various forms of eval-last-sexp have slightly different names in each mode, so I can't define the key once for everything. Rather, I need to bind the key based on the major mode that I am in also. Hopefully that adds another useful data point.
No need to use hooks, something like the following should work:
(eval-after-load "paredit"
#'(define-key paredit-mode-map (kbd "C-j") 'eval-last-sexp))
Alternatively, if for some reason that doesn't work, or you simply prefer the use of hooks, you can add the above define-key invocation to the hooks of the major modes for which paredit is activated.
Every mode defined by one of the define-*-mode macros automatically runs a corresponding MODE-hook.
I see that paredit-mode is a minor mode defined with (define-minor-mode paredit-mode ...), and therefore it will run paredit-mode-hook.
You can type M-x find-function RET define-minor-mode RET and search for run-hooks to see where this behaviour is defined.
Edit (based on addition to question):
Do they all use C-x C-e as a default binding for the mode-specific eval-last-sexp function, by any chance? That would seem like a consistent thing for them to do, and if so then you could use the following approach:
(local-set-key (kbd "C-j") (key-binding (kbd "C-x C-e")))
There is a paredit-mode-hook. You don't see it until you add something to it. Weird, but this is the way hooks behave.
However, in your case, the best approach may be to clear the paredit binding for C-j:
(eval-after-load 'paredit
#'(define-key paredit-mode-map (kbd "C-j") nil))
And then set your own via local-set-key in every major-mode hook.
I was wondering if anyone can provide me with some help on minifying my .emacs file.
Currently I have it set up where each language I use have a custom tab, for example, if I have a hook for Java, it would look like this.
;; Java Hook
(defun e-java-mode-hook ()
(setq tab-width 4)
(setq indent-tabs-mode t)
(define-key java-mode-map (kbd "") 'java-insert-tab))
(defun java-insert-tab (&optional arg)
(interactive "P")
(insert-tab arg))
(add-hook 'java-mode-hook 'e-java-mode-hook)
And if I were to add another language like CSS or JavaScript, I would add another hook for CSS and another hook for JavaScript. So I was wondering if there's a global way of setting it so it would apply to any and all language?
I am currently running GNU Emacs 23.2.1 on Windows 7.
I agree with Tyler; although it's a bit complicated, you would be better off in the long run if you try to understand and customize the default indentation features. The Emacs Wiki has good resources, and there are other relevant Q&As here on Stack Overflow.
Binding the tab key to insert-tab means you completely lose the benefit of the likes of indent-region, and any other intelligent behaviour that a major mode might offer.
To address your specific questions regardless, however:
1) If you are defining (java-insert-tab) and (css-insert-tab) and (javascript-insert-tab) etc, and they all do exactly the same thing... well, hopefully you can see that you don't actually need more than one of those functions. Just give it a more generic name, and re-use it.
2) (local-set-key ...) does the same thing as (define-key (current-local-map) ...), which means you can also have a single generic function to override the tab keybinding, regardless of the major mode.
(defun my-coding-config ()
(setq tab-width 4)
(setq indent-tabs-mode t)
(local-set-key (kbd "<tab>") 'my-insert-tab))
(defun my-insert-tab (&optional arg)
(interactive "P")
(insert-tab arg))
Then you just need to add my-coding-config to each applicable mode hook variable. If there are a lot of them, you might wrap it up in a list like this:
;; Use my coding hook for all programming modes
(mapcar
(lambda (language-mode-hook)
(add-hook language-mode-hook 'my-coding-config))
'(java-mode-hook
javascript-mode-hook
css-mode-hook
...))
3) If you look at C-h v tab-width RET and likewise for indent-tabs-mode, you'll notice that they both say "Automatically becomes buffer-local when set in any fashion."
As an alternative to the customize interface already mentioned, you can use (set-default 'indent-tabs-mode t) to establish the default value for such variables. In the absence of code which sets a buffer-local value, all of your buffers will use the default, which might help you to avoid writing unnecessary mode hooks.
I'm not sure what you're trying to do. If you want to set the tab-width to 4 spaces globally, then you can do that using the customize command:
M-x customize-variable tab-width <ret>
Any changes you make to tab-width in customize will be applied globally. So you won't need to set it individually for each mode with hooks.
If you have different settings you want to apply to different modes, you will necessarily have to have code specific for each mode in your .emacs.
More generally, it looks like you're trying to build your own custom tab insertion commands - does the built-in indentation not do what you need? I think it will be easier to customize the indentation settings in Emacs than to manually insert tabs where you want them.
If you haven't already, take a look at the manual section on indentation and see if you might be able to do what you need without a lot of extra hooks:
C-h r m Indentation
(that is: h-elp, r-ead the manual, m-enu item Indentation)
or:
(info "(emacs)Indentation")
espect.el is doing exactly what you want.
From the docs:
This mode makes it easy to configure settings for individual
buffers with a concice and extensible mini-language. It abstracts
away common configuration selection tasks, like checking the mode
or filename, into a simple declarative syntax. Declare conditions;
run a function when the new buffer matches them. This makes it
easy to do things like turn on flyspell-prog-mode for your favorite
programming languages, or make all text-mode buffers ending in .mkn
have special properties.