我想重新定义现有函数foo
,但仅限于特定缓冲区。
(defun foo ()
(message "Not done:("))
我正在跳这样做:
(make-local-variable 'foo)
(fset 'foo #'(lambda () (message "Done!")))
但事实并非如此。 有什么想法吗?
[编辑: 或者,因为函数被绑定到一个键,所以只修改当前缓冲区的绑定就足够了。但我不明白该怎么做。本地键映射由主模式中的所有缓冲区共享。修改它会修改所有缓冲区中使用此主要模式的绑定。
我能想到的唯一丑陋的解决方案是为整个缓冲区设置keymap text-property。这是继续进行的唯一途径吗?]
答案 0 :(得分:5)
你可以创建一个能够覆盖你的功能,其中包括:
(defun override-the-keymap ()
(let ((my-overriding-keymap (make-sparse-keymap)))
(set-keymap-parent my-overriding-keymap (current-local-map))
(use-local-map my-overriding-keymap)
(define-key my-overriding-keymap (kbd "C-M-x")
'(lambda () (interactive) (message "Done!")))))
显然可以适当地自定义键绑定。这仅在当前缓冲区中起作用。
答案 1 :(得分:4)
给定符号的值和函数属性是分开的,因此大概make-local-variable
只会影响值,而fset
会对函数进行操作< / em> property。
你可能最好更详细地描述你想要做什么,但一个通用的解决方案是使用“around advice”用你自己的代码包装原始函数。
(defadvice foo (around my-foo-wrapper)
(if (not (and (boundp 'use-my-foo) 'use-my-foo))
ad-do-it
(message "Not done:(")))
(ad-activate 'foo)
;; in special buffer
(set (make-local-variable 'use-my-foo) t)
编辑:(关于其他键映射注释)
也许你想要在你的特殊缓冲区中定义一个次要模式。次模式键映射优先于主模式键映射,因此您只需在次模式映射中定义相同的绑定。请参阅define-minor-mode
。
答案 2 :(得分:3)
如何将符号函数写入符号值,然后通过其他函数进行评估?
(defvar my-buffer-local-function
(lambda ()
(interactive)
(message "Default message"))
"This variable contains buffer local function")
(make-variable-buffer-local 'my-buffer-local-function)
(defun run-my-buffer-local-function (&rest args)
"This function run buffer-local function"
(interactive)
(if (called-interactively-p 'any) ;To call interactively AND to
;be able to have elisp-calls
(call-interactively my-buffer-local-function)
(apply my-buffer-local-function args)))
(setq my-buffer-local-function
(lambda (&optional arg)
(interactive "sinsert message: ")
(message (concat "Not so default message: " arg))))
明显不好的一面是,如果my-buffer-local-function
是互动的,那么效果很好。如果没有,run-my-buffer-local-function
仍然是互动的,并且在M-x
列表中可见。我认为你不能制作有时候互动的功能,因为interactive
应该是顶级电话。
顺便说一句,您可以使用相同的名称命名功能和值。
答案 3 :(得分:1)
如果函数定义是特定于缓冲区的,那通常表明它是主要模式特定的。如果事实上就是这种情况,那么处理它的正确方法是使用适合于特定缓冲区/模式的不同功能。如果问题是键绑定,那么只需将键绑定到主模式键映射中的专用函数。