summary refs log tree commit diff stats
path: root/lisp/+org-wc.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/+org-wc.el')
-rw-r--r--lisp/+org-wc.el97
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