Function: todo-convert-legacy-files

todo-convert-legacy-files is an interactive and byte-compiled function defined in todo-mode.el.gz.

Signature

(todo-convert-legacy-files)

Documentation

Convert legacy todo files to the current Todo mode format.

The old-style files named by the variables todo-file-do and todo-file-done from the old package are converted to the new format and saved (the latter as a todo archive file) with a new name in todo-directory. See also the documentation string of todo-legacy-date-time-regexp for further details.

Key Bindings

Source Code

;; Defined in /usr/src/emacs/lisp/calendar/todo-mode.el.gz
(defun todo-convert-legacy-files ()
  "Convert legacy todo files to the current Todo mode format.
The old-style files named by the variables `todo-file-do' and
`todo-file-done' from the old package are converted to the new
format and saved (the latter as a todo archive file) with a new
name in `todo-directory'.  See also the documentation string of
`todo-legacy-date-time-regexp' for further details."
  (interactive)
  ;; If there are user customizations of legacy options, use them,
  ;; otherwise use the legacy default values.
  (let ((todo-file-do-tem (if (boundp 'todo-file-do)
			      todo-file-do
			    (locate-user-emacs-file "todo-do" ".todo-do")))
	(todo-file-done-tem (if (boundp 'todo-file-done)
				todo-file-done
			      (locate-user-emacs-file "todo-done" ".todo-done")))
	(todo-initials-tem (and (boundp 'todo-initials) todo-initials))
	(todo-entry-prefix-function-tem (and (boundp 'todo-entry-prefix-function)
					     todo-entry-prefix-function))
	todo-prefix-tem)
    ;; Convert `todo-file-do'.
    (if (not (file-exists-p todo-file-do-tem))
	(message "No legacy todo file exists")
      (let ((default "todo-do-conv")
	    file archive-sexp)
	(with-temp-buffer
	  (insert-file-contents todo-file-do-tem)
	  ;; Eliminate old-style local variables list in first line.
	  (delete-region (line-beginning-position) (1+ (line-end-position)))
	  (search-forward " --- " nil t) ; Legacy todo-category-beg.
	  (setq todo-prefix-tem (buffer-substring-no-properties
				 (line-beginning-position) (match-beginning 0)))
	  (goto-char (point-min))
	  (while (not (eobp))
	    (cond
	     ;; Old-style category start delimiter.
	     ((looking-at (regexp-quote (concat todo-prefix-tem " --- ")))
	      (replace-match todo-category-beg))
	     ;; Old-style category end delimiter.
	     ((looking-at (regexp-quote "--- End"))
	      (replace-match ""))
	     ;; Old-style category separator.
	     ((looking-at (regexp-quote
			   (concat todo-prefix-tem " "
				   (make-string 75 ?-))))
	      (replace-match todo-category-done))
	     ;; Old-style item header (date/time/initials).
	     ((looking-at (concat (regexp-quote todo-prefix-tem) " "
				  (if todo-entry-prefix-function-tem
				      (funcall todo-entry-prefix-function-tem)
				    (concat todo-legacy-date-time-regexp " "
					    (if todo-initials-tem
						(regexp-quote todo-initials-tem)
					      "[^:]*")
					    ":"))))
	      (todo-convert-legacy-date-time)))
	    (forward-line))
	  (setq file (concat todo-directory
			     (read-string (format-prompt "Save file as" default)
                                          nil nil default)
			     ".todo"))
	  (unless (file-exists-p todo-directory)
	    (make-directory todo-directory))
	  (write-region (point-min) (point-max) file nil 'nomessage nil t))
	(with-temp-buffer
	  (insert-file-contents file)
	  (let ((todo-categories (todo-make-categories-list t)))
	    (todo-update-categories-sexp)
	    (todo-check-format))
	  (write-region (point-min) (point-max) file nil 'nomessage))
	(setq todo-files (funcall todo-files-function))
	;; Convert `todo-file-done'.
	(when (file-exists-p todo-file-done-tem)
	  (with-temp-buffer
	    (insert-file-contents todo-file-done-tem)
	    (let ((beg (make-marker))
		  (end (make-marker))
		  cat cats comment item)
	      (while (not (eobp))
		(when (looking-at todo-legacy-date-time-regexp)
		  (set-marker beg (point))
		  (todo-convert-legacy-date-time)
		  (set-marker end (point))
		  (goto-char beg)
		  (insert "[" todo-done-string)
		  (goto-char end)
		  (insert "]")
		  (forward-char)
		  (when (looking-at todo-legacy-date-time-regexp)
		    (todo-convert-legacy-date-time))
		  (when (looking-at (concat " " (if todo-initials-tem
						    (regexp-quote
						     todo-initials-tem)
						  "[^:]*")
					    ":"))
		    (replace-match "")))
		(if (re-search-forward
		     (concat "^" todo-legacy-date-time-regexp) nil t)
		    (goto-char (match-beginning 0))
		  (goto-char (point-max)))
		(backward-char)
		(when (looking-back "\\[\\([^][]+\\)\\]"
                                    (line-beginning-position))
		  (setq cat (match-string 1))
		  (goto-char (match-beginning 0))
		  (replace-match ""))
		;; If the item ends with a non-comment parenthesis not
		;; followed by a period, we lose (but we inherit that
		;; problem from the legacy code).
                ;; FIXME: fails on multiline comment
		(when (looking-back "(\\(.*\\)) " (line-beginning-position))
		  (setq comment (match-string 1))
		  (replace-match "")
		  (insert "[" todo-comment-string ": " comment "]"))
		(set-marker end (point))
		(if (member cat cats)
		    ;; If item is already in its category, leave it there.
		    (unless (save-excursion
			      (re-search-backward
			       (concat "^" (regexp-quote todo-category-beg)
				       "\\(.*\\)$")
                               nil t)
			      (string= (match-string 1) cat))
		      ;; Else move it to its category.
		      (setq item (buffer-substring-no-properties beg end))
		      (delete-region beg (1+ end))
		      (set-marker beg (point))
		      (re-search-backward
		       (concat "^"
			       (regexp-quote (concat todo-category-beg cat))
			       "$")
		       nil t)
		      (forward-line)
		      (if (re-search-forward
			   (concat "^" (regexp-quote todo-category-beg)
				   "\\(.*\\)$")
                           nil t)
			  (progn (goto-char (match-beginning 0))
				 (newline)
				 (forward-line -1))
			(goto-char (point-max)))
		      (insert item "\n")
		      (goto-char beg))
		  (push cat cats)
		  (goto-char beg)
		  (insert todo-category-beg cat "\n\n"
			  todo-category-done "\n"))
		(forward-line))
	      (set-marker beg nil)
	      (set-marker end nil))
	    (setq file (concat (file-name-sans-extension file) ".toda"))
	    (write-region (point-min) (point-max) file nil 'nomessage nil t))
	  (with-temp-buffer
	    (insert-file-contents file)
	    (let* ((todo-categories (todo-make-categories-list t)))
	      (todo-update-categories-sexp)
	      (todo-check-format))
	    (write-region (point-min) (point-max) file nil 'nomessage)
	    (setq archive-sexp (read (buffer-substring-no-properties
				      (line-beginning-position)
				      (line-end-position)))))
	  (setq file (concat (file-name-sans-extension file) ".todo"))
	  ;; Update categories sexp of converted todo file again, adding
	  ;; counts of archived items.
	  (with-temp-buffer
	    (insert-file-contents file)
	    (let ((sexp (read (buffer-substring-no-properties
			       (line-beginning-position)
			       (line-end-position))))
		  (print-length nil)
		  (print-level nil))
	      (dolist (cat sexp)
		(let ((archive-cat (assoc (car cat) archive-sexp)))
		  (if archive-cat
		      (aset (cdr cat) 3 (aref (cdr archive-cat) 2)))))
	      (delete-region (line-beginning-position) (line-end-position))
	      (prin1 sexp (current-buffer)))
	    (write-region (point-min) (point-max) file nil 'nomessage))
	  (setq todo-archives (funcall todo-files-function t)))
        (todo-update-filelist-defcustoms)
	(when (y-or-n-p (concat "Format conversion done; do you want to "
				"visit the converted file now? "))
	  (setq todo-current-todo-file file)
	  (unless todo-default-todo-file
	    ;; We just initialized the first todo file, so make it the
	    ;; default now to avoid an infinite recursion with todo-show.
	    (setq todo-default-todo-file (todo-short-file-name file)))
	  (todo-show))))))