Function: todo-merge-category
todo-merge-category is an interactive and byte-compiled function
defined in todo-mode.el.gz.
Signature
(todo-merge-category &optional FILE)
Documentation
Merge current category into another existing category.
With prefix argument FILE, prompt for a specific todo file and
choose (with TAB completion) a category in it to merge into;
otherwise, choose and merge into a category in either the
current todo file or a file in todo-category-completions-files.
After merging, the source category's todo and done items are appended to the chosen goal category's todo and done items, respectively. The goal category becomes the current category, and the source category is deleted.
If both the source and goal categories also have archived items, they are also merged. If only the source category has archived items, the goal category is added as a new category to the archive file and the source category is deleted.
Key Bindings
Source Code
;; Defined in /usr/src/emacs/lisp/calendar/todo-mode.el.gz
(defun todo-merge-category (&optional file)
"Merge current category into another existing category.
With prefix argument FILE, prompt for a specific todo file and
choose (with TAB completion) a category in it to merge into;
otherwise, choose and merge into a category in either the
current todo file or a file in `todo-category-completions-files'.
After merging, the source category's todo and done items are
appended to the chosen goal category's todo and done items,
respectively. The goal category becomes the current category,
and the source category is deleted.
If both the source and goal categories also have archived items,
they are also merged. If only the source category has archived
items, the goal category is added as a new category to the
archive file and the source category is deleted."
(interactive "P")
(let* ((tfile todo-current-todo-file)
(cat (todo-current-category))
(cat+file (todo-read-category "Merge into category: " 'todo file))
(goal (car cat+file))
(gfile (cdr cat+file))
(tarchive (concat (file-name-sans-extension tfile) ".toda"))
(garchive (concat (file-name-sans-extension gfile) ".toda"))
(archived-count (todo-get-count 'archived))
here)
(with-current-buffer (find-file-noselect tfile)
(widen)
(let* ((inhibit-read-only t)
(cbeg (progn
(re-search-backward
(concat "^" (regexp-quote todo-category-beg)) nil t)
(point-marker)))
(tbeg (progn (forward-line) (point-marker)))
(dbeg (progn
(re-search-forward
(concat "^" (regexp-quote todo-category-done)) nil t)
(forward-line) (point-marker)))
;; Omit empty line between todo and done items.
(tend (progn (forward-line -2) (point-marker)))
(cend (progn
(if (re-search-forward
(concat "^" (regexp-quote todo-category-beg)) nil t)
(progn
(goto-char (match-beginning 0))
(point-marker))
(point-max-marker))))
(todo (buffer-substring-no-properties tbeg tend))
(done (buffer-substring-no-properties dbeg cend))
(todo-count (todo-get-count 'todo cat))
(done-count (todo-get-count 'done cat)))
;; Merge into goal todo category.
(with-current-buffer (find-file-noselect gfile)
(unless (derived-mode-p 'todo-mode) (todo-mode))
(widen)
(goto-char (point-min))
(let ((inhibit-read-only t))
;; Merge any todo items.
(unless (zerop (length todo))
(re-search-forward
(concat "^" (regexp-quote (concat todo-category-beg goal)) "$")
nil t)
(re-search-forward
(concat "^" (regexp-quote todo-category-done)) nil t)
(forward-line -1)
(setq here (point-marker))
(insert todo)
(todo-update-count 'todo todo-count goal))
;; Merge any done items.
(unless (zerop (length done))
(goto-char (if (re-search-forward
(concat "^" (regexp-quote todo-category-beg))
nil t)
(match-beginning 0)
(point-max)))
(when (zerop (length todo)) (setq here (point-marker)))
(insert done)
(todo-update-count 'done done-count goal)))
(todo-update-categories-sexp))
;; Update and clean up source todo file.
(remove-overlays cbeg cend)
(delete-region cbeg cend)
(setq todo-categories (delete (assoc cat todo-categories)
todo-categories))
(todo-update-categories-sexp)
(when (> todo-category-number (length todo-categories))
(setq todo-category-number 1))
(todo-category-select)
(mapc (lambda (m) (set-marker m nil))
(list cbeg tbeg dbeg tend cend))))
(when (> archived-count 0)
(with-current-buffer (find-file-noselect tarchive)
(widen)
(goto-char (point-min))
(let* ((inhibit-read-only t)
(cbeg (progn
(when (re-search-forward
(concat "^" (regexp-quote
(concat todo-category-beg cat)) "$")
nil t)
(goto-char (match-beginning 0))
(point-marker))))
(cend (if (re-search-forward
(concat "^" (regexp-quote todo-category-beg)) nil t)
(match-beginning 0)
(point-max)))
(carch (progn
(goto-char cbeg)
(forward-line)
(buffer-substring-no-properties (point) cend))))
;; Merge into goal archive category, if it exists, else create it.
(with-current-buffer (find-file-noselect garchive)
(let ((gbeg (when (re-search-forward
(concat "^" (regexp-quote
(concat todo-category-beg goal))
"$")
nil t)
(goto-char (match-beginning 0))
(point-marker))))
(goto-char (if (and gbeg
(re-search-forward
(concat "^" (regexp-quote todo-category-beg))
nil t))
(match-beginning 0)
(point-max)))
(unless gbeg (todo-add-category nil goal))
(insert carch)
(todo-update-categories-sexp)))
;; Update and clean up source archive file.
(remove-overlays cbeg cend)
(delete-region cbeg cend)
(setq todo-categories (todo-make-categories-list t))
(todo-update-categories-sexp))))
;; Update goal todo file for merged archived items and display it.
(set-window-buffer (selected-window) (set-buffer (get-file-buffer gfile)))
(unless (zerop archived-count)
(todo-update-count 'archived archived-count goal)
(todo-update-categories-sexp))
(todo-category-number goal)
;; If there are only merged done items, show them.
(let ((todo-show-with-done (zerop (todo-get-count 'todo goal))))
(todo-category-select)
;; Put point on the first merged item.
(goto-char here))
(set-marker here nil)))