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