Minor Mode Conditional Emacs Shortcuts - emacs

I have an emacs shortcut set up like so:
;; Adding the key mappings to minor mode.
(defvar my-keys-minor-mode-map (make-keymap) "my-keys-minor-mode keymap.")
;; Cancel with one press of escape instead of three.
(define-key my-keys-minor-mode-map (kbd "<escape>") 'keyboard-quit)
(my-keys-minor-mode 1)
(defconst my-minor-mode-alist (list (cons 'my-keys-minor-mode
my-keys-minor-mode-map)))
(setf emulation-mode-map-alists '(my-minor-mode-alist))
This works great to override a shortcut in a truly global way, superseding all other minor modes. However I need a way to have a shortcut behave differently in different minor modes. For example I would like the escape key to run helm-keyboard-quit when helm is running bu run keyboard-quit otherwise. Doing so like:
(eval-after-load "helm"
'(progn
(define-key helm-map (kbd "<escape>") 'helm-keyboard-quit)))
won't work because the global escape shortcut will override it. Is there a way to do this?

Why not use a simple lambda. Something like this (untested):
(global-set-key (kbd "<escape>")
(lambda()
(interactive)
(if helm-mode (helm-keyboard-quit)
(keyboard-quit))))

Related

Bind C-z in evil mode to escape to shell

In Emacs evil mode, the key combo C-z is to toggle evil mode. I would like to rebind it to escape to shell instead. How would I do this ?
I have read about eshell, it seems to be great, but for now I would like to work with my zsh shell first.
Multi term seems to designed for this job, but I think escaping to shell is fine for me, since I'm used to this flow in Vim.
Thanks for reading.
Perhaps what you need is C-x C-z.
Just have the same requirement, and here's my configurations:
(add-to-list 'load-path "~/.emacs.d/evil")
(add-to-list 'load-path "~/.emacs.d/evil/lib")
(setq evil-toggle-key ""); remove default evil-toggle-key C-z, manually setup later
(require 'evil)
(evil-mode 1)
;; remove all keybindings from insert-state keymap, use emacs-state when editing
(setcdr evil-insert-state-map nil)
;; ESC to switch back normal-state
(define-key evil-insert-state-map [escape] 'evil-normal-state)
Ref:
1. https://gist.github.com/kidd/1828878
2. https://askubuntu.com/questions/99160/how-to-remap-emacs-evil-mode-toggle-key-from-ctrl-z
C-x C-z will suspend the frame and return you to the shell.
C-z as you mention toggles evil mode on/off.
I swap their behavior in evil like so:
(define-key evil-motion-state-map (kbd "C-z") 'suspend-frame)
(define-key evil-emacs-state-map (kbd "C-z") 'suspend-frame)
(define-key evil-motion-state-map (kbd "C-x C-z") 'evil-emacs-state)
(define-key evil-emacs-state-map (kbd "C-x C-z") 'evil-exit-emacs-state)
See this commit for an example (where I also make C-z emulate vim-behavior in insert/replace mode).

binding the escape key to a keychord for evil-mode

I have taken the below code from emacs site for evil -
(defun my-esc (prompt)
"Functionality for escaping generally. Includes exiting Evil insert state and C-g binding. "
(cond
;; If we're in one of the Evil states that defines [escape] key, return [escape] so as
;; Key Lookup will use it.
((or (evil-insert-state-p) (evil-normal-state-p) (evil-replace-state-p) (evil-visual-state-p)) [escape])
;; This is the best way I could infer for now to have C-c work during evil-read-key.
;; Note: As long as I return [escape] in normal-state, I don't need this.
;;((eq overriding-terminal-local-map evil-read-key-map) (keyboard-quit) (kbd ""))
(t (kbd "C-g"))))
(define-key key-translation-map (kbd "C-c") 'my-esc)
;; Works around the fact that Evil uses read-event directly when in operator state, which
;; doesn't use the key-translation-map.
(define-key evil-operator-state-map (kbd "C-c") 'keyboard-quit)
;; Not sure what behavior this changes, but might as well set it, seeing the Elisp manual's
;; documentation of it.
(set-quit-char "C-c")
It sets up the C-c key for escaping from the insert mode. How do I change it to a more convenient keychord such as "tt" ?
I used the below -
(key-chord-define evil-insert-state-map "tt" 'evil-normal-state)
However when I press 'tt' in the insert mode, it gives the following msg in the mini buffer -
<key-chord> <escape> is undefined
I couldn't reproduce your error, works fine for me.
Make sure you have the key-chord package installed.
(require 'key-chord)(key-chord-mode 1) ; turn on key-chord-mode
(key-chord-define evil-insert-state-map "tt" 'evil-normal-state)

How to override/change mode key bindings in elisp?

In particular, when I load dired-x, it sets M-o to toggle the omit minor mode. I use M-o for other-window, so I would like to change the key that dired-x binds to something else. I've attempted setting the key after the mode loads like this:
(add-hook 'dired-mode-hook
(lambda ()
(dired-omit-mode 1)
(global-set-key (kbd "M-o") 'other-window)
))
but to no avail.
Slightly better than adding another copy of your custom global binding to the local mode map, would be removing the local binding so that it no longer shadows the global binding. You might also give that function a new key before you do this.
(eval-after-load "dired-x"
'(progn
;; Add an alternative local binding for the command
;; bound to M-o
(define-key dired-mode-map (kbd "C-c o")
(lookup-key dired-mode-map (kbd "M-o")))
;; Unbind M-o from the local keymap
(define-key dired-mode-map (kbd "M-o") nil)))
The dired-mode bindings "shadow" the global ones so your "global-set-key" isn't helping. What you want to do is override the dired-mode binding:
(add-hook 'dired-mode-hook
(lambda ()
(dired-omit-mode 1)
(define-key dired-mode-map (kbd "M-o") 'other-window)
))

Setting shortcuts keys in specific modes in Emacs (e.g. ido)

I have two problems which are somewhat related I believe:
1) In IDO I'd like to change ido-restrict-to-matches to samething else than C-SPC or C-#. Unfortunately I do not know how to tell emacs that I want a different shortcut (say C-0).
2) I'd like to protect my C-; but whenever flyspell-mode is running it overtakes C-;. My definition is in .emacs as:
(global-set-key (kbd "C-;") 'mark-paragraph)
but apparently flyspell overwrites this... (although even then, if I look in the help M-h k C-; it does say mark-paragraph)
Could somebody please tell me how to bind/unbind keys in these conditions? It has to work without modifying ido.el and flyspell.el and re-building, right?
Thanks very much!
Flyspell provides a customization for the C-; binding, so you can either M-x customize RET flyspell-auto-correct-binding RET or put something like this in your ~/.emacs:
(setq flyspell-auto-correct-binding (kbd "C-~")) ; or a binding of your choice
As for ido, your question is slightly confusing, because it implies there are times when you're using ido outside the minibuffer...
The documentation in ido.el contains the following advice:
;; To modify the keybindings, use the ido-setup-hook. For example:
;;(add-hook 'ido-setup-hook 'ido-my-keys)
;;
;;(defun ido-my-keys ()
;; "Add my keybindings for ido."
;; (define-key ido-completion-map " " 'ido-next-match)
;; )
Using that knowledge, you can change the key bindings like this in your own "ido-my-keys" function:
(define-key ido-completion-map (kbd "C-SPC") nil)
(define-key ido-completion-map (kbd "C-#") nil)
(define-key ido-completion-map (kbd "C-0") 'ido-restrict-to-matches)
There's an additional ido hook specifically for the minibuffer, too, but it's not clear why you would need that: ido-minibuffer-setup-hook.

Remapping SLIME keys

Slime remaps several keys I like to use and have set in global-set-key.
I'd like to avoid directly editing slime.el.
What's the routine to override keys in a given mode?
Update:
In your .emacs, set the mode-map directly:
(define-key slime-mode-map "\M-n" 'next-line)
(define-key slime-mode-map "\M-p" 'previous-line)
It's not too easy to redefine a key for a mode since it can provide several keymaps. And there can be many modes that grab my favorite keys.
I solved it this way: I defined a minor mode that doesn't do anything except it has it's own keymap. I put some keys there i want to be really global.
;; my minor mode for really global keybindings
(defvar my-keys-minor-mode-map (make-keymap) "my-keys-minor-mode keymap.")
(define-minor-mode my-keys-minor-mode
"My minor mode for global keybindings."
:init-value t :lighter "" :keymap 'my-keys-minor-mode-map)
(defun my-minibuffer-setup-hook ()
(my-keys-minor-mode 0))
(add-hook 'minibuffer-setup-hook 'my-minibuffer-setup-hook)
(my-keys-minor-mode 1)
;; for example
(define-key my-keys-minor-mode-map (kbd "C-a") 'mark-whole-buffer)
...