* riece-addon.el (riece-command-list-addons): Adjust width of 2nd
[riece] / lisp / riece-commands.el
1 ;;; riece-commands.el --- commands available in command buffer
2 ;; Copyright (C) 1998-2003 Daiki Ueno
3
4 ;; Author: Daiki Ueno <ueno@unixuser.org>
5 ;; Created: 1998-09-28
6 ;; Keywords: IRC, riece
7
8 ;; This file is part of Riece.
9
10 ;; This program is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
13 ;; any later version.
14
15 ;; This program is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 ;; GNU General Public License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
24
25 ;;; Code:
26
27 (require 'riece-channel)
28 (require 'riece-complete)
29 (require 'riece-layout)
30 (require 'riece-display)
31 (require 'riece-server)
32 (require 'riece-misc)
33 (require 'riece-identity)
34 (require 'riece-message)
35
36 (autoload 'derived-mode-class "derived")
37
38 ;;; Channel movement:
39 (defun riece-command-switch-to-channel (channel)
40   (interactive (list (riece-completing-read-identity
41                       "Switch to channel/user: "
42                       riece-current-channels nil t)))
43   (unless (equal channel riece-current-channel)
44     (riece-switch-to-channel channel)))
45
46 (defun riece-command-switch-to-channel-by-number (number)
47   (interactive
48    (let ((command-name (symbol-name this-command)))
49      (if (string-match "[0-9]+$" command-name)
50          (list (string-to-number (match-string 0 command-name)))
51        (list (string-to-number (read-string "Switch to number: "))))))
52   (let ((channel (nth (1- number) riece-current-channels)))
53     (if channel
54         (riece-command-switch-to-channel channel)
55       (error "No such number!"))))
56
57 (eval-and-compile
58   (let ((number 1))
59     (while (<= number 20)
60       (defalias (intern (concat "riece-command-switch-to-channel-by-number-"
61                                 (number-to-string number)))
62         'riece-command-switch-to-channel-by-number)
63       (setq number (1+ number)))))
64
65 (defun riece-command-next-channel ()
66   "Select the next channel."
67   (interactive)
68   (when (> (length riece-current-channels) 1)
69     (let ((pointer (cdr (riece-identity-member
70                          riece-current-channel
71                          riece-current-channels))))
72       (while (and pointer
73                   (null (car pointer)))
74         (setq pointer (cdr pointer)))
75       (when (null pointer)
76         (setq pointer riece-current-channels)
77         (while (and pointer
78                     (null (car pointer)))
79           (setq pointer (cdr pointer))))
80       (if (car pointer)
81           (riece-command-switch-to-channel (car pointer))
82         (error "No such channel!")))))
83
84 (defun riece-command-previous-channel ()
85   "Select the previous channel."
86   (interactive)
87   (when (> (length riece-current-channels) 1)
88     (let ((pointer (riece-identity-member
89                     riece-current-channel
90                     riece-current-channels))
91           (start riece-current-channels)
92           channel)
93       (while (and start (not (eq start pointer)))
94         (if (car start)
95             (setq channel (car start)))
96         (setq start (cdr start)))
97       (when (null channel)
98         (setq start (copy-sequence riece-current-channels))
99         (setq start (delq nil start))
100         (and (> (length start) 1)
101              (setq channel (nth (1- (length start)) start))))
102       (if channel
103           (riece-command-switch-to-channel channel)
104         (error "No such channel!")))))
105
106 (defun riece-command-select-command-buffer ()
107   "Select the command buffer."
108   (interactive)
109   (let ((window (get-buffer-window riece-command-buffer)))
110     (if window
111         (select-window window))))
112
113 (defun riece-command-configure-windows ()
114   (interactive)
115   "Reconfigure windows with the current layout."
116   (riece-redisplay-buffers t))
117
118 (defun riece-command-suspend-resume ()
119   (interactive)
120   "Save or restore the current window configuration."
121   (let ((entry (assq 'riece-window-configuration (frame-parameters))))
122     (modify-frame-parameters (selected-frame)
123                              (list (cons 'riece-window-configuration
124                                          (current-window-configuration))))
125     (if (cdr entry)
126         (set-window-configuration (cdr entry))
127       (delete-other-windows))
128     (message
129      (substitute-command-keys
130       "\\[riece-command-suspend-resume] to get back the last windows"))))
131
132 (defun riece-command-change-layout (name)
133   "Select a layout-name from all current available layouts and change
134 the layout to the selected layout-name."
135   (interactive (list (completing-read "Change layout: " riece-layout-alist)))
136   (setq riece-layout name
137         riece-save-variables-are-dirty t)
138   (riece-command-configure-windows))
139
140 (defun riece-command-toggle-channel-buffer-mode ()
141   (interactive)
142   (setq riece-channel-buffer-mode
143         (not riece-channel-buffer-mode)
144         riece-save-variables-are-dirty t)
145   (riece-command-configure-windows))
146
147 (defun riece-command-toggle-others-buffer-mode ()
148   (interactive)
149   (setq riece-others-buffer-mode
150         (not riece-others-buffer-mode)
151         riece-save-variables-are-dirty t)
152   (riece-command-configure-windows))
153
154 (defun riece-command-toggle-user-list-buffer-mode ()
155   (interactive)
156   (setq riece-user-list-buffer-mode
157         (not riece-user-list-buffer-mode)
158         riece-save-variables-are-dirty t)
159   (riece-command-configure-windows))
160
161 (defun riece-command-toggle-channel-list-buffer-mode ()
162   (interactive)
163   (setq riece-channel-list-buffer-mode
164         (not riece-channel-list-buffer-mode)
165         riece-save-variables-are-dirty t)
166   (riece-command-configure-windows))
167
168 (defun riece-command-finger (user &optional recurse)
169   (interactive
170    (let* ((completion-ignore-case t)
171           (user (riece-completing-read-identity
172                  "Finger user: "
173                  (riece-get-users-on-server (riece-current-server-name))
174                  nil nil nil nil nil t)))
175      (list user current-prefix-arg)))
176   (if recurse
177       (riece-send-string (format "WHOIS %s %s\r\n"
178                                  (riece-identity-prefix user)
179                                  (riece-identity-prefix user)))
180     (riece-send-string (format "WHOIS %s\r\n" (riece-identity-prefix user)))))
181
182 (defun riece-command-topic (topic)
183   (interactive
184    (progn
185      (riece-check-channel-commands-are-usable t)
186      (list (read-from-minibuffer
187             "Set topic: " (cons (or (riece-with-server-buffer
188                                      (riece-identity-server
189                                       riece-current-channel)
190                                      (riece-channel-get-topic
191                                       (riece-identity-prefix
192                                        riece-current-channel)))
193                                     "")
194                                 0)))))
195   (riece-send-string (format "TOPIC %s :%s\r\n"
196                              (riece-identity-prefix riece-current-channel)
197                              topic)
198                      riece-current-channel))
199
200 (defun riece-command-invite (user)
201   (interactive
202    (let ((completion-ignore-case t))
203      (riece-check-channel-commands-are-usable t)
204      (list (riece-completing-read-identity
205             "Invite user: "
206             (riece-get-users-on-server (riece-current-server-name))
207             nil nil nil nil nil t))))
208   (riece-send-string (format "INVITE %s %s\r\n"
209                              (riece-identity-prefix user)
210                              (riece-identity-prefix riece-current-channel))))
211
212 (defun riece-command-kick (user &optional message)
213   (interactive
214    (let ((completion-ignore-case t))
215      (riece-check-channel-commands-are-usable t)
216      (list (completing-read
217             "Kick user: "
218             (riece-with-server-buffer
219                 (riece-identity-server riece-current-channel)
220               (riece-channel-get-users (riece-identity-prefix
221                                         riece-current-channel))))
222            (if current-prefix-arg
223                (read-string "Message: ")))))
224   (riece-send-string
225    (if message
226        (format "KICK %s %s :%s\r\n"
227                (riece-identity-prefix riece-current-channel)
228                user message)
229      (format "KICK %s %s\r\n"
230              (riece-identity-prefix riece-current-channel)
231              user))
232    riece-current-channel))
233
234 (defun riece-command-names (pattern)
235   (interactive
236    (let ((completion-ignore-case t))
237      (list (read-from-minibuffer
238             "NAMES pattern: "
239             (if (and riece-current-channel
240                      (riece-channel-p (riece-identity-prefix
241                                        riece-current-channel)))
242                 (cons (riece-identity-prefix riece-current-channel)
243                       0))))))
244   (if (or (not (equal pattern ""))
245           (yes-or-no-p "Really want to query NAMES without argument? "))
246       (riece-send-string (format "NAMES %s\r\n" pattern))))
247
248 (defun riece-command-who (pattern)
249   (interactive
250    (let ((completion-ignore-case t))
251      (list (read-from-minibuffer
252             "WHO pattern: "
253             (if (and riece-current-channel
254                      (riece-channel-p (riece-identity-prefix
255                                        riece-current-channel)))
256                 (cons (riece-identity-prefix riece-current-channel)
257                       0))))))
258   (if (or (not (equal pattern ""))
259           (yes-or-no-p "Really want to query WHO without argument? "))
260       (riece-send-string (format "WHO %s\r\n" pattern))))
261
262 (defun riece-command-list (pattern)
263   (interactive
264    (let ((completion-ignore-case t))
265      (list (read-from-minibuffer
266             "LIST pattern: "
267             (if (and riece-current-channel
268                      (riece-channel-p (riece-identity-prefix
269                                        riece-current-channel)))
270                 (cons (riece-identity-prefix riece-current-channel)
271                       0))))))
272   (if (or (not (equal pattern ""))
273           (yes-or-no-p "Really want to query LIST without argument? "))
274       (riece-send-string (format "LIST %s\r\n" pattern))))
275
276 (defun riece-command-change-mode (channel change)
277   (interactive
278    (let* ((completion-ignore-case t)
279           (channel
280            (if current-prefix-arg
281                (riece-completing-read-identity
282                 "Change mode for channel/user: "
283                 (riece-get-identities-on-server (riece-current-server-name))
284                 nil nil nil nil nil t)
285              (riece-check-channel-commands-are-usable t)
286              riece-current-channel))
287           (riece-overriding-server-name (riece-identity-server channel))
288           (riece-temp-minibuffer-message
289            (concat "[Available modes: "
290                    (riece-with-server-buffer (riece-identity-server channel)
291                      (if (riece-channel-p (riece-identity-prefix channel))
292                          (if riece-supported-channel-modes
293                              (apply #'string riece-supported-channel-modes))
294                        (if riece-supported-user-modes
295                            (apply #'string riece-supported-user-modes))))
296                    "]")))
297      (list channel
298            (read-from-minibuffer
299             (concat (riece-concat-channel-modes
300                      channel "Mode (? for help)") ": ")
301             nil riece-minibuffer-map))))
302   (if (equal change "")
303       (riece-send-string (format "MODE %s\r\n"
304                                  (riece-identity-prefix channel)))
305     (riece-send-string (format "MODE %s %s\r\n"
306                                (riece-identity-prefix channel)
307                                change))))
308
309 (defun riece-command-set-operators (users &optional arg)
310   (interactive
311    (progn
312      (riece-check-channel-commands-are-usable t)
313      (let ((completion-ignore-case t))
314        (list (riece-completing-read-multiple
315               (if current-prefix-arg
316                   "Unset +o for users"
317                 "Set +o for users")
318               (riece-with-server-buffer
319                   (riece-identity-server riece-current-channel)
320                 (riece-channel-get-users (riece-identity-prefix
321                                          riece-current-channel)))
322               (if current-prefix-arg
323                   (lambda (user)
324                     (memq ?o (cdr user)))
325                 (lambda (user)
326                   (not (memq ?o (cdr user))))))
327              current-prefix-arg))))
328   (let (group)
329     (while users
330       (setq group (cons (car users) group)
331             users (cdr users))
332       (when (or (= (length group) 3)
333                 (null users))
334         (riece-send-string
335          (format "MODE %s %c%s %s\r\n"
336                  (riece-identity-prefix riece-current-channel)
337                  (if current-prefix-arg
338                      ?-
339                    ?+)
340                  (make-string (length group) ?o)
341                  (mapconcat #'identity (nreverse group) " ")))
342         (setq group nil)))))
343
344 (defun riece-command-set-speakers (users &optional arg)
345   (interactive
346    (progn
347      (riece-check-channel-commands-are-usable t)
348      (let ((completion-ignore-case t))
349        (list (riece-completing-read-multiple
350               (if current-prefix-arg
351                   "Unset +v for users"
352                 "Set +v for users")
353               (riece-with-server-buffer
354                   (riece-identity-server riece-current-channel)
355                 (riece-channel-get-users (riece-identity-prefix
356                                           riece-current-channel)))
357               (if current-prefix-arg
358                   (lambda (user)
359                     (memq ?v (cdr user)))
360                 (lambda (user)
361                   (not (memq ?v (cdr user))))))
362              current-prefix-arg))))
363   (let (group)
364     (while users
365       (setq group (cons (car users) group)
366             users (cdr users))
367       (when (or (= (length group) 3)
368                 (null users))
369         (riece-send-string
370          (format "MODE %s %c%s %s\r\n"
371                  (riece-identity-prefix riece-current-channel)
372                  (if current-prefix-arg
373                      ?-
374                    ?+)
375                  (make-string (length group) ?v)
376                  (mapconcat #'identity (nreverse group) " ")))
377         (setq group nil)))))
378
379 (defun riece-command-send-message (message notice)
380   "Send MESSAGE to the current channel."
381   (run-hooks 'riece-command-send-message-hook)
382   (if (equal message "")
383       (error "No text to send"))
384   (riece-check-channel-commands-are-usable)
385   (if notice
386       (progn
387         (riece-send-string
388          (format "NOTICE %s :%s\r\n"
389                  (riece-identity-prefix riece-current-channel)
390                  message)
391          riece-current-channel)
392         (riece-display-message
393          (riece-make-message (riece-current-nickname) riece-current-channel
394                              message 'notice t)))
395     (riece-send-string
396      (format "PRIVMSG %s :%s\r\n"
397              (riece-identity-prefix riece-current-channel)
398              message)
399      riece-current-channel)
400     (riece-display-message
401      (riece-make-message (riece-current-nickname) riece-current-channel
402                          message nil t))))
403
404 (defun riece-command-enter-message ()
405   "Send the current line to the current channel."
406   (interactive)
407   (riece-command-send-message (buffer-substring
408                                (riece-line-beginning-position)
409                                (riece-line-end-position))
410                               nil)
411   (let ((next-line-add-newlines t))
412     (next-line 1)))
413
414 (defun riece-command-enter-message-as-notice ()
415   "Send the current line to the current channel as NOTICE."
416   (interactive)
417   (riece-command-send-message (buffer-substring
418                                (riece-line-beginning-position)
419                                (riece-line-end-position))
420                               t)
421   (let ((next-line-add-newlines t))
422     (next-line 1)))
423
424 (defun riece-command-enter-message-to-user (user)
425   "Send the current line to USER."
426   (interactive
427    (if (and (bolp) (eolp))
428        (error "No text to send")
429      (let ((completion-ignore-case t))
430        (list (riece-completing-read-identity
431               "Message to user: "
432               (riece-get-users-on-server (riece-current-server-name))
433               nil nil nil nil nil t)))))
434   (let ((text (buffer-substring
435                (riece-line-beginning-position)
436                (riece-line-end-position))))
437     (riece-send-string
438      (format "PRIVMSG %s :%s\r\n" (riece-identity-prefix user) text)
439      user)
440     (riece-display-message
441      (riece-make-message (riece-current-nickname) user text nil t)))
442   (let ((next-line-add-newlines t))
443     (next-line 1)))
444
445 (defun riece-command-join-channel (target key)
446   (let ((process (riece-server-process (riece-identity-server target))))
447     (unless process
448       (error "%s" (substitute-command-keys
449                    "Type \\[riece-command-open-server] to open server.")))
450     (riece-send-string (if key
451                            (format "JOIN %s :%s\r\n"
452                                    (riece-identity-prefix target)
453                                    key)
454                          (format "JOIN %s\r\n"
455                                  (riece-identity-prefix target)))
456                        target)))
457
458 (defun riece-command-join-partner (target)
459   (let ((pointer (riece-identity-member target riece-current-channels)))
460     (if pointer
461         (riece-command-switch-to-channel (car pointer))
462       (riece-join-channel target)
463       (riece-switch-to-channel target))))
464
465 (defun riece-command-join (target)
466   (interactive
467    (let ((completion-ignore-case t))
468      (list
469       (if riece-join-channel-candidate
470           (let ((default (riece-format-identity
471                           riece-join-channel-candidate)))
472             (riece-completing-read-identity
473              (format "Join channel/user (default %s): " default)
474              (riece-get-identities-on-server (riece-current-server-name))
475              nil nil nil nil default))
476         (riece-completing-read-identity
477          "Join channel/user: "
478          (riece-get-identities-on-server (riece-current-server-name)))))))
479   (let ((pointer (riece-identity-member target riece-current-channels)))
480     (if pointer
481         (riece-command-switch-to-channel (car pointer))
482       (if (riece-channel-p (riece-identity-prefix target))
483           (riece-command-join-channel target nil)
484         (riece-command-join-partner target)))))
485
486 (defun riece-command-part-channel (target message)
487   (let ((process (riece-server-process (riece-identity-server target))))
488     (riece-send-string (if message
489                            (format "PART %s :%s\r\n"
490                                    (riece-identity-prefix target)
491                                    message)
492                          (format "PART %s\r\n"
493                                  (riece-identity-prefix target)))
494                        target)))
495
496 (defun riece-command-part (target &optional message)
497   (interactive
498    (progn
499      (riece-check-channel-commands-are-usable)
500      (let* ((completion-ignore-case t)
501             (target
502              (riece-completing-read-identity
503               (format "Part from channel/user (default %s): "
504                       (riece-format-identity riece-current-channel))
505               riece-current-channels nil nil nil nil
506               (riece-format-identity riece-current-channel)))
507             (message
508              (if current-prefix-arg
509                  (read-string "Message: ")
510                riece-part-message)))
511        (list target message))))
512   (if (riece-identity-member target riece-current-channels)
513       (if (riece-channel-p (riece-identity-prefix target))
514           (riece-command-part-channel target message)
515         (riece-part-channel target))
516     (error "You are not talking with %s" target)))
517
518 (defun riece-command-change-nickname (nickname)
519   "Change your nickname to NICK."
520   (interactive "sEnter your nickname: ")
521   (riece-send-string (format "NICK %s\r\n" nickname)))
522
523 (defun riece-command-scroll-down (lines)
524   "Scroll LINES down dialogue buffer from command buffer."
525   (interactive "P")
526   (let ((buffer (if (and riece-channel-buffer-mode
527                          riece-current-channel)
528                     riece-channel-buffer
529                   riece-dialogue-buffer)))
530     (if (get-buffer-window buffer)
531         (condition-case nil
532             (let ((other-window-scroll-buffer buffer))
533               (scroll-other-window-down lines))
534           (beginning-of-buffer
535            (message "Beginning of buffer"))))))
536
537 (defun riece-command-scroll-up (lines)
538   "Scroll LINES up dialogue buffer from command buffer."
539   (interactive "P")
540   (let ((buffer (if (and riece-channel-buffer-mode
541                          riece-current-channel)
542                     riece-channel-buffer
543                   riece-dialogue-buffer)))
544     (if (get-buffer-window buffer)
545         (condition-case nil
546             (let ((other-window-scroll-buffer buffer))
547               (scroll-other-window lines))
548           (end-of-buffer
549            (message "End of buffer"))))))
550
551 (defun riece-command-user-list-scroll-down (lines)
552   "Scroll LINES down user list buffer from command buffer."
553   (interactive "P")
554   (if (get-buffer-window riece-user-list-buffer)
555       (condition-case nil
556           (let ((other-window-scroll-buffer riece-user-list-buffer))
557             (scroll-other-window-down lines))
558         (beginning-of-buffer
559          (message "Beginning of buffer")))))
560
561 (defun riece-command-user-list-scroll-up (lines)
562   "Scroll LINES up user list buffer from command buffer."
563   (interactive "P")
564   (if (get-buffer-window riece-user-list-buffer)
565       (condition-case nil
566           (let ((other-window-scroll-buffer riece-user-list-buffer))
567             (scroll-other-window lines))
568         (end-of-buffer
569          (message "End of buffer")))))
570
571 (defun riece-command-toggle-away (&optional message)
572   "Mark yourself as being away."
573   (interactive
574    (if (and (not (riece-with-server-buffer (riece-identity-server
575                                             (riece-current-nickname))
576                    (riece-user-get-away (riece-identity-prefix
577                                          (riece-current-nickname)))))
578             current-prefix-arg)
579        (list (read-from-minibuffer
580               "Away message: " (cons (or riece-away-message "") 0)))))
581   (if (riece-with-server-buffer (riece-identity-server
582                                  (riece-current-nickname))
583         (riece-user-get-away (riece-identity-prefix
584                               (riece-current-nickname))))
585       (riece-send-string "AWAY\r\n")
586     (riece-send-string (format "AWAY :%s\r\n" (or message
587                                                   riece-away-message)))))
588
589 (defun riece-command-toggle-freeze (&optional arg)
590   "Prevent automatic scrolling of the dialogue window.
591 If prefix argument ARG is non-nil, toggle frozen status."
592   (interactive "P")
593   (with-current-buffer (if (eq (derived-mode-class major-mode)
594                                'riece-dialogue-mode)
595                            (current-buffer)
596                          (if (and riece-channel-buffer-mode
597                                   riece-channel-buffer)
598                              riece-channel-buffer
599                            riece-dialogue-buffer))
600     (setq riece-freeze (if arg
601                            (< 0 (prefix-numeric-value arg))
602                          (not riece-freeze)))
603     (riece-emit-signal 'buffer-freeze-changed
604                        (current-buffer) riece-freeze)))
605
606 (defun riece-command-toggle-own-freeze (&optional arg)
607   "Prevent automatic scrolling of the dialogue window.
608 The difference from `riece-command-freeze' is that your messages are hidden.
609 If prefix argument ARG is non-nil, toggle frozen status."
610   (interactive "P")
611   (with-current-buffer (if (eq (derived-mode-class major-mode)
612                                'riece-dialogue-mode)
613                            (current-buffer)
614                          (if (and riece-channel-buffer-mode
615                                   riece-channel-buffer)
616                              riece-channel-buffer
617                            riece-dialogue-buffer))
618     (if (if arg
619             (< 0 (prefix-numeric-value arg))
620           (not (eq riece-freeze 'own)))
621         (setq riece-freeze 'own)
622       (setq riece-freeze nil))
623     (riece-emit-signal 'buffer-freeze-changed
624                        (current-buffer) riece-freeze)))
625
626 (eval-when-compile
627   (autoload 'riece-exit "riece"))
628 (defun riece-command-quit (&optional arg)
629   "Quit IRC."
630   (interactive "P")
631   (if (null riece-server-process-alist)
632       (progn
633         (message "No server process")
634         (ding))
635     (if (y-or-n-p "Really quit IRC? ")
636         (let ((message
637                (if arg
638                    (read-string "Message: ")
639                  riece-quit-message))
640               (alist riece-server-process-alist))
641           (while alist
642             (riece-quit-server-process (cdr (car alist)) message)
643             (setq alist (cdr alist)))))))
644
645 (defun riece-command-raw (command)
646   "Enter raw IRC command, which is sent to the server."
647   (interactive "sIRC command: ")
648   (riece-send-string (concat command "\r\n")))
649
650 (defun riece-command-beginning-of-buffer ()
651   "Scroll channel buffer to the beginning."
652   (interactive)
653   (let (buffer window)
654     (setq buffer (if riece-channel-buffer-mode
655                      riece-channel-buffer
656                    riece-dialogue-buffer))
657     (or (setq window (get-buffer-window buffer))
658         (setq window (get-buffer-window riece-dialogue-buffer)
659               buffer riece-dialogue-buffer))
660     (when window
661       (save-selected-window
662         (select-window window)
663         (goto-char (point-min))))))
664
665 (defun riece-command-end-of-buffer ()
666   "Scroll channel buffer to the end."
667   (interactive)
668   (let (buffer window)
669     (setq buffer (if riece-channel-buffer-mode
670                      riece-channel-buffer
671                    riece-dialogue-buffer))
672     (or (setq window (get-buffer-window buffer))
673         (setq window (get-buffer-window riece-dialogue-buffer)
674               buffer riece-dialogue-buffer))
675     (when window
676       (save-selected-window
677         (select-window window)
678         (goto-char (point-max))))))
679
680 (defun riece-command-copy-region (start end)
681   "Move current region between START and END to `kill-ring'."
682   (interactive "r")
683   (kill-new (buffer-substring-no-properties start end)))
684
685 (defun riece-command-complete-user ()
686   "Complete a user name in the current buffer."
687   (interactive)
688   (let* ((completion-ignore-case t)
689          (table (mapcar (lambda (user)
690                           (list (riece-format-identity user t)))
691                         (riece-get-users-on-server
692                          (riece-current-server-name))))
693          (current (or (current-word) ""))
694          (completion (try-completion current table))
695          (all (all-completions current table)))
696     (if (eq completion t)
697         nil
698       (if (null completion)
699           (message "Can't find completion for \"%s\"" current)
700         (if (equal current completion)
701             (with-output-to-temp-buffer "*Help*"
702               (display-completion-list all))
703           (re-search-forward "\\>" nil t)
704           (delete-region (point) (- (point) (length current)))
705           (insert completion))))))
706
707 (defun riece-command-open-server (server-name)
708   (interactive
709    (list (completing-read "Open server: " riece-server-alist)))
710   (if (riece-server-process server-name)
711       (error "%s is already opened" server-name))
712   (riece-open-server
713    (riece-server-name-to-server server-name)
714    server-name))
715
716 (defun riece-command-close-server (server-name &optional message)
717   (interactive
718    (list (completing-read "Close server: " riece-server-process-alist)
719          (if current-prefix-arg
720              (read-string "Message: ")
721            riece-quit-message)))
722   (riece-quit-server-process (riece-server-process server-name) message))
723
724 (defun riece-command-universal-server-name-argument ()
725   (interactive)
726   (let* ((riece-overriding-server-name
727           (completing-read "Server: " riece-server-process-alist))
728          (command
729           (key-binding (read-key-sequence
730                         (format "Command to execute on \"%s\":"
731                                 riece-overriding-server-name)))))
732     (message "")
733     (call-interactively command)))
734
735 (provide 'riece-commands)
736
737 ;;; riece-commands.el ends here