Add 2011 to FSF/AIST copyright years.
[bpt/emacs.git] / lisp / type-break.el
index b51a74e..ba08eb9 100644 (file)
@@ -1,6 +1,7 @@
 ;;; type-break.el --- encourage rests from typing at appropriate intervals
 
-;; Copyright (C) 1994, 95, 97, 2000, 2004 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 1995, 1997, 2000, 2001, 2002, 2003,
+;;   2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
 
 ;; Author: Noah Friedman
 ;; Maintainer: Noah Friedman <friedman@splode.com>
 
 ;; This file is part of GNU Emacs.
 
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -21,9 +22,7 @@
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
@@ -87,13 +86,13 @@ use either \\[customize] or the function `type-break-mode'."
 
 ;;;###autoload
 (defcustom type-break-interval (* 60 60)
-  "*Number of seconds between scheduled typing breaks."
+  "Number of seconds between scheduled typing breaks."
   :type 'integer
   :group 'type-break)
 
 ;;;###autoload
 (defcustom type-break-good-rest-interval (/ type-break-interval 6)
-  "*Number of seconds of idle time considered to be an adequate typing rest.
+  "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\"
@@ -106,7 +105,7 @@ asked whether or not really to interrupt the break."
 
 ;;;###autoload
 (defcustom type-break-good-break-interval nil
-  "*Number of seconds considered to be an adequate explicit typing rest.
+  "Number of seconds considered to be an adequate explicit typing rest.
 
 When this variable is non-nil, its value is considered to be a \"good\"
 length (in seconds) for a break initiated by the command `type-break',
