* Canonical way to add a pre-filter to completing-read
@ 2018-05-10 13:09 Kaushal Modi
2018-05-10 14:10 ` Drew Adams
2018-05-10 15:21 ` Stefan Monnier
0 siblings, 2 replies; 6+ messages in thread
From: Kaushal Modi @ 2018-05-10 13:09 UTC (permalink / raw)
To: Help Gnu Emacs mailing list
Hello,
I want to use completing-read to provide a "pre-filter" to narrow down the
completion list.
My real use use is to take the symbol-at-point as the pre-filter to narrow
down in a list of all identifiers. For a real example, the symbol name is
"walkDirRec", but the completion list contains "os.walkDirRec".. so I am
trying to figure out how to use completing-read with that.
(I am aware that I can use the counsel library to make this easier, but was
looking for a way for completing-read to Just Work(TM).)
So here are some minimal examples to explain my conundrum..
Below works exactly as I want.. but the docs and manual say that
INITIAL-INPUT is deprecated.
(completing-read "Entry: " '("abc" "bcd" "cde") nil :require-match "bc")
;INITIAL-INPUT deprecated, but works as I want
Above will show in the completion list with just the filtered items
matching "bc":
abc
bcd
So following the manual, I tried using the DEF (default) argument instead,
but that doesn't work as I want.. that just throws in that DEF value
verbatim to the completion list..
(completing-read "Entry: " '("abc" "bcd" "cde") nil :require-match nil nil
"bc") ;Using DEF does not work.. it just inserts that as one more element
in the completion list
Above will end up with this list:
bc
abc
bcd
cde
So the DEF approach is not useful unless the DEF value is matching exactly
with one of the items in COLLECTION.
So, what would be the right way, i.e. not using the deprecated
INITIAL-INPUT?
Thanks.
--
Kaushal Modi
^ permalink raw reply [flat|nested] 6+ messages in thread
* RE: Canonical way to add a pre-filter to completing-read
2018-05-10 13:09 Canonical way to add a pre-filter to completing-read Kaushal Modi
@ 2018-05-10 14:10 ` Drew Adams
2018-05-10 17:36 ` Kaushal Modi
2018-05-10 15:21 ` Stefan Monnier
1 sibling, 1 reply; 6+ messages in thread
From: Drew Adams @ 2018-05-10 14:10 UTC (permalink / raw)
To: Kaushal Modi, Help Gnu Emacs mailing list
> I want to use completing-read to provide a "pre-filter" to
> narrow down the completion list.
Possibilities:
1. Filter the list of completions before passing it.
IOW, pass '("abc" "bcd"), not '("abc" "bcd" "cde").
(Or if COMPLETIONS is a function, have it also filter,
as and when needed.)
2. Provide a PREDICATE arg that filters as needed. E.g.,
(lambda (xx) (string-match-p "bc" xx)).
With vanilla Emacs:
If you use a non-function COMPLETIONS arg then you need
to establish that list of candidates before completing.
You have only PREDICATE to play with. The candidates
are determined independently of whatever input might be
in the minibuffer
If you use a function COMPLETIONS arg then the function
can take into account the current minibuffer input.
The function can do anything you want, to come up with
the (current, dynamically computed) set of candidates.
----
Wrt INITIAL-INPUT: It should not be considered deprecated.
There was never any need for that. It should have been
enough for the manual or doc string to just explain the
difference between DEF and INITIAL-INPUT, and to suggest
that in many (most?) cases it can be more user-friendly
or more useful to use only DEF. The "deprecation" of
this arg was uncalled for, IMHO.
----
If you use Icicles:
1. There are 3 possibilities for filtering with a predicate:
a. Use argument PREDICATE. As usual, it filters raw
COMPLETIONS, e.g., alist elements or obarray symbols,
and it does so before you type anything in the
minibuffer. Nothing new here.
b. Bind variable `icicle-must-pass-after-match-predicate'
around the `completing-read' call. It filters the
_displayed_ candidates (strings - what you see in
`*Completions*'), and it does so _after_ matching your
minibuffer input.
c. Bind variable `icicle-must-pass-predicate': same as
`icicle-must-pass-after-match-predicate', but before
matching your current input.
These can be used in combination. PREDICATE filters all
initial candidates, even when that might be wasteful (not
so performant) because you've typed some text that would
more quickly rule out many of them, if matched first.
Different use cases call for different matching orders.
Sometimes it makes sense to use only PREDICATE, filtering
all raw candidates ahead of time. Sometimes it makes
sense to do input-matching first, before applying a
given predicate.
2. Option `icicle-default-value' controls arg DEF: whether
it is shown in the prompt, gets substituted for an empty
INITIAL-INPUT, and so on. In particular, 4 of the 6
values insert the default value into the minibuffer:
`insert-start' - Insert DEF and leave cursor at start.
`insert-end' - Insert DEF and leave cursor at end.
`preselect-start' - Insert & preselect DEF; cursor at start.
`preselect-end' - Insert & preselect DEF; cursor at end.
> Below works exactly as I want.. but the docs and manual
> say that INITIAL-INPUT is deprecated.
>
> (completing-read "Entry: " '("abc" "bcd" "cde") nil
> :require-match "bc")
>
> So, what would be the right way, i.e. not using the
> deprecated INITIAL-INPUT?
Ignore the docs. Emacs was wrong to proclaim INITIAL-INPUT
deprecated. It can be useful. It never hurt anyone for
Emacs to make it available. It is enough to suggest to
users that it is more conventional, and typically more
user-friendly, to use only DEF.
With luck, this silly uber-control will be removed from
the docs someday. Don't be scared away from using it
when it suits your purpose.
(Just one opinion.)
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Canonical way to add a pre-filter to completing-read
2018-05-10 13:09 Canonical way to add a pre-filter to completing-read Kaushal Modi
2018-05-10 14:10 ` Drew Adams
@ 2018-05-10 15:21 ` Stefan Monnier
2018-05-10 17:19 ` Kaushal Modi
1 sibling, 1 reply; 6+ messages in thread
From: Stefan Monnier @ 2018-05-10 15:21 UTC (permalink / raw)
To: help-gnu-emacs
> (completing-read "Entry: " '("abc" "bcd" "cde") nil :require-match "bc")
> ;INITIAL-INPUT deprecated, but works as I want
>
> Above will show in the completion list with just the filtered items
> matching "bc":
>
> abc
> bcd
Could you clarify exactly here:
- "will show"... when the user does what?
Just calling the above `completing-read` won't show any list of completions
- When I hit ? at the prompt, I indeed get a list of completions, but
that list only includes `bcd` because the default completion style
does not include `substring`. So your use/test case is different from
the default.
Let's say the user does
M-: (km-completion "Entry: " '("abc" "bcd" "cde") "bc") RET
and then types `a` (and then hits `?` to see the list of remaining
completions, or maybe he uses icomplete-mode to always see the list of
remaining candidates). What do you want the list of completions to be
at that point?
Some things you can do with the standard completion-UI:
- setup your completion table such that it uses `substring` completion
by default.
- use `completion-table-in-turn` with the first table being a sub-table
which only includes the entries that match "bc".
-- Stefan
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Canonical way to add a pre-filter to completing-read
2018-05-10 15:21 ` Stefan Monnier
@ 2018-05-10 17:19 ` Kaushal Modi
2018-05-10 22:05 ` Stefan Monnier
0 siblings, 1 reply; 6+ messages in thread
From: Kaushal Modi @ 2018-05-10 17:19 UTC (permalink / raw)
To: Stefan Monnier; +Cc: help-gnu-emacs
Hello,
On Thu, May 10, 2018 at 11:22 AM Stefan Monnier <monnier@iro.umontreal.ca>
wrote:
>
> Could you clarify exactly here:
> - "will show"... when the user does what?
> Just calling the above `completing-read` won't show any list of
> completions
>
Hmm. I use the ivy package, that provides a vertical list selection
interface even when using completing-read. This is what I meant:
https://i.imgur.com/1Ki7uFX.gifv
In the GIF, I first set the "bc" value to INITIAL-INPUT. In the later part
of the GIF, I set it to DEF, where that "bc" simply gets added to the
available entries (and also of no use to me).
- When I hit ? at the prompt, I indeed get a list of completions, but
> that list only includes `bcd` because the default completion style
> does not include `substring`. So your use/test case is different from
> the default.
>
Is there a way to make it behave as you see in the first part of that GIF?
i.e. make the "bc" filter the available candidates?
Let's say the user does
>
> M-: (km-completion "Entry: " '("abc" "bcd" "cde") "bc") RET
>
> and then types `a` (and then hits `?` to see the list of remaining
> completions, or maybe he uses icomplete-mode to always see the list of
> remaining candidates). What do you want the list of completions to be
> at that point?
>
If I type `a` there, the entry would become "bca", and nothing will match..
but if I do `C-a a`, the entry will be "abc", and will show only that "abc"
element.
> Some things you can do with the standard completion-UI:
> - setup your completion table such that it uses `substring` completion
> by default.
>
That sounds like that would work.. can you please point to an example?
> - use `completion-table-in-turn` with the first table being a sub-table
> which only includes the entries that match "bc".
>
I did not understand this suggestion.
--
Kaushal Modi
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Canonical way to add a pre-filter to completing-read
2018-05-10 14:10 ` Drew Adams
@ 2018-05-10 17:36 ` Kaushal Modi
0 siblings, 0 replies; 6+ messages in thread
From: Kaushal Modi @ 2018-05-10 17:36 UTC (permalink / raw)
To: Drew Adams; +Cc: Help Gnu Emacs mailing list
Hi Drew,
On Thu, May 10, 2018 at 10:10 AM Drew Adams <drew.adams@oracle.com> wrote:
> Possibilities:
>
> 1. Filter the list of completions before passing it.
> IOW, pass '("abc" "bcd"), not '("abc" "bcd" "cde").
> (Or if COMPLETIONS is a function, have it also filter,
> as and when needed.)
>
Pre-filtering would not work in my case, as I might even need to change the
filter on the fly *after it got initially set using INITIAL-INPUT*. See how
I use it in this GIF (the same that I linked in my earlier reply to
Stefan): https://imgur.com/1Ki7uFX.
2. Provide a PREDICATE arg that filters as needed. E.g.,
> (lambda (xx) (string-match-p "bc" xx)).
>
That might.. work. I will have to try.
With vanilla Emacs:
>
> If you use a non-function COMPLETIONS arg then you need
> to establish that list of candidates before completing.
> You have only PREDICATE to play with. The candidates
> are determined independently of whatever input might be
> in the minibuffer
>
> If you use a function COMPLETIONS arg then the function
> can take into account the current minibuffer input.
> The function can do anything you want, to come up with
>
> the (current, dynamically computed) set of candidates.
Let me play with PREDICATE. At the moment, the COMPLETIONS is just a list.
I will look into that if setting PREDICATE does not work.
> > Below works exactly as I want.. but the docs and manual
> > say that INITIAL-INPUT is deprecated.
> >
> > (completing-read "Entry: " '("abc" "bcd" "cde") nil
> > :require-match "bc")
> >
> > So, what would be the right way, i.e. not using the
> > deprecated INITIAL-INPUT?
>
> Ignore the docs. Emacs was wrong to proclaim INITIAL-INPUT
> deprecated. It can be useful. It never hurt anyone for
> Emacs to make it available. It is enough to suggest to
> users that it is more conventional, and typically more
> user-friendly, to use only DEF.
>
> With luck, this silly uber-control will be removed from
> the docs someday. Don't be scared away from using it
> when it suits your purpose.
>
For now, I am using the INITIAL-INPUT as that solves the purpose. But I
will later try out the PREDICATE.
> (Just one opinion.)
>
Thanks for that :)
--
Kaushal Modi
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Canonical way to add a pre-filter to completing-read
2018-05-10 17:19 ` Kaushal Modi
@ 2018-05-10 22:05 ` Stefan Monnier
0 siblings, 0 replies; 6+ messages in thread
From: Stefan Monnier @ 2018-05-10 22:05 UTC (permalink / raw)
To: Kaushal Modi; +Cc: help-gnu-emacs
>> M-: (km-completion "Entry: " '("abc" "bcd" "cde") "bc") RET
>> and then types `a` (and then hits `?` to see the list of remaining
>> completions, or maybe he uses icomplete-mode to always see the list of
>> remaining candidates). What do you want the list of completions to be
>> at that point?
> If I type `a` there, the entry would become "bca",
Is "bca" really what you think would be ideal here (where the user
never typed "bc")?
That seems to imply the user would have to use something like C-a C-k in
order to type something completely different from "bc". Most UIs seem
to find such behavior undesirable, AFAIK (in the default Emacs UI we
shun initial inputs altogether, requiring the user to hit M-n if he
wants to edit the default; and in more "mainstream" UIs I know, the
initial input is highlighted/selected at first, and hitting "a" would
first delete it (you'd need to use a cursor key first in order to
de-select the text before hitting "a" in order to keep the "bc")).
>> Some things you can do with the standard completion-UI:
>> - setup your completion table such that it uses `substring` completion
>> by default.
> That sounds like that would work.. can you please point to an example?
You want to setup your completion table so it returns a `metadata` which
includes a `category` of your choice, and then you want to add an entry
for that category to completion-category-defaults.
This is done for example for read-char-by-name.
>> - use `completion-table-in-turn` with the first table being a sub-table
>> which only includes the entries that match "bc".
> I did not understand this suggestion.
You could setup your completion table such that the UI would behave as
follows:
- Imagine your list of completion candidates is abc, bcd, acd, cde.
- And you want to start by filtering for "bc".
- At first the minibuffer says "Entry: "
- At this point the available completions would be "abc" and "bcd".
- Then the user hits "a".
- The minibuffer becomes "Entry: a"
- The available completions become just "abc" and nothing else.
- Then the user hits "ac".
- The minibuffer becomes "Entry: ac"
- The available completions become just "acd" and nothing else.
You'd do this by combining (with the mentioned function) two completion
tables: one containing only the entries that match "bc" and the other
containing all the entries, so when the input matches in the first
table, we stay in the first stable, but if it doesn't, then we search in
the second table.
Stefan
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2018-05-10 22:05 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-05-10 13:09 Canonical way to add a pre-filter to completing-read Kaushal Modi
2018-05-10 14:10 ` Drew Adams
2018-05-10 17:36 ` Kaushal Modi
2018-05-10 15:21 ` Stefan Monnier
2018-05-10 17:19 ` Kaushal Modi
2018-05-10 22:05 ` Stefan Monnier
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).