From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Spencer Baugh via "Bug reports for GNU Emacs, the Swiss army knife of text editors" Newsgroups: gmane.emacs.bugs Subject: bug#74561: [PATCH] Allow limiting the size of *Completions* Date: Wed, 27 Nov 2024 15:25:19 -0500 Message-ID: Reply-To: Spencer Baugh 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="25872"; mail-complaints-to="usenet@ciao.gmane.io" Cc: dmitry@gutov.dev, juri@linkov.net To: 74561@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Wed Nov 27 21:26:25 2024 Return-path: Envelope-to: geb-bug-gnu-emacs@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 1tGOcC-0006YN-QX for geb-bug-gnu-emacs@m.gmane-mx.org; Wed, 27 Nov 2024 21:26:25 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tGObu-0004sc-MK; Wed, 27 Nov 2024 15:26:06 -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 1tGObs-0004s7-Dk for bug-gnu-emacs@gnu.org; Wed, 27 Nov 2024 15:26:04 -0500 Original-Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1tGObr-000245-3T for bug-gnu-emacs@gnu.org; Wed, 27 Nov 2024 15:26:04 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=debbugs.gnu.org; s=debbugs-gnu-org; h=MIME-Version:Date:From:To:Subject; bh=t5P4N8if2RHQwvM+ETw6Dv1534Uti5eaHBmYjsw9WNA=; b=eNH+u0ESQqTELNq9vPGT0xhSju6NcdsbcFJWHxwc6PI00DjAAQkWLotJcoX6jJHHrRbhRhTJOS1whrj/4OVuanZSZeKiYzAsNAGLQDahDfk9LCljDhiqRMIfNlctCKz3qyNe4DURajpwgq/WZlDARNkzN86TjmsrLWisTh2qpupT8JsC/OW2ljnYcQ3wW1oqb/JyKMRPSKVnGvLNRi+6eWQla3plgJET7J82A3mWOvSVXrh4AAEuOhwic2ARKsTstcxG0WNkyWV9vuknRz/3JfRR3cVZfQEJYWAF0r2nag6pH5qoJscxXJuCk/PLclwfnWs7PiBRVxMZclf/lp0B+g==; Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1tGObq-0000NQ-PJ for bug-gnu-emacs@gnu.org; Wed, 27 Nov 2024 15:26:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Spencer Baugh Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Wed, 27 Nov 2024 20:26:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 74561 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch X-Debbugs-Original-To: bug-gnu-emacs@gnu.org Original-Received: via spool by submit@debbugs.gnu.org id=B.17327391291385 (code B ref -1); Wed, 27 Nov 2024 20:26:02 +0000 Original-Received: (at submit) by debbugs.gnu.org; 27 Nov 2024 20:25:29 +0000 Original-Received: from localhost ([127.0.0.1]:34765 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tGObI-0000MH-HT for submit@debbugs.gnu.org; Wed, 27 Nov 2024 15:25:29 -0500 Original-Received: from lists.gnu.org ([209.51.188.17]:33874) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tGObF-0000M5-LX for submit@debbugs.gnu.org; Wed, 27 Nov 2024 15:25:27 -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 1tGObE-0004qS-01 for bug-gnu-emacs@gnu.org; Wed, 27 Nov 2024 15:25:24 -0500 Original-Received: from mxout5.mail.janestreet.com ([64.215.233.18]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tGObC-0001fS-5t for bug-gnu-emacs@gnu.org; Wed, 27 Nov 2024 15:25:23 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=janestreet.com; s=waixah; t=1732739120; bh=t5P4N8if2RHQwvM+ETw6Dv1534Uti5eaHBmYjsw9WNA=; h=From:To:Cc:Subject:Date; b=Bodi7dfGmi+qzWnaYw1jsEPduK1HBRkAKT+43w4A44WqFI9vKoOBu56Fw6BrimJpK dPsxg+/hueyUE0wxn4QdBGgmp8CjFv0o26SgWkYtR8rT/7wsune3njv09sw/EFegb4 V69SaDvfMKTElsEiBmZgW2uU8PEBzpUH+5QE1Tu6QknvqS6s7liNrDZgjwv3BaNXYe +Zk+lDO0wMBDSCWIMypsmdjEuefkHJ8AO4uWmsN8CDo44v5+BzMdBISLq2YHuHhoT7 1WHKN2z/cnG4LStestvUpyQz8OW1E3I6niI8grYsLZmU/CZHpJ9UdpMG/N2hyVoffW v7InutHm/B+qw== Received-SPF: pass client-ip=64.215.233.18; envelope-from=sbaugh@janestreet.com; helo=mxout5.mail.janestreet.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, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.bugs:296039 Archived-At: --=-=-= Content-Type: text/plain Tags: patch >From profiling, the main bottleneck in completion over large completion sets is display-completion-list, when there are many available candidates. For example, in my large monorepo, when completing over the 589196 files or the 73897 branches, even with the candidates narrowed down by typing some prefix to complete, TAB (when it shows *Completions*) or ? is slow, mostly in display-completion-list. By adding completions-list-max with a very large default, performance is greatly improved in these situations without impacting the normal case of completion on reasonably sized sets. Limiting the work done by display-completion-list is also important for packages which auto-update *Completions* inside while-no-input: since display-completion-list doesn't do anything which reads input, while-no-input won't interrupt it. Such packages can instead just bind completions-list-max to a smaller value. * lisp/minibuffer.el (display-completion-list): Add FULL-COUNT argument. (completions-list-max): Add. (minibuffer-completion-help): Truncate completions based on completions-list-max. In GNU Emacs 29.2.50 (build 9, x86_64-pc-linux-gnu, X toolkit, cairo version 1.15.12, Xaw scroll bars) of 2024-11-20 built on igm-qws-u22796a Repository revision: 28dc0b6f9987e0def7dff4deaa23aa60f021d2a7 Repository branch: emacs-29 Windowing system distributor 'The X.Org Foundation', version 11.0.12011000 System Description: Rocky Linux 8.10 (Green Obsidian) Configured using: 'configure --with-x-toolkit=lucid --without-gpm --without-gconf --without-selinux --without-imagemagick --with-modules --with-gif=no --with-tree-sitter --with-native-compilation=aot PKG_CONFIG_PATH=/usr/local/home/garnish/libtree-sitter/0.22.6-1/lib/pkgconfig/' --=-=-= Content-Type: text/patch Content-Disposition: attachment; filename=0001-Allow-limiting-the-size-of-Completions.patch >From 808b1a6d01fcd2d2cc03324aa9826b3160047653 Mon Sep 17 00:00:00 2001 From: Spencer Baugh Date: Thu, 14 Nov 2024 17:14:10 -0500 Subject: [PATCH] Allow limiting the size of *Completions* >From profiling, the main bottleneck in completion over large completion sets is display-completion-list, when there are many available candidates. For example, in my large monorepo, when completing over the 589196 files or the 73897 branches, even with the candidates narrowed down by typing some prefix to complete, TAB (when it shows *Completions*) or ? is slow, mostly in display-completion-list. By adding completions-list-max with a very large default, performance is greatly improved in these situations without impacting the normal case of completion on reasonably sized sets. Limiting the work done by display-completion-list is also important for packages which auto-update *Completions* inside while-no-input: since display-completion-list doesn't do anything which reads input, while-no-input won't interrupt it. Such packages can instead just bind completions-list-max to a smaller value. * lisp/minibuffer.el (display-completion-list): Add FULL-COUNT argument. (completions-list-max): Add. (minibuffer-completion-help): Truncate completions based on completions-list-max. --- lisp/minibuffer.el | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 5d11064d900..8078e1603ae 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -2354,7 +2354,7 @@ completion-hilit-commonality completions) base-size)))) -(defun display-completion-list (completions &optional common-substring group-fun) +(defun display-completion-list (completions &optional common-substring group-fun full-count) "Display the list of completions, COMPLETIONS, using `standard-output'. Each element may be just a symbol or string or may be a list of two strings to be printed as if concatenated. @@ -2366,7 +2366,9 @@ display-completion-list At the end, this runs the normal hook `completion-setup-hook'. It can find the completion buffer in `standard-output'. GROUP-FUN is a `group-function' used for grouping the completion -candidates." +candidates. +If FULL-COUNT is non-nil, it's used as the total number of +completions." (declare (advertised-calling-convention (completions) "24.4")) (if common-substring (setq completions (completion-hilit-commonality @@ -2379,17 +2381,24 @@ display-completion-list (let ((standard-output (current-buffer)) (completion-setup-hook nil)) (with-suppressed-warnings ((callargs display-completion-list)) - (display-completion-list completions common-substring group-fun))) + (display-completion-list completions common-substring group-fun full-count))) (princ (buffer-string))) (with-current-buffer standard-output (goto-char (point-max)) (if completions-header-format - (insert (format completions-header-format (length completions))) + (insert (format completions-header-format (or full-count (length completions)))) (unless completion-show-help ;; Ensure beginning-of-buffer isn't a completion. (insert (propertize "\n" 'face '(:height 0))))) - (completion--insert-strings completions group-fun))) + (completion--insert-strings completions group-fun) + (when (and full-count (/= full-count (length completions))) + (newline) + (insert (propertize + (format "Displaying %s of %s possible completions.\n" + (length completions) full-count) + 'face + 'shadow))))) (run-hooks 'completion-setup-hook) nil) @@ -2455,6 +2464,15 @@ completions--fit-window-to-buffer (resize-temp-buffer-window win)) (fit-window-to-buffer win completions-max-height))) +(defcustom completions-list-max 10000 + "Maximum number of completions for `minibuffer-completion-help' to list. + +After the completions are sorted, any beyond this amount are +discarded and a message about truncation is inserted. This can +improve performance when displaying large numbers of completions." + :type 'number + :version "31.1") + (defcustom completion-auto-deselect t "If non-nil, deselect current completion candidate when you type in minibuffer. @@ -2554,7 +2572,8 @@ minibuffer-completion-help ;; window, mark it as softly-dedicated, so bury-buffer in ;; minibuffer-hide-completions will know whether to ;; delete the window or not. - (display-buffer-mark-dedicated 'soft)) + (display-buffer-mark-dedicated 'soft) + full-count) (with-current-buffer-window "*Completions*" ;; This is a copy of `display-buffer-fallback-action' @@ -2610,6 +2629,11 @@ minibuffer-completion-help (_ completions-group-sort)) completions))) + (when completions-list-max + (setq full-count (length completions)) + (when (< completions-list-max full-count) + (setq completions (take completions-list-max completions)))) + (cond (aff-fun (setq completions @@ -2661,7 +2685,7 @@ minibuffer-completion-help (if (eq (car bounds) (length result)) 'exact 'finished)))))) - (display-completion-list completions nil group-fun) + (display-completion-list completions nil group-fun full-count) (when current-candidate-and-offset (with-current-buffer standard-output (when-let* ((match (text-property-search-forward -- 2.39.3 --=-=-=--