reddit / emacs

Consistent Emacs Keybindings

ameer_taweel · 2022-04-11 01:00
Hello Everyone. I want all my Emacs keybindings to be consistent and make sense (for me). However, this does not come by default. I want to start from a scratch, so I would like to unbind **everything**. All Emacs default bindings, and plugin bindings (with the exception of Evil Mode). Basically, I want to things: + A way to unbind all default bindings. + A way to prevent a plugin from creating bindings. How can I do this? **EDIT:** I tried removing the default bindings with this: ```lisp (setq my-global-map (make-keymap)) (substitute-key-definition 'self-insert-command 'self-insert-command my-global-map global-map) (use-global-map my-global-map) ``` It almost does the job, except that some keys stop working properly, like `enter`, `backspace`, and `escape`.
[deleted] · 2022-04-11 01:55
[deleted]
7890yuiop · 2022-04-11 01:59
> A way to prevent a plugin from creating bindings. > How can I do this? You cannot do that. I *suspect* that https://stackoverflow.com/questions/683425/globally-override-key-binding-in-emacs is the sort of thing you're looking for in practice -- a way to have your personal keymap take precedence over others.
tmting · 2022-04-11 02:00
You are a mad man
ameer_taweel · 2022-04-11 02:03
May I ask why is that the case? I thought that since we can write Lisp code to configure Emacs, we can do anything we want...
ameer_taweel · 2022-04-11 02:04
Don't they do a similar thing in Spacemacs and Doom-Emacs? They have their own set of bindings instead of the default ones. So it seems I'm not the only one who dislikes the default bindings...
cgroza · 2022-04-11 02:13
Packages configure keybinds without asking. You must write code that deletes those bindings yourself.
bugamn · 2022-04-11 02:21
I haven't used these, but from what I heard they are just running evil with added keybindings, and I don't think that involved undoing all keybindings.
TommyJollyboat · 2022-04-11 02:53
Welll... You could set your keybinds in your init file, then `(fset #'define-key nil)`, to stop any more being created. But this isn't a good idea -- either check @7890yuiop 's link, or consider adopting an existing key scheme like Evil or ErgoEmacs. Or perhaps look at what ErgoEmacs (or similar) does and just copy that.
[deleted] · 2022-04-11 03:08
[deleted]
ieure · 2022-04-11 04:01
The packages are going to call `define-key` unless you go edit *their* code. You can do that, but it's not a great idea. Maybe you can add advice which turns it into a noop.
[deleted] · 2022-04-11 04:25
[deleted]
7890yuiop · 2022-04-11 04:33
You can't do it because you can't control how or when it happens. You can't control *when* it happens because that time might be "before you started (or even installed) Emacs". Keymaps are sometimes generated at byte-compilation time, and thus even if you were to take the extreme measure of preventing `define-key` from doing anything*, you will sometimes still acquire populated keymaps when libraries are loaded (although if the libraries were byte-compiled while the neutralised `define-key` was in place, you would then typically be loading empty keymaps; but you would need to recompile everything to get to that point). Native compilation might preclude even that, as IIRC it compiles everything asynchronously in isolation, so the intended clobbering might not actually be in effect when the native code was being generated. You would then have to edit the core code to enforce your override irrespective of whether your config was loaded. You can't control *how* it happens because in principle libraries could be adding bindings *without* using `define-key`. It would be highly unusual, and I don't know if that *actually* happens anywhere; but a keymap is, after all, just a list -- so your requirement is akin to intercepting every data manipulation that takes place, and figuring out whether the data being manipulated was part of a keymap. (*In practice* I think that messing with `define-key` and recompiling all of the things would affect almost all keymaps; but *in general* there's no guarantee.) Of course you can do anything you want in the sense that all of the source code is available, and therefore you can change it in any way you want; but I would urge you not to try to do what you've described. There are going to be better (and less-painful) ways of achieving your end goal. ---- (*) If you desperately want to do that, I'd suggest using: (advice-add 'define-key :override #'ignore) As you can then *remove* that advice again.
Status-Detective-783 · 2022-04-11 04:50
I used to think this was the way. The multitude of seemingly arbitrary keybindings scared me away from learning emacs. That prevented me from learning and benefiting from emacs/org-mode for 20 years. Recently, I decided to bite the bullet and just learn it the way it is "out of the box", using generally recommended key bindings. And I learned something new about myself and about key bindings. Key bindings are not necessarily a logical thing. Only at the beginning are they potentially logical. But after you use them, they just become second nature. It's better to think of keybindings as learning words in a language, it's very much like that. There's no logical sense that one thing is named "dog" and another "cat" and another "fly" and another "bird". Wouldn't it be more logical to call one thing low-pointy-eared-animal and another low-floppy-eared-animal and another small-buzzing-winged-animal? That might make learning the "names" for different things easier at first. But in the end, you just learn dog, cat, fly, and the logic doesn't matter any more. So that's what I learned about myself. I have a FAR better ability to learn keybindings than I realized. Because it's a natural skill to be able to learn a variety of "words" aka another language. That's what you learn when you learn emacs/org-mode. You are learning a language. And generally speaking, most of the main packages have been designed to stay out of each other's way, so the default, suggested key bindings are going to be pretty good. tldr: It's very probably not as important as you think it is, but you'll only be able to see the truth of this after using emacs on a regular basis for a few months.
Extension_Try_6870 · 2022-04-11 05:53
You may have heard of evil-collection ? You don't need to unbind everything. You can just rebind what you need and use.
ianjs · 2022-04-11 06:40
This. I went through the same process when I first started Emacs. I tried CUA mode I initially and that constantly conflicted with standard Emacs keys and tutorials. Then I decided to change keys to something that “made sense” to me. That ended up a mess. In the end I also bit the bullet and just used standard keys. I was amazed how quickly they became second nature. The designers of Emacs weren’t silly and there is usually some mnemonic value to the mappings if it’s feasible. Bonus: if you know the basics for cursor movement and editing they also work on a command line and some browsers can be coaxed into using them for text entry. Sometimes specialised apps like VSCODE have an Emacs emulation too.
Horrih · 2022-04-11 06:50
I did the same for the exact same reason (see [my emacs config](https://github.com/Horrih/config/blob/main/.emacs)) and it's surprisingly easy to do ! And it's really really nice, i really love it so far to have the bindings exactly the way you want. The best way it to define your own minor mode : in case of issue you can turn it off and all the default keybinding will come back. This way you can also turn it off for special buffers like magit I used mine to implement a vim-like editing mode, with - a typing mode with all the default bindings for typing. - a command mode for movement using ijkl and all the other keys for my own keybindings Here is an extract from my config (define-minor-mode ijkl-local-mode "Minor mode to be able to move using ijkl" :lighter " ijkl" :keymap '(([t] . ignore))) [t] specifies the default bindings for the mode, use self-insert-command if you want keys to insert letters by defaults, 'ignore if you want modal editing like me. All the default commands will be effectively unbound. Don' t forget to bind an exit command or meta-x Otherwise you won't be able to even exit emacs ! Last advice make extensive use of the following packages - hydra to define quickly groups of bindings easy to remember For example i bound an hydra to f for all the file related commands, to s for all the string related commands, b for all the buffer commands and so on. - the keychord package, it will give you tons of additional easy to use bindings
organic-bookworm · 2022-04-11 06:59
>Even then, in principle libraries could be adding bindings without using `define-key`. From the top of my head. The `ediff-save-buffer` command in `ediff` package, bound to `wa`, `wb`, `wc` and `wd`, directly checks `last-command-event` for buffer letter to decide which of compared buffers to save. Menus in `org` package, like ones from `org-agenda` and `org-capture` libraries, read keys directly via `read-char-exclusive` (e.g. see `org--mks-read-key`).
scatteredRobot · 2022-04-11 07:28
I'm a doom emacs user and all of the emacs default keybinds that I have tried still work. So I don't think it does remove all keybinds. It does have its own though.
7890yuiop · 2022-04-11 07:37
Good point. I was considering only keymaps, but reading key events interactively can happen in other contexts.
ameer_taweel · 2022-04-11 10:24
Thanks for the clarification!
ameer_taweel · 2022-04-11 10:27
Now that you explained it, I changed my mind about deleting them lol.
ameer_taweel · 2022-04-11 10:28
Totally makes sense. Thanks for the advice!
ameer_taweel · 2022-04-11 10:33
Thanks for sharing your config and for the advice!
ameer_taweel · 2022-04-11 10:34
The name is familiar but I didn't know what it does. I just checked it and I like the idea a lot. Thanks for mentioning it!
ftrx · 2022-04-11 11:04
Personally, in the year-long slow re-writing of my config I decide to just create a `mykeyboard.el` who concentrate all my bindings, so I see what I care about in a single place like (koe-global-bind-keys '( "<C-f5>" kill-this-buffer "<C-s-f5>" kill-buffer-and-window "<f1>" mode-line-other-buffer "<C-f1>" mode-line-other-buffer "<f2>" delete-other-windows "<C-f2>" delete-other-windows "<f3>" other-window "<C-f3>" other-window "s-<f1>" split-window-below "C-s-<f1>" split-window-below "s-<f3>" split-window-right "C-s-<f3>" split-window-right "M-|" koe-utils-minibuffer-shell "<iso-lefttab>" koe-utils-dpms-off "s-<iso-lefttab>" koe-utils-system-shutdown "<XF86AudioNext>" koe-utils-dpms-off "s-<XF86AudioNext>" koe-utils-system-shutdown "<f6>" koe-utils-goto-scratch-buffer "C-<f6>" koe-utils-goto-scratch-buffer "<insert>" calc)) where the function is just (defun koe-global-bind-key (KEY FUNCTION) "Bind KEY to FUNCTION in Emacs and, if loaded, EXWM." (if (fboundp 'exwm-input-set-key) (exwm-input-set-key (kbd KEY) FUNCTION) (global-set-key (kbd KEY) FUNCTION))) (defun koe-global-bind-keys (key-func-plist) "Bind keys to functions from KEY-FUNC-PLIST. Eg. (koe-global-bind-keys '( \"<f1>\" 'function \"<f2>\" 'other-func))" (while key-func-plist (koe-global-bind-key (car key-func-plist) (cadr key-func-plist)) (setq key-func-plist (cddr key-func-plist)))) Some have suggested General (package) but I found it overkill and not what I want since is more focused in use-package integration than in concentrate bindings in a single place to see them all. Before using and org-mode directly tangle-ed single file config I see bindings as noweb-ref-erenced blocks so I keep the inside use-package elisp side, but see them concentrated anyway in org-mode side, unfortunately such approach is too mechanic with much more overhead to be maintained than the actual "single elisp packages tangled from single org-mode files" approach, it's more complex to design at first but seems to be more modular and manageable specially when I change keyboard, witch is another year-long struggling since I still fail to find a good keyboard with enough keys...
thetemp_ · 2022-04-11 13:57
Just use the Super or Hyper modifiers. I believe I've taken the path you're looking down, and it leads to frustration. (Not sure if you're talking about rebinding evil-mode--which I tried--or using evil-mode but also rebinding all of the keys in "emacs-state", which honestly sounds like an even surer way to lose one's mind.) Emacs doesn't use Super or Hyper for any default bindings. So by pairing custom bindings with those modifiers you have the whole keyboard at your disposal. And you don't have to worry about relocating default bindings you might have replaced (or alternatively: throwing out functionality that you haven't even tried yet). In theory, you could redo all of Emacs's bindings on these layers. But it makes more sense to just use it for special situations. Those special situations may become less common anyway. I have a whole cluster of navigation commands bound under the Super key. But it turns out I've only consistently used them to select completion candidates, which was when I'd switch between upward and downward line movement a lot (annoying with default bindings in Dvorak layout, which places n and p on opposite sides of the keyboard). For actual cursor movement, I almost always use Avy, isearch, imenu, or anything else that will take me directly to the desired location. More recently, I started using 'vertico-quick to select completion candidates. And just like that, my custom-designed navigation cluster has become all but obsolete. So there's usually a better way than throwing out baby and bathwater.
hayduke2342 · 2022-04-11 18:37
I would stick to the defaults until they make some sense (They do ;-)) I configured this: `(use-package which-key` `:init (which-key-mode)` `:diminish which-key-mode` `:config (setq which-key-idle-delay 0.3))` Shows all possible keys after a small pause. This helped me learning the most needed ones really fast, and gives an easy reference when I forget some.
arthurno1 · 2022-04-11 20:27
> Basically, I want to things: > > A way to unbind all default bindings. > A way to prevent a plugin from creating bindings. > > How can I do this? Keybindings in Emacs are created dynamically and depend on which libraries are loaded. For the same reason for which you believe you can change everything in Emacs, so can you not prevent other packages to create new keybindings. You could re-define *defkeys* function, which is Emacs primitive on which most of the keybinding functions fall down, but a keymap in Emacs is just an a-list, so you can create it even without *defkeys*. So you would really be fighting windmills there. So it is not a viable approach. The normal approach is to define your own keys the way you want, if some keybinding from Emacs or a third package clashes with your bindings you just redefine that particular keybinding.
Busy_Ask_4990 · 2022-04-12 01:09
Ergoemacs mode does something like this. But it is imperfect.
ameer_taweel · 2022-04-12 02:48
Thanks for your reply. I'm coming to Emacs from Vim, so I already have a preferred way of navigation. That's why I love Evil Mode. However, sometimes plugins override my custom bindings. For example, I like to navigate my windows with `C-hjkl`, but `SLIME REPL` overrides `C-j` and `C-k`, which is annoying. Also, I like having custom bindings behind my leader key instead of `C-c` and `C-x`, so I will not be using the default bindings anyway. That's why I wanted a way to remove both the default and the plugin bindings.
ameer_taweel · 2022-04-12 02:50
I already use `which-key` for NeoVim. It's based off the Emacs plugin and it's awesome. It was one of the first plugins I installed for Emacs. It's indeed very handy.
oantolin · 2022-04-12 18:36
I think you don't need to unbind anything! Consider any keybinding that Emacs comes with: - If you never press it, you will have wasted time unbinding it. - If you do press it and it happens to do what you want, then you definitely wasted time by unbinding it! - If you press it and it does not do what you want, at that point rebind it, there is no need to unbind first. Unbinding is a waste of time in every case.
deltille · 2022-04-12 18:48
I went through the same thing. Incidentally, in VIM too. In both cases I found both programs strongly nudged me to just make my own special commands and ignore the default ones I didn't like, instead of working against what was already there. To the point of emacs in-theory reserving the c-c prefix for that out the gate (I think? Or is that the one that's in theory reserved for per-mode commands). I agree with and experienced what you describe, but I still time to time wish it was designed the other way, to encourage the rebind-everything use I was intuitively attracted to. Of course a strong argument could be made this is a design mistake, as then you could make no assumptions whatsoever about how someone has theirs set up, nor communicate much advice about input... but it still seems to run counter to the other design mission of complete customization. It's a weird self-contradiction. The language analogy is spot on. The balance between expressiveness and comprehensibility has to sit somewhere. (I just continue to wish it was a little further to the other side)
deltille · 2022-04-12 18:56
So glad you went to the effort and did this, I will be reading your config and taking notes of gotchas you must have had to solve.
deltille · 2022-04-12 18:57
You will find that while emacs *technically* lets you do just about anything, conventions in how people write things and other 'systems of doing' that have become norms are often designed less flexibly. (Including in systems that are rolled into emacs' core.) I learned this the hard way. -_-
thetemp_ · 2022-04-12 19:13
I hear what you're saying, but I would suggest a different approach to reach the desired result. You should ignore the global-map, in particular because you're using evil-mode already. Emacs uses a hierarchical approach to bindings. Bindings set in the global-map are at the bottom. Maps from major-modes are in the middle. And maps from minor-modes (like evil-mode) are at the top. EDIT: It's actually [a bit more complicated](https://www.gnu.org/software/emacs/manual/html_node/elisp/Searching-Keymaps.html), but notice from the linked manual page that Emacs only checks the global-map if the key is not bound in *any* other maps. If a map from a minor-mode or a major-mode is enabled, that map's bindings shadow (i.e. override) any conflicting bindings from the global-map. That's why you're C-hjkl bindings get overwritten by SLIME. You're changing bindings in the global-map, but SLIME's bindings are set in a major-mode map. What you want to do is set your bindings in a minor-mode-map, so they'll take precedence over major-mode bindings from SLIME. You could create your own minor mode to handle this, but that's probably not necessary, because you're already using evil-mode. Just set your bindings in the evil states you intend to use them with, and they'll override bindings from major-mode's like SLIME. EDIT: evil-mode's keymaps are in the `emulation-mode-map-alists`, so they get even higher precedence than minor-mode-maps. Set aside a little bit of time to learn properly how Emacs and evil-mode work together. Not sure if you've seen it, but here's [an excellent guide for transitioning from Vim to Emacs with evil-mode](https://github.com/noctuid/evil-guide). It's by the author/maintainer of [general.el](https://github.com/noctuid/general.el).
Horrih · 2022-04-12 20:16
Glad if it helps ! The first 600lines is not relevant to the keybindings so start at line 600 if you want to jump right to the interesting bits. Feel free to ask the questions you may have.
deltille · 2022-04-12 21:11
Went over it, I am pleased, it is a lot less wordy than I expected it to be. Questions requested: Is there any reason you're using 't instead of t? What is the story behind the mark ring code? Can you overview what key-alias is doing? I'm not that good (read: borderline clueless) at reading macros, and I *think* you're bypassing a common issue I've had dealing with interfering keybinds but I'd like to hear it in your words if you have the time.
Horrih · 2022-04-13 08:40
For 't instead of t : no reason, didn' t know both worked ! Elisp is not my strong point 😅 The mark ring: Emacs has a really unique way of handling the mark ring. First of all there are two rings : local and global mark ring. Both can only go backwards. The local is specific to the current buffer. The global spans multiple buffers but only stores one mark per buffer. My implementation implements a 3rd one, more like in traditional IDEs : a new global mark ring, with multiple marks per file, and where you can go forward as well as backwards. I'm not entirely happy with how it works but i like it better than the built-in Key alias: I wanted to be able to give an alias binding to existing binding. The issue if you do a traditional define-key is that a lot of bindings are replaced by the current mode. For example tab means indent, but in org mode tab is rebound to org-indent or whatever. Key-alias makes it possible to adapt to the context. You only have to specify if the binding you want to alias is in your own keymap or not. If it is outside, we set to nil this binding in your own keymap so that the search goes on in other keymaps
deltille · 2022-04-13 09:17
Thank you for the explanations, gives some insight to mark-related finagling I've been meaning to do, I never understood the emacs builtins for it that well. Right now for that style of navigation I rely on grabbing and shaking evil-jump by the shoulders until it does what I want.
ameer_taweel · 2022-04-13 23:50
Such a strong argument!