diff lisp/type-break.el @ 8304:6c34e249d217

type-break-good-rest-interval: Doc fix. type-break-keystroke-threshold: Calcuate based on 35wpm, not 30. type-break-demo-function-vector: Variable deleted. type-break-demo-functions: New variable. type-break: Use new variable. type-break-time-difference: Return absolute value. type-break-format-time: New inline function (defsubst). type-break-statistics, type-break: Use it. type-break-mode: Just test prefix-numeric-value >= 0 to to enable mode. The only visible difference is that invocation with no prefix arg the same as if given positive numeric prefix arg now. Do not document type-break-query-interval or type-break-query-function here; make fritterware-happy users read the source. type-break: If type break is much less (at least 2 minutes) than a "good rest interval", ask user whether or not to continue with the break. type-break-check: Do nothing if user is in the minibuffer. When alarm is signaled but min threshold isn't reached, reschedule break. type-break-demo-life: Eat char entered to end life demo.
author Noah Friedman <friedman@splode.com>
date Thu, 21 Jul 1994 10:11:59 +0000
parents 206451cdd48a
children d7bb8587fdf0
line wrap: on
line diff
--- a/lisp/type-break.el	Wed Jul 20 20:04:47 1994 +0000
+++ b/lisp/type-break.el	Thu Jul 21 10:11:59 1994 +0000
@@ -51,6 +51,7 @@
 ;;; repetitive strain injury?
 
 ;;; This package was inspired by Roland McGrath's hanoi-break.el.
+;;; Thanks to Mark Ashton <mpashton@gnu.ai.mit.edu> for feedback and ideas.
 
 ;;; Code:
 
@@ -73,11 +74,11 @@
   "*Number of seconds of idle time considered to be an adequate typing rest.
 
 When this variable is non-`nil', emacs checks the idle time between
-keystrokes.  If this idle time is long enough to be considered a "good"
+keystrokes.  If this idle time is long enough to be considered a \"good\"
 rest from typing, then the next typing break is simply rescheduled for later.
 
-The user will also be admonished if a forced break isn't at least as long
-as this time, to remind them to rest longer next time.")
+If a break is interrupted before this much time elapses, the user will be
+asked whether or not really to interrupt the break.")
 
 ;;;###autoload
 (defvar type-break-query-interval 60
@@ -87,7 +88,7 @@
 
 ;;;###autoload
 (defvar type-break-keystroke-threshold
-  ;; Assuming typing speed is 30wpm (on the average, do you really
+  ;; Assuming typing speed is 35wpm (on the average, do you really
   ;; type more than that in a minute?  I spend a lot of time reading mail
   ;; and simply studying code in buffers) and average word length is
   ;; about 5 letters, default upper threshold to the average number of
@@ -95,7 +96,7 @@
   ;; user goes through a furious burst of typing activity, cause a typing
   ;; break to be required sooner than originally scheduled.
   ;; Conversely, the minimum threshold should be about a fifth of this.
-  (let* ((wpm 30)
+  (let* ((wpm 35)
          (avg-word-length 5)
          (upper (* wpm avg-word-length (/ type-break-interval 60)))
          (lower (/ upper 5)))
@@ -124,22 +125,19 @@
 It should take a string as an argument, the prompt.
 Usually this should be set to `yes-or-no-p' or `y-or-n-p'.")
 
