Function elisp中的缓冲区局部函数

Function elisp中的缓冲区局部函数,function,emacs,elisp,buffer,local,Function,Emacs,Elisp,Buffer,Local,我想重新定义一个现有函数foo,但只针对特定的缓冲区 (defun foo () (message "Not done:(")) 我希望这样做可以: (make-local-variable 'foo) (fset 'foo #'(lambda () (message "Done!"))) 但事实并非如此。 有什么想法吗 [编辑: 或者,因为函数被绑定到一个键,所以只为当前缓冲区修改绑定就足够了。但我不知道怎么做。本地键映射由主模式下的所有缓冲区共享。修改它会修改此主模式下所有缓冲区中的

我想重新定义一个现有函数
foo
,但只针对特定的缓冲区

(defun foo ()
  (message "Not done:("))
我希望这样做可以:

(make-local-variable 'foo)
(fset 'foo #'(lambda () (message "Done!")))
但事实并非如此。 有什么想法吗

[编辑: 或者,因为函数被绑定到一个键,所以只为当前缓冲区修改绑定就足够了。但我不知道怎么做。本地键映射由主模式下的所有缓冲区共享。修改它会修改此主模式下所有缓冲区中的绑定


我能想到的唯一丑陋的解决方案是为整个缓冲区设置一个keymap文本属性。这是唯一的方法吗?]

给定符号的值和函数属性是分开的,因此推测
make local variable
只会影响值,而
fset
对函数属性进行操作

您最好更详细地描述您想要做的事情,但是一个通用的解决方案是使用“环绕建议”将原始函数与您自己的代码包装在一起

(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)
编辑:(关于其他关键地图注释)


然后,您可能需要定义一个次要模式,以便在特殊缓冲区中使用。次要模式键映射优先于主要模式键映射,因此您只需在次要模式的映射中定义相同的绑定。请参见
定义次要模式

您可以创建一个函数来为您执行覆盖操作,大致如下所示:

(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!")))))

显然,可以适当地定制密钥绑定。这仅在当前缓冲区中有效。

将符号函数写入符号值,然后用其他函数对其求值如何

(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
是交互式的,那么它工作得很好。否则,
运行我的缓冲区本地功能
仍将是交互式的,并且在
M-x
列表中可见。我认为您有时不能使用交互式函数,因为
交互式
应该是顶级调用


顺便说一句,您可以使用相同的名称命名函数和值。

如果函数定义是特定于缓冲区的,则通常表示它是特定于主模式的。如果这里的情况确实如此,那么正确的处理方法是使用适合该特定缓冲区/模式的不同功能。如果问题是键绑定,那么只需将键绑定到主模式的键映射中的专用函数。

这是针对我的包的,因此我可以直接修改函数,而不是通知它。问题是,对于一个非常特定的缓冲区,我需要一个不同的功能,并且不想仅针对这个非常特殊的情况而对功能进行模糊处理。这是一个交互式功能,因此可以在本地修改地图。但我也不知道怎么做。编辑了问题。你真正想解决的问题是什么?也许有一种不同的方法更有效。您如何知道何时需要“完成”和“未完成”(“?@Trey该软件包的帮助模式具有导航功能(跳转到部分)。它简短而优雅。但对于一种非常特定类型的帮助文件,我需要不同的行为。我不希望将该功能构建到函数中,而是希望能够在本地重新定义它。事实上,你的答案符合我的要求。很酷的技巧。它解决了我迄今为止提出的最好的问题。尽管就我的目的而言,它有点冗长。我将保留这一点我对未来的想法。这确实奏效,我会努力的,但是@desudesudesudesu answer解决了最初的问题,使函数缓冲区本地化,这有点理论的一面。因此,我接受了他的回答。