Merge from emacs--rel--22, gnus--devo--0
[bpt/emacs.git] / lisp / erc / erc-autoaway.el
1 ;;; erc-autoaway.el --- Provides autoaway for ERC
2
3 ;; Copyright (C) 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc.
4
5 ;; Author: Jorgen Schaefer <forcer@forcix.cx>
6 ;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcAutoAway
7
8 ;; This file is part of GNU Emacs.
9
10 ;; GNU Emacs is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 3, or (at your option)
13 ;; any later version.
14
15 ;; GNU Emacs is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING. If not, write to the
22 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 ;; Boston, MA 02110-1301, USA.
24
25 ;;; Commentary:
26
27 ;; TODO:
28 ;; - Legacy names: erc-auto-discard-away, erc-auto-set-away
29
30 ;;; Code:
31
32 (require 'erc)
33
34 (defgroup erc-autoaway nil
35 "Set yourself automatically away after some idletime and set
36 yourself back when you type something."
37 :group 'erc)
38
39 (defvar erc-autoaway-idletimer nil
40 "The Emacs idletimer.
41 This is only used when `erc-autoaway-idle-method' is set to 'emacs.")
42
43 (defvar erc-autoaway-last-sent-time (erc-current-time)
44 "The last time the user sent something.")
45
46 (defvar erc-autoaway-caused-away nil
47 "Indicates whether this module was responsible for setting the
48 user's away status.")
49
50 (eval-when-compile (defvar erc-autoaway-idle-seconds))
51
52 (defun erc-autoaway-reestablish-idletimer ()
53 "Reestablish the Emacs idletimer.
54 If `erc-autoaway-idle-method' is 'emacs, you must call this
55 function each time you change `erc-autoaway-idle-seconds'."
56 (interactive)
57 (when erc-autoaway-idletimer
58 (erc-cancel-timer erc-autoaway-idletimer))
59 (setq erc-autoaway-idletimer
60 (run-with-idle-timer erc-autoaway-idle-seconds
61 t
62 'erc-autoaway-set-away
63 erc-autoaway-idle-seconds)))
64
65 (defun erc-autoaway-some-server-buffer ()
66 "Return some ERC server buffer if its connection is alive.
67 If none is found, return nil."
68 (car (erc-buffer-list #'erc-open-server-buffer-p)))
69
70 (defun erc-autoaway-insinuate-maybe (&optional server &rest ignored)
71 "Add autoaway reset function to `post-command-hook' if at least one
72 ERC process is alive.
73
74 This is used when `erc-autoaway-idle-method' is 'user."
75 (when (or server (erc-autoaway-some-server-buffer))
76 (add-hook 'post-command-hook 'erc-autoaway-reset-idle-user)))
77
78 (defun erc-autoaway-remove-maybe (&rest ignored)
79 "Remove the autoaway reset function from `post-command-hook' if
80 no ERC process is alive.
81
82 This is used when `erc-autoaway-idle-method' is 'user."
83 (unless (erc-autoaway-some-server-buffer)
84 (remove-hook 'post-command-hook 'erc-autoaway-reset-idle-user)))
85
86 ;;;###autoload (autoload 'erc-autoaway-mode "erc-autoaway")
87 (define-erc-module autoaway nil
88 "In ERC autoaway mode, you can be set away automatically.
89 If `erc-auto-set-away' is set, then you will be set away after
90 the number of seconds specified in `erc-autoaway-idle-seconds'.
91
92 There are several kinds of being idle:
93
94 User idle time measures how long you have not been sending any
95 commands to Emacs. This is the default.
96
97 Emacs idle time measures how long Emacs has been idle. This is
98 currently not useful, since Emacs is non-idle when it handles
99 ping-pong with IRC servers. See `erc-autoaway-idle-method'
100 for more information.
101
102 IRC idle time measures how long since you last sent something (see
103 `erc-autoaway-last-sent-time').
104
105 If `erc-auto-discard-away' is set, then typing anything, will
106 set you no longer away.
107
108 Related variables: `erc-public-away-p' and `erc-away-nickname'."
109 ;; Enable:
110 ((when (boundp 'erc-autoaway-idle-method)
111 (add-hook 'erc-connect-pre-hook 'erc-autoaway-reset-indicators)
112 (setq erc-autoaway-last-sent-time (erc-current-time))
113 (cond
114 ((eq erc-autoaway-idle-method 'irc)
115 (add-hook 'erc-send-completed-hook 'erc-autoaway-reset-idle-irc)
116 (add-hook 'erc-server-001-functions 'erc-autoaway-reset-idle-irc))
117 ((eq erc-autoaway-idle-method 'user)
118 (add-hook 'erc-after-connect 'erc-autoaway-insinuate-maybe)
119 (add-hook 'erc-disconnected-hook 'erc-autoaway-remove-maybe)
120 (erc-autoaway-insinuate-maybe))
121 ((eq erc-autoaway-idle-method 'emacs)
122 (erc-autoaway-reestablish-idletimer)))
123 (add-hook 'erc-timer-hook 'erc-autoaway-possibly-set-away)
124 (add-hook 'erc-server-305-functions 'erc-autoaway-reset-indicators)))
125 ;; Disable:
126 ((when (boundp 'erc-autoaway-idle-method)
127 (remove-hook 'erc-connect-pre-hook 'erc-autoaway-reset-indicators)
128 (cond
129 ((eq erc-autoaway-idle-method 'irc)
130 (remove-hook 'erc-send-completed-hook 'erc-autoaway-reset-idle-irc)
131 (remove-hook 'erc-server-001-functions 'erc-autoaway-reset-idle-irc))
132 ((eq erc-autoaway-idle-method 'user)
133 (remove-hook 'post-command-hook 'erc-autoaway-reset-idle-user)
134 (remove-hook 'erc-after-connect 'erc-autoaway-insinuate-maybe)
135 (remove-hook 'erc-disconnected-hook 'erc-autoaway-remove-maybe))
136 ((eq erc-autoaway-idle-method 'emacs)
137 (erc-cancel-timer erc-autoaway-idletimer)
138 (setq erc-autoaway-idletimer nil)))
139 (remove-hook 'erc-timer-hook 'erc-autoaway-possibly-set-away)
140 (remove-hook 'erc-server-305-functions 'erc-autoaway-reset-indicators))))
141
142 (defcustom erc-autoaway-idle-method 'user
143 "*The method used to determine how long you have been idle.
144 If 'user, the time of the last command sent to Emacs is used.
145 If 'emacs, the idle time in Emacs is used.
146 If 'irc, the time of the last IRC command is used.
147
148 The time itself is specified by `erc-autoaway-idle-seconds'.
149
150 See `erc-autoaway-mode' for more information on the various
151 definitions of being idle."
152 :group 'erc-autoaway
153 :type '(choice (const :tag "User idle time" user)
154 (const :tag "Emacs idle time" emacs)
155 (const :tag "Last IRC action" irc))
156 :set (lambda (sym val)
157 (if erc-autoaway-mode
158 (progn
159 (erc-autoaway-disable)
160 (set sym val)
161 (erc-autoaway-enable))
162 (set sym val))))
163
164 (defcustom erc-auto-set-away t
165 "*If non-nil, set away after `erc-autoaway-idle-seconds' seconds of idling.
166 ERC autoaway mode can set you away when you idle, and set you no
167 longer away when you type something. This variable controls whether
168 you will be set away when you idle. See `erc-auto-discard-away' for
169 the other half."
170 :group 'erc-autoaway
171 :type 'boolean)
172
173 (defcustom erc-auto-discard-away t
174 "*If non-nil, sending anything when away automatically discards away state.
175 ERC autoaway mode can set you away when you idle, and set you no
176 longer away when you type something. This variable controls whether
177 you will be set no longer away when you type something. See
178 `erc-auto-set-away' for the other half.
179 See also `erc-autoaway-no-auto-discard-regexp'."
180 :group 'erc-autoaway
181 :type 'boolean)
182
183 (defcustom erc-autoaway-no-auto-discard-regexp "^/g?away.*$"
184 "*Input that matches this will not automatically discard away status.
185 See `erc-auto-discard-away'."
186 :group 'erc-autoaway
187 :type 'regexp)
188
189 (defcustom erc-autoaway-idle-seconds 1800
190 "*Number of seconds after which ERC will set you automatically away.
191 If you are changing this variable using lisp instead of customizing it,
192 you have to run `erc-autoaway-reestablish-idletimer' afterwards."
193 :group 'erc-autoaway
194 :set (lambda (sym val)
195 (set-default sym val)
196 (when (eq erc-autoaway-idle-method 'emacs)
197 (erc-autoaway-reestablish-idletimer)))
198 :type 'number)
199
200 (defcustom erc-autoaway-message
201 "I'm gone (autoaway after %i seconds of idletime)"
202 "*Message ERC will use when setting you automatically away.
203 It is used as a `format' string with the argument of the idletime
204 in seconds."
205 :group 'erc-autoaway
206 :type 'string)
207
208 (defun erc-autoaway-reset-idle-user (&rest stuff)
209 "Reset the stored user idle time.
210 This is one global variable since a user talking on one net can
211 talk on another net too."
212 (when erc-auto-discard-away
213 (erc-autoaway-set-back #'erc-autoaway-remove-maybe))
214 (setq erc-autoaway-last-sent-time (erc-current-time)))
215
216 (defun erc-autoaway-reset-idle-irc (line &rest stuff)
217 "Reset the stored IRC idle time.
218 This is one global variable since a user talking on one net can
219 talk on another net too."
220 (when (and erc-auto-discard-away
221 (stringp line)
222 (not (string-match erc-autoaway-no-auto-discard-regexp line)))
223 (erc-autoaway-set-back))
224 (setq erc-autoaway-last-sent-time (erc-current-time)))
225
226 (defun erc-autoaway-set-back (&optional none-alive-func)
227 "Discard the away state globally.
228
229 NONE-ALIVE-FUNC is the function to call if no ERC processes are alive."
230 (let ((server-buffer (erc-autoaway-some-server-buffer)))
231 (if (and erc-autoaway-caused-away
232 (buffer-live-p server-buffer)
233 (with-current-buffer server-buffer erc-away))
234 (erc-cmd-GAWAY "")
235 (when none-alive-func (funcall none-alive-func)))))
236
237 (defun erc-autoaway-some-open-server-buffer ()
238 "Return some ERC server buffer if its connection is alive and the
239 user is not away.
240 If none is found, return nil."
241 (car (erc-buffer-list (lambda ()
242 (and (erc-open-server-buffer-p)
243 (not erc-away))))))
244
245 (defun erc-autoaway-possibly-set-away (current-time)
246 "Set autoaway when `erc-auto-set-away' is true and the idletime is
247 exceeds `erc-autoaway-idle-seconds'."
248 ;; A test for (erc-server-process-alive) is not necessary, because
249 ;; this function is called from `erc-timer-hook', which is called
250 ;; whenever the server sends something to the client.
251 (when (and erc-server-connected
252 erc-auto-set-away
253 (not erc-autoaway-caused-away)
254 (erc-autoaway-some-open-server-buffer))
255 (let ((idle-time (erc-time-diff erc-autoaway-last-sent-time
256 current-time)))
257 (when (>= idle-time erc-autoaway-idle-seconds)
258 (erc-display-message
259 nil 'notice nil
260 (format "Setting automatically away after %i seconds of idle-time"
261 idle-time))
262 (erc-autoaway-set-away idle-time t)))))
263
264 (defun erc-autoaway-set-away (idle-time &optional notest)
265 "Set the away state globally.
266
267 If NOTEST is specified, do not check to see whether there is an
268 activer server buffer available."
269 ;; Note that the idle timer runs, even when Emacs is inactive. In
270 ;; order to prevent flooding when we connect, we test for an
271 ;; existing process.
272 (when (or notest (erc-autoaway-some-open-server-buffer))
273 (setq erc-autoaway-caused-away t)
274 (erc-cmd-GAWAY (format erc-autoaway-message idle-time))))
275
276 (defun erc-autoaway-reset-indicators (&rest stuff)
277 "Reset indicators used by the erc-autoaway module."
278 (setq erc-autoaway-last-sent-time (erc-current-time))
279 (setq erc-autoaway-caused-away nil))
280
281 (provide 'erc-autoaway)
282
283 ;;; erc-autoaway.el ends here
284 ;;
285 ;; Local Variables:
286 ;; indent-tabs-mode: t
287 ;; tab-width: 8
288 ;; End:
289
290 ;; arch-tag: 16fc241e-8358-4b56-9fe2-116bdd0ba3bc