branch: externals/org
commit 762fe766768abef901a20ce469c9803735e11d59
Author: Kenny Chen <[email protected]>
Commit: Ihor Radchenko <[email protected]>

    org-table.el: Cache invisibility spec for `org-string-width'
    
    * etc/ORG-NEWS (New function ~org-string-width-invisibility-spec~):
    Announce new function.
    (~org-string-width~ now takes an optional ~invisibility-spec~
    argument): Announce new optional argument.
    * lisp/org-macs.el (org-string-width): Refactor invisibility spec
    construction into a separate function, and accept the spec as a new
    optional argument.
    (org-string-width-invisibility-spec): New function to construct the
    invisibility spec for ~org-string-width'.
    * lisp/org-table.el (org-table-align): Call
    `org-string-width-invisibility-spec' once and pass the spec to the
    `org-string-width' calls.
---
 etc/ORG-NEWS      | 11 +++++++++++
 lisp/org-macs.el  | 59 ++++++++++++++++++++++++++++++-------------------------
 lisp/org-table.el |  3 ++-
 3 files changed, 45 insertions(+), 28 deletions(-)

diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index cb94c65a9f..fb53c5eba4 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -506,6 +506,11 @@ for source blocks where the appropriate major mode is 
unavailable.
 The new function is like ~org-gnus-no-new-news~, but always opens the
 link in other frame.
 
+*** New function ~org-string-width-invisibility-spec~
+
+The new function constructs an invisibility spec without folds and
+ellipses, suitable for ~org-string-width~. This can be helpful for
+performance if ~org-string-width~ is called multiple times.
 
 *** New command ~org-link-preview~ to preview Org links
 
@@ -597,6 +602,12 @@ accommodate even a single character of the headline, after 
accounting for spaces
 and the surrounding parentheses, it will omit the headline entirely and just
 show as much of the clock as fits under the limit.
 
+*** ~org-string-width~ now takes an optional ~invisibility-spec~ argument
+
+For performance, if the invisibility spec has been constructed, it can
+be passed in as ~invisibility-spec~ instead of having it be
+constructed again.
+
 ** Removed or renamed functions and variables
 
 *** ~org-cycle-display-inline-images~ is renamed to 
~org-cycle-display-link-previews~
diff --git a/lisp/org-macs.el b/lisp/org-macs.el
index 9ae1437641..c5335ab091 100644
--- a/lisp/org-macs.el
+++ b/lisp/org-macs.el
@@ -1171,11 +1171,40 @@ Results may be off sometimes if it cannot handle a given
 `display' value."
   (org--string-from-props string 'display 0 (length string)))
 
-(defun org-string-width (string &optional pixels default-face)
+(defun org-string-width-invisibility-spec ()
+  "Return the invisibility spec of this buffer without folds and ellipses."
+  ;; We need to remove the folds to make sure that folded table
+  ;; alignment is not messed up.
+  (or (and (not (listp buffer-invisibility-spec))
+           buffer-invisibility-spec)
+      (let (result)
+        (dolist (el buffer-invisibility-spec)
+          (unless (or (memq el
+                            '(org-fold-drawer
+                              org-fold-block
+                              org-fold-outline))
+                      (and (listp el)
+                           (memq (car el)
+                                 '(org-fold-drawer
+                                   org-fold-block
+                                   org-fold-outline))))
+            (push
+             ;; Consider ellipsis to have 0 width.
+             ;; It is what Emacs 28+ does, but we have
+             ;; to force it in earlier Emacs versions.
+             (if (and (consp el) (cdr el))
+                 (list (car el))
+               el)
+             result)))
+        result)))
+
+(defun org-string-width (string &optional pixels default-face 
invisibility-spec)
   "Return width of STRING when displayed in the current buffer.
 Return width in pixels when PIXELS is non-nil.
 When PIXELS is nil, DEFAULT-FACE is the face used to calculate relative
-STRING width.  When REFERENCE-FACE is nil, `default' face is used."
+STRING width.  When REFERENCE-FACE is nil, `default' face is used.
+Use INVISIBILITY-SPEC when non-nil, otherwise construct one without
+folds and ellipses."
   (if (and org-string-width--old-emacs (not pixels))
       ;; FIXME: Fallback to old limited version, because
       ;; `window-pixel-width' is buggy in older Emacs.
@@ -1192,31 +1221,7 @@ STRING width.  When REFERENCE-FACE is nil, `default' 
face is used."
     ;; when PIXELS are requested though).
     (unless pixels
       (put-text-property 0 (length string) 'face (or default-face 'default) 
string))
-    (let (;; We need to remove the folds to make sure that folded table
-          ;; alignment is not messed up.
-          (current-invisibility-spec
-           (or (and (not (listp buffer-invisibility-spec))
-                    buffer-invisibility-spec)
-               (let (result)
-                 (dolist (el buffer-invisibility-spec)
-                   (unless (or (memq el
-                                     '(org-fold-drawer
-                                       org-fold-block
-                                       org-fold-outline))
-                               (and (listp el)
-                                    (memq (car el)
-                                          '(org-fold-drawer
-                                            org-fold-block
-                                            org-fold-outline))))
-                     (push
-                      ;; Consider ellipsis to have 0 width.
-                      ;; It is what Emacs 28+ does, but we have
-                      ;; to force it in earlier Emacs versions.
-                      (if (and (consp el) (cdr el))
-                          (list (car el))
-                        el)
-                      result)))
-                 result)))
+    (let ((current-invisibility-spec (or invisibility-spec 
(org-string-width-invisibility-spec)))
           (current-char-property-alias-alist char-property-alias-alist))
       (with-current-buffer (get-buffer-create " *Org string width*" t)
         (setq-local display-line-numbers nil)
diff --git a/lisp/org-table.el b/lisp/org-table.el
index 8fcd3693ea..29c7cbfcba 100644
--- a/lisp/org-table.el
+++ b/lisp/org-table.el
@@ -4411,13 +4411,14 @@ FIELD's width.  Otherwise, it's calculated."
             (widths nil)
             (alignments nil)
             (columns-number 1)
+             (invisibility-spec (org-string-width-invisibility-spec))
              (cell-width-cache (make-hash-table :test 'equal))
              (get-or-compute-cell-width
               (lambda (cell)
                 (or (gethash cell cell-width-cache)
                     (puthash
                      cell
-                     (org-string-width cell nil 'org-table)
+                     (org-string-width cell nil 'org-table invisibility-spec)
                      cell-width-cache)))))
        (if (null rows)
            ;; Table contains only horizontal rules.  Compute the

Reply via email to