I really love key-chord.el. It's become an integral part of my workflow, but sometimes I wish I could have them in the minibuffer (for things like evil-search). Specifically, I'd like jj to exit out of evil-search and move down a line. Is this possible?
I know I can hack together a command that acts as both a prefix and a command (see this SO question), so I could bind j to a self inserting command, and jj to my special command. How would I be able to break the event loop after a specified idle time? I do type jj once in a blue moon, and I'd still like the flexibility of a timeout.
Is there any other way which I am unaware of to achieve what I want?
EDIT:
Origionally, this question was about the minibuffer in general. key-chord.el seems to work fine with minibuffer-local-map. It does not, however, work with isearch-mode-map. Binding a command to a single regular key like j does work in isearch. This is what I'm trying to solve.
I have found a solution which manually reproduces the behaviour of key-chord.el.
(defun isearch-exit-chord-worker (&optional arg)
(interactive "p")
(execute-kbd-macro (kbd "<backspace> <return>")))
(defun isearch-exit-chord (arg)
(interactive "p")
(isearch-printing-char)
(unless (fboundp 'smartrep-read-event-loop)
(require 'smartrep))
(run-at-time 0.3 nil 'keyboard-quit)
(condition-case e
(smartrep-read-event-loop
'(("j" . isearch-exit-chord-worker)
("k" . isearch-exit-chord-worker)))
(quit nil)))
;; example bindings
(define-key isearch-mode-map "j" 'isearch-exit-chord)
(define-key isearch-mode-map "k" 'isearch-exit-chord)
This approach actually has several advantages over key-chord.el.
It does not use an input method, so you can use a different input method in conjunction with this.
The first character is shown immediately, and retracted if it is incorrect, while key-chord.el only shows it after a delay.
I have found this to be useful:
(defun isearch-enable-key-chord ()
(key-chord-mode 1)
(key-chord-define isearch-mode-map "jj" 'isearch-cancel))
(add-hook 'isearch-mode-hook 'isearch-enable-key-chord)
Related
I'm using org-mode's speed keys alot and I would like to have key sequences as speed keys for ease of remembering. In this case, I want to have "i n" insert a subheading, and "i t" insert a todo subheading.
I know I can setup a sequence by using a prefix keymap like this:
(progn
(define-prefix-command 'my-org-speed-command-insert-subheading-map)
(define-key my-org-speed-command-insert-subheading-map (kbd "n") 'jan/org-insert-subheading)
(define-key my-org-speed-command-insert-subheading-map (kbd "t") 'jan/org-insert-todo-subheading)
)
(global-set-key (kbd "C-c i") my-org-speed-command-insert-subheading-map)
so pressing "C-c i n" and "C-c i t" call the corresponding functions. Fine.
Now, when I give "my-org-speed-command-insert-subheading-map" as the function to be called by org speed commands
(setq org-speed-commands-user (quote ((":" . helm-M-x)
("a" . org-toggle-archive-tag)
("i" . my-org-speed-command-insert-subheading-map)
… … …
)))
it doesn't work as expected. What am I doing wrong?
I understand I can't call the prefix map like actual commands, and hence it isn't quoted when bound with global-set-key, so I suspect that the problem is related to this. But then how do I call it? Or is there a much simpler way for achieving my goal that I simply didn't see?
EDIT:
I found a way to work around the issue for now by having the "i" speed key call this function:
(defun my-org-i-map-function ()
(let (key1)
(setq key1 (read-key-sequence "press \"i\" for a simple subheading, \"t\" for a TODO-subheading"))
(cond
((equal key1 "i")(jan/org-insert-subheading nil))
((equal key1 "t")(jan/org-insert-todo-subheading nil))
(t (message "you didn't set a function for this key sequence")))
))
but this is a rather ugly solution as I'd have to call different functions for every first letter, and the second and third letter are buried in the function definitions. So using this approach extensively is bound to bring about lots of confusion in the longer run.
https://github.com/abo-abo/worf
GNU Emacs minor mode that provides vi-like bindings for org-mode
Take a look or maybe "hydra" package from the same author.
I'm pretty sure you are limited to single letters for speed commands. E.g. the docstring for org-speed-command-activate says:
"Hook for activating single-letter speed commands.
org-speed-commands-default specifies a minimal command set.
Use org-speed-commands-user for further customization."
I have a problem when using Etags in Emacs. Everytime I tap \M+. to jump to a difinition point, a query is always popping up, like:
Find tag (default function_name):
And I have to tap 'Enter' to make sure of it.
But in most cases, I find I can choose the default one. So is there any method with which I can surpress this message?
I found the reason is because:
(defun find-tag (tagname &optional next-p regexp-p)
(interactive (find-tag-interactive "Find tag: "))
...
)
Why do I have to choose a tag? Why can not the default one just be the word under the point? Can I just remove this line? (interactive), or is there a good solution?
Going shortly through a couple of defuns in the etags sources via Emacs's awesome C-h f, one can find that the default tag to search is determined via a function named find-tag-default.
This means you could just define the following function:
(defun find-tag-under-point ()
(interactive)
(find-tag (find-tag-default)))
Then you can bind this to whatever key you want via define-key or global-set-key or local-set-key.
(The interactive form is always necessary if you want a function to be a "command" which can be called with M-x or bound to a key.)
You can write your own functionality over the find-tag (or any interactive function likewise)
(defun find-tag-under-point (&optional arg)
(interactive "P")
(cond ((eq arg 9)
(let ((current-prefix-arg nil))
(call-interactively 'find-tag)))
(arg
(call-interactively 'find-tag))
(t
(find-tag (find-tag-default)))))
(global-set-key (kbd "M-.") 'find-tag-under-point)
Then hotkey C-9M-. calls find-tag (old function) as usual, but the behaviour of find-tag-under-point (new-function) by default is what you want.
Context: I want to make a minor mode where pressing f twice fast results in whatever the pressing of ( should do at that time. This doesn't always mean just insertion of (. For example, in buffers where paredit mode or autopair mode is enabled, pressing of ( usually results in insertion of (). In a paredit mode buffer, that sometimes results in wrapping the selected text: for example, if I select a b and press (, that should result in replacing the selection with (a b).
For detection of f being pressed twice, I just need to take the logic in the short code in http://www.emacswiki.org/emacs/electric-dot-and-dash.el
So the only missing piece is a Lisp code snippet that tells Emacs "Trigger pressing of ( now!"
The first thing that came to my mind was that the snippet should do
find the command bound to the key (
and then call call-interactively on that command.
but that breaks down if the auto pairing package (autopair or paredit or other similar package) binds ( to a command that has a logic that looks up what key was used to call the command, or if the package simply relies on post-self-insert-hook or post-command-hook instead of binding (.
update
I've looked up Key Chord documentation and it turns out what I am trying to do with answers to this question has a simpler solution:
(require 'key-chord)
(key-chord-mode 1)
(defvar my-easy-open-paren-mode-map
(let ((map (make-sparse-keymap)))
(key-chord-define map ",." (kbd "("))
map))
(define-minor-mode my-easy-open-paren-mode
"In this mode, pressing . and , together is another way of pressing the open paren.")
(defvar my-easy-semicolon-mode-map
(let ((map (make-sparse-keymap)))
(key-chord-define map ";;" (kbd "C-e ;"))
map))
(define-minor-mode my-easy-semicolon-mode
"In this mode, pressing semicolon twice fast is another way of pressing C-e and semicolon.")
(add-hook 'prog-mode-hook 'my-easy-open-paren-mode)
(add-hook 'c-mode-common-hook 'my-easy-semicolon-mode)
Triggering key press may still be useful in other contexts though.
You might appreciate the Key Chord library for binding functions to a double key-press. (I wouldn't recommend using f if you'll be writing in English, mind you; but YMMV.)
post-self-insert-hook would still run if the binding was self-insert-command. post-command-hook will run in any case, but if you're worried about it seeing an incorrect function and/or input event, you can manipulate those...
After looking up the binding, your function can set this-command to the function you're about to call-interactively, and last-command-event to the required key. e.g.:
(defun my-fake-paren ()
(interactive)
(let ((command (key-binding "(")))
(setq last-command-event ?\()
(setq this-command command)
(call-interactively command)))
I use Key Chord for this sort of thing, although the page you link appears to do the same thing. The trick is getting the call to call-interactively to work correctly. I wrapped it in a let that reset the variable last-command-event, such that call-interactively thinks it was a "(". This works for me in paredit and fundamental modes.
(require 'key-chord)
(key-chord-mode 1)
(defun my-paren-call ()
(interactive)
(let ((last-command-event ?\())
(call-interactively (key-binding "("))))
(key-chord-define-global "ff" 'my-paren-call)
I've looked through a number of other questions and el files looking for something i could modify to suit my needs but I'm having trouble so I came to the experts.
Is there anyway to have a key behave differently depending on where in the line the cursor is?
To be more specific I'd like to map the tab key to go to the end of the line if I'm in the middle of the line but work as a tab normally would if my cursor is positioned at the beginning of the line.
So far I have braces and quotes auto-pairing and re-positioning the cursor within them for C++/Java etc. I'd like to use the tab key to end-of-line if for example a function doesn't have any arguments.
Behaving differently depending on where point is in the line is the easy bit (see (if (looking-back "^") ...) in the code). "[Working] as a tab normally would" is the harder bit, as that's contextual.
Here's one approach, but I was thinking afterwards that a more robust method would be to define a minor mode with its own binding for TAB and let that function look up the fallback binding dynamically. I wasn't sure how to do that last bit, but there's a solution right here:
Emacs key binding fallback
(defvar my-major-mode-tab-function-alist nil)
(defmacro make-my-tab-function ()
"Return a major mode-specific function suitable for binding to TAB.
Performs the original TAB behaviour when point is at the beginning of
a line, and moves point to the end of the line otherwise."
;; If we have already defined a custom function for this mode,
;; return that (otherwise that would be our fall-back function).
(or (cdr (assq major-mode my-major-mode-tab-function-alist))
;; Otherwise find the current binding for this mode, and
;; specify it as the fall-back for our custom function.
(let ((original-tab-function (key-binding (kbd "TAB") t)))
`(let ((new-tab-function
(lambda ()
(interactive)
(if (looking-back "^") ;; point is at bol
(,original-tab-function)
(move-end-of-line nil)))))
(add-to-list 'my-major-mode-tab-function-alist
(cons ',major-mode new-tab-function))
new-tab-function))))
(add-hook
'java-mode-hook
(lambda () (local-set-key (kbd "TAB") (make-my-tab-function)))
t) ;; Append, so that we run after the other hooks.
This page of Emacs Wiki lists several packages (smarttab, etc.) which make TAB do different things depending on the context. You can probably modify one of them to do what you want.
I don't know if there's something wrong with my settings but when I press M-f (forward a word)
it doesn't matter where I am, it never place the cursor in the next word (just between words). This doesn't happen with M-b which place my cursor in the beginning of the previous word.
Is this a normal behavior? How do I place my cursor at the beginning of the following word?
The macro solution described is a great way to get this behavior in a session, but it's a little inconvenient if that's the default behavior you want, since you have to define it every time you start emacs. If you want M-f to work like this all the time, you can define an elisp function and bind it to the key. Put this in your .emacs file:
(defun next-word (p)
"Move point to the beginning of the next word, past any spaces"
(interactive "d")
(forward-word)
(forward-word)
(backward-word))
(global-set-key "\M-f" 'next-word)
Ok, just so we're clear, Im going to assume you are talking about the commands forward-word and backward-word these are bound by default to Alt+f and Alt+b
eg string: "Hello dolly I am here"
If your cursor is on the "H" of "Hello", and you do forward-word the cursor will move to the space between "Hello" and "dolly", but it sounds like you want the cursor to be on the letter "d" of "dolly" instead of in-front of it.
So, do forward-word twice, then backward-word once.
That will put your cursor on the "d" of "dolly".
This can be automated with a macro.
;; = comments, do not type them
Ctrl+x ( ;;start macro
Alt+f Alt+f Alt+b
Ctrl+x ) ;;end macro
Then to run last defined macro do this:
Ctrl+x e
EDIT: as pascal mentioned in a comment, this can also just be done with
Alt+f Ctrl+f
You could put that into a macro as well, either way the result is the same.
That is correct behavior. According to the Emacs manual, "[f]orward motion stops right after the last letter of the word, while backward motion stops right before the first letter."
Why is it this way? Perhaps to be consistent with kill-word (M-d).
Moving forward twice and backwards once is fine unless you are at the beginning of a line with spaces in the front. Then going forward twice and back once will move you to the next word not the first word. The code below will mimic vi's "w" command perfectly. I've written this quite fast so this code can be cleaned up further.
(defun forward-word-to-beginning (&optional n)
"Move point forward n words and place cursor at the beginning."
(interactive "p")
(let (myword)
(setq myword
(if (and transient-mark-mode mark-active)
(buffer-substring-no-properties (region-beginning) (region-end))
(thing-at-point 'symbol)))
(if (not (eq myword nil))
(forward-word n))
(forward-word n)
(backward-word n)))
(global-set-key (kbd "M-C-f") 'forward-word-to-beginning)
Try something like following:
;; replace common word-operations on same-syntax-operations
(require 'thingatpt)
(global-set-key "\M-f" 'forward-same-syntax)
(global-set-key "\M-b" (lambda()
(interactive)
(forward-same-syntax -1)))
(defun kill-syntax (&optional arg)
"Kill ARG sets of syntax characters after point."
(interactive "p")
(let ((opoint (point)))
(forward-same-syntax arg)
(kill-region opoint (point))))
(global-set-key "\M-d" 'kill-syntax)
(global-set-key [(meta backspace)] (lambda()
(interactive)
(kill-syntax -1)))
You can achieve this behavior by using the forward-to-word and backward-to-word found in misc.el. I have these bound to Meta-F/Meta-B (i.e. with Shift pressed). These are equivalent to Meta-f/Meta-b for forward-word/backward-word
My .emacs has the following bindings
(global-set-key (kbd "M-F") #'forward-to-word)
(global-set-key (kbd "M-B") #'backward-to-word)