Data hosted with ♥ by Pastebin.com - Download Raw - See Original
  1. ;; Functions to maintain a simple personal diary / journal in Emacs.
  2. ;; Feel free to use, modify and improve the code! - mtvoid
  3.  
  4. ;; Some basic information before you get started: First, make sure
  5. ;; this file is loaded when you start your Emacs session by copying it
  6. ;; into your load path and adding the line (load "journal") into your
  7. ;; .emacs. You also need to specify the directory where your journal
  8. ;; files will be saved. You can do this by setting the variable
  9. ;; journal-dir in your .emacs (remember to put a trailing
  10. ;; slash). journal-dir is also a customizable variable.
  11. ;;
  12. ;; Inside the journal directory, a separate file is created for each
  13. ;; day with a journal entry, with a filename in the format YYYYMMDD.
  14. ;; Each journal entry begins with the date on the top, followed by the
  15. ;; time. Any subsequent entries on the same day are written in the
  16. ;; same file, with their own timestamp. You can customize the date and
  17. ;; time formats (or remove them entirely). To start writing a journal
  18. ;; entry, press "C-c j".
  19. ;;
  20. ;; You can browse through existing journal entries on disk via the
  21. ;; calendar. All dates for which an entry is present are highlighted.
  22. ;; Pressing "j" will open it up for viewing. Pressing [ or ] will
  23. ;; select the date with the previous or next journal entry,
  24. ;; respectively.
  25. ;;
  26. ;; If you prefer using a different face for displaying the text of
  27. ;; your journal entries, you can customize the face 'journal'.
  28. ;;
  29. ;; Quick summary:
  30. ;; To create a new journal entry: C-c j
  31. ;; In calendar view: j to view an entry
  32. ;;                   [ to go to previous entry
  33. ;;                   ] to go to next entry
  34.  
  35.  
  36. ; Customizable variables
  37. (defgroup journal nil "Settings for the personal journal" :group
  38. 'applications)
  39. (defcustom journal-dir "~/Documents/journal/" "Directory containing journal entries"
  40.   :type 'string :group 'journal)
  41. (defcustom journal-date-format "%x%n"
  42.   "Format string for date, by default YYYY-MM-DD."
  43.   :type 'string :group 'journal)
  44. (defcustom journal-time-format "%n%R%n"
  45.   "Format string for time, by default HH:MM. Set it to a blank string if you want to disable timestamps."
  46.   :type 'string :group 'journal)
  47. (defface journal '((t nil)) "Custom face to use in the journal" :group 'journal)
  48.  
  49. ;(defvar journal-dir "~/Documents/journal/") ; Directory containing journal files
  50. (defvar journal-date-list nil)
  51. (defvar journal-file)
  52.  
  53. ;; Automatically switch to journal mode when opening a journal entry file
  54. (add-to-list 'auto-mode-alist
  55.          (cons (concat (car (last (split-string journal-dir "/" t)))
  56.                "/[0-9]\\{8\\}$") 'journal-mode))
  57.  
  58. (require 'calendar)
  59. (add-hook 'calendar-initial-window-hook 'journal-get-list)
  60. (add-hook 'calendar-today-visible-hook 'journal-mark-entries)
  61. (add-hook 'calendar-today-invisible-hook 'journal-mark-entries)
  62.  
  63. ;; Key bindings
  64. (define-key calendar-mode-map "j" 'journal-read-entry)
  65. (define-key calendar-mode-map "]" 'journal-next-entry)
  66. (define-key calendar-mode-map "[" 'journal-previous-entry)
  67. (global-set-key "\C-cj" 'journal-new-entry)
  68.  
  69. ;; Journal mode definition
  70. (define-derived-mode journal-mode text-mode "Journal" "Mode for writing or viewing entries written in the journal"
  71.   (turn-on-visual-line-mode)
  72.   (buffer-face-set 'journal)
  73.   (add-hook 'change-major-mode-hook '(lambda nil (set-text-properties (point-min) (point-max) nil)) t t)
  74.   (run-mode-hooks))
  75.  
  76. (add-hook 'journal-mode-hook 'journal-format-title)
  77.  
  78. (defun journal-format-title nil
  79.   (save-excursion
  80.     (let ((unsaved (buffer-modified-p)))
  81.       (set-text-properties 1 (point-at-eol (goto-char (point-min)))
  82.                '(face (:height 1.5 :underline t)))
  83.       (set-buffer-modified-p unsaved))))
  84.  
  85. ;; Creates a new entry
  86. (defun journal-new-entry nil "Open today's journal file and start a new entry"
  87.   (interactive)
  88.   (unless (file-exists-p journal-dir) (error "Journal directory %s not found" journal-dir))
  89.   (find-file (concat journal-dir (format-time-string "%Y%m%d")))
  90.   (if view-mode (view-mode-disable))
  91.   (setq buffer-read-only nil)
  92.   (goto-char (point-max))
  93.   (let ((unsaved (buffer-modified-p)))
  94.     (if (equal (point-max) 1) (insert (format-time-string journal-date-format)))
  95.     (unless (eq (current-column) 0) (insert "\n"))
  96.     (remove-text-properties (point-min) (point-max) '(face))
  97.     (let ((beg (point)))
  98.       (insert (format-time-string journal-time-format))
  99.       (put-text-property beg (max beg (- (point) 1)) 'face '(:weight bold)))
  100.     (set-buffer-modified-p unsaved))
  101.   (journal-format-title))
  102.  
  103. ;;
  104. ;; Functions to browse existing journal entries using the calendar
  105. ;;
  106.  
  107. (defun journal-get-list nil "Loads the list of files in the journal directory, and converts it into a list of calendar DATE elements"
  108.   (unless (file-exists-p journal-dir) (error "Journal directory %s not found" journal-dir))
  109.   (setq journal-date-list
  110.     (mapcar '(lambda (journal-file)
  111.            (let ((y (string-to-number (substring journal-file 0 4)))
  112.              (m (string-to-number (substring journal-file 4 6)))
  113.              (d (string-to-number (substring journal-file 6 8))))
  114.              (list m d y)))
  115.            (directory-files journal-dir nil "^[0-9]\\{8\\}$" nil)))
  116.   (calendar-redraw))
  117.  
  118. (defun journal-mark-entries nil "Mark days in the calendar for which a diary entry is present"
  119.   (dolist (journal-entry journal-date-list)
  120.     (if (calendar-date-is-visible-p journal-entry)
  121.       (calendar-mark-visible-date journal-entry))))
  122.  
  123. (defun journal-read-entry nil "Open journal entry for selected date for viewing"
  124.   (interactive)
  125.   (setq journal-file (int-to-string (+ (* 10000 (nth 2 (calendar-cursor-to-date))) (* 100 (nth 0 (calendar-cursor-to-date))) (nth 1 (calendar-cursor-to-date)))))
  126.   (if (file-exists-p (concat journal-dir journal-file))
  127.       (view-file-other-window (concat journal-dir journal-file))
  128.     (message "No journal entry for this date.")))
  129.  
  130. (defun journal-next-entry nil "Go to the next date with a journal entry"
  131.   (interactive)
  132.   (let ((dates journal-date-list))
  133.     (while (and dates (not (calendar-date-compare (list (calendar-cursor-to-date)) dates)))
  134.       (setq dates (cdr dates)))
  135.     (if dates (calendar-goto-date (car dates)))))
  136.  
  137. (defun journal-previous-entry nil "Go to the previous date with a journal entry"
  138.   (interactive)
  139.   (let ((dates (reverse journal-date-list)))
  140.     (while (and dates (not (calendar-date-compare dates (list (calendar-cursor-to-date)))))
  141.       (setq dates (cdr dates)))
  142.     (if dates (calendar-goto-date (car dates)))))
  143.  
  144. (provide 'journal)