From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: sbaugh@catern.com Newsgroups: gmane.emacs.devel Subject: Re: Updating *Completions* as you type Date: Tue, 17 Oct 2023 09:48:30 -0400 Message-ID: <87ttqpwea9.fsf@catern.com> References: <87bkd3z9bi.fsf@catern.com> <86cyxjyr1y.fsf@mail.linkov.net> <86r0lxm7um.fsf@mail.linkov.net> <87sf6dx954.fsf@catern.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="34334"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) To: emacs-devel@gnu.org Cancel-Lock: sha1:Let/N2CorpP7qTN/nmxkG6qUDfI= Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Tue Oct 17 16:52:48 2023 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 1qslR9-0008g6-UW for ged-emacs-devel@m.gmane-mx.org; Tue, 17 Oct 2023 16:52:48 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qslQJ-0006cB-Eb; Tue, 17 Oct 2023 10:51:56 -0400 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 1qskRC-0006zT-H1 for emacs-devel@gnu.org; Tue, 17 Oct 2023 09:48:46 -0400 Original-Received: from ciao.gmane.io ([116.202.254.214]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qskRA-0005RC-Fo for emacs-devel@gnu.org; Tue, 17 Oct 2023 09:48:46 -0400 Original-Received: from list by ciao.gmane.io with local (Exim 4.92) (envelope-from ) id 1qskR7-0001gD-Fy for emacs-devel@gnu.org; Tue, 17 Oct 2023 15:48:41 +0200 X-Injected-Via-Gmane: http://gmane.org/ Received-SPF: pass client-ip=116.202.254.214; envelope-from=ged-emacs-devel@m.gmane-mx.org; helo=ciao.gmane.io X-Spam_score_int: -15 X-Spam_score: -1.6 X-Spam_bar: - X-Spam_report: (-1.6 / 5.0 requ) BAYES_00=-1.9, HEADER_FROM_DIFFERENT_DOMAINS=0.25, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Tue, 17 Oct 2023 10:51:49 -0400 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:311538 Archived-At: --=-=-= Content-Type: text/plain sbaugh@catern.com writes: >>> That being said, yes this may be nice. But minibuffer-completion-help >>> already does sort the completions using display-sort-function, just like >>> completion-all-sorted-completions, so what's causing the difference in >>> behavior? >> >> It seems this is implementable in minibuffer-completion-help >> by copying this code from completion-all-sorted-completions: >> >> (setq all (minibuffer--sort-by-position >> (minibuffer--sort-preprocess-history >> (substring string 0 base-size)) >> all)) > >Oh, very interesting! Maybe completions-sort should accept a new symbol >'history to behave this way? > >I already think this would be very nice for project-switch-project, for >example, since I'm often switching between a few related projects. > >Perhaps 'history should break ties by alphabetizing, otherwise >e.g. filenames you haven't visited before would be unsorted randomly. > >Hmm, actually the case of filenames is a bit complex. Because for >filenames, the strings we're completing over don't appear verbatim in >the history. So perhaps read-file-name would need its own specialized >sorting function, which whenever you're completing in some directory, >sorts to the front any files in that directory whose full path appears >in file-name-history. > >>> Honestly the main place I find myself wanting different sorting of >>> completions is for buffer completion - I'd prefer buffers to be sorted >>> by most-recently-used. Maybe we can just add such an option? >> >> Such an option would be nice. Maybe the right way to support it >> is to add a new sort function with the code above. Then the caller >> could provide such a function in the completion metadata. > >Oh, that's also interesting. So there would be a function that the >completion metadata could specify as display-sort-function, which would >have the behavior of sorting based on history? > >That also makes a lot of sense, and would allow commands like >project-switch-project and read-buffer to opt in on a command-by-command >basis, which might be more sensible. > >So maybe adding 'history as a new option for completions-sort isn't a >good idea. Instead we should just add user options for enabling history >sorting for files and buffers. (And perhaps we could just enable >history sorting by default for project-switch-project.) > >Also: it might be nice to switch between history-sorting and >alphabetized-sorting during the course of completion, both for files and >buffers. Maybe we could do that by making a command which puts >completion into a mode where it just ignores the display-sort-function >specified by the completion metadata, and just always uses >completions-sort. On reflection, I think adding a new option for completions-sort is indeed what we should do. Otherwise, we won't get historical sorting for non-programmed completing-read, which is a pretty common kind of completing-read. Here's a patch to do that. We can always add display-sort-functions later for buffers and files, if that ends up being desirable. Also, tangentially, I think probably we should rework minibuffer-complete-history and minibuffer-complete-defaults to be persistent - as in, regular TAB afterwards continues to complete history or defaults. And there should be some way to reset back to normal. That would be a good complement to this completions-sort change, by maybe giving a way to switch on-demand to alphabetical sorting. (I've long thought this would be good and useful, but in particular it's relevant for completions-auto-update since that will otherwise nearly immediately reset the displayed completions back to normal.) --=-=-= Content-Type: text/x-patch Content-Disposition: inline; filename=0001-Add-a-historical-option-to-completions-sort.patch >From b97e311ee42f7f9021b3c0e017636e258dd6d5d9 Mon Sep 17 00:00:00 2001 From: Spencer Baugh Date: Tue, 17 Oct 2023 09:09:55 -0400 Subject: [PATCH] Add a historical option to completions-sort This causes completion to sort based on history. This is useful for getting, e.g., most-recently-used order from C-x b. We only do historical sorting when there's a completion-specific history variable. Otherwise, candidate would be spuriously brought to the front if they just happened to match a string that the user has entered before. Also, the presence of a completion-specific history variable is a decent proxy for "does history matter for this command?"; if there isn't a specific history variable, sorting based on history would probably be undesirable. (Note also that the user can always choose to do historical sorting mid-completion by running minibuffer-complete-history.) * lisp/minibuffer.el (completions-sort): Document 'historical option. (minibuffer-completion-help): Support 'historical option. --- lisp/minibuffer.el | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index f53cd739e2f..782efff80f9 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -1313,14 +1313,26 @@ completion-cycle-threshold (defcustom completions-sort 'alphabetical "Sort candidates in the *Completions* buffer. -The value can be nil to disable sorting, `alphabetical' for -alphabetical sorting or a custom sorting function. The sorting -function takes and returns a list of completion candidate -strings." +Candidate completions in the *Completions* are sorted depending +on the value. + +If nil, sorting is disabled. +If `alphabetical', candidates are sorted alphabetically. +If `historical', candidates are first sorted alphabetically, then +candidates occurring in `minibuffer-history-variable' are moved +to the front based on the order they occur in the history. +If a function, the function is called to sort the candidates. +The sorting function takes and returns a list of completion +candidate strings. + +If the completion-specific metadata provides a +`display-sort-function', that is used instead and this value is +ignored." :type '(choice (const :tag "No sorting" nil) (const :tag "Alphabetical sorting" alphabetical) + (const :tag "Historical sorting" historical) (function :tag "Custom function")) - :version "29.1") + :version "30.1") (defcustom completions-group nil "Enable grouping of completion candidates in the *Completions* buffer. @@ -2510,6 +2522,15 @@ minibuffer-completion-help (pcase completions-sort ('nil completions) ('alphabetical (sort completions #'string-lessp)) + ('historical + (let ((alphabetized (sort completions #'string-lessp))) + ;; Only use history when it's specific to these completions. + (if (eq minibuffer-history-variable 'minibuffer-history) + alphabetized + (minibuffer--sort-by-position + (minibuffer--sort-preprocess-history + (substring string 0 base-size)) + alphabetized)))) (_ (funcall completions-sort completions))))) ;; After sorting, group the candidates using the -- 2.41.0 --=-=-=--