Merge from emacs-24; up to 2012-04-26T03:04:36Z!cyd@gnu.org
[bpt/emacs.git] / lisp / erc / erc-goodies.el
CommitLineData
597993cf
MB
1;; erc-goodies.el --- Collection of ERC modules
2
acaf905b 3;; Copyright (C) 2001-2012 Free Software Foundation, Inc.
597993cf
MB
4
5;; Author: Jorgen Schaefer <forcer@forcix.cx>
6
7;; Most code is taken verbatim from erc.el, see there for the original
8;; authors.
9
10;; This file is part of GNU Emacs.
11
4ee57b2a 12;; GNU Emacs is free software: you can redistribute it and/or modify
597993cf 13;; it under the terms of the GNU General Public License as published by
4ee57b2a
GM
14;; the Free Software Foundation, either version 3 of the License, or
15;; (at your option) any later version.
597993cf
MB
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
4ee57b2a 23;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
597993cf
MB
24
25;;; Commentary:
26
27;; This provides some small but still useful modes for ERC.
28
29;;; Code:
30
31(require 'erc)
32
5e56b3fb
MO
33;;; Imenu support
34
35(defun erc-imenu-setup ()
36 "Setup Imenu support in an ERC buffer."
37 (set (make-local-variable 'imenu-create-index-function)
38 'erc-create-imenu-index))
39
40(add-hook 'erc-mode-hook 'erc-imenu-setup)
597993cf
MB
41(autoload 'erc-create-imenu-index "erc-imenu" "Imenu index creation function")
42
43;;; Automatically scroll to bottom
44(defcustom erc-input-line-position nil
45 "Specify where to position the input line when using `erc-scroll-to-bottom'.
46
47This should be an integer specifying the line of the buffer on which
48the input line should stay. A value of \"-1\" would keep the input
49line positioned on the last line in the buffer. This is passed as an
50argument to `recenter'."
51 :group 'erc-display
52 :type '(choice integer (const nil)))
53
54(define-erc-module scrolltobottom nil
5e56b3fb
MO
55 "This mode causes the prompt to stay at the end of the window."
56 ((add-hook 'erc-mode-hook 'erc-add-scroll-to-bottom)
57 (dolist (buffer (erc-buffer-list))
58 (with-current-buffer buffer
59 (erc-add-scroll-to-bottom))))
60 ((remove-hook 'erc-mode-hook 'erc-add-scroll-to-bottom)
61 (dolist (buffer (erc-buffer-list))
62 (with-current-buffer buffer
7c2b8880 63 (remove-hook 'post-command-hook 'erc-scroll-to-bottom t)))))
597993cf
MB
64
65(defun erc-add-scroll-to-bottom ()
66 "A hook function for `erc-mode-hook' to recenter output at bottom of window.
67
68If you find that ERC hangs when using this function, try customizing
69the value of `erc-input-line-position'.
70
71This works whenever scrolling happens, so it's added to
72`window-scroll-functions' rather than `erc-insert-post-hook'."
7c2b8880 73 (add-hook 'post-command-hook 'erc-scroll-to-bottom nil t))
597993cf 74
7c2b8880 75(defun erc-scroll-to-bottom ()
597993cf
MB
76 "Recenter WINDOW so that `point' is on the last line.
77
78This is added to `window-scroll-functions' by `erc-add-scroll-to-bottom'.
79
80You can control which line is recentered to by customizing the
7c2b8880 81variable `erc-input-line-position'."
597993cf
MB
82 ;; Temporarily bind resize-mini-windows to nil so that users who have it
83 ;; set to a non-nil value will not suffer from premature minibuffer
84 ;; shrinkage due to the below recenter call. I have no idea why this
85 ;; works, but it solves the problem, and has no negative side effects.
86 ;; (Fran Litterio, 2003/01/07)
7c2b8880
AL
87 (let ((resize-mini-windows nil))
88 (save-restriction
89 (widen)
90 (when (and erc-insert-marker
91 ;; we're editing a line. Scroll.
92 (> (point) erc-insert-marker))
93 (save-excursion
94 (goto-char (point-max))
95 (recenter (or erc-input-line-position -1)))))))
597993cf
MB
96
97;;; Make read only
98(define-erc-module readonly nil
99 "This mode causes all inserted text to be read-only."
100 ((add-hook 'erc-insert-post-hook 'erc-make-read-only)
101 (add-hook 'erc-send-post-hook 'erc-make-read-only))
102 ((remove-hook 'erc-insert-post-hook 'erc-make-read-only)
103 (remove-hook 'erc-send-post-hook 'erc-make-read-only)))
104
105(defun erc-make-read-only ()
106 "Make all the text in the current buffer read-only.
107Put this function on `erc-insert-post-hook' and/or `erc-send-post-hook'."
108 (put-text-property (point-min) (point-max) 'read-only t)
109 (put-text-property (point-min) (point-max) 'front-sticky t)
110 (put-text-property (point-min) (point-max) 'rear-nonsticky t))
111
5e56b3fb
MO
112;;; Move to prompt when typing text
113(define-erc-module move-to-prompt nil
114 "This mode causes the point to be moved to the prompt when typing text."
115 ((add-hook 'erc-mode-hook 'erc-move-to-prompt-setup)
116 (dolist (buffer (erc-buffer-list))
117 (with-current-buffer buffer
118 (erc-move-to-prompt-setup))))
119 ((remove-hook 'erc-mode-hook 'erc-move-to-prompt-setup)
120 (dolist (buffer (erc-buffer-list))
121 (with-current-buffer buffer
122 (remove-hook 'pre-command-hook 'erc-move-to-prompt t)))))
123
124(defun erc-move-to-prompt ()
125 "Move the point to the ERC prompt if this is a self-inserting command."
126 (when (and erc-input-marker (< (point) erc-input-marker)
127 (eq 'self-insert-command this-command))
128 (deactivate-mark)
129 (push-mark)
130 (goto-char (point-max))))
131
132(defun erc-move-to-prompt-setup ()
133 "Initialize the move-to-prompt module for XEmacs."
134 (add-hook 'pre-command-hook 'erc-move-to-prompt nil t))
135
136;;; Keep place in unvisited channels
137(define-erc-module keep-place nil
138 "Leave point above un-viewed text in other channels."
139 ((add-hook 'erc-insert-pre-hook 'erc-keep-place))
140 ((remove-hook 'erc-insert-pre-hook 'erc-keep-place)))
141
142(defun erc-keep-place (ignored)
143 "Move point away from the last line in a non-selected ERC buffer."
144 (when (and (not (eq (window-buffer (selected-window))
145 (current-buffer)))
146 (>= (point) erc-insert-marker))
147 (deactivate-mark)
148 (goto-char (erc-beg-of-input-line))
149 (forward-line -1)))
150
151;;; Distinguish non-commands
597993cf
MB
152(defvar erc-noncommands-list '(erc-cmd-ME
153 erc-cmd-COUNTRY
154 erc-cmd-SV
155 erc-cmd-SM
156 erc-cmd-SMV
157 erc-cmd-LASTLOG)
f44407aa 158 "List of commands that are aliases for CTCP ACTION or for ERC messages.
597993cf
MB
159
160If a command's function symbol is in this list, the typed command
161does not appear in the ERC buffer after the user presses ENTER.")
162
163(define-erc-module noncommands nil
f44407aa 164 "This mode distinguishes non-commands.
597993cf
MB
165Commands listed in `erc-insert-this' know how to display
166themselves."
167 ((add-hook 'erc-send-pre-hook 'erc-send-distinguish-noncommands))
168 ((remove-hook 'erc-send-pre-hook 'erc-send-distinguish-noncommands)))
169
170(defun erc-send-distinguish-noncommands (str)
171 "If STR is an ERC non-command, set `erc-insert-this' to nil."
172 (let* ((command (erc-extract-command-from-line str))
173 (cmd-fun (and command
174 (car command))))
175 (when (and cmd-fun
176 (not (string-match "\n.+$" str))
177 (memq cmd-fun erc-noncommands-list))
178 (setq erc-insert-this nil))))
179
180;;; IRC control character processing.
181(defgroup erc-control-characters nil
f44407aa 182 "Dealing with control characters."
597993cf
MB
183 :group 'erc)
184
185(defcustom erc-interpret-controls-p t
fb7ada5f 186 "If non-nil, display IRC colors and other highlighting effects.
597993cf
MB
187
188If this is set to the symbol `remove', ERC removes all IRC colors and
189highlighting effects. When this variable is non-nil, it can cause Emacs to run
190slowly on systems lacking sufficient CPU speed. In chatty channels, or in an
191emergency (message flood) it can be turned off to save processing time. See
192`erc-toggle-interpret-controls'."
193 :group 'erc-control-characters
194 :type '(choice (const :tag "Highlight control characters" t)
195 (const :tag "Remove control characters" remove)
196 (const :tag "Display raw control characters" nil)))
197
198(defcustom erc-interpret-mirc-color nil
fb7ada5f 199 "If non-nil, ERC will interpret mIRC color codes."
597993cf
MB
200 :group 'erc-control-characters
201 :type 'boolean)
202
203(defcustom erc-beep-p nil
204 "Beep if C-g is in the server message.
205The value `erc-interpret-controls-p' must also be t for this to work."
206 :group 'erc-control-characters
207 :type 'boolean)
208
4b56d0fe 209(defface erc-bold-face '((t :weight bold))
597993cf
MB
210 "ERC bold face."
211 :group 'erc-faces)
4b56d0fe 212
597993cf 213(defface erc-inverse-face
4b56d0fe 214 '((t :foreground "White" :background "Black"))
597993cf
MB
215 "ERC inverse face."
216 :group 'erc-faces)
4b56d0fe
CY
217
218(defface erc-underline-face '((t :underline t))
597993cf
MB
219 "ERC underline face."
220 :group 'erc-faces)
221
4b56d0fe 222(defface fg:erc-color-face0 '((t :foreground "White"))
597993cf
MB
223 "ERC face."
224 :group 'erc-faces)
4b56d0fe 225(defface fg:erc-color-face1 '((t :foreground "black"))
597993cf
MB
226 "ERC face."
227 :group 'erc-faces)
4b56d0fe 228(defface fg:erc-color-face2 '((t :foreground "blue4"))
597993cf
MB
229 "ERC face."
230 :group 'erc-faces)
4b56d0fe 231(defface fg:erc-color-face3 '((t :foreground "green4"))
597993cf
MB
232 "ERC face."
233 :group 'erc-faces)
4b56d0fe 234(defface fg:erc-color-face4 '((t :foreground "red"))
597993cf
MB
235 "ERC face."
236 :group 'erc-faces)
4b56d0fe 237(defface fg:erc-color-face5 '((t :foreground "brown"))
597993cf
MB
238 "ERC face."
239 :group 'erc-faces)
4b56d0fe 240(defface fg:erc-color-face6 '((t :foreground "purple"))
597993cf
MB
241 "ERC face."
242 :group 'erc-faces)
4b56d0fe 243(defface fg:erc-color-face7 '((t :foreground "orange"))
597993cf
MB
244 "ERC face."
245 :group 'erc-faces)
4b56d0fe 246(defface fg:erc-color-face8 '((t :foreground "yellow"))
597993cf
MB
247 "ERC face."
248 :group 'erc-faces)
4b56d0fe 249(defface fg:erc-color-face9 '((t :foreground "green"))
597993cf
MB
250 "ERC face."
251 :group 'erc-faces)
4b56d0fe 252(defface fg:erc-color-face10 '((t :foreground "lightblue1"))
597993cf
MB
253 "ERC face."
254 :group 'erc-faces)
4b56d0fe 255(defface fg:erc-color-face11 '((t :foreground "cyan"))
597993cf
MB
256 "ERC face."
257 :group 'erc-faces)
4b56d0fe 258(defface fg:erc-color-face12 '((t :foreground "blue"))
597993cf
MB
259 "ERC face."
260 :group 'erc-faces)
4b56d0fe 261(defface fg:erc-color-face13 '((t :foreground "deeppink"))
597993cf
MB
262 "ERC face."
263 :group 'erc-faces)
4b56d0fe 264(defface fg:erc-color-face14 '((t :foreground "gray50"))
597993cf
MB
265 "ERC face."
266 :group 'erc-faces)
4b56d0fe 267(defface fg:erc-color-face15 '((t :foreground "gray90"))
597993cf
MB
268 "ERC face."
269 :group 'erc-faces)
270
4b56d0fe 271(defface bg:erc-color-face0 '((t :background "White"))
597993cf
MB
272 "ERC face."
273 :group 'erc-faces)
4b56d0fe 274(defface bg:erc-color-face1 '((t :background "black"))
597993cf
MB
275 "ERC face."
276 :group 'erc-faces)
4b56d0fe 277(defface bg:erc-color-face2 '((t :background "blue4"))
597993cf
MB
278 "ERC face."
279 :group 'erc-faces)
4b56d0fe 280(defface bg:erc-color-face3 '((t :background "green4"))
597993cf
MB
281 "ERC face."
282 :group 'erc-faces)
4b56d0fe 283(defface bg:erc-color-face4 '((t :background "red"))
597993cf
MB
284 "ERC face."
285 :group 'erc-faces)
4b56d0fe 286(defface bg:erc-color-face5 '((t :background "brown"))
597993cf
MB
287 "ERC face."
288 :group 'erc-faces)
4b56d0fe 289(defface bg:erc-color-face6 '((t :background "purple"))
597993cf
MB
290 "ERC face."
291 :group 'erc-faces)
4b56d0fe 292(defface bg:erc-color-face7 '((t :background "orange"))
597993cf
MB
293 "ERC face."
294 :group 'erc-faces)
4b56d0fe 295(defface bg:erc-color-face8 '((t :background "yellow"))
597993cf
MB
296 "ERC face."
297 :group 'erc-faces)
4b56d0fe 298(defface bg:erc-color-face9 '((t :background "green"))
597993cf
MB
299 "ERC face."
300 :group 'erc-faces)
4b56d0fe 301(defface bg:erc-color-face10 '((t :background "lightblue1"))
597993cf
MB
302 "ERC face."
303 :group 'erc-faces)
4b56d0fe 304(defface bg:erc-color-face11 '((t :background "cyan"))
597993cf
MB
305 "ERC face."
306 :group 'erc-faces)
4b56d0fe 307(defface bg:erc-color-face12 '((t :background "blue"))
597993cf
MB
308 "ERC face."
309 :group 'erc-faces)
4b56d0fe 310(defface bg:erc-color-face13 '((t :background "deeppink"))
597993cf
MB
311 "ERC face."
312 :group 'erc-faces)
4b56d0fe 313(defface bg:erc-color-face14 '((t :background "gray50"))
597993cf
MB
314 "ERC face."
315 :group 'erc-faces)
4b56d0fe 316(defface bg:erc-color-face15 '((t :background "gray90"))
597993cf
MB
317 "ERC face."
318 :group 'erc-faces)
319
320(defun erc-get-bg-color-face (n)
321 "Fetches the right face for background color N (0-15)."
322 (if (stringp n) (setq n (string-to-number n)))
323 (if (not (numberp n))
526dc846
MO
324 (prog1 'default
325 (erc-error "erc-get-bg-color-face: n is NaN: %S" n))
597993cf
MB
326 (when (> n 16)
327 (erc-log (format " Wrong color: %s" n))
328 (setq n (mod n 16)))
329 (cond
330 ((and (>= n 0) (< n 16))
331 (intern (concat "bg:erc-color-face" (number-to-string n))))
332 (t (erc-log (format " Wrong color: %s" n)) 'default))))
333
334(defun erc-get-fg-color-face (n)
335 "Fetches the right face for foreground color N (0-15)."
336 (if (stringp n) (setq n (string-to-number n)))
337 (if (not (numberp n))
526dc846
MO
338 (prog1 'default
339 (erc-error "erc-get-fg-color-face: n is NaN: %S" n))
597993cf
MB
340 (when (> n 16)
341 (erc-log (format " Wrong color: %s" n))
342 (setq n (mod n 16)))
343 (cond
344 ((and (>= n 0) (< n 16))
345 (intern (concat "fg:erc-color-face" (number-to-string n))))
346 (t (erc-log (format " Wrong color: %s" n)) 'default))))
347
348(define-erc-module irccontrols nil
349 "This mode enables the interpretation of IRC control chars."
350 ((add-hook 'erc-insert-modify-hook 'erc-controls-highlight)
351 (add-hook 'erc-send-modify-hook 'erc-controls-highlight))
352 ((remove-hook 'erc-insert-modify-hook 'erc-controls-highlight)
353 (remove-hook 'erc-send-modify-hook 'erc-controls-highlight)))
354
355(defun erc-controls-interpret (str)
356 "Return a copy of STR after dealing with IRC control characters.
357See `erc-interpret-controls-p' and `erc-interpret-mirc-color' for options."
358 (when str
359 (let ((s str))
360 (cond ((eq erc-interpret-controls-p 'remove)
361 (erc-controls-strip s))
362 (erc-interpret-controls-p
363 (let ((boldp nil)
364 (inversep nil)
365 (underlinep nil)
366 (fg nil)
367 (bg nil))
368 (while (string-match erc-controls-highlight-regexp s)
369 (let ((control (match-string 1 s))
370 (fg-color (match-string 2 s))
371 (bg-color (match-string 4 s))
372 (start (match-beginning 0))
373 (end (+ (match-beginning 0)
374 (length (match-string 5 s)))))
375 (setq s (erc-replace-match-subexpression-in-string
376 "" s control 1 start))
377 (cond ((and erc-interpret-mirc-color (or fg-color bg-color))
378 (setq fg fg-color)
379 (setq bg bg-color))
380 ((string= control "\C-b")
381 (setq boldp (not boldp)))
382 ((string= control "\C-v")
383 (setq inversep (not inversep)))
384 ((string= control "\C-_")
385 (setq underlinep (not underlinep)))
386 ((string= control "\C-c")
387 (setq fg nil
388 bg nil))
389 ((string= control "\C-g")
390 (when erc-beep-p
391 (ding)))
392 ((string= control "\C-o")
393 (setq boldp nil
394 inversep nil
395 underlinep nil
396 fg nil
397 bg nil))
398 (t nil))
399 (erc-controls-propertize
400 start end boldp inversep underlinep fg bg s)))
401 s))
402 (t s)))))
403
404(defun erc-controls-strip (str)
405 "Return a copy of STR with all IRC control characters removed."
406 (when str
407 (let ((s str))
408 (while (string-match erc-controls-remove-regexp s)
409 (setq s (replace-match "" nil nil s)))
410 s)))
411
412(defvar erc-controls-remove-regexp
413 "\C-b\\|\C-_\\|\C-v\\|\C-g\\|\C-o\\|\C-c[0-9]?[0-9]?\\(,[0-9][0-9]?\\)?"
414 "Regular expression which matches control characters to remove.")
415
416(defvar erc-controls-highlight-regexp
417 (concat "\\(\C-b\\|\C-v\\|\C-_\\|\C-g\\|\C-o\\|"
418 "\C-c\\([0-9][0-9]?\\)?\\(,\\([0-9][0-9]?\\)\\)?\\)"
419 "\\([^\C-b\C-v\C-_\C-c\C-g\C-o\n]*\\)")
420 "Regular expression which matches control chars and the text to highlight.")
421
422(defun erc-controls-highlight ()
423 "Highlight IRC control chars in the buffer.
f44407aa
JB
424This is useful for `erc-insert-modify-hook' and `erc-send-modify-hook'.
425Also see `erc-interpret-controls-p' and `erc-interpret-mirc-color'."
597993cf
MB
426 (goto-char (point-min))
427 (cond ((eq erc-interpret-controls-p 'remove)
428 (while (re-search-forward erc-controls-remove-regexp nil t)
429 (replace-match "")))
430 (erc-interpret-controls-p
431 (let ((boldp nil)
432 (inversep nil)
433 (underlinep nil)
434 (fg nil)
435 (bg nil))
436 (while (re-search-forward erc-controls-highlight-regexp nil t)
437 (let ((control (match-string 1))
438 (fg-color (match-string 2))
439 (bg-color (match-string 4))
440 (start (match-beginning 0))
441 (end (+ (match-beginning 0) (length (match-string 5)))))
442 (replace-match "" nil nil nil 1)
443 (cond ((and erc-interpret-mirc-color (or fg-color bg-color))
444 (setq fg fg-color)
445 (setq bg bg-color))
446 ((string= control "\C-b")
447 (setq boldp (not boldp)))
448 ((string= control "\C-v")
449 (setq inversep (not inversep)))
450 ((string= control "\C-_")
451 (setq underlinep (not underlinep)))
452 ((string= control "\C-c")
453 (setq fg nil
454 bg nil))
455 ((string= control "\C-g")
456 (when erc-beep-p
457 (ding)))
458 ((string= control "\C-o")
459 (setq boldp nil
460 inversep nil
461 underlinep nil
462 fg nil
463 bg nil))
464 (t nil))
465 (erc-controls-propertize start end
466 boldp inversep underlinep fg bg)))))
467 (t nil)))
468
469(defun erc-controls-propertize (from to boldp inversep underlinep fg bg
470 &optional str)
471 "Prepend properties from IRC control characters between FROM and TO.
472If optional argument STR is provided, apply to STR, otherwise prepend properties
473to a region in the current buffer."
474 (font-lock-prepend-text-property
475 from
476 to
477 'face
478 (append (if boldp
479 '(erc-bold-face)
480 nil)
481 (if inversep
482 '(erc-inverse-face)
483 nil)
484 (if underlinep
485 '(erc-underline-face)
486 nil)
487 (if fg
488 (list (erc-get-fg-color-face fg))
489 nil)
490 (if bg
491 (list (erc-get-bg-color-face bg))
492 nil))
493 str)
494 str)
495
496(defun erc-toggle-interpret-controls (&optional arg)
497 "Toggle interpretation of control sequences in messages.
498
499If ARG is positive, interpretation is turned on.
500Else interpretation is turned off."
501 (interactive "P")
502 (cond ((and (numberp arg) (> arg 0))
503 (setq erc-interpret-controls-p t))
504 (arg (setq erc-interpret-controls-p nil))
505 (t (setq erc-interpret-controls-p (not erc-interpret-controls-p))))
506 (message "ERC color interpretation %s"
507 (if erc-interpret-controls-p "ON" "OFF")))
508
509;; Smiley
510(define-erc-module smiley nil
511 "This mode translates text-smileys such as :-) into pictures.
512This requires the function `smiley-region', which is defined in
513smiley.el, which is part of Gnus."
514 ((add-hook 'erc-insert-modify-hook 'erc-smiley)
515 (add-hook 'erc-send-modify-hook 'erc-smiley))
516 ((remove-hook 'erc-insert-modify-hook 'erc-smiley)
517 (remove-hook 'erc-send-modify-hook 'erc-smiley)))
518
519(defun erc-smiley ()
520 "Smilify a region.
521This function should be used with `erc-insert-modify-hook'."
522 (when (fboundp 'smiley-region)
523 (smiley-region (point-min) (point-max))))
524
525;; Unmorse
526(define-erc-module unmorse nil
527 "This mode causes morse code in the current channel to be unmorsed."
528 ((add-hook 'erc-insert-modify-hook 'erc-unmorse))
529 ((remove-hook 'erc-insert-modify-hook 'erc-unmorse)))
530
531(defun erc-unmorse ()
532 "Unmorse some text.
533Add this to `erc-insert-modify-hook' if you happen to be on a
534channel that has weird people talking in morse to each other.
535
536See also `unmorse-region'."
537 (goto-char (point-min))
5e56b3fb
MO
538 (when (re-search-forward "[.-]+\\([.-]*/? *\\)+[.-]+/?" nil t)
539 (save-restriction
540 (narrow-to-region (match-beginning 0) (match-end 0))
541 ;; Turn " / " into " "
542 (goto-char (point-min))
543 (while (re-search-forward " / " nil t)
544 (replace-match " "))
545 ;; Turn "/ " into "/"
546 (goto-char (point-min))
547 (while (re-search-forward "/ " nil t)
548 (replace-match "/"))
549 ;; Unmorse region
550 (unmorse-region (point-min) (point-max)))))
597993cf
MB
551
552;;; erc-occur
553(defun erc-occur (string &optional proc)
554 "Search for STRING in all buffers related to current server.
555If called interactively and prefix argument is given, search on all connected
556servers. If called from a program, PROC specifies the server process."
557 (interactive
558 (list (read-string "Search for: ")
559 (if current-prefix-arg
560 nil erc-server-process)))
561 (if (fboundp 'multi-occur)
562 (multi-occur (erc-buffer-list nil proc) string)
563 (error "`multi-occur' is not defined as a function")))
564
565(provide 'erc-goodies)
566
597993cf 567;;; erc-goodies.el ends here