From mboxrd@z Thu Jan 1 00:00:00 1970 From: Leo Vivier Subject: [PATCH] Fix narrowed 1-line subtrees Date: Thu, 21 Feb 2019 16:38:17 +0100 Message-ID: <878sy9ywwm.fsf@hidden> References: <20190218002547.30325-1-leo.vivier@gmail.com> <87mumsqepg.fsf@nicolasgoaziou.fr> <871s44cbzb.fsf@hidden> <87sgwkoue5.fsf@nicolasgoaziou.fr> <87d0nnnbkf.fsf@hidden> <877edvn6g3.fsf@hidden> <874l8zn5vz.fsf@hidden> <87y36asiap.fsf@nicolasgoaziou.fr> <87y36atwdl.fsf@hidden> Mime-Version: 1.0 Content-Type: text/plain Return-path: Received: from eggs.gnu.org ([209.51.188.92]:36573) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gwqQf-0001J2-5q for emacs-orgmode@gnu.org; Thu, 21 Feb 2019 10:38:30 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gwqQd-0001Rj-70 for emacs-orgmode@gnu.org; Thu, 21 Feb 2019 10:38:29 -0500 Received: from mail-wr1-x442.google.com ([2a00:1450:4864:20::442]:39305) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1gwqQb-0001La-A6 for emacs-orgmode@gnu.org; Thu, 21 Feb 2019 10:38:26 -0500 Received: by mail-wr1-x442.google.com with SMTP id l5so29990824wrw.6 for ; Thu, 21 Feb 2019 07:38:21 -0800 (PST) In-Reply-To: <87y36atwdl.fsf@hidden> List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Sender: "Emacs-orgmode" To: Nicolas Goaziou Cc: emacs-orgmode@gnu.org * lisp/org.el (org-add-planning-info): Ensure insertion in current restriction. (org-remove-timestamp-with-keyword): Respect ambiguous newline when narrowed to 1-line-subtree. (org-remove-empty-drawer-at): Respect ambiguous newline when narrowed to 1-line subtree. (org-entry-delete): Respect ambiguous newline when narrowed to 1-line subtree. * lisp/org-clock.el (org-clock-find-position): Ensure clock-drawer insertion in current restriction. This patch addresses multiple issues occuring when running commands on a 1-line subtree when the buffer is narrowed to it. A 1-line subtree is a subtree only containing a heading and a newline at the end. Typical problem: ----------------------------------------------------------------------- * Tree 1 :PROPERTIES: :TEST: t :END: * Tree 2 ----------------------------------------------------------------------- With point on `Tree 1', run the following: (progn (org-narrow-to-subtree) (org-delete-property "TEST") (org-back-to-heading) (end-of-line) (delete-char 1) (widen)) Result: ----------------------------------------------------------------------- * Tree 1* Tree 2 ----------------------------------------------------------------------- Observation: The newline between the two headings has been removed despite the fact that it wasn't in the buffer restriction. The problem is due to two things: - The way that narrowing works in Emacs, notably how restrictions are restored after `save-restriction'. - The ambiguous newline between the end of a 1-line subtree and a following subtree. The solution is to stop the problematic commands from interacting with the ambiguous newline in order to preserve the narrowed region's `point-max'. This is done by inserting or removing newlines from the top of a heading rather than its bottom. Visually, instead of deleting the following bracketed region... ----------------------------------------------------------------------- * Tree 1 {:PROPERTIES: :TEST: t :END: }* Tree 2 ----------------------------------------------------------------------- We delete the following one: ----------------------------------------------------------------------- * Tree 1{ :PROPERTIES: :TEST: t :END:} * Tree 2 ----------------------------------------------------------------------- --- Please see my reply to this message for a detailed account of the problem and the solution. lisp/org-clock.el | 9 +++++---- lisp/org.el | 16 +++++++++------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/lisp/org-clock.el b/lisp/org-clock.el index b20158df6..5624af32a 100644 --- a/lisp/org-clock.el +++ b/lisp/org-clock.el @@ -1508,12 +1508,13 @@ line and position cursor in that line." (when (and org-clock-into-drawer (or (not (wholenump org-clock-into-drawer)) (< org-clock-into-drawer 2))) - (let ((beg (point))) - (insert ":" drawer ":\n:END:\n") + (let ((beg (1- (point)))) + (forward-char -1) + (insert "\n:" drawer ":\n:END:") (org-indent-region beg (point)) (org-flag-region - (line-end-position -1) (1- (point)) t 'org-hide-drawer) - (forward-line -1)))) + (line-end-position 0) (point) t 'org-hide-drawer) + (beginning-of-line)))) ;; When a clock drawer needs to be created because of the ;; number of clock items or simply if it is missing, collect ;; all clocks in the section and wrap them within the drawer. diff --git a/lisp/org.el b/lisp/org.el index ef6e40ca9..ae9494672 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -12937,7 +12937,7 @@ nil." "Remove all time stamps with KEYWORD in the current entry." (let ((re (concat "\\<" (regexp-quote keyword) " +<[^>\n]+>[ \t]*")) beg) - (save-excursion + (org-with-wide-buffer (org-back-to-heading t) (setq beg (point)) (outline-next-heading) @@ -12949,7 +12949,8 @@ nil." (when (string-match "^[ \t]*$" (buffer-substring (point-at-bol) (point-at-eol))) (delete-region (point-at-bol) - (min (point-max) (1+ (point-at-eol)))))))))) + (point-at-eol) + (delete-char -1)))))))) (defvar org-time-was-given) ; dynamically scoped parameter (defvar org-end-time-was-given) ; dynamically scoped parameter @@ -13046,8 +13047,8 @@ WHAT entry will also be removed." (unless (= (skip-chars-backward " \t" p) 0) (delete-region (point) (line-end-position))))))) ((not what) (throw 'exit nil)) ; Nothing to do. - (t (insert-before-markers "\n") - (backward-char 1) + (t (backward-char 1) + (insert "\n") (when org-adapt-indentation (indent-to-column (1+ (org-outline-level)))))) (when what @@ -13306,8 +13307,8 @@ POS may also be a marker." (delete-region (org-element-property :begin drawer) (progn (goto-char (org-element-property :end drawer)) (skip-chars-backward " \r\t\n") - (forward-line) - (point)))))))) + (point))) + (delete-char -1)))))) (defvar org-ts-type nil) (defun org-sparse-tree (&optional arg type) @@ -15222,7 +15223,8 @@ non-nil when a property was removed." ;; If drawer is empty, remove it altogether. (when (= begin end) (delete-region (line-beginning-position 0) - (line-beginning-position 2))) + (point-at-eol)) + (delete-char -1)) ;; Return non-nil if some property was removed. (prog1 (/= end origin) (set-marker end nil)))) (_ nil)))) -- 2.20.1