Last active
August 25, 2019 02:19
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; 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