Skip to content

Latest commit

 

History

History
289 lines (219 loc) · 12.5 KB

README.org

File metadata and controls

289 lines (219 loc) · 12.5 KB

User-Keys

Sequences consisting of C-c and a letter are the only sequences reserved for users.  (An error).
melpa package melpa stable package CI workflow status DCO Check
  • Remove legacy keymap spam
  • Move keys that express ideas, such as C-n, coherently across multiple modes
  • See the current state of your preferred top-level sequences
  • Introspect modal key bindings, for both package development & configuration

Install User-Keys

(use-package user-keys) ; vanilla

;; using elpaca's with explicit recipe
(use-package user-keys
  :elpaca (user-keys :host github :repo "positron-solutions/user-keys"))

;; straight with explicit recipe
(use-package user-keys
  :straight (user-keys :type git :host github :repo "positron-solutions/user-keys"))

;; or use manual load-path & require, you brave yak shaver

Use User-Keys

;; Show the state of your preferred sequences in the current major
;; mode.  Use this to find out which sequences you might want to bind
;; next.
(user-keys-report-preferred)

;; See a report of all "stupid" bindings and the maps that bind them.
(user-keys-report-stupid)

;; Check for shadows for a common sequence so you can move all of it's bindings
;; around at once.
(user-keys-report-shadows)

;; Open the output buffer and use the transient interface
(user-keys-start)

Contents

Other Packages

Absolutely check out the newer modal packages such as Meow. They don’t have a lot of pre-configured bindings, and this opens up room to do crazy things.

  • Completions frameworks alleviate the need for complex bindings because it’s just faster to complete the command name
  • Transient bindings (transient package) are a good way to present context specific bindings such as for applications like magit
  • Helpful presents bindings in a much better format when looking at keymap variables
  • Which-key is definitely more useful after cleaning out some bindings
  • Tree sitter is making more and more editing commands able to use the structure of text you are working on
  • General provides lots of support for defining bindings more succinctly and differentiating user-defined bindings

Not all of these packages have a clear best choice, so be sure to research Emacs awesome and Reddit etc before adopting a recommendation here.

Motivation

There are too many bindings. Everywhere. It gets in the way of progress. It gets in the way of use. We need tools to take back control and move forward.

  • Empower users to modify & develop new schemes

    Built-in ways to look at bindings are not appropriate for designing new bindings schemes or looking at bindings systematically. There’s not a good built-in way to see sets of bindings across multiple maps or the state of map activation across different buffers, information that is essential for designing and developing bindings schemes (such as new modal schemes).

  • Give the keyboard back to the user

    Having so many bindings in the way or being surprised by shadows from major & minor modes leads to user intimidation and calcification of things that were not intended to become standards. Whether you start with Evil or defaults, the mass proliferation of bad bindings gets in the way and adds risk and complexity to any attempt to go your own way. This package is developed with the belief that the keyboard belongs to the user, and that extra effort should be made to get out of the way.

  • Manage Ad-hoc conventions

    There is no configuration option for certain conventions, such as C-n usually selecting the next item in a list. Because these conventions exist but are not first class, changing the binding for an idea found in multiple keymaps usually requires modifying each keymap. By viewing all shadows in all maps at once, the user can modify and maintain their own conventions with more awareness and ease.

  • Support Tree Sitter Migration

    The timing of development was partly motivated by tree-sitter adoption. Because of tree-sitter, editing commands that are aware of syntax boundaries will become common. The old keymaps based on heuristic editing commands will need to evolve. We need tools that make it easy to open up space and move old conventions.

Long-Term Goal

It is possible that this package may become similar to a no-littering, but for key bindings. Maybe it should be the Magit of key bindings. Maybe it will become an editing interface for a new set of modal bindings. A lot depends on user demand. Be sure to support the project and help steer the direction.

Correctly Communicating About Commands and Sequences

We need to fix something culturally. Other users might say things such as, “The C-x C-f command.” This is wrong. There is no “C-x C-f” command. There is a “C-x f” key sequence that is bound, by default, to the command find-file. This is a binding.

