+++ /dev/null
-;;; erc-nicklist.el --- Display channel nicknames in a side buffer.
-
-;; Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
-
-;; Filename: erc-nicklist.el
-;; Author: Lawrence Mitchell <wence@gmx.li>
-;; Created: 2004-04-30
-;; Keywords: IRC chat client Internet
-
-;; This file is part of GNU Emacs.
-
-;; 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.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; 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.
-
-;;; Commentary:
-;;
-;; This provides a minimal mIRC style nicklist buffer for ERC. To
-;; activate, do M-x erc-nicklist RET in the channel buffer you want
-;; the nicklist to appear for. To close and quit the nicklist
-;; buffer, do M-x erc-nicklist-quit RET from within the nicklist buffer.
-;;
-;; TODO:
-;; o Somehow associate nicklist windows with channel windows so they
-;; appear together, and if one gets buried, then the other does.
-;;
-;; o Make "Query" and "Message" work.
-;;
-;; o Prettify the actual list of nicks in some way.
-;;
-;; o Add a proper erc-module that people can turn on and off, figure
-;; out a way of creating the nicklist window at an appropriate time
-;; --- probably in `erc-join-hook'.
-;;
-;; o Ensure XEmacs compatibility --- the mouse-menu support is likely
-;; broken.
-;;
-;; o Add option to display in a separate frame --- will again need to
-;; be able to associate the nicklist with the currently active
-;; channel buffer or something similar.
-;;
-;; o Allow toggling of visibility of nicklist via ERC commands.
-
-;;; History:
-;;
-
-;; Changes by Edgar Gonçalves <edgar.goncalves@inesc-id.pt>
-;; Jun 25 2005:
-;; - images are changed to a standard set of names.
-;; - /images now contain gaim's status icons.
-;; May 31 2005:
-;; - tooltips are improved. they try to access bbdb for a nice nick!
-;; Apr 26 2005:
-;; - erc-nicklist-channel-users-info was fixed (sorting bug)
-;; - Away names don't need parenthesis when using icons
-;; Apr 26 2005:
-;; - nicks can display icons of their connection type (msn, icq, for now)
-;; Mar 15 2005:
-;; - nicks now are different for unvoiced and op users
-;; - nicks now have tooltips displaying more info
-;; Mar 18 2005:
-;; - queries now work ok, both on menu and keyb shortcut RET.
-;; - nicklist is now sorted ignoring the case. Voiced nicks will
-;; appear according to `erc-nicklist-voiced-position'.
-
-;;; Code:
-
-(require 'erc)
-(condition-case nil
- (require 'erc-bbdb)
- (error nil))
-(eval-when-compile (require 'cl))
-
-(defgroup erc-nicklist nil
- "Display a list of nicknames in a separate window."
- :group 'erc)
-
-(defcustom erc-nicklist-use-icons t
- "*If non-nil, display an icon instead of the name of the chat medium.
-By \"chat medium\", we mean IRC, AOL, MSN, ICQ, etc."
- :group 'erc-nicklist
- :type 'boolean)
-
-(defcustom erc-nicklist-icons-directory
- (concat default-directory "images/")
- "*Directory of the PNG files for chat icons.
-Icons are displayed if `erc-nicklist-use-icons' is non-nil."
- :group 'erc-nicklist
- :type 'directory)
-
-(defcustom erc-nicklist-voiced-position 'bottom
- "*Position of voiced nicks in the nicklist.
-The value can be `top', `bottom' or nil (don't sort)."
- :group 'erc-nicklist
- :type '(choice
- (const :tag "Top" 'top)
- (const :tag "Bottom" 'bottom)
- (const :tag "Mixed" nil)))
-
-(defcustom erc-nicklist-window-size 20.0
- "*The size of the nicklist window.
-
-This specifies a percentage of the channel window width.
-
-A negative value means the nicklist window appears on the left of the
-channel window, and vice versa."
- :group 'erc-nicklist
- :type 'float)
-
-
-(defun erc-nicklist-buffer-name (&optional buffer)
- "Return the buffer name for a nicklist associated with BUFFER.
-
-If BUFFER is nil, use the value of `current-buffer'."
- (format " *%s-nicklist*" (buffer-name (or buffer (current-buffer)))))
-
-(defun erc-nicklist-make-window ()
- "Create an ERC nicklist window.
-
-See also `erc-nicklist-window-size'."
- (let ((width (floor (* (window-width) (/ erc-nicklist-window-size 100.0))))
- (buffer (erc-nicklist-buffer-name))
- window)
- (split-window-horizontally (- width))
- (setq window (next-window))
- (set-window-buffer window (get-buffer-create buffer))
- (with-current-buffer buffer
- (set-window-dedicated-p window t))))
-
-
-(defvar erc-nicklist-images-alist '()
- "Alist that maps a connection type to an icon.")
-
-(defun erc-nicklist-insert-medium-name-or-icon (host channel is-away)
- "Inserts an icon or a string identifying the current host type.
-This is configured using `erc-nicklist-use-icons' and
-`erc-nicklist-icons-directory'."
- ;; identify the network (for bitlebee usage):
- (let ((bitlbee-p (save-match-data
- (string-match "\\`&bitlbee\\b"
- (buffer-name channel)))))
- (cond ((and bitlbee-p
- (string= "login.icq.com" host))
- (if erc-nicklist-use-icons
- (if is-away
- (insert-image (cdr (assoc 'icq-away
- erc-nicklist-images-alist)))
- (insert-image (cdr (assoc 'icq
- erc-nicklist-images-alist))))
- (insert "ICQ")))
- (bitlbee-p
- (if erc-nicklist-use-icons
- (if is-away
- (insert-image (cdr (assoc 'msn-away
- erc-nicklist-images-alist)))
- (insert-image (cdr (assoc 'msn
- erc-nicklist-images-alist))))
- (insert "MSN")))
- (t
- (if erc-nicklist-use-icons
- (if is-away
- (insert-image (cdr (assoc 'irc-away
- erc-nicklist-images-alist)))
- (insert-image (cdr (assoc 'irc
- erc-nicklist-images-alist))))
- (insert "IRC"))))
- (insert " ")))
-
-(defun erc-nicklist-search-for-nick (finger-host)
- "Return the bitlbee-nick field for this contact given FINGER-HOST.
-Seach for the BBDB record of this contact. If not found, return nil."
- (when (boundp 'erc-bbdb-bitlbee-name-field)
- (let ((record (car
- (erc-member-if
- #'(lambda (r)
- (let ((fingers (bbdb-record-finger-host r)))
- (when fingers
- (string-match finger-host
- (car (bbdb-record-finger-host r))))))
- (bbdb-records)))))
- (when record
- (bbdb-get-field record erc-bbdb-bitlbee-name-field)))))
-
-(defun erc-nicklist-insert-contents (channel)
- "Insert the nicklist contents, with text properties and the optional images."
- (setq buffer-read-only nil)
- (erase-buffer)
- (dolist (u (erc-nicklist-channel-users-info channel))
- (let* ((server-user (car u))
- (channel-user (cdr u))
- (nick (erc-server-user-nickname server-user))
- (host (erc-server-user-host server-user))
- (login (erc-server-user-login server-user))
- (full-name(erc-server-user-full-name server-user))
- (info (erc-server-user-info server-user))
- (channels (erc-server-user-buffers server-user))
- (op (erc-channel-user-op channel-user))
- (voice (erc-channel-user-voice channel-user))
- (bbdb-nick (or (erc-nicklist-search-for-nick
- (concat login "@" host))
- ""))
- (away-status (if voice "" "\n(Away)"))
- (balloon-text (concat bbdb-nick (if (string= "" bbdb-nick)
- "" "\n")
- "Login: " login "@" host
- away-status)))
- (erc-nicklist-insert-medium-name-or-icon host channel (not voice))
- (unless (or voice erc-nicklist-use-icons)
- (setq nick (concat "(" nick ")")))
- (when op
- (setq nick (concat nick " (OP)")))
- (insert (erc-propertize nick
- 'erc-nicklist-nick nick
- 'mouse-face 'highlight
- 'erc-nicklist-channel channel
- 'help-echo balloon-text)
- "\n")))
- (erc-nicklist-mode))
-
-
-(defun erc-nicklist ()
- "Create an ERC nicklist buffer."
- (interactive)
- (let ((channel (current-buffer)))
- (unless (or (not erc-nicklist-use-icons)
- erc-nicklist-images-alist)
- (setq erc-nicklist-images-alist
- `((msn . ,(create-image (concat erc-nicklist-icons-directory
- "msn-online.png")))
- (msn-away . ,(create-image (concat erc-nicklist-icons-directory
- "msn-offline.png")))
- (irc . ,(create-image (concat erc-nicklist-icons-directory
- "irc-online.png")))
- (irc-away . ,(create-image (concat erc-nicklist-icons-directory
- "irc-offline.png")))
- (icq . ,(create-image (concat erc-nicklist-icons-directory
- "icq-online.png")))
- (icq-away . ,(create-image (concat erc-nicklist-icons-directory
- "icq-offline.png"))))))
- (erc-nicklist-make-window)
- (with-current-buffer (get-buffer (erc-nicklist-buffer-name channel))
- (erc-nicklist-insert-contents channel)))
- (add-hook 'erc-channel-members-changed-hook #'erc-nicklist-update))
-
-(defun erc-nicklist-update ()
- "Update the ERC nicklist buffer."
- (let ((b (get-buffer (erc-nicklist-buffer-name)))
- (channel (current-buffer)))
- (when b
- (with-current-buffer b
- (erc-nicklist-insert-contents channel)))))
-
-(defvar erc-nicklist-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map (kbd "<down-mouse-3>") 'erc-nicklist-menu)
- (define-key map "\C-j" 'erc-nicklist-kbd-menu)
- (define-key map "q" 'erc-nicklist-quit)
- (define-key map (kbd "RET") 'erc-nicklist-kbd-cmd-QUERY)
- map)
- "Keymap for `erc-nicklist-mode'.")
-
-(define-derived-mode erc-nicklist-mode fundamental-mode
- "Nicklist"
- "Major mode for the ERC nicklist buffer."
- (setq buffer-read-only t))
-
-(defun erc-nicklist-call-erc-command (command point buffer window)
- "Call an ERC COMMAND.
-
-Depending on what COMMAND is, it's called with one of POINT, BUFFER,
-or WINDOW as arguments."
- (when command
- (let* ((p (text-properties-at point))
- (b (plist-get p 'erc-nicklist-channel)))
- (if (memq command '(erc-nicklist-quit ignore))
- (funcall command window)
- ;; EEEK! Horrble, but it's the only way we can ensure the
- ;; response goes to the correct buffer.
- (erc-set-active-buffer b)
- (switch-to-buffer-other-window b)
- (funcall command (plist-get p 'erc-nicklist-nick))))))
-
-(defun erc-nicklist-cmd-QUERY (user &optional server)
- "Opens a query buffer with USER."
- ;; FIXME: find a way to switch to that buffer afterwards...
- (let ((send (if server
- (format "QUERY %s %s" user server)
- (format "QUERY %s" user))))
- (erc-cmd-QUERY user)
- t))
-
-(defun erc-nicklist-kbd-cmd-QUERY (&optional window)
- (interactive)
- (let* ((p (text-properties-at (point)))
- (server (plist-get p 'erc-nicklist-channel))
- (nick (plist-get p 'erc-nicklist-nick))
- (nick (or (and (string-match "(\\(.*\\))" nick)
- (match-string 1 nick))
- nick))
- (nick (or (and (string-match "\\+\\(.*\\)" nick)
- (match-string 1 nick))
- nick))
- (send (format "QUERY %s %s" nick server)))
- (switch-to-buffer-other-window server)
- (erc-cmd-QUERY nick)))
-
-
-(defvar erc-nicklist-menu
- (let ((map (make-sparse-keymap "Action")))
- (define-key map [erc-cmd-WHOIS]
- '("Whois" . erc-cmd-WHOIS))
- (define-key map [erc-cmd-DEOP]
- '("Deop" . erc-cmd-DEOP))
- (define-key map [erc-cmd-MSG]
- '("Message" . erc-cmd-MSG)) ;; TODO!
- (define-key map [erc-nicklist-cmd-QUERY]
- '("Query" . erc-nicklist-kbd-cmd-QUERY))
- (define-key map [ignore]
- '("Cancel" . ignore))
- (define-key map [erc-nicklist-quit]
- '("Close nicklist" . erc-nicklist-quit))
- map)
- "Menu keymap for the ERC nicklist.")
-
-(defun erc-nicklist-quit (&optional window)
- "Delete the ERC nicklist.
-
-Deletes WINDOW and stops updating the nicklist buffer."
- (interactive)
- (let ((b (window-buffer window)))
- (with-current-buffer b
- (set-buffer-modified-p nil)
- (kill-this-buffer)
- (remove-hook 'erc-channel-members-changed-hook 'erc-nicklist-update))))
-
-
-(defun erc-nicklist-kbd-menu ()
- "Show the ERC nicklist menu."
- (interactive)
- (let* ((point (point))
- (window (selected-window))
- (buffer (current-buffer)))
- (with-current-buffer buffer
- (erc-nicklist-call-erc-command
- (car (x-popup-menu point
- erc-nicklist-menu))
- point
- buffer
- window))))
-
-(defun erc-nicklist-menu (&optional arg)
- "Show the ERC nicklist menu.
-
-ARG is a parametrized event (see `interactive')."
- (interactive "e")
- (let* ((point (nth 1 (cadr arg)))
- (window (car (cadr arg)))
- (buffer (window-buffer window)))
- (with-current-buffer buffer
- (erc-nicklist-call-erc-command
- (car (x-popup-menu arg
- erc-nicklist-menu))
- point
- buffer
- window))))
-
-
-(defun erc-nicklist-channel-users-info (channel)
- "Return a nick-sorted list of all users on CHANNEL.
-Result are elements in the form (SERVER-USER . CHANNEL-USER). The
-list has all the voiced users according to
-`erc-nicklist-voiced-position'."
- (let* ((nicks (erc-sort-channel-users-alphabetically
- (with-current-buffer channel (erc-get-channel-user-list)))))
- (if erc-nicklist-voiced-position
- (let ((voiced-nicks (erc-remove-if-not
- #'(lambda (x)
- (null (erc-channel-user-voice (cdr x))))
- nicks))
- (devoiced-nicks (erc-remove-if-not
- #'(lambda (x)
- (erc-channel-user-voice
- (cdr x)))
- nicks)))
- (cond ((eq erc-nicklist-voiced-position 'top)
- (append devoiced-nicks voiced-nicks))
- ((eq erc-nicklist-voiced-position 'bottom)
- (append voiced-nicks devoiced-nicks))))
- nicks)))
-
-
-
-(provide 'erc-nicklist)
-
-;;; erc-nicklist.el ends here
-;;
-;; Local Variables:
-;; indent-tabs-mode: t
-;; tab-width: 8
-;; coding: utf-8
-;; End:
-
-;; arch-tag: db37a256-87a7-4544-bd90-e5f16c9f5ca5