Browse Source

Squash yet another bug due to outline-functions skipping invisible headings.

Bernt Hansen writes:

> I think I have something that is reproducible.
>
> ,----[ /tmp/x.org ]
> |
> | * Refile Targets
> | ** TODO One
> | ** TODO Two
> | ** TODO Three
> | ** TODO Four
> | ** TODO Five
> | ** TODO Six
> | *** TODO Six.one
> | *** TODO Six.two
> | **** TODO Clock me
> | ** TODO Seven
> | ** TODO Eight
> | ** TODO Nine
> | ** TODO Ten
> | * Refile Tasks
> | ** TODO Refile Me
> `----
>
> ,----[ /tmp/minimal.emacs ]
> | (add-to-list 'load-path (expand-file-name "~/git/org-mode/lisp"))
> | (add-to-list 'auto-mode-alist '("\\.\\(org\\|org_archive\\|txt\\)$" . org-mode))
> | (require 'org-install)
> |
> | (global-set-key "\C-cl" 'org-store-link)
> | (global-set-key "\C-ca" 'org-agenda)
> | (global-set-key "\C-cb" 'org-iswitchb)
> |
> | (setq org-log-done (quote time))
> | (setq org-log-into-drawer t)
> | (setq org-agenda-files '("/tmp/x.org"))
> | (setq user-init-file "/tmp/custom.el")
> |
> | (setq org-refile-allow-creating-parent-nodes nil)
> | (setq org-refile-targets (quote ((nil :maxlevel . 2) (org-agenda-files :maxlevel . 2))))
> | (setq org-refile-use-outline-path nil)
> | (setq org-todo-keywords (quote ((sequence "TODO(t!)" "STARTED(s!)" "|" "DONE(d!/!)") (sequence "WAITING(w@/!)" "SOMEDAY(S!)" "OPEN(O@)" "|" "CANCELLED(c@/!)") (sequence "QUOTE(q!)" "QUOTED(Q!)" "|" "APPROVED(A@)" "EXPIRED(E@)" "REJECTED(R@)"))))
> `----
>
> Steps to reproduce:
>
>  1. Save the files /tmp/x.org and /tmp/minimal.emacs
>  2. emacs -q -l /tmp/minimal.emacs /tmp/x.org
>  3. Go to CONTENTS view with S-TAB twice
>  4. Put point on **** TODO Clock Me
>  5. Clock in the task with C-c C-x C-i
>
>     This adds a logbook drawer with the clock
>
>  6. Fold to OVERVIEW view with S-TAB
>
>     So it looks like this
>
>     ,----[ x.org folder ]
>     |
>     | * Refile Targets...
>     | * Refile Tasks...
>     `----
>
>  7. M-x org-clock-goto
>
>     This reveals the buffer like so:
>
>     ,----
>     |
>     | * Refile Targets...
>     | **** TODO Clock me
>     |      :LOGBOOK:...
>     | ...
>     | * Refile Tasks...
>     `----
>
>     I think this is the critical step.
>
>  8. Put point on Refile Tasks
>  9. Show task to refile with TAB
>  10. Put point on ** TODO Refile Me
>  11. Refile to Ten with C-c C-w Ten RET
>  12. Put point on Refile Me
>  13. Reveal with C-c C-r
>
>      Shows that we are under TODO Ten.  So far so good
>
>      ,----
>      |
>      | * Refile Targets...
>      | **** TODO Clock me
>      |      :LOGBOOK:...
>      | ...
>      | ** TODO Ten
>      | *** TODO Refile Me
>      | * Refile Tasks
>      `----
>
>  14. Now repeat steps 10-13 but refile to 'Two' instead of 'Ten'
>
>      This goes to the wrong place.  This files under Nine for me
>
>      ,----
>      |
>      | * Refile Targets...
>      | **** TODO Clock me
>      |      :LOGBOOK:...
>      | ...
>      | ** TODO Nine
>      | *** TODO Refile Me
>      | ** TODO Ten
>      | * Refile Tasks
>      `----
>
>  15. Repeat steps 10-13 with refiling to 'Two' each time
>
>      This moves Refile Me up one task at a time until it gets to Two
>      ie. it refiles to Eight, then Seven, then Six, then Five, then
>      Four then Three, then Two.
>
> If you show contents view with S-TAB and then refile it goes to the
> right place immediately.  So this definitely has something to do with
> the folded view of the org file.
>
Carsten Dominik 11 years ago
parent
commit
10d59f78bb
2 changed files with 34 additions and 8 deletions
  1. 12 0
      lisp/ChangeLog
  2. 22 8
      lisp/org.el

