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

时间:2016-02-14 10:29:34

标签: emacs lisp elisp completion

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

如上所示,我想提示"foobar1""barfoo""foobaz",但要获得配对目录。

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

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

2 个答案:

答案 0 :(得分:3)

没有办法让<?php // Check if the form has been transmitted or not if ($_SERVER['REQUEST_METHOD']=='POST') { // A form was transmitted if (isset($_POST['name'])) var_dump($_POST['name']); } else { // Send the form out so the user can transmit it echo "<form action='check.php' method=\"post\"> <input type=\"text\" name=\"name\" > <input type=\"submit\" name=\"submit\" value=\"ok\"> </form>"; } ?> 返回值而不是键,所以你必须自己进行查找:

completing-read

对于哈希表,由于名称不是键,因此需要使用(let ((completions '(("foobar1" "~/foobar1/") ("barfoo" "/usr/barfoo/") ("foobaz" "/hello/")))) (cadr (assoc (completing-read "Complete a foo: " completions) completions))) 遍历哈希表中的每个对象以查找它。由于在您找到了您正在寻找的内容后继续进行迭代会很浪费,您可以使用maphashcatch,如下所示:

throw

如果没有名字等于(catch 'found-it (maphash (lambda (key value) (when (equal (person-name value) desired-name) (throw 'found-it key))) person-table)) 的人,则会返回此人ID或nil

答案 1 :(得分:3)

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

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

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

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

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

Icicles 通过使用属性化字符串作为候选项,并通过增强completing-read来实现,以便它可以返回用户选择的完整字符串,属性和所有内容。您可以从返回的有属字符串中恢复完整的alist条目。

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

示例:

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

  • 缓冲区中与模式匹配或包含标记的行或其他文本。这包括Icicles search中的匹配,您可以在其中以任何方式定义搜索上下文(而不仅仅是行)。它还包括缓冲区(包括限制,也称为缩小)和缓冲区位置(标记)。

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

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

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

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

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

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

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

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

  • 您可以通过点击密钥获取有关当前候选人的其他信息(完整*Help*)。

您需要做什么才能在自己的代码中利用 Icicles 功能 < / strong>

请参阅Defining Tripping Commands了解如何定义自己的命令,让用户在(探索)候选人之间旅行可能会有相关的位置或其他导航信息。 (有关预定义的 Icicles 跳闸命令,请参阅Tripping。)

简要概述您的命令:

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

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

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

  4. (另请参阅:Note to programmers using Icicles。)