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

如上所示,我想提示输入"foobar1", "barfoo", 并"foobaz"获得配对目录作为回报。

Mover,如果我有这样的哈希表

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

如何提示输入人员姓名但获得人员 ID 作为回报?

4

2 回答 2

7

没有办法completing-read返回值而不是键,因此您必须自己进行查找:

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

至于哈希表,由于名称不是键,您需要遍历哈希表中的每个对象才能找到它,使用maphash. 由于在找到所需内容后继续迭代会很浪费,因此您可以使用catchand throw,如下所示:

(catch 'found-it
  (maphash
   (lambda (key value)
     (when (equal (person-name value) desired-name)
       (throw 'found-it key)))
   person-table))

这将返回人员 ID,或者nil如果没有姓名等于 的人员desired-name

于 2016-02-14T13:09:05.413 回答
5

@legoscia 提供了一个很好的答案:不允许completing-read您访问与用于完成的键关联的值。例如,对于 alist参数,它不会让您访问所选 alist 键的 cdr。COLLECTION

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

但是,当存在重复的 key时,即当多个候选者具有相同的 key或 name时,这些方法排除了获取与特定选择的 key 出现相关联的特定 value。

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

如果您使用Icicles,则不会浪费 alist 条目。检索 cdr 值没有问题。完成后,您可以轻松获取所选候选人的完整信息completing-read

Icicles通过使用属性化字符串作为候选,并通过增强completing-read使其可以返回用户选择的完整字符串、属性和所有内容来做到这一点。您可以从返回的属性化字符串中恢复完整的 alist 条目。

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

例子:

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

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

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

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

  • 具有相同名称的标记项(例如函数)。

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

Icicles中,用户如何从多个具有相同名称的完成候选中选择一个?

  • 用户可以控制候选人的顺序(排序),包括即时更改顺序。*Completions*按特定顺序显示给您。您可以在候选人之间循环或直接选择其中任何一个。你不限于匹配、选择。(对于重复的候选人,匹配可能不足以让您只找到其中​​一个。)

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

  • 您还可以在模式行中查看有关当前候选的重要附加信息(例如在循环期间)。

  • 您可以*Help*通过按一个键按需获取有关当前候选人的其他信息(完整)。

您需要做什么才能 在您自己的代码中利用此Icicles功能?

请参阅定义跳闸命令了解如何定义您自己的命令,让用户在(探索)可能具有相关位置或其他导航信息的候选者之间跳闸。(有关预定义的Icicles脱扣命令,请参阅脱扣。)

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

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

  2. 将变量设置icicle-candidates-alist为您传递给的 alist completing-read。这具有将整个相应的原始 alist 条目编码为候选显示字符串上的文本属性的效果。

  3. icicle-get-alist-candidate在调用之后使用completing-read,来恢复关于用户选择的候选人的完整信息,即完整的 alist 元素,包括 cdr。

(另请参阅:使用 Icicles 的程序员注意事项。)

于 2016-02-14T16:46:24.283 回答