general.el icon indicating copy to clipboard operation
general.el copied to clipboard

How to define prefix keys for both case when evil-mode is enabled and disabled?

Open casouri opened this issue 6 years ago • 7 comments

What I want to achieve:

  • when evil-mode is disabled: S-SPC is prefix key
  • when evil-mode is enabled: SPC is prefix key for normal and visual state, S-SPC is prefix key for insert state.

I have tried

   (general-create-definer default-leader
    :states '(normal visual insert emacs jpnb)
    :keymaps 'override
    :prefix "SPC"
    :non-normal-prefix "S-SPC")

and

   (general-create-definer default-leader
    :states '(normal visual insert emacs jpnb)
    :keymaps 'override
    :prefix "SPC"
    :global-prefix "S-SPC")

What troubles me is that, when evil-mode is disabled, S-SPC has no effect.

casouri avatar Aug 09 '18 16:08 casouri

You're only defining keys in evil keymaps in your example. You could make non-evil keybindings with something like (general-define-key :prefix "prefix" "key" 'def ...). You could create a wrapper that calls your custom definer and one that has :prefix "S-SPC".

noctuid avatar Aug 09 '18 22:08 noctuid

Thanks. For anyone with the same question:

(general-create-definer moon--default-leader
 :states '(normal visual insert emacs jpnb)
 :keymaps 'override
 :prefix "SPC")

(general-create-definer moon-global-leader
  :prefix "S-SPC"
  :keymaps 'override)
  
(defmacro moon-default-leader (&rest args)
  "Define for both default leader and global leader."
  (declare (indent defun))
  `(progn
     (moon--default-leader
      ,@args)
     (moon-global-leader
      ,@args)))

I replaced the original definer with a macro, the definer is renamed from moon-default-leader to moon--default-leader.

casouri avatar Aug 10 '18 02:08 casouri

The same effect can be achieved without defining a macro:

(general-create-definer moon-global-leader
  :prefix "S-SPC"
  :keymaps 'override)
(general-def '(normal visual) "SPC" (general-simulate-key "S-SPC"))

But this and your code snippet both makes S-SPC also the leader key in normal and visual state, which doesn't meet your needs in the description.

AmaiKinono avatar Apr 03 '19 18:04 AmaiKinono

That's good to know. Thanks.

casouri avatar Apr 03 '19 18:04 casouri

I don't like the solution of using general-simulate-key for this. It should be avoided when it isn't necessary (and it isn't necessary here). To make this a little easier, I could either provide a helper to combine multiple definers or I could allow something like this:

(general-create-definer my-leader
  ;; can include nil to also define in just `general-override-mode-map'
  :states '(normal visual insert emacs nil)
  :keymaps 'override
  :global-prefix "S-SPC"
  :prefix "SPC")

This would complicate the code a bit more since I'd have to add some check to determine whether a keymap is an evil state keymap (and I don't think evil stores the defined states anywhere, so I'd have to do something like assume that evil-<name>-state-map is a state keymap).

noctuid avatar Apr 20 '19 16:04 noctuid

I would say a helper is simple and reliable, and can meet a variety of user needs that can or cannot be thought of now, so I prefer this.

AmaiKinono avatar Apr 20 '19 16:04 AmaiKinono

@noctuid Hi. I think it's better to show you the whole scheme used by me, maybe it can be a reference.

(defconst toki-leader-key "C-j")
(defconst toki-normal-state-leader-key "SPC")
(defconst toki-app-key "a")
(defconst toki-window-key "w")
(defconst toki-emacs-key "e")
(defconst toki-search-key "s")
(defconst toki-code-key "d")
(defconst toki-file-key "f")
(defconst toki-help-key "h")
(defconst toki-navigate-key "n")
(defconst toki-ui-key "u")
(defconst toki-buffer-key "j")
(defconst toki-manage-key "m")
(defconst toki-text-key "k")

(use-package general
  :config
  (general-create-definer toki-leader-def
    :prefix toki-leader-key
    :keymaps 'override)

  (general-def 'normal
    :start-maps t
    :keymaps 'override
    toki-normal-state-leader-key (eval `(general-simulate-keys ,toki-leader-key)))

  (general-create-definer toki-app-def
    :prefix (concat toki-leader-key " " toki-app-key)
    :keymaps 'override)

  (general-create-definer toki-window-def
    :prefix (concat toki-leader-key " " toki-window-key)
    :keymaps 'override)

  (general-create-definer toki-search-def
    :prefix (concat toki-leader-key " " toki-search-key)
    :keymaps 'override)

  (general-create-definer toki-emacs-def
    :prefix (concat toki-leader-key " " toki-emacs-key)
    :keymaps 'override)

  (general-create-definer toki-code-def
    :prefix (concat toki-leader-key " " toki-code-key)
    :keymaps 'override)

  (general-create-definer toki-file-def
    :prefix (concat toki-leader-key " " toki-file-key)
    :keymaps 'override)

  (general-create-definer toki-help-def
    :prefix (concat toki-leader-key " " toki-help-key)
    :keymaps 'override)

  (general-create-definer toki-navigate-def
    :prefix (concat toki-leader-key " " toki-navigate-key)
    :keymaps 'override)

  (general-create-definer toki-ui-def
    :prefix (concat toki-leader-key " " toki-ui-key)
    :keymaps 'override)

  (general-create-definer toki-buffer-def
    :prefix (concat toki-leader-key " " toki-buffer-key)
    :keymaps 'override)

  (general-create-definer toki-manage-def
    :prefix (concat toki-leader-key " " toki-manage-key)
    :keymaps 'override)

  (general-create-definer toki-text-def
    :prefix (concat toki-leader-key " " toki-text-key)
    :keymaps 'override)

  (toki-leader-def
    :start-maps t
    toki-window-key '(:wk "window")
    toki-emacs-key '(:wk "emacs")
    toki-search-key '(:wk "search-and-replace")
    toki-code-key '(:wk "code")
    toki-file-key '(:wk "file")
    toki-help-key '(:wk "help")
    toki-navigate-key '(:wk "navigate")
    toki-ui-key '(:wk "UI")
    toki-buffer-key '(:wk "buffer")
    toki-manage-key '(:wk "manage")
    toki-text-key '(:wk "text")))

So basically C-j is the start menu, and there are many sub menus under it. Specific keybindings are set in each modules in my config. general-simulate-keys is used since it seems to be the simplest way. The improvement should make this easier, not harder (e.g. having to create 10+ more definers).

AmaiKinono avatar Apr 28 '19 10:04 AmaiKinono