Browse Source

Merge branch 'maint'

Nicolas Goaziou 8 years ago
parent
commit
985ffb13d2
2 changed files with 94 additions and 71 deletions
  1. 71 70
      lisp/org.el
  2. 23 1
      testing/lisp/test-org.el

+ 71 - 70
lisp/org.el

@@ -8888,77 +8888,78 @@ subtree has a repeater.  Setting N to 0, then, can be used to
 remove the repeater from a subtree and create a shifted clone
 with the original repeater."
   (interactive "nNumber of clones to produce: ")
+  (unless (wholenump n) (user-error "Invalid number of replications %s" n))
   (when (org-before-first-heading-p) (user-error "No subtree to clone"))
-  (let ((shift
-	 (or shift
-	     (if (and (not (equal current-prefix-arg '(4)))
-		      (save-excursion
-			(org-back-to-heading t)
-			(re-search-forward
-			 org-ts-regexp-both
-			 (save-excursion (org-end-of-subtree t) (point)) t)))
-		 (read-from-minibuffer
-		  "Date shift per clone (e.g. +1w, empty to copy unchanged): ")
-	       ""))) ;; No time shift
-	(n-no-remove -1)
-	(drawer-re org-drawer-regexp)
-	(org-clock-re (format "^[ \t]*%s.*$" org-clock-string))
-	beg end template task idprop
-	shift-n shift-what doshift nmin nmax)
-    (unless (wholenump n)
-      (user-error "Invalid number of replications %s" n))
-    (when (and (setq doshift (and (stringp shift) (string-match "\\S-" shift)))
-	       (not (string-match "\\`[ \t]*\\+?\\([0-9]+\\)\\([hdwmy]\\)[ \t]*\\'"
-				  shift)))
-      (user-error "Invalid shift specification %s" shift))
-    (when doshift
-      (setq shift-n (string-to-number (match-string 1 shift))
-	    shift-what (cdr (assoc (match-string 2 shift)
-				   '(("d" . day) ("w" . week)
-				     ("m" . month) ("y" . year))))))
-    (when (eq shift-what 'week) (setq shift-n (* 7 shift-n) shift-what 'day))
-    (setq nmin 1 nmax n)
-    (setq beg (point))
-    (setq idprop (org-entry-get nil "ID"))
-    (org-end-of-subtree t t)
-    (or (bolp) (insert "\n"))
-    (setq end (point))
-    (setq template (buffer-substring beg end))
-    (when (and doshift
-	       (string-match "<[^<>\n]+ [.+]?\\+[0-9]+[hdwmy][^<>\n]*>" template))
-      (delete-region beg end)
-      (setq end beg)
-      (setq nmin 0 nmax (1+ nmax) n-no-remove nmax))
-    (goto-char end)
-    (cl-loop for n from nmin to nmax do
-	     ;; prepare clone
-	     (with-temp-buffer
-	       (insert template)
-	       (org-mode)
-	       (goto-char (point-min))
-	       (org-show-subtree)
-	       (and idprop (if org-clone-delete-id
-			       (org-entry-delete nil "ID")
-			     (org-id-get-create t)))
-	       (unless (= n 0)
-		 (while (re-search-forward org-clock-re nil t)
-		   (kill-whole-line))
-		 (goto-char (point-min))
-		 (while (re-search-forward drawer-re nil t)
-		   (org-remove-empty-drawer-at (point))))
-	       (goto-char (point-min))
-	       (when doshift
-		 (while (re-search-forward org-ts-regexp-both nil t)
-		   (org-timestamp-change (* n shift-n) shift-what))
-		 (unless (= n n-no-remove)
-		   (goto-char (point-min))
-		   (while (re-search-forward org-ts-regexp nil t)
-		     (save-excursion
-		       (goto-char (match-beginning 0))
-		       (when (looking-at "<[^<>\n]+\\( +[.+]?\\+[0-9]+[hdwmy]\\)")
-			 (delete-region (match-beginning 1) (match-end 1)))))))
-	       (setq task (buffer-string)))
-	     (insert task))
+  (let* ((beg (save-excursion (org-back-to-heading t) (point)))
+	 (end-of-tree (save-excursion (org-end-of-subtree t t) (point)))
+	 (shift
+	  (or shift
+	      (if (and (not (equal current-prefix-arg '(4)))
+		       (save-excursion
+			 (goto-char beg)
+			 (re-search-forward org-ts-regexp-both end-of-tree t)))
+		  (read-from-minibuffer
+		   "Date shift per clone (e.g. +1w, empty to copy unchanged): ")
+		"")))			;No time shift
+	 (doshift
+	  (or (not (org-string-nw-p shift))
+	      (string-match "\\`[ \t]*\\+?\\([0-9]+\\)\\([dwmy]\\)[ \t]*\\'"
+			    shift)
+	      (user-error "Invalid shift specification %s" shift))))
+    (goto-char end-of-tree)
+    (unless (bolp) (insert "\n"))
+    (let* ((end (point))
+	   (template (buffer-substring beg end))
+	   (shift-n (and doshift (string-to-number (match-string 1 shift))))
+	   (shift-what (pcase (match-string 2 shift)
+			 ("d" 'day)
+			 ("w" (setq shift-n (* 7 shift-n)) 'day)
+			 ("m" 'month)
+			 ("y" 'year)
+			 (_ (error "Unsupported time unit"))))
+	   (nmin 1)
+	   (nmax n)
+	   (n-no-remove -1)
+	   (idprop (org-entry-get nil "ID")))
+      (when (and doshift
+		 (string-match-p "<[^<>\n]+ [.+]?\\+[0-9]+[hdwmy][^<>\n]*>"
+				 template))
+	(delete-region beg end)
+	(setq end beg)
+	(setq nmin 0)
+	(setq nmax (1+ nmax))
+	(setq n-no-remove nmax))
+      (goto-char end)
+      (cl-loop for n from nmin to nmax do
+	       (insert
+		;; Prepare clone.
+		(with-temp-buffer
+		  (insert template)
+		  (org-mode)
+		  (goto-char (point-min))
+		  (org-show-subtree)
+		  (and idprop (if org-clone-delete-id
+				  (org-entry-delete nil "ID")
+				(org-id-get-create t)))
+		  (unless (= n 0)
+		    (while (re-search-forward org-clock-line-re nil t)
+		      (delete-region (line-beginning-position)
+				     (line-beginning-position 2)))
+		    (goto-char (point-min))
+		    (while (re-search-forward org-drawer-regexp nil t)
+		      (org-remove-empty-drawer-at (point))))
+		  (goto-char (point-min))
+		  (when doshift
+		    (while (re-search-forward org-ts-regexp-both nil t)
+		      (org-timestamp-change (* n shift-n) shift-what))
+		    (unless (= n n-no-remove)
+		      (goto-char (point-min))
+		      (while (re-search-forward org-ts-regexp nil t)
+			(save-excursion
+			  (goto-char (match-beginning 0))
+			  (when (looking-at "<[^<>\n]+\\( +[.+]?\\+[0-9]+[hdwmy]\\)")
+			    (delete-region (match-beginning 1) (match-end 1)))))))
+		  (buffer-string)))))
     (goto-char beg)))
 
 ;;; Outline Sorting

+ 23 - 1
testing/lisp/test-org.el

@@ -1328,6 +1328,10 @@
   (should-error
    (org-test-with-temp-text ""
      (org-clone-subtree-with-time-shift 1)))
+  ;; Raise an error on invalid number of clones.
+  (should-error
+   (org-test-with-temp-text "* Clone me"
+     (org-clone-subtree-with-time-shift -1)))
   ;; Clone non-repeating once.
   (should
    (equal "\
@@ -1371,7 +1375,25 @@
 	    (org-clone-subtree-with-time-shift 0 "+2d")
 	    (replace-regexp-in-string
 	     "\\( [.A-Za-z]+\\)\\( \\+[0-9][hdmwy]\\)?>" "" (buffer-string)
-	     nil nil 1)))))
+	     nil nil 1))))
+  ;; Find time stamps before point.  If SHIFT is not specified, ask
+  ;; for a time shift.
+  (should
+   (string-prefix-p
+    "* H <2012-03-30"
+    (org-test-with-temp-text "* H <2012-03-29 Thu><point>"
+      (org-clone-subtree-with-time-shift 1 "+1d")
+      (buffer-substring-no-properties (line-beginning-position 2)
+				      (line-end-position 2)))))
+  (should
+   (string-prefix-p
+    "* H <2014-03-05"
+    (org-test-with-temp-text "* H <2014-03-04 Tue><point>"
+      (cl-letf (((symbol-function 'read-from-minibuffer)
+		 (lambda (&rest args) "+1d")))
+	(org-clone-subtree-with-time-shift 1 "+1d"))
+      (buffer-substring-no-properties (line-beginning-position 2)
+				      (line-end-position 2))))))
 
 
 ;;; Fixed-Width Areas