-(defvar type-break-demo-function-vector
-  [type-break-demo-life type-break-demo-hanoi]
-  "*Vector consisting of functions to run as demos during typing breaks.
+(defvar type-break-demo-functions
+  '(type-break-demo-life type-break-demo-hanoi)
+  "*List of functions to consider running as demos during typing breaks.
 When a typing break begins, one of these functions is selected randomly
 to have emacs do something interesting.
 
-Any function in this vector should start a demo which ceases as soon as a
+Any function in this list should start a demo which ceases as soon as a
 key is pressed.")
 
 ;; These are internal variables.  Do not set them yourself.
 
-;; Non-nil when a scheduled typing break is due.
-(defvar type-break-alarm-p nil)
-
+(defvar type-break-alarm-p nil) ; Non-nil when a scheduled typing break is due.
 (defvar type-break-keystroke-count 0)
-
 (defvar type-break-time-last-break nil)
 (defvar type-break-time-next-break nil)
 (defvar type-break-time-last-command (current-time))
@@ -151,9 +149,18 @@
 ;; seconds to the cdr of some of my stored time values, which may throw off
 ;; the number of bits in the cdr.
 (defsubst type-break-time-difference (a b)
-  (+ (lsh (- (car b) (car a)) 16)
-     (- (car (cdr b)) (car (cdr a)))))
+  (abs (+ (lsh (- (car b) (car a)) 16)
+          (- (car (cdr b)) (car (cdr a))))))
 
+(defsubst type-break-format-time (secs)
+  (let ((mins (/ secs 60)))
+    (cond
+     ((> mins 0)
+      (format "%d minutes" mins))
+     (t
+      (format "%d seconds" secs)))))
+
+
 ;;;###autoload
 (defun type-break-mode (&optional prefix)
   "Enable or disable typing-break mode.
@@ -167,9 +174,8 @@
 to find a good breaking point in his or her work, but be sufficiently
 annoying to discourage putting typing breaks off indefinitely.
 
-Calling this command with no prefix argument toggles this mode.
 A negative prefix argument disables this mode.
-A non-negative prefix argument or any other non-`nil' argument enables it.
+No argument or any non-negative argument enables it.
 
 The user may enable or disable this mode by setting the variable of the
 same name, though setting it in that way doesn't reschedule a break or
@@ -185,44 +191,30 @@
 affect the time schedule; it simply provides a default for the
 `type-break-schedule' command.
 
-The variable `type-break-query-interval' specifies the number of seconds to
-schedule between repeated queries for breaks when the user answers \"no\"
-to the previous query.
-
-The variable `type-break-good-rest-interval' specifies the minimum amount
-of time which is considered a reasonable typing break.  Whenever that time
-has elapsed, typing breaks are automatically rescheduled for later even if
-emacs didn't prompt you to take one first.  You can disable this behavior.
+If set, the variable `type-break-good-rest-interval' specifies the minimum
+amount of time which is considered a reasonable typing break.  Whenever
+that time has elapsed, typing breaks are automatically rescheduled for
+later even if emacs didn't prompt you to take one first.  Also, if a break
+is ended before this much time has elapsed, the user will be asked whether
+or not to continue.
 
 The variable `type-break-keystroke-threshold' is used to determine the
 thresholds at which typing breaks should be considered.  You can use
 the command `type-break-guestimate-keystroke-threshold' to try to
 approximate good values for this.
 
-The variable `type-break-query-function' should contain a function (or the
-symbolic name of a function) to be used to query the user for typing
-breaks.
-
 Finally, the command `type-break-statistics' prints interesting things."
   (interactive "P")
   ;; make sure it's there.
   (add-hook 'post-command-hook 'type-break-check 'append)
 
   (let ((already-enabled type-break-mode))
-    (cond
-     ((null prefix)
-      (setq type-break-mode (not type-break-mode)))
-     ((numberp (prefix-numeric-value prefix))
-      (setq type-break-mode (>= (prefix-numeric-value prefix) 0)))
-     (prefix
-      (setq type-break-mode t))
-     (t
-      (setq type-break-mode nil)))
+    (setq type-break-mode (>= (prefix-numeric-value prefix) 0))
 
     (cond
      ((and already-enabled type-break-mode)
       (and (interactive-p)
-           (message "type-break-mode was already enabled")))
+           (message "type-break-mode is enabled")))
      (type-break-mode
       (setq type-break-keystroke-count 0)
       (type-break-schedule)
@@ -237,34 +229,50 @@
   "Take a typing break.
 
 During the break, a demo selected from the functions listed in
-`type-break-demo-function-vector' is run.
+`type-break-demo-functions' is run.
 
 After the typing break is finished, the next break is scheduled
-as per the function `type-break-schedule', and the keystroke counter is
-reset."
+as per the function `type-break-schedule'."
   (interactive)
-  (setq type-break-time-last-break (current-time))
-  (save-window-excursion
-    ;; Eat the screen.
-    (and (eq (selected-window) (minibuffer-window))
-         (other-window 1))
-    (delete-other-windows)
-    (scroll-right (window-width))
-    (message "Press any key to resume from typing break.")
+  (let ((continue t)
+        (start-time (current-time)))
+    (setq type-break-time-last-break start-time)
+    (while continue
+      (save-window-excursion
+        ;; Eat the screen.
+        (and (eq (selected-window) (minibuffer-window))
+             (other-window 1))
+        (delete-other-windows)
+        (scroll-right (window-width))
+        (message "Press any key to resume from typing break.")
 
-    (random t)
-    (let* ((len (length type-break-demo-function-vector))
-           (idx (random len))
-           (fn (aref type-break-demo-function-vector idx)))
-      (condition-case ()
-          (funcall fn)
-        (error nil))))
+        (random t)
+        (let* ((len (length type-break-demo-functions))
+               (idx (random len))
+               (fn (nth idx type-break-demo-functions)))
+          (condition-case ()
+              (funcall fn)
+            (error nil))))
 
-  (and type-break-good-rest-interval
-       (< (type-break-time-difference type-break-time-last-command
-                                      (current-time))
-          type-break-good-rest-interval)
-       (message "That typing break wasn't really long enough.  Rest more next time."))
+      (cond
+       (type-break-good-rest-interval
+        (let ((break-secs (type-break-time-difference
+                           start-time (current-time))))
+          (cond
+           ((>= break-secs type-break-good-rest-interval)
+            (setq continue nil))
+           ;; Don't be pedantic; if user's rest was only a minute or two
+           ;; short, why bother?
+           ((> 120 (abs (- break-secs type-break-good-rest-interval)))
+            (setq continue nil))
+           ((funcall 
+             type-break-query-function
+             (format "You really ought to rest %s more.  Continue break? "
+                     (type-break-format-time (- type-break-good-rest-interval
+                                                break-secs)))))
+           (t
+            (setq continue nil)))))
+       (t (setq continue nil)))))
 
   (setq type-break-keystroke-count 0)
   (type-break-schedule))
@@ -321,6 +329,7 @@
                 type-break-good-rest-interval)
              (progn
                (setq type-break-keystroke-count 0)
+               (setq type-break-time-last-break (current-time))
                (type-break-schedule)))
         (setq type-break-time-last-command (current-time))))
 
@@ -330,10 +339,12 @@
 
       (cond
        ((input-pending-p))
+       ((eq (selected-window) (minibuffer-window)))
        (type-break-alarm-p
         (cond
          ((and min-threshold
-               (< type-break-keystroke-count min-threshold)))
+               (< type-break-keystroke-count min-threshold))
+          (type-break-schedule))
          (t
           ;; If the keystroke count is within min-threshold characters of
           ;; the maximum threshold, set the count to min-threshold.  That
@@ -401,6 +412,8 @@
       (condition-case ()
           (progn
             (life 3)
+            ;; wait for user to return
+            (read-char)
             (kill-buffer "*Life*"))
         (life-extinct
          (message (get 'life-extinct 'error-message))
@@ -431,13 +444,10 @@
                    (if (and type-break-mode type-break-time-next-break)
                        (format "%s\t(%s from now)"
                                (current-time-string type-break-time-next-break)
-                               (let* ((secs (type-break-time-difference
-                                             (current-time) 
-                                             type-break-time-next-break))
-                                      (mins (/ secs 60)))
-                                 (if (> mins 0)
-                                     (format "%d minutes" mins)
-                                   (format "%d seconds" secs))))
+                               (type-break-format-time 
+                                (type-break-time-difference
+                                (current-time) 
+                                type-break-time-next-break)))
                      "none scheduled")
                    (or (car type-break-keystroke-threshold) "none")
                    (or (cdr type-break-keystroke-threshold) "none")