use-package时setq和define-key放:init还是:config?

:config会晚点加载,更环保一点,但是setq和define-key消耗不多,放:init也不会报错。

define-key要放init里,不然按下去不会load,按下去什么都不会发生?

这里说有些变量在load之后才定义,所以要放:config里?不对的


相关帖子:use-package autoload 的问题

如果有作者比较暴力用setq定义变量 不就凉凉了 :smiley:


而且理论上来说应该先定义才能setq。你放到定义前面是不合法的。

见下

1 个赞

先定义再setq,也就是要放到config后面,放到init后面是不是说你先定义了这个变量,然后插件作者使用了这个变量

差不多是这么一个道理,不过正规一点的用法是,就是啰嗦

:init (defvar aaa nil) (setq aaa 'bbb)

1 个赞

不需要,defvar 的作用就是为了让你能在定义加載之前 setq 的。而且一些情況下如:

(defvar foo 'blue)
(a-complex-calc-and-set-many-face foo) ;; 通過 foo 的值设置 10 多个不同的 face。

(setq foo 'yellow):config 里就晚了,在這個情況下字体在加載完后已经设置好了,再怎么 (setq foo ..) 都无济于事。

相反,define-key 要放 :config 里,因為 keymap 是要定义之后才能设定的。

3 个赞

也许是,也许不是,因为 OP 没有说 define-key 用到的 keymap 从何而来,比如说它可能是 global-map

1 个赞

你的问题没有一个固定的答案,

  • 有时必须用 :init
  • 有时必须用 :config
  • 有时两者都可以

use-package 非常复杂,三年前我看不懂它的实现,现在我很可能依旧还是看不懂。它给我带来了组织配置上的便利,也给我造成了很多困惑,以至于我常想放弃它。

1 个赞

常用的也就是:init, :config, :mode几种,或许可以自己实现一个简易版用?

不清楚 use-package 的加载过程,我个人配置是这样的:

(definit foo
  :pre
  (progn
    ;; load 之前
    )
  :post
  (progn
    ;; load 之后
    ))

如楼上所说,配置放在哪里,要考虑多种情况。

  • 必须在 load 之前

    有的 package 会在 load 过程中执行一些初始化操作,这些操作以后不会再执行了,所以必须抢在 load 之前改变相关变量(/函数)的默认值(/定义)。因为 load 之后再改变就不起作用了。

  • 必须在 load 之后

    需要用到 package 中定义的变量或函数,当然要写在 load 之后。大部分配置应该写在这个地方。另外,假如 package 推迟加载,也就达到了"加速"启动的效果。

  • 两者都可

    假如前面两点都考虑过,有些配置确实放哪效果都一样,就看放在哪里排版比较顺眼了。

1 个赞

(global-set-key (kbd "C-c y") 'youdao-dictionary-search-at-point+)是不是放:init更好,这样按下组合键的时候会load youdao-dictionary,而放:config里按下去就会没反应?

等一下,:initglobal-set-key的效果是不是和:bind一样?
是的,文档里key-binding这节说,

(use-package ace-jump-mode
  :bind ("C-." . ace-jump-mode))

(use-package ace-jump-mode
  :commands ace-jump-mode
  :init
  (bind-key "C-." 'ace-jump-mode))

效果一样,给ace-jump-mode加上autoload然后绑个键

实际是一样的。

1 个赞

:init / :config 这样含糊不清的词,带来的混乱恐怕多于便利

没有人提到 use-package-verbose 啊 看来也没有几个人看过源码

修改 use-package-core.el

(defmacro use-package-core (name args)
  `(let* ((args* (use-package-normalize-keywords ,name ,args))
          (use-package--form
           (if (eq use-package-verbose 'debug)
               (print (concat "\n\n"
                       (pp-to-string `(use-package ,name ,@,args))
                       "\n  -->\n\n"
                       (pp-to-string `(use-package ,name ,@args*))
                       "\n  ==>\n\n"
                       (pp-to-string
                        (macroexp-progn
                         (let ((use-package-verbose 'errors)
                               (use-package-expand-minimally t))
                           (use-package-process-keywords name args*
                             (and (plist-get args* :demand)
                                  (list :demand t)))))))
                      )
             ""
             )))

     (use-package-process-keywords name args*
       (and (plist-get args* :demand)
            (list :demand t)))))

M-x byte-compile-file use-package-core.el

C-x C-c

在 scratch 中写如下的代码

(setq use-package-verbose 'debug)
(use-package "swiper" :init (setq zxc 78) :config (setq zxc 99))

M-x eval-buffer

C-h e

我想绝大多数人(比如我)即使看了也看不懂。


对于那些不 Byte Compile 配置的人来说(比如我,因为 Byte Compile 会进一步地增加我理解配置的难度),一个简单地验证 use-package 使用是否正确的方法是:

  • 展开 use-package,得到没有了 use-package 的配置,然后看看其是否符合你的预期

我一般用 macrostep-expand 展开宏,用 Emacs 自带的 emacs-lisp-macroexpand 也行。

2 个赞