aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lisp/type-break.el353
1 files changed, 278 insertions, 75 deletions
diff --git a/lisp/type-break.el b/lisp/type-break.el
index 690f0842a39..26fec87a702 100644
--- a/lisp/type-break.el
+++ b/lisp/type-break.el
@@ -5,9 +5,9 @@
5;; Author: Noah Friedman <friedman@prep.ai.mit.edu> 5;; Author: Noah Friedman <friedman@prep.ai.mit.edu>
6;; Maintainer: friedman@prep.ai.mit.edu 6;; Maintainer: friedman@prep.ai.mit.edu
7;; Keywords: extensions, timers 7;; Keywords: extensions, timers
8;; Status: known to work in GNU Emacs 19.25 or later. 8;; Status: Works in GNU Emacs 19.25 or later
9;; Created: 1994-07-13 9;; Created: 1994-07-13
10;; $Id$ 10;; $Id: type-break.el,v 1.10 1994/10/06 19:12:46 friedman Exp friedman $
11 11
12;; This file is part of GNU Emacs. 12;; This file is part of GNU Emacs.
13 13
@@ -22,24 +22,37 @@
22;; GNU General Public License for more details. 22;; GNU General Public License for more details.
23 23
24;; You should have received a copy of the GNU General Public License 24;; You should have received a copy of the GNU General Public License
25;; along with GNU Emacs; see the file COPYING. If not, write to 25;; along with GNU Emacs; see the file COPYING. If not, write to the
26;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 26;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
27;; Boston, MA 02111-1307, USA.
27 28
28;;; Commentary: 29;;; Commentary:
29 30
30;;; The docstring for the function `type-break-mode' summarizes most of the 31;; The docstring for the function `type-break-mode' summarizes most of the
31;;; details of the interface. 32;; details of the interface.
32 33
33;;; This package relies on the assumption that you live entirely in emacs, 34;; This package relies on the assumption that you live entirely in emacs,
34;;; as the author does. If that's not the case for you (e.g. you often 35;; as the author does. If that's not the case for you (e.g. you often
35;;; suspend emacs or work in other windows) then this won't help very much; 36;; suspend emacs or work in other windows) then this won't help very much;
36;;; it will depend on just how often you switch back to emacs. At the very 37;; it will depend on just how often you switch back to emacs. At the very
37;;; least, you will want to turn off the keystroke thresholds and rest 38;; least, you will want to turn off the keystroke thresholds and rest
38;;; interval tracking. 39;; interval tracking.
39 40
40;;; This package was inspired by Roland McGrath's hanoi-break.el. 41;; This program has no hope of working in Emacs 18, and it doesn't
41;;; Thanks to both Roland McGrath <roland@gnu.ai.mit.edu> and Mark Ashton 42;; presently work in Lucid Emacs/XEmacs because the timer.el package is
42;;; <mpashton@gnu.ai.mit.edu> for feedback and ideas. 43;; entirely different.
44
45;; This program can truly cons up a storm because of all the calls to
46;; `current-time' (which always returns 3 fresh conses). I'm dismayed by
47;; this, but I think the health of my hands is far more important than a
48;; few pages of virtual memory.
49
50;; This package was inspired by Roland McGrath's hanoi-break.el.
51;; Several people contributed feedback and ideas, including
52;; Roland McGrath <roland@gnu.ai.mit.edu>
53;; Kleanthes Koniaris <kgk@martigny.ai.mit.edu>
54;; Mark Ashton <mpashton@gnu.ai.mit.edu>
55;; Matt Wilding <wilding@cli.com>
43 56
44;;; Code: 57;;; Code:
45 58
@@ -53,6 +66,11 @@
53 "*Non-`nil' means typing break mode is enabled. 66 "*Non-`nil' means typing break mode is enabled.
54See the docstring for the `type-break-mode' command for more information.") 67See the docstring for the `type-break-mode' command for more information.")
55 68
69(defvar type-break-warning-message-mode t
70 "*Non-`nil' means warn about imminent typing breaks in echo area.
71See the docstring for the `type-break-warning-message-mode' command for
72more information.")
73
56;;;###autoload 74;;;###autoload
57(defvar type-break-interval (* 60 60) 75(defvar type-break-interval (* 60 60)
58 "*Number of seconds between scheduled typing breaks.") 76 "*Number of seconds between scheduled typing breaks.")
@@ -99,7 +117,35 @@ scheduled break. If this second value is nil, then no pre-emptive breaks
99will occur; only scheduled ones will. 117will occur; only scheduled ones will.
100 118
101Keys with bucky bits (shift, control, meta, etc) are counted as only one 119Keys with bucky bits (shift, control, meta, etc) are counted as only one
102keystroke even though they really require multiple keys to generate them.") 120keystroke even though they really require multiple keys to generate them.
121
122The command `type-break-guesstimate-keystroke-threshold' can be used to
123guess a reasonably good pair of values for this variable.")
124
125(defvar type-break-query-function 'yes-or-no-p
126 "Function to use for making query for a typing break.
127It should take a string as an argument, the prompt.
128Usually this should be set to `yes-or-no-p' or `y-or-n-p'.
129
130Some people prefer a less intrusive way of being reminded to take a typing
131break. One possibility is simply to beep a couple of times. To accomplish
132this, one could do:
133
134 (defun my-type-break-query (&optional ignored-args)
135 (beep t)
136 (message \"You should take a typing break now. Do `M-x type-break'.\")
137 (sit-for 1)
138 (beep t)
139 ;; return nil so query caller knows to reset reminder, as if user
140 ;; said \"no\" in response to yes-or-no-p.
141 nil)
142
143 (setq type-break-query-function 'my-type-break-query)")
144
145(defvar type-break-query-interval 60
146 "*Number of seconds between queries to take a break, if put off.
147The user will continue to be prompted at this interval until he or she
148finally submits to taking a typing break.")
103 149
104(defvar type-break-time-warning-intervals '(300 120 60 30) 150(defvar type-break-time-warning-intervals '(300 120 60 30)
105 "*List of time intervals for warnings about upcoming typing break. 151 "*List of time intervals for warnings about upcoming typing break.
@@ -113,20 +159,40 @@ keystroke threshold, print a warning in the echo area.
113If either this variable or the upper threshold is set, then no warnings 159If either this variable or the upper threshold is set, then no warnings
114Will occur.") 160Will occur.")
115 161
116(defvar type-break-query-interval 60
117 "*Number of seconds between queries to take a break, if put off.
118The user will continue to be prompted at this interval until he or she
119finally submits to taking a typing break.")
120
121(defvar type-break-warning-repeat 40 162(defvar type-break-warning-repeat 40
122 "*Number of keystrokes for which warnings should be repeated. 163 "*Number of keystrokes for which warnings should be repeated.
123That is, for each of this many keystrokes the warning is redisplayed 164That is, for each of this many keystrokes the warning is redisplayed
124in the echo area to make sure it's really seen.") 165in the echo area to make sure it's really seen.")
125 166
126(defvar type-break-query-function 'yes-or-no-p 167(defvar type-break-warning-countdown-string nil
127 "Function to use for making query for a typing break. 168 "If non-nil, this is a countdown for the next typing break.
128It should take a string as an argument, the prompt. 169
129Usually this should be set to `yes-or-no-p' or `y-or-n-p'.") 170This variable, in conjunction with `type-break-warning-countdown-string-type'
171(which indicates whether this value is a number of keystrokes or seconds)
172can be installed by the user somewhere in mode-line-format to notify of
173imminent typing breaks there.
174
175For example, you could do
176
177 (defvar type-break-mode-line-string
178 '(type-break-warning-countdown-string
179 (\" ***Break in \"
180 type-break-warning-countdown-string
181 \" \"
182 type-break-warning-countdown-string-type
183 \"***\")))
184
185 (setq global-mode-string
186 (append global-mode-string '(type-break-mode-line-string)))
187
188If you do this, you may also wish to disable the warning messages in the
189minibuffer. To do this, either set the variable
190`type-break-warning-message-mode' to `nil' or call the function of the same
191name with a negative argument.")
192
193(defvar type-break-warning-countdown-string-type nil
194 "Indicates the unit type of `type-break-warning-countdown-string'.
195It will be either \"seconds\" or \"keystrokes\".")
130 196
131(defvar type-break-demo-functions 197(defvar type-break-demo-functions
132 '(type-break-demo-boring type-break-demo-life type-break-demo-hanoi) 198 '(type-break-demo-boring type-break-demo-life type-break-demo-hanoi)
@@ -138,7 +204,13 @@ Any function in this list should start a demo which ceases as soon as a
138key is pressed.") 204key is pressed.")
139 205
140(defvar type-break-post-command-hook nil 206(defvar type-break-post-command-hook nil
141 "Hook run indirectly by post-command-hook for typing break functions.") 207 "Hook run indirectly by post-command-hook for typing break functions.
208This is not really intended to be set by the user, but it's probably
209harmless to do so. Mainly it is used by various parts of the typing break
210program to delay actions until after the user has completed some command.
211It exists because `post-command-hook' itself is inaccessible while its
212functions are being run, and some type-break--related functions want to
213remove themselves after running.")
142 214
143;; These are internal variables. Do not set them yourself. 215;; These are internal variables. Do not set them yourself.
144 216
@@ -151,7 +223,45 @@ key is pressed.")
151(defvar type-break-current-keystroke-warning-interval nil) 223(defvar type-break-current-keystroke-warning-interval nil)
152(defvar type-break-time-warning-count 0) 224(defvar type-break-time-warning-count 0)
153(defvar type-break-keystroke-warning-count 0) 225(defvar type-break-keystroke-warning-count 0)
226
227;; This should return t if warnings were enabled, nil otherwise.
228(defsubst type-break-check-keystroke-warning ()
229 ;; This is safe because the caller should have checked that the cdr was
230 ;; non-nil already.
231 (let ((left (- (cdr type-break-keystroke-threshold)
232 type-break-keystroke-count)))
233 (cond
234 ((null (car type-break-current-keystroke-warning-interval))
235 nil)
236 ((> left (car type-break-current-keystroke-warning-interval))
237 nil)
238 (t
239 (while (and (car type-break-current-keystroke-warning-interval)
240 (< left (car type-break-current-keystroke-warning-interval)))
241 (setq type-break-current-keystroke-warning-interval
242 (cdr type-break-current-keystroke-warning-interval)))
243 (setq type-break-keystroke-warning-count type-break-warning-repeat)
244 (add-hook 'type-break-post-command-hook 'type-break-keystroke-warning)
245 (setq type-break-warning-countdown-string (number-to-string left))
246 (setq type-break-warning-countdown-string-type "keystrokes")
247 t))))
248
249;; Compute the difference, in seconds, between a and b, two structures
250;; similar to those returned by `current-time'.
251;; Use addition rather than logand since that is more robust; the low 16
252;; bits of the seconds might have been incremented, making it more than 16
253;; bits wide.
254(defsubst type-break-time-difference (a b)
255 (+ (lsh (- (car b) (car a)) 16)
256 (- (car (cdr b)) (car (cdr a)))))
154 257
258(defsubst type-break-format-time (secs)
259 (let ((mins (/ secs 60)))
260 (cond
261 ((= mins 1) (format "%d minute" mins))
262 ((> mins 0) (format "%d minutes" mins))
263 ((= secs 1) (format "%d second" secs))
264 (t (format "%d seconds" secs)))))
155 265
156;;;###autoload 266;;;###autoload
157(defun type-break-mode (&optional prefix) 267(defun type-break-mode (&optional prefix)
@@ -192,9 +302,25 @@ or not to continue.
192 302
193The variable `type-break-keystroke-threshold' is used to determine the 303The variable `type-break-keystroke-threshold' is used to determine the
194thresholds at which typing breaks should be considered. You can use 304thresholds at which typing breaks should be considered. You can use
195the command `type-break-guestimate-keystroke-threshold' to try to 305the command `type-break-guesstimate-keystroke-threshold' to try to
196approximate good values for this. 306approximate good values for this.
197 307
308There are several variables that affect how or when warning messages about
309imminent typing breaks are displayed. They include:
310
311 type-break-warning-message-mode
312 type-break-time-warning-intervals
313 type-break-keystroke-warning-intervals
314 type-break-warning-repeat
315 type-break-warning-countdown-string
316 type-break-warning-countdown-string-type
317
318There are several variables that affect how and when queries to begin a
319typing break occur. They include:
320
321 type-break-query-function
322 type-break-query-interval
323
198Finally, the command `type-break-statistics' prints interesting things." 324Finally, the command `type-break-statistics' prints interesting things."
199 (interactive "P") 325 (interactive "P")
200 ;; make sure it's there. 326 ;; make sure it's there.
@@ -217,6 +343,24 @@ Finally, the command `type-break-statistics' prints interesting things."
217 (message "type-break-mode is disabled")))) 343 (message "type-break-mode is disabled"))))
218 type-break-mode) 344 type-break-mode)
219 345
346(defun type-break-warning-message-mode (&optional prefix)
347 "Enable or disable warnings in the echo area about imminent typing breaks.
348
349A negative prefix argument disables this mode.
350No argument or any non-negative argument enables it.
351
352The user may also enable or disable this mode simply by setting the
353variable of the same name."
354 (interactive "P")
355 (setq type-break-warning-message-mode (>= (prefix-numeric-value prefix) 0))
356 (cond
357 ((not (interactive-p)))
358 (type-break-warning-message-mode
359 (message "type-break-warning-message-mode is enabled"))
360 (t
361 (message "type-break-warning-message-mode is disabled")))
362 type-break-warning-message-mode)
363
220;;;###autoload 364;;;###autoload
221(defun type-break () 365(defun type-break ()
222 "Take a typing break. 366 "Take a typing break.
@@ -255,10 +399,11 @@ as per the function `type-break-schedule'."
255 (cond 399 (cond
256 ((>= break-secs type-break-good-rest-interval) 400 ((>= break-secs type-break-good-rest-interval)
257 (setq continue nil)) 401 (setq continue nil))
258 ;; Don't be pedantic; if user's rest was only a minute short, 402 ;; 60 seconds may be too much leeway if the break is only 3
259 ;; why bother? 403 ;; minutes to begin with. You can just say "no" to the query
260 ((> 60 (abs (- break-secs type-break-good-rest-interval))) 404 ;; below if you're in that much of a hurry.
261 (setq continue nil)) 405 ;((> 60 (abs (- break-secs type-break-good-rest-interval)))
406 ; (setq continue nil))
262 ((funcall 407 ((funcall
263 type-break-query-function 408 type-break-query-function
264 (format "You really ought to rest %s more. Continue break? " 409 (format "You really ought to rest %s more. Continue break? "
@@ -278,9 +423,11 @@ If time is not specified, default to `type-break-interval'."
278 (interactive (list (and current-prefix-arg 423 (interactive (list (and current-prefix-arg
279 (prefix-numeric-value current-prefix-arg)))) 424 (prefix-numeric-value current-prefix-arg))))
280 (or time (setq time type-break-interval)) 425 (or time (setq time type-break-interval))
426 (let ((type-break-mode t))
427 (type-break-mode 1))
281 (type-break-cancel-schedule) 428 (type-break-cancel-schedule)
282 (type-break-time-warning-schedule time 'reset) 429 (type-break-time-warning-schedule time 'reset)
283 (run-at-time time nil 'type-break-alarm) 430 (run-at-time (max 1 time) nil 'type-break-alarm)
284 (setq type-break-time-next-break 431 (setq type-break-time-next-break
285 (type-break-time-sum (current-time) time))) 432 (type-break-time-sum (current-time) time)))
286 433
@@ -292,7 +439,7 @@ If time is not specified, default to `type-break-interval'."
292 (setq type-break-time-next-break nil)) 439 (setq type-break-time-next-break nil))
293 440
294(defun type-break-time-warning-schedule (&optional time resetp) 441(defun type-break-time-warning-schedule (&optional time resetp)
295 (let (type-break-current-time-warning-interval) 442 (let ((type-break-current-time-warning-interval nil))
296 (type-break-cancel-time-warning-schedule)) 443 (type-break-cancel-time-warning-schedule))
297 (cond 444 (cond
298 (type-break-time-warning-intervals 445 (type-break-time-warning-intervals
@@ -315,21 +462,33 @@ If time is not specified, default to `type-break-interval'."
315 (setq type-break-current-time-warning-interval 462 (setq type-break-current-time-warning-interval
316 (cdr type-break-current-time-warning-interval)) 463 (cdr type-break-current-time-warning-interval))
317 464
318 (let (type-break-current-time-warning-interval) 465 ;(let (type-break-current-time-warning-interval)
319 (type-break-cancel-time-warning-schedule)) 466 ; (type-break-cancel-time-warning-schedule))
320 (run-at-time time nil 'type-break-time-warning-alarm)))))) 467 (run-at-time (max 1 time) nil 'type-break-time-warning-alarm)
468
469 (cond
470 (resetp
471 (setq type-break-warning-countdown-string nil))
472 (t
473 (setq type-break-warning-countdown-string (number-to-string time))
474 (setq type-break-warning-countdown-string-type "seconds"))))))))
321 475
322(defun type-break-cancel-time-warning-schedule () 476(defun type-break-cancel-time-warning-schedule ()
323 (let ((timer-dont-exit t)) 477 (let ((timer-dont-exit t))
324 (cancel-function-timers 'type-break-time-warning-alarm)) 478 (cancel-function-timers 'type-break-time-warning-alarm))
325 (remove-hook 'type-break-post-command-hook 'type-break-time-warning) 479 (remove-hook 'type-break-post-command-hook 'type-break-time-warning)
326 (setq type-break-current-time-warning-interval 480 (setq type-break-current-time-warning-interval
327 type-break-time-warning-intervals)) 481 type-break-time-warning-intervals)
482 (setq type-break-warning-countdown-string nil))
328 483
329(defun type-break-alarm () 484(defun type-break-alarm ()
485 (let ((type-break-mode t))
486 (type-break-mode 1))
330 (setq type-break-alarm-p t)) 487 (setq type-break-alarm-p t))
331 488
332(defun type-break-time-warning-alarm () 489(defun type-break-time-warning-alarm ()
490 (let ((type-break-mode t))
491 (type-break-mode 1))
333 (type-break-time-warning-schedule) 492 (type-break-time-warning-schedule)
334 (setq type-break-time-warning-count type-break-warning-repeat) 493 (setq type-break-time-warning-count type-break-warning-repeat)
335 (add-hook 'type-break-post-command-hook 'type-break-time-warning 'append)) 494 (add-hook 'type-break-post-command-hook 'type-break-time-warning 'append))
@@ -358,12 +517,16 @@ keystroke threshold has been exceeded."
358 (setq type-break-time-last-command (current-time)))) 517 (setq type-break-time-last-command (current-time))))
359 518
360 (and type-break-keystroke-threshold 519 (and type-break-keystroke-threshold
361 (setq type-break-keystroke-count 520 (let ((keys (this-command-keys)))
362 (+ type-break-keystroke-count (length (this-command-keys))))) 521 (cond
522 ;; Ignore mouse motion
523 ((and (vectorp keys)
524 (consp (aref keys 0))
525 (memq (car (aref keys 0)) '(mouse-movement))))
526 (t
527 (setq type-break-keystroke-count
528 (+ type-break-keystroke-count (length keys)))))))
363 529
364 ;; This has been optimized for speed; calls to input-pending-p and
365 ;; checking for the minibuffer window are only done if it would
366 ;; matter for the sake of querying user.
367 (cond 530 (cond
368 (type-break-alarm-p 531 (type-break-alarm-p
369 (cond 532 (cond
@@ -374,7 +537,7 @@ keystroke threshold has been exceeded."
374 (type-break-schedule)) 537 (type-break-schedule))
375 (t 538 (t
376 ;; If keystroke count is within min-threshold of 539 ;; If keystroke count is within min-threshold of
377 ;; max-threshold, lower it to reduce the liklihood of an 540 ;; max-threshold, lower it to reduce the likelihood of an
378 ;; immediate subsequent query. 541 ;; immediate subsequent query.
379 (and max-threshold 542 (and max-threshold
380 min-threshold 543 min-threshold
@@ -397,6 +560,8 @@ keystroke threshold has been exceeded."
397 560
398;; This should return t if warnings were enabled, nil otherwise. 561;; This should return t if warnings were enabled, nil otherwise.
399(defsubst type-break-check-keystroke-warning () 562(defsubst type-break-check-keystroke-warning ()
563 ;; This is safe because the caller should have checked that the cdr was
564 ;; non-nil already.
400 (let ((left (- (cdr type-break-keystroke-threshold) 565 (let ((left (- (cdr type-break-keystroke-threshold)
401 type-break-keystroke-count))) 566 type-break-keystroke-count)))
402 (cond 567 (cond
@@ -411,44 +576,69 @@ keystroke threshold has been exceeded."
411 (cdr type-break-current-keystroke-warning-interval))) 576 (cdr type-break-current-keystroke-warning-interval)))
412 (setq type-break-keystroke-warning-count type-break-warning-repeat) 577 (setq type-break-keystroke-warning-count type-break-warning-repeat)
413 (add-hook 'type-break-post-command-hook 'type-break-keystroke-warning) 578 (add-hook 'type-break-post-command-hook 'type-break-keystroke-warning)
579 (setq type-break-warning-countdown-string (number-to-string left))
580 (setq type-break-warning-countdown-string-type "keystrokes")
414 t)))) 581 t))))
415 582
583;; Arrange for a break query to be made, when the user stops typing furiously.
416(defun type-break-query () 584(defun type-break-query ()
417 (condition-case () 585 (add-hook 'type-break-post-command-hook 'type-break-do-query))
418 (cond 586
419 ((let ((type-break-mode nil)) 587;; Ask to take a break, but only after the user stops typing continuously
420 (funcall type-break-query-function "Take a break from typing now? ")) 588;; for at least a second. Renaming the minibuffer because you did M-x
421 (type-break)) 589;; rename-buffer just as type-break popped the question is... annoying.
422 (t 590(defun type-break-do-query ()
423 (type-break-schedule type-break-query-interval))) 591 (cond
424 (quit 592 ((sit-for 1)
425 (type-break-schedule type-break-query-interval)))) 593 (condition-case ()
594 (cond
595 ((let ((type-break-mode nil)
596 ;; yes-or-no-p sets this-command to exit-minibuffer,
597 ;; which hoses undo or yank-pop (if you happened to be
598 ;; yanking just when the query occurred).
599 (this-command this-command))
600 (funcall type-break-query-function
601 "Take a break from typing now? "))
602 (type-break))
603 (t
604 (type-break-schedule type-break-query-interval)))
605 (quit
606 (type-break-schedule type-break-query-interval)))
607 (remove-hook 'type-break-post-command-hook 'type-break-do-query))))
426 608
427(defun type-break-time-warning () 609(defun type-break-time-warning ()
428 (cond 610 (cond
429 ((and (car type-break-keystroke-threshold) 611 ((and (car type-break-keystroke-threshold)
430 (< type-break-keystroke-count (car type-break-keystroke-threshold)))) 612 (< type-break-keystroke-count (car type-break-keystroke-threshold))))
431 ((> type-break-time-warning-count 0) 613 ((> type-break-time-warning-count 0)
432 (cond 614 (let ((timeleft (type-break-time-difference (current-time)
433 ((eq (selected-window) (minibuffer-window))) 615 type-break-time-next-break)))
434 (t 616 (setq type-break-warning-countdown-string (number-to-string timeleft))
435 ;; Pause for a moment so previous messages can be seen. 617 (cond
436 (sit-for 2) 618 ((eq (selected-window) (minibuffer-window)))
437 (message "Warning: typing break due in %s." 619 ;; Do nothing if the command was just a prefix arg, since that will
438 (type-break-format-time 620 ;; immediately be followed by some other interactive command.
439 (type-break-time-difference (current-time) 621 ((memq this-command '(digit-argument universal-argument)))
440 type-break-time-next-break))) 622 (type-break-warning-message-mode
441 (setq type-break-time-warning-count 623 ;; Pause for a moment so any previous message can be seen.
442 (1- type-break-time-warning-count))))) 624 (sit-for 2)
625 (message "Warning: typing break due in %s."
626 (type-break-format-time timeleft))
627 (setq type-break-time-warning-count
628 (1- type-break-time-warning-count))))))
443 (t 629 (t
444 (remove-hook 'type-break-post-command-hook 'type-break-time-warning)))) 630 (remove-hook 'type-break-post-command-hook 'type-break-time-warning)
631 (setq type-break-warning-countdown-string nil))))
445 632
446(defun type-break-keystroke-warning () 633(defun type-break-keystroke-warning ()
447 (cond 634 (cond
448 ((> type-break-keystroke-warning-count 0) 635 ((> type-break-keystroke-warning-count 0)
636 (setq type-break-warning-countdown-string
637 (number-to-string (- (cdr type-break-keystroke-threshold)
638 type-break-keystroke-count)))
449 (cond 639 (cond
450 ((eq (selected-window) (minibuffer-window))) 640 ((eq (selected-window) (minibuffer-window)))
451 (t 641 (type-break-warning-message-mode
452 (sit-for 2) 642 (sit-for 2)
453 (message "Warning: typing break due in %s keystrokes." 643 (message "Warning: typing break due in %s keystrokes."
454 (- (cdr type-break-keystroke-threshold) 644 (- (cdr type-break-keystroke-threshold)
@@ -457,7 +647,8 @@ keystroke threshold has been exceeded."
457 (1- type-break-keystroke-warning-count))))) 647 (1- type-break-keystroke-warning-count)))))
458 (t 648 (t
459 (remove-hook 'type-break-post-command-hook 649 (remove-hook 'type-break-post-command-hook
460 'type-break-keystroke-warning)))) 650 'type-break-keystroke-warning)
651 (setq type-break-warning-countdown-string nil))))
461 652
462 653
463;;;###autoload 654;;;###autoload
@@ -468,11 +659,16 @@ scheduled, the keystroke thresholds and the current keystroke count, etc."
468 (interactive) 659 (interactive)
469 (with-output-to-temp-buffer "*Typing Break Statistics*" 660 (with-output-to-temp-buffer "*Typing Break Statistics*"
470 (princ (format "Typing break statistics\n-----------------------\n 661 (princ (format "Typing break statistics\n-----------------------\n
471Last typing break : %s 662Typing break mode is currently %s.
663Warnings of imminent typing breaks in echo area is %s.
664
665Last typing break ended : %s
472Next scheduled typing break : %s\n 666Next scheduled typing break : %s\n
473Minimum keystroke threshold : %s 667Minimum keystroke threshold : %s
474Maximum keystroke threshold : %s 668Maximum keystroke threshold : %s
475Current keystroke count : %s" 669Current keystroke count : %s"
670 (if type-break-mode "enabled" "disabled")
671 (if type-break-warning-message-mode "enabled" "disabled")
476 (if type-break-time-last-break 672 (if type-break-time-last-break
477 (current-time-string type-break-time-last-break) 673 (current-time-string type-break-time-last-break)
478 "never") 674 "never")
@@ -489,21 +685,28 @@ Current keystroke count : %s"
489 type-break-keystroke-count)))) 685 type-break-keystroke-count))))
490 686
491;;;###autoload 687;;;###autoload
492(defun type-break-guestimate-keystroke-threshold (wpm &optional wordlen frac) 688(defun type-break-guesstimate-keystroke-threshold (wpm &optional wordlen frac)
493 "Guess values for the minimum/maximum keystroke threshold for typing breaks. 689 "Guess values for the minimum/maximum keystroke threshold for typing breaks.
690
494If called interactively, the user is prompted for their guess as to how 691If called interactively, the user is prompted for their guess as to how
495many words per minute they usually type. From that, the command sets the 692many words per minute they usually type. This value should not be your
496values in `type-break-keystroke-threshold' based on a fairly simple 693maximum WPM, but your average. Of course, this is harder to gauge since it
497algorithm involving assumptions about the average length of words (5). 694can vary considerably depending on what you are doing. For example, one
498For the minimum threshold, it uses about a quarter of the computed maximum 695tends actually to type less when debugging a program, as opposed to writing
499threshold. 696documentation. (Perhaps a separate program should be written to estimate
697average typing speed.)
698
699From that, this command sets the values in `type-break-keystroke-threshold'
700based on a fairly simple algorithm involving assumptions about the average
701length of words (5). For the minimum threshold, it uses about a fifth of
702the computed maximum threshold.
500 703
501When called from lisp programs, the optional args WORDLEN and FRAC can be 704When called from lisp programs, the optional args WORDLEN and FRAC can be
502used to override the default assumption about average word length and the 705used to override the default assumption about average word length and the
503fraction of the maximum threshold to which to set the minimum threshold. 706fraction of the maximum threshold to which to set the minimum threshold.
504FRAC should be the inverse of the fractional value; for example, a value of 707FRAC should be the inverse of the fractional value; for example, a value of
5052 would mean to use one half, a value of 4 would mean to use one quarter, etc." 7082 would mean to use one half, a value of 4 would mean to use one quarter, etc."
506 (interactive "NHow many words per minute do you type? ") 709 (interactive "NOn average, how many words per minute do you type? ")
507 (let* ((upper (* wpm (or wordlen 5) (/ type-break-interval 60))) 710 (let* ((upper (* wpm (or wordlen 5) (/ type-break-interval 60)))
508 (lower (/ upper (or frac 5)))) 711 (lower (/ upper (or frac 5))))
509 (or type-break-keystroke-threshold 712 (or type-break-keystroke-threshold
@@ -617,7 +820,7 @@ FRAC should be the inverse of the fractional value; for example, a value of
617 (read-char) 820 (read-char)
618 (kill-buffer "*Life*")) 821 (kill-buffer "*Life*"))
619 (life-extinct 822 (life-extinct
620 (message (get 'life-extinct 'error-message)) 823 (message "%s" (get 'life-extinct 'error-message))
621 (sit-for 3) 824 (sit-for 3)
622 ;; restart demo 825 ;; restart demo
623 (setq continue t)) 826 (setq continue t))