Closed milanglacier closed 2 years ago
Hi ;)
You can just learn from how citre-peek
defines it. citre-peek
defines keybind like this (just open citre-peek.el
and search the code!):
(define-key map (kbd "M-n") 'citre-peek-next-line)
So you could do:
(define-key citre-peek-keymap (kbd "M-n") 'citre-peek-next-line)
See the documentation of define-key
and kbd
to learn more (C-h k
, or M-x describe-function
).
I am using evil with doom, so it would be better it is evil-compatible.
I don't use doom and haven't been using evil for a long time, so I may not have a working solution for this. Keybindings defined in a minor mode can be overriden by motion state keymap (which also applies to normal state), and the simplest way is to just avoid motion state keybindings in citre-peek-keymap
. But doing that for a all minor modes you use can be time consuming.
My own solution is to let the minor mode keymap override motion state keymap. It's easy:
(evil-make-overriding-map citre-peek-keymap 'motion)
Then I add back h/j/k/l
, :
, G
and gg
so basic motions could still work. You can find my solution here, see the function toki/add-minimal-evil-keybinds-to-local-map
.
Thank you for you help! Though followed your instruction, I still find that for some reason, my following config does not work.
(use-package! citre
:defer t
:init
(require 'citre-config)
(map! ;; this is the doom macro to make defining modal keymap more easily
:n "C-]" 'citre-jump
:n "C-w ]" 'citre-peek
:n "C-t" 'citre-jump-back)
(evil-make-overriding-map citre-peek-keymap 'motion)
(evil-make-overriding-map citre-peek-keymap 'normal)
;; the above three keymaps work, but the following two keymaps doesn't work
(define-key citre-peek-map (kbd "]t") 'citre-peek-next-definition)
(define-key citre-peek-map (kbd "[t") 'citre-peek-prev-definition)
;; or define keymaps using evil-define-keys also not work
(evil-define-key 'normal citre-peek-keymap
(kbd "]t") #'citre-peek-next-definition
(kbd "[t") #'citre-peek-prev-definition))
First, a piece of advice: when configuring Emacs, it's better to make sure a small snippet of code works, then put it into your init file, then working on the next small snippet of code, rather than just write things in the init file and hoping it to work. C-x C-e
(eval-last-sexp
) is a good helper.
but the following two keymaps doesn't work
But how? You got an error? The keybinding doesn't do anything? Or it triggers another command?
My guess is you got an error saying "]" is not a prefix key. This is expected as normally pressing "]" should insert it, so any keybinding starting with "]" could not work. To make it work, let "]" do nothing in citre-peek-keymap
so it could be used as a prefix key:
(define-key citre-peek-map (kbd "]") nil)
(define-key citre-peek-map (kbd "]t") 'citre-peek-next-definition)
But this is undesired. When citre-peek-mode
is enabled, it makes it impossible to insert "[".
or define keymaps using
evil-define-keys
also not work
Sorry but I don't know about this function. And again, how does it "not work"?
I tried and your code actually works for me:
(evil-define-key 'normal citre-peek-keymap
(kbd "]t") #'citre-peek-next-definition
(kbd "[t") #'citre-peek-prev-definition)
The problem may be you called it before citre-peek
is loaded, so citre-peek-keymap
is still undefined. evil-define-key
doesn't signal an error in this case. Try put it in the :config
block instead.
Hi! The thing is: nothing happens, what happens is completely the same as what happens if I didn't define those keymaps:
In both case: evil-define-key
and define-key
, when I press ]t
, the thing happening is the same: the minibuffer has output: no more matches
.
I was thinking about this is because ]
is defined by evil in normal state, then ]t
doesn't override evil setting.
describe-key ]t
shows that it is defined by evil:
] t runs the command hl-todo-next (found in evil-motion-state-map), which is an
interactive compiled Lisp function in ‘hl-todo.el’.
It is bound to ] t.
(hl-todo-next ARG)
Jump to the next TODO or similar keyword.
The prefix argument ARG specifies how many keywords to move.
A negative argument means move backward that many keywords.
then I am wondering, why my override settings doesn't work?
But I also defines
I think this may not be a citre
specific question but rather than a evil specific question, I think may be I should search for evil's github repo‘s documentation. But since I am new to elisp, I would be very appreciated if you could provide me some idea on what's happening here.
I tried and your code actually works for me:
(evil-define-key 'normal citre-peek-keymap (kbd "]t") #'citre-peek-next-definition (kbd "[t") #'citre-peek-prev-definition)
The problem may be you called it before
citre-peek
is loaded, socitre-peek-keymap
is still undefined.evil-define-key
doesn't signal an error in this case. Try put it in the:config
block instead.
Thank you! I havn't see this thread before I make my reply as above! I will give it a try!
And this works for me. So I just need to put it in the config part.
May I ask about a question? What config options should I set before the package being loaded, like I set C-]
as citre-jump
at the init part, i.e. before the package is loaded and it works but I need to define keymaps of citre-peek-keymap
after the package is loaded, how do I know when to set the options?
It's not easy to answer :D
You bind citre-jump
in global-map
, and it is part of Emacs, not Citre. So this works before Citre is loaded.
But you bind peek related commands in citre-peek-map
, which is defined by Citre, so it could not work before Citre is loaded.
If you need any value/function... defined in the package, you should put it in the :config
block. Normally if you use them before they are defined, Emacs will signal an error, but evil-define-key
is a macro, it could choose to evaluate its arguments or not, so it may not produce the error.
A package could be "lazy loaded". That is, it's loaded after you use any of the specified functions in it. Package developers usually specify interactive commands as these functions, so the package is only loaded after you call the commands.
:defer t
and several other keywords enables lazy loading. So if that's the case, make sure you bind these commands in the :init
block. You need to think a bit here: You may call citre-peek
before Citre is loaded, so you bind it in :init
block; But you only use commands like citre-peek-next-definition
after you call citre-peek
, and by then the package is already loaded, so you could bind it in the :config
block.
Normally, to reduce the impact on Emacs startup time, we put only necessary code ino the :init
block, and the rest into the :config
block.
thanks for your help. After some tweaking, I find that where the keymaps are defined (at :config or :init block) doesn’t matter. What matters is I need to firstly enter the insert mode after I opens the citre-peek-window(only once) After that all the keymaps I defined in citre-peek-keymap will work. I think the reason might be evil-define-key
will lazy load the keymaps you defined. And only after entering insert mode will evil-define-key
knows that you have entering citre-peek-mode
and then the keymaps you defined will be activated.
I am new to elisp and I don’t know this behavior is designed as expected or not. But I’m fine with just entering insert mode once, since it doesn’t take me much more key strokes.
I solve the issue of evil specific citre-mode-map not activated unless a state transition by the following config
(add-hook 'citre-mode-hook #'evil-normalize-keymaps)
(add-hook 'citre-peek--mode-hook #'evil-normalize-keymaps)
see the rationale at https://github.com/emacs-evil/evil/issues/301#issuecomment-591569346
Hi! I am new to elisp and not quiet familiar it, how can I change the keymaps defined in
citre-peek-keymap
without directly changing the source code? If I directly call(define-key blablabla)
in my config file, then such keymaps would have effects globally. Besides, I am using evil with doom, so it would be better it is evil-compatible. Thanks for your correspondence!