就像 helm-find-file
会把用户输入添加到候选列表中:
[?] file <----
file1
file2
file3
当输入到 file4
没有任何匹配到任何文件名的时候,仍然有一个可选项:
[?] file4 <----
看了下 wiki 上的这个例子 :
(defun helm/test-default-action (candidate)
(browse-url (format
"http://www.google.com/search?q=%s"
(url-hexify-string candidate))))
(helm :sources (helm-build-dummy-source "test"
:action '(("Google" . helm/test-default-action)))
:buffer "*helm test*")
是可以处理用户输入了,但是固定选项如何设置?
helm-find-files
应该是自己在 candidates 函数里实现的
helm-find-files
-> helm-find-files-1
-> helm-source-find-files
-> helm-find-files-get-candidates
-> search /(list path)/
不了解 Ivy,只就 Helm 来说。
helm-build-dummy-source
是添加一个新的 Source,一般用来处理其它的 Source 没匹配时的情况,比如在 helm-filtered-bookmarks
中,它用来创建一个新的 Bookmark。又比如这一例(允许选择和创建一个名字):
(helm :sources
(list (helm-build-sync-source "Names"
:candidates '("Alice" "Ekko" "Jess"))
(helm-build-dummy-source "Create Name")))
不清楚你的需求,你可以把输入加入候选列表(注意要把 volatile
设为 t
):
(helm :sources
(helm-build-sync-source "Test"
:volatile t
:candidates
(lambda () (list "foo" "bar" "baz" helm-pattern))))
但这么做好像没什么意义。
1 个赞
xuchunyang:
不清楚你的需求
给定一组 candidates,让用户选择,但是如果都不符合期望,就以用户输入为准,helm-find-files
就是这么做的。但是 helm-find-files
太复杂了,一时找不到关键所在,就来论坛求助了😄
:volatile t
是有效的,接下来我看看怎么给用户输入的那一行做个标记,以示区别。
感谢 @xuchunyang 提供思路。不过,其实不需要 :volatile t
,也无需往 :candidates
列表添加 helm-pattern
:
(let ((default-candidates '("file1" "file12" "file3"))
(user-input-indicator "[?] "))
(helm :sources
(helm-build-sync-source "Test"
:candidates default-candidates
:action
(lambda (candidate)
(message "Result: %s"
(if (string-prefix-p user-input-indicator candidate)
helm-pattern
candidate)))
:filtered-candidate-transformer
(lambda (candidates _source)
(if (not (string-empty-p helm-pattern))
(if (member helm-pattern default-candidates)
candidates
(cons (concat user-input-indicator helm-pattern) candidates))
candidates))
)))
存在有两个小问题:
高亮始终落在第一个选项上。当用户输入不完全匹配时,高亮应该落在第二项;
初始化之后列表没有行号,直到用户输入才显示行号,不过 heml-find-files
也是这样(或是我哪里设置不对?)。
Ivy 可以实现这种功能,我在 exwmx-dmenu 里面用了好久了。。。。
(ivy-read
“test”
#'(lambda (input)
(cons (if (< (length input) 1)
"**NULL**"
input)
(cl-remove-if-not
#'(lambda (cmd)
(string-match-p (funcall ivy--regex-function input) cmd))
commands)))
:dynamic-collection t
:keymap exwmx-dmenu-ivy-minibuffer-map)))))))
1 个赞
ivy 这个写法挺直观,不过为什么 “test” 最后一个字符显示不出来?
emacs -Q 测试一下,我这边似乎没有这个问题
ztlevi
2017 年9 月 14 日 14:16
13
对ivy来说,虽然加不到里面,但是默认的有(setq ivy-use-selectable-prompt t)
。设定后就可以选择用户输入了
测了,新建一份配置,就加载 ivy
一个包,问题仍然存在。
macOS 10.11.6
emacs 25.2 / 26.0.50
ivy-20170817.1000 / ivy-20170911.1034
“test” 后面加一个空格就好像可以了。。。。
(ivy-read
"test "
#'(lambda (input)
(cons (if (< (length input) 1)
"**NULL**"
input)
'("this" "that" "hello")))
:dynamic-collection t)
tumashu:
“test” 后面加一个空格就好像可以了。。。。
看了 ivy-read 文档,这是 feature
PROMPT is a format string, normally ending in a colon and a
space; %d anywhere in the string is replaced by the current
number of matching candidates. For the literal % character,
escape it with %%. See also ‘ivy-count-format’.
正确应该这样写:
"Test: "
先前差点就去提 issue 了,还好没找到 ivy 项目地址,而是跑去 avy 了,搜了一下发现没有 ivy-read
相关的结果,才意识到不对。ivy 的项目地址竟然是 GitHub - abo-abo/swiper: Ivy - a generic completion frontend for Emacs, Swiper - isearch with an overview, and more. Oh, man!
1 个赞
et2010
2017 年9 月 15 日 14:38
17
ivy, counsel, swiper 三位一体,最初我也很困惑。