aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/erc/erc-nicklist.el
diff options
context:
space:
mode:
authorAmin Bandali2020-09-09 23:20:34 -0400
committerAmin Bandali2020-09-10 00:19:37 -0400
commitdcab4d0f0c3e480846c4337ff231dc55eb26124f (patch)
tree93ce6abef96b136410391da1e0044b16aaf8e2e5 /lisp/erc/erc-nicklist.el
parent931b9f5953013c1e8844d0c723411b87ccfedb1a (diff)
downloademacs-scratch/erc-oldies.tar.gz
emacs-scratch/erc-oldies.zip
Import erc-bbdb.el, erc-chess.el, erc-nicklist.el, and erc-speak.elscratch/erc-oldies
* lisp/erc/erc-bbdb.el, lisp/erc/erc-chess.el, lisp/erc/erc-nicklist.el, lisp/erc/erc-speak.el: Import these files from commit 9497cc92bf1feb63c24425c46b1e033265c2cea9 of https://git.savannah.gnu.org/cgit/erc.git, the old ERC repository outside the GNU Emacs source tree. These FSF-copyrighted files were part of ERC before erc.git was (for the most part) folded into emacs.git, but they were left out largely due to depending on packages outside Emacs. It is worth noting that their dependencies are all free software, and bbdb and chess are actually available on GNU ELPA.
Diffstat (limited to 'lisp/erc/erc-nicklist.el')
-rw-r--r--lisp/erc/erc-nicklist.el417
1 files changed, 417 insertions, 0 deletions
diff --git a/lisp/erc/erc-nicklist.el b/lisp/erc/erc-nicklist.el
new file mode 100644
index 00000000000..cc913c5fe93
--- /dev/null
+++ b/lisp/erc/erc-nicklist.el
@@ -0,0 +1,417 @@
1;;; erc-nicklist.el --- Display channel nicknames in a side buffer.
2
3;; Copyright (C) 2004, 2005, 2006, 2007, 2008,
4;; 2009 Free Software Foundation, Inc.
5
6;; Filename: erc-nicklist.el
7;; Author: Lawrence Mitchell <wence@gmx.li>
8;; Created: 2004-04-30
9;; Keywords: IRC chat client Internet
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, or (at your option)
16;; 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; see the file COPYING. If not, write to the
25;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
26;; Boston, MA 02110-1301, USA.
27
28;;; Commentary:
29;;
30;; This provides a minimal mIRC style nicklist buffer for ERC. To
31;; activate, do M-x erc-nicklist RET in the channel buffer you want
32;; the nicklist to appear for. To close and quit the nicklist
33;; buffer, do M-x erc-nicklist-quit RET from within the nicklist buffer.
34;;
35;; TODO:
36;; o Somehow associate nicklist windows with channel windows so they
37;; appear together, and if one gets buried, then the other does.
38;;
39;; o Make "Query" and "Message" work.
40;;
41;; o Prettify the actual list of nicks in some way.
42;;
43;; o Add a proper erc-module that people can turn on and off, figure
44;; out a way of creating the nicklist window at an appropriate time
45;; --- probably in `erc-join-hook'.
46;;
47;; o Ensure XEmacs compatibility --- the mouse-menu support is likely
48;; broken.
49;;
50;; o Add option to display in a separate frame --- will again need to
51;; be able to associate the nicklist with the currently active
52;; channel buffer or something similar.
53;;
54;; o Allow toggling of visibility of nicklist via ERC commands.
55
56;;; History:
57;;
58
59;; Changes by Edgar Gonçalves <edgar.goncalves@inesc-id.pt>
60;; Jun 25 2005:
61;; - images are changed to a standard set of names.
62;; - /images now contain gaim's status icons.
63;; May 31 2005:
64;; - tooltips are improved. they try to access bbdb for a nice nick!
65;; Apr 26 2005:
66;; - erc-nicklist-channel-users-info was fixed (sorting bug)
67;; - Away names don't need parenthesis when using icons
68;; Apr 26 2005:
69;; - nicks can display icons of their connection type (msn, icq, for now)
70;; Mar 15 2005:
71;; - nicks now are different for unvoiced and op users
72;; - nicks now have tooltips displaying more info
73;; Mar 18 2005:
74;; - queries now work ok, both on menu and keyb shortcut RET.
75;; - nicklist is now sorted ignoring the case. Voiced nicks will
76;; appear according to `erc-nicklist-voiced-position'.
77
78;;; Code:
79
80(require 'erc)
81(condition-case nil
82 (require 'erc-bbdb)
83 (error nil))
84(eval-when-compile (require 'cl))
85
86(defgroup erc-nicklist nil
87 "Display a list of nicknames in a separate window."
88 :group 'erc)
89
90(defcustom erc-nicklist-use-icons t
91 "*If non-nil, display an icon instead of the name of the chat medium.
92By \"chat medium\", we mean IRC, AOL, MSN, ICQ, etc."
93 :group 'erc-nicklist
94 :type 'boolean)
95
96(defcustom erc-nicklist-icons-directory
97 (let ((dir (locate-library "erc-nicklist.el")))
98 (when dir
99 (concat (file-name-directory dir) "images/")))
100 "*Directory of the PNG files for chat icons.
101Icons are displayed if `erc-nicklist-use-icons' is non-nil."
102 :group 'erc-nicklist
103 :type 'directory)
104
105(defcustom erc-nicklist-voiced-position 'bottom
106 "*Position of voiced nicks in the nicklist.
107The value can be `top', `bottom' or nil (don't sort)."
108 :group 'erc-nicklist
109 :type '(choice
110 (const :tag "Top" top)
111 (const :tag "Bottom" bottom)
112 (const :tag "Mixed" nil)))
113
114(defcustom erc-nicklist-window-size 20.0
115 "*The size of the nicklist window.
116
117This specifies a percentage of the channel window width.
118
119A negative value means the nicklist window appears on the left of the
120channel window, and vice versa."
121 :group 'erc-nicklist
122 :type 'float)
123
124
125(defun erc-nicklist-buffer-name (&optional buffer)
126 "Return the buffer name for a nicklist associated with BUFFER.
127
128If BUFFER is nil, use the value of `current-buffer'."
129 (format " *%s-nicklist*" (buffer-name (or buffer (current-buffer)))))
130
131(defun erc-nicklist-make-window ()
132 "Create an ERC nicklist window.
133
134See also `erc-nicklist-window-size'."
135 (let ((width (floor (* (window-width) (/ erc-nicklist-window-size 100.0))))
136 (buffer (erc-nicklist-buffer-name))
137 window)
138 (split-window-horizontally (- width))
139 (setq window (next-window))
140 (set-window-buffer window (get-buffer-create buffer))
141 (with-current-buffer buffer
142 (set-window-dedicated-p window t))))
143
144
145(defvar erc-nicklist-images-alist '()
146 "Alist that maps a connection type to an icon.")
147
148(defun erc-nicklist-insert-medium-name-or-icon (host channel is-away)
149 "Inserts an icon or a string identifying the current host type.
150This is configured using `erc-nicklist-use-icons' and
151`erc-nicklist-icons-directory'."
152 ;; identify the network (for bitlebee usage):
153 (let ((bitlbee-p (save-match-data
154 (string-match "\\`&bitlbee\\b"
155 (buffer-name channel)))))
156 (cond ((and bitlbee-p
157 (string= "login.icq.com" host))
158 (if erc-nicklist-use-icons
159 (if is-away
160 (insert-image (cdr (assoc 'icq-away
161 erc-nicklist-images-alist)))
162 (insert-image (cdr (assoc 'icq
163 erc-nicklist-images-alist))))
164 (insert "ICQ")))
165 (bitlbee-p
166 (if erc-nicklist-use-icons
167 (if is-away
168 (insert-image (cdr (assoc 'msn-away
169 erc-nicklist-images-alist)))
170 (insert-image (cdr (assoc 'msn
171 erc-nicklist-images-alist))))
172 (insert "MSN")))
173 (t
174 (if erc-nicklist-use-icons
175 (if is-away
176 (insert-image (cdr (assoc 'irc-away
177 erc-nicklist-images-alist)))
178 (insert-image (cdr (assoc 'irc
179 erc-nicklist-images-alist))))
180 (insert "IRC"))))
181 (insert " ")))
182
183(defun erc-nicklist-search-for-nick (finger-host)
184 "Return the bitlbee-nick field for this contact given FINGER-HOST.
185Seach for the BBDB record of this contact. If not found, return nil."
186 (when (boundp 'erc-bbdb-bitlbee-name-field)
187 (let ((record (car
188 (erc-member-if
189 #'(lambda (r)
190 (let ((fingers (bbdb-record-finger-host r)))
191 (when fingers
192 (string-match finger-host
193 (car (bbdb-record-finger-host r))))))
194 (bbdb-records)))))
195 (when record
196 (bbdb-get-field record erc-bbdb-bitlbee-name-field)))))
197
198(defun erc-nicklist-insert-contents (channel)
199 "Insert the nicklist contents, with text properties and the optional images."
200 (setq buffer-read-only nil)
201 (erase-buffer)
202 (dolist (u (erc-nicklist-channel-users-info channel))
203 (let* ((server-user (car u))
204 (channel-user (cdr u))
205 (nick (erc-server-user-nickname server-user))
206 (host (erc-server-user-host server-user))
207 (login (erc-server-user-login server-user))
208 (full-name(erc-server-user-full-name server-user))
209 (info (erc-server-user-info server-user))
210 (channels (erc-server-user-buffers server-user))
211 (op (erc-channel-user-op channel-user))
212 (voice (erc-channel-user-voice channel-user))
213 (bbdb-nick (or (erc-nicklist-search-for-nick
214 (concat login "@" host))
215 ""))
216 (away-status (if voice "" "\n(Away)"))
217 (balloon-text (concat bbdb-nick (if (string= "" bbdb-nick)
218 "" "\n")
219 "Login: " login "@" host
220 away-status)))
221 (erc-nicklist-insert-medium-name-or-icon host channel (not voice))
222 (unless (or voice erc-nicklist-use-icons)
223 (setq nick (concat "(" nick ")")))
224 (when op
225 (setq nick (concat nick " (OP)")))
226 (insert (erc-propertize nick
227 'erc-nicklist-nick nick
228 'mouse-face 'highlight
229 'erc-nicklist-channel channel
230 'help-echo balloon-text)
231 "\n")))
232 (erc-nicklist-mode))
233
234
235(defun erc-nicklist ()
236 "Create an ERC nicklist buffer."
237 (interactive)
238 (let ((channel (current-buffer)))
239 (unless (or (not erc-nicklist-use-icons)
240 erc-nicklist-images-alist)
241 (setq erc-nicklist-images-alist
242 `((msn . ,(create-image (concat erc-nicklist-icons-directory
243 "msn-online.png")))
244 (msn-away . ,(create-image (concat erc-nicklist-icons-directory
245 "msn-offline.png")))
246 (irc . ,(create-image (concat erc-nicklist-icons-directory
247 "irc-online.png")))
248 (irc-away . ,(create-image (concat erc-nicklist-icons-directory
249 "irc-offline.png")))
250 (icq . ,(create-image (concat erc-nicklist-icons-directory
251 "icq-online.png")))
252 (icq-away . ,(create-image (concat erc-nicklist-icons-directory
253 "icq-offline.png"))))))
254 (erc-nicklist-make-window)
255 (with-current-buffer (get-buffer (erc-nicklist-buffer-name channel))
256 (erc-nicklist-insert-contents channel)))
257 (add-hook 'erc-channel-members-changed-hook #'erc-nicklist-update))
258
259(defun erc-nicklist-update ()
260 "Update the ERC nicklist buffer."
261 (let ((b (get-buffer (erc-nicklist-buffer-name)))
262 (channel (current-buffer)))
263 (when b
264 (with-current-buffer b
265 (erc-nicklist-insert-contents channel)))))
266
267(defvar erc-nicklist-mode-map
268 (let ((map (make-sparse-keymap)))
269 (define-key map (kbd "<down-mouse-3>") 'erc-nicklist-menu)
270 (define-key map "\C-j" 'erc-nicklist-kbd-menu)
271 (define-key map "q" 'erc-nicklist-quit)
272 (define-key map (kbd "RET") 'erc-nicklist-kbd-cmd-QUERY)
273 map)
274 "Keymap for `erc-nicklist-mode'.")
275
276(define-derived-mode erc-nicklist-mode fundamental-mode
277 "Nicklist"
278 "Major mode for the ERC nicklist buffer."
279 (setq buffer-read-only t))
280
281(defun erc-nicklist-call-erc-command (command point buffer window)
282 "Call an ERC COMMAND.
283
284Depending on what COMMAND is, it's called with one of POINT, BUFFER,
285or WINDOW as arguments."
286 (when command
287 (let* ((p (text-properties-at point))
288 (b (plist-get p 'erc-nicklist-channel)))
289 (if (memq command '(erc-nicklist-quit ignore))
290 (funcall command window)
291 ;; EEEK! Horrble, but it's the only way we can ensure the
292 ;; response goes to the correct buffer.
293 (erc-set-active-buffer b)
294 (switch-to-buffer-other-window b)
295 (funcall command (plist-get p 'erc-nicklist-nick))))))
296
297(defun erc-nicklist-cmd-QUERY (user &optional server)
298 "Opens a query buffer with USER."
299 ;; FIXME: find a way to switch to that buffer afterwards...
300 (let ((send (if server
301 (format "QUERY %s %s" user server)
302 (format "QUERY %s" user))))
303 (erc-cmd-QUERY user)
304 t))
305
306(defun erc-nicklist-kbd-cmd-QUERY (&optional window)
307 (interactive)
308 (let* ((p (text-properties-at (point)))
309 (server (plist-get p 'erc-nicklist-channel))
310 (nick (plist-get p 'erc-nicklist-nick))
311 (nick (or (and (string-match "(\\(.*\\))" nick)
312 (match-string 1 nick))
313 nick))
314 (nick (or (and (string-match "\\+\\(.*\\)" nick)
315 (match-string 1 nick))
316 nick))
317 (send (format "QUERY %s %s" nick server)))
318 (switch-to-buffer-other-window server)
319 (erc-cmd-QUERY nick)))
320
321
322(defvar erc-nicklist-menu
323 (let ((map (make-sparse-keymap "Action")))
324 (define-key map [erc-cmd-WHOIS]
325 '("Whois" . erc-cmd-WHOIS))
326 (define-key map [erc-cmd-DEOP]
327 '("Deop" . erc-cmd-DEOP))
328 (define-key map [erc-cmd-MSG]
329 '("Message" . erc-cmd-MSG)) ;; TODO!
330 (define-key map [erc-nicklist-cmd-QUERY]
331 '("Query" . erc-nicklist-kbd-cmd-QUERY))
332 (define-key map [ignore]
333 '("Cancel" . ignore))
334 (define-key map [erc-nicklist-quit]
335 '("Close nicklist" . erc-nicklist-quit))
336 map)
337 "Menu keymap for the ERC nicklist.")
338
339(defun erc-nicklist-quit (&optional window)
340 "Delete the ERC nicklist.
341
342Deletes WINDOW and stops updating the nicklist buffer."
343 (interactive)
344 (let ((b (window-buffer window)))
345 (with-current-buffer b
346 (set-buffer-modified-p nil)
347 (kill-this-buffer)
348 (remove-hook 'erc-channel-members-changed-hook 'erc-nicklist-update))))
349
350
351(defun erc-nicklist-kbd-menu ()
352 "Show the ERC nicklist menu."
353 (interactive)
354 (let* ((point (point))
355 (window (selected-window))
356 (buffer (current-buffer)))
357 (with-current-buffer buffer
358 (erc-nicklist-call-erc-command
359 (car (x-popup-menu point
360 erc-nicklist-menu))
361 point
362 buffer
363 window))))
364
365(defun erc-nicklist-menu (&optional arg)
366 "Show the ERC nicklist menu.
367
368ARG is a parametrized event (see `interactive')."
369 (interactive "e")
370 (let* ((point (nth 1 (cadr arg)))
371 (window (car (cadr arg)))
372 (buffer (window-buffer window)))
373 (with-current-buffer buffer
374 (erc-nicklist-call-erc-command
375 (car (x-popup-menu arg
376 erc-nicklist-menu))
377 point
378 buffer
379 window))))
380
381
382(defun erc-nicklist-channel-users-info (channel)
383 "Return a nick-sorted list of all users on CHANNEL.
384Result are elements in the form (SERVER-USER . CHANNEL-USER). The
385list has all the voiced users according to
386`erc-nicklist-voiced-position'."
387 (let* ((nicks (erc-sort-channel-users-alphabetically
388 (with-current-buffer channel (erc-get-channel-user-list)))))
389 (if erc-nicklist-voiced-position
390 (let ((voiced-nicks (erc-remove-if-not
391 #'(lambda (x)
392 (null (erc-channel-user-voice (cdr x))))
393 nicks))
394 (devoiced-nicks (erc-remove-if-not
395 #'(lambda (x)
396 (erc-channel-user-voice
397 (cdr x)))
398 nicks)))
399 (cond ((eq erc-nicklist-voiced-position 'top)
400 (append devoiced-nicks voiced-nicks))
401 ((eq erc-nicklist-voiced-position 'bottom)
402 (append voiced-nicks devoiced-nicks))))
403 nicks)))
404
405
406
407(provide 'erc-nicklist)
408
409;;; erc-nicklist.el ends here
410;;
411;; Local Variables:
412;; indent-tabs-mode: t
413;; tab-width: 8
414;; coding: utf-8
415;; End:
416
417;; arch-tag: db37a256-87a7-4544-bd90-e5f16c9f5ca5