;;; liece-commands.el --- Interactive commands in command buffer. ;; Copyright (C) 1998-2000 Daiki Ueno ;; Author: Daiki Ueno ;; Created: 1998-09-28 ;; Revised: 1999-12-24 ;; Keywords: IRC, liece ;; This file is part of Liece. ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2, or (at your option) ;; any later version. ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. ;;; Commentary: ;; ;;; Code: (eval-when-compile (require 'liece-misc)) (require 'liece-channel) (require 'liece-nick) (require 'liece-coding) (require 'liece-intl) (require 'liece-minibuf) (autoload 'liece-dcc-chat-send "liece-dcc") (autoload 'liece-command-ctcp-action "liece-ctcp" nil t) (autoload 'liece-command-ctcp-version "liece-ctcp" nil t) (autoload 'liece-command-ctcp-userinfo "liece-ctcp" nil t) (autoload 'liece-command-ctcp-userinfo-from-minibuffer "liece-ctcp" nil t) (autoload 'liece-command-ctcp-help "liece-ctcp" nil t) (autoload 'liece-command-ctcp-clientinfo "liece-ctcp" nil t) (autoload 'liece-command-ctcp-ping "liece-ctcp" nil t) (autoload 'liece-command-ctcp-time "liece-ctcp" nil t) (autoload 'liece-command-ctcp-x-face "liece-ctcp" nil t) (autoload 'liece-command-ctcp-x-face-from-xbm-file "liece-ctcp" nil t) (autoload 'liece-command-ctcp-comment "liece-ctcp" nil t) (defun liece-command-poll-names () "Handler for polling NAMES." (when (liece-server-opened) (setq liece-polling (+ liece-polling (length liece-channel-alist))) (dolist (chnl liece-channel-alist) (liece-send "NAMES %s" (car chnl))))) (defun liece-command-poll-friends () "Handler for polling ISON." (and liece-friends (liece-server-opened) (liece-send "ISON %s" (mapconcat 'identity liece-friends " ")))) (defun liece-command-find-timestamp () "Find recent timestamp in dialogue buffer." (interactive) (save-excursion (let ((range "") (regexp (concat "^\\(" liece-time-prefix-regexp "\\)?" (regexp-quote liece-timestamp-prefix)))) (unless (eq 'liece-dialogue-mode (derived-mode-class major-mode)) (set-buffer liece-dialogue-buffer) (goto-char (point-max))) (if (re-search-backward regexp (point-min) t) (setq range (concat (buffer-substring (match-end 0) (line-end-position)) " --- "))) (if (re-search-forward regexp (point-max) t) (setq range (concat range (buffer-substring (match-end 0) (line-end-position))))) (liece-message range)))) (defun liece-command-keepalive () "Handler for polling server connection." (if (not (liece-server-opened)) (liece) (liece-ping-if-idle))) (defvar liece-last-timestamp-time nil "Last time timestamp was inserted.") (defvar liece-last-timestamp-no-cons-p nil "Last timestamp was no-cons.") (defun liece-command-timestamp-if-interval-expired (&optional no-cons) "If interval timer has expired, insert timestamp into dialogue buffer. And save variables into `liece-variable-file' if there are variables to save. Optional argument NO-CONS specifies timestamp format is cons cell." (interactive) (when (and (not (and no-cons liece-last-timestamp-no-cons-p)) (numberp liece-timestamp-interval) (> liece-timestamp-interval 0) (or (null liece-last-timestamp-time) (> (liece-time-difference liece-last-timestamp-time (current-time)) liece-timestamp-interval))) (if liece-save-variables-are-dirty (liece-command-save-vars)) (liece-command-timestamp) (setq liece-last-timestamp-no-cons-p no-cons))) (defun liece-command-timestamp () "Insert timestamp into dialogue buffer." (interactive) (let ((stamp (format liece-timestamp-format (funcall liece-format-time-function (current-time)))) (liece-timestamp-interval 0)) (liece-insert liece-D-buffer (concat stamp "\n")) (setq liece-last-timestamp-time (current-time)))) (defun liece-command-point-back-to-command-buffer () "Set point back to command buffer." (interactive) (let ((win (liece-get-buffer-window liece-command-buffer))) (if win (select-window win)))) (defun liece-command-send-message (message) "Send MESSAGE to current chat partner of current channel." (if (string-equal message "") (progn (liece-message (_ "No text to send")) nil) (let ((addr (if (eq liece-command-buffer-mode 'chat) liece-current-chat-partner liece-current-channel)) repr method name target) (cond ((eq liece-command-buffer-mode 'chat) (or liece-current-chat-partner (error (substitute-command-keys "Type \\[liece-command-join] to start private conversation"))) (setq repr (liece-channel-parse-representation liece-current-chat-partner) method (aref repr 0) name (aref repr 1) target (aref repr 2)) (cond ((eq method 'dcc) (liece-dcc-chat-send target message)) ((eq method 'irc) (liece-send "PRIVMSG %s :%s" liece-current-chat-partner message))) (liece-own-private-message message)) (t (or liece-current-channel (error (substitute-command-keys "Type \\[liece-command-join] to join a channel"))) (liece-send "PRIVMSG %s :%s" (liece-channel-real liece-current-channel) message) (liece-own-channel-message message)))))) (defun liece-command-enter-message () "Enter the current line as an entry in the IRC dialogue." (interactive) (beginning-of-line) (liece-command-send-message (buffer-substring (point)(progn (end-of-line) (point)))) (liece-next-line 1)) (defun liece-dialogue-enter-message () "Ask for a line as an entry in the IRC dialogue on the current channel." (interactive) (let (message) (while (not (string-equal (setq message (read-string "> ")) "")) (liece-command-send-message message)))) (defun liece-command-join-channel (join-channel-var key) "Join a JOIN-CHANNEL-VAR with KEY." (let ((nicks liece-nick-alist) nick) (while (and nicks (not (and (car nick) (liece-channel-equal join-channel-var (car nick))))) (setq nick (pop nicks))) (when nicks (setq join-channel-var (or (car (get (intern (car nick) liece-obarray) 'chnl)) join-channel-var))) (if (liece-channel-member join-channel-var liece-current-channels) (progn (setq liece-current-channel join-channel-var) (liece-switch-to-channel liece-current-channel) (liece-channel-change)) (liece-send "JOIN %s %s" (liece-channel-real join-channel-var) key)))) (defun liece-command-join-partner (join-channel-var) "Join a JOIN-CHANNEL-VAR." (if (liece-channel-member join-channel-var liece-current-chat-partners) (progn (setq liece-current-chat-partner join-channel-var) (liece-switch-to-channel liece-current-chat-partner)) (setq liece-current-chat-partner join-channel-var) (liece-channel-join liece-current-chat-partner)) (liece-channel-change)) (defun liece-command-join (join-channel-var &optional key) "Join a JOIN-CHANNEL-VAR with KEY. If user nickname is given join the same set of channels as the specified user. If command-buffer is in chat-mode, start private conversation with specified user." (interactive (let (join-channel-var key (completion-ignore-case t)) (setq join-channel-var (if (numberp current-prefix-arg) current-prefix-arg (liece-channel-virtual (if (eq liece-command-buffer-mode 'chat) (liece-minibuffer-completing-read (_ "Start private conversation with: ") liece-nick-alist nil nil nil nil liece-privmsg-partner) (liece-minibuffer-completing-read (_ "Join channel: ") (append liece-channel-alist liece-nick-alist) nil nil nil nil liece-default-channel-candidate))))) (if (and current-prefix-arg (not (numberp current-prefix-arg))) (setq key (if (eq current-prefix-arg '-) (read-string (format (_ "Key for channel %s: ") join-channel-var)) (liece-read-passwd (format (_ "Key for channel %s: ") join-channel-var))))) (list join-channel-var key))) (let ((real-chnl (liece-channel-real join-channel-var))) (if (numberp join-channel-var) (liece-switch-to-channel-no join-channel-var) (setq liece-default-channel-candidate nil) (if (liece-channel-p real-chnl) (liece-toggle-command-buffer-mode 'channel) (liece-toggle-command-buffer-mode 'chat)) (if (eq liece-command-buffer-mode 'chat) (liece-command-join-partner join-channel-var) (if (null key) (setq key (get (intern join-channel-var liece-obarray) 'key))) (put (intern join-channel-var liece-obarray) 'key key) (if (null key) (setq key "")) (liece-command-join-channel join-channel-var key)) (force-mode-line-update)))) (defun liece-command-part (part-channel-var &optional part-msg) "Part a PART-CHANNEL-VAR with PART-MSG." (interactive (let (part-channel-var (completion-ignore-case t) (part-msg "bye...")) (setq part-channel-var (liece-channel-virtual (if (eq liece-command-buffer-mode 'chat) (liece-minibuffer-completing-read (_ "End private conversation with: ") (list-to-alist liece-current-chat-partners) nil nil nil nil liece-current-chat-partner) (liece-minibuffer-completing-read (_ "Part channel: ") (list-to-alist liece-current-channels) nil nil nil nil liece-current-channel)))) (when current-prefix-arg (setq part-msg (read-string (_ "Part Message: ")))) (list part-channel-var part-msg))) (let ((real-chnl (liece-channel-real part-channel-var))) (if (liece-channel-p real-chnl) (progn (if (liece-channel-member part-channel-var liece-current-channels) (setq liece-current-channel part-channel-var)) (liece-send "PART %s :%s" real-chnl part-msg) (setq liece-default-channel-candidate part-channel-var)) (setq liece-current-chat-partners (liece-channel-remove part-channel-var liece-current-chat-partners) liece-current-chat-partner (car liece-current-chat-partners)) (liece-set-channel-indicator) (liece-channel-part part-channel-var)))) (defun liece-command-kill (kill-nickname-var &optional timeout silent) "Ignore messages from KILL-NICKNAME-VAR. Username can be given as case insensitive regular expression of form \".*@.*\.sub.domain\". If already ignoring him/her, toggle. If `liece-variables-file' is defined and the file is writable, settings are updated automatically for future sessions. Optional argument TIMEOUT says expiration. If SILENT is non-nil, don't notify current status." (interactive (let (kill-nickname-var timeout (completion-ignore-case t)) (setq kill-nickname-var (completing-read (_ "Ignore nickname or regexp: ") (append liece-nick-alist liece-kill-nickname))) (or (string-equal "" kill-nickname-var) (string-assoc-ignore-case kill-nickname-var liece-kill-nickname) (setq timeout (string-to-int (read-from-minibuffer (_ "Timeout [RET for none]: "))))) (list kill-nickname-var timeout))) ;; empty, just list them (if (string-equal "" kill-nickname-var) (with-current-buffer liece-dialogue-buffer (let ((ignores liece-kill-nickname) (time (current-time)) buffer-read-only expire expiretime) (goto-char (point-max)) (liece-insert-info liece-D-buffer (_ "Currently ignoring:")) (dolist (ignore ignores) (setq expiretime (if (cdr ignore) (/ (liece-time-difference time (cdr ignore)) 60)) expire (cond ((not expiretime) "") ((>= expiretime 0) (format (_ " (%d min)") expiretime)) ((< expiretime 0) (_ " expired")))) (liece-insert liece-D-buffer (concat " " (car ignore) expire "\n"))))) ;; else not empty, check if exists (let ((ignore (string-assoc-ignore-case kill-nickname-var liece-kill-nickname))) (if ignore (when (setq ignore (string-assoc-ignore-case (car ignore) liece-kill-nickname)) (setq liece-kill-nickname (delq ignore liece-kill-nickname)) (liece-insert-info liece-D-buffer (format (_ "No longer ignoring: %s.\n") (car ignore)))) ;; did not find, add to ignored ones (let ((expire-time (if (> timeout 0) (liece-time-elapsed (current-time) (* timeout 60))))) (and silent (> timeout 0) (setcar (cdr (cdr expire-time)) -1)) (setq liece-kill-nickname (cons (cons kill-nickname-var expire-time) liece-kill-nickname)) (unless silent (liece-insert-info liece-D-buffer (format (_ "Ignoring %s") kill-nickname-var)) (liece-insert-info liece-D-buffer (if (> timeout 0) (format " for %d minutes.\n" timeout) (format ".\n"))))))) (setq liece-save-variables-are-dirty t))) (defun liece-command-kick (nick &optional msg) "Kick this NICK out with MSG." (interactive (let ((completion-ignore-case t) (nicks (liece-channel-get-nicks)) nick msg) (setq nick (completing-read (_ "Kick out nickname: ") (list-to-alist nicks))) (if current-prefix-arg (setq msg (concat " :" (read-string (_ "Kick Message: "))))) (list nick msg))) (liece-send "KICK %s %s%s" (liece-channel-real liece-current-channel) nick (or msg ""))) (defun liece-command-ban (ban) "BAN this user out." (interactive (let* ((completion-ignore-case t) (nicks (liece-channel-get-nicks)) (uahs (mapcar (function (lambda (nick) (list (concat nick "!" (liece-nick-get-user-at-host nick))))) nicks)) ban nick msg) (setq ban (liece-minibuffer-completing-read (_ "Ban pattern: ") uahs nil nil nil nil (concat nick "!" (liece-nick-get-user-at-host nick)))) (list ban))) (liece-send "MODE %s :+b %s" (liece-channel-real liece-current-channel) ban)) (defun liece-command-ban-kick (ban nick &optional msg) "BAN kick this NICK out with MSG." (interactive (let* ((completion-ignore-case t) (nicks (liece-channel-get-nicks)) (uahs (mapcar (function (lambda (nick) (list (concat nick "!" (liece-nick-get-user-at-host nick))))) nicks)) ban nick msg) (setq nick (completing-read (_ "Kick out nickname: ") (list-to-alist nicks)) ban (liece-minibuffer-completing-read (_ "Ban pattern: ") uahs nil nil nil nil (concat nick "!" (liece-nick-get-user-at-host nick)))) (if current-prefix-arg (setq msg (concat " :" (read-string (_ "Kick Message: ")))) (setq msg "")) (list ban nick msg))) (liece-send "MODE %s :+b %s" (liece-channel-real liece-current-channel) ban) (liece-send "KICK %s %s%s" (liece-channel-real liece-current-channel) nick (or msg ""))) (defun liece-command-list (&optional channel) "List the given CHANNEL and its topics. If you enter only Control-U as argument, list the current channel. With - as argument, list all channels." (interactive (if (or current-prefix-arg (null liece-current-channel)) (if (eq current-prefix-arg '-) (list current-prefix-arg)) (let ((completion-ignore-case t) channel) (setq channel (liece-minibuffer-completing-read (_ "LIST channel: ") liece-channel-alist nil nil nil nil liece-current-channel)) (unless (string-equal "" channel) (list channel))))) (cond ((not channel) (if liece-current-channel (liece-send "LIST %s" (liece-channel-real liece-current-channel)))) ((and (eq channel '-) (y-or-n-p (_ "Do you really query LIST without argument?"))) (liece-send "LIST")) ((not (string-equal channel "")) (liece-send "LIST %s" (liece-channel-real channel)) ))) (defun liece-command-modec (chnl change) "Send a MODE command to this CHNL. Argument CHANGE ." (interactive (let ((completion-ignore-case t) (chnl liece-current-channel) liece-minibuffer-complete-function prompt) (if current-prefix-arg (setq chnl (liece-minibuffer-completing-read (_ "Channel/User: ") (append liece-channel-alist liece-nick-alist) nil nil nil nil liece-current-channel))) (cond ((liece-channel-p (liece-channel-real chnl)) (setq prompt (format (_ "Mode for channel %s [%s]: ") chnl (or (liece-channel-get-modes chnl) "")) liece-minibuffer-complete-function (function liece-minibuffer-complete-channel-modes))) (t (setq prompt (format (_ "Mode for user %s [%s]: ") chnl (or (liece-nick-get-modes chnl) "")) liece-minibuffer-complete-function (function liece-minibuffer-complete-user-modes)))) (list chnl (read-from-minibuffer prompt nil liece-minibuffer-map)))) (liece-send "MODE %s %s" (liece-channel-real chnl) change)) (defun liece-command-qualify-nicks (mode nicks val) (liece-send "MODE %s %c%s %s" (liece-channel-real liece-current-channel) (if val ?+ ?-) (make-string (length nicks) mode) (string-join nicks " "))) (defun liece-command-set-operators (nicks &optional arg) (interactive (let ((opers (liece-channel-get-operators)) (completion-ignore-case t) nicks) (if current-prefix-arg (setq nicks (liece-minibuffer-completing-read-multiple (_ "Divest operational privilege from: ") (list-to-alist opers))) (setq nicks (liece-channel-get-nicks) nicks (filter-elements nick nicks (not (liece-nick-member nick opers))) nicks (liece-minibuffer-completing-read-multiple (_ "Assign operational privilege to: ") (list-to-alist nicks)))) (list nicks current-prefix-arg))) (let (run) (unwind-protect (dolist (nick nicks) (push nick run) (when (= (length run) liece-compress-mode-length) (liece-command-qualify-nicks ?o run (not arg)) (setq run nil))) (when run (liece-command-qualify-nicks ?o run (not arg)))))) (defun liece-command-set-voices (nicks &optional arg) (interactive (let ((voices (liece-channel-get-voices)) (completion-ignore-case t) nicks) (if current-prefix-arg (setq nicks (liece-minibuffer-completing-read-multiple (_ "Forbid to speak: ") (list-to-alist voices))) (setq voices (append voices (liece-channel-get-operators)) nicks (liece-channel-get-nicks) nicks (filter-elements nick nicks (not (liece-nick-member nick voices))) nicks (liece-minibuffer-completing-read-multiple (_ "Allow to speak: ") (list-to-alist nicks)))) (list nicks current-prefix-arg))) (let (run) (unwind-protect (dolist (nick nicks) (push nick run) (when (= (length run) liece-compress-mode-length) (liece-command-qualify-nicks ?v run (not arg)) (setq run nil))) (when run (liece-command-qualify-nicks ?v run (not arg)))))) (defun liece-command-message (address message) "Send ADDRESS a private MESSAGE." (interactive (let ((completion-ignore-case t) address) (setq address (liece-channel-virtual (liece-minibuffer-completing-read (_ "Private message to: ") (append liece-nick-alist liece-channel-alist) nil nil nil nil liece-privmsg-partner))) (list address (read-string (format (_ "Private message to %s: ") address))))) (if (funcall liece-message-empty-predicate message) (progn (liece-message (_ "No text to send")) nil) (let ((chnl (liece-channel-real address))) (liece-send "PRIVMSG %s :%s" chnl message) (if (liece-channel-p chnl) (liece-own-channel-message message (liece-channel-virtual address)) (liece-own-private-message message address))))) (defun liece-command-mta-private (partner) "Send a private message (current line) to PARTNER." (interactive (let ((completion-ignore-case t)) (setq liece-privmsg-partner (liece-channel-virtual (liece-minibuffer-completing-read (_ "To whom: ") (append liece-nick-alist liece-channel-alist) nil nil nil nil liece-privmsg-partner))) (list liece-privmsg-partner))) (let ((message (buffer-substring (progn (beginning-of-line) (point)) (progn (end-of-line) (point))))) (if (> (length message) 0) (progn (liece-command-message liece-privmsg-partner message) (liece-next-line 1)) (liece-message (_ "No text to send"))))) (defun liece-command-names (&optional expr) "List the nicknames of the current IRC users on given EXPR. With an Control-U as argument, only the current channel is listed. With - as argument, list all channels." (interactive (if (or current-prefix-arg (null liece-current-channel)) (if (eq current-prefix-arg '-) (list current-prefix-arg)) (let ((completion-ignore-case t) expr) (setq expr (liece-minibuffer-completing-read (_ "Names on channel: ") liece-channel-alist nil nil nil nil liece-current-channel)) (unless (string-equal "" expr) (list expr))))) (when (or (and (eq expr '-) (y-or-n-p (_ "Do you really query NAMES without argument?"))) (not (or expr (if liece-current-channel (setq expr (liece-channel-real liece-current-channel)))))) (setq expr "")) (when expr (liece-send "NAMES %s" expr))) (defun liece-command-nickname (nick) "Set your nickname to NICK." (interactive "sEnter your nickname: ") (let ((nickname (truncate-string nick liece-nick-max-length))) (if (zerop (length nickname)) (liece-message (_ "illegal nickname \"%s\"; not changed") nickname) (liece-send "NICK %s" nick)))) (defun liece-command-who (&optional expr) "Lists tue users that match the given expression EXPR. If you enter only Control-U as argument, list the current channel. With - as argument, list all users." (interactive (if (or current-prefix-arg (null liece-current-channel)) (if (eq current-prefix-arg '-) (list current-prefix-arg)) (let ((completion-ignore-case t) expr) (setq expr (completing-read (_ "WHO expression: ") (append liece-channel-alist liece-nick-alist))) (unless (string-equal "" expr) (list expr))))) (when (or (and (eq expr '-) (y-or-n-p (_ "Do you really query WHO without argument?"))) (not (or expr (if liece-current-channel (setq expr (liece-channel-real liece-current-channel)))))) (setq expr "")) (when expr (liece-send "WHO %s" expr) (setq liece-who-expression expr))) (defun liece-command-finger (finger-nick-var &optional server) "Get information about a specific user FINGER-NICK-VAR. If called with optional argument SERVER or any prefix argument, query information to the foreign server." (interactive (let (finger-nick-var (completion-ignore-case t)) (setq finger-nick-var (completing-read (_ "Finger whom: ") liece-nick-alist)) (list finger-nick-var (and current-prefix-arg finger-nick-var)))) (if server (liece-send "WHOIS %s %s" server finger-nick-var) (liece-send "WHOIS %s" finger-nick-var))) (defun liece-command-topic (topic) "Change TOPIC of the current channel." (interactive (list (read-from-minibuffer "Topic: " (cons (or (liece-channel-get-topic) "") 0)))) (liece-send "TOPIC %s :%s" (liece-channel-real liece-current-channel) topic)) (defun liece-command-invite (&optional invite-nick-var invite-channel-var) "Invite INVITE-NICK-VAR to INVITE-CHANNEL-VAR." (interactive (let ((completion-ignore-case t) invite-channel-var invite-nick-var) (if current-prefix-arg (setq invite-channel-var (liece-channel-virtual (completing-read (_ "Invite channel: ") (list-to-alist liece-current-channels))))) (setq invite-nick-var (completing-read (_ "Invite whom: ") liece-nick-alist)) (list invite-nick-var invite-channel-var))) (or invite-channel-var (setq invite-channel-var liece-current-channel)) (liece-send "INVITE %s %s" invite-nick-var (liece-channel-real invite-channel-var))) (defun liece-command-away (awaymsg) "Mark/unmark yourself as being away. Leave message AWAYMSG." (interactive "sAway message: ") (liece-send "AWAY :%s" awaymsg) (setq liece-away-message awaymsg)) (defun liece-command-scroll-down (lines) "Scroll LINES down dialogue buffer from command buffer." (interactive "P") (let ((other-window-scroll-buffer (if liece-channel-buffer-mode liece-channel-buffer liece-dialogue-buffer))) (when (liece-get-buffer-window other-window-scroll-buffer) (condition-case nil (scroll-other-window-down lines) (beginning-of-buffer (message "Beginning of buffer")))))) (defun liece-command-scroll-up (lines) "Scroll LINES up dialogue buffer from command buffer." (interactive "P") (let* ((other-window-scroll-buffer (if liece-channel-buffer-mode liece-channel-buffer liece-dialogue-buffer))) (when (liece-get-buffer-window other-window-scroll-buffer) (condition-case nil (scroll-other-window lines) (end-of-buffer (message "End of buffer")))))) (defun liece-command-nick-scroll-down (lines) "Scroll LINES down nick buffer from command buffer." (interactive "P") (let ((other-window-scroll-buffer liece-nick-buffer)) (when (liece-get-buffer-window other-window-scroll-buffer) (condition-case nil (scroll-other-window-down lines) (beginning-of-buffer (message "Beginning of buffer")))))) (defun liece-command-nick-scroll-up (lines) "Scroll LINES up nick buffer from command buffer." (interactive "P") (let* ((other-window-scroll-buffer liece-nick-buffer)) (when (liece-get-buffer-window other-window-scroll-buffer) (condition-case nil (scroll-other-window lines) (end-of-buffer (message "End of buffer")))))) (defun liece-command-freeze (&optional arg) "Prevent automatic scrolling of the dialogue window. If prefix argument ARG is non-nil, toggle frozen status." (interactive "P") (liece-freeze (if liece-channel-buffer-mode liece-channel-buffer liece-dialogue-buffer) (if arg (prefix-numeric-value arg)))) (defun liece-command-own-freeze (&optional arg) "Prevent automatic scrolling of the dialogue window. The difference from `liece-command-freeze' is that your messages are hidden. If prefix argument ARG is non-nil, toggle frozen status." (interactive "P") (liece-own-freeze (if liece-channel-buffer-mode liece-channel-buffer liece-dialogue-buffer) (if arg (prefix-numeric-value arg)))) (defun liece-command-beep (&optional arg) "Toggle the automatic beep notice when the channel message is received." (interactive "P") (liece-set-beep (if liece-channel-buffer-mode liece-channel-buffer liece-dialogue-buffer) (if arg (prefix-numeric-value arg)))) (defun liece-command-quit (&optional arg) "Quit IRC. If prefix argument ARG is non-nil, leave signoff message." (interactive "P") (when (and (liece-server-opened) (y-or-n-p (_ "Quit IRC? "))) (message "") (let ((quit-string (if arg (read-string (_ "Signoff message: ")) (or liece-signoff-message (product-name (product-find 'liece-version)))))) (liece-close-server quit-string)))) (defun liece-command-generic (message) "Enter a generic IRC MESSAGE, which is sent to the server. A ? lists the useful generic messages." (interactive "sIRC command (? to help): ") (if (string-equal message "?") (with-output-to-temp-buffer "*IRC Help*" (princ "The following generic IRC messages may be of interest to you: TOPIC set the topic of your channel INVITE invite another user to join your channel LINKS lists the currently reachable IRC servers SUMMON invites an user not currently in IRC USERS lists the users on a host AWAY marks you as not really actively using IRC (an empty reason clears it) WALL send to everyone on IRC NAMES lists users per channel ")) (liece-send "%s" message))) (defun liece-command-irc-compatible () "If entered at column 0, allow you to enter a generic IRC message." (interactive) (if (zerop (current-column)) (call-interactively (function liece-command-generic)) (self-insert-command 1))) (defun liece-command-yank-send (&optional arg) "Send message from yank buffer. Prefix argument ARG is regarded as distance from yank pointer." (interactive) (when (y-or-n-p (_ "Really SEND from Yank Buffer?")) (save-restriction (narrow-to-region (point) (point)) (insert (car kill-ring-yank-pointer)) (goto-char (point-min)) (while (eobp) (liece-command-enter-message) (set-buffer liece-command-buffer))))) (defun liece-command-complete () "Complete word before point from userlist." (interactive) (let ((completion-ignore-case t) (alist (if liece-current-channel (list-to-alist (liece-channel-get-nicks)) liece-nick-alist)) candidate completion all) (setq candidate (current-word) completion (try-completion candidate alist) all (all-completions candidate alist)) (liece-minibuffer-finalize-completion completion candidate all))) (defun liece-command-load-vars () "Load configuration from liece-variables-file." (interactive) (let ((nick liece-real-nickname)) (unwind-protect (liece-read-variables-files) (setq liece-real-nickname nick) (liece-command-reconfigure-windows)))) (defun liece-command-save-vars () "Save current settings to `liece-variables-file'." (interactive) (let* ((output-buffer (find-file-noselect (expand-file-name liece-variables-file))) output-marker p) (save-excursion (set-buffer output-buffer) (goto-char (point-min)) (cond ((re-search-forward "^;; Saved Settings *\n" nil 'move) (setq p (match-beginning 0)) (goto-char p) (or (re-search-forward "^;; End of Saved Settings *\\(\n\\|\\'\\)" nil t) (error (concat "can't find END of saved state in " liece-variables-file))) (delete-region p (match-end 0))) (t (goto-char (point-max)) (insert "\n"))) (setq output-marker (point-marker)) (let ((print-readably t) (print-escape-newlines t) (standard-output output-marker)) (princ ";; Saved Settings\n") (dolist (var liece-saved-forms) (if (symbolp var) (prin1 (list 'setq var (let ((val (symbol-value var))) (if (memq val '(t nil)) val (list 'quote val))))) (setq var (eval var)) (cond ((eq (car-safe var) 'progn) (while (setq var (cdr var)) (prin1 (car var)) (princ "\n") (if (cdr var) (princ " ")))) (var (prin1 "xx")(prin1 var)))) (if var (princ "\n"))) (princ "\n") (princ ";; End of Saved Settings\n"))) (set-marker output-marker nil) (save-excursion (set-buffer output-buffer) (save-buffer))) (setq liece-save-variables-are-dirty nil)) (defun liece-command-reconfigure-windows () "Rearrange window splitting." (interactive) (let ((command-window (liece-get-buffer-window liece-command-buffer)) (dialogue-window (liece-get-buffer-window liece-dialogue-buffer)) (obuffer (current-buffer))) (if (and command-window dialogue-window) (let ((ch (window-height command-window)) (dh (window-height dialogue-window))) (delete-window command-window) (pop-to-buffer liece-dialogue-buffer) (enlarge-window (+ ch dh (- dh)))) (pop-to-buffer liece-dialogue-buffer)) (liece-configure-windows) (if liece-one-buffer-mode (pop-to-buffer liece-dialogue-buffer) (pop-to-buffer obuffer)))) (defun liece-command-end-of-buffer () "Get end of the dialogue buffer." (interactive) (let (buffer window) (setq buffer (if liece-channel-buffer-mode liece-channel-buffer liece-dialogue-buffer)) (or (setq window (liece-get-buffer-window buffer)) (setq window (liece-get-buffer-window liece-dialogue-buffer) buffer liece-dialogue-buffer)) (when window (save-selected-window (select-window window) (goto-char (point-max)))))) (defun liece-command-private-conversation (arg) "Toggle between private conversation mode and channel mode. User can then join and part to a private conversation as he would join or part to a channel. If there are no private conversations or argument is given user is prompted the partner/channel (return as partner/channel means toggle mode, the current channel and current chat partner are not altered) Argument ARG is prefix argument of toggle status." (interactive (let ((completion-ignore-case t)) (list (if current-prefix-arg ;; prefixed, ask where to continue (if (eq liece-command-buffer-mode 'chat) (liece-minibuffer-completing-read (_ "Return to channel: ") (append liece-channel-alist liece-nick-alist) nil nil nil nil liece-current-channel) (completing-read (_ "Start private conversation with: ") liece-nick-alist nil nil)) ;; no prefix, see if going to chat (if (eq liece-command-buffer-mode 'channel) ;; and if we have chat partner, select that (if liece-current-chat-partner liece-current-chat-partner (completing-read (_ "Start private conversation with: ") liece-nick-alist ))))))) (liece-toggle-command-buffer-mode) (if (and arg (not (string-equal arg ""))) (liece-command-join arg)) (liece-set-channel-indicator) ;; refresh mode line (force-mode-line-update)) (defun liece-command-next-channel () "Select next channel or chat partner, and *DONT* rotate list." (interactive) (let ((rest (copy-sequence (if (eq liece-command-buffer-mode 'chat) liece-current-chat-partners liece-current-channels))) (chnl (if (eq liece-command-buffer-mode 'chat) liece-current-chat-partner liece-current-channel))) (liece-switch-to-channel (or (cadr (liece-channel-member chnl (delq nil rest))) (car (delq nil rest)) chnl)))) (defun liece-command-previous-channel () "Select previous channel or chat partner, and *DONT* rotate list." (interactive) (let ((rest (reverse (if (eq liece-command-buffer-mode 'chat) liece-current-chat-partners liece-current-channels))) (chnl (if (eq liece-command-buffer-mode 'chat) liece-current-chat-partner liece-current-channel))) (liece-switch-to-channel (or (cadr (liece-channel-member chnl (delq nil rest))) (car (delq nil rest)) chnl)))) (defun liece-command-unread-channel () "Select unread channel or chat partner." (interactive) (let ((chnl (car liece-channel-unread-list))) (if chnl (liece-switch-to-channel chnl) (liece-message (_ "No unread channel or chat partner."))))) (defun liece-command-push () "Select next channel or chat partner, and rotate list." (interactive) (let* ((rest (if (eq liece-command-buffer-mode 'chat) liece-current-chat-partners liece-current-channels)) (temp (car (last rest))) (len (length rest))) (unwind-protect (while (< 1 len) (setcar (nthcdr (1- len) rest) (nth (- len 2) rest)) (decf len)) (when rest (setcar rest temp))) (liece-channel-change))) (defun liece-command-pop () "Select previous channel or chat partner, and rotate list." (interactive) (let* ((rest (if (eq liece-command-buffer-mode 'chat) liece-current-chat-partners liece-current-channels)) (temp (car rest)) (len (length rest))) (unwind-protect (dotimes (i len) (setcar (nthcdr i rest) (nth (1+ i) rest))) (when rest (setcar (last rest) temp))) (liece-channel-change))) (defvar liece-redisplay-buffer-functions '(liece-channel-redisplay-buffer liece-nick-redisplay-buffer liece-channel-list-redisplay-buffer)) (defun liece-switch-to-channel (chnl) "Switch the current channel to CHNL." (if (liece-channel-p (liece-channel-real chnl)) (progn (liece-toggle-command-buffer-mode 'channel) (setq liece-current-channel chnl) (liece-set-channel-indicator)) (liece-toggle-command-buffer-mode 'chat) (setq liece-current-chat-partner chnl) (liece-set-channel-indicator)) (save-excursion (run-hook-with-args 'liece-redisplay-buffer-functions chnl))) (defun liece-switch-to-channel-no (num) "Switch the current channel to NUM." (let* ((mode liece-command-buffer-mode) (chnls (if (eq mode 'chat) liece-current-chat-partners liece-current-channels))) (if (and (integerp num) (stringp (nth num chnls))) (let ((chnl (nth num chnls))) (if (eq mode 'chat) (progn (liece-toggle-command-buffer-mode 'chat) (setq liece-current-chat-partner chnl) (liece-set-channel-indicator)) (liece-toggle-command-buffer-mode 'channel) (setq liece-current-channel chnl) (liece-set-channel-indicator)) (save-excursion (run-hook-with-args 'liece-redisplay-buffer-functions chnl))) (message "Invalid channel!")))) (defun liece-command-ping () "Send PING to server." (interactive) (if (stringp liece-server-name) (liece-send "PING %s" liece-server-name))) (defun liece-command-ison (nicks) "IsON users NICKS." (interactive (let (nicks (completion-ignore-case t)) (setq nicks (liece-minibuffer-completing-read-multiple "IsON" liece-nick-alist)) (list nicks))) (liece-send "ISON :%s" (mapconcat #'identity nicks " "))) (defun liece-command-activate-friends (nicks) "Register NICKS to the frinends list." (interactive (let (nicks (completion-ignore-case t)) (setq nicks (liece-minibuffer-completing-read-multiple (_ "Friend") (filter-elements nick liece-nick-alist (not (string-list-member-ignore-case (car nick) liece-friends))))) (list nicks))) (setq liece-friends (append nicks liece-friends))) (defun liece-command-deactivate-friends () "Clear current friends list." (interactive) (setq liece-friends nil)) (defun liece-command-display-friends () "Display status of the friends." (interactive) (with-output-to-temp-buffer " *IRC Friends*" (set-buffer standard-output) (insert "Friends status: \n\n") (dolist (friend liece-friends) (if (string-list-member-ignore-case friend liece-friends-last) (insert "+ " friend "\n") (insert "- " friend "\n"))))) (defun liece-command-show-last-kill () "Dig last kill from KILL and show it." (interactive) (liece-insert-info (append liece-D-buffer liece-O-buffer) (save-excursion (set-buffer liece-KILLS-buffer) (goto-char (point-max)) (forward-line -1) (concat (buffer-substring (point) (point-max)) "\n")))) (defun liece-command-toggle-private () "Toggle private mode / channel mode." (interactive) (case (prog1 liece-command-buffer-mode (liece-toggle-command-buffer-mode)) (chat (if liece-current-channel (liece-switch-to-channel liece-current-channel)) (setq liece-command-buffer-mode-indicator "Channels")) (channel (if liece-current-chat-partner (liece-switch-to-channel liece-current-chat-partner)) (setq liece-command-buffer-mode-indicator "Partners"))) (liece-channel-change)) (defun liece-command-tag-region (start end) "Move current region between START and END to `kill-ring'." (interactive (if (region-active-p) (list (region-beginning)(region-end)) (list (line-beginning-position)(line-end-position)))) (static-if (fboundp 'extent-property) (kill-ring-save start end) (let ((start (set-marker (make-marker) start)) (end (set-marker (make-marker) end)) (inhibit-read-only t) buffer-read-only buffer-undo-list) (liece-remove-properties-region start end) (kill-ring-save start end) (push nil buffer-undo-list) (undo)))) (provide 'liece-commands) ;;; liece-commands.el ends here