1 ;;; liece-nick.el --- Various facility for nick operation.
2 ;; Copyright (C) 1998-2000 Daiki Ueno
4 ;; Author: Daiki Ueno <ueno@unixuser.org>
7 ;; Keywords: IRC, liece
9 ;; This file is part of Liece.
11 ;; This program is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
16 ;; This program is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING. If not, write to the
23 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 ;; Boston, MA 02111-1307, USA.
32 (require 'liece-hilit)
34 (defalias 'liece-nick-set-operator 'liece-channel-set-operator)
35 (defalias 'liece-nick-set-voice 'liece-channel-set-voice)
36 (defalias 'liece-nick-equal 'string-equal-ignore-case)
38 (defun liece-nick-member (nick nicks)
39 "Return non-nil if NICK is member of NICKS."
42 (and (stringp item) (liece-nick-equal nick item)))
45 (defvar liece-nick-insert-hook nil)
46 (defvar liece-nick-replace-hook nil)
48 (define-widget 'liece-nick-push-button 'push-button
50 :action 'liece-nick-popup-menu)
52 (defcustom liece-nick-sort-nicks nil
53 "If t, sort nick list in each time."
57 (defcustom liece-nick-sort-predicate 'string-lessp
58 "Function for sorting nick buffers."
62 ;;; @ internal access methods
64 (defmacro liece-nick-get-joined-channels (nick)
65 "Return channels as list NICK is joined."
66 `(get (intern ,nick liece-obarray) 'chnl))
68 (defmacro liece-nick-get-user-at-host (nick)
69 "Return user-at-host as string NICK is joined."
70 `(get (intern ,nick liece-obarray) 'user-at-host))
72 (defmacro liece-nick-set-user-at-host (nick uah)
73 "Set user at host as string NICK is joined."
74 `(put (intern ,nick liece-obarray) 'user-at-host ,uah))
76 (defmacro liece-nick-mark-as-apart (nick)
77 "Mark NICK is temporary apart."
78 `(put (intern ,nick liece-obarray) 'part t))
80 (defmacro liece-nick-unmark-as-apart (nick)
81 "Mark NICK is temporary apart."
82 `(put (intern ,nick liece-obarray) 'part nil))
84 (defmacro liece-nick-get-modes (nick)
85 "Return modes as string NICK is joined."
86 `(get (intern ,nick liece-obarray) 'mode))
88 (defmacro liece-nick-add-mode (mode &optional nick)
89 "Add MODE as char to NICK."
90 `(let* ((n (intern ,nick liece-obarray))
91 (modes (string-to-char-list (or (get n 'mode) ""))))
92 (put n 'mode (mapconcat #'char-to-string
93 (or (memq ,mode modes)
94 (cons ,mode modes)) ""))))
96 (defmacro liece-nick-remove-mode (mode &optional nick)
97 "Remove MODE as char to NICK."
98 `(let* ((n (intern ,nick liece-obarray))
99 (modes (string-to-char-list (or (get n 'mode) ""))))
101 (put n 'mode (mapconcat #'char-to-string modes ""))))
103 (defmacro liece-nick-set-mode (val mode &optional nick)
104 "Set MODE as char to CHNL."
106 (liece-nick-add-mode ,mode ,nick)
107 (liece-nick-remove-mode ,mode ,nick)))
109 (defmacro liece-nick-strip (nick)
110 `(if (and ,nick (memq (aref ,nick 0) '(?@ ?+ ? )))
114 (defmacro liece-nick-normalize (nick)
115 `(if (and ,nick (memq (aref ,nick 0) '(?@ ?+ ? )))
121 (defun liece-nick-insert (nick)
122 ;; Find sorted position
124 ((and (eq liece-nick-sort-nicks t)
125 (liece-functionp liece-nick-sort-predicate))
127 (goto-char (point-min))
128 (while (and (not (eobp)) (not found))
129 (if (condition-case nil
130 (funcall liece-nick-sort-predicate
131 (liece-nick-strip nick)
132 (widget-value (widget-at (1+ (point)))))
135 (beginning-of-line 2)))))
136 ((eq liece-nick-sort-nicks 'reverse)
137 (goto-char (point-min)))
138 (t (goto-char (point-max))))
140 (insert (substring nick 0 1))
141 (let ((st (point)) (nick (liece-nick-strip nick)))
143 (when liece-highlight-mode
144 (liece-widget-convert-button
145 'liece-nick-push-button st (point) nick))
147 (run-hook-with-args 'liece-nick-insert-hook st (point))))
149 (defun liece-nick-replace (old new &optional limit regexp)
151 (setq old (concat "^\\(" old "\\)$"))
152 (setq old (concat "^\\([ @+]\\)\\(" (regexp-quote old) "\\)$")))
153 (let (case-fold-search beg end)
154 (when (re-search-forward old limit t)
156 (setq new (concat (match-string 1) new)))
157 (if (and (eq liece-nick-sort-nicks t)
158 (liece-functionp liece-nick-sort-predicate))
160 (delete-region (match-beginning 0)
161 (progn (goto-char (match-end 0))
162 (forward-char) (point)))
163 (liece-nick-insert new))
165 (widget-delete (widget-at (1+ (point))))
167 (replace-match new t t)
169 beg (progn (beginning-of-line) (1+ (point))))
170 (when liece-highlight-mode
171 (liece-widget-convert-button
172 'liece-nick-push-button beg end (substring new 1)))
173 (run-hook-with-args 'liece-nick-replace-hook beg end)))))
176 (defun liece-command-toggle-nick-buffer-mode ()
178 (when (and (eq liece-command-buffer-mode 'channel)
179 (get-buffer liece-nick-buffer))
180 (setq liece-nick-buffer-mode (not liece-nick-buffer-mode)))
181 (liece-configure-windows))
183 (defmacro liece-nick-buffer-create (chnl)
184 `(with-current-buffer
185 (liece-get-buffer-create (format liece-nick-buffer-format ,chnl))
186 (unless (eq major-mode 'liece-nick-mode)
188 (set-alist 'liece-nick-buffer-alist ,chnl (current-buffer))
191 (defun liece-change-nick-of-1 (old new nicks)
193 (do ((nicks nicks (cdr nicks)))
195 (if (liece-nick-equal (caar nicks) old)
196 (setcar (car nicks) new))))
199 `(lambda (nick) (liece-nick-equal (car nick) ,old))
202 (defun liece-change-nick-of-2 (old new nicks)
204 (do ((nicks nicks (cdr nicks)))
206 (if (liece-nick-equal (car nicks) old)
207 (setcar nicks new))))
210 `(lambda (nick) (liece-nick-equal nick ,old))
213 (defun liece-change-nick-of (old new)
214 (liece-change-nick-of-1 old new liece-nick-alist)
215 (let ((chnls (liece-nick-get-joined-channels old)))
217 (liece-change-nick-of-2 old new (liece-channel-get-nicks chnl))
218 (liece-change-nick-of-2 old new (liece-channel-get-operators chnl))
219 (liece-change-nick-of-2 old new (liece-channel-get-voices chnl)))))
221 (defmacro liece-nick-join-1 (user chnl)
222 "Add CHNL to list of channels USER belongs to."
223 `(let* ((flag (string-to-char user))
224 (user (liece-nick-strip ,user))
225 (u (intern user liece-obarray))
226 (c (intern ,chnl liece-obarray)))
227 (or (string-assoc-ignore-case user liece-nick-alist)
228 (push (list user) liece-nick-alist))
230 ((char-equal flag ?@)
231 (liece-channel-set-operator ,chnl user t))
232 ((char-equal flag ?+)
233 (liece-channel-set-voice ,chnl user t)))
234 (or (string-list-member-ignore-case ,chnl (get u 'chnl))
235 (put u 'chnl (cons ,chnl (get u 'chnl))))
236 (or (string-list-member-ignore-case user (get c 'nick))
237 (put c 'nick (cons user (get c 'nick))))))
239 (defmacro liece-nick-part-1 (user chnl)
240 "Remove USER information from his CHNL."
241 `(let ((u (intern ,user liece-obarray))
242 (c (intern ,chnl liece-obarray)))
243 (liece-channel-set-operator ,chnl ,user nil)
244 (liece-channel-set-voice ,chnl ,user nil)
245 (put u 'chnl (string-list-remove-ignore-case ,chnl (get u 'chnl)))
246 (put c 'nick (string-list-remove-ignore-case ,user (get c 'nick)))))
249 (defun liece-nick-join (user chnl)
250 (liece-nick-join-1 user chnl)
251 (let ((nbuf (cdr (string-assoc-ignore-case chnl liece-nick-buffer-alist))))
252 (with-current-buffer nbuf
253 (let (buffer-read-only)
254 (liece-nick-insert (liece-nick-normalize user))))))
257 (defun liece-nick-part (user chnl)
258 (let ((nbuf (cdr (string-assoc-ignore-case chnl liece-nick-buffer-alist))))
259 (setq user (liece-nick-strip user))
260 (with-current-buffer nbuf
261 (let ((case-fold-search t) buffer-read-only)
262 (goto-char (point-min))
263 (when (re-search-forward (concat "^." (regexp-quote user) "$") nil t)
264 (delete-region (match-beginning 0)
265 (progn (goto-char (match-end 0))
266 (forward-char) (point)))
267 (liece-nick-part-1 user chnl))))))
270 (defun liece-nick-change (old new)
271 (let* ((old (liece-nick-strip old)) (new (liece-nick-strip new))
272 (chnls (get (intern old liece-obarray) 'chnl)) chnl nbuf)
273 (liece-change-nick-of old new)
275 (put (intern new liece-obarray) 'chnl chnls))
276 (unintern old liece-obarray)
279 (liece-nick-part old chnl)
280 (setq nbuf (cdr (string-assoc-ignore-case
281 chnl liece-nick-buffer-alist)))
282 (with-current-buffer nbuf
283 (let (buffer-read-only)
284 (goto-char (point-min))
285 (liece-nick-replace old new)))))))
288 (defun liece-nick-update (chnl users)
289 (let ((c (intern chnl liece-obarray))
290 (nbuf (cdr (string-assoc-ignore-case chnl liece-nick-buffer-alist))))
291 (mapcar (lambda (prop) (put c prop nil)) '(nick oper voice))
292 (with-current-buffer nbuf
293 (let (buffer-read-only)
294 (liece-kill-all-overlays)
296 (when (and liece-nick-sort-nicks
297 (liece-functionp liece-nick-sort-predicate))
298 (setq users (sort users
300 (funcall liece-nick-sort-predicate
301 (liece-nick-strip s1)
302 (liece-nick-strip s2))))))
303 (let (liece-nick-sort-predicate)
305 (liece-nick-join user chnl)))))
307 (defvar liece-nick-region-nicks nil)
308 (defvar liece-nick-region-opers nil)
309 (defvar liece-nick-region-voices nil)
312 (defun liece-nick-update-region ()
313 (setq liece-nick-region-nicks nil
314 liece-nick-region-opers nil
315 liece-nick-region-voices nil)
318 (if (not (region-active-p))
319 (setq region (cons (line-beginning-position)
320 (line-beginning-position 2)))
321 (setq region (cons (region-beginning) (region-end)))
322 (goto-char (car region))
323 (setcar region (line-beginning-position))
324 (goto-char (cdr region))
326 (setcdr region (line-beginning-position))
327 (setcdr region (line-beginning-position 2))))
329 (narrow-to-region (car region) (cdr region))
330 (goto-char (point-min))
332 (setq nick (widget-value (widget-at (1+ (point)))))
333 (push nick liece-nick-region-nicks)
334 (if (memq (char-after) '(?@ ?+))
335 (push nick liece-nick-region-voices))
336 (if (eq ?@ (char-after))
337 (push nick liece-nick-region-opers))
338 (beginning-of-line 2))))))
340 (defun liece-nick-add-buttons (start end)
343 (while (re-search-forward
345 (concat "^\\(" liece-time-prefix-regexp "\\)?"
346 "[][=<>(][][=<>(]?\\([^:]*:\\)?\\([^][=<>(]+\\)"))
348 (let* ((nick-start (match-beginning 3))
349 (nick-end (match-end 3))
350 (nick (buffer-substring nick-start nick-end)))
351 (when liece-highlight-mode
352 (liece-widget-convert-button
353 'liece-nick-push-button nick-start nick-end nick))))))
356 (defun liece-nick-redisplay-buffer (chnl)
358 (cdr (string-assoc-ignore-case
359 chnl liece-nick-buffer-alist)))
360 (window (liece-get-buffer-window liece-nick-buffer)))
362 (with-current-buffer buffer
363 (set-window-buffer window buffer)
364 (unless (liece-frozen buffer)
365 (set-window-start window (point-min)))
366 (setq liece-nick-buffer buffer)))))
368 (provide 'liece-nick)
370 ;;; liece-nick.el ends here