diff options
Diffstat (limited to 'lisp/+org-wc.el')
-rw-r--r-- | lisp/+org-wc.el | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/lisp/+org-wc.el b/lisp/+org-wc.el new file mode 100644 index 0000000..7ab0050 --- /dev/null +++ b/lisp/+org-wc.el | |||
@@ -0,0 +1,97 @@ | |||
1 | ;;; +org-wc.el --- org-wc in the modeline -*- lexical-binding: t; -*- | ||
2 | |||
3 | ;;; Commentary: | ||
4 | |||
5 | ;;; Code: | ||
6 | |||
7 | (require 'org-wc) | ||
8 | (require '+modeline) | ||
9 | (require 'cl-lib) | ||
10 | |||
11 | (defgroup +org-wc nil | ||
12 | "Extra fast word-counting in `org-mode'" | ||
13 | :group 'org-wc | ||
14 | :group 'org) | ||
15 | |||
16 | (defvar-local +org-wc-word-count nil | ||
17 | "Running total of words in this buffer.") | ||
18 | |||
19 | (defcustom +org-wc-update-after-funcs '(org-narrow-to-subtree | ||
20 | org-narrow-to-block | ||
21 | org-narrow-to-element | ||
22 | org-capture-narrow | ||
23 | org-taskwise-narrow-to-task) | ||
24 | "Functions after which to update the word count." | ||
25 | :type '(repeat function)) | ||
26 | |||
27 | (defcustom +org-wc-deletion-idle-timer 0.25 | ||
28 | "Length of time, in seconds, to wait before updating word-count." | ||
29 | :type 'number) | ||
30 | |||
31 | (defcustom +org-wc-huge-change 5000 | ||
32 | "Number of characters that constitute a \"huge\" insertion." | ||
33 | :type 'number) | ||
34 | |||
35 | (defvar-local +org-wc-update-timer nil) | ||
36 | |||
37 | (defun +org-wc-delayed-update (&rest _) | ||
38 | (if +org-wc-update-timer | ||
39 | (setq +org-wc-update-timer nil) | ||
40 | (setq +org-wc-update-timer | ||
41 | (run-with-idle-timer +org-wc-deletion-idle-timer nil #'+org-wc-update)))) | ||
42 | |||
43 | (defun +org-wc-force-update () | ||
44 | (interactive) | ||
45 | (message "Counting words...") | ||
46 | (when (timerp +org-wc-update-timer) | ||
47 | (cancel-timer +org-wc-update-timer)) | ||
48 | (+org-wc-update) | ||
49 | (message "Counting words...done")) | ||
50 | |||
51 | (defun +org-wc-update () | ||
52 | (dlet ((+org-wc-counting t)) | ||
53 | (+org-wc-buffer) | ||
54 | (force-mode-line-update) | ||
55 | (setq +org-wc-update-timer nil))) | ||
56 | |||
57 | (defun +org-wc-changed (start end length) | ||
58 | (+org-wc-delayed-update)) | ||
59 | |||
60 | (defun +org-wc-buffer () | ||
61 | "Count the words in the buffer." | ||
62 | (when (derived-mode-p 'org-mode) | ||
63 | (setq +org-wc-word-count | ||
64 | (org-word-count-aux (point-min) (point-max))))) | ||
65 | |||
66 | (defvar +org-wc-counting nil | ||
67 | "Are we currently counting?") | ||
68 | |||
69 | (defun +org-wc-recount-widen (&rest _) | ||
70 | (when (and (not +org-wc-counting)) | ||
71 | (+org-wc-update))) | ||
72 | |||
73 | (defun +org-wc-modeline () | ||
74 | (when +org-wc-word-count | ||
75 | (format " %sw" +org-wc-word-count))) | ||
76 | |||
77 | (define-minor-mode +org-wc-mode | ||
78 | "Count words in `org-mode' buffers in the mode-line." | ||
79 | :lighter "" | ||
80 | :keymap (let ((map (make-sparse-keymap))) | ||
81 | (define-key map (kbd "C-c C-.") #'+org-wc-force-update) | ||
82 | map) | ||
83 | (if +org-wc-mode | ||
84 | (progn ; turn on | ||
85 | (+org-wc-buffer) | ||
86 | (add-hook 'after-change-functions #'+org-wc-delayed-update nil t) | ||
87 | (setq-local +modeline-position-function #'+org-wc-modeline) | ||
88 | (dolist (fn +org-wc-update-after-funcs) | ||
89 | (advice-add fn :after #'+org-wc-update))) | ||
90 | (progn ; turn off | ||
91 | (remove-hook 'after-change-functions #'+org-wc-delayed-update t) | ||
92 | (kill-local-variable '+modeline-position-function) | ||
93 | (dolist (fn +org-wc-update-after-funcs) | ||
94 | (advice-remove fn #'+org-wc-update))))) | ||
95 | |||
96 | (provide '+org-wc) | ||
97 | ;;; +org-wc.el ends here | ||