Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Helper function to create prefix keys for leader commands #131

Closed
wants to merge 1 commit into from
Closed

Helper function to create prefix keys for leader commands #131

wants to merge 1 commit into from

Conversation

bitspook
Copy link

I am kinda new to Emacs lisp, and I had a hard time figuring out how to add new prefixes to the leader key. (error "Key sequence z s starts with non-prefix key z") didn't help much, but enough that I could find my way to write a helper function.

I think it can be useful for others as well. Please take a look. If you think it can be an acceptable addition to the repo and want me to make some changes, I'll be very happy to do that.

Thank you for your work on this project.

@bitspook bitspook changed the title Add helper function to create prefix keys for leader commands Helper function to create prefix keys for leader commands Dec 16, 2021
@DogLooksGood
Copy link
Collaborator

Hi, thanks for the contribution!

It seems like meow-leader-define-prefix is added for define a prefix, which is useful for which-key and keypad state.
It had been asked in #71. Additionally, users may care about building a nested leader key system. Personally, I'm against this idea and I have a detailed explanation in this PR: #126.

My thought is we just create a keymap, alias it, then have a simple binding in meow. Users may not be aware of this solution, but that is just a problem for documentation.

How do you think?

@bitspook
Copy link
Author

What you suggest makes perfect sense. I'll close my PR and see if I can find a good place in documentation to add this. Thank you for taking time to respond.

I suppose this is how I'd accomplish what you're suggesting:

(defvar spook-git-keymap (make-sparse-keymap)
  "My custom keymap for easily accessing git stuff")
(defalias 'spook-git spook-git-keymap)

(define-key spook-git-keymap (kbd "s") #'magit-status)

(global-set-key (kbd "C-c g") 'spook-git)

(meow-leader-define-key
 '("g" . "C-c g"))

Small problem here is, even though on doing C-c which-key can show +spook-git, but Spc shows meow-dispath-NN

meow-git-help

Is it possible to somehow get a good help text for SPC as well in this case?

@bitspook bitspook closed this Dec 17, 2021
@bitspook
Copy link
Author

I figure I can just do

    (meow-leader-define-key
     '("p" . projectile-command-map))

@DogLooksGood
Copy link
Collaborator

Yes, you can bind a key to a keymap.

If you bind like this

(meow-leader-define-key
 '("g" . "C-c g"))

The command/keymap for g is not determined until it is called.
The remapping by other packages can happen at any time that meow is not aware of.

@bitspook
Copy link
Author

I've found that if I do the following, sometimes the keybindings clash(?) and don't do what I expect/want.

(meow-leader-define-key
 '("g" . "C-c g"))

E.g "C-c g g", assigned to magit-dispatch works if I call it with C-c g g, but if I do SPC g, it don't show up in the listing, and pressing g anyway shows this:

image

So I figured I'll just add keymaps directly. When I add projectile-command-map, it works as expected; however, using my custom keymaps give me an error saying: command-execute: Wrong type argument: commandp, spook-windows-keymap.
As far as I can tell, projectile is defining the keymap just like I am.

    (defvar spook-buffer-keymap (make-sparse-keymap))
    (defalias 'spook-buffer spook-buffer-keymap)

    (global-set-key (kbd "C-c b") spook-buffer-keymap)

    (define-key spook-buffer-keymap (kbd "b") #'ivy-switch-buffer)
    (define-key spook-buffer-keymap (kbd "d") #'kill-current-buffer)
    (define-key spook-buffer-keymap (kbd "s") #'startup--get-buffer-create-scratch)

@bitspook
Copy link
Author

I figured it out. I have to use the alias i.e spook-buffer and not the keymap itself to have it work with meow. I don't understand why, but I am kinda tired of fumbling since morning, so I am gonna let this one pass.

Here's how I am configuring my stuff now.

I've create a macro to help me:

  (defmacro spook-defkeymap (name prefix &rest bindings)
    "Create a new NAME-keymap bound to PREFIX, with BINDINGS.

  Usage:
    (spook-defkeymap \"spook-git\" \"C-c g\"
      '(\"s\" . magit-status))
  "
    (let* ((keymap-name (intern (concat name "-keymap")))
           (keymap-alias (intern name))
           (keymap-bindings (mapcar
                             (lambda (binding)
                               (let ((binding (eval binding)))
                                 `(define-key ,keymap-name (kbd ,(car binding)) #',(cdr binding))))
                             bindings)))
      `(progn
         (defvar ,keymap-name (make-sparse-keymap))
         (defalias ',keymap-alias ,keymap-name)
         (global-set-key (kbd ,prefix) ',keymap-alias)
         ,@keymap-bindings)))

I define my keymap like this:

    (spook-defkeymap
     "spook-buffers" "C-c b"
     '("b" . ivy-switch-buffer)
     '("d" . kill-current-buffer))

Then assign them to meow-leader-key

    (meow-leader-define-key
     '("p" . projectile-command-map)
     '("w" . spook-windows)
     '("b" . spook-buffers)
     '("g" . spook-git))

I get nice help in popups:
image

and keys don't clash either.

Sorry for the spam, I thought I should put it out here in case someone else might stumble here.

@DogLooksGood
Copy link
Collaborator

DogLooksGood commented Dec 17, 2021

Firstly, g is for C-M-, since there's no C-g in the key seq, so using g here is safe. Keypad has a "fallback to literal key" feature. That is, you can use SPC c a for C-c a, if there's no keybinding on C-c C-a. Since g is always available for C-M-, so this fallback behavior will not work in this case.

I'm just typing, and found you figured it out. :)


The way you just shown is what I considered the best way. Building your keymap in your own way, not bound to meow, looks pretty.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants