Another Elisp package defines a minor mode as global. In other words, the package defines the minor mode with:
(define-minor-mode some-minor-mode
;; ... other stuff ...
:global t)
I'd like to make it buffer-local so that when I activate it, it only applies to the buffer in which it is activated. How do I do this?
You can't. Or at least, you can't in a generic way.
When a minor mode is defined as global, the logic of the mode will undoubtedly make that exact same assumption, and there's no generic change you could make which would cause any arbitrary global minor mode to have only buffer-local effects.
Furthermore, for some global modes a buffer-local variant wouldn't even make sense, such as modes which affect window configurations or frame parameters.
Global modes have to be treated on a case-by-case basis, looking at their specific implementation details. Depending on the code in question, you might be able to achieve your goal for some particular mode; but that same approach would not be guaranteed to work for all global modes.
It's worth mentioning that there are "globalized" minor modes which blend the other two concepts, by taking an existing buffer-local minor mode, and then defining a global mode which enables or disables the buffer-local mode en masse in all of the applicable buffers. You can't go in the other direction, though -- if you don't already have a buffer-local mode, then you would have to write that first.
Related
In emacs, we can define customizable user option variable.
defcustom - Programming in Emacs Lisp http://www.gnu.org/software/emacs/manual/html_node/eintr/defcustom.html
And we can make variable to have buffer-local binding.
Creating Buffer-Local - GNU Emacs Lisp Reference Manual http://www.gnu.org/software/emacs/manual/html_node/elisp/Creating-Buffer_002dLocal.html#Creating-Buffer_002dLocal
If I want to make non-customizable variable, I can use make-local-variable or setq-local.
But I can't find any ways how to make customizable variable to have buffer-local binding.
Even if I call make-local-variable for variable defined by defcustom, custom-set-variables set to global-value.
If I call setq-local, value is set to local-variable. It is better. But I don't think this is best practice.
Is there any valid ways how to set buffer-local value for a variable defined by defcustom?
The answer is: You can't, at least not using the Customize UI.
What you can do is add a sexp that sets the buffer-local value of the variable to your init file.
Do one of the following:
Make it always buffer-local, no matter what the buffer is:
(make-variable-buffer-local 'the-variable)
You can put this anywher in your init file.
Make it buffer-local only for the current buffer, i.e., for some buffer after you select it:
(make-local-variable 'the-variable)
For that, you need to put the sexp in a sexp that selects the buffer you want. That could be, for example:
(with-current-buffer (get-buffer-create "the-buffer-name")
(make-local-variable 'the-variable))
That assumes that the buffer can be reasonably created or already exists. If you do this, do it after your custom-file has been loaded. That is, in your init file, either after loading custom-file (which I recommend) or, if you do not use custom-file, after any code generated automatically by Customize (e.g., custom-set-variables).
You can alternatively put the make-local-variable sexp on a mode hook, so whenever you are in a buffer that has a particular mode, it is executed.
All of that said, I submitted an enhancement request to Emacs Dev in 2012, requesting that user's be able to use the Customize UI to set (and possibly save) buffer-local values of user options. It sleeps in category "wishlist", so far.
After defcustom form write
(make-variable-buffer-local 'my-var)
Now, if you change the value in some buffer, other buffers will keep resp. deliver the old customized one.
The problem is that Customize is mostly designed for persistent configuration, i.e. configuration that is saved in the config file so it also applies to future Emacs sessions. But buffers are not persistent: when you restart Emacs you get a new buffer object.
So persistent customization "per-buffer" is not a clearly defined concept. We could/should add Customize support for settings that are specific to some major modes (i.e. "per-mode" settings), on the other hand.
I want to enable rainbow-mode everytime I start emacs, rather than having to use M-x rainbow-mode.
I guess there is some command I put in my .emacs file.
I tried all of the following, but none of them worked:
(require 'rainbow-mode)
(rainbow-mode initialize)
(global-rainbow-mode)
More generally, how do I load any mode/package automatically on startup?
rainbow-mode isn't a global minor mode, so it needs to be enabled on a per-buffer basis.
I only use it for CSS, so I have:
(add-hook 'css-mode-hook 'my-css-mode-hook)
(defun my-css-mode-hook ()
(rainbow-mode 1))
If you genuinely want it to be global, everywhere, you can easily define a global minor mode yourself:
(define-globalized-minor-mode my-global-rainbow-mode rainbow-mode
(lambda () (rainbow-mode 1)))
(my-global-rainbow-mode 1)
You can add any arbitrary logic to that (lambda () (rainbow-mode 1)) function (which will be evaluated in every buffer) in order to decide whether or not to actually call (rainbow-mode 1) for a given buffer, so if you're comfortable with elisp then you can easily extend this approach to cover your specific requirements for the mode in question.
More generally, how do I load any mode/package automatically on startup?
It can vary, but the approaches I've shown would suffice for most minor modes: Either you want them enabled whenever MODE is enabled (being some specific other mode name), in which case you can use the MODE-hook variable (which will always be available) as per the css-mode-hook example; or else you want the mode enabled permanently, in which case a global minor mode is a good approach (because you can toggle it on and off globally). Some minor modes are global by default (or provide global variants), but you can create your own if necessary, as per the my-global-rainbow-mode example.
Also be aware that modes can be derived from other modes, in which case all relevant MODE-hook hooks will be run (for details see https://stackoverflow.com/a/19295380/324105). A common use-case is to use prog-mode-hook to enable functionality wanted for all the programming modes which are derived from it (which is most programming modes).
Remember that many (hopefully most) libraries and packages will provide usage instructions. If you can't find documentation, be sure to try M-x find-library to visit the library file, and then read through the comments at the top. There is often a very informative "Commentary" section, and sometimes this is the primary source of end-user documentation, and explain how to enable its functionality.
I always get error when use flymake-mode. And flymake-mode turn off.
So I want to check whether flymake-mode is on. If it is not on, I will turn it on before call flymake-next-error.
Thanks.
Most minor modes are defined using the define-minor-mode macro. For buffer-local modes, that macro creates a buffer-local variable of the same name as the mode itself1. The variable is non-nil when the mode is enabled for the current buffer.
Therefore to check whether flymake-mode is enabled, you can test the variable flymake-mode (noting that this variable might not be defined at all if the mode has not been enabled):
(and (boundp 'flymake-mode) flymake-mode)
Which, as Thom point out in the comments, can be expressed using the convenient macro:
(bound-and-true-p flymake-mode)
Which we can use as the condition for an if or when or unless expression:
(if (bound-and-true-p flymake-mode)
(message "flymake-mode is on")
(message "flymake-mode is off"))
1 For global minor modes, the corresponding variable is global; but flymake-mode is buffer-local.
Another solution is to use M-x describe-mode to show all the active minor modes (and major mode) and a brief description of each.
If the minor mode is on in the current buffer, you can find it's name on the popup buffer.
After a few years customizing my .emacs file, I find I used two different
kinds of constructs to setup major-mode-specific key bindings:
1. using a hook and local-set-key. For example:
(defun my/bindkey-recompile ()
"Bind <F5> to `recompile'."
(local-set-key (kbd "<f5>") 'recompile))
(add-hook 'c-mode-common-hook 'my/bindkey-recompile)
I would say this construct makes it easy to use the same key bindings for
different major-modes by adding the same function to all relevant major-mode
hooks (in other words, the "which keybindings do I want" is clearly separated
from the "for which modes do I want them"). However, I'm not comfortable with
the fact that such customizations are done at the buffer level, whereas I would
think they belong to the major mode.
2. using define-key (often combined with eval-after-load to delay
evaluation until the relevant keymap is loaded). For example:
(eval-after-load "cc-mode"
'(progn
(define-key c-mode-map (kbd "C-c o") 'ff-find-other-file)
(define-key c++-mode-map (kbd "C-c o") 'ff-find-other-file)))
By contrast, this construct customizes the major-mode itself, but is less
flexible: if I want to use the same key bindings for another mode, I will have
to find the correct file and keymap names for this mode, and almost duplicate
the eval-after-load expression (although this could probably be automated with
a function/macro).
Question: although both construct types work well and produce the result I
want, they are technically very different, setting-up the key bindings in
different keymaps at different times. So my question is: among these two
constructs, is there a "preferred/better" way to do things? (Or maybe the "best"
construct is a third one which I'm not aware of?)
By "preferred/better", I mean such things as:
less prone to break with new emacs versions
less prone to disturb/be disturbed by active minor-modes
more idiomatic / readable / shareable with others
I believe the two approaches you describe are less different than you think.
Notice that local-set-key does in fact evaluate (define-key map key command) where map is the value of (current-local-map), which is typically set by the major mode.
So although they could be doing different things; most of the time the only real difference will be that the hook function with the local-set-key call will be setting that same key repeatedly/redundantly, whereas the other approach sets it only once.
You can demonstrate this to yourself by using local-set-key in a mode hook, removing that hook function after it has been used, and then creating a new buffer in that same major mode, and testing the binding.
less prone to break with new emacs versions
I guess you could argue that the name of a keymap might change in future and therefore not needing to know the name is an advantage, but you could equally say the name of the mode hook might change. I don't think either is enough of a concern to worry about.
One thing to note is that local-set-key will work even if the major mode did not establish a current-local-map, which I guess makes it slightly more robust as far as generalised approaches go.
less prone to disturb/be disturbed by active minor-modes
There's no difference. All minor mode keymaps take precedence over all major mode keymaps, and neither approach is going to have any effect on the order of minor-mode-map-alist (which determines the precedence of minor mode keymaps).
more idiomatic / readable / shareable with others
They're both entirely readable to my mind, so I can't distinguish them in this aspect either.
I say just use whichever approach seems best to you in each context. I do think it's good to have a standard approach for most things for the sake of consistency in your code, but I doubt it matters which one you choose. There's obviously a saving of a few CPU cycles to be had by not evaluating the same code unnecessarily, but that should matter so very little as to be of no concern whatsoever.
I think the most obvious case for one over the other is the one you already mentioned -- if you want to apply the same binding to multiple modes using a common hook (but not to all modes -- for that I thoroughly recommend creating a custom minor mode), then a local-set-key within that hook is definitely the way to go.
I have lots of custom keyboard commands and I couldn't bother with various ways to set them in Emacs and all these keymaps overriding each other, so I just installed John Wiegley's bind-key as per my relevant answer.
(require 'bind-key)
(bind-key "C-l" 'goto-line)
Is there a command to globally override a keybinding such that it overrides even the local settings of major modes? global-set-key is overridden by major mode bindings, as stated here: http://www.gnu.org/software/emacs/manual/html_node/emacs/Rebinding.html
No, there is no (built-in) way to set up a key binding that overrides all others. Look at how Emacs searches the keymap by reading "Searching the Active Keymaps".
You could set overriding-terminal-local-map or overriding-local-map to a keymap containing the binding you want, but that'd prevent your buffer from having any buffer/overlay/minor-mode keymaps, pretty much disabling the majority of Emacs.
The next area Emacs looks for a binding is in the character property at the current point - which probably isn't used all over the place, but it's one way your binding would be overridden (unless you muck with character properties to define your key everywhere, really icky).
The next place Emacs looks is in the variable emulation-mode-map-alists, which is probably your best bet. It was set up for packages to use in cases where there are multiple minor-mode keymaps it wants to juggle.
Make a global minor mode (see Defining Minor Modes), put your key binding in there, add your minor mode and keymap into the emulation-mode-map-alists, and turn on your minor mode.
Your key binding will now have precedence over all others, except those earlier in the emulation-mode-map-alist list, or found in character properties, or in the overriding-local-map...
I believe that's the best you can do, w/out hacking Emacs source.
In the case of minor mode keybindings overriding my personal global bindings i have had luck using add-hook + local-unset-key
(add-hook 'undo-tree-mode
(lambda ()
(local-unset-key "C-/")))