;;; erc-track.el --- Track modified channel buffers
-;; Copyright (C) 2002, 2003, 2004, 2005, 2006,
-;; 2007 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2011 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@delysid.org>
;; Keywords: comm, faces
;; This file is part of GNU Emacs.
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 3, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
:type '(choice (const :tag "All frames" t)
(const :tag "All visible frames" visible)
(const :tag "Only the selected frame" nil)
- (const :tag "Only the selected frame if it was active"
- active)))
+ (const :tag "Only the selected frame if it is visible"
+ selected-visible)))
(defcustom erc-track-exclude nil
"A list targets (channel names or query targets) which should not be tracked."
:group 'erc-track
:type 'boolean)
-(defcustom erc-track-exclude-types '("NICK")
+(defcustom erc-track-exclude-types '("NICK" "333" "353")
"*List of message types to be ignored.
-This list could look like '(\"JOIN\" \"PART\")."
+This list could look like '(\"JOIN\" \"PART\").
+
+By default, exclude changes of nicknames (NICK), display of who
+set the channel topic (333), and listing of users on the current
+channel (353)."
:group 'erc-track
:type 'erc-message-type)
:type 'boolean)
(defcustom erc-track-faces-priority-list
- '(erc-error-face erc-current-nick-face erc-keyword-face erc-pal-face
- erc-nick-msg-face erc-direct-msg-face erc-button erc-dangerous-host-face
- erc-default-face erc-action-face erc-nick-default-face erc-fool-face
- erc-notice-face erc-input-face erc-prompt-face)
+ '(erc-error-face
+ (erc-nick-default-face erc-current-nick-face)
+ erc-current-nick-face
+ erc-keyword-face
+ (erc-nick-default-face erc-pal-face)
+ erc-pal-face
+ erc-nick-msg-face
+ erc-direct-msg-face
+ (erc-button erc-default-face)
+ (erc-nick-default-face erc-dangerous-host-face)
+ erc-dangerous-host-face
+ erc-nick-default-face
+ (erc-nick-default-face erc-default-face)
+ erc-default-face
+ erc-action-face
+ (erc-nick-default-face erc-fool-face)
+ erc-fool-face
+ erc-notice-face
+ erc-input-face
+ erc-prompt-face)
"A list of faces used to highlight active buffer names in the modeline.
If a message contains one of the faces in this list, the buffer name will
be highlighted using that face. The first matching face is used."
:group 'erc-track
- :type '(repeat face))
+ :type '(repeat (choice face
+ (repeat :tag "Combination" face))))
(defcustom erc-track-priority-faces-only nil
"Only track text highlighted with a priority face.
will be ignored while all other channels will be tracked as normal.
Other options are 'all, to apply this to all channels or nil, to disable
this feature.
+
Note: If you have a lot of faces listed in `erc-track-faces-priority-list',
setting this variable might not be very useful."
:group 'erc-track
(repeat string)
(const all)))
+(defcustom erc-track-faces-normal-list
+ '((erc-button erc-default-face)
+ (erc-nick-default-face erc-dangerous-host-face)
+ erc-dangerous-host-face
+ erc-nick-default-face
+ (erc-nick-default-face erc-default-face)
+ erc-default-face
+ erc-action-face)
+ "A list of faces considered to be part of normal conversations.
+This list is used to highlight active buffer names in the modeline.
+
+If a message contains one of the faces in this list, and the
+previous modeline face for this buffer is also in this list, then
+the buffer name will be highlighted using the face from the
+message. This gives a rough indication that active conversations
+are occurring in these channels.
+
+The effect may be disabled by setting this variable to nil."
+ :group 'erc-track
+ :type '(repeat (choice face
+ (repeat :tag "Combination" face))))
+
(defcustom erc-track-position-in-mode-line 'before-modes
"Where to show modified channel information in the mode-line.
Setting this variable only has effects in GNU Emacs versions above 21.3.
Choices are:
-'before-modes - add to the beginning of `mode-line-modes'
-'after-modes - add to the end of `mode-line-modes'
-t - add to the end of `global-mode-string'.
-nil - don't add to mode line
-"
+'before-modes - add to the beginning of `mode-line-modes',
+'after-modes - add to the end of `mode-line-modes',
+t - add to the end of `global-mode-string',
+nil - don't add to mode line."
:group 'erc-track
:type '(choice (const :tag "Just before mode information" before-modes)
(const :tag "Just after mode information" after-modes)
;;; Test:
-(erc-assert
+(assert
(and
;; verify examples from the doc strings
(equal (let ((erc-track-shorten-aggressively nil))
;;;###autoload
(define-minor-mode erc-track-minor-mode
- "Global minor mode for tracking ERC buffers and showing activity in the
-mode line.
-
-This exists for the sole purpose of providing the C-c C-SPC and
-C-c C-@ keybindings. Make sure that you have enabled the track
-module, otherwise the keybindings will not do anything useful."
+ "Toggle mode line display of ERC activity (ERC Track minor mode).
+With a prefix argument ARG, enable ERC Track minor mode if ARG is
+positive, and disable it otherwise. If called from Lisp, enable
+the mode if ARG is omitted or nil.
+
+ERC Track minor mode is a global minor mode. It exists for the
+sole purpose of providing the C-c C-SPC and C-c C-@ keybindings.
+Make sure that you have enabled the track module, otherwise the
+keybindings will not do anything useful."
:init-value nil
:lighter ""
:keymap erc-track-minor-mode-map
:global t
:group 'erc-track)
-(defun erc-track-minor-mode-maybe ()
+(defun erc-track-minor-mode-maybe (&optional buffer)
"Enable `erc-track-minor-mode', depending on `erc-track-enable-keybindings'."
- (unless (or erc-track-minor-mode
- ;; don't start the minor mode until we have an ERC
- ;; process running, because we don't want to prompt the
- ;; user while starting Emacs
- (null (erc-buffer-list)))
+ (when (and (not erc-track-minor-mode)
+ ;; don't start the minor mode until we have an ERC
+ ;; process running, because we don't want to prompt the
+ ;; user while starting Emacs
+ (or (and (buffer-live-p buffer)
+ (with-current-buffer buffer (eq major-mode 'erc-mode)))
+ (erc-buffer-list)))
(cond ((eq erc-track-enable-keybindings 'ask)
(let ((key (or (and (key-binding (kbd "C-c C-SPC")) "C-SPC")
(and (key-binding (kbd "C-c C-@")) "C-@"))))
(add-hook 'erc-send-completed-hook 'erc-user-is-active)
(add-hook 'erc-server-001-functions 'erc-user-is-active))
(erc-track-add-to-mode-line erc-track-position-in-mode-line)
- (setq erc-modified-channels-object (erc-modified-channels-object nil))
(erc-update-mode-line)
(if (featurep 'xemacs)
(defadvice switch-to-buffer (after erc-update (&rest args) activate)
(erc-modified-channels-update))
(add-hook 'window-configuration-change-hook
- 'erc-modified-channels-update))
+ 'erc-window-configuration-change))
(add-hook 'erc-insert-post-hook 'erc-track-modified-channels)
(add-hook 'erc-disconnected-hook 'erc-modified-channels-update))
;; enable the tracking keybindings
+ (add-hook 'erc-connect-pre-hook 'erc-track-minor-mode-maybe)
(erc-track-minor-mode-maybe)))
;; Disable:
((when (boundp 'erc-track-when-inactive)
(if (featurep 'xemacs)
(ad-disable-advice 'switch-to-buffer 'after 'erc-update)
(remove-hook 'window-configuration-change-hook
- 'erc-modified-channels-update))
+ 'erc-window-configuration-change))
(remove-hook 'erc-disconnected-hook 'erc-modified-channels-update)
(remove-hook 'erc-insert-post-hook 'erc-track-modified-channels))
;; disable the tracking keybindings
+ (remove-hook 'erc-connect-pre-hook 'erc-track-minor-mode-maybe)
(when erc-track-minor-mode
(erc-track-minor-mode -1)))))
;;; Tracking the channel modifications
+(defun erc-window-configuration-change ()
+ (unless (minibuffer-window-active-p (minibuffer-window))
+ ;; delay this until command has finished to make sure window is
+ ;; actually visible before clearing activity
+ (add-hook 'post-command-hook 'erc-modified-channels-update)))
+
(defvar erc-modified-channels-update-inside nil
"Variable to prevent running `erc-modified-channels-update' multiple
times. Without it, you cannot debug `erc-modified-channels-display',
(erc-modified-channels-remove-buffer buffer))))
erc-modified-channels-alist)
(when removed-channel
- (erc-modified-channels-display)
- (force-mode-line-update t)))))
+ (erc-modified-channels-display)
+ (force-mode-line-update t)))
+ (remove-hook 'post-command-hook 'erc-modified-channels-update)))
(defvar erc-track-mouse-face (if (featurep 'xemacs)
'modeline-mousable
(when (featurep 'xemacs)
(erc-modified-channels-object nil))
(setq erc-modified-channels-object
- (erc-modified-channels-object strings))))))
+ (erc-modified-channels-object strings))))))
(defun erc-modified-channels-remove-buffer (buffer)
"Remove BUFFER from `erc-modified-channels-alist'."
(defun erc-track-find-face (faces)
"Return the face to use in the modeline from the faces in FACES.
-If `erc-track-faces-priority-list' is set, the one from FACES who is
-first in that list will be used."
- (let ((candidates erc-track-faces-priority-list)
- candidate face)
- (while (and candidates (not face))
- (setq candidate (car candidates)
- candidates (cdr candidates))
- (when (memq candidate faces)
- (setq face candidate)))
- face))
+If `erc-track-faces-priority-list' is set, the one from FACES who
+is first in that list will be used. If nothing matches or if
+`erc-track-faces-priority-list' is not set, the default mode-line
+faces will be used.
+
+If `erc-track-faces-normal-list' is non-nil, use it to produce a
+blinking effect that indicates channel activity when the first
+element in FACES and the highest-ranking face among the rest of
+FACES are both members of `erc-track-faces-normal-list'.
+
+If one of the faces is a list, then it will be ranked according
+to its highest-tanking face member. A list of faces including
+that member will take priority over just the single member
+element."
+ (let ((choice (catch 'face
+ (dolist (candidate erc-track-faces-priority-list)
+ (when (member candidate faces)
+ (throw 'face candidate)))))
+ (no-first (and erc-track-faces-normal-list
+ (catch 'face
+ (dolist (candidate erc-track-faces-priority-list)
+ (when (member candidate (cdr faces))
+ (throw 'face candidate)))))))
+ (cond ((null choice)
+ nil)
+ ((and (member choice erc-track-faces-normal-list)
+ (member no-first erc-track-faces-normal-list))
+ no-first)
+ (t
+ choice))))
(defun erc-track-modified-channels ()
"Hook function for `erc-insert-post-hook' to check if the current
"Return a list of all faces used in STR."
(let ((i 0)
(m (length str))
- (faces (erc-list (get-text-property 0 'face str))))
+ (faces (erc-list (get-text-property 0 'face str)))
+ cur)
(while (and (setq i (next-single-property-change i 'face str m))
(not (= i m)))
- (dolist (face (erc-list (get-text-property i 'face str)))
- (add-to-list 'faces face)))
+ (when (setq cur (get-text-property i 'face str))
+ (add-to-list 'faces cur)))
faces))
-(erc-assert
+(assert
(let ((str "is bold"))
(put-text-property 3 (length str)
'face '(bold erc-current-nick-face)
(let ((count 0))
(catch 'done
(dolist (item erc-track-faces-priority-list)
- (if (eq item face)
+ (if (equal item face)
(throw 'done t)
(setq count (1+ count)))))
count))
((oldest leastactive)
(- (length erc-modified-channels-alist) arg))
(t (1- arg))))
- ;; normalise out of range user input
+ ;; normalize out of range user input
(cond ((>= offset (length erc-modified-channels-alist))
(setq offset (1- (length erc-modified-channels-alist))))
((< offset 0)
;; indent-tabs-mode: t
;; tab-width: 8
;; End:
-
-;; arch-tag: 11b439f5-e5d7-4c6c-bb3f-eda98f9b0ac1