Ihor Radchenko <[email protected]> writes: > Slawomir Grochowski <[email protected]> writes: >> - (let* ((pos (match-beginning 0)) >> ... >> - (summary >> - (org-columns--put-summary pos spec summary) >> ... >> + (value (cond >> + (summary (org-columns--put-summary (point) spec >> summary) > > Is there any specific reason why you removed using saved POS for > `org-columne--put-summary'?
I was simply working on a maximally simplified version of the code while developing this. Saving the position to a separate variable seemed unnecessary to me at the time, so when I later ported my changes to the main branch, I just left it out. Since you pointed it out, I agree it makes sense to restore it just to be safe against unexpected point movements. I've attached the updated patch. Best, -- Slawomir Grochowski
From 2a94f5f75c04f936a11cda8b8e5da90b843f3d30 Mon Sep 17 00:00:00 2001 From: Slawomir Grochowski <[email protected]> Date: Thu, 20 Aug 2026 15:10:54 +0200 Subject: [PATCH] ; org-colview: Simplify column summary computation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * lisp/org-colview.el (org-columns--extend-values-by-level) (org-columns--values-below-level) (org-columns--clear-values-below-level): Remove. (org-columns--compute-spec): Use a stack of level-value pairs instead of a dynamically resized vector and level-clearing loops. Using a stack significantly simplifies the code and improves readability by eliminating three auxiliary helper functions, manual vector resizing, and nested level-clearing loops. It also eliminates the overhead of iterating over deeper levels when ascending the outline tree. The speedup scales with the depth of the hierarchy (up to 5×–10× on deep trees): Benchmark (10 runs each, median times for summary computation) 5 summary columns (depth 5): Headings Depth Old (vector) New (stack) Speedup ────────────────────────────────────────────────────── 10 5 0.00490 s 0.00214 s 2.3× 100 5 0.04935 s 0.01607 s 3.1× 500 5 0.25625 s 0.13464 s 1.9× 1000 5 0.56025 s 0.26654 s 2.1× 2000 5 1.14261 s 0.74478 s 1.5× 10 summary columns (deep hierarchy, depth 10): Headings Depth Old (vector) New (stack) Speedup ────────────────────────────────────────────────────── 100 10 0.26293 s 0.02592 s 10.1× 500 10 0.77635 s 0.15476 s 5.0× 1000 10 1.14439 s 0.23697 s 4.8× 2000 10 2.37339 s 0.47034 s 5.0× Scaling across hierarchy depth (1000 headings, 5 summary columns): Headings Depth Old (vector) New (stack) Speedup ────────────────────────────────────────────────────── 1000 4 0.55512 s 0.30566 s 1.8× 1000 8 1.06393 s 0.22224 s 4.8× 1000 16 0.57331 s 0.09688 s 5.9× 1000 30 0.63103 s 0.09008 s 7.0× Refactoring: Inline Function, Consolidate Conditional Expression. No behavior change. --- lisp/org-colview.el | 78 ++++++++++++++------------------------------- 1 file changed, 24 insertions(+), 54 deletions(-) diff --git a/lisp/org-colview.el b/lisp/org-colview.el index d5548802f..9556c2957 100644 --- a/lisp/org-colview.el +++ b/lisp/org-colview.el @@ -1549,35 +1549,17 @@ they have their own way to be computed." (and (not (member property org-special-properties)) (org-columns--spec-operator spec)))) -(defun org-columns--extend-values-by-level (values-by-level level) - "Return VALUES-BY-LEVEL large enough to include LEVEL." - (if (< level (length values-by-level)) values-by-level - (vconcat values-by-level - (make-vector (- (1+ level) (length values-by-level)) nil)))) - -(defun org-columns--values-below-level (values-by-level level) - "Return values in VALUES-BY-LEVEL accumulated deeper than LEVEL." - (cl-loop for deeper-level from (1+ level) below (length values-by-level) - append (aref values-by-level deeper-level))) - -(defun org-columns--clear-values-below-level (values-by-level level) - "Clear accumulated values below LEVEL in VALUES-BY-LEVEL." - (cl-loop for deeper-level from (1+ level) below (length values-by-level) - do (aset values-by-level deeper-level nil))) - (defun org-columns--compute-spec (spec &optional update-property-p) "Update tree according to SPEC. SPEC is a column format specification. When optional argument UPDATE-PROPERTY-P is non-nil, summarized values can replace existing ones in properties drawers." (when-let* ((operator (org-columns--summarizable-operator spec))) - (let* ((values-by-level (make-vector 1 nil)) - (current-level 0) - (previous-level 0) - (property (org-columns--spec-property spec)) - (format-string (org-columns--spec-format-string spec)) - (collect-function (org-columns--collect-function operator)) - (summarize-function (org-columns--summarize-function operator))) + (let ((property (org-columns--spec-property spec)) + (format-string (org-columns--spec-format-string spec)) + (collect-function (org-columns--collect-function operator)) + (summarize-function (org-columns--summarize-function operator)) + (stack nil)) (org-with-wide-buffer ;; Find the region to compute. (goto-char org-columns-top-level-marker) @@ -1585,38 +1567,26 @@ existing ones in properties drawers." ;; Walk the tree from the back and do the computations. (while (re-search-backward org-outline-regexp-bol org-columns-top-level-marker t) - (unless (= current-level 0) (setq previous-level current-level)) - (setq current-level (org-reduced-level (org-outline-level))) - (setq values-by-level - (org-columns--extend-values-by-level - values-by-level current-level)) (let* ((pos (match-beginning 0)) - (current-value (if collect-function - (funcall collect-function property) - (org-entry-get (point) property))) - (value-nonempty-p (org-string-nw-p current-value))) - (cond - ((< current-level previous-level) - ;; Collect values from lower levels and inline tasks here - ;; and summarize them using SUMMARIZE-FUNCTION. Store them in text - ;; property `org-summaries', in alist whose key is SPEC. - (let* ((values (and summarize-function - (org-columns--values-below-level - values-by-level current-level))) - (summary (and values - (funcall summarize-function values format-string)))) - (cond - (summary - (org-columns--put-summary pos spec summary) - (when update-property-p - (org-columns--update-summary-property property current-value summary)) - (push summary (aref values-by-level current-level))) - (value-nonempty-p - (push current-value (aref values-by-level current-level)))) - (org-columns--clear-values-below-level - values-by-level current-level))) - (value-nonempty-p - (push current-value (aref values-by-level current-level)))))))))) + (level (org-reduced-level (org-outline-level))) + (child-values nil)) + (while (and stack (< level (caar stack))) + (push (cdr (pop stack)) child-values)) + (setq child-values (nreverse child-values)) + (let* ((summary (and summarize-function + child-values + (funcall summarize-function child-values format-string))) + (current-value (and (or update-property-p (not summary)) + (if collect-function + (funcall collect-function property) + (org-entry-get pos property)))) + (value (cond + (summary (org-columns--put-summary pos spec summary) + (when update-property-p (org-columns--update-summary-property property current-value summary)) + summary) + (t current-value)))) + (when (org-string-nw-p value) + (push (cons level value) stack))))))))) ;;;###autoload (defun org-columns-compute (property) -- 2.39.5
