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

    org-table.el: Cache cell width when aligning tables
    
    * lisp/org-table.el (org-table-align): Cache `org-string-width' results
    and reuse when possible instead of calling it for every cell, twice.
    (org-table--align-field): Accept a new optional argument for the field
    width.
---
 lisp/org-table.el | 33 ++++++++++++++++++++++++---------
 1 file changed, 24 insertions(+), 9 deletions(-)

diff --git a/lisp/org-table.el b/lisp/org-table.el
index 4a84ab147e..8fcd3693ea 100644
--- a/lisp/org-table.el
+++ b/lisp/org-table.el
@@ -4376,11 +4376,12 @@ extension of the given file name, and finally on the 
variable
        (user-error "TABLE_EXPORT_FORMAT invalid")))))
 
 ;;;###autoload
-(defun org-table--align-field (field width align)
+(defun org-table--align-field (field width align &optional field-width)
   "Format FIELD according to column WIDTH and alignment ALIGN.
 FIELD is a string.  WIDTH is a number.  ALIGN is either \"c\",
-\"l\" or\"r\"."
-  (let* ((spaces (- width (org-string-width field nil 'org-table)))
+\"l\" or\"r\".  If FIELD-WIDTH is non-nil, then it's used as
+FIELD's width.  Otherwise, it's calculated."
+  (let* ((spaces (- width (or field-width (org-string-width field nil 
'org-table))))
         (prefix (pcase align
                   ("l" "")
                   ("r" (make-string spaces ?\s))
@@ -4409,7 +4410,15 @@ FIELD is a string.  WIDTH is a number.  ALIGN is either 
\"c\",
              (rows (remq 'hline table))
             (widths nil)
             (alignments nil)
-            (columns-number 1))
+            (columns-number 1)
+             (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)
+                     cell-width-cache)))))
        (if (null rows)
            ;; Table contains only horizontal rules.  Compute the
            ;; number of columns anyway, and choose an arbitrary width
@@ -4429,7 +4438,7 @@ FIELD is a string.  WIDTH is a number.  ALIGN is either 
\"c\",
                  (non-empty 0))
              (dolist (row rows)
                (let ((cell (or (nth i row) "")))
-                 (setq max-width (max max-width (org-string-width cell nil 
'org-table)))
+                 (setq max-width (max max-width (funcall 
get-or-compute-cell-width cell)))
                  (cond (fixed-align? nil)
                        ((equal cell "") nil)
                        ((string-match "\\`<\\([lrc]\\)[0-9]*>\\'" cell)
@@ -4470,10 +4479,16 @@ FIELD is a string.  WIDTH is a number.  ALIGN is either 
\"c\",
                                                  (append row
                                                          (make-list offset 
"")))))
                                   (mapconcat #'identity
-                                             (cl-mapcar 
#'org-table--align-field
-                                                        fields
-                                                        widths
-                                                        alignments)
+                                             (cl-mapcar
+                                               (lambda (field width alignment)
+                                                 (org-table--align-field
+                                                  field
+                                                  width
+                                                  alignment
+                                                  (funcall 
get-or-compute-cell-width field)))
+                                              fields
+                                              widths
+                                              alignments)
                                              "|")))
                               "|")))
                  (if (equal new previous)

Reply via email to