aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNoah Friedman1994-07-18 07:37:18 +0000
committerNoah Friedman1994-07-18 07:37:18 +0000
commit4cf64c15e59e8fa7a5bec836aed35442843c9d88 (patch)
tree2c9548cfb5bf2f2635968f5f21fcda95bb249f4e
parenta9c82aaf4137beca79b06b9339badc9208e34f73 (diff)
downloademacs-4cf64c15e59e8fa7a5bec836aed35442843c9d88.tar.gz
emacs-4cf64c15e59e8fa7a5bec836aed35442843c9d88.zip
type-break-mode: New variable and function.
type-break-interval: Increase default to 1 hour. type-break-query-interval: Variable renamed from type-break-delay-interval. type-break-keystroke-interval: Variable deleted. type-break-keystroke-threshold: New variable. type-break-demo-life: Function renamed from type-break-life. type-break-demo-hanoi: Function renamed from type-break-hanoi. type-break-alarm-p: Variable renamed from type-break-p. type-break: Don't query. type-break-query: (New function) query here. type-break-check: Call type-break-query, not type-break. Do nothing if type-break-mode is nil. Increment type-break-keystroke-count with the length of this-command-keys, not just 1. Query for break when keystroke count exceeds cdr of keystroke threshold variable. Query for break after an alarm only if keystroke count exceeds car of keystroke threshold variable. type-break-select: Function deleted. type-break: Move that code here. type-break-cancel-schedule: Function renamed from cancel-type-break. Reset type-break-alarm-p. type-break-alarm: Function renamed from type-break-soon. (top level): Call type-break-mode; don't set up hook explicitly.
-rw-r--r--lisp/type-break.el284
1 files changed, 192 insertions, 92 deletions
diff --git a/lisp/type-break.el b/lisp/type-break.el
index 47da688ad0c..7390613498a 100644
--- a/lisp/type-break.el
+++ b/lisp/type-break.el
@@ -1,4 +1,4 @@
1;;; type-break.el --- take breaks from typing 1;;; type-break.el --- take breaks from typing at appropriate intervals
2 2
3;;; Copyright (C) 1994 Roland McGrath 3;;; Copyright (C) 1994 Roland McGrath
4;;; Copyright (C) 1994 Noah S. Friedman 4;;; Copyright (C) 1994 Noah S. Friedman
@@ -6,9 +6,15 @@
6;;; Author: Noah Friedman <friedman@prep.ai.mit.edu> 6;;; Author: Noah Friedman <friedman@prep.ai.mit.edu>
7;;; Roland McGrath <roland@prep.ai.mit.edu> 7;;; Roland McGrath <roland@prep.ai.mit.edu>
8;;; Maintainer: friedman@prep.ai.mit.edu 8;;; Maintainer: friedman@prep.ai.mit.edu
9;;; Keywords: extensions, timer, RSI, CTS, tendinitis, suffering, pain 9;;; Keywords: extensions, timers
10;;; Status: works in GNU Emacs 19
10;;; Created: 1994-07-13 11;;; Created: 1994-07-13
11 12
13;;; LCD Archive Entry:
14;;; type-break|Noah Friedman|friedman@prep.ai.mit.edu|
15;;; take breaks from typing at appropriate intervals|
16;;; $Date$|$Revision$||
17
12;;; $Id$ 18;;; $Id$
13 19
14;;; This program is free software; you can redistribute it and/or modify 20;;; This program is free software; you can redistribute it and/or modify
@@ -27,43 +33,62 @@
27;;; Inc.; 675 Massachusetts Avenue; Cambridge, MA 02139, USA. 33;;; Inc.; 675 Massachusetts Avenue; Cambridge, MA 02139, USA.
28 34
29;;; Commentary: 35;;; Commentary:
30
31;;; Based on Roland McGrath's hanoi-break.el (unreleased).
32;;; The idea for keystroke recording was suggested by
33;;; Mark Ashton <mpashston@gnu.ai.mit.edu>
34
35;;; Code: 36;;; Code:
36 37
37 38
38(require 'timer) 39(require 'timer)
39 40
40;;;###autoload 41;;;###autoload
41(defvar type-break-interval (* 60 30) 42(defvar type-break-mode t
42 "*Number of seconds between typing breaks.") 43 "*Non-`nil' means typing break mode is enabled.
44See the docstring for the `type-break-mode' command for more information.")
45
46;;;###autoload
47(defvar type-break-interval (* 60 60)
48 "*Number of seconds between scheduled typing breaks.")
43 49
44;;;###autoload 50;;;###autoload
45(defvar type-break-delay-interval 60 51(defvar type-break-query-interval 60
46 "*Number of seconds between queries to take a break, if put off. 52 "*Number of seconds between queries to take a break, if put off.
47The user will continue to be prompted at this interval until he or she 53The user will continue to be prompted at this interval until he or she
48finally submits to taking a typing break.") 54finally submits to taking a typing break.")
49 55
50;; Assuming average typing speed is 45wpm, default this to the average
51;; number of keystrokes one is likely to type in a break interval.
52;; That way if the user goes through a furious burst of typing activity,
53;; cause a typing break to be required sooner than originally scheduled.
54;;;###autoload 56;;;###autoload
55(defvar type-break-keystroke-interval (* 45 (/ type-break-interval 60)) 57(defvar type-break-keystroke-threshold
56 "*Number of keystrokes to record before querying for a typing break. 58 ;; Assuming average typing speed is 45wpm and the average word length is
57If not a number, don't keep track of keystrokes. 59 ;; about 5 letters, default upper threshold to the average number of
58 60 ;; keystrokes one is likely to type in a break interval. That way if the
59Actually, this is not the number of keystrokes per se, but the number of 61 ;; user goes through a furious burst of typing activity, cause a typing
60interactive commands (including self-inserting characters typed). 62 ;; break to be required sooner than originally scheduled.
61Compound key bindings like C-x C-f count as a single command even though 63 ;; Conversely, the minimum threshold should be about a quarter of this.
62that consists of multiple keystrokes.") 64 (let* ((wpm 45)
65 (avg-word-length 5)
66 (upper (* wpm avg-word-length (/ type-break-interval 60)))
67 (lower (/ upper 4)))
68 (cons lower upper))
69 "*Upper and lower bound on number of keystrokes for considering typing break.
70
71This structure is a pair of numbers. The first number is the minimum
72number of keystrokes that must have been entered since the last typing
73break before considering another one, even if the scheduled time has
74elapsed; the break is simply rescheduled until later if the minimum
75threshold hasn't been reached.
76
77The second number is the maximum number of keystrokes that can be entered
78before a typing break is requested immediately, pre-empting the originally
79scheduled break.
80
81Keys with bucky bits (shift, control, meta, etc) are counted as only one
82keystroke even though they really require multiple keys to generate them.")
63 83
64;;;###autoload 84;;;###autoload
85(defvar type-break-query-function 'yes-or-no-p
86 "*Function to use for making query for a typing break.
87It should take a string as an argument, the prompt.
88Usually this should be set to `yes-or-no-p' or `y-or-n-p'.")
89
65(defvar type-break-demo-function-vector 90(defvar type-break-demo-function-vector
66 [type-break-life type-break-hanoi] 91 [type-break-demo-life type-break-demo-hanoi]
67 "*Vector consisting of functions to run as demos during typing breaks. 92 "*Vector consisting of functions to run as demos during typing breaks.
68When a typing break begins, one of these functions is selected randomly 93When a typing break begins, one of these functions is selected randomly
69to have emacs do something interesting. 94to have emacs do something interesting.
@@ -71,106 +96,181 @@ to have emacs do something interesting.
71Any function in this vector should start a demo which ceases as soon as a 96Any function in this vector should start a demo which ceases as soon as a
72key is pressed.") 97key is pressed.")
73 98
74;; The original motivation for this variable was that in emacs 19.25 (or 99;; These are internal variables. Do not set them yourself.
75;; perhaps just in unreleased versions of emacs 19.26), the function
76;; keyboard.c:safe_run_hooks wasn't reentrant, so that running yes-or-no-p
77;; from a post-command-hook caused the inferior command loop to wipe out
78;; the original value of the hook. That was fixed, but it occured to me
79;; that some people might prefer y-or-n-p.
80;;;###autoload
81(defvar type-break-query-function 'yes-or-no-p
82 "*Function to use for making query for a typing break.
83Usually this will be `yes-or-no-p' or `y-or-n-p'.")
84
85;; The rest are internal variables. Do not set them yourself.
86 100
87;; Number of commands (roughly # of keystrokes) recorded since last break. 101;; Number of commands (roughly # of keystrokes) recorded since last break.
88(defvar type-break-keystroke-count 0) 102(defvar type-break-keystroke-count 0)
89 103
90;; Non-nil if we need a typing break soon. 104;; Non-nil when a scheduled typing break is due.
91(defvar type-break-p nil) 105(defvar type-break-alarm-p nil)
92 106
93 107
94;;;###autoload 108;;;###autoload
109(defun type-break-mode (&optional prefix)
110 "Enable or disable typing-break mode.
111This is a minor mode, but it is global to all buffers by default.
112
113When this mode is enabled, the user is encouraged to take typing breaks at
114appropriate intervals; either after a specified amount of time or when the
115user has exceeded a keystroke threshold. When the time arrives, the user
116is asked to take a break. If the user refuses at that time, emacs will ask
117again in a short period of time. The idea is to give the user enough time
118to find a good breaking point in his or her work, but be sufficiently
119annoying to discourage putting typing breaks off indefinitely.
120
121Calling this command with no prefix argument toggles this mode.
122A negative prefix argument disables this mode.
123A non-negative prefix argument or any other non-`nil' argument enables it.
124
125The user may enable or disable this mode by setting the variable of the
126same name, though setting it in that way doesn't reschedule a break or
127reset the keystroke counter.
128
129When this function enables the mode, it schedules a break with
130`type-break-schedule' to make sure one occurs (the user can call that
131command to reschedule the break at any time). It also initializes the
132keystroke counter.
133
134The variable `type-break-interval' specifies the number of seconds to
135schedule between regular typing breaks. This variable doesn't directly
136affect the time schedule; it simply provides a default for the
137`type-break-schedule' command.
138
139The variable `type-break-query-interval' specifies the number of seconds to
140schedule between repeated queries for breaks when the user answers \"no\"
141to the previous query.
142
143The variable `type-break-keystroke-theshold' is used to determine the
144thresholds at which typing breaks should be considered.
145
146The variable `type-break-query-function' should contain a function (or the
147symbolic name of a function) to be used to query the user for typing
148breaks."
149 (interactive "P")
150 ;; make sure it's there.
151 (add-hook 'post-command-hook 'type-break-check 'append)
152
153 (cond
154 ((null prefix)
155 (setq type-break-mode (not type-break-mode)))
156 ((numberp (prefix-numeric-value prefix))
157 (setq type-break-mode (>= (prefix-numeric-value prefix) 0)))
158 (prefix
159 (setq type-break-mode t))
160 (t
161 (setq type-break-mode nil)))
162
163 (cond
164 (type-break-mode
165 (setq type-break-keystroke-count 0)
166 (type-break-schedule)
167 (and (interactive-p)
168 (message "type-break-mode is enabled and reset")))
169 ((interactive-p)
170 (message "type-break-mode is disabled")))
171
172 type-break-mode)
173
174;;;###autoload
95(defun type-break () 175(defun type-break ()
96 "Take a typing break. 176 "Take a typing break.
97 177
98If `type-break-delay-interval' seconds have passed since the last typing 178During the break, a demo selected from the functions listed in
99break, or `type-break-keystroke-interval' keystrokes have been recorded 179`type-break-demo-function-vector' is run.
100since the last typing break, ask the user to take a break now.
101 180
102The user can refuse by answering \"no\", in which case another query will 181After the typing break is finished, the next break is scheduled
103be made in `type-break-delay-interval' seconds. 182as per the function `type-break-schedule', and the keystroke counter is
104 183reset."
105During the typing break, a demo selected from the functions listed in
106`type-break-demo-function-vector' is run."
107 (interactive) 184 (interactive)
108 (setq type-break-p nil)
109 (setq type-break-keystroke-count 0)
110 (cancel-type-break)
111 (save-window-excursion 185 (save-window-excursion
112 (condition-case () 186 ;; Eat the screen.
113 (cond 187 (and (eq (selected-window) (minibuffer-window))
114 ((funcall type-break-query-function "Take a break from typing now? ") 188 (other-window 1))
115 ;; Eat the screen. 189 (delete-other-windows)
116 (and (eq (selected-window) (minibuffer-window)) 190 (scroll-right (window-width))
117 (other-window 1)) 191 (message "Press any key to finish typing break.")
118 (delete-other-windows) 192
119 (scroll-right (window-width)) 193 (random t)
120 (message "Take a break from typing.") 194 (let* ((len (length type-break-demo-function-vector))
121 (type-break-select) 195 (idx (random len))
122 (type-break-schedule)) 196 (fn (aref type-break-demo-function-vector idx)))
123 (t 197 (condition-case ()
124 (type-break-schedule type-break-delay-interval))) 198 (funcall fn)
125 (quit 199 (error nil)))
126 (type-break-schedule type-break-delay-interval))))) 200
127 201 (setq type-break-keystroke-count 0)
128(defun type-break-select () 202 (type-break-schedule)))
129 (random t)
130 (let* ((len (length type-break-demo-function-vector))
131 (idx (random len))
132 (fn (aref type-break-demo-function-vector idx)))
133 (condition-case ()
134 (funcall fn)
135 (error nil))))
136 203
137 204
138;;;###autoload 205;;;###autoload
139(defun type-break-schedule (&optional time) 206(defun type-break-schedule (&optional time)
140 "Schedule a typing break TIME seconds from now. 207 "Schedule a typing break for TIME seconds from now.
141If time is not specified, default to type-break-interval." 208If time is not specified, default to `type-break-interval'."
142 (interactive (list (and current-prefix-arg 209 (interactive (list (and current-prefix-arg
143 (prefix-numeric-value current-prefix-arg)))) 210 (prefix-numeric-value current-prefix-arg))))
144 (or time (setq time type-break-interval)) 211 (or time (setq time type-break-interval))
145 ;; Remove any old scheduled break 212 ;; Remove any old scheduled break
146 (cancel-type-break) 213 (type-break-cancel-schedule)
147 (run-at-time time nil 'type-break-soon)) 214 (run-at-time time nil 'type-break-alarm))
148 215
149(defun cancel-type-break () 216(defun type-break-cancel-schedule ()
150 "Cancel scheduled typing breaks." 217 "Cancel scheduled typing breaks.
218This does not prevent queries for typing breaks when the keystroke
219threshold has been reached; to turn off typing breaks altogether, turn off
220type-break-mode."
151 (interactive) 221 (interactive)
152 (let ((timer-dont-exit t)) 222 (let ((timer-dont-exit t))
153 (cancel-function-timers 'type-break-soon))) 223 (cancel-function-timers 'type-break-alarm))
224 (setq type-break-alarm-p nil))
154 225
155(defun type-break-soon () 226(defun type-break-alarm ()
156 "Take a typing break very soon." 227 "This function is run when a scheduled typing break is due."
157 (setq type-break-p t)) 228 (setq type-break-alarm-p t))
158 229
159(defun type-break-check () 230(defun type-break-check ()
160 "Take a typing break if the time has come." 231 "Ask to take a typing break if appropriate.
161 (setq type-break-keystroke-count (1+ type-break-keystroke-count)) 232This may be the case either because the scheduled time has come \(and the
233minimum keystroke threshold has been reached\) or because the maximum
234keystroke threshold has been exceeded."
162 (cond 235 (cond
163 ((input-pending-p)) 236 (type-break-mode
164 ((or type-break-p 237 (let* ((pair (and (consp type-break-keystroke-threshold)
165 (and (natnump type-break-keystroke-interval) 238 type-break-keystroke-threshold))
166 (> type-break-keystroke-count type-break-keystroke-interval))) 239 (min-threshold (car pair))
167 (type-break)))) 240 (max-threshold (cdr pair)))
241 (and pair
242 (stringp (this-command-keys))
243 (setq type-break-keystroke-count
244 (+ type-break-keystroke-count (length (this-command-keys)))))
245 (cond
246 ((input-pending-p))
247 ((and (numberp max-threshold)
248 (> type-break-keystroke-count max-threshold))
249 (setq type-break-keystroke-count 0)
250 (type-break-query))
251 (type-break-alarm-p
252 (cond
253 ((and (numberp min-threshold)
254 (< type-break-keystroke-count min-threshold)))
255 (t
256 (setq type-break-keystroke-count 0)
257 (type-break-query)))))))))
258
259(defun type-break-query ()
260 (condition-case ()
261 (cond
262 ((funcall type-break-query-function "Take a break from typing now? ")
263 (type-break))
264 (t
265 (type-break-schedule type-break-query-interval)))
266 (quit
267 (type-break-schedule type-break-query-interval))))
168 268
169 269
170;; This is a wrapper around hanoi that calls it with an arg large enough to 270;; This is a wrapper around hanoi that calls it with an arg large enough to
171;; make the largest discs possible that will fit in the window. 271;; make the largest discs possible that will fit in the window.
172;; Also, clean up the *Hanoi* buffer after we're done. 272;; Also, clean up the *Hanoi* buffer after we're done.
173(defun type-break-hanoi () 273(defun type-break-demo-hanoi ()
174 "Take a hanoiing typing break." 274 "Take a hanoiing typing break."
175 (and (get-buffer "*Hanoi*") 275 (and (get-buffer "*Hanoi*")
176 (kill-buffer "*Hanoi*")) 276 (kill-buffer "*Hanoi*"))
@@ -187,7 +287,7 @@ If time is not specified, default to type-break-interval."
187;; This is a wrapper around life that calls it with a `sleep' arg to make 287;; This is a wrapper around life that calls it with a `sleep' arg to make
188;; it run a little more leisurely. 288;; it run a little more leisurely.
189;; Also, clean up the *Life* buffer after we're done. 289;; Also, clean up the *Life* buffer after we're done.
190(defun type-break-life () 290(defun type-break-demo-life ()
191 "Take a typing break and get a life." 291 "Take a typing break and get a life."
192 (and (get-buffer "*Life*") 292 (and (get-buffer "*Life*")
193 (kill-buffer "*Life*")) 293 (kill-buffer "*Life*"))
@@ -204,6 +304,6 @@ If time is not specified, default to type-break-interval."
204 304
205(provide 'type-break) 305(provide 'type-break)
206 306
207(add-hook 'post-command-hook 'type-break-check 'append) 307(type-break-mode t)
208 308
209;;; type-break.el ends here 309;;; type-break.el ends here