From 6cda490b129ac4d13638a1a6acfacd0f8fb8c5a1 Mon Sep 17 00:00:00 2001 From: Carsten Dominik Date: Wed, 11 Mar 2009 15:13:59 +0100 Subject: [PATCH] Cloning tasks New command to clone tasks, with time stamps shifted. --- doc/ChangeLog | 5 ++++ doc/org.texi | 15 +++++++++++ lisp/ChangeLog | 2 ++ lisp/org.el | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+) diff --git a/doc/ChangeLog b/doc/ChangeLog index ce3694114..6853638eb 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,8 @@ +2009-03-11 Carsten Dominik + + * org.texi (Structure editing): Document the new command + `org-clone-subtree-with-time-shift'. + 2009-03-10 Carsten Dominik * org.texi (Publishing): Refresh this chapter. diff --git a/doc/org.texi b/doc/org.texi index c34fc9d99..219b1329c 100644 --- a/doc/org.texi +++ b/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 diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 680e4b8e3..04dd81222 100755 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,5 +1,7 @@ 2009-03-11 Carsten Dominik + * 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. diff --git a/lisp/org.el b/lisp/org.el index 2dbd6dd72..bc89a3895 100644 --- a/lisp/org.el +++ b/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))]