Why you should always prefer command names when communicating:

  • Command names point to source code and can be used as fuel for hacking new commands.
  • Command names are named using frequent concepts from the glossary
  • Command names do not change when users rebind keys. You can communicate about commands no matter what bindings system another user has.
  • Command names tell users more about what package they came from.

Unfortunately there seems to be no mechanism to find out what a key was bound to in the default settings. We can all use commands. We cannot all know what a binding means.

Command names make you and other users more successful. Communicate by saying command names, not key sequences.

The C-c Convention is Terrible

The elisp manual states that only the C-c prefix and only with a single letter should be respected by all major and minor modes. This means the user is expected to bind all of their preferred global commands behind just one prefix sequence.

Don’t define C-c letter as a key in Lisp programs. Sequences consisting of C-c and a letter (either upper or lower case; ASCII or non-ASCII) are reserved for users; they are the only sequences reserved for users, so do not block them.

Meanwhile countless packages add bindings to high-value short key sequences just because the package author felt like it or because they wanted to shadow an ad-hoc convention without knowing if the user reconfigured it.

Being forced to sort through massive lists of bindings with many ad-hoc conventions leads to user intimidation and a calcification of things that never should have been allowed to become standards.

C-c was never a good idea. It is the kind of choice that occurred after far too much spam was protected by being legacy, a legacy that emerged from mixed contributions and exhausting bike shed mailing list threads that reach conclusions like a ouija board.

Please, Package Authors

Commands do not deserve bindings. They are not entitled to them. At the very most, a package author should provide a keymap and then tell the user how to bind that to a prefix. We have absolutely amazing command discovery these days. The user doesn’t need your bindings. Publish a list of commands in your package usage documentation. Put them into a context-specific application interface like transient. Avoid bad key sequences and ad-hoc conventions unless it’s the purpose of your package to shadow the defaults.

What We Should Do

In addition to innovation in modal bindings that seek to sidestep the entire problem altogether…

  • Reserve short sequences for the user

    Meta and control keys, especially on the home row, should be considered sacred real-estate only available to the user. Opening up space will lower the friction for change, speeding up evolution, eventually leading us to discover new things we actually want to bind.

  • Lean on M-x

    In the modern era of awesome M-x completions, there’s almost no use to bind functions beyond a certain level of rarity. It only makes sense to have short sequences bound when no M-x sequences are actually very long.

  • RISC, stateful commands with composition

    In the global bindings, we should try to do more with a smaller set of commands, similar to a RISC style of compressing the possible input values but increasing the meaning of strings of values, which can be composed more easily than long sequences.

  • Use modal interfaces for context-specific commands

    For bindings that are very context-specific, they should be moved into more transient-like interfaces. If you won’t use a command often, it doesn’t make sense to try to use it from memory or to use it non-modally.

  • Remove crufty applications from Emacs

    Many bindings and the applications that they are tied to should just be removed from Emacs altogether and treated as independent packages on the GNU ELPA. This will lower the weight of the manual and other deep integrations, making more room to grow.

  • Put legacy choices into a package

    It needs to be easier to remove default bindings without disrupting legacy users, and that means using a compat package like every other platform out there. Users who want modern Emacs don’t need to care. Users who rely on the old ways should be served by a compat package, not by carrying forward the same old legacy defaults forever.

Contributing

CONTRIBUTING contains instructions on using this repository’s functionality. A DCO and GPL3 license are included with this project.

Check the hacking NOTES document for some help getting started hacking on keymaps and bindings. The keymap data structures themselves are a little bit unwieldy.

Github Sponsors is configured. If you want features & support, organize an international coalition of backers and each donate a comfortable amount, while delegating the authority to pick priorities to those who either demonstrate competence or are willing to pay for what they want.

Acknowledgments

Thanks to Tarsius for publishing the keymap-utils package to MELPA. Some of the built-in functions for exploring keymaps in Emacs were not immediately appropriate for implementing all of the ideas in user-keys. keymap-map-keys seemed to provide a buffet of data types and structures. kmu-map-keymap was very helpful.