+ 12 - 0
lisp/ChangeLog

@@ -1,3 +1,15 @@
+2009-08-28  Carsten Dominik  <carsten.dominik@gmail.com>
+
+	* org.el (org-move-subtree-down): Use `org-get-next-sibling' and
+	`org-get-last-sibling' instead of the outline versions of these
+	functions.
+	(org-get-last-sibling): New function.
+	(org-refile): Use `org-get-next-sibling' instead of the outline
+	version of this function.
+	(org-clean-visibility-after-subtree-move): Use
+	`org-get-next-sibling' and `org-get-last-sibling' instead of the
+	outline versions of these functions.
+
 2009-08-27  Carsten Dominik  <carsten.dominik@gmail.com>
 
 	* org-agenda.el (org-prepare-agenda): When creating a new frame

+ 22 - 8
lisp/org.el

@@ -5203,13 +5203,13 @@ This function is the default value of the hook `org-cycle-hook'."
   ;; First, find a reasonable region to look at:
   ;; Start two siblings above, end three below
   (let* ((beg (save-excursion
-		(and (outline-get-last-sibling)
-		     (outline-get-last-sibling))
+		(and (org-get-last-sibling)
+		     (org-get-last-sibling))
 		(point)))
 	 (end (save-excursion
-		(and (outline-get-next-sibling)
-		     (outline-get-next-sibling)
-		     (outline-get-next-sibling))
+		(and (org-get-next-sibling)
+		     (org-get-next-sibling)
+		     (org-get-next-sibling))
 		(if (org-at-heading-p)
 		    (point-at-eol)
 		  (point))))
@@ -6099,8 +6099,8 @@ is signaled in this case."
   "Move the current subtree down past ARG headlines of the same level."
   (interactive "p")
   (setq arg (prefix-numeric-value arg))
-  (let ((movfunc (if (> arg 0) 'outline-get-next-sibling
-		   'outline-get-last-sibling))
+  (let ((movfunc (if (> arg 0) 'org-get-next-sibling
+		   'org-get-last-sibling))
 	(ins-point (make-marker))
 	(cnt (abs arg))
 	beg beg0 end txt folded ne-beg ne-end ne-ins ins-end)
@@ -8719,7 +8719,7 @@ See also `org-refile-use-outline-path' and `org-completion-use-ido'"
 		      (goto-char
 		       (if reversed
 			   (or (outline-next-heading) (point-max))
-			 (or (save-excursion (outline-get-next-sibling))
+			 (or (save-excursion (org-get-next-sibling))
 			     (org-end-of-subtree t t)
 			     (point-max)))))
 		  (setq level 1)
@@ -16686,6 +16686,20 @@ This is like outline-next-sibling, but invisible headings are ok."
 	nil
       (point))))
 
+(defun org-get-last-sibling ()
+  "Move to previous heading of the same level, and return point.
+If there is no such heading, return nil."
+  (let ((opoint (point))
+	(level (funcall outline-level)))
+    (outline-previous-heading)
+    (when (and (/= (point) opoint) (outline-on-heading-p t))
+      (while (and (> (funcall outline-level) level)
+		  (not (bobp)))
+	(outline-previous-heading))
+      (if (< (funcall outline-level) level)
+	  nil
+        (point)))))
+
 (defun org-end-of-subtree (&optional invisible-OK to-heading)
   ;; This contains an exact copy of the original function, but it uses
   ;; `org-back-to-heading', to make it work also in invisible