(mouse-drag-region-1): Delete some debugging code.
[bpt/emacs.git] / lisp / midnight.el
CommitLineData
60370d40 1;;; midnight.el --- run something every midnight, e.g., kill old buffers
ac06bd0f 2
320cb80d 3;;; Copyright (C) 1998, 2004, 2005 Free Software Foundation, Inc.
ac06bd0f 4
60370d40
PJ
5;; Author: Sam Steingold <sds@usa.net>
6;; Maintainer: Sam Steingold <sds@usa.net>
7;; Created: 1998-05-18
8;; Keywords: utilities
ac06bd0f
RS
9
10;; This file is part of GNU Emacs.
11
12;; GNU Emacs is free software; you can redistribute it and/or modify
13;; it under the terms of the GNU General Public License as published by
14;; the Free Software Foundation; either version 2, or (at your option)
15;; any later version.
16
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
23;; along with GNU Emacs; see the file COPYING. If not, write to the
24;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25;; Boston, MA 02111-1307, USA.
26
27;;; Commentary:
28
29;; To use the file, put (require 'midnight) into your .emacs. Then, at
30;; midnight, Emacs will run the normal hook `midnight-hook'. You can
31;; put whatever you like there, say, `calendar'; by default there is
32;; only one function there - `clean-buffer-list'. It will kill the
33;; buffers matching `clean-buffer-list-kill-buffer-names' and
34;; `clean-buffer-list-kill-regexps' and the buffers which where last
35;; displayed more than `clean-buffer-list-delay-general' days ago,
36;; keeping `clean-buffer-list-kill-never-buffer-names' and
37;; `clean-buffer-list-kill-never-regexps'.
38
9cc077f6
RS
39;;; Code:
40
849ac835 41(eval-when-compile
51eb1909
KH
42 (require 'cl))
43
44(require 'timer)
ac06bd0f
RS
45
46(defgroup midnight nil
47 "Run something every day at midnight."
1e484d64
DN
48 :group 'calendar
49 :version "20.3")
ac06bd0f 50
6d9d01a9 51(defcustom midnight-mode nil
e9d7cff0
RS
52 "*Non-nil means run `midnight-hook' at midnight.
53Setting this variable outside customize has no effect;
54call `cancel-timer' or `timer-activate' on `midnight-timer' instead."
55 :type 'boolean
56 :group 'midnight
57 :require 'midnight
6d9d01a9 58 :initialize 'custom-initialize-default
e9d7cff0
RS
59 :set (lambda (symb val)
60 (set symb val) (require 'midnight)
61 (if val (timer-activate midnight-timer)
62 (cancel-timer midnight-timer))))
63
ac06bd0f
RS
64;;; time conversion
65
6d9d01a9 66(defun midnight-time-float (num)
ac06bd0f
RS
67 "Convert the float number of seconds since epoch to the list of 3 integers."
68 (let* ((div (ash 1 16)) (1st (floor num div)))
69 (list 1st (floor (- num (* (float div) 1st)))
70 (round (* 10000000 (mod num 1))))))
71
6d9d01a9 72(defun midnight-buffer-display-time (&optional buf)
ac06bd0f 73 "Return the time-stamp of the given buffer, or current buffer, as float."
5044b74a 74 (with-current-buffer (or buf (current-buffer))
a1f84f6d 75 (when buffer-display-time (float-time buffer-display-time))))
ac06bd0f
RS
76
77;;; clean-buffer-list stuff
78
79(defcustom clean-buffer-list-delay-general 3
80 "*The number of days before any buffer becomes eligible for autokilling.
81The autokilling is done by `clean-buffer-list' when is it in `midnight-hook'.
82Currently displayed and/or modified (unsaved) buffers, as well as buffers
83matching `clean-buffer-list-kill-never-buffer-names' and
84`clean-buffer-list-kill-never-regexps' are excluded."
85 :type 'integer
1e484d64 86 :group 'midnight)
ac06bd0f
RS
87
88(defcustom clean-buffer-list-delay-special 3600
89 "*The number of seconds before some buffers become eligible for autokilling.
90Buffers matched by `clean-buffer-list-kill-regexps' and
91`clean-buffer-list-kill-buffer-names' are killed if they were last
92displayed more than this many seconds ago."
93 :type 'integer
1e484d64 94 :group 'midnight)
ac06bd0f 95
b2f9ab3c 96(defcustom clean-buffer-list-kill-regexps nil
ac06bd0f
RS
97 "*List of regexps saying which buffers will be killed at midnight.
98If buffer name matches a regexp in the list and the buffer was not displayed
99in the last `clean-buffer-list-delay-special' seconds, it is killed by
100`clean-buffer-list' when is it in `midnight-hook'.
f40c9c7b 101If a member of the list is a cons, its `car' is the regexp and its `cdr' is
ac06bd0f
RS
102the number of seconds to use instead of `clean-buffer-list-delay-special'.
103See also `clean-buffer-list-kill-buffer-names',
104`clean-buffer-list-kill-never-regexps' and
105`clean-buffer-list-kill-never-buffer-names'."
1e5a4438 106 :type '(repeat (regexp :tag "Regexp matching Buffer Name"))
1e484d64 107 :group 'midnight)
ac06bd0f
RS
108
109(defcustom clean-buffer-list-kill-buffer-names
b2f9ab3c 110 '("*Help*" "*Apropos*" "*Man " "*Buffer List*" "*Compile-Log*" "*info*"
9cc077f6 111 "*vc*" "*vc-diff*" "*diff*")
ac06bd0f
RS
112 "*List of strings saying which buffers will be killed at midnight.
113Buffers with names in this list, which were not displayed in the last
114`clean-buffer-list-delay-special' seconds, are killed by `clean-buffer-list'
115when is it in `midnight-hook'.
f40c9c7b 116If a member of the list is a cons, its `car' is the name and its `cdr' is
ac06bd0f
RS
117the number of seconds to use instead of `clean-buffer-list-delay-special'.
118See also `clean-buffer-list-kill-regexps',
119`clean-buffer-list-kill-never-regexps' and
120`clean-buffer-list-kill-never-buffer-names'."
1e5a4438 121 :type '(repeat (string :tag "Buffer Name"))
1e484d64 122 :group 'midnight)
ac06bd0f
RS
123
124(defcustom clean-buffer-list-kill-never-buffer-names
125 '("*scratch*" "*Messages*")
126 "*List of buffer names which will never be killed by `clean-buffer-list'.
127See also `clean-buffer-list-kill-never-regexps'.
128Note that this does override `clean-buffer-list-kill-regexps' and
129`clean-buffer-list-kill-buffer-names' so a buffer matching any of these
130two lists will NOT be killed if it is also present in this list."
1e5a4438 131 :type '(repeat (string :tag "Buffer Name"))
1e484d64
DN
132 :group 'midnight)
133
ac06bd0f 134
b3275b47 135(defcustom clean-buffer-list-kill-never-regexps '("^ \\*Minibuf-.*\\*$")
ac06bd0f
RS
136 "*List of regexp saying which buffers will never be killed at midnight.
137See also `clean-buffer-list-kill-never-buffer-names'.
138Killing is done by `clean-buffer-list'.
139Note that this does override `clean-buffer-list-kill-regexps' and
140`clean-buffer-list-kill-buffer-names' so a buffer matching any of these
141two lists will NOT be killed if it also matches anything in this list."
1e5a4438 142 :type '(repeat (regexp :tag "Regexp matching Buffer Name"))
1e484d64 143 :group 'midnight)
ac06bd0f
RS
144
145(defun midnight-find (el ls test &optional key)
146 "A stopgap solution to the absence of `find' in ELisp."
9cc077f6 147 (dolist (rr ls)
b3275b47 148 (when (funcall test (if key (funcall key rr) rr) el)
9cc077f6 149 (return rr))))
849ac835 150
b2f9ab3c
RS
151(defun clean-buffer-list-delay (name)
152 "Return the delay, in seconds, before killing a buffer named NAME.
ac06bd0f
RS
153Uses `clean-buffer-list-kill-buffer-names', `clean-buffer-list-kill-regexps'
154`clean-buffer-list-delay-general' and `clean-buffer-list-delay-special'.
155Autokilling is done by `clean-buffer-list'."
b2f9ab3c 156 (or (assoc-default name clean-buffer-list-kill-buffer-names 'string=
849ac835 157 clean-buffer-list-delay-special)
b2f9ab3c 158 (assoc-default name clean-buffer-list-kill-regexps 'string-match
849ac835
RS
159 clean-buffer-list-delay-special)
160 (* clean-buffer-list-delay-general 24 60 60)))
ac06bd0f 161
80252f73 162;;;###autoload
ac06bd0f 163(defun clean-buffer-list ()
b2f9ab3c 164 "Kill old buffers that have not been displayed recently.
9cc077f6 165The relevant variables are `clean-buffer-list-delay-general',
ac06bd0f
RS
166`clean-buffer-list-delay-special', `clean-buffer-list-kill-buffer-names',
167`clean-buffer-list-kill-never-buffer-names',
9cc077f6
RS
168`clean-buffer-list-kill-regexps' and
169`clean-buffer-list-kill-never-regexps'.
170While processing buffers, this procedure displays messages containing
171the current date/time, buffer name, how many seconds ago it was
82f08756
RS
172displayed (can be nil if the buffer was never displayed) and its
173lifetime, i.e., its \"age\" when it will be purged."
ac06bd0f 174 (interactive)
a1f84f6d 175 (let ((tm (float-time)) bts (ts (format-time-string "%Y-%m-%d %T"))
83bc1919 176 (bufs (buffer-list)) buf delay cbld bn)
9cc077f6 177 (while (setq buf (pop bufs))
6d9d01a9 178 (setq bts (midnight-buffer-display-time buf) bn (buffer-name buf)
9cc077f6
RS
179 delay (if bts (- tm bts) 0) cbld (clean-buffer-list-delay bn))
180 (message "[%s] `%s' [%s %d]" ts bn (if bts (round delay)) cbld)
849ac835 181 (unless (or (midnight-find bn clean-buffer-list-kill-never-regexps
ac06bd0f
RS
182 'string-match)
183 (midnight-find bn clean-buffer-list-kill-never-buffer-names
184 'string-equal)
83bc1919 185 (get-buffer-process buf)
9cc077f6
RS
186 (and (buffer-file-name buf) (buffer-modified-p buf))
187 (get-buffer-window buf 'visible) (< delay cbld))
ac06bd0f
RS
188 (message "[%s] killing `%s'" ts bn)
189 (kill-buffer buf)))))
190
191;;; midnight hook
192
193(defvar midnight-period (* 24 60 60)
b2f9ab3c 194 "The number of seconds in a day--the delta for `midnight-timer'.")
ac06bd0f 195
82f08756 196(defcustom midnight-hook '(clean-buffer-list)
ac06bd0f
RS
197 "The hook run `midnight-delay' seconds after midnight every day.
198The default value is `clean-buffer-list'."
199 :type 'hook
1e484d64 200 :group 'midnight)
ac06bd0f
RS
201
202(defun midnight-next ()
203 "Return the number of seconds till the next midnight."
204 (multiple-value-bind (sec min hrs) (decode-time)
205 (- (* 24 60 60) (* 60 60 hrs) (* 60 min) sec)))
206
207(defvar midnight-timer nil
208 "Timer running the `midnight-hook' `midnight-delay' seconds after midnight.
209Use `cancel-timer' to stop it and `midnight-delay-set' to change
210the time when it is run.")
211
212;;;###autoload
213(defun midnight-delay-set (symb tm)
214 "Modify `midnight-timer' according to `midnight-delay'.
9cc077f6
RS
215Sets the first argument SYMB (which must be symbol `midnight-delay')
216to its second argument TM."
217 (assert (eq symb 'midnight-delay) t
320cb80d 218 "Invalid argument to `midnight-delay-set': `%s'")
ac06bd0f
RS
219 (set symb tm)
220 (when (timerp midnight-timer) (cancel-timer midnight-timer))
221 (setq midnight-timer
222 (run-at-time (if (numberp tm) (+ (midnight-next) tm) tm)
cef7e1da 223 midnight-period 'run-hooks 'midnight-hook)))
ac06bd0f
RS
224
225(defcustom midnight-delay 3600
226 "*The number of seconds after the midnight when the `midnight-timer' is run.
227You should set this variable before loading midnight.el, or
228set it by calling `midnight-delay-set', or use `custom'.
229If you wish, you can use a string instead, it will be passed as the
230first argument to `run-at-time'."
231 :type 'sexp
232 :set 'midnight-delay-set
1e484d64 233 :group 'midnight)
ac06bd0f
RS
234
235(provide 'midnight)
236
ab5796a9 237;;; arch-tag: a5979be9-2890-46a3-ba84-791f0a4a6e80
ac06bd0f 238;;; midnight.el ends here