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 (defun liece-command-poll-names ()
46 "Handler for polling NAMES."
47 (when (liece-server-opened)
50 (length liece-channel-alist)))
51 (dolist (chnl liece-channel-alist)
52 (liece-send "NAMES %s" (car chnl)))))
54 (defun liece-command-poll-friends ()
55 "Handler for polling ISON."
58 (liece-send "ISON %s" (mapconcat 'identity liece-friends " "))))
60 (defun liece-command-find-timestamp ()
61 "Find recent timestamp in dialogue buffer."
65 (regexp (concat "^\\(" liece-time-prefix-regexp "\\)?"
66 (regexp-quote liece-timestamp-prefix))))
67 (unless (eq 'liece-dialogue-mode (derived-mode-class major-mode))
68 (set-buffer liece-dialogue-buffer)
69 (goto-char (point-max)))
70 (if (re-search-backward regexp (point-min) t)
71 (setq range (concat (buffer-substring (match-end 0)
74 (if (re-search-forward regexp (point-max) t)
75 (setq range (concat range (buffer-substring (match-end 0)
76 (line-end-position)))))
77 (liece-message range))))
79 (defun liece-command-keepalive ()
80 "Handler for polling server connection."
81 (if (not (liece-server-opened))
83 (liece-ping-if-idle)))
85 (defvar liece-last-timestamp-time nil "Last time timestamp was inserted.")
86 (defvar liece-last-timestamp-no-cons-p nil "Last timestamp was no-cons.")
88 (defun liece-command-timestamp-if-interval-expired (&optional no-cons)
89 "If interval timer has expired, insert timestamp into dialogue buffer.
90 And save variables into `liece-variable-file' if there are variables to save.
91 Optional argument NO-CONS specifies timestamp format is cons cell."
93 (when (and (not (and no-cons
94 liece-last-timestamp-no-cons-p))
95 (numberp liece-timestamp-interval)
96 (> liece-timestamp-interval 0)
97 (or (null liece-last-timestamp-time)
98 (> (liece-time-difference liece-last-timestamp-time
100 liece-timestamp-interval)))
101 (if liece-save-variables-are-dirty
102 (liece-command-save-vars))
103 (liece-command-timestamp)
104 (setq liece-last-timestamp-no-cons-p no-cons)))
106 (defun liece-command-timestamp ()
107 "Insert timestamp into dialogue buffer."
109 (let ((stamp (format liece-timestamp-format
110 (funcall liece-format-time-function (current-time))))
111 (liece-timestamp-interval 0))
112 (liece-insert liece-D-buffer (concat stamp "\n"))
113 (setq liece-last-timestamp-time (current-time))))
115 (defun liece-command-point-back-to-command-buffer ()
116 "Set point back to command buffer."
118 (let ((win (liece-get-buffer-window liece-command-buffer)))
119 (if win (select-window win))))
121 (defun liece-command-send-message
122 (message &optional arg key)
123 "Send MESSAGE to current chat partner of current channel.
124 If argument ARG is non-nil message will be encrypted with KEY."
126 (setq liece-crypt-mode-active (not liece-crypt-mode-active)))
127 (if (string-equal message "")
128 (progn (liece-message (_ "No text to send")) nil)
129 (let ((addr (if (eq liece-command-buffer-mode 'chat)
130 liece-current-chat-partner
131 liece-current-channel))
132 repr method name target
134 (with-liece-encryption (msg addr arg key)
136 ((eq liece-command-buffer-mode 'chat)
137 (if (null liece-current-chat-partner)
139 (substitute-command-keys
140 "Type \\[liece-command-join] to start private conversation"))
141 (setq repr (liece-channel-parse-representation
142 liece-current-chat-partner)
145 target (aref repr 2))
146 (cond ((eq method 'dcc)
147 (liece-dcc-chat-send target msg))
149 (liece-send "PRIVMSG %s :%s"
150 liece-current-chat-partner msg)))
151 (liece-own-private-message message)))
152 ((not liece-current-channel)
154 (message (substitute-command-keys
155 "Type \\[liece-command-join] to join a channel")))
159 (liece-channel-real liece-current-channel) msg)
160 (liece-own-channel-message message))))
163 (defun liece-enter-message (&optional arg key)
164 "Enter the current line as an entry in the IRC dialogue.
165 If argument ARG is non-nil message will be encrypted with KEY."
167 (if (liece-command-send-message
168 (buffer-substring (point)(progn (end-of-line) (point)))
170 (liece-next-line 1)))
172 (defun liece-command-enter-message (&optional arg key)
173 "Enter the current line as an entry in the IRC dialogue.
174 If the prefix argument ARG is non-nil, message will be encrypted with KEY."
176 (let ((completion-ignore-case t))
177 (and (if current-prefix-arg
178 (not liece-crypt-mode-active)
179 liece-crypt-mode-active)
183 (_ "Encrypt message with key [RET for none]: ")
185 liece-crypt-encryption-keys))))))
186 (liece-enter-message arg (if (string-equal key "") nil key)))
188 (defun liece-dialogue-enter-message ()
189 "Ask for a line as an entry in the IRC dialogue on the current channel."
192 (while (not (string-equal (setq message (read-string "> ")) ""))
193 (liece-command-send-message message))))
195 (defun liece-command-inline ()
196 "Send current line as a message to the IRC server."
199 (liece-send (buffer-substring (point)(progn (end-of-line) (point))))
202 (defun liece-command-join-channel (join-channel-var key)
203 "Join a JOIN-CHANNEL-VAR with KEY."
204 (let ((nicks liece-nick-alist) nick)
208 (liece-channel-equal join-channel-var (car nick)))))
209 (setq nick (pop nicks)))
211 (setq join-channel-var
212 (or (car (get (intern (car nick) liece-obarray) 'chnl))
214 (if (liece-channel-member join-channel-var liece-current-channels)
216 (setq liece-current-channel join-channel-var)
217 (liece-switch-to-channel liece-current-channel)
218 (liece-channel-change))
219 (liece-send "JOIN %s %s" (liece-channel-real join-channel-var) key))))
221 (defun liece-command-join-partner (join-channel-var)
222 "Join a JOIN-CHANNEL-VAR."
223 (if (liece-channel-member join-channel-var liece-current-chat-partners)
225 (setq liece-current-chat-partner join-channel-var)
226 (liece-switch-to-channel liece-current-chat-partner))
227 (setq liece-current-chat-partner join-channel-var)
228 (liece-channel-join liece-current-chat-partner))
229 (liece-channel-change))
231 (defun liece-command-join (join-channel-var &optional key)
232 "Join a JOIN-CHANNEL-VAR with KEY.
233 If user nickname is given join the same set of channels as the specified user.
234 If command-buffer is in chat-mode, start private conversation
235 with specified user."
237 (let (join-channel-var key (completion-ignore-case t))
238 (setq join-channel-var
239 (if (numberp current-prefix-arg)
241 (liece-channel-virtual
242 (if (eq liece-command-buffer-mode 'chat)
243 (liece-minibuffer-completing-default-read
244 (_ "Start private conversation with: ")
246 nil nil liece-privmsg-partner)
247 (liece-minibuffer-completing-default-read
249 (append liece-channel-alist liece-nick-alist)
250 nil nil liece-default-channel-candidate)))))
251 (if (and current-prefix-arg
252 (not (numberp current-prefix-arg)))
254 (if (eq current-prefix-arg '-)
256 (format (_ "Key for channel %s: ") join-channel-var))
257 (let ((passwd-echo ?*))
259 (format (_ "Key for channel %s: ") join-channel-var))))))
260 (list join-channel-var key)))
261 (let ((real-chnl (liece-channel-real join-channel-var)))
262 (if (numberp join-channel-var)
263 (liece-switch-to-channel-no join-channel-var)
264 (setq liece-default-channel-candidate nil)
265 (if (liece-channel-p real-chnl)
266 (liece-toggle-command-buffer-mode 'channel)
267 (liece-toggle-command-buffer-mode 'chat))
268 (if (eq liece-command-buffer-mode 'chat)
269 (liece-command-join-partner join-channel-var)
271 (setq key (get (intern join-channel-var liece-obarray) 'key)))
272 (put (intern join-channel-var liece-obarray) 'key key)
275 (liece-command-join-channel join-channel-var key))
276 (force-mode-line-update))))
278 (defun liece-command-part (part-channel-var &optional part-msg)
279 "Part a PART-CHANNEL-VAR with PART-MSG."
281 (let (part-channel-var
282 (completion-ignore-case t)
284 (setq part-channel-var
285 (liece-channel-virtual
286 (if (eq liece-command-buffer-mode 'chat)
287 (liece-minibuffer-completing-default-read
288 (_ "End private conversation with: ")
289 (list-to-alist liece-current-chat-partners)
290 nil nil liece-current-chat-partner)
291 (liece-minibuffer-completing-default-read
293 (list-to-alist liece-current-channels)
294 nil nil liece-current-channel))))
295 (when current-prefix-arg
296 (setq part-msg (read-string (_ "Part Message: "))))
297 (list part-channel-var part-msg)))
298 (let ((real-chnl (liece-channel-real part-channel-var)))
299 (if (liece-channel-p real-chnl)
301 (if (liece-channel-member part-channel-var liece-current-channels)
302 (setq liece-current-channel part-channel-var))
303 (liece-send "PART %s :%s" real-chnl part-msg)
304 (setq liece-default-channel-candidate part-channel-var))
305 (setq liece-current-chat-partners
306 (liece-channel-remove part-channel-var
307 liece-current-chat-partners)
308 liece-current-chat-partner
309 (car liece-current-chat-partners))
310 (liece-set-channel-indicator)
311 (liece-set-crypt-indicator)
312 (liece-channel-part part-channel-var))))
314 (defun liece-command-kill (kill-nickname-var &optional timeout silent)
315 "Ignore messages from KILL-NICKNAME-VAR.
316 Username can be given as case insensitive regular expression of form
317 \".*@.*\.sub.domain\".
318 If already ignoring him/her, toggle.
319 If `liece-variables-file' is defined and the file is writable,
320 settings are updated automatically for future sessions.
321 Optional argument TIMEOUT says expiration.
322 If SILENT is non-nil, don't notify current status."
324 (let (kill-nickname-var timeout (completion-ignore-case t))
325 (setq kill-nickname-var (completing-read
326 (_ "Ignore nickname or regexp: ")
327 (append liece-nick-alist
328 liece-kill-nickname)))
329 (or (string-equal "" kill-nickname-var)
330 (string-assoc-ignore-case kill-nickname-var liece-kill-nickname)
331 (setq timeout (string-to-int (read-from-minibuffer
332 (_ "Timeout [RET for none]: ")))))
333 (list kill-nickname-var timeout)))
334 ;; empty, just list them
335 (if (string-equal "" kill-nickname-var)
336 (with-current-buffer liece-dialogue-buffer
337 (let ((ignores liece-kill-nickname) (time (current-time))
338 buffer-read-only expire expiretime)
339 (goto-char (point-max))
340 (liece-insert-info liece-D-buffer (_ "Currently ignoring:"))
341 (dolist (ignore ignores)
342 (setq expiretime (if (cdr ignore)
343 (/ (liece-time-difference time (cdr ignore))
345 expire (cond ((not expiretime) "")
347 (format (_ " (%d min)") expiretime))
350 (liece-insert liece-D-buffer
351 (concat " " (car ignore) expire "\n")))))
352 ;; else not empty, check if exists
354 (string-assoc-ignore-case
355 kill-nickname-var liece-kill-nickname)))
357 (when (setq ignore (string-assoc-ignore-case
358 (car ignore) liece-kill-nickname))
359 (setq liece-kill-nickname
360 (delq ignore liece-kill-nickname))
361 (liece-insert-info liece-D-buffer
362 (format (_ "No longer ignoring: %s.\n")
364 ;; did not find, add to ignored ones
365 (let ((expire-time (if (> timeout 0)
366 (liece-time-add (current-time)
368 (and silent (> timeout 0)
369 (setcar (cdr (cdr expire-time)) -1))
370 (setq liece-kill-nickname
371 (cons (cons kill-nickname-var expire-time)
372 liece-kill-nickname))
374 (liece-insert-info liece-D-buffer
375 (format (_ "Ignoring %s") kill-nickname-var))
376 (liece-insert-info liece-D-buffer
378 (format " for %d minutes.\n" timeout)
380 (setq liece-save-variables-are-dirty t)))
382 (defun liece-command-kick (nick &optional msg)
383 "Kick this NICK out with MSG."
385 (let ((completion-ignore-case t)
386 (nicks (liece-channel-get-nicks)) nick msg)
387 (setq nick (completing-read
388 (_ "Kick out nickname: ")
389 (list-to-alist nicks)))
390 (if current-prefix-arg
391 (setq msg (concat " :" (read-string (_ "Kick Message: ")))))
393 (liece-send "KICK %s %s%s"
394 (liece-channel-real liece-current-channel)
397 (defun liece-command-ban (ban)
400 (let* ((completion-ignore-case t)
401 (nicks (liece-channel-get-nicks))
406 (concat nick "!" (liece-nick-get-user-at-host nick)))))
409 (setq ban (liece-minibuffer-completing-default-read
410 (_ "Ban pattern: ") uahs nil nil
411 (concat nick "!" (liece-nick-get-user-at-host nick))))
413 (liece-send "MODE %s :+b %s"
414 (liece-channel-real liece-current-channel) ban))
416 (defun liece-command-ban-kick (ban nick &optional msg)
417 "BAN kick this NICK out with MSG."
419 (let* ((completion-ignore-case t)
420 (nicks (liece-channel-get-nicks))
425 (concat nick "!" (liece-nick-get-user-at-host nick)))))
428 (setq nick (completing-read (_ "Kick out nickname: ")
429 (list-to-alist nicks))
430 ban (liece-minibuffer-completing-default-read
431 (_ "Ban pattern: ") uahs nil nil
432 (concat nick "!" (liece-nick-get-user-at-host nick))))
433 (if current-prefix-arg
434 (setq msg (concat " :" (read-string (_ "Kick Message: "))))
436 (list ban nick msg)))
437 (liece-send "MODE %s :+b %s"
438 (liece-channel-real liece-current-channel) ban)
439 (liece-send "KICK %s %s%s"
440 (liece-channel-real liece-current-channel)
443 (defun liece-command-list (&optional channel)
444 "List the given CHANNEL and its topics.
445 If you enter only Control-U as argument, list the current channel.
446 With - as argument, list all channels."
448 (if (or current-prefix-arg (null liece-current-channel))
449 (if (eq current-prefix-arg '-)
450 (list current-prefix-arg))
451 (let ((completion-ignore-case t) channel)
452 (setq channel (liece-minibuffer-completing-default-read
454 liece-channel-alist nil nil liece-current-channel))
455 (unless (string-equal "" channel)
459 (if liece-current-channel
460 (liece-send "LIST %s"
461 (liece-channel-real liece-current-channel))))
462 ((and (eq channel '-)
463 (y-or-n-p (_ "Do you really query LIST without argument?")))
465 ((not (string-equal channel ""))
466 (liece-send "LIST %s" (liece-channel-real channel))
469 (defun liece-command-lusers ()
470 "List the number of users and servers."
472 (liece-send "LUSERS"))
474 (defun liece-command-modec (chnl change)
475 "Send a MODE command to this CHNL.
478 (let ((completion-ignore-case t)
479 (chnl liece-current-channel)
480 liece-minibuffer-complete-function prompt)
481 (if current-prefix-arg
483 (liece-minibuffer-completing-default-read
485 (append liece-channel-alist liece-nick-alist)
486 nil nil liece-current-channel)))
488 ((liece-channel-p (liece-channel-real chnl))
490 (_ "Mode for channel %s [%s]: ")
491 chnl (or (liece-channel-get-modes chnl) ""))
492 liece-minibuffer-complete-function
493 (function liece-minibuffer-complete-channel-modes)))
496 (_ "Mode for user %s [%s]: ")
497 chnl (or (liece-nick-get-modes chnl) ""))
498 liece-minibuffer-complete-function
499 (function liece-minibuffer-complete-user-modes))))
500 (list chnl (read-from-minibuffer prompt nil liece-minibuffer-map))))
501 (liece-send "MODE %s %s" (liece-channel-real chnl) change))
503 (defun liece-command-mode+o (opers)
504 "Send a MODE +o OPERS command."
506 (let ((opers (liece-channel-get-operators)) oper
507 (nicks (liece-channel-get-nicks))
508 (completion-ignore-case t))
509 (setq nicks (filter-elements
511 (not (liece-nick-member nick opers)))
512 opers (liece-minibuffer-completing-sequential-read
513 (_ "Set Operator for") 0
514 (list-to-alist nicks)))
519 (when (= (length ops) liece-compress-mode-length)
520 (liece-send "MODE %s +%s %s"
521 (liece-channel-real liece-current-channel)
522 (string-times "o" liece-compress-mode-length)
523 (string-join ops " "))
526 (liece-send "MODE %s +%s %s"
527 (liece-channel-real liece-current-channel)
528 (string-times "o" (length ops))
529 (string-join ops " ")))))
531 (defun liece-command-mode-o (opers)
532 "Send a MODE -o OPERS command."
534 (let ((completion-ignore-case t)
535 (opers (liece-channel-get-operators)) oper nicks)
536 (setq nicks (liece-minibuffer-completing-sequential-read
537 (_ "Unset Operator for") 0
538 (list-to-alist opers)))
543 (when (= (length ops) liece-compress-mode-length)
544 (liece-send "MODE %s -%s %s"
545 (liece-channel-real liece-current-channel)
546 (string-times "o" liece-compress-mode-length)
547 (string-join ops " "))
550 (liece-send "MODE %s -%s %s"
551 (liece-channel-real liece-current-channel)
552 (string-times "o" (length ops))
553 (string-join ops " ")))))
555 (defun liece-command-mode+v (voices)
556 "Send a MODE +v VOICES command."
558 (let ((voices (append (liece-channel-get-voices)
559 (liece-channel-get-operators)))
561 (nicks (liece-channel-get-nicks))
562 (completion-ignore-case t)
564 (setq nicks (filter-elements nick nicks
565 (not (string-assoc-ignore-case nick voices)))
566 voices (liece-minibuffer-completing-sequential-read
567 (_ "Set Voice for") 0 (list-to-alist nicks)))
570 (dolist (voice voices)
572 (when (= (length vcs) liece-compress-mode-length)
573 (liece-send "MODE %s +%s %s"
574 (liece-channel-real liece-current-channel)
575 (string-times "v" liece-compress-mode-length)
576 (string-join vcs " "))
579 (liece-send "MODE %s +%s %s"
580 (liece-channel-real liece-current-channel)
581 (string-times "v" (length vcs))
582 (string-join vcs " ")))))
584 (defun liece-command-mode-v (voices)
585 "Send a MODE -v VOICES command."
587 (let ((completion-ignore-case t)
588 (voices (liece-channel-get-voices)) voice nicks)
589 (setq nicks (liece-minibuffer-completing-sequential-read
590 (_ "Unset Voice for") 0 (list-to-alist voices)))
593 (dolist (voice voices)
595 (when (= (length vcs) liece-compress-mode-length)
596 (liece-send "MODE %s -%s %s"
597 (liece-channel-real liece-current-channel)
598 (string-times "v" liece-compress-mode-length)
599 (string-join vcs " "))
602 (liece-send "MODE %s -%s %s"
603 (liece-channel-real liece-current-channel)
604 (string-times "v" (length vcs))
605 (string-join vcs " ")))))
607 (defun liece-command-message (address message &optional arg key)
608 "Send ADDRESS a private MESSAGE.
609 If argument ARG is non-nil message will be encrypted with KEY."
611 (let ((completion-ignore-case t) address)
613 (liece-channel-virtual
614 (liece-minibuffer-completing-default-read
615 (_ "Private message to: ")
616 (append liece-nick-alist liece-channel-alist)
617 nil nil liece-privmsg-partner)))
621 (_ "Private message to %s: ")
623 (if current-prefix-arg
624 (not liece-crypt-mode-active)
625 liece-crypt-mode-active)
627 (if (funcall liece-message-empty-predicate message)
628 (progn (liece-message (_ "No text to send")) nil)
629 (let ((chnl (liece-channel-real address)) (msg message))
630 (with-liece-encryption (msg address arg key)
631 (liece-send "PRIVMSG %s :%s" chnl msg)
632 (if (liece-channel-p chnl)
633 (liece-own-channel-message message
634 (liece-channel-virtual address))
635 (liece-own-private-message message address)))
638 ;; Added at mta@tut.fi's request...
639 ;; Does not support encryption (yet!?)
641 (defun liece-command-mta-private (partner)
642 "Send a private message (current line) to PARTNER."
644 (let ((completion-ignore-case t))
645 (setq liece-privmsg-partner
646 (liece-channel-virtual
647 (liece-minibuffer-completing-default-read
649 (append liece-nick-alist liece-channel-alist)
650 nil nil liece-privmsg-partner)))
651 (list liece-privmsg-partner)))
652 (let ((message (buffer-substring (progn (beginning-of-line) (point))
653 (progn (end-of-line) (point)))))
654 (if (> (length message) 0)
656 (liece-command-message liece-privmsg-partner message)
658 (liece-message (_ "No text to send")))))
660 (defun liece-command-names (&optional channel)
661 "List the nicknames of the current IRC users on given CHANNEL.
662 With an Control-U as argument, only the current channel is listed.
663 With - as argument, list all channels."
665 (if (or current-prefix-arg (null liece-current-channel))
666 (if (eq current-prefix-arg '-)
667 (list current-prefix-arg))
668 (let ((completion-ignore-case t) channel)
669 (setq channel (liece-minibuffer-completing-default-read
670 (_ "Names on channel: ")
671 liece-channel-alist nil nil liece-current-channel))
672 (unless (string-equal "" channel)
676 (liece-send "NAMES %s"
677 (liece-channel-real liece-current-channel)))
678 ((and (eq channel '-)
679 (y-or-n-p (_ "Do you really query NAMES without argument?")))
680 (liece-send "NAMES"))
682 (liece-send "NAMES %s" (liece-channel-real channel)))))
684 (defun liece-command-nickname (nick)
685 "Set your nickname to NICK."
686 (interactive "sEnter your nickname: ")
687 (let ((nickname (truncate-string nick liece-nick-max-length)))
688 (if (zerop (length nickname))
689 (liece-message (_ "illegal nickname \"%s\"; not changed") nickname)
690 (liece-send "NICK %s" nick))))
692 (defun liece-command-who (&optional expr)
693 "Lists tue users that match the given expression EXPR.
694 If you enter only Control-U as argument, list the current channel.
695 With - as argument, list all users."
697 (if (or current-prefix-arg (null liece-current-channel))
698 (if (eq current-prefix-arg '-)
699 (list current-prefix-arg))
700 (let ((completion-ignore-case t) expr)
701 (setq expr (liece-minibuffer-completing-default-read
702 (_ "WHO expression: ")
703 (append liece-channel-alist liece-nick-alist)))
704 (unless (string-equal "" expr)
708 (liece-send "WHO %s" (liece-channel-real liece-current-channel)))
710 (y-or-n-p (_ "Do you really query WHO without argument?")))
713 (liece-send "WHO %s" expr)
714 (setq liece-who-expression expr))))
716 (defun liece-command-finger (finger-nick-var &optional server)
717 "Get information about a specific user FINGER-NICK-VAR.
718 If called with optional argument SERVER or any prefix argument,
719 query information to the foreign server."
721 (let (finger-nick-var (completion-ignore-case t))
722 (setq finger-nick-var
723 (completing-read (_ "Finger whom: ") liece-nick-alist))
724 (list finger-nick-var (and current-prefix-arg finger-nick-var))))
726 (liece-send "WHOIS %s %s" server finger-nick-var)
727 (liece-send "WHOIS %s" finger-nick-var)))
729 (defun liece-command-topic (topic)
730 "Change TOPIC of the current channel."
732 (list (read-from-minibuffer
733 "Topic: " (cons (or (liece-channel-get-topic) "") 0))))
734 (liece-send "TOPIC %s :%s"
735 (liece-channel-real liece-current-channel) topic))
737 (defun liece-command-invite (&optional invite-nick-var invite-channel-var)
738 "Invite INVITE-NICK-VAR to INVITE-CHANNEL-VAR."
740 (let ((completion-ignore-case t) invite-channel-var invite-nick-var)
741 (if current-prefix-arg
742 (setq invite-channel-var
743 (liece-channel-virtual
745 (_ "Invite channel: ")
746 (list-to-alist liece-current-channels)))))
747 (setq invite-nick-var
751 (list invite-nick-var invite-channel-var)))
752 (or invite-channel-var
753 (setq invite-channel-var liece-current-channel))
754 (liece-send "INVITE %s %s"
755 invite-nick-var (liece-channel-real invite-channel-var)))
757 (defun liece-command-away (awaymsg)
758 "Mark/unmark yourself as being away.
759 Leave message AWAYMSG."
760 (interactive "sAway message: ")
761 (liece-send "AWAY :%s" awaymsg)
762 (setq liece-away-message awaymsg))
764 (defun liece-command-scroll-down (lines)
765 "Scroll LINES down dialogue buffer from command buffer."
767 (let ((other-window-scroll-buffer
768 (if liece-channel-buffer-mode
770 liece-dialogue-buffer)))
771 (when (liece-get-buffer-window other-window-scroll-buffer)
773 (scroll-other-window-down lines)
775 (message "Beginning of buffer"))))))
777 (defun liece-command-scroll-up (lines)
778 "Scroll LINES up dialogue buffer from command buffer."
780 (let* ((other-window-scroll-buffer
781 (if liece-channel-buffer-mode
783 liece-dialogue-buffer)))
784 (when (liece-get-buffer-window other-window-scroll-buffer)
786 (scroll-other-window lines)
788 (message "End of buffer"))))))
790 (defun liece-command-nick-scroll-down (lines)
791 "Scroll LINES down nick buffer from command buffer."
793 (let ((other-window-scroll-buffer liece-nick-buffer))
794 (when (liece-get-buffer-window other-window-scroll-buffer)
796 (scroll-other-window-down lines)
798 (message "Beginning of buffer"))))))
800 (defun liece-command-nick-scroll-up (lines)
801 "Scroll LINES up nick buffer from command buffer."
803 (let* ((other-window-scroll-buffer liece-nick-buffer))
804 (when (liece-get-buffer-window other-window-scroll-buffer)
806 (scroll-other-window lines)
808 (message "End of buffer"))))))
810 (defun liece-command-toggle-crypt (&optional arg)
811 "Toggle crypt status.
812 If prefix argument ARG is non-nil, force set crypt status."
815 (setq liece-crypt-mode-active (prefix-numeric-value arg))
816 (if liece-crypt-mode-active
817 (setq liece-crypt-mode-active nil)
818 (setq liece-crypt-mode-active t)))
819 (liece-set-crypt-indicator)
820 (switch-to-buffer (current-buffer)))
822 (defun liece-command-freeze (&optional arg)
823 "Prevent automatic scrolling of the dialogue window.
824 If prefix argument ARG is non-nil, toggle frozen status."
826 (liece-freeze (if liece-channel-buffer-mode
828 liece-dialogue-buffer)
829 (if arg (prefix-numeric-value arg))))
831 (defun liece-command-own-freeze (&optional arg)
832 "Prevent automatic scrolling of the dialogue window.
833 The difference from `liece-command-freeze' is that your messages are hidden.
834 If prefix argument ARG is non-nil, toggle frozen status."
836 (liece-own-freeze (if liece-channel-buffer-mode
838 liece-dialogue-buffer)
839 (if arg (prefix-numeric-value arg))))
841 (defun liece-command-quit (&optional arg)
843 If prefix argument ARG is non-nil, leave signoff message."
845 (when (and (liece-server-opened)
846 (y-or-n-p (_ "Quit IRC? ")))
849 (if arg (read-string (_ "Signoff message: "))
850 (or liece-signoff-message
851 (product-name (product-find 'liece-version))))))
852 (liece-send "QUIT :%s" quit-string))
855 (if liece-save-variables-are-dirty
856 (liece-command-save-vars))
858 (liece-window-configuration-pop))
859 (run-hooks 'liece-exit-hook)))
861 (defun liece-command-generic (message)
862 "Enter a generic IRC MESSAGE, which is sent to the server.
863 A ? lists the useful generic messages."
864 (interactive "sIRC command (? to help): ")
865 (if (string-equal message "?")
866 (with-output-to-temp-buffer "*IRC Help*"
867 (princ "The following generic IRC messages may be of interest to you:
868 TOPIC <new topic> set the topic of your channel
869 INVITE <nickname> invite another user to join your channel
870 LINKS lists the currently reachable IRC servers
871 SUMMON <user@host> invites an user not currently in IRC
872 USERS <host> lists the users on a host
873 AWAY <reason> marks you as not really actively using IRC
874 (an empty reason clears it)
875 WALL <message> send to everyone on IRC
876 NAMES <channel> lists users per channel
878 (liece-send "%s" message)))
880 (defun liece-command-irc-compatible ()
881 "If entered at column 0, allow you to enter a generic IRC message."
883 (if (zerop (current-column))
884 (call-interactively (function liece-command-generic))
885 (self-insert-command 1)))
887 (defun liece-command-exec (command)
888 "Execute COMMAND, stdout to dialogue."
889 (interactive "sShell command: ")
890 (shell-command command t)
891 (let ((opoint (point)))
892 (while (< (point) (mark))
893 (liece-command-enter-message)
894 (set-buffer liece-command-buffer))
895 (push-mark opoint t)))
897 (defun liece-command-yank-send (&optional arg)
898 "Send message from yank buffer.
899 Prefix argument ARG is regarded as distance from yank pointer."
901 (when (y-or-n-p (_ "Really SEND from Yank Buffer?"))
903 (narrow-to-region (point) (point))
904 (insert (car kill-ring-yank-pointer))
905 (goto-char (point-min))
907 (liece-command-enter-message)
908 (set-buffer liece-command-buffer)))))
910 (defun liece-command-complete ()
911 "Complete word before point from userlist."
913 (let ((completion-ignore-case t)
914 (alist (if liece-current-channel
915 (list-to-alist (liece-channel-get-nicks))
917 candidate completion all)
918 (setq candidate (current-word)
919 completion (try-completion candidate alist)
920 all (all-completions candidate alist))
921 (liece-minibuffer-finalize-completion completion candidate all)))
923 (defun liece-command-load-vars ()
924 "Load configuration from liece-variables-file."
926 (let ((nick liece-real-nickname))
928 (liece-read-variables-files)
929 (setq liece-real-nickname nick)
930 (liece-command-reconfigure-windows))))
932 (defun liece-command-save-vars ()
933 "Save current settings to `liece-variables-file'."
935 (let* ((output-buffer
937 (expand-file-name liece-variables-file)))
940 (set-buffer output-buffer)
941 (goto-char (point-min))
942 (cond ((re-search-forward "^;; Saved Settings *\n" nil 'move)
943 (setq p (match-beginning 0))
945 (or (re-search-forward
946 "^;; End of Saved Settings *\\(\n\\|\\'\\)" nil t)
948 (concat "can't find END of saved state in "
949 liece-variables-file)))
950 (delete-region p (match-end 0)))
952 (goto-char (point-max))
954 (setq output-marker (point-marker))
955 (let ((print-readably t)
956 (print-escape-newlines t)
957 (standard-output output-marker))
958 (princ ";; Saved Settings\n")
959 (dolist (var liece-saved-forms)
961 (prin1 (list 'setq var
962 (let ((val (symbol-value var)))
963 (if (memq val '(t nil))
965 (list 'quote val)))))
966 (setq var (eval var))
967 (cond ((eq (car-safe var) 'progn)
968 (while (setq var (cdr var))
971 (if (cdr var) (princ " "))))
973 (prin1 "xx")(prin1 var))))
974 (if var (princ "\n")))
976 (princ ";; End of Saved Settings\n")))
977 (set-marker output-marker nil)
979 (set-buffer output-buffer)
981 (setq liece-save-variables-are-dirty nil))
983 (defun liece-command-reconfigure-windows ()
984 "Rearrange window splitting."
986 (let ((command-window (liece-get-buffer-window liece-command-buffer))
987 (dialogue-window (liece-get-buffer-window liece-dialogue-buffer))
988 (obuffer (current-buffer)))
989 (if (and command-window dialogue-window)
990 (let ((ch (window-height command-window))
991 (dh (window-height dialogue-window)))
992 (delete-window command-window)
993 (pop-to-buffer liece-dialogue-buffer)
994 (enlarge-window (+ ch dh (- dh))))
995 (pop-to-buffer liece-dialogue-buffer))
996 (liece-configure-windows)
997 (if liece-one-buffer-mode
998 (pop-to-buffer liece-dialogue-buffer)
999 (pop-to-buffer obuffer))))
1001 (defun liece-command-end-of-buffer ()
1002 "Get end of the dialogue buffer."
1004 (let (buffer window)
1005 (setq buffer (if liece-channel-buffer-mode
1006 liece-channel-buffer
1007 liece-dialogue-buffer))
1008 (or (setq window (liece-get-buffer-window buffer))
1009 (setq window (liece-get-buffer-window liece-dialogue-buffer)
1010 buffer liece-dialogue-buffer))
1012 (save-selected-window
1013 (select-window window)
1014 (goto-char (point-max))))))
1016 (defun liece-command-private-conversation (arg)
1017 "Toggle between private conversation mode and channel mode.
1018 User can then join and part to a private conversation as he would
1019 join or part to a channel.
1021 If there are no private conversations or argument is given user is
1022 prompted the partner/channel (return as partner/channel means toggle
1023 mode, the current channel and current chat partner are not altered)
1024 Argument ARG is prefix argument of toggle status."
1026 (let ((completion-ignore-case t))
1028 (if current-prefix-arg
1029 ;; prefixed, ask where to continue
1030 (if (eq liece-command-buffer-mode 'chat)
1031 (liece-minibuffer-completing-default-read
1032 (_ "Return to channel: ")
1033 (append liece-channel-alist liece-nick-alist)
1034 nil nil liece-current-channel)
1036 (_ "Start private conversation with: ")
1037 liece-nick-alist nil nil))
1038 ;; no prefix, see if going to chat
1039 (if (eq liece-command-buffer-mode 'channel)
1040 ;; and if we have chat partner, select that
1041 (if liece-current-chat-partner
1042 liece-current-chat-partner
1044 (_ "Start private conversation with: ")
1045 liece-nick-alist )))))))
1047 (liece-toggle-command-buffer-mode)
1048 (if (and arg (not (string-equal arg "")))
1049 (liece-command-join arg))
1050 (liece-set-channel-indicator)
1051 (liece-set-crypt-indicator)
1052 ;; refresh mode line
1053 (force-mode-line-update))
1055 (defun liece-command-next-channel ()
1056 "Select next channel or chat partner, and *DONT* rotate list."
1058 (let ((rest (copy-sequence
1059 (if (eq liece-command-buffer-mode 'chat)
1060 liece-current-chat-partners
1061 liece-current-channels)))
1062 (chnl (if (eq liece-command-buffer-mode 'chat)
1063 liece-current-chat-partner
1064 liece-current-channel)))
1065 (liece-switch-to-channel
1066 (or (cadr (liece-channel-member chnl (delq nil rest)))
1067 (car (delq nil rest))
1070 (defun liece-command-previous-channel ()
1071 "Select previous channel or chat partner, and *DONT* rotate list."
1075 (if (eq liece-command-buffer-mode 'chat)
1076 liece-current-chat-partners
1077 liece-current-channels)))
1079 (if (eq liece-command-buffer-mode 'chat)
1080 liece-current-chat-partner
1081 liece-current-channel)))
1082 (liece-switch-to-channel
1083 (or (cadr (liece-channel-member chnl (delq nil rest)))
1084 (car (delq nil rest))
1087 (defun liece-command-push ()
1088 "Select next channel or chat partner, and rotate list."
1091 (if (eq liece-command-buffer-mode 'chat)
1092 liece-current-chat-partners
1093 liece-current-channels))
1094 (temp (car (last rest)))
1095 (len (length rest)))
1098 (setcar (nthcdr (1- len) rest) (nth (- len 2) rest))
1101 (setcar rest temp)))
1102 (liece-channel-change)))
1104 (defun liece-command-pop ()
1105 "Select previous channel or chat partner, and rotate list."
1108 (if (eq liece-command-buffer-mode 'chat)
1109 liece-current-chat-partners
1110 liece-current-channels))
1112 (len (length rest)))
1115 (setcar (nthcdr i rest) (nth (1+ i) rest)))
1117 (setcar (last rest) temp)))
1118 (liece-channel-change)))
1120 (defvar liece-redisplay-buffer-functions
1121 '(liece-channel-redisplay-buffer
1122 liece-nick-redisplay-buffer
1123 liece-channel-list-redisplay-buffer))
1125 (defun liece-switch-to-channel (chnl)
1126 "Switch the current channel to CHNL."
1127 (if (liece-channel-p (liece-channel-real chnl))
1129 (liece-toggle-command-buffer-mode 'channel)
1130 (setq liece-current-channel chnl)
1131 (liece-set-channel-indicator))
1132 (liece-toggle-command-buffer-mode 'chat)
1133 (setq liece-current-chat-partner chnl)
1134 (liece-set-channel-indicator))
1136 (run-hook-with-args 'liece-redisplay-buffer-functions chnl))
1137 (liece-set-crypt-indicator)
1140 (defun liece-switch-to-channel-no (num)
1141 "Switch the current channel to NUM."
1142 (let* ((mode liece-command-buffer-mode)
1143 (chnls (if (eq mode 'chat)
1144 liece-current-chat-partners
1145 liece-current-channels)))
1146 (if (and (integerp num)
1147 (stringp (nth num chnls)))
1148 (let ((chnl (nth num chnls)))
1151 (liece-toggle-command-buffer-mode 'chat)
1152 (setq liece-current-chat-partner chnl)
1153 (liece-set-channel-indicator))
1154 (liece-toggle-command-buffer-mode 'channel)
1155 (setq liece-current-channel chnl)
1156 (liece-set-channel-indicator))
1158 (run-hook-with-args 'liece-redisplay-buffer-functions chnl))
1159 (liece-set-crypt-indicator)
1161 (message "Invalid channel!")
1164 (defun liece-command-ping ()
1165 "Send PING to server."
1167 (if (stringp liece-server-name)
1168 (liece-send "PING %s" liece-server-name)))
1170 (defun liece-command-ison (nicks)
1173 (let (nicks (completion-ignore-case t))
1174 (setq nicks (liece-minibuffer-completing-sequential-read
1175 "IsON" 0 liece-nick-alist))
1177 (liece-send "ISON :%s" (mapconcat #'identity nicks " ")))
1179 (defun liece-command-activate-friends (nicks)
1180 "Register NICKS to the frinends list."
1182 (let (nicks (completion-ignore-case t))
1184 (liece-minibuffer-completing-sequential-read
1186 (filter-elements nick liece-nick-alist
1187 (not (string-list-member-ignore-case
1188 (car nick) liece-friends)))))
1190 (setq liece-friends (append nicks liece-friends)))
1192 (defun liece-command-deactivate-friends ()
1193 "Clear current friends list."
1195 (setq liece-friends nil))
1197 (defun liece-command-display-friends ()
1198 "Display status of the friends."
1200 (with-output-to-temp-buffer " *IRC Friends*"
1201 (set-buffer standard-output)
1202 (insert "Friends status: \n\n")
1203 (dolist (friend liece-friends)
1204 (if (string-list-member-ignore-case friend liece-friends-last)
1205 (insert "+ " friend "\n")
1206 (insert "- " friend "\n")))))
1208 (defun liece-command-userhost (nicks)
1209 "Ask for the hostnames of NICKS."
1211 (let (nicks (completion-ignore-case t))
1212 (setq nicks (liece-minibuffer-completing-sequential-read
1213 (_ "Userhost nick") 0
1214 (list-to-alist liece-nick-alist)))
1216 (liece-send "USERHOST :%s" (mapconcat 'identity nicks ",")))
1218 (defun liece-command-show-last-kill ()
1219 "Dig last kill from KILL and show it."
1222 (append liece-D-buffer liece-O-buffer)
1224 (set-buffer liece-KILLS-buffer)
1225 (goto-char (point-max))
1227 (concat (buffer-substring (point) (point-max)) "\n"))))
1229 (defun liece-command-toggle-private ()
1230 "Toggle private mode / channel mode."
1232 (case (prog1 liece-command-buffer-mode
1233 (liece-toggle-command-buffer-mode))
1235 (if liece-current-channel
1236 (liece-switch-to-channel liece-current-channel))
1237 (setq liece-command-buffer-mode-indicator "Channels"))
1239 (if liece-current-chat-partner
1240 (liece-switch-to-channel liece-current-chat-partner))
1241 (setq liece-command-buffer-mode-indicator "Partners")))
1242 (liece-channel-change))
1244 (defun liece-command-tag-region (start end)
1245 "Move current region between START and END to `kill-ring'."
1247 (if (region-active-p)
1248 (list (region-beginning)(region-end))
1249 (list (line-beginning-position)(line-end-position))))
1250 (static-if (fboundp 'extent-property)
1251 (kill-ring-save start end)
1252 (let ((start (set-marker (make-marker) start))
1253 (end (set-marker (make-marker) end))
1254 (inhibit-read-only t)
1257 (liece-remove-properties-region start end)
1258 (kill-ring-save start end)
1259 (push nil buffer-undo-list)
1262 (provide 'liece-commands)
1264 ;;; liece-commands.el ends here