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

Using general.el with meow #546

Open
noctuid opened this issue Mar 25, 2023 · 4 comments
Open

Using general.el with meow #546

noctuid opened this issue Mar 25, 2023 · 4 comments
Labels

Comments

@noctuid
Copy link
Owner

noctuid commented Mar 25, 2023

          Hi, coming back after a couple of weekends of exploration. The author of meow directed me to this particular thread and message : https://github.com/meow-edit/meow/pull/126#issuecomment-992004368. 

I have been doing some testing using a config like this:

(use-package general
  :straight t
  :config
  (general-override-mode 1)
  (general-auto-unbind-keys)

  ;; We need the leader-key commands to replace the limited menus from meow-keypad
  (general-create-definer +m/map-leader
    :keymaps '(meow-motion-state-keymap meow-normal-state-keymap)
    :prefix "SPC")

  ;; Create a "mode-leader"
  (general-create-definer +m/map-modeleader
    :prefix "SPC SPC"
    "" '(:ignore t :wk "modebindings")))

My mode-specific mappings end up covering all state, including the insert state.

I have tried to make a function which will take a mode and a list of keybindings as inputs, and will then add a hook to the said mode which only maps to meow-normal-state-keymap. This also fails miserably. However, in this case, I think it might be my lack of elisp skills... Any tips or comments will be very helpful !

Originally posted by @ChauhanT in #497 (comment)

@noctuid
Copy link
Owner Author

noctuid commented Mar 25, 2023

@ChauhanT I've made a separate issue.

I don't fully understand what you want. Could you give me an example keybinding form that you would like to be able to use and tell me what it should do?

Since meow doesn't support this directly, I don't think there are any perfect solutions to do what you want. Using a hook like you describe won't work well since it will clobber keybindings in a global keymap. You'd have to update the keybindings every time you switched buffers as well.

Depending on specifically what you want to do, there might be some workable solution.

@ChauhanT
Copy link

Hi, sorry, should have started a separate thread for this.

An example: in org-mode I bind things like increasing priority or changing the TODO keyword to mode-specific menus. I use evil in my current distro emacs-groundup, and I implement such bindings so that they only appear in the required mode (org-mode in this case). These are implemented (assuming the hydras) as:

(+/UIX/map-to-modeleader
  :states '(normal visual motion)
  :keymaps 'org-mode-map

  ;; Priorities
  "p" '(+/UIX/hydra-org-priority/body :wk "priority")

  ;; TODOs
  "t" '(+/UIX/hydra-org-todo/body :wk "todo"))

I am looking for something similar as I try to replace evil with meow. In my meow variant, the relevant config could be summed up in:

(use-package meow
  :straight t
  :config
  (+f/meow-setup)
  (meow-global-mode 1)
  (meow-setup-indicator))

(use-package general
  :straight t
  :config
  (general-override-mode 1)
  (general-auto-unbind-keys)

  ;; We only need the leader-key commands to replace meow-keypad
  (general-create-definer +m/map-leader
    :keymaps '(meow-motion-state-keymap meow-normal-state-keymap)
    :prefix +v/leader
    "" '(:ignore t :wk "leader"))

  (general-create-definer +m/map-modeleader
    :prefix "SPC SPC"
    "" '(:ignore t :wk "modebindings"))

So, in org-mode I am trying to implement a function like (there are similar variants I am trying with add-hook etc.):

(defun +f/create-modal-keybindings (mode keybindings)
  "Create modal keybindings in the meow-normal-state-keymap for major mode MODE."
  (dolist (binding keybindings)
    (let ((key (car binding))
          (function (cdr binding)))
      (define-key meow-normal-state-keymap key function)))
  t)

The idea is to be able to do mode-local keybindings with:

(+f/create-modal-keybindings 'org-mode  '(("SPC SPC p" . #'+h/org-priority/body)))

I also tried the C-c m trick that the meow maintainer referred me to - but it also ends up mapping the insert mode (I think because of the general-auto-unbind-keys). Hopefully this makes sense. I know it's confusing...

@noctuid
Copy link
Owner Author

noctuid commented Mar 26, 2023

There are a couple of approaches you could take, though none of them are great.

  1. Take the approach suggested in the comment you linked and bind keys to simulate others globally. For example "SPC" could simulate "C-c SPC" in normal/motion or "C-c a" in insert (pick some keys you don't use), and you could have a wrapper to bind to specific keys in org-mode-map (or whatever the mode keymap given is) depending on the prefix/state.
  2. If this is just for prefix keys, you can use mode hooks and local keymaps.
(defvar my-local-normal-spc-prefix-map nil)
(make-variable-buffer-local 'my-local-normal-spc-prefix-map)
(defmacro my-local-normal-spc-bind (&rest args)
  `(progn (unless (and my-local-normal-spc-prefix-map
                       (local-variable-p 'my-local-normal-spc-prefix-map))
            (setq my-local-normal-spc-prefix-map (make-sparse-keymap)))
          (general-def my-local-normal-spc-prefix-map ,@args)))

;; assuming you've aliased normal to `meow-normal-state-keymap'
;; using a menu-item to get the local version of the keymap at lookup time
(general-def
  'normal
  "SPC"
  '(menu-item
    ""
    nil
    :filter (lambda (&optional _)
              my-local-normal-spc-prefix-map)))
;; or just
(general-def 'normal "SPC" (general-predicate-dispatch my-local-normal-spc-prefix-map))

;; create a wrapper to use hooks to make keybindings
(add-hook 'org-mode-hook
          (lambda (&rest _)
            (my-local-normal-spc-bind "a" #'a)))

This is just a basic example. I'll leave it up to you to create wrappers/clean things up if you like the approach. You could, for example, create a wrapper to automate the setup process (create keymaps for all meow states and bind keys to them), e.g. (my-create-mode-definer my-spc-bind "SPC") then (my-spc-bind 'normal 'org-mode-hook ...).

@ChauhanT
Copy link

I really appreciate your taking the time/interest/pains to give such a detailed response. I will attempt implementing this during the coming weekend, and I will update this thread with my results. Thank you once again !

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

No branches or pull requests

2 participants