如何给use-package增加evil-bind关键词

如题,我想要给 use-package 增加 evil-bind 关键词,这样就不用把按键的定义放到 :config 里,结构也能更清晰一些,目前参考 :bind 的定义添加一下函数

(defalias 'use-package-normalize/:evil-bind 'use-package-normalize-binder)

(defun use-package-handler/:evil-bind
    (name keyword arg rest state &optional evil-bind-macro)
  (let ((commands (remq nil (mapcar #'(lambda (arg)
                                        (if (listp arg)
                                            (cdr arg)
                                          nil)) arg))))
    (use-package-concat
     (use-package-process-keywords name
       (use-package-sort-keywords
        (use-package-plist-maybe-put rest :defer t))
       (use-package-plist-append state :commands commands))
     `((ignore
        ,(macroexpand
          `(,(if evil-bind-macro evil-bind-macro 'evil-define-key)
            :package ,name ,@arg)))))))

(add-to-list 'use-package-keywords :evil-bind t)

一个简单的配置

(use-package yapfify
  :ensure t
  :defer t
  :evil-bind
  (normal python-mode-map
          (kbd "<f6>") 'yapfify-buffer))

虽然没有报错,但也没有生效

ps:我找到两个已有的例子,但感觉有些复杂了

  1. https://github.com/chrisbarrett/spacemacs-layers/blob/486730d05649b7fdc3af86674f92e514a68ee806/cb-use-package-extensions.el
  2. https://github.com/torgeir/.emacs.d/blob/26fd2896d4edcc95f8896db37379b6b688f8cf8b/site-lisp/evil-use-package/evil-use-package.el

第一个报错,第二个虽然可以,但觉得不太"正宗"

其实你可以给 use-package 添加任何关键字:

(use-package yapfify
  :whatever
  (do-something)
  )

但是如果没有响应的实现,:whatever 这个关键字是会被过滤掉的。这里有些相关的讨论:给 use-package 添加新的(没实际作用的)关键词

官方文档是有教怎么实现的:GitHub - jwiegley/use-package: A use-package declaration for simplifying your .emacs

第一个例子看起来像是实现了,但是为什么报错,报什么错,你都没有讲清楚。

use-package 的代码的确非常难懂,我一直没法看明白,估计是不熟悉「宏」的缘故。

我没用过 Evil,但是我看了下 evil-define-key 的文档,其中有例子:

(evil-define-key ’normal foo-map
  "a" ’bar
  "b" ’foo)

再结合你想要的 :evil-bind

(use-package yapfify
  :ensure t
  :defer t
  :evil-bind
  (normal python-mode-map
          (kbd "<f6>") 'yapfify-buffer))

显然你只需要把 :evil-bind 后面的参数直接传给 evil-define-key 就好了,所以你用不着 use-package-normalize-binder(它是为了迎合 bind-keys )。


下面是我的尝试:

(add-to-list 'use-package-keywords :evil-bind t)
(defalias 'use-package-normalize/:evil-bind 'use-package-normalize-forms)
(defun use-package-handler/:evil-bind (name keyword arg rest state)
  (let* ((body (use-package-process-keywords name rest state))
         (name-symbol (use-package-as-symbol name))
         (config-body
          (use-package-concat
           (use-package-hook-injector (symbol-name name-symbol)
                                      :config `((evil-define-key ,@(car arg))))
           body
           (list t))))
    config-body))

会得到:

(use-package yapfify
  :ensure t
  :defer t
  :evil-bind
  (normal python-mode-map
          (kbd "<f6>") 'yapfify-buffer)
  :config (message "configuring `yapfify'..."))

=>

(progn
  (use-package-ensure-elpa 'yapfify 't 'nil :ensure)
  (eval-after-load 'yapfify
    '(progn
       (message "configuring `yapfify'...")
       (evil-define-key normal python-mode-map
         (kbd "<f6>")
         'yapfify-buffer)
       t t)))

感觉就是你想要的。另外你还可以继续处理下 Key,可以避免写 kbd

Update: 我刚才没注意到你的 :evil-bind 中的 normal 没有加 Quote,所以后面也漏加了,你自己构造 evil-define-key 的时候不用忘记加上,估计就是换成

`((evil-define-key ',(caar arg) ,@(cdar arg)))
2 个赞

Thank you

你好,我是在 Google 类似的方案的时候找到这个帖子的

这个帖子已经比较早了,我不知道你现在是不是已经知道有另外一个办法能实现这个效果了:

(use-package xxxx
  :bind
  (:map evil-normal-state-map ("RET" . color-rg-open-file)))

现在可以这么做了

1 个赞

这样的方式一开始就支持的,我需要的是像这样的

(use-package xxxx
  :bind
  (:state insert :map python-mode-map ("RET" . color-rg-open-file)))

我自己添加了几个use-package关键词,有需要的同道可以参考一下 maple-use-package.el

(use-package package-name
  :evil-bind
  (:state normal :map python-mode-map
          ("C-c" . run-python))
  (:state (normal insert) :map python-mode-map
   ("C-s" . run-python))
  :evil-leader
  ("C-c" . run-python)
  (("C-c" . run-python)
   ("C-s" . run-python))
  (:mode python-mode
         ("C-s" . run-python)
         ("C-c" . run-python))
  :evil-state
  (comint-mode . insert)
  (sql-interactive-mode . insert)
  :custom
  (:mode org-mode
         company-tooltip-align-annotations nil)
  (:mode markdown-mode
         company-tooltip-align-annotations nil))
2 个赞