首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Emacs中是否有命令的“`flet`”?

Emacs中是否有命令的“`flet`”?
EN

Stack Overflow用户
提问于 2015-04-16 07:13:31
回答 2查看 282关注 0票数 4

我希望使用around通知动态地将一个命令重定向到某个函数中的另一个命令,如下所示:

代码语言:javascript
复制
(defun f1 (arg)
  (interactive (list (read-from-minibuffer "F1: ")))
  (message "f1: %S" arg)
  arg)
(defun f2 (arg)
  (interactive (list (read-from-minibuffer "F2: ")))
  (message "f2: %S" arg)
  arg)
;; Function that invokes the f1 command
(defun myfunc ()
  (call-interactively 'f1))

;; I want myfunc to invoke f2 instead whenever it would invoke f1
(defadvice myfunc (around f1-to-f2 activate)
  (flet ((f1 (&rest args) (interactive) (call-interactively 'f2)))
    ad-do-it))

(myfunc)

但是,这会给出一个错误(wrong-type-argument commandp f1),表明当flet重新定义f1函数时,它没有处理交互式表单并将其视为命令,因此call-interactively无法调用它。

是否有flet的变体可以以这种方式处理命令?

(以下是我想要做的实际重定义:)

代码语言:javascript
复制
(defadvice org-metaleft (around osx-command activate)
        (flet ((backward-word (&rest args)
                (interactive)
                (call-interactively #'move-beginning-of-line)))
          ad-do-it))

(defadvice org-metaright (around osx-command activate)
        (flet ((forward-word (&rest args)
                (interactive)
                (call-interactively #'move-end-of-line)))
          ad-do-it))
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-04-16 13:55:53

您在flet中遇到了一个愚蠢的bug :flet的宏扩展将有:(lambda (&rest args) (progn (interactive) (call-interactively 'f2)))。注意这里添加的虚假progn,它“隐藏”了interactive

要获得更多的控制(同时避免cl.el ),您可以这样做:

代码语言:javascript
复制
(defadvice myfunc (around f1-to-f2 activate)
  (cl-letf (((symbol-function 'f1)
             (lambda (&rest args)
               (interactive) (call-interactively 'f2))))
    ad-do-it))
票数 4
EN

Stack Overflow用户

发布于 2015-04-16 07:39:28

(编辑:cl-letf宏可以在现代emacs中本地地实现这一点。下面的答案对于旧版本仍然是有用的。)

好吧,如果以前没有,现在有:

代码语言:javascript
复制
(require 'cl)
(require 'cl-lib)
(defmacro command-let (bindings &rest body)
  "Like `flet', but works for interactive commands.

In addition to the standard `(FUNC ARGLIST BODY...)' syntax from
`flet', this also supports `(FUNC NEW-FUNC)' as a shorthand for
remapping command FUNC to another command NEW-FUNC, like this:

  (defun FUNC (&rest ignored)
    (interactive)
    (call-interactively NEW-FUNC))

\(fn ((FUNC ARGLIST BODY...) ...) FORM...)"
  (declare (indent 1))
  (cl-loop for binding in bindings
           collect (list (car binding) nil) into empty-bindings
           collect (if (symbolp (cadr binding))
                       ;; Remap one command to another
                       `(defun ,(car binding) (&rest args)
                          (interactive)
                          (call-interactively ',(cadr binding)))
                     ;; Define command on the fly
                     (cons 'defun binding))
           into defun-forms
           finally return
           `(flet (,@empty-bindings)
              ,@defun-forms
              ,@body)))

在行动中:

代码语言:javascript
复制
(defadvice myfunc (around f1-to-f2 activate)
  (command-let ((f1 f2))
    ad-do-it))
(myfunc)

根据需要,该代码现在使用f2调用call-interactively命令。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29667809

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档