Skip to content


Subversion checkout URL

You can clone with
Download ZIP
Branch: master
Fetching contributors…

Cannot retrieve contributors at this time

242 lines (198 sloc) 6.88 KB
;;; jdone.el --- *job done* diary
;; Copyright (C) 2011 by Oleksandr Gavenko <>
;; You can do anything with this file without any warranty.
;; Author: Oleksandr Gavenko <>
;; Maintainer: Oleksandr Gavenko <>
;; Created: 2011-11-12
;; Version: 0.1
;; Keywords: blog, microblog, blogging, gtd
;;; Commentary:
;; Very pure release.
;;; Code:
(defgroup jdone nil
"Job have done dairy."
:group 'applications)
(defconst jdone-major-version 0
"jdone major version.")
(defconst jdone-minor-version 1
"jdone minor version.")
(defun jdone-version (&optional here)
"Return jdone version."
(interactive "P")
(let ( (version-string (format "jdone %d.%d" jdone-major-version jdone-minor-version)) )
(if here
(insert version-string)
(if (called-interactively-p 'interactive)
(message "%s" version-string)
(defconst jdone-db-version 0
"jdonedb version.")
(defcustom jdone-db-dir (or (getenv "JDONEDB") "~/.jdone")
"Directory for storing jdone entries."
:type 'directory
:group 'jdone)
(defconst jdone-db-version-file "VERSION.jdonedb")
(defun jdone-db-version-file ()
(concat jdone-db-dir "/" jdone-db-version-file) )
(defconst jdone-db-current-file "current"
"File in `jdone-db-dir' to store recent entries.")
(defun jdone-db-current-file ()
(concat jdone-db-dir "/" jdone-db-current-file) )
(defconst jdone-db-current-tmp-file "current.tmp"
"File in `jdone-db-dir' to store recent entries.")
(defun jdone-db-current-tmp-file ()
(concat jdone-db-dir "/" jdone-db-current-tmp-file) )
(defconst jdone-archive-prefix "archive"
"Common prefix for entries archiving files.")
(defvar jdone-archive-format 'monthly
"Archive format. Currently only `monthly' supported. Ignored.")
(defcustom jdone-after-post-hook nil
"`jdone-after-post-hook' called after adding post to `jdone-current' file.
You can use this hook to render and publish content of `jdone-db-dir'."
:type 'hook
:group 'jdone)
(defun jdone-db-set-version ()
(with-temp-file (jdone-db-version-file)
(insert (format "%d\n" jdone-db-version))
(defun jdone-db-check-and-fix ()
"Check if storage exist and properly initialized. Opposite try
safely create or update storage."
(unless (file-directory-p jdone-db-dir)
(make-directory jdone-db-dir) )
(unless (file-readable-p (jdone-db-version-file))
(jdone-db-set-version) )
(defun jdone-reinit ()
"Reread configuration file and initialize jdone package."
(defvar jdone-inited nil)
(defun jdone-init ()
"Read configuration file and initialize jdone package if
already does not do so."
(unless jdone-inited
(setq jdone-inited t)
(defun jdone-strip-lines (str)
(if (string-match "\n" str)
(substring str 0 (match-beginning 0))
(defun jdone-insert-tag (tag tags)
(let ( (value (plist-get tags tag)) )
(when (stringp value)
(format "%s: %s\n" (substring (symbol-name tag) 1 nil) (jdone-strip-lines value)))
(defun jdone-post (msg &rest tags)
"Add post to `jdone-current' file.
Automatically set time to current value.
`jdone-after-post-hook' called after adding entries. You
can use this hook to render and publish content of `jdone-db-dir'.
Supported tag for TAGS are: `:app', `:engine'"
(let ( (coding-system-for-read 'utf-8-unix) (coding-system-for-write 'utf-8-unix) )
(with-temp-file (jdone-db-current-tmp-file)
;; (beginning-of-buffer)
(insert msg)
(when (equal (char-before) ?\n)
(delete-char -1))
(goto-char (point-min))
(while (search-forward-regexp "^" nil t)
(replace-match " " nil t))
(goto-char (point-min))
"date: "
(format-time-string "%Y-%m-%d %H:%M:%S%z" (current-time))
(jdone-insert-tag :app tags)
(jdone-insert-tag :engine tags)
(goto-char (point-max))
(insert ?\n)
(when (file-readable-p (jdone-db-current-file))
(insert-file (jdone-db-current-file)))
(rename-file (jdone-db-current-tmp-file) (jdone-db-current-file) t)
(run-hooks 'jdone-after-post-hook)
(defvar jdone-post-buffer-name "*jdone-post*"
"`jdone' buffer name for composing editing message")
(defun jdone-post-buffer ()
(let ( (msg (buffer-substring-no-properties (point-min) (point-max))) )
((eq major-mode 'log-edit-mode)
(jdone-post (format "Commit from: %s\n%s" default-directory msg) ))
(t (jdone-post msg))
(defcustom jdone-pre-post-buffer-hook nil
"Hook called after `jdone-post-buffer' was created.
You can use this hook to activate `flyspell-mode'."
:type 'hook
:group 'jdone)
(defun jdone-post-org ()
"Post from org enabled buffers.
Designed for use with `org-after-todo-state-change-hook'."
(when (member state org-done-keywords-for-agenda)
((eq major-mode 'org-mode)
(jdone-post (buffer-substring-no-properties (org-entry-beginning-position) (org-entry-end-position))))
((eq major-mode 'org-agenda-mode)
(jdone-post (buffer-substring-no-properties (line-beginning-position) (line-end-position))))
(defun jdone-post-and-kill-buffer ()
(kill-buffer (current-buffer))
(defun jdone-post-ui (&optional prefix start end)
"Add post.
Interactively, in Transient Mark mode when the mark is active,
operate on the contents of the region.
With prefix only post current line. If you prefix with M-- (or
C-u -) also kill current line (to `kill-ring').
Otherwise, open `jdone-post-buffer-name' buffer for message
(interactive (list current-prefix-arg (point) (mark)))
(let ( msg )
(when (called-interactively-p 'interactive)
((and transient-mark-mode mark-active)
(setq msg (buffer-substring-no-properties start end))
(setq msg (buffer-substring-no-properties (line-beginning-position) (line-end-position)))
(when (eq prefix '-)
(move-beginning-of-line 1)
(kill-line) )
(if msg
(jdone-post msg)
(switch-to-buffer (get-buffer-create jdone-post-buffer-name))
(delete-region (point-min) (point-max))
(local-set-key (kbd "C-c C-c") 'jdone-post-and-kill-buffer)
(run-hooks 'jdone-pre-post-buffer-hook)
(message "After finishing edit press C-c C-c.")
(defun jdone-setup-key-binding ()
"Bind 'C-c y' to `jdone-post-ui'."
(global-set-key (kbd "C-c y") 'jdone-post-ui)
(defun jdone-integrate-hook ()
(add-hook 'log-edit-done-hook 'jdone-post-buffer)
(add-hook 'org-after-todo-state-change-hook 'jdone-post-org)
(provide 'jdone)
;;; jdone.el ends here
Jump to Line
Something went wrong with that request. Please try again.