(require 'cl)
(require 'emacs-wiki)
(defgroup emacs-wiki-journal nil
"Options controlling the behaviour of Emacs Wiki journaling.
See `emacs-wiki-journal-add-entry' for more information."
:group 'emacs-wiki)
(defcustom emacs-wiki-journal-wiki "MyJournal"
"*Default name of the file to which journal entries are added."
:type 'string
:group 'emacs-wiki-journal)
(defcustom emacs-wiki-journal-category-directory nil
"*Default directory to search for category wiki files."
:type 'directory
:group 'emacs-wiki-journal)
(defcustom emacs-wiki-journal-icons-subdirectory "images"
"*Default base url to a directory containing category icons."
:type 'string
:group 'emacs-wiki-journal)
(defcustom emacs-wiki-journal-time-format "%a, %e %b. %2y"
"*Format for the date string of journal entries.
See `format-time-string' for more information."
:type 'string
:group 'emacs-wiki-journal)
(defcustom emacs-wiki-journal-category-regexp "^Category"
"*Each of the category index Wiki files start with this prefix."
:type 'string
:group 'emacs-wiki-journal)
(defun emacs-wiki-journal-category-alist (&optional no-check-p)
"Return possible category index Wikis in `emacs-wiki-directories'.
If NO-CHECK-P is non-nil, then don't check for changes in the directories
to decide whether to re-read the cached alist, just re-read the disk."
(let ((file-alist (emacs-wiki-file-alist no-check-p))
(category-alist nil))
(save-match-data
(while file-alist
(if (string-match emacs-wiki-journal-category-regexp
(caar file-alist))
(setq category-alist (cons (car file-alist)
category-alist)))
(setq file-alist (cdr file-alist))))
category-alist))
(defun emacs-wiki-journal-prompt-for-category-wiki ()
"Prompt for a category index file."
(let* ((directory (or emacs-wiki-journal-category-directory
(car emacs-wiki-directories)))
(file-alist (emacs-wiki-journal-category-alist))
(emacs-wiki-default-page (or (caar file-alist) "CategoryEmacs")))
(emacs-wiki-read-name file-alist "Category Wiki: ")))
(defun emacs-wiki-journal-make-extended-link (target-url
&optional link-description)
"Make an Emacs Wiki extended link from TARGET-URL and LINK-DESCRIPTION,"
(concat "[[" target-url
(and link-description (concat "][" link-description))
"]]"))
(defun emacs-wiki-journal-add-category-entry (wiki target-url
&optional link-description)
"Find category index file and add an entry for today."
(emacs-wiki-find-file wiki)
(undo-boundary)
(goto-char (point-min))
(goto-char
(or (search-forward-regexp "^\\* " (point-max) t) (point)))
(beginning-of-line)
(forward-line 1)
(goto-char
(or (search-forward-regexp "^- " (point-max) t) (point)))
(beginning-of-line)
(insert (concat "- "
(format-time-string emacs-wiki-journal-time-format)
" "
(emacs-wiki-journal-make-extended-link
target-url link-description)
"\n")))
(defun emacs-wiki-journal-1+-string (value)
"Increment an ascii encoded number."
(int-to-string (1+ (string-to-int value))))
(defun emacs-wiki-journal-add-entry (&optional other-window)
"Find journal file and add an entry and category index for today."
(interactive)
(let* ((category-wiki (emacs-wiki-journal-prompt-for-category-wiki))
(journal-entry-heading (read-from-minibuffer "Journal Heading: "))
(category-anchor-base (downcase category-wiki))
(anchor-regexp (concat "^#" (regexp-quote category-anchor-base)
"\\([0-9][0-9]*\\)"))
(anchor-ord "0"))
(emacs-wiki-find-file emacs-wiki-journal-wiki)
(goto-char (point-min))
(save-excursion
(if (search-forward-regexp anchor-regexp (point-max) t)
(setq anchor-ord
(emacs-wiki-journal-1+-string
(buffer-substring (match-beginning 1)
(match-end 1))))))
(save-excursion
(emacs-wiki-journal-add-category-entry
category-wiki
(concat emacs-wiki-journal-wiki "#" category-anchor-base anchor-ord)
journal-entry-heading))
(while (and (looking-at "^\\(#\\|\n\\)")
(equal 0 (forward-line 1))))
(goto-char
(or (search-forward-regexp "^\\* " (point-max) t) (point)))
(beginning-of-line)
(let* ((time-string (format-time-string
emacs-wiki-journal-time-format))
(icon-file-name (concat emacs-wiki-journal-icons-subdirectory "/"
category-wiki ".png"))
(icon-link (if (file-exists-p icon-file-name)
(concat (emacs-wiki-journal-make-extended-link
icon-file-name) " ")
"")))
(if (not (looking-at (regexp-quote (concat "* " time-string))))
(insert (concat "\n* " time-string "\n\n"))
(forward-line 1)
(insert "\n"))
(open-line 1)
(insert (concat "#" category-anchor-base anchor-ord " " icon-link "\n** "
journal-entry-heading "\n*** " category-wiki "\n\n\n")))
(emacs-wiki-find-file emacs-wiki-journal-wiki)
(forward-line -1) ))
(defun emacs-wiki-journal-add-entry-other-window ()
"Find category index file in another window and add an entry for today."
(interactive)
(emacs-wiki-journal-add-entry t))
(provide 'emacs-wiki-journal)