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: Sat, 14 Oct 2023 16:05:11 -0400 Message-ID: <87sf6dx954.fsf@catern.com> References: <87bkd3z9bi.fsf@catern.com> <86cyxjyr1y.fsf@mail.linkov.net> <86r0lxm7um.fsf@mail.linkov.net> 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="31853"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) To: emacs-devel@gnu.org Cancel-Lock: sha1:i347OPzMrJAc77jH3u1Ghmuhd40= Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Sun Oct 15 07:10:24 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 1qrtOR-00085J-IF for ged-emacs-devel@m.gmane-mx.org; Sun, 15 Oct 2023 07:10:23 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qrtNm-0005nS-J1; Sun, 15 Oct 2023 01:09:42 -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 1qrktS-0005bn-AA for emacs-devel@gnu.org; Sat, 14 Oct 2023 16:05:50 -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 1qrktJ-0006At-B5 for emacs-devel@gnu.org; Sat, 14 Oct 2023 16:05:50 -0400 Original-Received: from list by ciao.gmane.io with local (Exim 4.92) (envelope-from ) id 1qrksz-0008wP-H0 for emacs-devel@gnu.org; Sat, 14 Oct 2023 22:05:21 +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: Sun, 15 Oct 2023 01:09:41 -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:311468 Archived-At: --=-=-= Content-Type: text/plain Juri Linkov writes: >>>> It would be nice if there was a built-in customization which caused >>>> *Completions* to update as you type, as long as that buffer is visible. >>>> I imagine such a request has been made before, so what is the obstacle >>>> to adding it? >>> >>> I don't remember what was the obstacle, but here is the previous patch >>> that implements the behavior of zsh and is based on icomplete-mode. >> >> Nice! Although again this is more features than I want - I just want >> *Completions* to automatically update after it opens. > > Probably it's possible to pare it down to less code with less features > that could basically do the same after toggling a new option. Yes, agreed. Taking inspiration from zcomplete, I wrote this patch to provide just this feature, thoughts? --=-=-= Content-Type: text/x-patch Content-Disposition: inline; filename=0001-Add-completions-auto-update.patch >From fef547ece1d5cd3eebbc2fb7f51e51f15cfc2b4a Mon Sep 17 00:00:00 2001 From: Spencer Baugh Date: Sat, 14 Oct 2023 14:27:23 -0400 Subject: [PATCH] Add completions-auto-update It can be useful for the *Completions* buffer to automatically update as you type. That way you can see immediately what the next completion operation will do, even if you've changed text in the buffer since triggering completion. * lisp/minibuffer.el (completions-auto-update): Add. (completions-no-auto-update-commands): Add. (completions--post-command): Add. (minibuffer-completion-help): Add completions--post-command to post-command-hook. --- lisp/minibuffer.el | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 3e30b68d5e9..9995da9e4b7 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -2376,6 +2376,40 @@ completions--fit-window-to-buffer (resize-temp-buffer-window win)) (fit-window-to-buffer win completions-max-height))) +(defcustom completions-auto-update t + "If non-nil, update the *Completions* buffer as you type. + +This only affects the *Completions* buffer if it is already +displayed." + :type '(choice (const :tag "*Completions* doesn't change as you type" nil) + (const :tag "*Completions* updates as you type" t)) + :version "30.1") + +(defconst completions-no-auto-update-commands + '(previous-history-element + next-history-element + previous-line-or-history-element + next-line-or-history-element + completion-at-point + minibuffer-complete-and-exit + minibuffer-force-complete-and-exit + minibuffer-next-completion + minibuffer-previous-completion + minibuffer-choose-completion) + "Commands to skip updating *Completions*") + +(defun completions--post-command () + "Update a displayed *Completions* buffer after a change" + (when completions-auto-update + (while-no-input + (let ((non-essential t)) + (when (and (get-buffer-window "*Completions*" 0) + (not (memq this-command completions-no-auto-update-commands))) + (redisplay) + (if completion-in-region-mode + (completion-help-at-point) + (minibuffer-completion-help))))))) + (defun minibuffer-completion-help (&optional start end) "Display a list of possible completions of the current minibuffer contents." (interactive) @@ -2398,6 +2432,7 @@ minibuffer-completion-help ;; If there are no completions, or if the current input is already ;; the sole completion, then hide (previous&stale) completions. (minibuffer-hide-completions) + (remove-hook 'post-command-hook #'completions--post-command t) (if completions (completion--message "Sole completion") (unless completion-fail-discreetly @@ -2449,6 +2484,9 @@ minibuffer-completion-help (body-function . ,#'(lambda (_window) (with-current-buffer mainbuf + (when completions-auto-update + (add-hook 'post-command-hook #'completions--post-command nil t)) + ;; Remove the base-size tail because `sort' requires a properly ;; nil-terminated list. (when last (setcdr last nil)) -- 2.41.0 --=-=-= Content-Type: text/plain >> 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. --=-=-=--