* 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 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 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 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).