help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: Canonical way to add a pre-filter to completing-read


From: Drew Adams
Subject: RE: Canonical way to add a pre-filter to completing-read
Date: Thu, 10 May 2018 07:10:05 -0700 (PDT)

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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]