Skip to content

Instantly share code, notes, and snippets.

@takaxp
Last active August 25, 2019 02:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save takaxp/ee515896a87d96c6ec28cac79ad00c37 to your computer and use it in GitHub Desktop.
Save takaxp/ee515896a87d96c6ec28cac79ad00c37 to your computer and use it in GitHub Desktop.
semi-automated clock-in and clock-out for DOING - https://github.com/takaxp/org-onit
;; integrated to https://github.com/takaxp/org-onit
(with-eval-after-load "org"
(when (require 'bookmark nil t)
(bookmark-maybe-load-default-file))
(require 'org-clock)
(require 'org-bookmark-heading nil t) ;; ブックマークの高精度化
;; ログをドロアーに入れる
(setq org-log-into-drawer nil)
;; タイムスタンプによるログ収集設定
(setq org-log-done 'time) ; 'time 以外に,'(done), '(state) を指定できる
;; タグとキーワードを設定
(setq org-tag-faces '(("Doing" :foreground "#FF0000")))
(setq org-todo-keywords
'((sequence "TODO(t)" "|" "DONE(d)")
(sequence "REV1(1)" "REV2(2)" "REV3(3)" "|" "APPROVED(a@/!)")))
;; キーバインドを設定
(define-key org-mode-map (kbd "<f11>") 'my-toggle-doing-tag)
(define-key org-mode-map (kbd "M-<f11>") 'my-sparse-doing-tree) ;; require org-agenda-files
(global-set-key (kbd "C-<f11>") 'org-clock-goto)
;; org-clock の計測時間をモードラインではなくタイトルに表示する
(setq org-clock-clocked-in-display 'frame-title)
;; タイトルの表示をカスタマイズ
(setq org-clock-frame-title-format
'((:eval (format "ドゥイング( ' -')b %s"
;; (all-the-icons-faicon "sort-amount-asc")
org-mode-line-string))
" - %b"))
;; 1分未満は記録しない
(setq org-clock-out-remove-zero-time-clocks t)
;; org-clock-out 時にステータスを変える(also configure org-todo-keywords)
(defun my-promote-todo-revision (state)
(cond ((member state '("TODO")) "REV1")
((member state '("REV1")) "REV2")
((member state '("REV2")) "REV3")
(t state)))
(setq org-clock-out-switch-to-state #'my-promote-todo-revision)
(defvar my-doing-tag "Doing")
(defun my-doing-p ()
(string-match
(concat ":" my-doing-tag ":")
(org-get-tags-string)))
;; 特定タグを持つツリーリストに一発移動(org-tags-view)
(defun my-sparse-doing-tree ()
(interactive)
(org-tags-view nil my-doing-tag))
;; Doingタグをトグルする(clock-in/-out を自動化)
(defun my-toggle-doing-tag ()
(interactive)
(when (eq major-mode 'org-mode)
(save-excursion
(save-restriction
(org-back-to-heading t)
;; before 9
;; (unless (org-at-heading-p)
;; (outline-previous-heading))
(if (my-doing-p)
(progn
(when (org-clocking-p)
(org-clock-out))
(org-toggle-tag my-doing-tag 'off))
(progn
(when (org-entry-is-done-p)
(org-todo "TODO")) ;; already done, restart the task.
(org-clock-in)
(org-toggle-tag my-doing-tag 'on)))))
(org-cycle-hide-drawers 'children)
(org-reveal)))
;; 最後にチェックインしたタスク用のブックマークを準備
(defvar my-org-clock-bookmark "org-clock-last-clock-in")
(defun my-org-clock-bookmark-set ()
(save-excursion
(save-restriction
(org-back-to-heading t)
(bookmark-set my-org-clock-bookmark))))
(add-hook 'org-clock-in-hook #'my-org-clock-bookmark-set)
;; clock-out したツリーから Doing タグを取る.
(defun my-remove-doing-tag ()
(when (my-doing-p)
(org-toggle-tag my-doing-tag 'off)))
(with-eval-after-load "org-clock"
(add-hook 'org-clock-out-hook #'my-remove-doing-tag))
;; org-clock-goto を高精度化
;; Emacs 終了で Doing タグが対象タスクから消えるが,
;; 再起動後,bookmark が読み込まれれば,即座に移動できる.
(defun ad:org-clock-goto (f &optional select)
"Go to the current task if the clock is working.
After restart Emacs, try to restore the task from `bookmark'."
(let ((bm (bookmark-get-bookmark my-org-clock-bookmark 'noerror)))
(cond ((and (require 'org-bookmark-heading nil t) ;; most reliable
bm)
(bookmark-jump my-org-clock-bookmark)) ;; call org-bookmark-jump
(org-clock-history
(apply f select))
(bm
(bookmark-jump my-org-clock-bookmark) ;; use normal bookmark
(org-back-to-heading t))
(t (message "No clock is found to be shown")))))
(advice-add 'org-clock-goto :around #'ad:org-clock-goto)
;; Emacs 終了時に計測中のタスクを終了
(defun my-org-clock-out-and-save-when-exit ()
"Save buffers and stop clocking when kill emacs."
(when (org-clocking-p)
(org-clock-out)
(save-some-buffers t)))
(add-hook 'kill-emacs-hook #'my-org-clock-out-and-save-when-exit)
(defvar org-doing--heading nil)
(defvar org-doing--todo nil)
(defun org-doing--switched-p ()
(if (org-before-first-heading-p)
(setq org-doing--heading nil)
(save-excursion
(save-restriction
(org-back-to-heading t)
(let* ((element (cadr (org-element-at-point)))
(heading (plist-get element :title))
(todo (plist-get element :todo-keyword))
(switched nil))
(unless (equal org-doing--todo todo)
(when (member org-doing--todo org-done-keywords)
(setq switched t))
(setq org-doing--todo todo))
(unless (equal org-doing--heading heading)
(setq switched t)
(setq org-doing--heading heading))
switched)))))
(defun org-doing--post-action ()
(when (and org-doing-mode
(org-doing--switched-p))
(when (org-clocking-p)
(org-clock-out))
(unless (org-entry-is-done-p)
(org-toggle-tag my-doing-tag 'on)
(org-clock-in))
(org-cycle-hide-drawers 'children)
(org-reveal)))
(defun org-doing--setup ()
(add-hook 'post-command-hook #'org-doing--post-action))
(defun org-doing--abort ()
(remove-hook 'post-command-hook #'org-doing--post-action)
(when (org-clocking-p)
(org-clock-out)))
(define-minor-mode org-doing-mode
:init-value nil
:lighter " Doing"
:require 'org-clock
:group 'org-doing
(if org-doing-mode
(org-doing--setup)
(org-doing--abort))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment