如何安全地销毁 buffer local variable?

elisp

#1

例如有多个 minor mode 共用一个变量, 这些 mode 不知道彼此的存在,它们在各自启用时都会设置 buffer local variable,禁用的时候销毁 buffer local variable。

那么问题来了,当 foo-mode, bar-mode 都启用了,这时禁用其中之一,buffer local variabe 被销毁,剩下的 mode 使用的就是默认变量值了。

(with-default-emacs
  (defvar lvar nil)

  (define-minor-mode foo-mode
    "Toggle Foo mode."
    :init-value nil
    :lighter " Foo"
    :group 'foo
    (if foo-mode
        (setq-local lvar t)
      (kill-local-variable 'lvar)))

  (define-minor-mode bar-mode
    "Toggle Bar mode."
    :init-value nil
    :lighter " Bar"
    :group 'bar
    (if bar-mode
        (setq-local lvar t)
      (kill-local-variable 'lvar)))
  
  (with-current-buffer (get-buffer-create "*test*")
    (foo-mode)
    (bar-mode)
    (foo-mode -1)
    lvar))
    ;; => nil   [actual] 
    ;; => t     [expected]

是不是可以实现类似引用计数的效果,只有当最后一个使用该变量的 mode 禁用时才真正销毁?


#2

不是自己的变量,就不要乱kill。依赖minor-mode A的minor-mode B,应该随着A被关闭的时候也被关闭才对


用helpful.el 看了下我有什么插件用了这个函数,似乎只有flycheck,magit-blame,with-editor,company和transient在用,而且他们kill的都是自己的variable


#3

原则上是这样的,但是我想讨论的不是该不该,而是不得已需要用到,应如何避免产生问题。


#4

什么时候会必须删除本地变量呢?

advice的话,引用计数应该不难