Emacs 如何通过完成读取来返回值而不是键

Emacs 如何通过完成读取来返回值而不是键,emacs,lisp,elisp,completion,Emacs,Lisp,Elisp,Completion,如上所示,我想提示输入“foobar1”,“barfoo”,以及“foobaz”,但返回的是成对的目录 Moverover,如果我有这样一个哈希表 (completing-read "Complete a foo: " '(("foobar1" "~/foobar1/") ("barfoo" "/usr/barfoo/") ("foobaz" "/hello/"))) 我怎样才能提示输入人名,但得到一个人名作为回报?没有办法让完成读取返回值而不是键,因此您必须自己进行查找: (cl-def

如上所示,我想提示输入
“foobar1”
“barfoo”
,以及
“foobaz”
,但返回的是成对的目录

Moverover,如果我有这样一个哈希表

(completing-read
 "Complete a foo: "
 '(("foobar1" "~/foobar1/") ("barfoo" "/usr/barfoo/") ("foobaz" "/hello/")))

我怎样才能提示输入人名,但得到一个人名作为回报?

没有办法让
完成读取
返回值而不是键,因此您必须自己进行查找:

(cl-defstruct person ID name)
(setq person-object (make-person :ID 123 :name "foo"))
(setq person-table (make-hash-table))
(pushash (person-ID person-object) person-object person-table)
至于哈希表,由于名称不是键,因此需要使用
maphhash
遍历哈希表中的每个对象以找到它。由于在找到要查找的内容后继续迭代是浪费时间的,因此可以使用
catch
throw
,如下所示:

(let ((completions '(("foobar1" "~/foobar1/") ("barfoo" "/usr/barfoo/") ("foobaz" "/hello/"))))
  (cadr (assoc (completing-read "Complete a foo: " completions) completions)))

这将返回person ID,如果没有人的姓名等于所需姓名,则返回
nil
。@Legossia提供了一个很好的答案:
完成读取
不会让您访问与用于完成的键相关的值。例如,对于alist
集合
参数,它不允许您访问所选alist键的cdr

对于列表,可以使用
assoc
获取第一个匹配的列表元素,对于哈希表,可以使用
maphhash
或执行get

但是,这些方法排除了在存在重复项时,即当多个候选项具有相同的键或名称时,获取与特定选定键出现相关联的特定值

无法获取第二个匹配元素或第十三个匹配元素。事实上,香草Emacs
完成读取
消除了具有相同键(名称)的完成候选项的重复。对于普通的Emacs,alist条目的cdr中的任何信息都是浪费的。为了方便起见,如果您已经有了一个列表,那么您可以使用一个列表,如果没有,那么您最好只使用一个名称列表(字符串或符号),而不是conse

如果使用,则不会浪费列表条目。检索cdr值没有问题。完成阅读后,您可以轻松获得所选候选人的完整信息

冰柱通过使用属性化字符串作为候选字符串,并通过增强
完成读取
来实现这一点,以便它可以返回用户选择的完整字符串、属性和所有内容。您可以从返回的属性化字符串中恢复完整的列表项

什么时候能够拥有和使用具有不同关联值的重复键很重要?如果它们是重复的,用户如何区分它们(例如,在
*Completions*
中)

示例:

  • 具有相同名称但用于不同目标的书签-例如,用于不同目录中具有相同相对名称的不同文件

  • 缓冲区中与图案匹配或包含标记的行或其他文本。这包括中的匹配项,您可以在其中以任何方式定义搜索上下文(而不仅仅是行)。它还包括缓冲区(包括限制,又名变窄)和缓冲区位置(标记)

  • 具有相同文本但注释不同的候选文本。(用户输入与
    *Completions*
    中显示的注释不匹配)

  • 具有相同名称的Imenu项,例如具有相同名称的对象(例如函数)的多个定义

  • 具有相同名称的标记项(如功能)

  • 候选对象是可以具有相同名称的其他Lisp对象,如框架

冰柱中,用户如何从几个同名的候选完成项目中选择一个

  • 用户可以控制候选人的顺序(排序),包括动态更改顺序<代码>*完成*按特定顺序向您显示它们。您可以在候选对象之间循环,也可以直接选择其中任何一个。你不局限于匹配,选择。(对于重复的候选对象,匹配可能不足以让您只找到其中一个。)

  • *补全*
    还可以向您显示有关候选人的其他信息,即使他们有相同的姓名/文本,也可以将他们区分开来。这些信息可以是周围的文本(如果候选文本与缓冲区文本匹配),也可以是候选元数据(例如文件或书签属性)

  • 您还可以在模式行中看到有关当前候选人的重要附加信息(例如,在骑自行车期间)

  • 点击一个键,您可以根据需要获得有关当前候选人的其他信息(完整的
    *帮助*

要在您自己的代码中利用此冰柱功能,您必须做些什么?

有关如何定义自己的命令的信息,请参见。这些命令允许用户在可能具有相关位置或其他导航信息的候选对象之间来回搜索(浏览)。(有关预定义的冰柱跳闸命令,请参阅。)

简要概述在命令中要执行的操作:

  • 将变量
    icicle-whole-candidate-as-text-prop-p
    绑定到非
    nil

  • 将变量
    冰柱候选列表
    设置为传递给
    完成读取的列表
    。这具有将整个对应的原始条目编码为候选显示字符串上的文本属性的效果

  • 调用
    完成读取
    后,使用
    ICICICLE get alist SUMBERT
    ,恢复用户选择的候选人的完整信息,即完整的ALister元素,包括cdr


  • (另请参见:)

    @Legossia提供了我所需的所有信息。但是,我选择这个答案是因为它提醒我复制问题。
    (catch 'found-it
      (maphash
       (lambda (key value)
         (when (equal (person-name value) desired-name)
           (throw 'found-it key)))
       person-table))