@@ -130,7 +129,7 @@ break interruptions when `type-break-good-rest-interval' is nil."
          (upper (* wpm avg-word-length (/ type-break-interval 60)))
          (lower (/ upper 5)))
     (cons lower upper))
-  "*Upper and lower bound on number of keystrokes for considering typing break.
+  "Upper and lower bound on number of keystrokes for considering typing break.
 This structure is a pair of numbers (MIN . MAX).
 
 The first number is the minimum number of keystrokes that must have been
@@ -154,14 +153,14 @@ guess a reasonably good pair of values for this variable."
   :group 'type-break)
 
 (defcustom type-break-query-mode t
-  "*Non-nil means ask whether or not to prompt user for breaks.
+  "Non-nil means ask whether or not to prompt user for breaks.
 If so, call the function specified in the value of the variable
 `type-break-query-function' to do the asking."
   :type 'boolean
   :group 'type-break)
 
 (defcustom type-break-query-function 'yes-or-no-p
-  "*Function to use for making query for a typing break.
+  "Function to use for making query for a typing break.
 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'.
 
@@ -172,21 +171,21 @@ To avoid being queried at all, set `type-break-query-mode' to nil."
   :group 'type-break)
 
 (defcustom type-break-query-interval 60
-  "*Number of seconds between queries to take a break, if put off.
+  "Number of seconds between queries to take a break, if put off.
 The user will continue to be prompted at this interval until he or she
 finally submits to taking a typing break."
   :type 'integer
   :group 'type-break)
 
 (defcustom type-break-time-warning-intervals '(300 120 60 30)
-  "*List of time intervals for warnings about upcoming typing break.
+  "List of time intervals for warnings about upcoming typing break.
 At each of the intervals (specified in seconds) away from a scheduled
 typing break, print a warning in the echo area."
   :type '(repeat integer)
   :group 'type-break)
 
 (defcustom type-break-keystroke-warning-intervals '(300 200 100 50)
-  "*List of keystroke measurements for warnings about upcoming typing break.
+  "List of keystroke measurements for warnings about upcoming typing break.
 At each of the intervals (specified in keystrokes) away from the upper
 keystroke threshold, print a warning in the echo area.
 If either this variable or the upper threshold is set, then no warnings
@@ -195,21 +194,21 @@ will occur."
   :group 'type-break)
 
 (defcustom type-break-warning-repeat 40
-  "*Number of keystrokes for which warnings should be repeated.
+  "Number of keystrokes for which warnings should be repeated.
 That is, for each of this many keystrokes the warning is redisplayed
 in the echo area to make sure it's really seen."
   :type 'integer
   :group 'type-break)
 
 (defcustom type-break-time-stamp-format "[%H:%M] "
-  "*Timestamp format used to prefix messages.
+  "Timestamp format used to prefix messages.
 Format specifiers are as used by `format-time-string'."
   :type 'string
   :group 'type-break)
 
 (defcustom type-break-demo-functions
   '(type-break-demo-boring type-break-demo-life type-break-demo-hanoi)
-  "*List of functions to consider running as demos during typing breaks.
+  "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.
 
@@ -219,17 +218,18 @@ key is pressed."
   :group 'type-break)
 
 (defcustom type-break-demo-boring-stats nil
-  "*Show word per minute and keystroke figures in the Boring demo."
+  "Show word per minute and keystroke figures in the Boring demo."
   :type 'boolean
   :group 'type-break)
 
 (defcustom type-break-terse-messages nil
-  "*Use slightly terser messages."
+  "Use slightly terser messages."
   :type 'boolean
   :group 'type-break)
 
 (defcustom type-break-file-name (convert-standard-filename "~/.type-break")
-  "*Name of file used to save state across sessions."
+  "Name of file used to save state across sessions.
+If this is nil, no data will be saved across sessions."
   :type 'file
   :group 'type-break)
 
@@ -246,7 +246,7 @@ remove themselves after running.")
 ;; Mode line frobs
 
 (defcustom type-break-mode-line-message-mode nil
-  "*Non-nil means put type-break related messages in the mode line.
+  "Non-nil means put type-break related messages in the mode line.
 Otherwise, messages typically go in the echo area.
 
 See also `type-break-mode-line-format' and its members."
@@ -386,9 +386,13 @@ problems."
 
     (cond
      ((and already-enabled type-break-mode)
-      (and (interactive-p)
+      (and (called-interactively-p 'interactive)
            (message "Type Break mode is already enabled")))
      (type-break-mode
+      (when type-break-file-name
+       (with-current-buffer (find-file-noselect type-break-file-name 'nowarn)
+         (setq buffer-save-without-query t)))
+
       (or global-mode-string
           (setq global-mode-string '("")))
       (or (assq 'type-break-mode-line-message-mode
@@ -399,7 +403,9 @@ problems."
       (type-break-keystroke-reset)
       (type-break-mode-line-countdown-or-break nil)
 
-      (setq type-break-time-last-break (type-break-get-previous-time))
+      (setq type-break-time-last-break
+            (or (type-break-get-previous-time)
+                (current-time)))
 
       ;; schedule according to break time from session file
       (type-break-schedule
@@ -424,20 +430,20 @@ problems."
        type-break-interval-start
        type-break-interval)
 
-      (and (interactive-p)
+      (and (called-interactively-p 'interactive)
            (message "Type Break mode is enabled and set")))
      (t
       (type-break-keystroke-reset)
       (type-break-mode-line-countdown-or-break nil)
       (type-break-cancel-schedule)
       (do-auto-save)
-      (with-current-buffer (find-file-noselect type-break-file-name
-                                               'nowarn)
-       (setq buffer-save-without-query t)
-       (set-buffer-modified-p nil)
-        (unlock-buffer)
-        (kill-this-buffer))
-      (and (interactive-p)
+      (when type-break-file-name
+       (with-current-buffer (find-file-noselect type-break-file-name
+                                                'nowarn)
+         (set-buffer-modified-p nil)
+         (unlock-buffer)
+         (kill-this-buffer)))
+      (and (called-interactively-p 'interactive)
            (message "Type Break mode is disabled")))))
   type-break-mode)
 
@@ -459,7 +465,7 @@ Variables controlling the display of messages in the mode line include:
   (interactive "P")
   (setq type-break-mode-line-message-mode
         (>= (prefix-numeric-value prefix) 0))
-  (and (interactive-p)
+  (and (called-interactively-p 'interactive)
        (if type-break-mode-line-message-mode
            (message "type-break-mode-line-message-mode is enabled")
          (message "type-break-mode-line-message-mode is disabled")))
@@ -480,7 +486,7 @@ variable of the same name."
   (interactive "P")
   (setq type-break-query-mode
         (>= (prefix-numeric-value prefix) 0))
-  (and (interactive-p)
+  (and (called-interactively-p 'interactive)
        (if type-break-query-mode
            (message "type-break-query-mode is enabled")
          (message "type-break-query-mode is disabled")))
@@ -496,7 +502,8 @@ variable of the same name."
 
 (defun type-break-file-time (&optional time)
   "File break time in `type-break-file-name', unless the file is locked."
-  (if (not (stringp (file-locked-p type-break-file-name)))
+  (if (and type-break-file-name
+           (not (stringp (file-locked-p type-break-file-name))))
       (with-current-buffer (find-file-noselect type-break-file-name
                                                'nowarn)
         (let ((inhibit-read-only t))
@@ -507,7 +514,8 @@ variable of the same name."
 
 (defun type-break-file-keystroke-count ()
   "File keystroke count in `type-break-file-name', unless the file is locked."
-  (if (not (stringp (file-locked-p type-break-file-name)))
+  (if (and type-break-file-name
+           (not (stringp (file-locked-p type-break-file-name))))
       ;; Prevent deactivation of the mark in some other buffer.
       (let (deactivate-mark)
        (with-current-buffer (find-file-noselect type-break-file-name
@@ -534,6 +542,8 @@ return TIME, else return nil."
 (defun type-break-choose-file ()
   "Return file to read from."
   (cond
+   ((not type-break-file-name)
+    nil)
    ((and (file-exists-p type-break-auto-save-file-name)
          (file-readable-p type-break-auto-save-file-name))
     type-break-auto-save-file-name)
@@ -550,9 +560,12 @@ Returns nil if the file is missing or if the time breaks with the
     (if file
         (timep ;; returns expected format, else nil
          (with-current-buffer (find-file-noselect file 'nowarn)
-           (save-excursion
-             (goto-char (point-min))
-             (read (current-buffer))))))))
+          (condition-case nil
+              (save-excursion
+                (goto-char (point-min))
+                (read (current-buffer)))
+            (end-of-file
+             (error "End of file in `%s'" file))))))))
 
 (defun type-break-get-previous-count ()
   "Get previous keystroke count from `type-break-file-name'.
@@ -564,10 +577,13 @@ integer."
               (setq file
                     (with-current-buffer
                         (find-file-noselect file 'nowarn)
-                      (save-excursion
-                        (goto-char (point-min))
-                        (forward-line 1)
-                        (read (current-buffer)))))))
+                    (condition-case nil
+                        (save-excursion
+                          (goto-char (point-min))
+                          (forward-line 1)
+                          (read (current-buffer)))
+                      (end-of-file
+                       (error "End of file in `%s'" file)))))))
         file
       0)))
 
@@ -999,7 +1015,7 @@ FRAC should be the inverse of the fractional value; for example, a value of
         (setq type-break-keystroke-threshold (cons nil nil)))
     (setcar type-break-keystroke-threshold lower)
     (setcdr type-break-keystroke-threshold upper)
-    (if (interactive-p)
+    (if (called-interactively-p 'interactive)
         (message "min threshold: %d\tmax threshold: %d" lower upper))
     type-break-keystroke-threshold))
 
@@ -1078,7 +1094,7 @@ FRAC should be the inverse of the fractional value; for example, a value of
 (defun type-break-force-mode-line-update (&optional all)
   "Force the mode-line of the current buffer to be redisplayed.
 With optional non-nil ALL, force redisplay of all mode-lines."
-  (and all (save-excursion (set-buffer (other-buffer))))
+  (and all (with-current-buffer (other-buffer)))
   (set-buffer-modified-p (buffer-modified-p)))
 
 ;; If an exception occurs in Emacs while running the post command hook, the
@@ -1092,9 +1108,9 @@ With optional non-nil ALL, force redisplay of all mode-lines."
 
 \f
 ;;; Timer wrapper functions
-;;;
-;;; These shield type-break from variations in the interval timer packages
-;;; for different versions of Emacs.
+;;
+;; These shield type-break from variations in the interval timer packages
+;; for different versions of Emacs.
 
 (defun type-break-run-at-time (time repeat function)
   (condition-case nil (or (require 'timer) (require 'itimer)) (error nil))
@@ -1108,6 +1124,13 @@ With optional non-nil ALL, force redisplay of all mode-lines."
 \f
 ;;; Demo wrappers
 
+(defun type-break-catch-up-event ()
+  ;; If the last input event is a down-event, read and discard the
+  ;; corresponding up-event too, to avoid triggering another prompt.
+  (and (eventp last-input-event)
+       (memq 'down (event-modifiers last-input-event))
+       (read-event)))
+
 ;; This is a wrapper around hanoi that calls it with an arg large enough to
 ;; make the largest discs possible that will fit in the window.
 ;; Also, clean up the *Hanoi* buffer after we're done.
@@ -1119,11 +1142,12 @@ With optional non-nil ALL, force redisplay of all mode-lines."
       (progn
         (hanoi (/ (window-width) 8))
         ;; Wait for user to come back.
-        (read-char)
+        (read-event)
+       (type-break-catch-up-event)
         (kill-buffer "*Hanoi*"))
     (quit
-     ;; eat char
-     (read-char)
+     (read-event)
+     (type-break-catch-up-event)
      (and (get-buffer "*Hanoi*")
           (kill-buffer "*Hanoi*")))))
 
@@ -1141,14 +1165,15 @@ With optional non-nil ALL, force redisplay of all mode-lines."
           (progn
             (life 3)
             ;; wait for user to return
-            (read-char)
+            (read-event)
+           (type-break-catch-up-event)
             (kill-buffer "*Life*"))
         (life-extinct
          (message "%s" (get 'life-extinct 'error-message))
-         (sit-for 3)
          ;; restart demo
          (setq continue t))
         (quit
+        (type-break-catch-up-event)
          (and (get-buffer "*Life*")
               (kill-buffer "*Life*")))))))
 
@@ -1234,7 +1259,8 @@ With optional non-nil ALL, force redisplay of all mode-lines."
                      message))))
             (goto-char (point-min))
             (sit-for 60))
-          (read-char)
+         (read-event)
+         (type-break-catch-up-event)
           (kill-buffer buffer-name))
       (quit
        (and (get-buffer buffer-name)
@@ -1246,5 +1272,5 @@ With optional non-nil ALL, force redisplay of all mode-lines."
 (if type-break-mode
     (type-break-mode 1))
 
-;;; arch-tag: 943a2eb3-07e6-420b-993f-96e4796f5fd0
+;; arch-tag: 943a2eb3-07e6-420b-993f-96e4796f5fd0
 ;;; type-break.el ends here