emacs + clojure-mode: add multiple hooks - emacs

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))

Related

Inspecting / modifying Emacs hooks for minor modes

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.)

Binding similar commands from different modes to the same key

I use emacs in multiple modes (ESS, Auctex, Slime, elisp, etc...) all using evil-mode key-bindings. Each of the interaction modes have similar functions for evaluating regions, lines or buffers that I have bound to shortcuts using spacebar as a prefix.
;; bind slime's eval and elisp eval to the key sequence "<SPC>e"
(evil-define-key 'normal lisp-mode-map (kbd "<SPC>e") 'slime-eval-last-expression)
(evil-define-key 'normal lisp-interaction-mode-map (kbd "<SPC>e") 'eval-last-sexp)
I would like to set a default key for a "type" of function, so that I don't need to have an entry like the above for every interaction mode I use and for every command. This would hopefully give a more readable .emacs init file and make it easier to change my key-bindings in the future.
I'm fairly sure that I could do this myself using a series of hooks, but I wonder if there is any existing or built-in support for this?
Thanks
tensorproduct
I don't know anything about Evil, so I'll give the normal Emacs solution:
(global-set-key [?\s ?e] #'my-eval-last-sexp)
(defvar my-eval-last-sexp-command #'undefined)
(defun my-eval-last-sexp ()
(interactive)
(call-interactively my-eval-last-sexp-command))
(add-hook 'emacs-lisp-mode-hook
(lambda () (set (make-local-variable 'my-eval-last-sexp-command) #'eval-last-sexp))
(add-hook 'lisp-mode-hook
(lambda () (set (make-local-variable 'my-eval-last-sexp-command) #'slime-eval-last-expression))
...
As you can see, there's only one mention of the key you want (in this case [?\s ?e]). But you don't save much on the amount of code you have to write. You might improve it by making my-eval-last-sexp a bit more complex (e.g. it could try to guess the command name from the major mode name), or by replacing the hook function with a global alist.
Hopefully, in some future Emacs, all such source-code modes that interact with some interpreter/compiler will share more of their code so that your problem will simply disappear.

Is there an Emacs paredit hook available so I can redefine C-j?

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.

Forcing haskell-indent-mode over haskell-indentation-mode in haskell-mode 2.7?

I'm an Emacs user with no skills with regards to configuring the editor. After I upgraded from haskell-mode 2.4 to 2.7, I've noticed two changes:
Indentation is different somehow, in a way I don't quite like. I can't quite put my finger on what it is.
More importantly: If I have cua-mode enabled and highlight a block of text, backspace/delete does not delete the entire block, just the previous/next character from my marker.
I see that haskell-mode 2.7 uses the minor mode haskell-indentation-mode by default, while 2.4's behaviour has been preserved in the form of haskell-indent-mode. If I first turn off the former, and then on the latter, the behaviour I want is restored (i.e. indentation feels like before, and backspace/delete deletes highlighted blocks).
I can't, however, get this to happen automatically whenever I open a file with a .hs suffix. I've tried various things resembling
(remove-hook 'haskell-mode-hook 'turn-on-haskell-indentation-mode)
(add-hook 'haskell-mode-hook 'turn-on-haskell-indent-mode)
and the likes of it, but I either end up with the standard mode or with plain haskell-mode without indent and doc.
Any ideas?
Solution (thanks to nominolo):
(remove-hook 'haskell-mode-hook 'turn-on-haskell-indent)
(remove-hook 'haskell-mode-hook 'turn-on-haskell-indentation)
(add-hook 'haskell-mode-hook 'my-haskell-mode-hook)
(defun my-haskell-mode-hook ()
(haskell-indentation-mode -1) ;; turn off, just to be sure
(haskell-indent-mode 1) ;; turn on indent-mode
)
The best way to configure such things is by writing a custom hook:
(add-hook 'haskell-mode-hook 'my-haskell-mode-hook)
(defun my-haskell-mode-hook ()
(haskell-indentation-mode -1) ;; turn off, just to be sure
(haskell-indent-mode 1) ;; turn on indent-mode
;; further customisations go here. For example:
(setq locale-coding-system 'utf-8 )
(flyspell-prog-mode) ;; spell-checking in comments and strings
;; etc.
)
You could also stick an anonymous function in there, but having a named function is easier if you want to experiment with some settings. Just redefining the function (and re-opening a Haskell file) will give you the new behaviour.

How to minify .emacs configuration file?

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.