Ihor Radchenko <[email protected]> writes: > Then, why is that goto-char necessary at all? org-map-entries will map > over the narrowed portion of the buffer. It does not matter where the > point position is.
For local capture, `org-map-entries' is called with scope `tree', so the scope depends on point. `org-columns--prepare-rows' may select an ancestor as the column view scope, for example because COLUMNS is inherited. The `goto-char' makes `org-map-entries' use that same scope. I added a small test for this in v4; it fails if that line is commented out. Best, -- Slawomir Grochowski
>From 8b36c44cd754a30dad276dd857a5977e3500981e Mon Sep 17 00:00:00 2001 From: Slawomir Grochowski <[email protected]> Date: Mon, 15 Jun 2026 07:00:53 +0200 Subject: [PATCH v4] org-colview: Capture column view without rendering overlays * lisp/org-colview.el (org-columns--capture-view): Prepare rows directly instead of enabling column view. Read captured values from collected rows and clear row markers once consumed. * testing/lisp/test-org-colview.el (test-org-colview/dblock): Test capture with an inherited column view scope. Dynamic block capture only needs collected row data. Preserve cleanup of an existing column view and temporary preparation state without rendering column overlays. --- lisp/org-colview.el | 43 +++++++++++++++++++------------- testing/lisp/test-org-colview.el | 19 ++++++++++++++ 2 files changed, 45 insertions(+), 17 deletions(-) diff --git a/lisp/org-colview.el b/lisp/org-colview.el index 37cfbe937..34d14f9ed 100644 --- a/lisp/org-colview.el +++ b/lisp/org-colview.el @@ -1699,23 +1699,27 @@ to COLUMNS-FORMAT. All subsequent lists each represent a body row as a list whose first element is an integer indicating the outline level of the entry, and whose remaining elements are strings with the contents for the columns according to COLUMNS-FORMAT." - (org-columns (not local) columns-format) - (goto-char org-columns-top-level-marker) - (let ((columns (length org-columns-current-fmt-compiled)) - (has-item (assoc "ITEM" org-columns-current-fmt-compiled)) - table) + (org-columns-remove-overlays) + (let* ((rows (save-excursion + (org-columns--prepare-rows (not local) columns-format))) + (has-item (assoc "ITEM" org-columns-current-fmt-compiled)) + table) + (goto-char org-columns-top-level-marker) (org-map-entries (lambda () - (when (get-char-property (point) 'org-columns-key) - (let (row) - (dotimes (i columns) - (let* ((col (+ (line-beginning-position) i)) - (p (get-char-property col 'org-columns-key))) - (push (get-char-property col - (if (string= p "ITEM") - 'org-columns-value - 'org-columns-value-modified)) - row))) + (while (and rows (< (caar rows) (point))) + (set-marker (caar rows) nil) + (pop rows)) + (when-let* ((triplets (and rows + (= (caar rows) (point)) + (cdar rows)))) + (let ((row + (mapcar + (pcase-lambda (`(,spec ,value ,displayed-value)) + (if (string= (org-columns--spec-property spec) "ITEM") + value + displayed-value)) + triplets))) (unless (or (and skip-empty (let ((r (delete-dups (remove "" row)))) @@ -1723,14 +1727,19 @@ for the columns according to COLUMNS-FORMAT." (and exclude-tags (cl-some (lambda (tag) (member tag exclude-tags)) (org-get-tags)))) - (push (cons (org-reduced-level (org-current-level)) (nreverse row)) + (push (cons (org-reduced-level (org-current-level)) row) table))))) (if match (concat match (and maxlevel (format "+LEVEL<=%d" maxlevel))) (and maxlevel (format "LEVEL<=%d" maxlevel))) (and local 'tree) 'archive 'comment) - (org-columns-quit) + (dolist (row rows) (set-marker (car row) nil)) + (when (markerp org-columns-begin-marker) + (set-marker org-columns-begin-marker nil)) + (when (markerp org-columns-top-level-marker) + (set-marker org-columns-top-level-marker nil)) + (setq org-columns-current-fmt nil) ;; Add column titles and a horizontal rule in front of the table. (cons (mapcar #'org-columns--spec-title org-columns-current-fmt-compiled) (cons 'hline (nreverse table))))) diff --git a/testing/lisp/test-org-colview.el b/testing/lisp/test-org-colview.el index 6a1f9d21b..81cd6871d 100644 --- a/testing/lisp/test-org-colview.el +++ b/testing/lisp/test-org-colview.el @@ -1859,6 +1859,25 @@ CLOCK: [2022-11-03 06:05]--[2022-11-03 06:06] => 0:01 "* H1\n<point>#+BEGIN: columnview :id local\n#+END:\n** H1.1\n* H2" (let ((org-columns-default-format "%ITEM")) (org-update-dblock)) (buffer-substring-no-properties (point) (outline-next-heading))))) + ;; Inherited COLUMNS makes capture start at "P", not at the block under "C". + (should + (equal + "#+BEGIN: columnview +| ITEM | +|------| +| P | +| C | +#+END:" + (org-test-with-temp-text + "* P +:PROPERTIES: +:COLUMNS: %ITEM +:END: +** C +<point>#+BEGIN: columnview +#+END:" + (org-update-dblock) + (buffer-substring-no-properties (point) (point-max))))) (should (equal "#+BEGIN: columnview :id global -- 2.39.5
