-
Notifications
You must be signed in to change notification settings - Fork 44
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
add which-key integration #26
Comments
- Add support for adding which-key descriptions for keys (addresses #26) - Add support for binding a key to an "autoloaded" keymap - Add support for specifying a predicate for a single definition - Simplify general-define-key by consolidating logic for checking which maps to use (when :non-normal-prefix and/or :global prefix are used) and by moving things out of general--delay into a separate function New keywords for an "extended definition" can be added by the user.
I added initial support for these "extended definitions" (no documentation in the readme yet); they are user extensible. Your example could be written like this:
"Autoloading" keymaps like in bind-key is also implemented. You can specify For other bindings, Let me know if you have any problems. Feel free to make another issue if you have any suggestions for other keywords.
I could just have |
Amazing work! I'll give it a shot.
Yeah I'm ok with nil. |
I'm gonna give this a shot now. By the way, I imagine and hope that this will also be awesome for handling the case of multiple prefixes, similar to what we're talking about in #28. That is, I previously had this very annoying configuration: (which-key-add-key-based-replacements
"SPC b" "buffer"
"SPC b m" "move"
"SPC c" "flycheck"
"SPC e" "emacs"
"SPC f" "frame"
"SPC g" "git"
"SPC g g" "gist"
"SPC k" "kill"
"SPC k f" "frame"
"SPC k w" "window"
"SPC h" "helm"
"SPC o" "open"
"SPC o a" "all"
"SPC p" "projectile"
"SPC t" "toggle"
"SPC t r" "rainbow"
"SPC w" "window"
"SPC w s" "split"
) but naturally it only applied to my |
Ah I think I misunderstood. So it seems that (my-map
;; kill things
"k" '(:ignore t :which-key "kill")
"k e" 'save-buffers-kill-terminal
"k b" 'my-kill-this-buffer
"k f" 'delete-frame
"k o f" 'delete-other-frames
"k o w" 'delete-other-windows
;; windows
"w" '(:ignore t :which-key "window")
"w f" 'my-pop-to-frame
"w s v" 'evil-window-vsplit
"w s h" 'evil-window-split
"w s p" 'my-split-with-previous-buffer
;; frames
"w" '(:ignore t :which-key "frame")
"f o" 'other-frame
"f f" 'toggle-frame-fullscreen
;; buffers
"w" '(:ignore t :which-key "buffer")
"b b" 'bury-buffer
"b o" 'my-switch-to-previous-buffer
"b s" 'my-force-save) I'll split it out into the separate ones. Besides it's what I'd do once we get ad-hoc prefixes with |
Yeah I guess I'll try this once we get ad-hoc prefixes cause otherwise I'll only be able to apply it to one prefix like But also I'd be interested in the ability to specify arbitrary which-keys like I showed in my most recent example. Because for example consider this part: "w" '(:ignore t :which-key "window")
"w f" 'my-pop-to-frame
"w s" '(:ignore t :which-key "split")
"w s v" 'evil-window-vsplit
"w s h" 'evil-window-split
"w s p" 'my-split-with-previous-buffer See how I was able to label the new level of binds (for |
Keys need to be given as "SPC ..." not " ...". Giving the key in format used for bindings will work for some keys (e.g. "C-c") but not for space. Addresses #26.
Yes, they should be added for every prefix.
Your definition looks right to me. Previously I was giving the keys to the which-key functions as they would be given to |
I imagine |
Nevermind looks like you had that before. Not sure why that was happening. |
Yeah I think it was because of the variable being declared before and outside of |
I ran into it myself a while back. |
Yeah it looks like now the function arguments aren't available with the new placement. Thanks, I'll look into/fix it. It shouldn't be a problem if which-key is already loaded though. |
Sorry about that. I don't know why I was thinking that |
No worries! 👍 💃 |
Personally I always use |
I can confirm this all seems to be working perfectly! Check it out, it's pretty awesome!! 🎉 I'm gonna clean this up but I put it this way to show the various things now possible. (my-map
;; kill things
"k" '(:ignore t :which-key "kill")
"k e" 'save-buffers-kill-terminal
"k b" 'my-kill-this-buffer
"k f" 'delete-frame
"k o f" 'delete-other-frames
"k o w" 'delete-other-windows
;; frames
"f" '(:ignore t :which-key "frame")
"f o" 'other-frame
"f f" 'toggle-frame-fullscreen
;; buffers
"b" '(:ignore t :which-key "buffer")
"b b" 'bury-buffer
"b o" 'my-switch-to-previous-buffer
"b s" 'my-force-save)
(my-map :infix "w"
;; ;; windows
"" '(:ignore t :which-key "window")
"f" 'my-pop-to-frame
"s" '(:ignore t :which-key "split")
"s v" 'evil-window-vsplit
"s h" 'evil-window-split
"s p" 'my-split-with-previous-buffer) |
Also this works as expected: "b b" '(:command bury-buffer :which-key "bury") |
Also what you said, putting the command as the first element: "b b" '(bury-buffer :which-key "bury") |
I think I found a problem. When I use (use-package projectile
:demand t
:general
("C-M-/" 'helm-projectile-ag)
(my-map
"p" '(:keymap projectile-command-map)
"e e" 'my-edit-inits)
) So that gives that error, but if I eval the |
It expands to this: (progn
(progn
(require 'package)
(use-package-ensure-elpa 'projectile))
(unless
(fboundp 'helm-projectile-ag)
(autoload #'helm-projectile-ag "projectile" nil t))
(unless
(fboundp
'(:keymap projectile-command-map))
(autoload
#'(:keymap projectile-command-map)
"projectile" nil t))
(unless
(fboundp 'my-edit-inits)
(autoload #'my-edit-inits "projectile" nil t))
(if
(not
(require 'projectile nil 'noerror))
(ignore
(message
(format "Cannot load %s" 'projectile))))
(ignore
(general-define-key "C-M-/" 'helm-projectile-ag)
(my-map "p"
'(:keymap projectile-command-map)
"e e" 'my-edit-inits))) |
Seems like a problem with the autoloads. |
I remember you had said that in (progn
(progn
(require 'package)
(use-package-ensure-elpa 'projectile))
(unless
(fboundp 'helm-projectile-ag)
(autoload #'helm-projectile-ag "projectile" nil t))
(unless
(fboundp
'(:keymap projectile-command-map :package projectile))
(autoload
#'(:keymap projectile-command-map :package projectile)
"projectile" nil t))
(unless
(fboundp 'my-edit-inits)
(autoload #'my-edit-inits "projectile" nil t))
(if
(not
(require 'projectile nil 'noerror))
(ignore
(message
(format "Cannot load %s" 'projectile))))
(ignore
(general-define-key "C-M-/" 'helm-projectile-ag)
(my-map "p"
'(:keymap projectile-command-map :package projectile)
"e e" 'my-edit-inits))) |
Ohhh okay it seems like it's simply the case that you haven't implemented |
Yeah I just hadn't changed the handler yet. Try it now.
The quoting isn't too hard to read in this situation, but maybe I'll switch to using closures in the future. I probably should be using lexical binding anyway since it's faster (I don't know if it would matter at all for this package though). |
Seems to work perfectly well! Feel free to close this unless you have more prepared! |
Hey I think I might have found one last thing. It seems like when I use Basically I had a bind like this: (use-package projectile
:general
("C-M-/" 'helm-projectile-ag)
(my-map
"p" '(:keymap projectile-command-map
:package projectile
:which-key "projectile"))) So I would go to press So I decided to (lambda nil
(interactive)
(unless
(or (featurep (quote projectile))
(require (quote projectile) nil t))
(error (concat "Failed to load package: " (symbol-name (quote projectile)))))
(unless (and (boundp (quote projectile-command-map))
(keymapp (symbol-value (quote projectile-command-map))))
(error (format "A keymap called %s is not defined in the %s package"
(quote projectile-command-map)
(quote projectile))))
(let ((keys (this-command-keys)))
(general-define-key
:states (quote normal)
:keymaps (quote global)
keys projectile-command-map)
(setq unread-command-events (listify-key-sequence keys))) |
I should've done this earlier but I ruled out |
This is another key formatting bug ( |
So when Thanks for the prompt fix, I'll report back! |
I accidentally committed/pushed some unfinished changes and just force pushed again (just a notice).
Yes, it's comparable to binding a key to a keyboard macro. |
Ah okay, no problem! Thanks again!! |
I actually still may have broke something. You may want to put off testing until the next commit. |
No worries! |
Okay, things should now be working. I also added documentation. I'll close this after fixing the other problem I mentioned unless you have any other issues. |
Thanks a lot for all the suggestions and bug reports. Hopefully everything is working as expected now. One noteworthy change is that |
Agreed on the name change for |
So if I have something like this: (use-package helm-projectile
:diminish projectile-mode
:general
;; FIXME
;; https://github.com/noctuid/general.el/issues/26
(my-map
"p" '(:keymap projectile-command-map
:package helm-projectile
:which-key "projectile"))) When I press What does seem to be fixed is that it no longer cycles infinitely, i.e. the binding is correctly established and I can enter it, it's just that when I first trigger it it doesn't re-simulate the complete sequence just the prefix. Also it's not clobbering my |
I was going to try doing EDebug on the intermediary function to see what's happening but it's a lambda and I'm not sure how or if I can EDebug a lambda. Perhaps I can EDebug a key trigger or something? Not sure. |
Actually I guess I could put that in scratch, give it a name, re-attach it to the bind, then debug it, duh. |
Heh, yeah I'm not sure how to go about debugging this correctly. I was doing it but then |
A breakpoint didn't work because it keeps stopping at the first line which ends up replacing/clobbering the keys that it'll read when I press the key to continue until the breakpoint. I ended up just rigging up messages: (defun my-intermediary-func ()
(interactive)
(unless (or (featurep (quote helm-projectile))
(require (quote helm-projectile) nil t))
(error (concat "Failed to load package: " (symbol-name (quote helm-projectile)))))
(unless (and (boundp (quote projectile-command-map))
(keymapp (symbol-value (quote projectile-command-map))))
(error (format "A keymap called %s is not defined in the %s package"
(quote projectile-command-map)
(quote helm-projectile))))
(let ((keys (this-command-keys))
(general-implicit-kbd nil))
(message "keys: %s" keys)
(general-define-key
:states (quote normal)
:keymaps (quote global)
keys projectile-command-map)
(setq unread-command-events (listify-key-sequence keys))
(message "seq: %s" unread-command-events))) Then I replace the bind
So it seems correct to me, 32 is space and 112 is p, and yet right after this I have |
I'm still a bit unsure as to why the bind is created with |
I have no idea why this happens. It looks like this bug also happens with
|
Woah I just noticed something, I hope it helps. So I launch emacs, then I press
So it seems as if somehow it did re-apply |
I GOT IT! |
Yes, it will still work. Another more annoying problems is that which-key will show the bindings under |
Check it. I figured I'd see how which-key replays key sequences, and the way they do it works perfectly! (defun my-intermediary-func ()
(interactive)
(unless (or (featurep (quote helm-projectile))
(require (quote helm-projectile) nil t))
(error (concat "Failed to load package: " (symbol-name (quote helm-projectile)))))
(unless (and (boundp (quote projectile-command-map))
(keymapp (symbol-value (quote projectile-command-map))))
(error (format "A keymap called %s is not defined in the %s package"
(quote projectile-command-map)
(quote helm-projectile))))
(let ((keys (this-command-keys))
(general-implicit-kbd nil))
(message "keys: %s" keys)
(general-define-key
:states (quote normal)
:keymaps (quote global)
keys projectile-command-map)
(message "events: %s" unread-command-events)
(which-key-reload-key-sequence (listify-key-sequence keys))
(message "seq: %s" unread-command-events))) Output:
I did notice the |
Can you rephrase or elaborate? Nevermind I saw #29. |
Continuing our discussion from #22.
I just started creating spacemacs-like bindings where I have a prefix like
SPC
and you can drill down from there, paired with which-key, and it's pretty cool but it kind of becomes a pain to have to call a different function to label the prefix keys that arise from this setup. It'd be great if we could have a way to label them via general.el, perhaps something like was discussed in #22, a more flexible form to which the current form is expanded:So the first is a prefix, which I guess it can either detect from the
:prefix t
(perhaps you can devise another way if you prefer).:which-key
can be applied to any binding though.Note that the second style, the current style, would be rewritten to the third style, i.e.
'(:command some-cmd)
, so that you can then handle them all uniformly. Or perhaps that's not necessary, just a suggestion.This kind of provides some form of type hinting too considering the issue you were running into earlier, for example we can introduce
:keymap helm-command-map
to bind a key to a keymap and so it knows that it has to wait for that keymap to load before actually creating the bind, or perhaps generating an autoload for it or whatever, and we can also use:package
so we can specify to which package that keymap belongs.This would be more flexible and would allow for future functionality, all while not bothering current users or the general simple case.
This is slightly unrelated but I was wondering also that it feels like binding to
nil
to unbind doesn't seem very intuitive. bind-key hasunbind-key
for example. Rather than introducing yet another function though perhaps it would be cool if we could "bind" to:unbind
or:unset
or something, although that's such a minor cosmetic thing that's probably not worth the effort, but just something I was thinking about.The text was updated successfully, but these errors were encountered: