Define key-chord key with specific mode - emacs

How do you define a key-chord key only in specific mode, for example I want to bind a cider repl to a specific key only in clojure-mode or cider-mode. I can only find an example that activates the key globally.
Thanks for your help.
EDIT:
(require 'evil)
(require 'key-chord)
(evil-mode 1)
(key-chord-mode 1)
(key-chord-define evil-insert-state-map "jk" 'evil-normal-state)
(key-chord-define-global "gt" 'other-window)
(key-chord-define clojure-mode-hook "gj" 'cider-jack-in)
;; error : Wrong type argument: keymapp, (rainbow-delimiters-mode)
(provide 'init-evil)

Defining mode-specific key bindings
Here is an example of how to do this:
(define-key clojure-mode-map (kbd "C-c r") 'cider-repl)
... where of course you would have to replace cider-repl with the specific command you want to bind. Note that the quote ' before the command name is required.
To generalize:
(define-key <mode-map> <key-binding> '<command>)
key-chord-specific instructions
You need to change the line where you're trying to set up the clojure-mode-specific key binding to
(add-hook 'clojure-mode-hook
(lambda () (key-chord-define clojure-mode-map "gj" 'cider-jack-in)))
Appendix: Making sure mode-maps are defined before modifying them
In order for modifications to clojure-mode-map to work properly, you have to make sure it is defined when you call define-key as described above.
If you are using the Emacs Package Manager, you are likely to have this line
(package-initialize)
somewhere in your .emacs file (which takes care of loading packages installed via package-install). Make sure you call define-key somewhere below this line.
Alternatively you can add the call to define-key to the hook that is run when clojure-mode is enabled:
(defun clojure-set-up-key-bindings ()
(define-key clojure-mode-map (kbd "C-c r") 'cider-repl)
;; If necessary, add more calls to `define-key' here ...
)
(add-hook 'clojure-mode-hook 'clojure-set-up-key-bindings)

Related

Minor Mode Conditional Emacs Shortcuts

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

Why can't I use "C-," to bind keys in org-mode?

I've used keybindings that start with "C-," in many other major modes and they all work. But it does not seem to work in org-mode (I tried to bind "C-, C-d" to org-deadline).
This is how I bind keys:
(add-hook 'org-mode-hook
(lambda ()
(local-set-key (kbd "C-, C-d") 'org-deadline)))
It looks like if I change it to
(add-hook 'org-mode-hook
(lambda ()
(local-set-key "\C-cp" 'org-deadline)))
then the binding works. However, it is still unclear to me how to bind "C-, C-d". And the first way of binding works in other major modes (Latex, Python, etc...) I use.
local-set-key in this context will attempt to bind a key sequence in org-mode-map, and there is already a non-prefix binding for C-, in that keymap, so you can't then create a binding in the same keymap which treats C-, as a prefix.
n.b. You can ask Emacs what C-, is bound to by typing C-h k C-, in an org-mode buffer.
You can remove the default binding using:
(eval-after-load "org" '(define-key org-mode-map (kbd "C-,") nil))
(after which you would be able to execute your original code.)

Emacs replacing require with autoload

After profiling my Emacs init file, I saw that many of my modes are taking a long time to load, explaining why I've been having slow start times.
I am trying to use after-load or autoload to decrease the load time but have been unsuccessful in many modes.
For example, I have a mode called multiple-cursors.el that I downloaded manually and placed in my .emacs.d directory. Here is the code I have now:
;; Multiple Cursors
(add-to-list 'load-path "~/.emacs.d/multiple-cursors.el/")
(require 'multiple-cursors)
(global-set-key (kbd "C-c c") 'mc/edit-lines)
(global-set-key (kbd "C-c .") 'mc/mark-next-like-this)
(global-set-key (kbd "C-c ,") 'mc/mark-previous-like-this)
(global-set-key (kbd "C-c /") 'mc/mark-all-like-this)
I tried to replace the require line with (autoload 'multiple-cursors-mode "multiple-cursors.el" "Multiple cursors mode") but that did not work.
This format of the autoload seems to work well only with Melpa-installed packages. How can I do the equivalent for manually installed packages, such as the example above?
You need to write autoloads for the functions that you are actually calling through the key bindings (i.e. mc/edit-lines, mc/mark-next-like-this, mc/mark-previous-like-this and mc/mark-all-like-this), since that's how the loading of the file is triggered. The autoloads need to refer to the files where the respective functions are defined, which is mc-edit-lines for mc/edit-lines, and mc-mark-more for the others.
So after setting the load path and binding the keys, add something like this:
(autoload 'mc/edit-lines "mc-edit-lines" "" t)
(autoload 'mc/mark-next-like-this "mc-mark-more" "" t)
(autoload 'mc/mark-previous-like-this "mc-mark-more" "" t)
(autoload 'mc/mark-all-like-this "mc-mark-more" "" t)

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