From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Eshel Yaron Newsgroups: gmane.emacs.devel Subject: Possible minibuffer completion enhancements Date: Sun, 14 Jan 2024 18:28:27 +0100 Message-ID: Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="37354"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Sun Jan 14 18:29:20 2024 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1rP4IS-0009Y3-DS for ged-emacs-devel@m.gmane-mx.org; Sun, 14 Jan 2024 18:29:20 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rP4Hj-0008Uu-SX; Sun, 14 Jan 2024 12:28:35 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rP4Hh-0008Um-Fy for emacs-devel@gnu.org; Sun, 14 Jan 2024 12:28:33 -0500 Original-Received: from mail.eshelyaron.com ([107.175.124.16] helo=eshelyaron.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rP4Hf-0001cB-7V for emacs-devel@gnu.org; Sun, 14 Jan 2024 12:28:33 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=eshelyaron.com; s=mail; t=1705253310; bh=mDVGwzlaEKoicS+Z4WUvAGsWGN+21AG7+ABhFTnZB/Q=; h=From:To:Subject:Date:From; b=iayUD4c6Prg9WS0iOWxaIHk64aIwF358skN2iMBpKwp2wWbvNrsg6GzK7k+bMzvtJ WKGiula2UFZunrmDkxJ/7N3nEr7uqVTKp9DxHM5ZYMzR0U44ZRvs3cgrOWqF5gPcOj rj9hPgruJLjRPMjCaoWwO0G+iQ5FigQ0ZuiPIxvZIliekblnIv4iJ14TTZKQc3elaL EF4Llsi8YsL9tzlhkLBGMiQNn9V4Gw5LMVIblXwe4DgiJ5EPhzly4RmbTAGdoQYjLK FDQXtExB9TAuv+r3gHTtD3GhvM2El0hRLAamKrQGWzndm8VCIkVqwwcTCsdn224Ssv SNi28g0gzpTeg== Received-SPF: pass client-ip=107.175.124.16; envelope-from=me@eshelyaron.com; helo=eshelyaron.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.devel:314971 Archived-At: Hello Emacs, I have a few enhancements in my working branch that revolve around inspecting and modifying minibuffer completion settings interactively. These additions (described below) are backward compatible, documented, and, at times, even useful. So I propose adding them to upstream. You can try out and examine these changes by cloning from https://git.sr.ht/~eshel/emacs and building Emacs as usual. [ git.sr.ht has been having some connectivity issues in the past few days, to put it mildly, so in case it doesn't work, you can also find the code at git://git.eshelyaron.com/emacs.git ] If any of this looks like it might be appropriate for upstream Emacs, I'll format and submit the relevant parts as individual patches. There are five additions that can be considered, together or separately: 1. Interactively narrow (restrict) the list of minibuffer completions This lets you filter the list of possible completions. A new Info node "Completions Narrowing" describes this feature in full: When there are many possible completion candidates, you may want to narrow the selection to a smaller subset by filtering out some of the options. You can use the commands =E2=80=98C-x n n=E2=80=99 and =E2= =80=98C-x n m=E2=80=99 in the minibuffer to restrict the completions list. Narrowing the list of minibuffer completions is different from narrowing buffers (*note Narrowing::), although the two are conceptually related since both all= ow you to focus on some part of a larger whole. =E2=80=98C-x n n=E2=80=99 (=E2=80=98minibuffer-narrow-completions-to-c= urrent=E2=80=99) restricts the list of possible completions to only include candidates that match the current minibuffer input. This command clears the minibuffer so you c= an type another (partial) input and complete it with completion candidates that also match the previous input. If you call this command with a negative prefix argument (=E2=80=98C-- C-x n n=E2=80=99), it instead e= xcludes all matches for the current input from subsequent completions. =E2=80=98C-x n m=E2=80=99 (=E2=80=98minibuffer-narrow-completions=E2= =80=99) is similar to =E2=80=98C-x n n=E2=80=99, but more versatile. This command restricts the list of possible completions in different ways, depending on what kind of completion candidates you're dealing with. For example, commands that read a symbol name from the minibuffer, such as =E2=80=98C-h f=E2=80=99 and = =E2=80=98C-h o=E2=80=99 (*note Name Help::), let you restrict the completions list with =E2=80=98C-x n m= =E2=80=99 to show only symbols with a given property. *Note (elisp)Symbol Properties::. Similarly, commands that read a buffer name, such as =E2=80=98C-x b=E2= =80=99 (*note Select Buffer::), make =E2=80=98C-x n m=E2=80=99 restrict the completi= ons list by candidate buffer major mode. When the command does not provide a specific way of restricting completion candidates, =E2=80=98C-x n m=E2= =80=99 prompts you for a regular expression and narrows the completions list to only include candidates which match that regular expression. *Note Regexps::. When you narrow the completions list with =E2=80=98C-x n n=E2=80=99 or= with =E2=80=98C-x n m=E2=80=99, Emacs extends the completions heading line with a description of the restriction that is currently in effect (*note Completions Heading Line::). The mode line of the =E2=80=98*Completions*=E2=80=99 buffer = also indicates the restriction with the text =E2=80=98CompsNarrow=E2=80=99. You can appl= y multiple restrictions one after the other to narrow the completions list incrementally. For example, typing =E2=80=98M-x C-x n m foo C-x= n m bar =E2=80=99 shows only commands that match both =E2=80=98foo=E2=80= =99 and =E2=80=98bar=E2=80=99 in the completions list. Use =E2=80=98C-x n w=E2=80=99 (=E2=80=98minibuffer-widen-completions= =E2=80=99) in the minibuffer to remove the restrictions on the list of possible completions that you s= et with =E2=80=98C-x n n=E2=80=99 or with =E2=80=98C-x n m=E2=80=99. =E2= =80=98C-x n w=E2=80=99 prompts you for the description of a current completions restriction, and removes the corresponding restriction. The default candidate is the most recent restriction, and you can use completion to select other restriction descriptions. You can even specify multiple restrictions to remove at once, by separating their descriptions with commas in the minibuffer. If there is only one restriction to begin with, =E2=80=98C-x n w=E2=80= =99 removes it without prompting. If you invoke this command with a prefix argument (=E2=80=98C-u C-x n w=E2=80=99), it removes all restrictions without p= rompting, regardless of how many there are. 2. Interactively sort the list of minibuffer completions This lets you change the order of the completions list by invoking a command in the minibuffer. Here's the gist of it: =E2=80=98C-x C-v=E2=80=99 (=E2=80=98minibuffer-sort-completions=E2=80= =99) changes the order of the completions list. By default, Emacs sorts the list of possible completion candidates in the order that you specify in user option =E2=80=98completions-sort=E2=80=99 (*note Completion Options::). This= command lets you change the order of the current completions list interactively. You c= an invoke it with a negative prefix argument (=E2=80=98C-- C-x C-v=E2=80= =99) to reverse the current order. The user option =E2=80=98minibuffer-completions-sort-o= rders=E2=80=99 determines which orders this command suggests for sorting the completions list. By default, this includes alphabetical sorting, sorting by candidate position in the minibuffer history, and no sorting at all. Some commands that use minibuffer completion also provide additional sorting options that are specifically useful with their completion candidates. For example, during file name completion, as in =E2=80=98C-x C-f=E2=80=99 (*note Visiting::), you can use =E2=80=98C-x= C-v=E2=80=99 to sort candidate file names chronologically by their last modified time. Another possibly interesting detail is that the completions heading line indicates a non-default sorting order; for example, it might say "70 possible completions, sorted alphabetically...". This is customizable via the existing `completions-header-format` option, which is extended accordingly (in a backward compatible manner). 3. Interactively set the completion styles for the current minibuffer This lets you modify the completion styles that the current minibuffer makes use of, on the fly: =E2=80=98C-x /=E2=80=99 (minibuffer-set-completion-styles) lets you se= t the completion styles for the current minibuffer. *Note Completion Styles::. This command prompts you for a list of completion styles, a= nd sets that list as the effective completion styles for following completion operations in the current minibuffer. With a plain prefix argument (=E2=80=98C-u C-x /=E2=80=99), it instead discards all change= s that you made to the current completion styles. With a zero numeric prefix argument (=E2=80=98C-0 C-x /=E2=80=99), it keeps all current completion styles = except the style that produced that current completions list. Conversely, a numeric prefix argument of one (=E2=80=98C-1 C-x /=E2=80=99) says to keep only= the completion style that produced the current completions list, disabling other completion styles for the current minibuffer. ... The mode line of the =E2=80=98*Completions*=E2=80=99 buffer indicates = which completion style produced the listed completion candidates, by showing the name of that style. (For example, the mode line says =E2=80=98Completions[basic]=E2=80=99 when the =E2=80=98basic=E2=80=99 = completion style is in effect.) You can hover over the mode line style indicator with the mouse to see its full description. 4. Interactively replace the separator in `completing-read-multiple` This lets you examine and change the regular expression that matches input separators in a `completing-read-multiple` minibuffer: When displaying the completions list for =E2=80=98completing-read-mult= iple=E2=80=99, the mode line of the =E2=80=98*Completions*=E2=80=99 buffer includes a= n indicator that says =E2=80=98Multi=E2=80=99. Hovering over that indicator with the m= ouse shows help about the current input separator. ... [=E2=80=98crm-change-separator=E2=80=99], bound to =E2=80=98C-x ,=E2= =80=99 in the minibuffer during =E2=80=98completing-read-multiple=E2=80=99, changes the current input = separator. It prompts for a new separator regular expression, and sets the local value of =E2=80=98crm-separator=E2=80=99 to that regular express= ion. With a prefix argument, this command also prompts for a replacement string (that should match the new separator) and replaces all of the existing separators in the minibuffer with that replacement string. 5. Cycling completions convenience commands This adds a dedicated command for cycling completions so you can make use of both cycling and the regular completion behavior at any time. Another new command lets you restore the minibuffer contents to the partial input you had when you started cycling: =E2=80=98C-o=E2=80=99 (=E2=80=98minibuffer-cycle-completion=E2=80=99) = cycles among the list of possible completions. The first time you hit =E2=80=98C-o=E2=80=99, i= t expands your partial input in the minibuffer to the first matching completion candidate. Another =E2=80=98C-o=E2=80=99 replaces the minibuffer cont= ents with the next completion candidate, and repeating =E2=80=98C-o=E2=80=99 lets you cyc= le among all completions for your initial input, wrapping around when you reach the end of the list. While you're cycling, Emacs remembers the initial partial input you started with, and the corresponding set of completion candidates. If you edit a completion candidate in the minibuffer after cycling to it, that tells Emacs to forget about your previous partial input and compute a new set of completion candidates based on your new input the next time you hit =E2=80=98C-o=E2=80=99. You can invoke =E2= =80=98C-o=E2=80=99 with a numeric prefix argument N to cycle N candidates forward at once. A negative N cycles backward instead. A prefix argument of zero (=E2=80=98C-0 C-o= =E2=80=99) switches the cycling direction, so the next =E2=80=98C-o=E2=80=99 presses cycle= backward. =E2=80=98C-l=E2=80=99 (=E2=80=98minibuffer-restore-completion-input=E2= =80=99) restores the minibuffer contents to the (partial) input that you last used for completion in t= he current minibuffer. Commands that complete your input, such as =E2=80= =98=E2=80=99 and =E2=80=98C-o=E2=80=99, record the partial input that you provide t= hem for you to later retrieve it with =E2=80=98C-l=E2=80=99. For example, if you typ= e =E2=80=98M-x bar=E2=80=99 and start cycling with =E2=80=98C-o=E2=80=99, only to realize that you wan= t a candidate that matches =E2=80=98baz=E2=80=99 and not =E2=80=98bar=E2=80=99, then you = can type =E2=80=98C-l=E2=80=99 to restore the minibuffer input to =E2=80=98bar=E2=80=99, change it to =E2=80=98baz= =E2=80=99 and complete again. The overall theme is to provide more control over minibuffer completions while you're using them. This is inspired by Icicles by Drew Adams, although Icicles covers a much wider ground, and my changes aim for compatibility and integration with "vanilla" Emacs completions first. I've tried to pick key bindings that are convenient and don't currently do something particularly useful in the minibuffer, but I'm open for suggestions on this regard. How do people feel about adding something along these lines to Emacs? In general, I'm happy to upstream anything that seems useful/desirable in my working branch, even if I haven't mentioned it here specifically. Best, Eshel