我可以使用ido-completing-read替代completing-read吗?(问题标题)

13

我非常喜欢ido-mode,我希望能像在“Can I get ido-mode-style completion for searching tags in Emacs?”那样,不用为每个命令都编写代码,而是直接在describe-functionfind-tag等命令中使用。

两者都

(defalias completing-read ido-completing-read)

并且

(setf 'completing-read 'ido-completing-read)

这种方法不起作用,至少部分原因是ido-completing-read在其主体中调用completing-read,因此任何简单的重新定义都会导致无限递归。

从理论上讲,这应该是可能的,因为ido-completing-read的文档字符串的第一行是“内置completing-read的Ido替代品。”我已经找了一些资料,似乎没有人尝试或者成功过。

我知道Icicles可能提供了类似的功能,而且我可能最终会使用它,但这比我现在想要采取的措施还要深入一些。

感谢任何帮助。

6个回答

10

编辑:这是现在一个可从MELPA获得的Emacs软件包。它已经扩展成一个完整的次要模式。开发在GitHub进行。

原始帖子:

这是对Jacobo答案的改进。原始代码来自他。我添加了一个覆盖变量,你可以使用它来防止在特定函数中使用ido-completing-read。如果没有匹配项,我还添加了一个检查,使用原始的completing-read(例如,在org-mode中的org-remember-apply-template中偶尔会出现这种情况,这打破了Jacobo的建议)。

(defvar ido-enable-replace-completing-read t
  "If t, use ido-completing-read instead of completing-read if possible.

Set it to nil using let in around-advice for functions where the
original completing-read is required.  For example, if a function
foo absolutely must use the original completing-read, define some
advice like this:

(defadvice foo (around original-completing-read-only activate)
  (let (ido-enable-replace-completing-read) ad-do-it))")

;; Replace completing-read wherever possible, unless directed otherwise
(defadvice completing-read
  (around use-ido-when-possible activate)
  (if (or (not ido-enable-replace-completing-read) ; Manual override disable ido
          (boundp 'ido-cur-list)) ; Avoid infinite loop from ido calling this
      ad-do-it
    (let ((allcomp (all-completions "" collection predicate)))
      (if allcomp
          (setq ad-return-value
                (ido-completing-read prompt
                               allcomp
                               nil require-match initial-input hist def))
        ad-do-it))))

顺便提一下,如果想在M-x中使用ido,请使用amx


7

Hocus pocus, abracadabra, presto!

(defadvice completing-read
  (around foo activate)
  (if (boundp 'ido-cur-list)
      ad-do-it
    (setq ad-return-value
      (ido-completing-read
       prompt
       (all-completions "" collection predicate)
       nil require-match initial-input hist def))))

这适用于除了subr之外的所有内容,其中execute-extended-command是最重要的(绑定到M-x)。但我们可以从M-x中得到想要的结果。

(global-set-key
 "\M-x"
 (lambda ()
   (interactive)
   (call-interactively
    (intern
     (ido-completing-read
      "M-x "
      (all-completions "" obarray 'commandp))))))

3
似乎在 Emacs 23.2 版本中出现了问题。将 ido-cur-item 替换为 ido-cur-list 可以让它再次正常工作。 - polyglot

3
我认为ido-mode目前还没有准备好。特别是,ido-completing-read目前只能与字符串一起使用,而completing-read也支持关联列表。当您想要在完成项上具有不同的用户级描述时,这非常重要。
因此,我并不惊讶它不能立即运行。除非你自己修改代码,否则你最好的选择可能就是提交一个错误报告/功能请求。

1

使用 Emacs 24.3 版本时,ido-ubiquitous 插件无法正常工作。因此我尝试了以下方法,目前运行良好:

(defun my-completing-read (prompt collection &optional predicate
                  require-match initial-input
                  hist def inherit-input-method)
  (if (listp collection)
      (ido-completing-read prompt collection predicate require-match
               initial-input hist def inherit-input-method)
    (completing-read-default prompt collection predicate require-match
                 initial-input hist def inherit-input-method)))

(setq completing-read-function 'my-completing-read)

ido-ubiquitous现在与最新的Emacsen完美兼容,因为Ryan进行了重写。 - sanityinc

1

Ido自带一个函数可以实现这个功能,所以只需要在你的.emacs文件中调用它:

(ido-everywhere t)


2
我一直希望这个能够起作用,但ido对“everywhere”的看法相当有限,仅限于文件、目录和缓冲区完成。它对像describe-functionfind-tag这样的东西没有任何影响,因为它们正在完成其他事情。我的当前想法是将completing-read保存到一个变量中,将名称别名为ido-completing-read,然后在ido-completing-read周围放置一个defadvice,在ido期间恢复原始的completing-read。这非常hackish,可能不值得这样做。 - haxney

0
只是一个想法:你尝试过编辑ido-completing-read,调用original-completing-read而不是completing-read,定义original-completing-read为当前的completing-read,然后进行defalias或setf操作吗?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接