Disabling minor mode key bindings - emacs

I asked a question here, and got good responses, but the problem turned out to be different from what I had thought.
I am trying to assign a certain function to the key "C-c" in shell mode, but it seems that a minor mode called tabbar-mode has a prefix-key assigned to "C-c", which overrides my setting for shell mode. How can I disable tabbar mode key assignments?
I put these after (require 'tabbar), but they did not work:
(defvar tabbar-mode-map nil)
(defvar tabbar-prefix-key nil)

(defvar) only initialises a variable if it has no value. See C-hfdefvarRET for details.
Use (setq) to change the value of an existing variable.
To prevent the mode's keymap from being used when looking up key-bindings, you can delete it from the minor-mode-map-alist variable:
(assq-delete-all 'tabbar-mode minor-mode-map-alist)

Related

How can I set buffer-local value for a variable defined by defcustom?

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.

How do I get a list of all the currently available commands and hotkeys?

To help me learn to work with various emacs modes, I would like to have a second monitor with a little HTML page that is used for showing me what sorts of things I can type or key-chord on whatever I'm currently looking at in emacs.
So how can I get a list of all the commands or key-chords available to me in my current mode?
Someone else will no doubt tell you how to get a cheatsheet such as you request (well, here is info about that too).
But if you want something that tells you dynamically what keys are available in the current context, no matter what it is, then this is what I have to offer:
C-h m tells you about the current (major) mode. C-h b tells you about currently available keys.
The Icicles feature key completion gives you access to all of the currently available key sequences, via key S-TAB. If you use a prefix key first, then S-TAB, then you see all the completions of that prefix key. You can move up and down the key hierarchy, including even menu items, to see all possible keys. You can use C-M-RET to get help (info about) any given key that is available. Here is some more about this feature of showing you all currently possible key bindings.
I would very much like to know good answer to this question myself! At present I am using this simple function to display key bindings for the current major mode in *Help on keys* buffer:
(defun describe-current-bindings (mode)
"Show key bindings for the current major mode in *Help on keys* buffer."
(interactive)
(with-current-buffer (get-buffer-create "*Help on keys*")
(erase-buffer)
(insert (documentation mode))))
And then use defadvice to call the function automatically whenever I switch buffers or windows:
(defadvice switch-to-buffer (after display-keys-buffer activate)
(describe-current-bindings major-mode))
(defadvice select-window (after display-keys-window activate)
(describe-current-bindings major-mode))
Now I can open *Help on keys* buffer in another frame and move that frame to my second monitor.
If you use other functions to switch windows (from windmove package, etc) you may need to add defadvice for them as well.
Try the pacakge help-fns+.el, there are some useful functions: describe-mode - "Display documentation of current major mode and minor modes.", describe-keymap - "Describe bindings in KEYMAP, a variable whose value is a keymap.", etc. For example,
(describe-keymap 'global-map) ;; global bindings
(describe-keymap 'emacs-lisp-mode-map) ;; major mode bindings
(describe-keymap 'smartparens-mode-map) ;; minor mode bindings

how to change buffer-local variable for a major mode in Emacs?

Generally, how can I customize the value of a buffer-local variable in Emacs? For example, the variable w3m-lnum-mode is buffer-local, if I set (setq w3m-lnum-mode t) in .emacs, its value in a w3m mode buffer is still nil. How could I set it to t in w3m major mode?
Major modes have a hook variable for this sort of thing. Look for w3m-mode-hook.
(defun my-w3m-hook nil
(setq w3m-lnum-mode t))
(add-hook 'w3m-mode-hook #'my-w3m-hook)
The indirection to hook a separate function is not absolutely necessary, but simplifies the management of the hook functionality (otherwise you'd have to restart Emacs or jump through several hoops to add something to an existing hook; now all you need to do is evaluate a new defun of the function called from the hook).
You can set a default like so:
(setq-default w3m-lnum-mode t)
For fine-grained control, use a hook as RNAer suggests. As far as I can tell though, this is not a normal local variable but a minor mode variable. You actually probably want to do (w3m-lnum-mode 1).

Mode-local defadvice

Is it possible to modify function's behavior with defadvice for specific mode/buffer only? I want mouse-yank-primary to insert extra text, but only when i'm in specific mode. I've tried 'defadvice after' for mouse-yank-primary, but once activated it works in all other buffer as well.
I think it can be resolved by rebinding mouse button to my own function in mode hook, but elisp manual says it's better to use defadvice.
Rebinding the mouse button to another function seems preferable to me. You don't need a mode hook for that, usually you just modify the mode's keymap:
(eval-after-load '<mode>
'(define-key <mode>-map [mouse-2] 'my-mouse-yank-primary))
Localizing an advice to a major mode is a bit harder. There's no argument you can pass to defadvice to do that, but you can set some variable's buffer-local value in a mode hook, and then check this value in the advice code. If it's set, do something special. If not, just evaluate ad-do-it.
Localizing an advice to a major mode is easy:
(defadvice foo (after bar activate)
(when (derived-mode-p 'python-mode)
(do (something) now)))

Globally overriding emacs keybindings

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