Explorar o código

Cloning tasks

New command to clone tasks, with time stamps shifted.
Carsten Dominik %!s(int64=16) %!d(string=hai) anos
pai
achega
6cda490b12
Modificáronse 4 ficheiros con 94 adicións e 0 borrados
  1. 5 0
      doc/ChangeLog
  2. 15 0
      doc/org.texi
  3. 2 0
      lisp/ChangeLog
  4. 72 0
      lisp/org.el

+ 5 - 0
doc/ChangeLog

@@ -1,3 +1,8 @@
+2009-03-11  Carsten Dominik  <carsten.dominik@gmail.com>
+
+	* org.texi (Structure editing): Document the new command
+	`org-clone-subtree-with-time-shift'.
+
 2009-03-10  Carsten Dominik  <carsten.dominik@gmail.com>
 
 	* org.texi (Publishing): Refresh this chapter.

+ 15 - 0
doc/org.texi

@@ -997,6 +997,14 @@ previously visible.  Any prefix argument to this command will force a normal
 force a normal yank is @kbd{C-u C-y}.  If you use @code{yank-pop} after a
 yank, it will yank previous kill items plainly, without adjustment and
 folding.
+@kindex C-c C-x c
+@item C-c C-x c
+Clone a subtree by making a number of sibling copies of it.  You will be
+prompted for the number of copies to make, and you can also specify if any
+time stamps in the entry should be shifted.  This can be useful, for example,
+to create a number of tasks related to a series of lectures to prepare.  For
+more details, see the docstring of the command
+@code{org-clone-subtree-with-time-shift}.
 @kindex C-c C-w
 @item C-c C-w
 Refile entry or region to a different location.  @xref{Refiling notes}.
@@ -4998,6 +5006,8 @@ schedule the marked item.
 
 @node Repeated tasks,  , Inserting deadline/schedule, Deadlines and scheduling
 @subsection Repeated tasks
+@cindex tasks, repeated
+@cindex repeated tasks
 
 Some tasks need to be repeated again and again.  Org mode helps to
 organize such tasks using a so-called repeater in a DEADLINE, SCHEDULED,
@@ -5066,6 +5076,11 @@ special repeaters markers with @samp{++} and @samp{.+}.  For example:
 You may have both scheduling and deadline information for a specific
 task - just make sure that the repeater intervals on both are the same.
 
+An alternative to using a repeater is to create a number of copies of a task
+subtree, with dates shifted in each copy.  The command @kbd{C-c C-x c} was
+created for this purpose, it is described in @ref{Structure editing}.
+
+
 @node Clocking work time, Effort estimates, Deadlines and scheduling, Dates and Times
 @section Clocking work time
 

+ 2 - 0
lisp/ChangeLog

@@ -1,5 +1,7 @@
 2009-03-11  Carsten Dominik  <carsten.dominik@gmail.com>
 
+	* org.el (org-clone-subtree-with-time-shift): New command.
+
 	* org-export-latex.el (org-export-latex-special-chars)
 	(org-export-latex-treat-sub-super-char): Fix subscript export.
 

+ 72 - 0
lisp/org.el

@@ -5809,6 +5809,75 @@ If yes, remember the marker and the distance to BEG."
        (progn (org-back-to-heading) (point))
        (progn (org-end-of-subtree t) (point))))))
 
+(defun org-clone-subtree-with-time-shift (n &optional shift)
+  "Clone the task (subtree) at point N times.
+The clones will be inserted as siblings.
+
+In interactive use, the user will be prompted for the number of clones
+to be produced, and for a time SHIFT, which may be a repeater as used
+in time stamps, for example `+3d'.
+
+When a valid repeater is given and the entry contains any time stamps,
+the clones will become a sequence in time, with time stamps in the
+subtree shifted for each clone produced.  If SHIFT is nil or the
+empty string, time stamps will be left alone.
+
+If the original subtree did contain time stamps with a repeater,
+the following will happen:
+- the repeater will be removed in each clone
+- an additional clone will be produced, with the current, unshifted
+  date(s) in the entry.
+- the original entry will be placed *after* all the clones, with
+  repeater intact.
+- the start days in the repeater in the original entry will be shifted
+  to past the last clone.
+I this way you can spell out a number of instances of a repeating task,
+and still retain the repeater to cover future instances of the task."
+  (interactive "nNumber of clones to produce: \nsDate shift per clone (e.g. +1w, empty to copy unchanged): ")
+  (let (beg end template shift-n shift-what doshift nmin nmax (n-no-remove -1))
+    (if (not (and (integerp n) (> n 0)))
+	(error "Invalid number of replications %s" n))
+    (if (and (setq doshift (and (stringp shift) (string-match "\\S-" shift)))
+	     (not (string-match "\\`[ \t]*\\+?\\([0-9]+\\)\\([dwmy]\\)[ \t]*\\'"
+				shift)))
+	(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))))))
+    (if (eq shift-what 'week) (setq shift-n (* 7 shift-n) shift-what 'day))
+    (setq nmin 1 nmax n)
+    (org-back-to-heading t)
+    (setq beg (point))
+    (org-end-of-subtree t t)
+    (setq end (point))
+    (setq template (buffer-substring beg end))
+    (when (and doshift
+	       (string-match "<[^<>\n]+ \\+[0-9]+[dwmy][^<>\n]*>" template))
+      (delete-region beg end)
+      (setq end beg)
+      (setq nmin 0 nmax (1+ nmax) n-no-remove nmax))
+    (goto-char end)
+    (loop for n from nmin to nmax do
+	  (if (not doshift)
+	      (setq task template)
+	    (with-temp-buffer
+	      (insert template)
+	      (org-mode)
+	      (goto-char (point-min))
+	      (while (re-search-forward org-ts-regexp 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))
+		    (if (looking-at "<[^<>\n]+\\( +\\+[0-9]+[dwmy]\\)")
+			(delete-region (match-beginning 1) (match-end 1))))))
+	      (setq task (buffer-string))))
+	  (insert task))
+    (goto-char beg)))
 
 ;;; Outline Sorting
 
@@ -13292,6 +13361,7 @@ The images can be removed again with \\[org-ctrl-c-ctrl-c]."
 (org-defkey org-mode-map "\C-c\\"   'org-match-sparse-tree) ; Minor-mode res.
 (org-defkey org-mode-map "\C-c\C-m" 'org-ctrl-c-ret)
 (org-defkey org-mode-map "\M-\C-m"  'org-insert-heading)
+(org-defkey org-mode-map "\C-c\C-xc" 'org-clone-subtree-with-time-shift)
 (org-defkey org-mode-map [(control return)] 'org-insert-heading-respect-content)
 (org-defkey org-mode-map [(shift control return)] 'org-insert-todo-heading-respect-content)
 (org-defkey org-mode-map "\C-c\C-x\C-n" 'org-next-link)
@@ -14242,6 +14312,8 @@ See the individual commands for more information."
      ["Cut Subtree"  org-cut-special (not (org-at-table-p))]
      ["Paste Subtree"  org-paste-special (not (org-at-table-p))]
      "--"
+     ["Clone subtree, shift time" org-clone-subtree-with-time-shift t]
+     "--"
      ["Promote Heading" org-metaleft (not (org-at-table-p))]
      ["Promote Subtree" org-shiftmetaleft (not (org-at-table-p))]
      ["Demote Heading"  org-metaright (not (org-at-table-p))]