1 ;;; liece-commands.el --- Interactive commands in command buffer.
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.
33 (require 'liece-crypt)
34 (require 'liece-misc))
36 (require 'liece-channel)
38 (require 'liece-coding)
40 (require 'liece-minibuf)
42 (autoload 'liece-dcc-chat-send "liece-dcc")
43 (autoload 'liece-window-configuration-pop "liece-window")
45 (autoload 'liece-command-ctcp-version "liece-ctcp" nil t)
46 (autoload 'liece-command-ctcp-userinfo "liece-ctcp" nil t)
47 (autoload 'liece-command-ctcp-clientinfo "liece-ctcp" nil t)
48 (autoload 'liece-command-ctcp-ping "liece-ctcp" nil t)
49 (autoload 'liece-command-ctcp-time "liece-ctcp" nil t)
50 (autoload 'liece-command-ctcp-x-face "liece-ctcp" nil t)
51 (autoload 'liece-command-ctcp-comment "liece-ctcp" nil t)
52 (autoload 'liece-command-ctcp-help "liece-ctcp" nil t)
54 (defun liece-command-poll-names ()
55 "Handler for polling NAMES."
56 (when (liece-server-opened)
59 (length liece-channel-alist)))
60 (dolist (chnl liece-channel-alist)
61 (liece-send "NAMES %s" (car chnl)))))
63 (defun liece-command-poll-friends ()
64 "Handler for polling ISON."
67 (liece-send "ISON %s" (mapconcat 'identity liece-friends " "))))
69 (defun liece-command-find-timestamp ()
70 "Find recent timestamp in dialogue buffer."
74 (regexp (concat "^\\(" liece-time-prefix-regexp "\\)?"
75 (regexp-quote liece-timestamp-prefix))))
76 (unless (eq 'liece-dialogue-mode (derived-mode-class major-mode))
77 (set-buffer liece-dialogue-buffer)
78 (goto-char (point-max)))
79 (if (re-search-backward regexp (point-min) t)
80 (setq range (concat (buffer-substring (match-end 0)
83 (if (re-search-forward regexp (point-max) t)
84 (setq range (concat range (buffer-substring (match-end 0)
85 (line-end-position)))))
86 (liece-message range))))
88 (defun liece-command-keepalive ()
89 "Handler for polling server connection."
90 (if (not (liece-server-opened))
92 (liece-ping-if-idle)))
94 (defvar liece-last-timestamp-time nil "Last time timestamp was inserted.")
95 (defvar liece-last-timestamp-no-cons-p nil "Last timestamp was no-cons.")
97 (defun liece-command-timestamp-if-interval-expired (&optional no-cons)
98 "If interval timer has expired, insert timestamp into dialogue buffer.
99 And save variables into `liece-variable-file' if there are variables to save.
100 Optional argument NO-CONS specifies timestamp format is cons cell."
102 (when (and (not (and no-cons
103 liece-last-timestamp-no-cons-p))
104 (numberp liece-timestamp-interval)
105 (> liece-timestamp-interval 0)
106 (or (null liece-last-timestamp-time)
107 (> (liece-time-difference liece-last-timestamp-time
109 liece-timestamp-interval)))
110 (if liece-save-variables-are-dirty
111 (liece-command-save-vars))
112 (liece-command-timestamp)
113 (setq liece-last-timestamp-no-cons-p no-cons)))
115 (defun liece-command-timestamp ()
116 "Insert timestamp into dialogue buffer."
118 (let ((stamp (format liece-timestamp-format
119 (funcall liece-format-time-function (current-time))))
120 (liece-timestamp-interval 0))
121 (liece-insert liece-D-buffer (concat stamp "\n"))
122 (setq liece-last-timestamp-time (current-time))))
124 (defun liece-command-point-back-to-command-buffer ()
125 "Set point back to command buffer."
127 (let ((win (liece-get-buffer-window liece-command-buffer)))
128 (if win (select-window win))))
130 (defun liece-command-send-message
131 (message &optional arg key)
132 "Send MESSAGE to current chat partner of current channel.
133 If argument ARG is non-nil message will be encrypted with KEY."
135 (setq liece-crypt-mode-active (not liece-crypt-mode-active)))
136 (if (string-equal message "")
137 (progn (liece-message (_ "No text to send")) nil)
138 (let ((addr (if (eq liece-command-buffer-mode 'chat)
139 liece-current-chat-partner
140 liece-current-channel))
141 repr method name target
143 (with-liece-encryption (msg addr arg key)
145 ((eq liece-command-buffer-mode 'chat)
146 (if (null liece-current-chat-partner)
148 (substitute-command-keys
149 "Type \\[liece-command-join] to start private conversation"))
150 (setq repr (liece-channel-parse-representation
151 liece-current-chat-partner)
154 target (aref repr 2))
155 (cond ((eq method 'dcc)
156 (liece-dcc-chat-send target msg))
158 (liece-send "PRIVMSG %s :%s"
159 liece-current-chat-partner msg)))
160 (liece-own-private-message message)))
161 ((not liece-current-channel)
163 (message (substitute-command-keys
164 "Type \\[liece-command-join] to join a channel")))
168 (liece-channel-real liece-current-channel) msg)
169 (liece-own-channel-message message))))
172 (defun liece-enter-message (&optional arg key)
173 "Enter the current line as an entry in the IRC dialogue.
174 If argument ARG is non-nil message will be encrypted with KEY."
176 (if (liece-command-send-message
177 (buffer-substring (point)(progn (end-of-line) (point)))
179 (liece-next-line 1)))
181 (defun liece-command-enter-message (&optional arg key)
182 "Enter the current line as an entry in the IRC dialogue.
183 If the prefix argument ARG is non-nil, message will be encrypted with KEY."
185 (let ((completion-ignore-case t))
186 (and (if current-prefix-arg
187 (not liece-crypt-mode-active)
188 liece-crypt-mode-active)
192 (_ "Encrypt message with key [RET for none]: ")
194 liece-crypt-encryption-keys))))))
195 (liece-enter-message arg (if (string-equal key "") nil key)))
197 (defun liece-dialogue-enter-message ()
198 "Ask for a line as an entry in the IRC dialogue on the current channel."
201 (while (not (string-equal (setq message (read-string "> ")) ""))
202 (liece-command-send-message message))))
204 (defun liece-command-inline ()
205 "Send current line as a message to the IRC server."
208 (liece-send (buffer-substring (point)(progn (end-of-line) (point))))
211 (defun liece-command-join-channel (join-channel-var key)
212 "Join a JOIN-CHANNEL-VAR with KEY."
213 (let ((nicks liece-nick-alist) nick)
217 (liece-channel-equal join-channel-var (car nick)))))
218 (setq nick (pop nicks)))
220 (setq join-channel-var
221 (or (car (get (intern (car nick) liece-obarray) 'chnl))
223 (if (liece-channel-member join-channel-var liece-current-channels)
225 (setq liece-current-channel join-channel-var)
226 (liece-switch-to-channel liece-current-channel)
227 (liece-channel-change))
228 (liece-send "JOIN %s %s" (liece-channel-real join-channel-var) key))))
230 (defun liece-command-join-partner (join-channel-var)
231 "Join a JOIN-CHANNEL-VAR."
232 (if (liece-channel-member join-channel-var liece-current-chat-partners)
234 (setq liece-current-chat-partner join-channel-var)
235 (liece-switch-to-channel liece-current-chat-partner))
236 (setq liece-current-chat-partner join-channel-var)
237 (liece-channel-join liece-current-chat-partner))
238 (liece-channel-change))
240 (defun liece-command-join (join-channel-var &optional key)
241 "Join a JOIN-CHANNEL-VAR with KEY.
242 If user nickname is given join the same set of channels as the specified user.
243 If command-buffer is in chat-mode, start private conversation
244 with specified user."
246 (let (join-channel-var key (completion-ignore-case t))
247 (setq join-channel-var
248 (if (numberp current-prefix-arg)
250 (liece-channel-virtual
251 (if (eq liece-command-buffer-mode 'chat)
252 (liece-minibuffer-completing-default-read
253 (_ "Start private conversation with: ")
255 nil nil liece-privmsg-partner)
256 (liece-minibuffer-completing-default-read
258 (append liece-channel-alist liece-nick-alist)
259 nil nil liece-default-channel-candidate)))))
260 (if (and current-prefix-arg
261 (not (numberp current-prefix-arg)))
263 (if (eq current-prefix-arg '-)
265 (format (_ "Key for channel %s: ") join-channel-var))
266 (let ((passwd-echo ?*))
268 (format (_ "Key for channel %s: ") join-channel-var))))))
269 (list join-channel-var key)))
270 (let ((real-chnl (liece-channel-real join-channel-var)))
271 (if (numberp join-channel-var)
272 (liece-switch-to-channel-no join-channel-var)
273 (setq liece-default-channel-candidate nil)
274 (if (liece-channel-p real-chnl)
275 (liece-toggle-command-buffer-mode 'channel)
276 (liece-toggle-command-buffer-mode 'chat))
277 (if (eq liece-command-buffer-mode 'chat)
278 (liece-command-join-partner join-channel-var)
280 (setq key (get (intern join-channel-var liece-obarray) 'key)))
281 (put (intern join-channel-var liece-obarray) 'key key)
284 (liece-command-join-channel join-channel-var key))
285 (force-mode-line-update))))
287 (defun liece-command-part (part-channel-var &optional part-msg)
288 "Part a PART-CHANNEL-VAR with PART-MSG."
290 (let (part-channel-var
291 (completion-ignore-case t)
293 (setq part-channel-var
294 (liece-channel-virtual
295 (if (eq liece-command-buffer-mode 'chat)
296 (liece-minibuffer-completing-default-read
297 (_ "End private conversation with: ")
298 (list-to-alist liece-current-chat-partners)
299 nil nil liece-current-chat-partner)
300 (liece-minibuffer-completing-default-read
302 (list-to-alist liece-current-channels)
303 nil nil liece-current-channel))))
304 (when current-prefix-arg
305 (setq part-msg (read-string (_ "Part Message: "))))
306 (list part-channel-var part-msg)))
307 (let ((real-chnl (liece-channel-real part-channel-var)))
308 (if (liece-channel-p real-chnl)
310 (if (liece-channel-member part-channel-var liece-current-channels)
311 (setq liece-current-channel part-channel-var))
312 (liece-send "PART %s :%s" real-chnl part-msg)
313 (setq liece-default-channel-candidate part-channel-var))
314 (setq liece-current-chat-partners
315 (liece-channel-remove part-channel-var
316 liece-current-chat-partners)
317 liece-current-chat-partner
318 (car liece-current-chat-partners))
319 (liece-set-channel-indicator)
320 (liece-set-crypt-indicator)
321 (liece-channel-part part-channel-var))))
323 (defun liece-command-kill (kill-nickname-var &optional timeout silent)
324 "Ignore messages from KILL-NICKNAME-VAR.
325 Username can be given as case insensitive regular expression of form
326 \".*@.*\.sub.domain\".
327 If already ignoring him/her, toggle.
328 If `liece-variables-file' is defined and the file is writable,
329 settings are updated automatically for future sessions.
330 Optional argument TIMEOUT says expiration.
331 If SILENT is non-nil, don't notify current status."
333 (let (kill-nickname-var timeout (completion-ignore-case t))
334 (setq kill-nickname-var (completing-read
335 (_ "Ignore nickname or regexp: ")
336 (append liece-nick-alist
337 liece-kill-nickname)))
338 (or (string-equal "" kill-nickname-var)
339 (string-assoc-ignore-case kill-nickname-var liece-kill-nickname)
340 (setq timeout (string-to-int (read-from-minibuffer
341 (_ "Timeout [RET for none]: ")))))
342 (list kill-nickname-var timeout)))
343 ;; empty, just list them
344 (if (string-equal "" kill-nickname-var)
345 (with-current-buffer liece-dialogue-buffer
346 (let ((ignores liece-kill-nickname) (time (current-time))
347 buffer-read-only expire expiretime)
348 (goto-char (point-max))
349 (liece-insert-info liece-D-buffer (_ "Currently ignoring:"))
350 (dolist (ignore ignores)
351 (setq expiretime (if (cdr ignore)
352 (/ (liece-time-difference time (cdr ignore))
354 expire (cond ((not expiretime) "")
356 (format (_ " (%d min)") expiretime))
359 (liece-insert liece-D-buffer
360 (concat " " (car ignore) expire "\n")))))
361 ;; else not empty, check if exists
363 (string-assoc-ignore-case
364 kill-nickname-var liece-kill-nickname)))
366 (when (setq ignore (string-assoc-ignore-case
367 (car ignore) liece-kill-nickname))
368 (setq liece-kill-nickname
369 (delq ignore liece-kill-nickname))
370 (liece-insert-info liece-D-buffer
371 (format (_ "No longer ignoring: %s.\n")
373 ;; did not find, add to ignored ones
374 (let ((expire-time (if (> timeout 0)
375 (liece-time-add (current-time)
377 (and silent (> timeout 0)
378 (setcar (cdr (cdr expire-time)) -1))
379 (setq liece-kill-nickname
380 (cons (cons kill-nickname-var expire-time)
381 liece-kill-nickname))
383 (liece-insert-info liece-D-buffer
384 (format (_ "Ignoring %s") kill-nickname-var))
385 (liece-insert-info liece-D-buffer
387 (format " for %d minutes.\n" timeout)
389 (setq liece-save-variables-are-dirty t)))
391 (defun liece-command-kick (nick &optional msg)
392 "Kick this NICK out with MSG."
394 (let ((completion-ignore-case t)
395 (nicks (liece-channel-get-nicks)) nick msg)
396 (setq nick (completing-read
397 (_ "Kick out nickname: ")
398 (list-to-alist nicks)))
399 (if current-prefix-arg
400 (setq msg (concat " :" (read-string (_ "Kick Message: ")))))
402 (liece-send "KICK %s %s%s"
403 (liece-channel-real liece-current-channel)
406 (defun liece-command-ban (ban)
409 (let* ((completion-ignore-case t)
410 (nicks (liece-channel-get-nicks))
415 (concat nick "!" (liece-nick-get-user-at-host nick)))))
418 (setq ban (liece-minibuffer-completing-default-read
419 (_ "Ban pattern: ") uahs nil nil
420 (concat nick "!" (liece-nick-get-user-at-host nick))))
422 (liece-send "MODE %s :+b %s"
423 (liece-channel-real liece-current-channel) ban))
425 (defun liece-command-ban-kick (ban nick &optional msg)
426 "BAN kick this NICK out with MSG."
428 (let* ((completion-ignore-case t)
429 (nicks (liece-channel-get-nicks))
434 (concat nick "!" (liece-nick-get-user-at-host nick)))))
437 (setq nick (completing-read (_ "Kick out nickname: ")
438 (list-to-alist nicks))
439 ban (liece-minibuffer-completing-default-read
440 (_ "Ban pattern: ") uahs nil nil
441 (concat nick "!" (liece-nick-get-user-at-host nick))))
442 (if current-prefix-arg
443 (setq msg (concat " :" (read-string (_ "Kick Message: "))))
445 (list ban nick msg)))
446 (liece-send "MODE %s :+b %s"
447 (liece-channel-real liece-current-channel) ban)
448 (liece-send "KICK %s %s%s"
449 (liece-channel-real liece-current-channel)
452 (defun liece-command-list (&optional channel)
453 "List the given CHANNEL and its topics.
454 If you enter only Control-U as argument, list the current channel.
455 With - as argument, list all channels."
457 (if (or current-prefix-arg (null liece-current-channel))
458 (if (eq current-prefix-arg '-)
459 (list current-prefix-arg))
460 (let ((completion-ignore-case t) channel)
461 (setq channel (liece-minibuffer-completing-default-read
463 liece-channel-alist nil nil liece-current-channel))
464 (unless (string-equal "" channel)
468 (if liece-current-channel
469 (liece-send "LIST %s"
470 (liece-channel-real liece-current-channel))))
471 ((and (eq channel '-)
472 (y-or-n-p (_ "Do you really query LIST without argument?")))
474 ((not (string-equal channel ""))
475 (liece-send "LIST %s" (liece-channel-real channel))
478 (defun liece-command-lusers ()
479 "List the number of users and servers."
481 (liece-send "LUSERS"))
483 (defun liece-command-modec (chnl change)
484 "Send a MODE command to this CHNL.
487 (let ((completion-ignore-case t)
488 (chnl liece-current-channel)
489 liece-minibuffer-complete-function prompt)
490 (if current-prefix-arg
492 (liece-minibuffer-completing-default-read
494 (append liece-channel-alist liece-nick-alist)
495 nil nil liece-current-channel)))
497 ((liece-channel-p (liece-channel-real chnl))
499 (_ "Mode for channel %s [%s]: ")
500 chnl (or (liece-channel-get-modes chnl) ""))
501 liece-minibuffer-complete-function
502 (function liece-minibuffer-complete-channel-modes)))
505 (_ "Mode for user %s [%s]: ")
506 chnl (or (liece-nick-get-modes chnl) ""))
507 liece-minibuffer-complete-function
508 (function liece-minibuffer-complete-user-modes))))
509 (list chnl (read-from-minibuffer prompt nil liece-minibuffer-map))))
510 (liece-send "MODE %s %s" (liece-channel-real chnl) change))
512 (defun liece-command-mode+o (opers)
513 "Send a MODE +o OPERS command."
515 (let ((opers (liece-channel-get-operators)) oper
516 (nicks (liece-channel-get-nicks))
517 (completion-ignore-case t))
518 (setq nicks (filter-elements
520 (not (liece-nick-member nick opers)))
521 opers (liece-minibuffer-completing-sequential-read
522 (_ "Set Operator for") 0
523 (list-to-alist nicks)))
528 (when (= (length ops) liece-compress-mode-length)
529 (liece-send "MODE %s +%s %s"
530 (liece-channel-real liece-current-channel)
531 (string-times "o" liece-compress-mode-length)
532 (string-join ops " "))
535 (liece-send "MODE %s +%s %s"
536 (liece-channel-real liece-current-channel)
537 (string-times "o" (length ops))
538 (string-join ops " ")))))
540 (defun liece-command-mode-o (opers)
541 "Send a MODE -o OPERS command."
543 (let ((completion-ignore-case t)
544 (opers (liece-channel-get-operators)) oper nicks)
545 (setq nicks (liece-minibuffer-completing-sequential-read
546 (_ "Unset Operator for") 0
547 (list-to-alist opers)))
552 (when (= (length ops) liece-compress-mode-length)
553 (liece-send "MODE %s -%s %s"
554 (liece-channel-real liece-current-channel)
555 (string-times "o" liece-compress-mode-length)
556 (string-join ops " "))
559 (liece-send "MODE %s -%s %s"
560 (liece-channel-real liece-current-channel)
561 (string-times "o" (length ops))
562 (string-join ops " ")))))
564 (defun liece-command-mode+v (voices)
565 "Send a MODE +v VOICES command."
567 (let ((voices (append (liece-channel-get-voices)
568 (liece-channel-get-operators)))
570 (nicks (liece-channel-get-nicks))
571 (completion-ignore-case t)
573 (setq nicks (filter-elements nick nicks
574 (not (string-assoc-ignore-case nick voices)))
575 voices (liece-minibuffer-completing-sequential-read
576 (_ "Set Voice for") 0 (list-to-alist nicks)))
579 (dolist (voice voices)
581 (when (= (length vcs) liece-compress-mode-length)
582 (liece-send "MODE %s +%s %s"
583 (liece-channel-real liece-current-channel)
584 (string-times "v" liece-compress-mode-length)
585 (string-join vcs " "))
588 (liece-send "MODE %s +%s %s"
589 (liece-channel-real liece-current-channel)
590 (string-times "v" (length vcs))
591 (string-join vcs " ")))))
593 (defun liece-command-mode-v (voices)
594 "Send a MODE -v VOICES command."
596 (let ((completion-ignore-case t)
597 (voices (liece-channel-get-voices)) voice nicks)
598 (setq nicks (liece-minibuffer-completing-sequential-read
599 (_ "Unset Voice for") 0 (list-to-alist voices)))
602 (dolist (voice voices)
604 (when (= (length vcs) liece-compress-mode-length)
605 (liece-send "MODE %s -%s %s"
606 (liece-channel-real liece-current-channel)
607 (string-times "v" liece-compress-mode-length)
608 (string-join vcs " "))
611 (liece-send "MODE %s -%s %s"
612 (liece-channel-real liece-current-channel)
613 (string-times "v" (length vcs))
614 (string-join vcs " ")))))
616 (defun liece-command-message (address message &optional arg key)
617 "Send ADDRESS a private MESSAGE.
618 If argument ARG is non-nil message will be encrypted with KEY."
620 (let ((completion-ignore-case t) address)
622 (liece-channel-virtual
623 (liece-minibuffer-completing-default-read
624 (_ "Private message to: ")
625 (append liece-nick-alist liece-channel-alist)
626 nil nil liece-privmsg-partner)))
630 (_ "Private message to %s: ")
632 (if current-prefix-arg
633 (not liece-crypt-mode-active)
634 liece-crypt-mode-active)
636 (if (funcall liece-message-empty-predicate message)
637 (progn (liece-message (_ "No text to send")) nil)
638 (let ((chnl (liece-channel-real address)) (msg message))
639 (with-liece-encryption (msg address arg key)
640 (liece-send "PRIVMSG %s :%s" chnl msg)
641 (if (liece-channel-p chnl)
642 (liece-own-channel-message message
643 (liece-channel-virtual address))
644 (liece-own-private-message message address)))
647 ;; Added at mta@tut.fi's request...
648 ;; Does not support encryption (yet!?)
650 (defun liece-command-mta-private (partner)
651 "Send a private message (current line) to PARTNER."
653 (let ((completion-ignore-case t))
654 (setq liece-privmsg-partner
655 (liece-channel-virtual
656 (liece-minibuffer-completing-default-read
658 (append liece-nick-alist liece-channel-alist)
659 nil nil liece-privmsg-partner)))
660 (list liece-privmsg-partner)))
661 (let ((message (buffer-substring (progn (beginning-of-line) (point))
662 (progn (end-of-line) (point)))))
663 (if (> (length message) 0)
665 (liece-command-message liece-privmsg-partner message)
667 (liece-message (_ "No text to send")))))
669 (defun liece-command-names (&optional expr)
670 "List the nicknames of the current IRC users on given EXPR.
671 With an Control-U as argument, only the current channel is listed.
672 With - as argument, list all channels."
674 (if (or current-prefix-arg (null liece-current-channel))
675 (if (eq current-prefix-arg '-)
676 (list current-prefix-arg))
677 (let ((completion-ignore-case t) expr)
678 (setq expr (liece-minibuffer-completing-default-read
679 (_ "Names on channel: ")
680 liece-channel-alist nil nil liece-current-channel))
681 (unless (string-equal "" expr)
683 (when (or (and (eq expr '-)
685 (_ "Do you really query NAMES without argument?")))
687 (if liece-current-channel
688 (setq expr (liece-channel-real
689 liece-current-channel))))))
692 (liece-send "NAMES %s" expr)))
694 (defun liece-command-nickname (nick)
695 "Set your nickname to NICK."
696 (interactive "sEnter your nickname: ")
697 (let ((nickname (truncate-string nick liece-nick-max-length)))
698 (if (zerop (length nickname))
699 (liece-message (_ "illegal nickname \"%s\"; not changed") nickname)
700 (liece-send "NICK %s" nick))))
702 (defun liece-command-who (&optional expr)
703 "Lists tue users that match the given expression EXPR.
704 If you enter only Control-U as argument, list the current channel.
705 With - as argument, list all users."
707 (if (or current-prefix-arg (null liece-current-channel))
708 (if (eq current-prefix-arg '-)
709 (list current-prefix-arg))
710 (let ((completion-ignore-case t) expr)
711 (setq expr (liece-minibuffer-completing-default-read
712 (_ "WHO expression: ")
713 (append liece-channel-alist liece-nick-alist)))
714 (unless (string-equal "" expr)
716 (when (or (and (eq expr '-)
718 (_ "Do you really query WHO without argument?")))
720 (if liece-current-channel
721 (setq expr (liece-channel-real
722 liece-current-channel))))))
725 (liece-send "WHO %s" expr)
726 (setq liece-who-expression expr)))
728 (defun liece-command-finger (finger-nick-var &optional server)
729 "Get information about a specific user FINGER-NICK-VAR.
730 If called with optional argument SERVER or any prefix argument,
731 query information to the foreign server."
733 (let (finger-nick-var (completion-ignore-case t))
734 (setq finger-nick-var
735 (completing-read (_ "Finger whom: ") liece-nick-alist))
736 (list finger-nick-var (and current-prefix-arg finger-nick-var))))
738 (liece-send "WHOIS %s %s" server finger-nick-var)
739 (liece-send "WHOIS %s" finger-nick-var)))
741 (defun liece-command-topic (topic)
742 "Change TOPIC of the current channel."
744 (list (read-from-minibuffer
745 "Topic: " (cons (or (liece-channel-get-topic) "") 0))))
746 (liece-send "TOPIC %s :%s"
747 (liece-channel-real liece-current-channel) topic))
749 (defun liece-command-invite (&optional invite-nick-var invite-channel-var)
750 "Invite INVITE-NICK-VAR to INVITE-CHANNEL-VAR."
752 (let ((completion-ignore-case t) invite-channel-var invite-nick-var)
753 (if current-prefix-arg
754 (setq invite-channel-var
755 (liece-channel-virtual
757 (_ "Invite channel: ")
758 (list-to-alist liece-current-channels)))))
759 (setq invite-nick-var
763 (list invite-nick-var invite-channel-var)))
764 (or invite-channel-var
765 (setq invite-channel-var liece-current-channel))
766 (liece-send "INVITE %s %s"
767 invite-nick-var (liece-channel-real invite-channel-var)))
769 (defun liece-command-away (awaymsg)
770 "Mark/unmark yourself as being away.
771 Leave message AWAYMSG."
772 (interactive "sAway message: ")
773 (liece-send "AWAY :%s" awaymsg)
774 (setq liece-away-message awaymsg))
776 (defun liece-command-scroll-down (lines)
777 "Scroll LINES down dialogue buffer from command buffer."
779 (let ((other-window-scroll-buffer
780 (if liece-channel-buffer-mode
782 liece-dialogue-buffer)))
783 (when (liece-get-buffer-window other-window-scroll-buffer)
785 (scroll-other-window-down lines)
787 (message "Beginning of buffer"))))))
789 (defun liece-command-scroll-up (lines)
790 "Scroll LINES up dialogue buffer from command buffer."
792 (let* ((other-window-scroll-buffer
793 (if liece-channel-buffer-mode
795 liece-dialogue-buffer)))
796 (when (liece-get-buffer-window other-window-scroll-buffer)
798 (scroll-other-window lines)
800 (message "End of buffer"))))))
802 (defun liece-command-nick-scroll-down (lines)
803 "Scroll LINES down nick buffer from command buffer."
805 (let ((other-window-scroll-buffer liece-nick-buffer))
806 (when (liece-get-buffer-window other-window-scroll-buffer)
808 (scroll-other-window-down lines)
810 (message "Beginning of buffer"))))))
812 (defun liece-command-nick-scroll-up (lines)
813 "Scroll LINES up nick buffer from command buffer."
815 (let* ((other-window-scroll-buffer liece-nick-buffer))
816 (when (liece-get-buffer-window other-window-scroll-buffer)
818 (scroll-other-window lines)
820 (message "End of buffer"))))))
822 (defun liece-command-toggle-crypt (&optional arg)
823 "Toggle crypt status.
824 If prefix argument ARG is non-nil, force set crypt status."
827 (setq liece-crypt-mode-active (prefix-numeric-value arg))
828 (if liece-crypt-mode-active
829 (setq liece-crypt-mode-active nil)
830 (setq liece-crypt-mode-active t)))
831 (liece-set-crypt-indicator)
832 (switch-to-buffer (current-buffer)))
834 (defun liece-command-freeze (&optional arg)
835 "Prevent automatic scrolling of the dialogue window.
836 If prefix argument ARG is non-nil, toggle frozen status."
838 (liece-freeze (if liece-channel-buffer-mode
840 liece-dialogue-buffer)
841 (if arg (prefix-numeric-value arg))))
843 (defun liece-command-own-freeze (&optional arg)
844 "Prevent automatic scrolling of the dialogue window.
845 The difference from `liece-command-freeze' is that your messages are hidden.
846 If prefix argument ARG is non-nil, toggle frozen status."
848 (liece-own-freeze (if liece-channel-buffer-mode
850 liece-dialogue-buffer)
851 (if arg (prefix-numeric-value arg))))
853 (defun liece-command-beep (&optional arg)
854 "Toggle the automatic beep notice when the channel message is received."
856 (liece-beep (if liece-channel-buffer-mode
858 liece-dialogue-buffer)
859 (if arg (prefix-numeric-value arg))))
861 (defun liece-command-quit (&optional arg)
863 If prefix argument ARG is non-nil, leave signoff message."
865 (when (and (liece-server-opened)
866 (y-or-n-p (_ "Quit IRC? ")))
869 (if arg (read-string (_ "Signoff message: "))
870 (or liece-signoff-message
871 (product-name (product-find 'liece-version))))))
872 (liece-send "QUIT :%s" quit-string))
875 (if liece-save-variables-are-dirty
876 (liece-command-save-vars))
878 (liece-window-configuration-pop))
879 (run-hooks 'liece-exit-hook)))
881 (defun liece-command-generic (message)
882 "Enter a generic IRC MESSAGE, which is sent to the server.
883 A ? lists the useful generic messages."
884 (interactive "sIRC command (? to help): ")
885 (if (string-equal message "?")
886 (with-output-to-temp-buffer "*IRC Help*"
887 (princ "The following generic IRC messages may be of interest to you:
888 TOPIC <new topic> set the topic of your channel
889 INVITE <nickname> invite another user to join your channel
890 LINKS lists the currently reachable IRC servers
891 SUMMON <user@host> invites an user not currently in IRC
892 USERS <host> lists the users on a host
893 AWAY <reason> marks you as not really actively using IRC
894 (an empty reason clears it)
895 WALL <message> send to everyone on IRC
896 NAMES <channel> lists users per channel
898 (liece-send "%s" message)))
900 (defun liece-command-irc-compatible ()
901 "If entered at column 0, allow you to enter a generic IRC message."
903 (if (zerop (current-column))
904 (call-interactively (function liece-command-generic))
905 (self-insert-command 1)))
907 (defun liece-command-exec (command)
908 "Execute COMMAND, stdout to dialogue."
909 (interactive "sShell command: ")
910 (shell-command command t)
911 (let ((opoint (point)))
912 (while (< (point) (mark))
913 (liece-command-enter-message)
914 (set-buffer liece-command-buffer))
915 (push-mark opoint t)))
917 (defun liece-command-yank-send (&optional arg)
918 "Send message from yank buffer.
919 Prefix argument ARG is regarded as distance from yank pointer."
921 (when (y-or-n-p (_ "Really SEND from Yank Buffer?"))
923 (narrow-to-region (point) (point))
924 (insert (car kill-ring-yank-pointer))
925 (goto-char (point-min))
927 (liece-command-enter-message)
928 (set-buffer liece-command-buffer)))))
930 (defun liece-command-complete ()
931 "Complete word before point from userlist."
933 (let ((completion-ignore-case t)
934 (alist (if liece-current-channel
935 (list-to-alist (liece-channel-get-nicks))
937 candidate completion all)
938 (setq candidate (current-word)
939 completion (try-completion candidate alist)
940 all (all-completions candidate alist))
941 (liece-minibuffer-finalize-completion completion candidate all)))
943 (defun liece-command-load-vars ()
944 "Load configuration from liece-variables-file."
946 (let ((nick liece-real-nickname))
948 (liece-read-variables-files)
949 (setq liece-real-nickname nick)
950 (liece-command-reconfigure-windows))))
952 (defun liece-command-save-vars ()
953 "Save current settings to `liece-variables-file'."
955 (let* ((output-buffer
957 (expand-file-name liece-variables-file)))
960 (set-buffer output-buffer)
961 (goto-char (point-min))
962 (cond ((re-search-forward "^;; Saved Settings *\n" nil 'move)
963 (setq p (match-beginning 0))
965 (or (re-search-forward
966 "^;; End of Saved Settings *\\(\n\\|\\'\\)" nil t)
968 (concat "can't find END of saved state in "
969 liece-variables-file)))
970 (delete-region p (match-end 0)))
972 (goto-char (point-max))
974 (setq output-marker (point-marker))
975 (let ((print-readably t)
976 (print-escape-newlines t)
977 (standard-output output-marker))
978 (princ ";; Saved Settings\n")
979 (dolist (var liece-saved-forms)
981 (prin1 (list 'setq var
982 (let ((val (symbol-value var)))
983 (if (memq val '(t nil))
985 (list 'quote val)))))
986 (setq var (eval var))
987 (cond ((eq (car-safe var) 'progn)
988 (while (setq var (cdr var))
991 (if (cdr var) (princ " "))))
993 (prin1 "xx")(prin1 var))))
994 (if var (princ "\n")))
996 (princ ";; End of Saved Settings\n")))
997 (set-marker output-marker nil)
999 (set-buffer output-buffer)
1001 (setq liece-save-variables-are-dirty nil))
1003 (defun liece-command-reconfigure-windows ()
1004 "Rearrange window splitting."
1006 (let ((command-window (liece-get-buffer-window liece-command-buffer))
1007 (dialogue-window (liece-get-buffer-window liece-dialogue-buffer))
1008 (obuffer (current-buffer)))
1009 (if (and command-window dialogue-window)
1010 (let ((ch (window-height command-window))
1011 (dh (window-height dialogue-window)))
1012 (delete-window command-window)
1013 (pop-to-buffer liece-dialogue-buffer)
1014 (enlarge-window (+ ch dh (- dh))))
1015 (pop-to-buffer liece-dialogue-buffer))
1016 (liece-configure-windows)
1017 (if liece-one-buffer-mode
1018 (pop-to-buffer liece-dialogue-buffer)
1019 (pop-to-buffer obuffer))))
1021 (defun liece-command-end-of-buffer ()
1022 "Get end of the dialogue buffer."
1024 (let (buffer window)
1025 (setq buffer (if liece-channel-buffer-mode
1026 liece-channel-buffer
1027 liece-dialogue-buffer))
1028 (or (setq window (liece-get-buffer-window buffer))
1029 (setq window (liece-get-buffer-window liece-dialogue-buffer)
1030 buffer liece-dialogue-buffer))
1032 (save-selected-window
1033 (select-window window)
1034 (goto-char (point-max))))))
1036 (defun liece-command-private-conversation (arg)
1037 "Toggle between private conversation mode and channel mode.
1038 User can then join and part to a private conversation as he would
1039 join or part to a channel.
1041 If there are no private conversations or argument is given user is
1042 prompted the partner/channel (return as partner/channel means toggle
1043 mode, the current channel and current chat partner are not altered)
1044 Argument ARG is prefix argument of toggle status."
1046 (let ((completion-ignore-case t))
1048 (if current-prefix-arg
1049 ;; prefixed, ask where to continue
1050 (if (eq liece-command-buffer-mode 'chat)
1051 (liece-minibuffer-completing-default-read
1052 (_ "Return to channel: ")
1053 (append liece-channel-alist liece-nick-alist)
1054 nil nil liece-current-channel)
1056 (_ "Start private conversation with: ")
1057 liece-nick-alist nil nil))
1058 ;; no prefix, see if going to chat
1059 (if (eq liece-command-buffer-mode 'channel)
1060 ;; and if we have chat partner, select that
1061 (if liece-current-chat-partner
1062 liece-current-chat-partner
1064 (_ "Start private conversation with: ")
1065 liece-nick-alist )))))))
1067 (liece-toggle-command-buffer-mode)
1068 (if (and arg (not (string-equal arg "")))
1069 (liece-command-join arg))
1070 (liece-set-channel-indicator)
1071 (liece-set-crypt-indicator)
1072 ;; refresh mode line
1073 (force-mode-line-update))
1075 (defun liece-command-next-channel ()
1076 "Select next channel or chat partner, and *DONT* rotate list."
1078 (let ((rest (copy-sequence
1079 (if (eq liece-command-buffer-mode 'chat)
1080 liece-current-chat-partners
1081 liece-current-channels)))
1082 (chnl (if (eq liece-command-buffer-mode 'chat)
1083 liece-current-chat-partner
1084 liece-current-channel)))
1085 (liece-switch-to-channel
1086 (or (cadr (liece-channel-member chnl (delq nil rest)))
1087 (car (delq nil rest))
1090 (defun liece-command-previous-channel ()
1091 "Select previous channel or chat partner, and *DONT* rotate list."
1095 (if (eq liece-command-buffer-mode 'chat)
1096 liece-current-chat-partners
1097 liece-current-channels)))
1099 (if (eq liece-command-buffer-mode 'chat)
1100 liece-current-chat-partner
1101 liece-current-channel)))
1102 (liece-switch-to-channel
1103 (or (cadr (liece-channel-member chnl (delq nil rest)))
1104 (car (delq nil rest))
1107 (defun liece-command-unread-channel ()
1108 "Select unread channel or chat partner."
1110 (let ((chnl (car liece-channel-unread-list)))
1112 (liece-switch-to-channel chnl)
1113 (liece-message (_ "No unread channel or chat partner.")))))
1115 (defun liece-command-push ()
1116 "Select next channel or chat partner, and rotate list."
1119 (if (eq liece-command-buffer-mode 'chat)
1120 liece-current-chat-partners
1121 liece-current-channels))
1122 (temp (car (last rest)))
1123 (len (length rest)))
1126 (setcar (nthcdr (1- len) rest) (nth (- len 2) rest))
1129 (setcar rest temp)))
1130 (liece-channel-change)))
1132 (defun liece-command-pop ()
1133 "Select previous channel or chat partner, and rotate list."
1136 (if (eq liece-command-buffer-mode 'chat)
1137 liece-current-chat-partners
1138 liece-current-channels))
1140 (len (length rest)))
1143 (setcar (nthcdr i rest) (nth (1+ i) rest)))
1145 (setcar (last rest) temp)))
1146 (liece-channel-change)))
1148 (defvar liece-redisplay-buffer-functions
1149 '(liece-channel-redisplay-buffer
1150 liece-nick-redisplay-buffer
1151 liece-channel-list-redisplay-buffer))
1153 (defun liece-switch-to-channel (chnl)
1154 "Switch the current channel to CHNL."
1155 (if (liece-channel-p (liece-channel-real chnl))
1157 (liece-toggle-command-buffer-mode 'channel)
1158 (setq liece-current-channel chnl)
1159 (liece-set-channel-indicator))
1160 (liece-toggle-command-buffer-mode 'chat)
1161 (setq liece-current-chat-partner chnl)
1162 (liece-set-channel-indicator))
1164 (run-hook-with-args 'liece-redisplay-buffer-functions chnl))
1165 (liece-set-crypt-indicator)
1168 (defun liece-switch-to-channel-no (num)
1169 "Switch the current channel to NUM."
1170 (let* ((mode liece-command-buffer-mode)
1171 (chnls (if (eq mode 'chat)
1172 liece-current-chat-partners
1173 liece-current-channels)))
1174 (if (and (integerp num)
1175 (stringp (nth num chnls)))
1176 (let ((chnl (nth num chnls)))
1179 (liece-toggle-command-buffer-mode 'chat)
1180 (setq liece-current-chat-partner chnl)
1181 (liece-set-channel-indicator))
1182 (liece-toggle-command-buffer-mode 'channel)
1183 (setq liece-current-channel chnl)
1184 (liece-set-channel-indicator))
1186 (run-hook-with-args 'liece-redisplay-buffer-functions chnl))
1187 (liece-set-crypt-indicator)
1189 (message "Invalid channel!")
1192 (defun liece-command-ping ()
1193 "Send PING to server."
1195 (if (stringp liece-server-name)
1196 (liece-send "PING %s" liece-server-name)))
1198 (defun liece-command-ison (nicks)
1201 (let (nicks (completion-ignore-case t))
1202 (setq nicks (liece-minibuffer-completing-sequential-read
1203 "IsON" 0 liece-nick-alist))
1205 (liece-send "ISON :%s" (mapconcat #'identity nicks " ")))
1207 (defun liece-command-activate-friends (nicks)
1208 "Register NICKS to the frinends list."
1210 (let (nicks (completion-ignore-case t))
1212 (liece-minibuffer-completing-sequential-read
1214 (filter-elements nick liece-nick-alist
1215 (not (string-list-member-ignore-case
1216 (car nick) liece-friends)))))
1218 (setq liece-friends (append nicks liece-friends)))
1220 (defun liece-command-deactivate-friends ()
1221 "Clear current friends list."
1223 (setq liece-friends nil))
1225 (defun liece-command-display-friends ()
1226 "Display status of the friends."
1228 (with-output-to-temp-buffer " *IRC Friends*"
1229 (set-buffer standard-output)
1230 (insert "Friends status: \n\n")
1231 (dolist (friend liece-friends)
1232 (if (string-list-member-ignore-case friend liece-friends-last)
1233 (insert "+ " friend "\n")
1234 (insert "- " friend "\n")))))
1236 (defun liece-command-userhost (nicks)
1237 "Ask for the hostnames of NICKS."
1239 (let (nicks (completion-ignore-case t))
1240 (setq nicks (liece-minibuffer-completing-sequential-read
1241 (_ "Userhost nick") 0
1242 (list-to-alist liece-nick-alist)))
1244 (liece-send "USERHOST :%s" (mapconcat 'identity nicks ",")))
1246 (defun liece-command-show-last-kill ()
1247 "Dig last kill from KILL and show it."
1250 (append liece-D-buffer liece-O-buffer)
1252 (set-buffer liece-KILLS-buffer)
1253 (goto-char (point-max))
1255 (concat (buffer-substring (point) (point-max)) "\n"))))
1257 (defun liece-command-toggle-private ()
1258 "Toggle private mode / channel mode."
1260 (case (prog1 liece-command-buffer-mode
1261 (liece-toggle-command-buffer-mode))
1263 (if liece-current-channel
1264 (liece-switch-to-channel liece-current-channel))
1265 (setq liece-command-buffer-mode-indicator "Channels"))
1267 (if liece-current-chat-partner
1268 (liece-switch-to-channel liece-current-chat-partner))
1269 (setq liece-command-buffer-mode-indicator "Partners")))
1270 (liece-channel-change))
1272 (defun liece-command-tag-region (start end)
1273 "Move current region between START and END to `kill-ring'."
1275 (if (region-active-p)
1276 (list (region-beginning)(region-end))
1277 (list (line-beginning-position)(line-end-position))))
1278 (static-if (fboundp 'extent-property)
1279 (kill-ring-save start end)
1280 (let ((start (set-marker (make-marker) start))
1281 (end (set-marker (make-marker) end))
1282 (inhibit-read-only t)
1285 (liece-remove-properties-region start end)
1286 (kill-ring-save start end)
1287 (push nil buffer-undo-list)
1290 (provide 'liece-commands)
1292 ;;; liece-commands.el ends here