Commit adf794e4 authored by Eli Zaretskii's avatar Eli Zaretskii

Use split-string OMIT-NULLS argument.

(rcirc-print): Force redisplay before running hooks.  Do long
buffer truncation after making new text read-only.  Deal with nil
text when decoding strings.  If TARGET is nil, use either the
currently selected buffer, if it is an rcirc buffer and of the
same process or the process buffer.
(rcirc-mode): Remove header-line.  Recompute short buffer names.
Initialize rcirc-buffer-alist here instead of rcirc-get-buffer-create.
(rcirc-short-buffer-name): Add variable.
(rcirc-kill-buffer-hook): Recompute short buffer names.  Remove
nick from private channel.
(rcirc-send-input): Send command text to current-buffer.  Don't
clear overlay arrow here.
(rcirc-short-buffer-name): Return a short buffer name.
(rcirc-update-short-buffer-names, rcirc-abbreviate)
(rcirc-rebuild-tree, rcirc-make-trees): Add functions to generate
buffer-name abbreviations.
(rcirc-kill-buffer-hook-1): Split to make debugging easier.  Do
not touch nick-table when killing a parted channel.
(rcirc-window-configuration-change): Rename from
rcirc-update-activity.  Clear arrow from current buffer if it is now hidden.
(rcirc-current-buffer): Add variable.
(rcirc-my-nick, rcirc-other-nick, rcirc-server)
(rcirc-nick-in-message, rcirc-prompt, rcirc-mode-line-nick):
Remove -face from names.
(rcirc-update-activity-string): Print "DND" when globally ignoring activity.
(rcirc-ignore-buffer-activity-flag): Rename from rcirc-ignore-channel-activity.
(rcirc-ignore-all-activity-flag): Doc fix.
(rcirc-channels): Remove variable.
(rcirc-kill-buffer-hook):
(rcirc-get-buffer-create): Add nick to private channel.
(rcirc-multiline-edit-submit): Remove tabs.
(rcirc-put-nick-channel, rcirc-channel-nicks): Look up nicks case folded.
(rcirc-remove-nick-channel): Bug fix.
(rcirc-toggle-ignore-buffer-activity): Rename from
rcirc-toggle-ignore-channel-activity.
(rcirc-record-activity): Add buffers to the front of the list.
(rcirc-update-activity): Remove killed buffers from list.
(rcirc-process-server-response-1): Remove last argument if it is
null before calling handler.
(rcirc): Add "rcirc" defcustom prefix.
(rcirc-prompt): Simplify default prompt.  Use custom-initialize-default.
(rcirc-private-chats): Remove variable.
(rcirc-prompt): Change initialization.
(rcirc-version): Remove function.
(rcirc-id-string): Add constant.
(rcirc-last-buffer): Remove variable.
(rcirc-buffer-alist): Add variable.
(rcirc-connect): Update variable setup.
(rcirc-sentinel, rcirc-update-prompt): Use `rcirc-buffer-alist'.
(rcirc-trap-errors-flag): Rename from `rcirc-trap-errors' change default.
(rcirc-handler-generic): Trigger activity.
(rcirc-send-message): Create the buffor of the target.
(rcirc-generate-new-buffer-name): Rename from
`rcirc-get-buffer-name'.
(rcirc-get-buffer): Just return nil if there is no matching buffer.
(rcirc-multiline-edit-cancel): Remove function.
(rcirc-set-last-buffer): Remove function.
(rcirc-get-any-buffer): Add function.
(rcirc-join-channels): Don't print /join text.
(rcirc-toggle-ignore-channel-activity): Add and update echo area messages.
(rcirc-cmd-ctcp): Use rcirc-send-string to send request.
(rcirc-handler-NOTICE): Recognize CTCP responses.
(rcirc-handler-332, rcirc-handler-332): Use a temp buffer for
constructing TOPIC string for buffers we are not JOINed.
(rcirc-handler-CTCP-response): Add handler.
(rcirc-multiline-edit-submit): Restore the window-configuration
before adjusting point.
(rcirc): Add customization group.
(rcirc-server, rcirc-port, rcirc-nick, rcirc-user-name)
(rcirc-user-full-name, rcirc-startup-channels-alist)
(rcirc-fill-flag, rcirc-fill-column, rcirc-fill-prefix)
(rcirc-ignore-all-activity-flag, rcirc-time-format)
(rcirc-input-ring-size, rcirc-read-only-flag)
(rcirc-buffer-maximum-lines, rcirc-authinfo-file-name)
(rcirc-auto-authenticate-flag, rcirc-prompt, rcirc-print-hooks):
Change defvar to defcustom.
(rcirc-update-prompt): Add optional ALL arg, which will update
prompts in all rcirc buffers.  Regexp quote replacement text.
(rcirc-fill-column): Accept 'frame-width as a value.
(rcirc-set-changed): Add function.
(rcirc-next-active-buffer): Write more meaningful messages.
(rcirc-faces): Add customization group.
(rcirc-my-nick-face, rcirc-other-nick-face, rcirc-server-face)
(rcirc-nick-in-message-face, rcirc-prompt-face)
(rcirc-mode-line-nick-face): Move into rcirc-faces group.
(with-rcirc-process-buffer): Move before first usage.
(rcirc-debug-buffer): Rename from `rcirc-log-buffer'.
(rcirc-debug-flag): Rename from `rcirc-log-p'.
(rcirc-debug): Rename from `rcirc-log'.
(rcirc-format-response-string): Do not print '-' chars for a
NOTICE with no sender.  Simplify output of server responses.
(rcirc-browse-url-map, rcirc-browse-url-at-point)
(rcirc-browse-url-at-mouse, rcirc-mangle-text): Make urls
mouse and RET clickable.
parent ffce4757
......@@ -25,12 +25,17 @@
;;; Commentary:
;; rcirc is an Internet Relay Chat (IRC) client for Emacs
;; IRC is a form of instant communication over the Internet. It is
;; mainly designed for group (many-to-many) communication in
;; discussion forums called channels, but also allows one-to-one
;; communication.
;; Internet Relay Chat (IRC) is a form of instant communication over
;; the Internet. It is mainly designed for group (many-to-many)
;; communication in discussion forums called channels, but also allows
;; one-to-one communication.
;; Rcirc has simple defaults and clear and consistent behaviour.
;; Message arrival timestamps, activity notification on the modeline,
;; message filling, nick completion, and keepalive pings are all
;; enabled by default, but can easily be adjusted or turned off. Each
;; discussion takes place in its own buffer and there is a single
;; server buffer per connection.
;; Open a new irc connection with:
;; M-x irc RET
......@@ -41,61 +46,101 @@
(require 'time-date)
(eval-when-compile (require 'cl))
(defvar rcirc-server "irc.freenode.net"
"The default server to connect to.")
(defgroup rcirc nil
"Simple IRC client."
:version "22.1"
:prefix "rcirc"
:group 'applications)
(defcustom rcirc-server "irc.freenode.net"
"The default server to connect to."
:type 'string
:group 'rcirc)
(defvar rcirc-port 6667
"The default port to connect to.")
(defcustom rcirc-port 6667
"The default port to connect to."
:type 'integer
:group 'rcirc)
(defvar rcirc-nick (user-login-name)
"Your nick.")
(defcustom rcirc-nick (user-login-name)
"Your nick."
:type 'string
:group 'rcirc)
(defvar rcirc-user-name (user-login-name)
"Your user name sent to the server when connecting.")
(defcustom rcirc-user-name (user-login-name)
"Your user name sent to the server when connecting."
:type 'string
:group 'rcirc)
(defvar rcirc-user-full-name (if (string= (user-full-name) "")
(defcustom rcirc-user-full-name (if (string= (user-full-name) "")
rcirc-user-name
(user-full-name))
"The full name sent to the server when connecting.")
"The full name sent to the server when connecting."
:type 'string
:group 'rcirc)
(defvar rcirc-startup-channels-alist nil
(defcustom rcirc-startup-channels-alist nil
"Alist of channels to join at startup.
Each element looks like (REGEXP . CHANNEL-LIST).")
Each element looks like (SERVER-REGEXP . CHANNEL-LIST)."
:type '(alist :key-type string :value-type (repeat string))
:group 'rcirc)
(defvar rcirc-fill-flag t
"*Non-nil means fill messages printed in channel buffers.")
(defcustom rcirc-fill-flag t
"*Non-nil means line-wrap messages printed in channel buffers."
:type 'boolean
:group 'rcirc)
(defvar rcirc-fill-column nil
"*If non-nil, fill to this column, otherwise use value of `fill-column'.")
(defcustom rcirc-fill-column nil
"*Column beyond which automatic line-wrapping should happen.
If nil, use value of `fill-column'. If frame-width, use the
maximum frame width."
:type '(choice (const :tag "Value of `fill-column'")
(const :tag "Full frame width" frame-width)
(integer :tag "Number of columns"))
:group 'rcirc)
(defvar rcirc-fill-prefix nil
(defcustom rcirc-fill-prefix nil
"*Text to insert before filled lines.
If nil, calculate the prefix dynamically to line up text
underneath each nick.")
underneath each nick."
:type '(choice (const :tag "Dynamic" nil)
(string :tag "Prefix text"))
:group 'rcirc)
(defvar rcirc-ignore-channel-activity nil
"If non-nil, ignore activity in this channel.")
(make-variable-buffer-local 'rcirc-ignore-channel-activity)
(defvar rcirc-ignore-buffer-activity-flag nil
"If non-nil, ignore activity in this buffer.")
(make-variable-buffer-local 'rcirc-ignore-buffer-activity-flag)
(defvar rcirc-ignore-all-activity-flag nil
"*Non-nil means track activity, but do not display it in the modeline.")
(defcustom rcirc-ignore-all-activity-flag nil
"*Non-nil means do not indicate any activity in the modeline."
:type 'boolean
:group 'rcirc)
(defvar rcirc-time-format "%H:%M "
(defcustom rcirc-time-format "%H:%M "
"*Describes how timestamps are printed.
Used as the first arg to `format-time-string'.")
Used as the first arg to `format-time-string'."
:type 'string
:group 'rcirc)
(defvar rcirc-input-ring-size 1024
"*Size of input history ring.")
(defcustom rcirc-input-ring-size 1024
"*Size of input history ring."
:type 'integer
:group 'rcirc)
(defvar rcirc-read-only-flag t
"*Non-nil means make text in irc buffers read-only.")
(defcustom rcirc-read-only-flag t
"*Non-nil means make text in irc buffers read-only."
:type 'boolean
:group 'rcirc)
(defvar rcirc-buffer-maximum-lines nil
(defcustom rcirc-buffer-maximum-lines nil
"*The maximum size in lines for rcirc buffers.
Channel buffers are truncated from the top to be no greater than this
number. If zero or nil, no truncating is done.")
number. If zero or nil, no truncating is done."
:type '(choice (const :tag "No truncation" nil)
(integer :tag "Number of lines"))
:group 'rcirc)
(defvar rcirc-authinfo-file-name
(defcustom rcirc-authinfo-file-name
"~/.rcirc-authinfo"
"File containing rcirc authentication passwords.
The file consists of a single list, with each element itself a
......@@ -111,17 +156,17 @@ The required ARGUMENTS for each METHOD symbol are:
Example:
((\"freenode\" \"bob\" nickserv \"p455w0rd\")
(\"freenode\" \"bob\" chanserv \"#bobland\" \"passwd99\")
(\"bitlbee\" \"robert\" bitlbee \"sekrit\"))")
(\"bitlbee\" \"robert\" bitlbee \"sekrit\"))"
:type 'string
:group 'rcirc)
(defvar rcirc-auto-authenticate-flag (file-readable-p rcirc-authinfo-file-name)
(defcustom rcirc-auto-authenticate-flag (file-readable-p rcirc-authinfo-file-name)
"*Non-nil means automatically send authentication string to server.
See also `rcirc-authinfo-file-name'.")
(defvar rcirc-print-hooks nil
"Hook run after text is printed.
Called with 5 arguments, PROCESS, SENDER, RESPONSE, TARGET and TEXT.")
See also `rcirc-authinfo-file-name'."
:type 'boolean
:group 'rcirc)
(defvar rcirc-prompt "%n> "
(defcustom rcirc-prompt "> "
"Prompt string to use in irc buffers.
The following replacements are made:
......@@ -129,14 +174,27 @@ The following replacements are made:
%s is the server.
%t is the buffer target, a channel or a user.
Setting this alone will not affect the prompt;
use `rcirc-update-prompt' after changing this variable.")
Setting this alone will not affect the prompt;
use either M-x customize or also call `rcirc-update-prompt'."
:type 'string
:set 'rcirc-set-changed
:initialize 'custom-initialize-default
:group 'rcirc)
(defcustom rcirc-print-hooks nil
"Hook run after text is printed.
Called with 5 arguments, PROCESS, SENDER, RESPONSE, TARGET and TEXT."
:type 'hook
:group 'rcirc)
(defvar rcirc-prompt-start-marker nil)
(defvar rcirc-prompt-end-marker nil)
(defvar rcirc-nick-table nil)
;; each process has an alist of (target . buffer) pairs
(defvar rcirc-buffer-alist nil)
(defvar rcirc-activity nil
"List of channels with unviewed activity.")
......@@ -150,30 +208,14 @@ use `rcirc-update-prompt' after changing this variable.")
(defvar rcirc-target nil
"The channel or user associated with this buffer.")
(defvar rcirc-channels nil
"Joined channels.")
(defvar rcirc-private-chats nil
"Private chats open.")
(defvar rcirc-urls nil
"List of urls seen in the current buffer.")
(defvar rcirc-keepalive-seconds 60
"Number of seconds between keepalive pings.")
(defconst rcirc-id-string (concat "rcirc on GNU Emacs " emacs-version))
(defun rcirc-version (&optional here)
"Return rcirc version string.
If optional argument HERE is non-nil, insert string at point."
(interactive "P")
(let ((version "rcirc.el 0.9 $Revision: 1.4 $"))
(if here
(insert version)
(if (interactive-p)
(message "%s" version)
version))))
(defvar rcirc-startup-channels nil)
;;;###autoload
(defun rcirc (&optional server port nick channels)
......@@ -181,7 +223,7 @@ If optional argument HERE is non-nil, insert string at point."
If any of the the optional SERVER, PORT, NICK or CHANNELS are not
supplied, they are taken from the variables `rcirc-server',
`rcirc-port', `rcirc-nick', and `rcirc-startup-channels',
`rcirc-port', `rcirc-nick', and `rcirc-startup-channels-alist',
respectively."
(interactive (list (read-string "IRC Server: " rcirc-server)
(read-string "IRC Port: " (number-to-string rcirc-port))
......@@ -192,19 +234,19 @@ respectively."
(or channels
(setq channels
(if (interactive-p)
(delete ""
(split-string
(read-string "Channels: "
(mapconcat 'identity
(rcirc-startup-channels server)
" "))
"[, ]+"))
(split-string
(read-string "Channels: "
(mapconcat 'identity
(rcirc-startup-channels server)
" "))
"[, ]+" t)
(rcirc-startup-channels server))))
(or global-mode-string (setq global-mode-string '("")))
(and (not (memq 'rcirc-activity-string global-mode-string))
(setq global-mode-string
(append global-mode-string '(rcirc-activity-string))))
(add-hook 'window-configuration-change-hook 'rcirc-update-activity)
(add-hook 'window-configuration-change-hook
'rcirc-window-configuration-change)
(rcirc-connect server port nick rcirc-user-name rcirc-user-full-name
channels))
......@@ -213,7 +255,6 @@ respectively."
(defvar rcirc-process-output nil)
(defvar rcirc-last-buffer nil)
(defvar rcirc-topic nil)
(defvar rcirc-keepalive-timer nil)
(make-variable-buffer-local 'rcirc-topic)
......@@ -233,10 +274,12 @@ STARTUP-CHANNELS will automatically be joined on startup."
;; set up process
(set-process-coding-system process 'raw-text 'raw-text)
(set-process-filter process 'rcirc-filter)
(switch-to-buffer (concat "*" (process-name process) "*"))
(switch-to-buffer (rcirc-generate-new-buffer-name process nil))
(set-process-buffer process (current-buffer))
(set-process-sentinel process 'rcirc-sentinel)
(rcirc-mode process nil)
(make-local-variable 'rcirc-buffer-alist)
(setq rcirc-buffer-alist nil)
(make-local-variable 'rcirc-nick-table)
(setq rcirc-nick-table (make-hash-table :test 'equal))
(make-local-variable 'rcirc-server)
......@@ -245,12 +288,6 @@ STARTUP-CHANNELS will automatically be joined on startup."
(setq rcirc-nick nick)
(make-local-variable 'rcirc-process-output)
(setq rcirc-process-output nil)
(make-local-variable 'rcirc-last-buffer)
(setq rcirc-last-buffer (current-buffer))
(make-local-variable 'rcirc-channels)
(setq rcirc-channels nil)
(make-local-variable 'rcirc-private-chats)
(setq rcirc-private-chats nil)
(make-local-variable 'rcirc-startup-channels)
(setq rcirc-startup-channels startup-channels)
......@@ -270,34 +307,39 @@ STARTUP-CHANNELS will automatically be joined on startup."
;; return process object
process)))
(defmacro with-rcirc-process-buffer (process &rest body)
(declare (indent 1) (debug t))
`(with-current-buffer (process-buffer ,process)
,@body))
(defun rcirc-keepalive ()
"Send keep alive pings to active rcirc processes."
(if (rcirc-process-list)
(mapc (lambda (process)
(with-current-buffer (process-buffer process)
(with-rcirc-process-buffer process
(rcirc-send-string process (concat "PING " rcirc-server))))
(rcirc-process-list))
(cancel-timer rcirc-keepalive-timer)
(setq rcirc-keepalive-timer nil)))
(defvar rcirc-log-buffer "*rcirc log*")
(defvar rcirc-log-p nil
"If non-nil, write information to `rcirc-log-buffer'.")
(defun rcirc-log (process text)
(defvar rcirc-debug-buffer " *rcirc debug*")
(defvar rcirc-debug-flag nil
"If non-nil, write information to `rcirc-debug-buffer'.")
(defun rcirc-debug (process text)
"Add an entry to the debug log including PROCESS and TEXT.
Debug text is written to `rcirc-log-buffer' if `rcirc-log-p' is
non-nil."
(when rcirc-log-p
Debug text is written to `rcirc-debug-buffer' if `rcirc-debug-p'
is non-nil."
(when rcirc-debug-flag
(save-excursion
(save-window-excursion
(set-buffer (get-buffer-create rcirc-log-buffer))
(set-buffer (get-buffer-create rcirc-debug-buffer))
(goto-char (point-max))
(insert (concat
"["
(format-time-string "%Y-%m-%dT%T ") (process-name process)
"] "
text))))))
(defvar rcirc-sentinel-hooks nil
"Hook functions called when the process sentinel is called.
Functions are called with PROCESS and SENTINEL arguments.")
......@@ -305,20 +347,16 @@ Functions are called with PROCESS and SENTINEL arguments.")
(defun rcirc-sentinel (process sentinel)
"Called when PROCESS receives SENTINEL."
(let ((sentinel (replace-regexp-in-string "\n" "" sentinel)))
(rcirc-log process (format "SENTINEL: %S %S\n" process sentinel))
(with-current-buffer (process-buffer process)
(dolist (target (append rcirc-channels
rcirc-private-chats
(list (current-buffer))))
(rcirc-print process "rcirc.el" "ERROR" target
(rcirc-debug process (format "SENTINEL: %S %S\n" process sentinel))
(with-rcirc-process-buffer process
(dolist (buffer (cons nil (mapcar 'cdr rcirc-buffer-alist)))
(rcirc-print process "rcirc.el" "ERROR" buffer
(format "%s: %s (%S)"
(process-name process)
sentinel
(process-status process)) t)
;; remove the prompt from buffers
(with-current-buffer (if (eq target (current-buffer))
(current-buffer)
(rcirc-get-buffer process target))
(with-current-buffer (or buffer (current-buffer))
(let ((inhibit-read-only t))
(delete-region rcirc-prompt-start-marker
rcirc-prompt-end-marker)))))
......@@ -329,7 +367,7 @@ Functions are called with PROCESS and SENTINEL arguments.")
(let (ps)
(mapc (lambda (p)
(when (process-buffer p)
(with-current-buffer (process-buffer p)
(with-rcirc-process-buffer p
(when (eq major-mode 'rcirc-mode)
(setq ps (cons p ps))))))
(process-list))
......@@ -340,24 +378,24 @@ Functions are called with PROCESS and SENTINEL arguments.")
Function is called with PROCESS COMMAND SENDER ARGS and LINE.")
(defun rcirc-filter (process output)
"Called when PROCESS receives OUTPUT."
(rcirc-log process output)
(with-current-buffer (process-buffer process)
(rcirc-debug process output)
(with-rcirc-process-buffer process
(setq rcirc-process-output (concat rcirc-process-output output))
(when (= (aref rcirc-process-output
(1- (length rcirc-process-output))) ?\n)
(mapc (lambda (line)
(rcirc-process-server-response process line))
(delete "" (split-string rcirc-process-output "[\n\r]")))
(split-string rcirc-process-output "[\n\r]" t))
(setq rcirc-process-output nil))))
(defvar rcirc-trap-errors nil)
(defvar rcirc-trap-errors-flag t)
(defun rcirc-process-server-response (process text)
(if rcirc-trap-errors
(if rcirc-trap-errors-flag
(condition-case err
(rcirc-process-server-response-1 process text)
(error
(rcirc-print process "RCIRC" "ERROR" nil
(format "rcirc: error processing: \"%s\" %s" text err))))
(format "\"%s\" %s" text err) t)))
(rcirc-process-server-response-1 process text)))
(defun rcirc-process-server-response-1 (process text)
......@@ -369,8 +407,8 @@ Function is called with PROCESS COMMAND SENDER ARGS and LINE.")
(string-match "^\\([^:]*\\):?\\(.+\\)?$" args)
(let* ((args1 (match-string 1 args))
(args2 (match-string 2 args))
(args (append (delete "" (split-string args1 " "))
(list args2))))
(args (delq nil (append (split-string args1 " " t)
(list args2)))))
(if (not (fboundp handler))
(rcirc-handler-generic process cmd sender args text)
(funcall handler process sender args text))
......@@ -381,24 +419,24 @@ Function is called with PROCESS COMMAND SENDER ARGS and LINE.")
(defun rcirc-handler-generic (process command sender args text)
"Generic server response handler."
(rcirc-print process sender command nil
(mapconcat 'identity (cdr args) " ")))
(mapconcat 'identity (cdr args) " ") t))
(defun rcirc-send-string (process string)
"Send PROCESS a STRING plus a newline."
(let ((string (concat (encode-coding-string string
buffer-file-coding-system)
"\n")))
(rcirc-log process string)
(rcirc-debug process string)
(process-send-string process string)))
(defun rcirc-server (process)
"Return PROCESS server, given by the 001 response."
(with-current-buffer (process-buffer process)
(with-rcirc-process-buffer process
rcirc-server))
(defun rcirc-nick (process)
"Return PROCESS nick."
(with-current-buffer (process-buffer process)
(with-rcirc-process-buffer process
rcirc-nick))
(defvar rcirc-max-message-length 450
......@@ -418,7 +456,9 @@ If NOTICEP is non-nil, send a notice instead of privmsg."
text))
(more (if oversize
(substring message rcirc-max-message-length))))
(rcirc-print process (rcirc-nick process) response target text)
(rcirc-print process (rcirc-nick process) response
(rcirc-get-buffer-create process target)
text)
(rcirc-send-string process (concat response " " target " :" text))
(if more
(rcirc-send-message process target more noticep))))
......@@ -459,8 +499,8 @@ If NOTICEP is non-nil, send a notice instead of privmsg."
rcirc-prompt-end-marker))
(setq rcirc-nick-completions
(let ((completion-ignore-case t))
(all-completions
(buffer-substring
(all-completions
(buffer-substring
(+ rcirc-prompt-end-marker
rcirc-nick-completion-start-offset)
(point))
......@@ -469,11 +509,11 @@ If NOTICEP is non-nil, send a notice instead of privmsg."
(rcirc-buffer-target)))))))
(let ((completion (car rcirc-nick-completions)))
(when completion
(delete-region (+ rcirc-prompt-end-marker
(delete-region (+ rcirc-prompt-end-marker
rcirc-nick-completion-start-offset)
(point))
(insert (concat completion
(if (= (+ rcirc-prompt-end-marker
(if (= (+ rcirc-prompt-end-marker
rcirc-nick-completion-start-offset)
rcirc-prompt-end-marker)
": "))))))
......@@ -507,7 +547,7 @@ If buffer is nil, return the target of the current buffer."
(define-key rcirc-mode-map (kbd "C-c C-w") 'rcirc-cmd-whois)
(define-key rcirc-mode-map (kbd "C-c C-x") 'rcirc-cmd-quit)
(define-key rcirc-mode-map (kbd "C-c TAB") ; C-i
'rcirc-toggle-ignore-channel-activity)
'rcirc-toggle-ignore-buffer-activity)
(define-key rcirc-mode-map (kbd "C-c C-s") 'rcirc-switch-to-server-buffer)
(define-key rcirc-mode-map (kbd "C-c C-a") 'rcirc-jump-to-first-unread-line)
......@@ -515,6 +555,15 @@ If buffer is nil, return the target of the current buffer."
(define-key global-map (kbd "C-c C-@") 'rcirc-next-active-buffer)
(define-key global-map (kbd "C-c C-SPC") 'rcirc-next-active-buffer)
(defvar rcirc-browse-url-map (make-sparse-keymap)
"Keymap used ror browsing URLs in `rcirc-mode'.")
(define-key rcirc-browse-url-map (kbd "RET") 'rcirc-browse-url-at-point)
(define-key rcirc-browse-url-map (kbd "<mouse-2>") 'rcirc-browse-url-at-mouse)
(defvar rcirc-short-buffer-name nil
"Generated abbreviation to use to indicate buffer activity.")
(defvar rcirc-mode-hook nil
"Hook run when setting up rcirc buffer.")
......@@ -533,11 +582,12 @@ If buffer is nil, return the target of the current buffer."
(setq rcirc-process process)
(make-local-variable 'rcirc-target)
(setq rcirc-target target)
(make-local-variable 'rcirc-short-buffer-name)
(setq rcirc-short-buffer-name nil)
(make-local-variable 'rcirc-urls)
(setq rcirc-urls nil)
(setq use-hard-newlines t)
(when (rcirc-channel-p rcirc-target)
(setq header-line-format 'rcirc-topic))
;; setup the prompt and markers
(make-local-variable 'rcirc-prompt-start-marker)
......@@ -552,38 +602,59 @@ If buffer is nil, return the target of the current buffer."
(setq overlay-arrow-position (make-marker))
(set-marker overlay-arrow-position nil)
;; add to buffer list, and update buffer abbrevs
(when target ; skip server buffer
(let ((buffer (current-buffer)))
(with-rcirc-process-buffer process
(setq rcirc-buffer-alist (cons (cons target buffer)
rcirc-buffer-alist))))
(rcirc-update-short-buffer-names))
(run-hooks 'rcirc-mode-hook))
(defmacro with-rcirc-process-buffer (process &rest body)
(declare (indent 1) (debug t))
`(with-current-buffer (process-buffer ,process)
,@body))
(defun rcirc-update-prompt (&optional all)
"Reset the prompt string in the current buffer.
(defun rcirc-update-prompt ()
"Reset the prompt string in the current buffer."
(let ((inhibit-read-only t)
(prompt (or rcirc-prompt "")))
(mapc (lambda (rep)
(setq prompt
(replace-regexp-in-string (car rep) (cdr rep) prompt)))
(list (cons "%n" (with-rcirc-process-buffer rcirc-process
rcirc-nick))
(cons "%s" (with-rcirc-process-buffer rcirc-process
rcirc-server))
(cons "%t" (or rcirc-target ""))))
(save-excursion
(delete-region rcirc-prompt-start-marker rcirc-prompt-end-marker)
(goto-char rcirc-prompt-start-marker)
(let ((start (point)))
(insert-before-markers prompt)
(set-marker rcirc-prompt-start-marker start)
(when (not (zerop (- rcirc-prompt-end-marker
rcirc-prompt-start-marker)))
(add-text-properties rcirc-prompt-start-marker
rcirc-prompt-end-marker
(list 'face 'rcirc-prompt-face
'read-only t 'field t
'front-sticky t 'rear-nonsticky t)))))))
If ALL is non-nil, update prompts in all IRC buffers."
(if all
(mapc (lambda (process)
(mapc (lambda (buffer)
(with-current-buffer buffer
(rcirc-update-prompt)))
(with-rcirc-process-buffer process
(mapcar 'cdr rcirc-buffer-alist))))
(rcirc-process-list))
(let ((inhibit-read-only t)
(prompt (or rcirc-prompt "")))
(mapc (lambda (rep)
(setq prompt
(replace-regexp-in-string (car rep) (regexp-quote (cdr rep)) prompt)))
(list (cons "%n" (with-rcirc-process-buffer rcirc-process
rcirc-nick))
(cons "%s" (with-rcirc-process-buffer rcirc-process
rcirc-server))
(cons "%t" (or rcirc-target ""))))
(save-excursion
(delete-region rcirc-prompt-start-marker rcirc-prompt-end-marker)
(goto-char rcirc-prompt-start-marker)
(let ((start (point)))
(insert-before-markers prompt)
(set-marker rcirc-prompt-start-marker start)
(when (not (zerop (- rcirc-prompt-end-marker
rcirc-prompt-start-marker)))
(add-text-properties rcirc-prompt-start-marker
rcirc-prompt-end-marker
(list 'face 'rcirc-prompt
'read-only t 'field t
'front-sticky t 'rear-nonsticky t))))))))
(defun rcirc-set-changed (option value)
"Set OPTION to VALUE and do updates after a customization change."
(set-default option value)
(cond ((eq option 'rcirc-prompt)
(rcirc-update-prompt 'all))
(t
(error "Bad option %s" option))))
(defun rcirc-channel-p (target)
"Return t if TARGET is a channel name."
......@@ -595,65 +666,67 @@ If buffer is nil, return the target of the current buffer."
(defun rcirc-kill-buffer-hook ()
"Part the channel when killing an rcirc buffer."
(when (eq major-mode 'rcirc-mode)
(rcirc-clear-activity (current-buffer))
(rcirc-kill-buffer-hook-1)))
(defun rcirc-kill-buffer-hook-1 ()
(let ((buffer (current-buffer)))
(rcirc-clear-activity buffer)
(when (and rcirc-process
(eq (process-status rcirc-process) 'open))
(eq (process-status rcirc-process) 'open))
(with-rcirc-process-buffer rcirc-process
(setq rcirc-buffer-alist
(rassq-delete-all buffer rcirc-buffer-alist)))
(rcirc-update-short-buffer-names)
(if (rcirc-channel-p rcirc-target)
(rcirc-cmd-part "" rcirc-process rcirc-target)
;; remove target from privchat list
(when rcirc-target
(let ((target (downcase rcirc-target)))
(with-rcirc-process-buffer rcirc-process
(setq rcirc-private-chats
(delete target rcirc-private-chats)))))))))
(rcirc-send-string rcirc-process
(concat "PART " rcirc-target
" :Killed buffer"))