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