From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <emacs-orgmode-bounces+larch=yhetil.org@gnu.org>
Received: from mp0.migadu.com ([2001:41d0:303:5f26::])
	(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits))
	by ms8.migadu.com with LMTPS
	id cBcREtBTnWV22gAAkFu2QA
	(envelope-from <emacs-orgmode-bounces+larch=yhetil.org@gnu.org>)
	for <larch@yhetil.org>; Tue, 09 Jan 2024 15:10:24 +0100
Received: from aspmx1.migadu.com ([2001:41d0:403:58f0::])
	(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits))
	by mp0.migadu.com with LMTPS
	id cK9pDdBTnWWeQQAAqHPOHw
	(envelope-from <emacs-orgmode-bounces+larch=yhetil.org@gnu.org>)
	for <larch@yhetil.org>; Tue, 09 Jan 2024 15:10:24 +0100
X-Envelope-To: larch@yhetil.org
Authentication-Results: aspmx1.migadu.com;
	dkim=pass header.d=posteo.net header.s=2017 header.b=KpjZ8JrP;
	spf=pass (aspmx1.migadu.com: domain of "emacs-orgmode-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="emacs-orgmode-bounces+larch=yhetil.org@gnu.org";
	dmarc=pass (policy=none) header.from=posteo.net
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org;
	s=key1; t=1704809424;
	h=from:from:sender:sender:reply-to:subject:subject:date:date:
	 message-id:message-id:to:to:cc:cc:mime-version:mime-version:
	 content-type:content-type:in-reply-to:in-reply-to:
	 references:references:list-id:list-help:list-unsubscribe:
	 list-subscribe:list-post:dkim-signature;
	bh=VCXCDCmR0iIwrbjsvehQnnRdho5UI68BDOjDMNOGv+Q=;
	b=hzJfqhScfdLSq1qlf5Kd9RYUizpLEn1IXCtjq270Upq8qE5obr4wZhb4UxIUgsUktNh20a
	QhgAKEjc9SbfzJQq0b+R+eK+ZJSpQXa+vpSOzybriCqALUV2Za8DCL9Y2U1H/nQeP88cS4
	ueRVvc+RTTls4Shfp7+yScyDYvz5Gy9vb8larJyZd4R6vTpNrbpGrX4ZIo+bCyCppRJWmQ
	CW29BBOGGhEPMUEozD0dynbH/UXu7NIvQxFDGtEBck8JGixs2oyFJqG66qvqgeBNKrLU8/
	xmBI15OsMc9bDQ3thzwObGPXzu9MWKIw2qgOYd21MFJqYi6+hhSQzQepAo6wjw==
ARC-Seal: i=1; s=key1; d=yhetil.org; t=1704809424; a=rsa-sha256; cv=none;
	b=a2JJFrOmbTBKumGgHQnfLMra0z9RFI5awxXXZmcVTBVAzSy5ecC1f+eIMsdRjI/iWOYlTU
	ABowIbFb4oJJL6cqJMOGCda4OtEVEWMdINvYz1J+fQkwIV02PqUg9Qk9dqW+8vi61lH2RN
	BoKPLwKth3sU0q+gXMVFJi5VjgLBrXC7K2RGZkyjGJRqvC7PLzmj3/rlOUuCHXzxN+cOHM
	m8HR8HvaTRNaGeoDzX3T/cDVIpCuhpf7WbXOQV183eUREpd44dSaGyKST+gYfqHVovQKNX
	ZG8w9U7tRsOTW1L3RzQ0+Oe/X+/s1eh0ml7Euzq9I+AA5XPy6QH3+MqM78GpoA==
ARC-Authentication-Results: i=1;
	aspmx1.migadu.com;
	dkim=pass header.d=posteo.net header.s=2017 header.b=KpjZ8JrP;
	spf=pass (aspmx1.migadu.com: domain of "emacs-orgmode-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="emacs-orgmode-bounces+larch=yhetil.org@gnu.org";
	dmarc=pass (policy=none) header.from=posteo.net
Received: from lists.gnu.org (lists.gnu.org [209.51.188.17])
	(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
	(No client certificate requested)
	by aspmx1.migadu.com (Postfix) with ESMTPS id 3755D385B8
	for <larch@yhetil.org>; Tue,  9 Jan 2024 15:10:23 +0100 (CET)
Received: from localhost ([::1] helo=lists1p.gnu.org)
	by lists.gnu.org with esmtp (Exim 4.90_1)
	(envelope-from <emacs-orgmode-bounces@gnu.org>)
	id 1rNCnG-0007M3-BF; Tue, 09 Jan 2024 09:09:26 -0500
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 <yantar92@posteo.net>)
 id 1rNCnE-0007Ll-5j
 for emacs-orgmode@gnu.org; Tue, 09 Jan 2024 09:09:24 -0500
Received: from mout01.posteo.de ([185.67.36.65])
 by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.90_1) (envelope-from <yantar92@posteo.net>)
 id 1rNCn9-0008S8-Ch
 for emacs-orgmode@gnu.org; Tue, 09 Jan 2024 09:09:23 -0500
Received: from submission (posteo.de [185.67.36.169]) 
 by mout01.posteo.de (Postfix) with ESMTPS id 956E5240027
 for <emacs-orgmode@gnu.org>; Tue,  9 Jan 2024 15:09:14 +0100 (CET)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=posteo.net; s=2017;
 t=1704809354; bh=ggbK45bVBXSMsDNNZsWSOgthTEyJ2/FW4GgfDa0kLZA=;
 h=From:To:Cc:Subject:Date:Message-ID:MIME-Version:From;
 b=KpjZ8JrParepSOm9lyYaMKegwsVw4nqGVjIJpX46J2t3PnWWJl6x0dOsdzmrvxyUK
 E2YGQounKZwjvco/SWU8BtX4JFGaQIXAaT/52gAFGZPtdmkADRRmFhZbhmC+kj7u+P
 PoUG5qPKGz3dir7Rib19x/ngk+MowkGwKtw9lY61iP3NjRJrK4J+x13oTQ5yPg661G
 gTYe8lFTiihXhdu0PHigRK3O7XIA3M+x4DiIeN2dxWCxwiSaKJI9OMSjwIsihdIv2J
 Xz/0nH9q9VykwZy8hqJhlApwYB+9gSMYm/WfFa+0klZRTKDozkKc+zKpKXtFcf/7Vv
 JdoOv7WGz6Vhg==
Received: from customer (localhost [127.0.0.1])
 by submission (posteo.de) with ESMTPSA id 4T8XqF5lcvz9rxK;
 Tue,  9 Jan 2024 15:09:13 +0100 (CET)
From: Ihor Radchenko <yantar92@posteo.net>
To: "Christopher M. Miles" <numbchild@gmail.com>
Cc: Org-mode <emacs-orgmode@gnu.org>
Subject: [PATCH v6] Re: Improve the performance of `org-set-tags-command` on
 large `org-tag-alist`
In-Reply-To: <87pm5boofs.fsf@localhost>
References: <CAL1eYuK7GUx_=47e8+N5Jh+ZJnDexY+CDMUjPjJHNmcMiVVRrQ@mail.gmail.com>
 <87a5y8iiak.fsf@localhost> <645fc094.170a0220.4d545.38e1@mx.google.com>
 <87wn1cgjij.fsf@localhost> <64604168.170a0220.99926.5b4f@mx.google.com>
 <87lehrgwqn.fsf@localhost> <6460f5e3.630a0220.b9085.17d2@mx.google.com>
 <87ilcvdknx.fsf@localhost> <64611586.a70a0220.53db4.4151@mx.google.com>
 <871qjiiziz.fsf@localhost> <64612e34.170a0220.28faa.5dcb@mx.google.com>
 <87v8gthnc9.fsf@localhost> <64624762.170a0220.fd372.5c0d@mx.google.com>
 <64625a39.620a0220.e2d74.706d@mx.google.com> <87v8gs4o88.fsf@localhost>
 <646375bd.170a0220.b1c70.dbf1@mx.google.com> <87o7mk3y72.fsf@localhost>
 <64646d12.170a0220.b780c.b216@mx.google.com> <87sfa9p0sy.fsf@localhost>
 <64a000ea.170a0220.250a9.7355@mx.google.com> <87pm5boofs.fsf@localhost>
Date: Tue, 09 Jan 2024 14:12:25 +0000
Message-ID: <87frz6y4s6.fsf@localhost>
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="=-=-="
Received-SPF: pass client-ip=185.67.36.65; envelope-from=yantar92@posteo.net;
 helo=mout01.posteo.de
X-Spam_score_int: -43
X-Spam_score: -4.4
X-Spam_bar: ----
X-Spam_report: (-4.4 / 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_MED=-2.3, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001,
 SPF_HELO_NONE=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-orgmode@gnu.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: "General discussions about Org-mode." <emacs-orgmode.gnu.org>
List-Unsubscribe: <https://lists.gnu.org/mailman/options/emacs-orgmode>,
 <mailto:emacs-orgmode-request@gnu.org?subject=unsubscribe>
List-Archive: <https://lists.gnu.org/archive/html/emacs-orgmode>
List-Post: <mailto:emacs-orgmode@gnu.org>
List-Help: <mailto:emacs-orgmode-request@gnu.org?subject=help>
List-Subscribe: <https://lists.gnu.org/mailman/listinfo/emacs-orgmode>,
 <mailto:emacs-orgmode-request@gnu.org?subject=subscribe>
Errors-To: emacs-orgmode-bounces+larch=yhetil.org@gnu.org
Sender: emacs-orgmode-bounces+larch=yhetil.org@gnu.org
X-Migadu-Flow: FLOW_IN
X-Migadu-Country: US
X-Migadu-Spam-Score: -8.00
X-Spam-Score: -8.00
X-Migadu-Queue-Id: 3755D385B8
X-Migadu-Scanner: mx11.migadu.com
X-TUID: 2ttzavt41PI5

--=-=-=
Content-Type: text/plain

I have incorporated my suggestions into an updated patch.

Note that I dropped the condition that new customization only works for
org-use-fast-tag-selection = 'auto.

Please let me know if anything you wanted to see in this patch is
missing.


--=-=-=
Content-Type: text/x-patch
Content-Disposition: inline;
 filename=v6-0001-org-fast-tag-selection-Limit-the-number-of-displa.patch

>From 79fee381dc5ecbaed5bfe3ba66b11bb2a02aa97f Mon Sep 17 00:00:00 2001
Message-ID: <79fee381dc5ecbaed5bfe3ba66b11bb2a02aa97f.1704809509.git.yantar92@posteo.net>
From: stardiviner <numbchild@gmail.com>
Date: Sat, 1 Jul 2023 18:29:02 +0800
Subject: [PATCH v6] org-fast-tag-selection: Limit the number of displayed tags

* lisp/org.el (org-fast-tag-selection): Do not print tags without
explicit bindings and tags outside groups when the number of displayed
tags exceeds new customization.
* lisp/org.el (org-fast-tag-selection-maximum-tags): Add new custom
option to set maximum tags number for fast tag selection.
(org--fast-tag-selection-keys): New internal variable holding keys
available for auto-assigning tag bindings.
* doc/org-manual.org (org-fast-tag-selection-maximum-tags): Add new
custom option documentation.
* etc/ORG-NEWS: Declare this new custom option.

Co-Authored-by: Ihor Radchenko <yantar92@posteo.net>
Link: https://list.orgmode.org/orgmode/CAL1eYuK7GUx_=47e8+N5Jh+ZJnDexY+CDMUjPjJHNmcMiVVRrQ@mail.gmail.com/
---
 doc/org-manual.org |  5 ++++
 etc/ORG-NEWS       |  5 ++++
 lisp/org.el        | 73 +++++++++++++++++++++++++++++++++++-----------
 3 files changed, 66 insertions(+), 17 deletions(-)

diff --git a/doc/org-manual.org b/doc/org-manual.org
index acc6d07ff..bb4b6e625 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -5090,6 +5090,11 @@ ** Setting Tags
 the special window is not even shown for single-key tag selection, it
 comes up only when you press an extra {{{kbd(C-c)}}}.
 
+#+vindex: org-fast-tag-selection-maximum-tags
+The number of tags displayed in the fast tag selection interface is
+limited by ~org-fast-tag-selection-maximum-tags~ to avoid running out
+of keyboard keys.  You can customize this variable.
+
 ** Tag Hierarchy
 :PROPERTIES:
 :DESCRIPTION: Create a hierarchy of tags.
diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index b808357d8..847ddf614 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -371,6 +371,11 @@ The change is breaking when ~org-use-property-inheritance~ is set to ~t~.
 
 The =TEST= parameter is better served by Emacs debugging tools.
 ** New and changed options
+*** New option ~org-fast-tag-selection-maximum-tags~
+
+You can now limit the total number of tags displayed in the fast tag
+selection interface.  Useful in buffers with huge number of tags.
+
 *** New variable ~org-clock-out-removed-last-clock~
 
 The variable is intended to be used by ~org-clock-out-hook~.  It is a
diff --git a/lisp/org.el b/lisp/org.el
index 57379c26a..3d3099c48 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -2790,6 +2790,25 @@ (defcustom org-fast-tag-selection-single-key nil
 	  (const :tag "Yes" t)
 	  (const :tag "Expert" expert)))
 
+(defvar org--fast-tag-selection-keys
+  (string-to-list "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~")
+  "List of chars to be used as bindings by `org-fast-tag-selection'.")
+
+(defcustom org-fast-tag-selection-maximum-tags (length org--fast-tag-selection-keys)
+  "Set the maximum tags number for fast tag selection.
+This variable only affects tags without explicit key bindings outside
+tag groups.  All the tags with user bindings and all the tags
+corresponding to tag groups are always displayed.
+
+When the number of tags with bindings + tags inside tag groups is
+smaller than `org-fast-tag-selection-maximum-tags', tags without
+explicit bindings will be assigned a binding and displayed up to the
+limit."
+  :package-version '(Org . "9.7")
+  :group 'org-tags
+  :type 'number
+  :safe #'numberp)
+
 (defvar org-fast-tag-selection-include-todo nil
   "Non-nil means fast tags selection interface will also offer TODO states.
 This is an undocumented feature, you should not rely on it.")
@@ -11983,9 +12002,8 @@ (defun org-fast-tag-selection (current-tags inherited-tags tag-table &optional t
 	 (inherited-face 'org-done)
 	 (current-face 'org-todo)
          ;; Characters available for auto-assignment.
-         (tag-binding-char-list
-          (eval-when-compile
-            (string-to-list "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~")))
+         (tag-binding-char-list org--fast-tag-selection-keys)
+         (tag-binding-chars-left org-fast-tag-selection-maximum-tags)
          field-number ; current tag column in the completion buffer.
          tag-binding-spec ; Alist element.
          current-tag current-tag-char auto-tag-char
@@ -11995,6 +12013,22 @@ (defun org-fast-tag-selection (current-tags inherited-tags tag-table &optional t
 	 (exit-after-next org-fast-tag-selection-single-key)
 	 (done-keywords org-done-keywords)
 	 groups ingroup intaggroup)
+    ;; Calculate the number of tags with explicit user bindings + tags in groups.
+    ;; These tags will be displayed unconditionally.  Other tags will
+    ;; be displayed only when there are free bindings left according
+    ;; to `org-fast-tag-selection-maximum-tags'.
+    (dolist (tag-binding-spec tag-alist)
+      (pcase tag-binding-spec
+        (`((or :startgroup :startgrouptag) . _)
+         (setq ingroup t))
+        (`((or :endgroup :endgrouptag) . _)
+         (setq ingroup nil))
+        ((guard (cdr tag-binding-spec))
+         (cl-decf tag-binding-chars-left))
+        (`((or :newline :grouptags))) ; pass
+        ((guard ingroup)
+         (cl-decf tag-binding-chars-left))))
+    (setq ingroup nil) ; It t, it means malformed tag alist.  Reset just in case.
     ;; Move global `org-tags-overlay' overlay to current heading.
     ;; Calls to `org-set-current-tags-overlay' will take care about
     ;; updating the overlay text.
@@ -12083,6 +12117,9 @@ (defun org-fast-tag-selection (current-tags inherited-tags tag-table &optional t
 	     (if (cdr tag-binding-spec)
                  ;; Custom binding.
 		 (setq current-tag-char (cdr tag-binding-spec))
+               ;; No auto-binding.  Update `tag-binding-chars-left'.
+               (unless (or ingroup intaggroup) ; groups are always displayed.
+                 (cl-decf tag-binding-chars-left))
 	       ;; Automatically assign a character according to the tag string.
 	       (setq auto-tag-char
                      (string-to-char
@@ -12116,20 +12153,22 @@ (defun org-fast-tag-selection (current-tags inherited-tags tag-table &optional t
 				               ((member current-tag inherited-tags) inherited-face))))
 	     (when (equal (caar tag-alist) :grouptags)
 	       (org-add-props current-tag nil 'face 'org-tag-group))
-             ;; Insert the tag.
-	     (when (and (zerop field-number) (not ingroup) (not intaggroup)) (insert "  "))
-	     (insert "[" current-tag-char "] " current-tag
-                     ;; Fill spaces up to FIELD-WIDTH.
-                     (make-string
-		      (- field-width 4 (length current-tag)) ?\ ))
-             ;; Record tag and the binding/auto-binding.
-	     (push (cons current-tag current-tag-char) tag-table-local)
-             ;; Last column in the row.
-	     (when (= (cl-incf field-number) (/ (- (window-width) 4) field-width))
-	       (unless (memq (caar tag-alist) '(:endgroup :endgrouptag))
-	         (insert "\n")
-	         (when (or ingroup intaggroup) (insert "  ")))
-	       (setq field-number 0)))))
+             ;; Respect `org-fast-tag-selection-maximum-tags'.
+             (when (or ingroup intaggroup (cdr tag-binding-spec) (> tag-binding-chars-left 0))
+               ;; Insert the tag.
+	       (when (and (zerop field-number) (not ingroup) (not intaggroup)) (insert "  "))
+	       (insert "[" current-tag-char "] " current-tag
+                       ;; Fill spaces up to FIELD-WIDTH.
+                       (make-string
+		        (- field-width 4 (length current-tag)) ?\ ))
+               ;; Record tag and the binding/auto-binding.
+	       (push (cons current-tag current-tag-char) tag-table-local)
+               ;; Last column in the row.
+	       (when (= (cl-incf field-number) (/ (- (window-width) 4) field-width))
+	         (unless (memq (caar tag-alist) '(:endgroup :endgrouptag))
+	           (insert "\n")
+	           (when (or ingroup intaggroup) (insert "  ")))
+	         (setq field-number 0))))))
         (insert "\n")
         ;; Keep the tags in order displayed.  Will be used later for sorting.
         (setq tag-table-local (nreverse tag-table-local))
-- 
2.43.0


--=-=-=
Content-Type: text/plain


-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>

--=-=-=--