-
Notifications
You must be signed in to change notification settings - Fork 0
/
partial-recall-concentration.el
194 lines (140 loc) · 6.55 KB
/
partial-recall-concentration.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
;;; partial-recall-concentration.el --- Focus through concentration -*- lexical-binding: t; -*-
;; Author: Krister Schuchardt <krister.schuchardt@gmail.com>
;; Homepage: https://github.com/Walheimat/partial-recall
;; Version: 0.11.0
;; Package-Requires: ((emacs "29.1"))
;; Keywords: frames files convenience
;;; Commentary:
;; This is an optional behavior that increases a moment's focus when
;; it remains visible over long periods of time.
;;; Code:
(require 'partial-recall)
;;; Customization
(defcustom partial-recall-concentration-cycle 60
"Number of seconds a cycle of concentration takes.
If a buffer remains visible from when the cycle began until it
ends, its focus is increased. Can be set to nil to disable
concentration."
:type '(choice (integer :tag "Number of seconds")
(const :tag "Don't use" nil))
:group 'partial-recall)
;;; Variables
(defvar partial-recall--faint-focus nil
"The moment focused before concentration broke.")
(defvar partial-recall-concentration--timer nil
"Timer after which concentration will be checked.")
(defvar partial-recall-concentration--deferred nil
"Timer after which it is checked if concentration may resume.")
;;; Errors
(define-error 'partial-recall-concentration-not-owned "Buffer is not owned" 'partial-recall-errors)
(define-error 'partial-recall-concentration-changed "Buffer has changed" 'partial-recall-errors)
(define-error 'partial-recall-concentration-not-ready "No reality" 'partial-recall-errors)
(defun partial-recall-concentration--concentrate ()
"Concentrate on the current moment.
If the moment has remained the same since the last cycle, its
focus is intensified, otherwise concentration breaks and the now
current moment is focused."
(condition-case err
(progn
(partial-recall-concentration--hold)
;; Move faint to last focus if it exists.
(when partial-recall--faint-focus
(setq partial-recall--last-focus partial-recall--faint-focus
partial-recall--faint-focus nil)
(partial-recall-concentration--renew))
(partial-recall-moment--intensify partial-recall--last-focus 'concentrate))
((partial-recall-concentration-not-ready partial-recall-concentration-not-owned)
(partial-recall-concentration--defer))
(partial-recall-concentration-changed
(let ((moment (cdr err)))
(when-let ((lost (or partial-recall--faint-focus partial-recall--last-focus)))
(partial-recall-debug "Concentration on `%s' broke" lost))
(partial-recall-concentration--renew)
(partial-recall-debug "Concentration on `%s' begins" moment)
(setq partial-recall--last-focus moment
partial-recall--faint-focus nil)))))
(defun partial-recall-concentration--hold ()
"Try to hold concentration."
(unless (partial-recall--reality)
(signal 'partial-recall-concentration-not-ready nil))
(let* ((buffer (current-buffer))
(moment (partial-recall--find-owning-moment buffer))
(focus (or partial-recall--last-focus partial-recall--faint-focus)))
(unless (or moment (partial-recall--buffer-in-memory-p buffer))
(signal 'partial-recall-concentration-not-owned buffer))
(unless (and focus
(or (eq moment focus)
(partial-recall--buffer-visible-p
(partial-recall-moment--buffer focus))))
(signal 'partial-recall-concentration-changed moment))
(partial-recall-debug "Concentration held on `%s'" focus)))
(defun partial-recall-concentration--defer ()
"Defer concentration.
This restarts the cycle with a much shorter repeat time until
concentration on a moment can begin. The last focus is retained
as a faint focus.
If deferring is already in place, the faint focus is lost as
well."
(if partial-recall-concentration--deferred
(setq partial-recall--faint-focus nil)
(partial-recall-debug "Deferring concentration")
(setq partial-recall-concentration--deferred t
partial-recall--faint-focus partial-recall--last-focus
partial-recall--last-focus nil)
(partial-recall-concentration--start nil (/ partial-recall-concentration-cycle 10))))
(defun partial-recall-concentration--renew ()
"Renew concentration cycle."
(when partial-recall-concentration--deferred
(partial-recall-debug "Aborting deferred concentration")
(setq partial-recall-concentration--deferred nil)
(partial-recall-concentration--start partial-recall-concentration-cycle)))
(defun partial-recall-concentration--shift (name)
"Re-concentrate after switching to NAME.
This cancels and re-runs the timer."
(partial-recall-debug "Shifting concentration towards `%s'" name)
(partial-recall-concentration--start))
(defun partial-recall-concentration--start (&optional secs repeat)
"Start concentrating.
This cancels a previously running timer.
Optionally SECS and REPEAT can be passed which are passed along
to `run-with-timer'. They default to
`partial-recall-handle-delay' and
`partial-recall-concentration-cycle'."
(when partial-recall-concentration--timer
(cancel-timer partial-recall-concentration--timer))
(when-let ((secs (or secs partial-recall-handle-delay))
(repeat (or repeat partial-recall-concentration-cycle)))
(setq partial-recall-concentration--timer (run-with-timer
(1+ secs)
(1+ repeat)
#'partial-recall-concentration--concentrate))))
;;;; Mode
(defun partial-recall-concentration--setup ()
"Setup `partial-recall-concentration-mode'."
(when (partial-recall--reality)
(partial-recall-concentration--concentrate))
(add-hook
'partial-recall-after-create-hook
#'partial-recall-concentration--shift)
(add-hook
'partial-recall-after-reality-change-hook
#'partial-recall-concentration--shift))
(defun partial-recall-concentration--teardown ()
"Tear down `partial-recall-concentration-mode'."
(cancel-timer partial-recall-concentration--timer)
(remove-hook
'partial-recall-after-create-hook
#'partial-recall-concentration--shift)
(remove-hook
'partial-recall-after-reality-change-hook
#'partial-recall-concentration--shift))
;;;###autoload
(define-minor-mode partial-recall-concentration-mode
"Mode that increases a moment's focus through concentration."
:group 'partial-recall
:global t
(if partial-recall-concentration-mode
(partial-recall-concentration--setup)
(partial-recall-concentration--teardown)))
(provide 'partial-recall-concentration)
;;; partial-recall-concentration.el ends here