How to make Emacs key-bindings work in minibuffer? [duplicate] - emacs

I'm trying to redefine the keys used to navigate the history when inside several commands accepting regexps and offering C-p / C-n history navigation. I'd like to use other keys, in addition to C-p / C-n. For example when using occur or replace-regexp, C-p and C-n can be used to go to previous and next elements.
I've tried several things but can't make it work. I think I'm missing the "big picture" here.
Which mode-map do I need to modify, when and how? Everything I tried failed.
P.S: Note that I've got my own minor mode with all my keymaps as adviced here.

I'm assuming you just needed minibuffer-local-map. Subsequent definitions using keys previously assigned to that key map will trump the prior definitions. To disable a prior key assignment, then just create a new definition and set the last portion to nil instead of 'function-name.
(define-key minibuffer-local-map (kbd "<f6>") 'help-for-help)
Here is an excerpt from Emacs Trunk .../lisp/bindings.el:
(let ((map minibuffer-local-map))
(define-key map "\en" 'next-history-element)
(define-key map [next] 'next-history-element)
(define-key map [down] 'next-history-element)
(define-key map [XF86Forward] 'next-history-element)
(define-key map "\ep" 'previous-history-element)
(define-key map [prior] 'previous-history-element)
(define-key map [up] 'previous-history-element)
(define-key map [XF86Back] 'previous-history-element)
(define-key map "\es" 'next-matching-history-element)
(define-key map "\er" 'previous-matching-history-element)
;; Override the global binding (which calls indent-relative via
;; indent-for-tab-command). The alignment that indent-relative tries to
;; do doesn't make much sense here since the prompt messes it up.
(define-key map "\t" 'self-insert-command)
(define-key map [C-tab] 'file-cache-minibuffer-complete))

To add to what #lawlist said (which was to bind the key in minibuffer-local-map):
There are multiple minibuffer keymaps, depending on what is being read in the minibuffer, and how. And which of those keymaps you might want to use can depend on which Emacs version you are using.
In addition, there is also the keymap for interaction with buffer *Completions*: completion-list-mode-map.
For completion in the minibuffer, the main keymap is minibuffer-local-completion-map.
Here is a list of the minibuffer keymaps. Some of these might not be available (used) in your Emacs version.
minibuffer-local-map
minibuffer-local-ns-map
minibuffer-local-isearch-map
minibuffer-local-completion-map
minibuffer-local-must-match-map
minibuffer-local-filename-completion-map
minibuffer-local-filename-must-match-map
minibuffer-local-must-match-filename-map
In addition, you can use minibuffer-with-setup-hook (or minibuffer-setup-hook directly) to add key bindings on the fly, for the duration of a single minibuffer reading.
I will add this info, since it can be really helpful when you are manipulating minibuffer keymaps: You can use C-h M-k (command describe-keymap), from library help-fns+.el, to see all of the bindings of a given minibuffer keymap in human-readable form.

Related

How can I unbind ctrl+c in emacs

Im a new user in emacs, and use emacs because of the ansi-term/multi-term
Now I have to type ctrl+C twice to send it to term.
I would like to unbind the CTRL+C shortcut in emacs so I can send it directly to the term.
Is it possible?
Solution to override all other keymaps in term-mode buffers:
(defun jpk/term-mode-hook ()
(let ((map (make-sparse-keymap)))
(define-key map (kbd "C-c") 'term-send-raw)
(set-transient-map map (lambda () t))))
(add-to-hook 'term-mode-hook 'jpk/term-mode-hook)
Assuming you don't have any other binds to C-c (this is unlikely, see below):
(define-key term-mode-map (kbd "C-c") 'term-send-raw)
This was sufficient for me when starting emacs with emacs -q (i.e. without any of my customizations).
It is possible to change the key binding, but in my opinion it isn't worth it. C-c is a prefix key in Emacs, meaning that many key bindings start with it. You'll be fighting pervasive conventions and you will probably be frustrated. Accept that Emacs is not 100% a terminal emulator and there are a few minor compromises to be made.
Not too sure what you're asking, but binding a key to nil unbinds it.
So for a global C-c binding: (global-set-key "\C-c" nil).
And for a local binding in mode foo: (define-key foo-mode-map "\C-c" nil).
Note that you might need to undefine it in more than one local map. Remember too that you can use (current-local-map) and (current-global-map). For example, if you use M-x report-emacs-bug then C-c is a key prefix for multiple keys, in multiple keymaps. To undefine it in the bug-reporting buffer, you will need to use both of these:
(define-key (current-local-map) "\C-c" nil)
(define-key mml-mode-map "\C-c" nil)
How did I find out that mml-mode-map was involved? C-c C-h.

How to restore anything-like behavior for TAB autocomplete in helm?

A related question was asked here. But the answer is to get used to the new way autocomplete works in helm. I cannot get used to it, here's why.
Say, I want to open a file /home/user/work/f.txt. I do C-x C-f, it takes me to current dir, say /current/dir/. I hit Backspace and notice that autocomplete won't let me delete /. Ok, turn off autocomplete with C-Backspace. Then kill the line C-a C-k and start typing. Notice that autocomplete doesn't work, turn it back on C-Backspace. Normally I would type the part that I know is probably unique, e.g. /hom and hit Tab.
Not here. As soon as I type /ho, autocomplete resolves it to /home/, but since I type fast, I end up with /home/m, and continue typing now meaningless characters until I notice it. Chances are, by that time I got autocompleted into directories that I had no intent of going.
So I have to constantly watch what autocomplete is doing, rather than rely on what I type and only checking suggested completions when I hit Tab.
I also find myself descending into wrong directories due to occasional typo, and then having difficulty going up a level -- evil autocomplete won't let you fix the situation with a couple of Backspaces.
This interaction of autocomplete behavior and the removal of Tab functionality completely upsets my work, so much that I decided to ask this question. I am looking to either:
restore the old functionality
learn how to use autocomplete in a meaningful way, or
configure helm's C-x C-f to behave more like a linux command line
Please help.
Here are some ido tricks if you want to start using it.
Let me know if helm is better, perhaps I'll switch over.
I tried once shortly, but didn't like it.
Basic setup:
This will give you `ido-find-file on C-x C-f.
(ido-mode)
(setq ido-enable-flex-matching t)
Smex setup:
Install from https://github.com/nonsequitur/smex.
(require 'smex)
(global-set-key "\C-t" 'smex)
Switch buffers with ido:
(global-set-key
"η"
(lambda()(interactive)
(when (buffer-file-name)
(save-buffer))
(ido-switch-buffer)))
(global-set-key
(kbd "C-η")
(lambda()(interactive)
(let ((ido-default-buffer-method 'other-window))
(ido-switch-buffer))))
Tricks:
;; 1
(add-hook 'dired-mode-hook
(lambda()
(define-key dired-mode-map "j" 'ido-find-file)))
(add-hook
'ido-setup-hook
(lambda()
;; 2
(define-key ido-file-dir-completion-map "~"
(lambda ()(interactive)
(ido-set-current-directory "~/")
(setq ido-exit 'refresh)
(exit-minibuffer)))
;; 3
(define-key ido-buffer-completion-map "η" 'ido-next-match)
;; 4
(define-key ido-buffer-completion-map (kbd "C-p")
'ido-fallback-command)
;; 5
(define-key ido-completion-map (kbd "C-.") 'smex-find-function)
(define-key ido-completion-map (kbd "C-,") 'smex-describe-function)))
Quick open file from dired.
Move to home directory one key faster (i.e. ~ instead of ~/).
Cycle buffer candidates with the same key that shows the candidates (a la C-TAB in Firefox).
Useful to have a fall back when you want to create a file-less buffer (ido will try
select an existing buffer unless you fall back).
Useful to jump to function definition/documentation.
If you want TAB completion of directories and file names, map helm-execute-persistent-action to the TAB key:
(define-key helm-map (kbd "<tab>") 'helm-execute-persistent-action)
See also the answer to "How can I change emacs helm-find-file default action[...]".

Emacs keybinding not working in custom major mode

I'm in the early stages of creating a major mode for Emacs for browsing and interacting with the Stack Exchange Network.
Involved in it are several major modes, all with one-key keybindings similar to dired. I looked at the source for dired, and extracted what I thought would work:
(defvar stack-network-mode-map
(let ((map (make-keymap)))
(define-key map "n" 'stack-network-next-site)
(define-key map "p" 'stack-network-previous-site)
(define-key map "," 'stack-network-move-site-up)
(define-key map "." 'stack-network-move-site-down)
(define-key map "j" 'stack-network-jump-to-bookmarks)
(define-key map "\C-m" 'stack-network-do-enter-site) ; ret
(define-key map "o" 'stack-network-do-enter-site)
(define-key map "u" 'stack-network-do-profile-summary)
(define-key map "\C-uu" 'stack-network-do-profile-summary-for-user)
(define-key map "i" 'stack-network-do-inbox)
(define-key map "b" 'stack-network-toggle-bookmark)
(define-key map "?" 'stack-network-list-functions) ; [1]
(define-key map "\C-i" 'stack-network-display-details) ; tab
map)
"Keymap for Stack Exchange: Network Browser major mode")
but unfortunately this seems to have absolutely no effect; the buffer is simply edited just as any other normal buffer would be. How can I achieve single-key keybindings if this isn't they way? (Which, by the way, I'm sure it is. There has to be something else going on here.)
You want to define stack-network-mode using define-derived-mode (and make it derive from special-mode, for example).
Other comments about your code:
use () rather than nil for empty argument lists.
stack-network-next-site needs to have (interactive) right after the docstring to make it an interactive command otherwise it won't work as a key-binding.
If you don't want to use special-mode, you can call supress-keymap right after creating your make-keymap.
Move the definition of stack-network-mode-map before the definition of the mode. Otherwise define-derived-mode implicitly defines this variable, and defvar does not change the value of non-nil variables, so the map will be empty actually.
See Derived Modes:
The new mode has its own sparse keymap, named variant-map. define-derived-mode makes the parent mode's keymap the parent of the new map, unless variant-map is already set and already has a parent.
You have defined a keymap but you have not used it. The variable exists but does not capture any key events.
(use-local-map stack-network-mode-map)

emacs, python-mode.el define-key map assignment

When I load the python-mode.el file in emacs, I don't get any of the key bindings specified.
I started playing with the file and noticed that when I change:
(define-key map [(control c)(\#)] 'py-comment-region)
to:
(define-key global-map [(control c)(\#)] 'py-comment-region)
it works fine.
I went to look where the define the map variable and saw:
(defvar py-shell-map nil
"Keymap used in *Python* shell buffers.")
;; used by py-completion-at-point, the way of python.el
(defvar python-shell-map
(let ((map (copy-keymap comint-mode-map)))
(define-key map [tab] 'py-shell-complete)
(define-key map "\C-c-" 'py-up-exception)
(define-key map "\C-c=" 'py-down-exception)
map)
"Keymap used in *Python* shell buffers.")
Is the 'map' variable defined alright? Should I do some changes to my init file? I assume that this file works to everybody else, so why I need to change the 'map' variable to 'global-map' for it to work in my computer?
I'm running in a virtual machine if that's of any help.
The code you quoted in which you believe map is defined is not actually the relevant portion of the code. It is a different keymap used for a python shell, and it's not the one used when you edit a python file in Emacs.
The line you're editing appears in python-mode inside the following code block:
(defvar python-mode-map)
(setq python-mode-map
(let ((map (make-sparse-keymap)))
;; electric keys
(define-key map [(:)] 'py-electric-colon)
(define-key map [(\#)] 'py-electric-comment)
...
As you can see the variable map is first initialized as a "sparse keymap", then certain key-bindings get defined in that map, and finally the map is set as the value of python-mode-map. The latter is the keymap used in a buffer that is in python-mode.
So the keybindings should work - but of course only in a buffer that is in python-mode. To activate python-mode in a buffer, type M-x python-mode. This works only after the file python-mode.el has been loaded.
You can check if your current buffer is in python-mode in two ways:
your mode line should display the letters "Py"
type M-: ENTER major-mode ENTER -> this should print "python-mode" to the minibuffer
Each major mode and some minor modes have their own keymap, which is overlaid on the global keymap (which is global-map). When you press a key, Emacs tries to find a binding for that key in the overlaid keymaps, falling back to "more global" ones until it gets to the global-map. This is why global-map works and map doesn't.
In lisp, let is used to bind local variables. The map variable doesn't exist outside of the let (or maybe it does, but it's probably not the one you want). Read the documentation for let and defvar (e.g. C-h f defvar).
You need to figure out which keymap is being used in the major mode, and use define-key on that. In this case, (define-key python-mode-map (kbd "C-c #") 'py-comment-region) will probably work. N.B. I do not use python-mode.el, but looking at the source it seems like it uses python-mode-map as the keymap variable. The other keymaps are for auxiliary buffers.

Assign multiple Emacs keybindings to a single command?

I'm giving ErgoEmacs mode a try to see if I can use Emacs more comfortably. Some of its keybindings are fairly intuitive, but in many cases I don't want to outright replace the defaults.
For example, in the context of ErgoEmacs' navigation shortcut structure, M-h makes sense as a replacement for C-a--but I want to be able to use both, not just M-h. I tried simply duplicating the commands:
;; Move to beginning/ending of line
(defconst ergoemacs-move-beginning-of-line-key (kbd "C-a")) ; original
(defconst ergoemacs-move-end-of-line-key (kbd "C-e")) ; original
(defconst ergoemacs-move-beginning-of-line-key (kbd "M-h")) ; ergoemacs
(defconst ergoemacs-move-end-of-line-key (kbd "M-H")) ; ergoemacs
But Emacs simply overwrites the first keybinding with the second. What's the best way to address this?
To re-post reply from ergo-emacs mailing list:
Xah Lee said:
that's very easy.
in the
ergoemacs-mode.el file, there's this
line (load "ergoemacs-unbind") just
comment it out. That should be all
you need to do. However, note that
ErgoEmacs keybinding defines those
common shortcuts such as Open, Close,
New, Save... with keys Ctrl+o,
Ctrl+w, Ctrl+n, Ctrl+s etc. About 7 of
them or so. So, i think some of these
will hit on emacs traditional
bindings with Ctrl. if you are new to
ErgoEmacs and trying to explore it,
you might just try starting with few
keys. this page might have some
useful info:
http://code.google.com/p/ergoemacs/wiki/adoption
thanks for checking out ErgoEmacs!
Xah ∑ http://xahlee.org/
As it turns out, ErgoEmacs uses two files to define the keybinding. One is the main ergoemacs-mode.el file, and the other is the specific keyboard layout you select (e.g. ergoemacs-layout-us.el). The latter document creates a constant, which the former uses to create the keybinding. So while I thought I was duplicating the keybinding, I was actually changing the constant which was subsequently used for that purpose.
Solution:
In ergomacs-mode.el:
;; Move to beginning/ending of line
(define-key ergoemacs-keymap ergoemacs-move-beginning-of-line-key 'move-beginning-of-line)
(define-key ergoemacs-keymap ergoemacs-move-end-of-line-key 'move-end-of-line)
(define-key ergoemacs-keymap ergoemacs-move-beginning-of-line-key2 'move-beginning-of-line) ; new
(define-key ergoemacs-keymap ergoemacs-move-end-of-line-key2 'move-end-of-line) ; new
In ergoemacs-layout-us.el:
;; Move to beginning/ending of line
(defconst ergoemacs-move-beginning-of-line-key (kbd "M-h"))
(defconst ergoemacs-move-end-of-line-key (kbd "M-H"))
(defconst ergoemacs-move-beginning-of-line-key2 (kbd "C-a")) ; new
(defconst ergoemacs-move-end-of-line-key2 (kbd "C-e")) ; new
Huh? Is having one and only one way for every function some golden principle of ErgoEmacs? Because normal keybinding works exactly the opposite way: you name one key at a time and specify what it should do. If a mode defines a global variable to mean "the key that end-of-line is bound to", then of course there can be only one value, but with the normal binding commands you can bind the same function to as many combinations as you like. In fact, every keybinding I have ever seen used looked either like this
(global-set-key [(meta space)] 'just-one-space)
or like this
(add-hook 'c-mode-hook 'my-c-mode-hook)
(defun my-c-mode-hook ()
(define-key c-mode-map [(control c) b] 'c-insert-block))
if it's only for a specific mode.