Hi Ihor,

Thanks for the review, and sorry for the delayed response.

You are right that restoring the original narrowing unconditionally can
hide the old title when the edited heading is outside the restriction.
In v2, `org-edit-headline' restores the narrowing during the prompt only
when the whole heading line is visible.  Otherwise, the prompt remains in
the widened buffer, keeping the old title visible.

Best,
-- 
Slawomir Grochowski
>From dafe83a9ab82d95001e47b543ab7d203d684159e Mon Sep 17 00:00:00 2001
From: Slawomir Grochowski <[email protected]>
Date: Wed, 1 Jul 2026 09:08:21 +0200
Subject: [PATCH v2 1/2] org: Preserve narrowing when editing headings

* lisp/org.el (org-edit-headline): Restore the original narrowing
while reading a new title when the edited heading is visible.  Keep
the buffer widened when the heading is outside the narrowing.
* testing/lisp/test-org.el (test-org/edit-headline): Test prompts for
headings inside and outside the narrowing.
---
 lisp/org.el              | 35 ++++++++++++++++++++++-------------
 testing/lisp/test-org.el | 30 +++++++++++++++++++++++++++++-
 2 files changed, 51 insertions(+), 14 deletions(-)

diff --git a/lisp/org.el b/lisp/org.el
index 6f9a5c4b3..d1310ee74 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -6855,19 +6855,28 @@ This is a list with the following elements:
   "Edit the current headline.
 Set it to HEADING when provided."
   (interactive nil org-mode)
-  (org-with-wide-buffer
-   (org-back-to-heading t)
-   (let ((case-fold-search nil))
-     (when (looking-at org-complex-heading-regexp)
-       (let* ((old (match-string-no-properties 4))
-	      (new (save-match-data
-		     (org-trim (or heading (read-string "Edit: " old))))))
-	 (unless (equal old new)
-	   (if old (replace-match new t t nil 4)
-	     (goto-char (or (match-end 3) (match-end 2) (match-end 1)))
-	     (insert " " new))
-	   (when org-auto-align-tags (org-align-tags))
-	   (when (looking-at "[ \t]*$") (replace-match ""))))))))
+  (let ((beg (point-min))
+	(end (point-max)))
+    (org-with-wide-buffer
+     (org-back-to-heading t)
+     (let ((case-fold-search nil))
+       (when (looking-at org-complex-heading-regexp)
+	 (let* ((old (match-string-no-properties 4))
+		(new
+		 (save-match-data
+		   (org-trim
+		    (or heading
+			(save-restriction
+			  (when (and (<= beg (point))
+				     (<= (line-end-position) end))
+			    (narrow-to-region beg end))
+			  (read-string "Edit: " old)))))))
+	   (unless (equal old new)
+	     (if old (replace-match new t t nil 4)
+	       (goto-char (or (match-end 3) (match-end 2) (match-end 1)))
+	       (insert " " new))
+	     (when org-auto-align-tags (org-align-tags))
+	     (when (looking-at "[ \t]*$") (replace-match "")))))))))
 
 (defun org-insert-heading-after-current ()
   "Insert a new heading with same level as current, after current subtree."
diff --git a/testing/lisp/test-org.el b/testing/lisp/test-org.el
index 7a6750f2a..949e75089 100644
--- a/testing/lisp/test-org.el
+++ b/testing/lisp/test-org.el
@@ -3324,7 +3324,35 @@ More text
    (equal "* B :tag:"
 	  (org-test-with-temp-text "* A :tag:"
 	    (let ((org-tags-column 4)) (org-edit-headline "B"))
-	    (buffer-string)))))
+	    (buffer-string))))
+  ;; Preserve narrowing while reading the new title when the edited
+  ;; heading is visible.
+  (should
+   (equal "* B\n* Other"
+	  (org-test-with-temp-text "* A\n* Other"
+	    (narrow-to-region (point-min) (line-end-position))
+	    (let ((beg (point-min))
+		  (end (point-max)))
+	      (cl-letf (((symbol-function 'read-string)
+			 (lambda (&rest _)
+			   (should (= beg (point-min)))
+			   (should (= end (point-max)))
+			   "B")))
+		(org-edit-headline)))
+	    (save-restriction (widen) (buffer-string)))))
+  ;; Keep the prompt widened when the edited heading is outside the
+  ;; original narrowing, so the old title remains visible.
+  (should
+   (equal "* B\nBody"
+	  (org-test-with-temp-text "* A\n<point>Body"
+	    (narrow-to-region (point) (point-max))
+	    (cl-letf (((symbol-function 'read-string)
+		       (lambda (&rest _)
+			 (should-not (buffer-narrowed-p))
+			 (should (looking-at-p "\\* A"))
+			 "B")))
+	      (org-edit-headline))
+	    (save-restriction (widen) (buffer-string))))))
 
 
 
-- 
2.39.5

>From baf0bcdad7d7f1b9e8376d5f245e7d510d16d55d Mon Sep 17 00:00:00 2001
From: Slawomir Grochowski <[email protected]>
Date: Wed, 1 Jul 2026 09:10:07 +0200
Subject: [PATCH v2 2/2] org-colview: Preserve narrowing when editing ITEM

* lisp/org-colview.el (org-columns-edit-value): Read the ITEM
value before moving to the heading marker, preserving narrowing
during the prompt.  Keep agenda behavior unchanged.
* testing/lisp/test-org-colview.el
(test-org-colview/columns-edit-value): Test narrowing while editing
ITEM.
---
 lisp/org-colview.el              | 10 +++++++++-
 testing/lisp/test-org-colview.el | 20 +++++++++++++++++++-
 2 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/lisp/org-colview.el b/lisp/org-colview.el
index fec35358a..66fdb911f 100644
--- a/lisp/org-colview.el
+++ b/lisp/org-colview.el
@@ -897,7 +897,15 @@ Where possible, use the standard interface for changing this line."
 	      ("BEAMER_ENV" (command-action #'org-beamer-select-environment))
 	      ("CLOCKSUM" (user-error "This special column cannot be edited"))
 	      ("DEADLINE" (command-action #'org-deadline))
-	      ("ITEM" (command-action #'org-edit-headline))
+	      ("ITEM"
+	       (if (eq major-mode 'org-agenda-mode)
+		   (command-action #'org-edit-headline)
+		 (let ((heading
+			(org-trim
+			 (read-string
+			  "Edit: " (get-char-property (point) 'org-columns-value)))))
+		   (lambda ()
+		     (org-with-point-at pom (org-edit-headline heading))))))
 	      ("PRIORITY" (command-action #'org-priority))
 	      ("SCHEDULED" (command-action #'org-schedule))
 	      ("TAGS"
diff --git a/testing/lisp/test-org-colview.el b/testing/lisp/test-org-colview.el
index 81cd6871d..bfd9cf727 100644
--- a/testing/lisp/test-org-colview.el
+++ b/testing/lisp/test-org-colview.el
@@ -1729,7 +1729,25 @@ https://list.orgmode.org/[email protected]/T/#u.";
 	    (cl-letf (((symbol-function 'read-string)
 		       (lambda (&rest _) "y")))
 	      (org-columns-edit-value))
-	    (org-entry-get (point) "A")))))
+	    (org-entry-get (point) "A"))))
+  ;; Preserve narrowing while reading an ITEM value when the edited
+  ;; heading is visible.
+  (should
+   (equal "* New\n** Child\n* Other"
+	  (org-test-with-temp-text "* Old\n** Child\n* Other"
+	    (narrow-to-region (point-min)
+			      (save-excursion (org-end-of-subtree t t)))
+	    (let ((beg (point-min))
+		  (end (point-max)))
+	      (let ((org-columns-default-format "%ITEM")) (org-columns))
+	      (cl-letf (((symbol-function 'read-string)
+			 (lambda (_prompt initial &rest _)
+			   (should (equal initial "Old"))
+			   (should (= beg (point-min)))
+			   (should (= end (point-max)))
+			   "New")))
+		(org-columns-edit-value "ITEM")))
+	    (save-restriction (widen) (buffer-string))))))
 
 (ert-deftest test-org-colview/column-property/clocksum ()
   "Test `org-columns' display of the CLOCKSUM property."
-- 
2.39.5

Reply via email to