summaryrefslogtreecommitdiff
path: root/lisp/erc
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/erc')
-rw-r--r--lisp/erc/ChangeLog324
-rw-r--r--lisp/erc/erc-backend.el111
-rw-r--r--lisp/erc/erc-button.el2
-rw-r--r--lisp/erc/erc-compat.el13
-rw-r--r--lisp/erc/erc-goodies.el15
-rw-r--r--lisp/erc/erc-identd.el3
-rw-r--r--lisp/erc/erc-log.el95
-rw-r--r--lisp/erc/erc-sound.el12
-rw-r--r--lisp/erc/erc-stamp.el76
-rw-r--r--lisp/erc/erc-track.el103
-rw-r--r--lisp/erc/erc.el257
11 files changed, 824 insertions, 187 deletions
diff --git a/lisp/erc/ChangeLog b/lisp/erc/ChangeLog
index 43f4c230d14..f262a6324fb 100644
--- a/lisp/erc/ChangeLog
+++ b/lisp/erc/ChangeLog
@@ -1,26 +1,346 @@
+2007-09-18 Exal de Jesus Garcia Carrillo <exal@gmx.de> (tiny change)
+
+ * erc.texi (Special-Features): Fix small typo.
+
+2007-09-16 Michael Olson <mwolson@gnu.org>
+
+ * erc-track.el (erc-track-switch-direction): Mention
+ erc-track-faces-priority-list. Thanks to Leo for the suggestion.
+
+2007-09-11 Exal de Jesus Garcia Carrillo <exal@gnu.org> (tiny change)
+
+ * erc-sound.el: Fix typo in setting up instructions.
+
+2007-09-10 Michael Olson <mwolson@gnu.org>
+
+ * Makefile (elpa): Copy dir template rather than echoing a few
+ lines. The reason for this is that the ELPA package for ERC was
+ getting a corrupt dir entry.
+
+ * dir-template: Template for the ELPA dir file.
+
+2007-09-08 Michael Olson <mwolson@gnu.org>
+
+ * erc-log.el (erc-log-filter-function): New option that specifies
+ the function to call for filtering text before writing it to a log
+ file. Thanks to David O'Toole for the suggestion.
+ (erc-save-buffer-in-logs): Use erc-log-filter-function. Make sure
+ we carry along the value of coding-system-for-write, because this
+ could potentially be shadowed by the temporary buffer.
+
+ * erc.el (erc-version-string): Update to 5.3, development version.
+
+2007-09-07 Glenn Morris <rgm@gnu.org>
+
+ * erc.el (erc-toggle-debug-irc-protocol): Fix call to
+ erc-view-mode-enter.
+
2007-08-08 Glenn Morris <rgm@gnu.org>
* erc-log.el, erc.el: Replace `iff' in doc-strings and comments.
+2007-09-03 Michael Olson <mwolson@gnu.org>
+
+ * erc.el (erc-default-port): Make this an integer value rather
+ than a string. Thanks to Luca Capello for the report.
+
+2007-08-27 Michael Olson <mwolson@gnu.org>
+
+ * erc.el (erc-cmd-GQUIT): If erc-kill-queries-on-quit is non-nil,
+ kill all query buffers after 4 seconds.
+
+2007-08-16 Michael Olson <mwolson@gnu.org>
+
+ * NEWS: Add ERC 5.3 changes section, and mention jbms' erc-track
+ compatibility note.
+
+ * erc-track.el (erc-track-list-changed-hook): Turn this into a
+ customizable option.
+ (erc-track-switch-direction): Add 'importance option.
+ (erc-modified-channels-display): If erc-track-switch-direction is
+ 'importance, call erc-track-sort-by-importance.
+ (erc-track-face-priority): New function that returns a number
+ indicating the position of a face in
+ erc-track-faces-priority-list.
+ (erc-track-sort-by-importance): New function that sorts
+ erc-modified-channels-list according to erc-track-face-priority.
+ (erc-track-get-active-buffer): Make 'oldest a rough opposite of
+ 'importance.
+
+2007-08-14 Jeremy Maitin-Shepard <jbms@cmu.edu>
+
+ * erc-track.el (erc-track-remove-disconnected-buffers): New
+ variable which controls whether buffers associated with a server
+ that is disconnected should be removed from
+ `erc-modified-channels-alist'. Existing behavior is to
+ unconditionally remove such buffers, which is achieved by setting
+ `erc-track-removed-disconnected-buffers' to t. When set to t,
+ which is the new default value, such buffers remain in the list,
+ which I think is often the desired behavior, since the user may
+ likely wish to find out about activity that occurred in a channel
+ prior to it being disconnected.
+ (erc-track-list-changed-hook): New hook that is run whenever the
+ contents of `erc-modified-channels-alist' changes; it is useful
+ for users such as myself that don't use the default mode-line
+ notification but instead use a separate mechanism (which is tied
+ to my window manager) to provide notification of channel activity.
+ (erc-track-get-buffer-window): New function that acts as a wrapper
+ around `get-buffer-window' that handles the `selected-visible'
+ option of `erc-track-visibility'; previously, the value of
+ `erc-track-visibility' was passed directly to `get-buffer-window',
+ which does not support `selected-visible'; consequently,
+ `selected-visible' was not properly supported.
+ (erc-track-modified-channels): Fix a bug in the logic for removing
+ buffers from the list in certain cases.
+ (erc-track-position-in-mode-line): Add a supported value that
+ specifies that the tracking information should not be added to the
+ mode line at all. The value of nil is used to indicate that the
+ information should not be added at all to the mode line.
+ (erc-track-add-to-mode-line): Check for position eq to t, rather
+ than non-nil.
+ (erc-buffer-visible): Use erc-track-get-buffer-window.
+ (erc-modified-channels-update): Take
+ erc-track-remove-disconnected-buffers into account.
+ (erc-modified-channels-display): Run
+ `erc-track-list-changed-hook'.
+
+ * erc.el (erc-reuse-frames): New option that determines whether
+ new frames are always created. Defaults to t. This only has an
+ effect when erc-join-buffer is set to 'frame.
+ (erc-setup-buffer): Use it.
+
+2007-08-14 Michael Olson <mwolson@gnu.org>
+
+ * erc-backend.el (erc-server-reconnect): If the server buffer has
+ been killed, use the current buffer instead. If the current
+ buffer is not an ERC buffer, give an error. This fixes a bug when
+ /reconnect is run from a channel buffer whose server buffer has
+ been deleted. Thanks to jbms for the report.
+ (erc-process-sentinel-1): Take server buffer as an argument, so
+ that we can make sure that it is current.
+ (erc-process-sentinel): Pass buffer to erc-process-sentinel-1.
+ (erc-process-sentinel-2): New function split from
+ erc-process-sentinel-1. If server buffer is deleted during a
+ reconnect attempt, stop trying to reconnect. Fix bug where
+ reconnect was not happening when erc-server-reconnect-attempts was
+ t. Call erc-server-reconnect-p only once each time. If we are
+ instructed to try connecting indefinitely, tell the user that they
+ can stop this by killing the server buffer. Call the process
+ sentinel by means of run-at-time, so that there is time to kill
+ the buffer if need be; this also removes the need for a while
+ loop. Refuse to reconnect again if erc-server-reconnect-timeout
+ is not an number.
+
+ * erc.el (erc-command-no-process-p): Fix bug: the return value of
+ erc-extract-command-from-line is a list rather than a single
+ symbol. Thanks to jbms for the report.
+ (erc-cmd-RECONNECT): Use simpler logic, and use buffer-live-p
+ rather than bufferp.
+ (erc-send-current-line, erc-display-command, erc-display-msg):
+ Handle case where erc-server-process is nil, so that /reconnect
+ works.
+
+2007-08-12 Michael Olson <mwolson@gnu.org>
+
+ * erc-identd.el (erc-identd-filter): Instead of sending an EOF
+ character, which now confuses freenode, stop the server process,
+ so that no new connections are accepted, and kill the current
+ client process.
+
2007-07-30 Michael Olson <mwolson@gnu.org>
* erc-nicklist.el: Remove from the Emacs source tree. This file
is not release quality, and relies heavily on a module which
cannot be distributed with ERC due to licensing reasons.
+2007-07-29 Michael Olson <mwolson@gnu.org>
+
+ * erc-list.el: Relicense to GPLv3. Since the file was already
+ licensed under version 2 or later, it turns out that we do not
+ need the permission of all of the authors in order to proceed.
+
2007-07-25 Glenn Morris <rgm@gnu.org>
* Relicense all FSF files to GPLv3 or later.
+2007-07-13 Michael Olson <mwolson@gnu.org>
+
+ * erc-goodies.el (erc-get-bg-color-face, erc-get-fg-color-face):
+ Use erc-error rather than message and beep.
+
+ * erc-sound.el: Indentation fix.
+
+ * erc.el (erc-command-no-process-p): New function that determines
+ if its argument is an ERC command that can be run when the server
+ process is not alive.
+ (erc-cmd-SET, erc-cmd-CLEAR, erc-cmd-COUNTRY, erc-cmd-HELP)
+ (erc-cmd-LASTLOG, erc-cmd-QUIT, erc-cmd-GQUIT)
+ (erc-cmd-RECONNECT, erc-cmd-SERVER): Denote that these commands
+ can be run even when the server process is not alive.
+ (erc-send-current-line): Call erc-command-no-process-p if the
+ server process is not alive, to determine if we have a command
+ that can be run anyway. Thanks to Tom Tromey for the bug report.
+ (erc-error): New function that either displays a message or throws
+ an error, depending on whether debug-on-error is non-nil.
+ (erc-cmd-SERVER, erc-send-current-line): Use it.
+
+2007-07-10 Michael Olson <mwolson@gnu.org>
+
+ * Relicense all FSF-assigned code to GPLv3.
+
+2007-06-25 Michael Olson <mwolson@gnu.org>
+
+ * erc.texi (Options): Fix typo.
+ (Getting Help and Reporting Bugs): Update webpage URL. Make Gmane
+ part more readable.
+
+2007-06-20 Michael Olson <mwolson@gnu.org>
+
+ * erc-stamp.el (erc-timestamp-format-left): New option that
+ specifies the left timestamp to use for
+ erc-insert-timestamp-left-and-right.
+ (erc-timestamp-format-right): New option that specifies the right
+ timestamp to use for erc-insert-timestamp-left-and-right.
+ (erc-insert-timestamp-function): Change default to
+ erc-insert-timestamp-left-and-right.
+ (erc-insert-away-timestamp-function): Ditto.
+ (erc-timestamp-last-inserted-left)
+ (erc-timestamp-last-inserted-right): New variables to keep track
+ of data for erc-insert-timestamp-left-and-right.
+ (erc-insert-timestamp-left-and-right): New function that places
+ timestamps on both the left and right sides of the screen, but
+ only if each timestamp has changed since it was last computed.
+ Thanks to offby1 for urging me to merge this.
+
+ * erc.el (erc-open-ssl-stream): Display informative error when
+ ssl.el not found.
+ (erc-tls): New function to connect using tls.el.
+ (erc-open-tls-stream): New function to initiate tls connection.
+ Display informative error when tls.el not found.
+
+2007-06-19 Michael Olson <mwolson@gnu.org>
+
+ * erc-log.el: Update header with accurate instructions.
+
+2007-06-17 Michael Olson <mwolson@gnu.org>
+
+ * erc-pkg.el: Update description to match what is currently in
+ ELPA.
+
2007-06-14 Juanma Barranquero <lekktu@gmail.com>
* erc-goodies.el (erc-scroll-to-bottom): Remove redundant check.
+2007-06-13 Michael Olson <mwolson@gnu.org>
+
+ * erc-compat.el (erc-with-selected-window): New compatibility
+ macro that implements `with-selected-window'.
+
+ * erc-goodies.el (erc-scroll-to-bottom): Use it. This fixes a bug
+ with buffer ordering where ERC buffers would move to the top.
+ Thanks to Ivan Kanis for the patch.
+
+2007-06-10 Michael Olson <mwolson@gnu.org>
+
+ * erc-log.el (erc-logging-enabled): Fix a bug that occurred when
+ `erc-log-channels-directory' had the name of a function.
+
2007-06-06 Juanma Barranquero <lekktu@gmail.com>
* erc.el (erc-show-channel-key-p, erc-startup-file-list):
Fix typo in docstring.
+2007-06-03 Michael Olson <mwolson@gnu.org>
+
+ * erc-compat.el (erc-view-mode-enter): Make this its own function,
+ in order to document what we do, and provide sane fallback
+ behavior.
+
+ * erc.el (erc-toggle-debug-irc-protocol): Don't pass any arguments
+ to erc-view-mode-enter, since we don't do anything special with
+ the exit function. This fixes a bug with Emacs 21 and Emacs 22.
+ Thanks to Leo for noticing.
+
+2007-05-30 Michael Olson <mwolson@gnu.org>
+
+ * erc-compat.el (erc-user-emacs-directory): New variable that
+ determines where to find user-specific Emacs settings. For Emacs,
+ this is usually ~/.emacs.d, and for XEmacs this is usually
+ ~/.xemacs.
+
+ * erc.el (erc-startup-file-list): Use erc-user-emacs-directory.
+
+2007-05-28 Michael Olson <mwolson@gnu.org>
+
+ * erc-button.el (erc-button-url-regexp): Recognize parentheses as
+ part of URLs. Thanks to Lawrence Mitchell for the fix.
+
+2007-05-26 Michael Olson <mwolson@gnu.org>
+
+ * erc.texi (Modules): Fix references to completion modules.
+
+2007-05-21 Michael Olson <mwolson@gnu.org>
+
+ * Makefile (SOURCE): Remove erc-pkg.el.
+ (debclean): New rule to clean old Debian packages of ERC.
+ (debprepare): Don't modify the released tarball, but copy it as
+ the .orig.tar.gz file.
+ (debrelease. debrevision): Remove.
+ (debinstall): New target that copies the generated Debian file to
+ a distro-specific location.
+ (deb): New rule that chains together the stages in building a
+ Debian package.
+ (EXTRAS): Add erc-nicklist.el, since it is not release-quality.
+ (extras): Copy images directory.
+
+ * erc-nicklist.el (erc-nicklist-icons-directory): Use
+ locate-library to find the "images" directory. This should be
+ more failsafe. Thanks to Tom Tromey for the idea.
+
+2007-05-19 Michael Olson <mwolson@gnu.org>
+
+ * Makefile (ELPA): New variable that contains the location of my
+ local ELPA repository.
+ (elpa): New rule that makes an ELPA package for ERC.
+
+2007-04-19 Michael Olson <mwolson@gnu.org>
+
+ * erc.el (erc-parse-prefix): New function that retrieves the
+ PREFIX server parameter from the current server and returns an
+ alist of prefix type to prefix character.
+ (erc-channel-receive-names): Use `erc-parse-prefix' to determine
+ whether the first character of a nick is a prefix character or
+ not. This should fix a bug reported by bromine about needing to
+ type "%" first to complete nicks of people who are "hops" on
+ Slashnet. This should also support for very exotic IRC server
+ setups, if any exist.
+ (erc-update-current-channel-member): Indentation.
+
+2007-04-15 Michael Olson <mwolson@gnu.org>
+
+ * erc-log.el (erc-generate-log-file-name-function): Docfix.
+ Mention how to deal with the case for putting log files in
+ different directories. Change a customization type from `symbol'
+ to `function'.
+ (erc-log-channels-directory): Allow this to contain a function
+ name, which is called with the same args as in
+ `erc-generate-log-file-name-function'. Thanks to andrewy for the
+ report and use case.
+ (erc-current-logfile): Detect if `erc-log-channels-directory' is a
+ function and call it with arguments if so.
+
+2007-04-12 Michael Olson <mwolson@gnu.org>
+
+ * erc-backend.el (define-erc-response-handler): Mention that hook
+ processing stops when the function returns non-nil. This should
+ help avoid a nasty "gotcha" when making custom functions. Thanks
+ to John Sullivan for the report.
+
+2007-04-08 Diane Murray <disumu@x3y2z1.net>
+
+ * erc-nicklist.el (erc-nicklist-voiced-position): Fixed
+ customization mismatch.
+
2007-04-01 Michael Olson <mwolson@gnu.org>
* erc.el (erc-version-string): Release ERC 5.2.
@@ -49,6 +369,10 @@
tarball.
(upload-extras): New rule to upload the extras tarball. It's
yucky to replicate upload, but oh well.
+ (DISTRIBUTOR): New variable used to differentiate between building
+ packages for Ubuntu and Debian.
+ (debrelease, debrevision): Use it.
+ (debbuild): Run linda in addition to lintian.
* NEWS: Mention extras tarball. Note which files have been
renamed. Note that erc-list is enabled by default, except in
diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el
index 349f9137066..4e250490e9c 100644
--- a/lisp/erc/erc-backend.el
+++ b/lisp/erc/erc-backend.el
@@ -550,11 +550,12 @@ We will store server variables in the buffer given by BUFFER."
(defun erc-server-reconnect ()
"Reestablish the current IRC connection.
Make sure you are in an ERC buffer when running this."
- (let ((server (erc-server-buffer)))
- (unless (and server
- (buffer-live-p server))
- (error "Couldn't switch to server buffer"))
- (with-current-buffer server
+ (let ((buffer (erc-server-buffer)))
+ (unless (buffer-live-p buffer)
+ (if (eq major-mode 'erc-mode)
+ (setq buffer (current-buffer))
+ (error "Reconnect must be run from an ERC buffer")))
+ (with-current-buffer buffer
(erc-update-mode-line)
(erc-set-active-buffer (current-buffer))
(setq erc-server-last-sent-time 0)
@@ -609,39 +610,61 @@ EVENT is the message received from the closed connection process."
;; open-network-stream-nowait error for connection refused
(not (string-match "^failed with code 111" event)))))
-(defun erc-process-sentinel-1 (event)
+(defun erc-process-sentinel-2 (event buffer)
+ "Called when `erc-process-sentinel-1' has detected an unexpected disconnect."
+ (if (not (buffer-live-p buffer))
+ (erc-update-mode-line)
+ (with-current-buffer buffer
+ (let ((reconnect-p (erc-server-reconnect-p event)))
+ (erc-display-message nil 'error (current-buffer)
+ (if reconnect-p 'disconnected
+ 'disconnected-noreconnect))
+ (if (not reconnect-p)
+ ;; terminate, do not reconnect
+ (progn
+ (erc-display-message nil 'error (current-buffer)
+ 'terminated ?e event)
+ ;; Update mode line indicators
+ (erc-update-mode-line)
+ (set-buffer-modified-p nil))
+ ;; reconnect
+ (condition-case err
+ (progn
+ (setq erc-server-reconnecting nil)
+ (erc-server-reconnect)
+ (setq erc-server-reconnect-count 0))
+ (error (when (buffer-live-p buffer)
+ (set-buffer buffer)
+ (if (integerp erc-server-reconnect-attempts)
+ (setq erc-server-reconnect-count
+ (1+ erc-server-reconnect-count))
+ (message "%s ... %s"
+ "Reconnecting until we succeed"
+ "kill the ERC server buffer to stop"))
+ (if (numberp erc-server-reconnect-timeout)
+ (run-at-time erc-server-reconnect-timeout nil
+ #'erc-process-sentinel-2
+ event buffer)
+ (error (concat "`erc-server-reconnect-timeout`"
+ " must be a number")))))))))))
+
+(defun erc-process-sentinel-1 (event buffer)
"Called when `erc-process-sentinel' has decided that we're disconnecting.
Determine whether user has quit or whether erc has been terminated.
Conditionally try to reconnect and take appropriate action."
- (if erc-server-quitting
- ;; normal quit
- (progn
- (erc-display-message nil 'error (current-buffer) 'finished)
- (when erc-kill-server-buffer-on-quit
+ (with-current-buffer buffer
+ (if erc-server-quitting
+ ;; normal quit
+ (progn
+ (erc-display-message nil 'error (current-buffer) 'finished)
+ ;; Update mode line indicators
+ (erc-update-mode-line)
+ ;; Kill server buffer if user wants it
(set-buffer-modified-p nil)
- (kill-buffer (current-buffer))))
- ;; unexpected disconnect
- (let ((again t))
- (while again
- (setq again nil)
- (erc-display-message nil 'error (current-buffer)
- (if (erc-server-reconnect-p event)
- 'disconnected
- 'disconnected-noreconnect))
- (if (erc-server-reconnect-p event)
- (condition-case err
- (progn
- (setq erc-server-reconnecting nil)
- (erc-server-reconnect)
- (setq erc-server-reconnect-count 0))
- (error (when (integerp erc-server-reconnect-attempts)
- (setq erc-server-reconnect-count
- (1+ erc-server-reconnect-count))
- (sit-for erc-server-reconnect-timeout)
- (setq again t))))
- ;; terminate, do not reconnect
- (erc-display-message nil 'error (current-buffer)
- 'terminated ?e event))))))
+ (when erc-kill-server-buffer-on-quit
+ (kill-buffer (current-buffer))))
+ ;; unexpected disconnect
+ (erc-process-sentinel-2 event buffer))))
(defun erc-process-sentinel (cproc event)
"Sentinel function for ERC process."
@@ -668,12 +691,7 @@ Conditionally try to reconnect and take appropriate action."
(delete-region (point) (point-max))
;; Decide what to do with the buffer
;; Restart if disconnected
- (erc-process-sentinel-1 event)
- ;; Make sure we don't write to the buffer if it has been
- ;; killed
- (when (buffer-live-p buf)
- (erc-update-mode-line)
- (set-buffer-modified-p nil))))))
+ (erc-process-sentinel-1 event buf)))))
;;;; Sending messages
@@ -1054,8 +1072,11 @@ Would expand to:
\"Some non-generic variable documentation.
Hook called upon receiving a WHOIS server response.
+
Each function is called with two arguments, the process associated
- with the response and the parsed response.
+ with the response and the parsed response. If the function returns
+ non-nil, stop processing the hook. Otherwise, continue.
+
See also `erc-server-311'.\")
(defalias 'erc-server-WI 'erc-server-311)
@@ -1064,7 +1085,9 @@ Would expand to:
Hook called upon receiving a WI server response.
Each function is called with two arguments, the process associated
- with the response and the parsed response.
+ with the response and the parsed response. If the function returns
+ non-nil, stop processing the hook. Otherwise, continue.
+
See also `erc-server-311'.\"))
\(fn (NAME &rest ALIASES) &optional EXTRA-FN-DOC EXTRA-VAR-DOC &rest FN-BODY)"
@@ -1078,7 +1101,9 @@ Would expand to:
(fn-name (intern (format "erc-server-%s" name)))
(hook-doc (format "%sHook called upon receiving a %%s server response.
Each function is called with two arguments, the process associated
-with the response and the parsed response.
+with the response and the parsed response. If the function returns
+non-nil, stop processing the hook. Otherwise, continue.
+
See also `%s'."
(if extra-var-doc
(concat extra-var-doc "\n\n")
diff --git a/lisp/erc/erc-button.el b/lisp/erc/erc-button.el
index 35a20d5279f..81c604d0538 100644
--- a/lisp/erc/erc-button.el
+++ b/lisp/erc/erc-button.el
@@ -99,7 +99,7 @@ above them."
(concat "\\(www\\.\\|\\(s?https?\\|"
"ftp\\|file\\|gopher\\|news\\|telnet\\|wais\\|mailto\\):\\)"
"\\(//[-a-zA-Z0-9_.]+:[0-9]*\\)?"
- "[-a-zA-Z0-9_=!?#$@~`%&*+\\/:;.,]+[-a-zA-Z0-9_=#$@~`%&*+\\/]")
+ "[-a-zA-Z0-9_=!?#$@~`%&*+\\/:;.,()]+[-a-zA-Z0-9_=#$@~`%&*+\\/()]")
"Regular expression that matches URLs."
:group 'erc-button
:type 'regexp)
diff --git a/lisp/erc/erc-compat.el b/lisp/erc/erc-compat.el
index 8be3bed1a78..47bdd94ade2 100644
--- a/lisp/erc/erc-compat.el
+++ b/lisp/erc/erc-compat.el
@@ -56,6 +56,18 @@ See `erc-encoding-coding-alist'."
(format-time-string "%Y-%m-%d" emacs-build-time))
"Time at which Emacs was dumped out.")
+;; Emacs 21 and XEmacs do not have user-emacs-directory, but XEmacs
+;; has user-init-directory.
+(defvar erc-user-emacs-directory
+ (cond ((boundp 'user-emacs-directory)
+ user-emacs-directory)
+ ((boundp 'user-init-directory)
+ user-init-directory)
+ (t "~/.emacs.d/"))
+ "Directory beneath which additional per-user Emacs-specific files
+are placed.
+Note that this should end with a directory separator.")
+
;; XEmacs' `replace-match' does not replace matching subexpressions in strings.
(defun erc-replace-match-subexpression-in-string
(newtext string match subexp start &optional fixedcase literal)
@@ -68,6 +80,7 @@ See `replace-match' for explanations of FIXEDCASE and LITERAL."
(replace-match newtext fixedcase literal string))
(t (replace-match newtext fixedcase literal string subexp))))
+(defalias 'erc-with-selected-window 'with-selected-window)
(defalias 'erc-cancel-timer 'cancel-timer)
(defalias 'erc-make-obsolete 'make-obsolete)
(defalias 'erc-make-obsolete-variable 'make-obsolete-variable)
diff --git a/lisp/erc/erc-goodies.el b/lisp/erc/erc-goodies.el
index 49a04513733..9131ce68282 100644
--- a/lisp/erc/erc-goodies.el
+++ b/lisp/erc/erc-goodies.el
@@ -84,8 +84,7 @@ DISPLAY-START is ignored."
;; works, but it solves the problem, and has no negative side effects.
;; (Fran Litterio, 2003/01/07)
(let ((resize-mini-windows nil))
- (save-selected-window
- (select-window window)
+ (erc-with-selected-window window
(save-restriction
(widen)
(when (and erc-insert-marker
@@ -282,10 +281,8 @@ The value `erc-interpret-controls-p' must also be t for this to work."
"Fetches the right face for background color N (0-15)."
(if (stringp n) (setq n (string-to-number n)))
(if (not (numberp n))
- (progn
- (message "erc-get-bg-color-face: n is NaN: %S" n)
- (beep)
- 'default)
+ (prog1 'default
+ (erc-error "erc-get-bg-color-face: n is NaN: %S" n))
(when (> n 16)
(erc-log (format " Wrong color: %s" n))
(setq n (mod n 16)))
@@ -298,10 +295,8 @@ The value `erc-interpret-controls-p' must also be t for this to work."
"Fetches the right face for foreground color N (0-15)."
(if (stringp n) (setq n (string-to-number n)))
(if (not (numberp n))
- (progn
- (message "erc-get-fg-color-face: n is NaN: %S" n)
- (beep)
- 'default)
+ (prog1 'default
+ (erc-error "erc-get-fg-color-face: n is NaN: %S" n))
(when (> n 16)
(erc-log (format " Wrong color: %s" n))
(setq n (mod n 16)))
diff --git a/lisp/erc/erc-identd.el b/lisp/erc/erc-identd.el
index 4b72ee171b3..db933094e19 100644
--- a/lisp/erc/erc-identd.el
+++ b/lisp/erc/erc-identd.el
@@ -74,7 +74,8 @@ This can be either a string or a number."
(format "%s, %s : USERID : %s : %s\n"
port-on-server port-on-client
system-type (user-login-name)))
- (process-send-eof erc-identd-process)))))
+ (stop-process erc-identd-process)
+ (delete-process proc)))))
;;;###autoload
(defun erc-identd-start (&optional port)
diff --git a/lisp/erc/erc-log.el b/lisp/erc/erc-log.el
index 88132afae0c..1733b3d1b00 100644
--- a/lisp/erc/erc-log.el
+++ b/lisp/erc/erc-log.el
@@ -31,17 +31,26 @@
;; Quick start:
;;
-;; (setq erc-enable-logging t)
+;; (require 'erc-log)
;; (setq erc-log-channels-directory "/path/to/logfiles") ; must be writable
+;; (erc-log-enable)
;;
-;; There are two ways to setup logging. The first will write to the log files
-;; on each incoming or outgoing line - this may not be optimal on a laptop
-;; HDD. To do this, M-x customize-variable erc-modules, and add "log".
+;; Or:
;;
-;; The second method will save buffers on /part, /quit, or killing the
-;; channel buffer. To do this, add the following to your .emacs:
+;; M-x customize-variable erc-modules, and add "log".
;;
-;; (require 'erc-log)
+;; There are two ways to setup logging. The first (default) method
+;; will save buffers on /part, /quit, or killing the channel
+;; buffer.
+;;
+;; The second will write to the log files on each incoming or outgoing
+;; line - this may not be optimal on a laptop HDD. To use this
+;; method, add the following to the above instructions.
+;;
+;; (setq erc-save-buffer-on-part nil
+;; erc-save-queries-on-quit nil
+;; erc-log-write-after-send t
+;; erc-log-write-after-insert t)
;;
;; If you only want to save logs for some buffers, customise the
;; variable `erc-enable-logging'.
@@ -99,15 +108,19 @@ The function must take five arguments: BUFFER, TARGET, NICK, SERVER and PORT.
BUFFER is the buffer to be saved,
TARGET is the name of the channel, or the target of the query,
NICK is the current nick,
-SERVER and PORT are the parameters used to connect BUFFERs
-`erc-server-process'."
+SERVER and PORT are the parameters that were used to connect to BUFFERs
+`erc-server-process'.
+
+If you want to write logs into different directories, make a
+custom function which returns the directory part and set
+`erc-log-channels-directory' to its name."
:group 'erc-log
:type '(choice (const :tag "Long style" erc-generate-log-file-name-long)
(const :tag "Long, but with network name rather than server"
erc-generate-log-file-name-network)
(const :tag "Short" erc-generate-log-file-name-short)
(const :tag "With date" erc-generate-log-file-name-with-date)
- (symbol :tag "Other function")))
+ (function :tag "Other function")))
(defcustom erc-truncate-buffer-on-save nil
"Truncate any ERC (channel, query, server) buffer when it is saved."
@@ -134,10 +147,16 @@ Log files are stored in `erc-log-channels-directory'."
"The directory to place log files for channels.
Leave blank to disable logging. If not nil, all the channel
buffers are logged in separate files in that directory. The
-directory should not end with a trailing slash."
+directory should not end with a trailing slash.
+
+If this is the name of a function, the function will be called
+with the buffer, target, nick, server, and port arguments. See
+`erc-generate-log-file-name-function' for a description of these
+arguments."
:group 'erc-log
:type '(choice directory
- (const nil)))
+ (function "Function")
+ (const :tag "Disable logging" nil)))
(defcustom erc-log-insert-log-on-open nil
"*Insert log file contents into the buffer if a log file exists."
@@ -186,6 +205,16 @@ This should ideally, be a \"catch-all\" coding system, like
`emacs-mule', or `iso-2022-7bit'."
:group 'erc-log)
+(defcustom erc-log-filter-function nil
+ "*If non-nil, pass text through the given function before writing it to
+a log file.
+
+The function should take one argument, which is the text to filter."
+ :group 'erc-log
+ :type '(choice (function "Function")
+ (const :tag "No filtering" nil)))
+
+
;;;###autoload (autoload 'erc-log-mode "erc-log" nil t)
(define-erc-module log nil
"Automatically logs things you receive on IRC into files.
@@ -297,7 +326,8 @@ Logging is enabled if `erc-log-channels-directory' is non-nil, the directory
is writeable (it will be created as necessary) and
`erc-enable-logging' returns a non-nil value."
(and erc-log-channels-directory
- (erc-directory-writable-p erc-log-channels-directory)
+ (or (functionp erc-log-channels-directory)
+ (erc-directory-writable-p erc-log-channels-directory))
(if (functionp erc-enable-logging)
(funcall erc-enable-logging (or buffer (current-buffer)))
erc-enable-logging)))
@@ -316,14 +346,19 @@ filename is downcased."
If BUFFER is nil, the value of `current-buffer' is used.
This is determined by `erc-generate-log-file-name-function'.
The result is converted to lowercase, as IRC is case-insensitive"
- (expand-file-name
- (erc-log-standardize-name
- (funcall erc-generate-log-file-name-function
- (or buffer (current-buffer))
- (or (buffer-name buffer) (erc-default-target))
- (erc-current-nick)
- erc-session-server erc-session-port))
- erc-log-channels-directory))
+ (unless buffer (setq buffer (current-buffer)))
+ (let ((target (or (buffer-name buffer) (erc-default-target)))
+ (nick (erc-current-nick))
+ (server erc-session-server)
+ (port erc-session-port))
+ (expand-file-name
+ (erc-log-standardize-name
+ (funcall erc-generate-log-file-name-function
+ buffer target nick server port))
+ (if (functionp erc-log-channels-directory)
+ (funcall erc-log-channels-directory
+ buffer target nick server port)
+ erc-log-channels-directory))))
(defun erc-generate-log-file-name-with-date (buffer &rest ignore)
"This function computes a short log file name.
@@ -380,17 +415,25 @@ You can save every individual message by putting this function on
(or buffer (setq buffer (current-buffer)))
(when (erc-logging-enabled buffer)
(let ((file (erc-current-logfile buffer))
- (coding-system-for-write erc-log-file-coding-system))
+ (coding-system erc-log-file-coding-system))
(save-excursion
(with-current-buffer buffer
(save-restriction
(widen)
- ;; early on in the initalisation, don't try and write the log out
+ ;; early on in the initialization, don't try and write the log out
(when (and (markerp erc-last-saved-position)
(> erc-insert-marker (1+ erc-last-saved-position)))
- (write-region (1+ (marker-position erc-last-saved-position))
- (marker-position erc-insert-marker)
- file t 'nomessage)
+ (let ((start (1+ (marker-position erc-last-saved-position)))
+ (end (marker-position erc-insert-marker)))
+ (if (functionp erc-log-filter-function)
+ (let ((text (buffer-substring start end)))
+ (with-temp-buffer
+ (insert (funcall erc-log-filter-function text))
+ (let ((coding-system-for-write coding-system))
+ (write-region (point-min) (point-max)
+ file t 'nomessage))))
+ (let ((coding-system-for-write coding-system))
+ (write-region start end file t 'nomessage))))
(if (and erc-truncate-buffer-on-save (interactive-p))
(progn
(let ((inhibit-read-only t)) (erase-buffer))
diff --git a/lisp/erc/erc-sound.el b/lisp/erc/erc-sound.el
index 4d3d792b1b8..7a1a28198bf 100644
--- a/lisp/erc/erc-sound.el
+++ b/lisp/erc/erc-sound.el
@@ -30,7 +30,7 @@
;; Add the following to your .emacs if you want to play sounds.
;;
-;; (require 'erc-soud)
+;; (require 'erc-sound)
;; (erc-sound-enable)
;;
;; To send requests to other users from within query buffers, type the
@@ -125,7 +125,7 @@ See also `play-sound-file'."
(if (and (not filepath) erc-default-sound)
(setq filepath erc-default-sound))
(cond ((and filepath (file-exists-p filepath))
- (play-sound-file filepath))
+ (play-sound-file filepath))
(t (beep)))
(erc-log (format "Playing sound file %S" filepath))))
@@ -142,5 +142,11 @@ See also `play-sound-file'."
(provide 'erc-sound)
-;; arch-tag: 53657d1d-007f-4a20-91c1-588e71cf0cee
;;; erc-sound.el ends here
+;;
+;; Local Variables:
+;; indent-tabs-mode: t
+;; tab-width: 8
+;; End:
+
+;; arch-tag: 53657d1d-007f-4a20-91c1-588e71cf0cee
diff --git a/lisp/erc/erc-stamp.el b/lisp/erc/erc-stamp.el
index d67dffeaede..3b7f5ba18f2 100644
--- a/lisp/erc/erc-stamp.el
+++ b/lisp/erc/erc-stamp.el
@@ -58,16 +58,48 @@ If nil, timestamping is turned off."
:type '(choice (const nil)
(string)))
-(defcustom erc-insert-timestamp-function 'erc-insert-timestamp-right
+(defcustom erc-timestamp-format-left "\n[%a %b %e %Y]\n"
+ "*If set to a string, messages will be timestamped.
+This string is processed using `format-time-string'.
+Good examples are \"%T\" and \"%H:%M\".
+
+This timestamp is used for timestamps on the left side of the
+screen when `erc-insert-timestamp-function' is set to
+`erc-insert-timestamp-left-and-right'.
+
+If nil, timestamping is turned off."
+ :group 'erc-stamp
+ :type '(choice (const nil)
+ (string)))
+
+(defcustom erc-timestamp-format-right " [%H:%M]"
+ "*If set to a string, messages will be timestamped.
+This string is processed using `format-time-string'.
+Good examples are \"%T\" and \"%H:%M\".
+
+This timestamp is used for timestamps on the right side of the
+screen when `erc-insert-timestamp-function' is set to
+`erc-insert-timestamp-left-and-right'.
+
+If nil, timestamping is turned off."
+ :group 'erc-stamp
+ :type '(choice (const nil)
+ (string)))
+
+(defcustom erc-insert-timestamp-function 'erc-insert-timestamp-left-and-right
"*Function to use to insert timestamps.
It takes a single argument STRING which is the final string
which all text-properties already appended. This function only cares about
inserting this string at the right position. Narrowing is in effect
while it is called, so (point-min) and (point-max) determine the region to
-operate on."
+operate on.
+
+You will probably want to set
+`erc-insert-away-timestamp-function' to the same value."
:group 'erc-stamp
- :type '(choice (const :tag "Right" erc-insert-timestamp-right)
+ :type '(choice (const :tag "Both sides" erc-insert-timestamp-left-and-right)
+ (const :tag "Right" erc-insert-timestamp-right)
(const :tag "Left" erc-insert-timestamp-left)
function))
@@ -82,12 +114,14 @@ If `erc-timestamp-format' is set, this will not be used."
:type '(choice (const nil)
(string)))
-(defcustom erc-insert-away-timestamp-function 'erc-insert-timestamp-right
+(defcustom erc-insert-away-timestamp-function
+ 'erc-insert-timestamp-left-and-right
"*Function to use to insert the away timestamp.
See `erc-insert-timestamp-function' for details."
:group 'erc-stamp
- :type '(choice (const :tag "Right" erc-insert-timestamp-right)
+ :type '(choice (const :tag "Both sides" erc-insert-timestamp-left-and-right)
+ (const :tag "Right" erc-insert-timestamp-right)
(const :tag "Left" erc-insert-timestamp-left)
function))
@@ -160,6 +194,18 @@ or `erc-send-modify-hook'."
"Last timestamp inserted into the buffer.")
(make-variable-buffer-local 'erc-timestamp-last-inserted)
+(defvar erc-timestamp-last-inserted-left nil
+ "Last timestamp inserted into the left side of the buffer.
+This is used when `erc-insert-timestamp-function' is set to
+`erc-timestamp-left-and-right'")
+(make-variable-buffer-local 'erc-timestamp-last-inserted-left)
+
+(defvar erc-timestamp-last-inserted-right nil
+ "Last timestamp inserted into the right side of the buffer.
+This is used when `erc-insert-timestamp-function' is set to
+`erc-timestamp-left-and-right'")
+(make-variable-buffer-local 'erc-timestamp-last-inserted-right)
+
(defcustom erc-timestamp-only-if-changed-flag t
"*Insert timestamp only if its value changed since last insertion.
If `erc-insert-timestamp-function' is `erc-insert-timestamp-left', a
@@ -272,6 +318,26 @@ be printed just before the window-width."
(when erc-timestamp-intangible
(erc-put-text-property from (1+ (point)) 'intangible t)))))
+(defun erc-insert-timestamp-left-and-right (string)
+ "This is another function that can be assigned to
+`erc-insert-timestamp-function'. If the date is changed, it will
+print a blank line, the date, and another blank line. If the time is
+changed, it will then print it off to the right."
+ (let* ((ct (current-time))
+ (ts-left (erc-format-timestamp ct erc-timestamp-format-left))
+ (ts-right (erc-format-timestamp ct erc-timestamp-format-right)))
+ ;; insert left timestamp
+ (unless (string-equal ts-left erc-timestamp-last-inserted-left)
+ (goto-char (point-min))
+ (erc-put-text-property 0 (length ts-left) 'field 'erc-timestamp ts-left)
+ (insert ts-left)
+ (setq erc-timestamp-last-inserted-left ts-left))
+ ;; insert right timestamp
+ (let ((erc-timestamp-only-if-changed-flag t)
+ (erc-timestamp-last-inserted erc-timestamp-last-inserted-right))
+ (erc-insert-timestamp-right ts-right)
+ (setq erc-timestamp-last-inserted-right ts-right))))
+
;; for testing: (setq erc-timestamp-only-if-changed-flag nil)
(defun erc-format-timestamp (time format)
diff --git a/lisp/erc/erc-track.el b/lisp/erc/erc-track.el
index f72a5be1de1..1408adcd942 100644
--- a/lisp/erc/erc-track.el
+++ b/lisp/erc/erc-track.el
@@ -95,6 +95,12 @@ Activity means that there was no user input in the last 10 seconds."
:group 'erc-track
:type '(repeat string))
+(defcustom erc-track-remove-disconnected-buffers nil
+ "*If true, remove buffers associated with a server that is
+disconnected from `erc-modified-channels-alist'."
+ :group 'erc-track
+ :type 'boolean)
+
(defcustom erc-track-exclude-types '("NICK")
"*List of message types to be ignored.
This list could look like '(\"JOIN\" \"PART\")."
@@ -151,6 +157,16 @@ If nil instead of a function, shortening is disabled."
:type '(choice (const :tag "Disabled")
function))
+(defcustom erc-track-list-changed-hook nil
+ "Hook that is run whenever the contents of
+`erc-modified-channels-alist' changes.
+
+This is useful for people that don't use the default mode-line
+notification but instead use a separate mechanism to provide
+notification of channel activity."
+ :group 'erc-track
+ :type 'hook)
+
(defcustom erc-track-use-faces t
"*Use faces in the mode-line.
The faces used are the same as used for text in the buffers.
@@ -192,12 +208,14 @@ Setting this variable only has effects in GNU Emacs versions above 21.3.
Choices are:
'before-modes - add to the beginning of `mode-line-modes'
'after-modes - add to the end of `mode-line-modes'
-
-Any other value means add to the end of `global-mode-string'."
+t - add to the end of `global-mode-string'.
+nil - don't add to mode line
+"
:group 'erc-track
:type '(choice (const :tag "Just before mode information" before-modes)
(const :tag "Just after mode information" after-modes)
- (const :tag "After all other information" nil))
+ (const :tag "After all other information" t)
+ (const :tag "Don't display in mode line" nil))
:set (lambda (sym val)
(set sym val)
(when (and (boundp 'erc-track-mode)
@@ -263,12 +281,18 @@ when there are no more active channels."
(defcustom erc-track-switch-direction 'oldest
"Direction `erc-track-switch-buffer' should switch.
+ importance - find buffer with the most important message
oldest - find oldest active buffer
newest - find newest active buffer
leastactive - find buffer with least unseen messages
- mostactive - find buffer with most unseen messages."
+ mostactive - find buffer with most unseen messages.
+
+If set to 'importance, the importance is determined by position
+in `erc-track-faces-priority-list', where first is most
+important."
:group 'erc-track
- :type '(choice (const oldest)
+ :type '(choice (const importance)
+ (const oldest)
(const newest)
(const leastactive)
(const mostactive)))
@@ -296,7 +320,7 @@ See `erc-track-position-in-mode-line' for possible values."
(boundp 'mode-line-modes))
(add-to-list 'mode-line-modes
'(t erc-modified-channels-object) t))
- (t
+ ((eq position t)
(when (not global-mode-string)
(setq global-mode-string '(""))) ; Padding for mode-line wart
(add-to-list 'global-mode-string
@@ -644,14 +668,21 @@ only consider active buffers visible.")
(setq erc-buffer-activity (erc-current-time))
(erc-track-modified-channels))
+(defun erc-track-get-buffer-window (buffer frame-param)
+ (if (eq frame-param 'selected-visible)
+ (if (eq (frame-visible-p (selected-frame)) t)
+ (get-buffer-window buffer nil)
+ nil)
+ (get-buffer-window buffer frame-param)))
+
(defun erc-buffer-visible (buffer)
"Return non-nil when the buffer is visible."
(if erc-track-when-inactive
(when erc-buffer-activity; could be nil
- (and (get-buffer-window buffer erc-track-visibility)
+ (and (erc-track-get-buffer-window buffer erc-track-visibility)
(<= (erc-time-diff erc-buffer-activity (erc-current-time))
erc-buffer-activity-timeout)))
- (get-buffer-window buffer erc-track-visibility)))
+ (erc-track-get-buffer-window buffer erc-track-visibility)))
;;; Tracking the channel modifications
@@ -668,18 +699,22 @@ called via `window-configuration-change-hook'.
ARGS are ignored."
(interactive)
(unless erc-modified-channels-update-inside
- (let ((erc-modified-channels-update-inside t))
+ (let ((erc-modified-channels-update-inside t)
+ (removed-channel nil))
(mapcar (lambda (elt)
(let ((buffer (car elt)))
(when (or (not (bufferp buffer))
(not (buffer-live-p buffer))
(erc-buffer-visible buffer)
+ (and erc-track-remove-disconnected-buffers
(not (with-current-buffer buffer
- erc-server-connected)))
+ erc-server-connected))))
+ (setq removed-channel t)
(erc-modified-channels-remove-buffer buffer))))
erc-modified-channels-alist)
+ (when removed-channel
(erc-modified-channels-display)
- (force-mode-line-update t))))
+ (force-mode-line-update t)))))
(defvar erc-track-mouse-face (if (featurep 'xemacs)
'modeline-mousable
@@ -729,10 +764,13 @@ If FACES are provided, color STRING with them."
"Set `erc-modified-channels-object'
according to `erc-modified-channels-alist'.
Use `erc-make-mode-line-buffer-name' to create buttons."
- (if (or
- (eq 'mostactive erc-track-switch-direction)
- (eq 'leastactive erc-track-switch-direction))
- (erc-track-sort-by-activest))
+ (cond ((or (eq 'mostactive erc-track-switch-direction)
+ (eq 'leastactive erc-track-switch-direction))
+ (erc-track-sort-by-activest))
+ ((eq 'importance erc-track-switch-direction)
+ (erc-track-sort-by-importance)))
+ (run-hooks 'erc-track-list-changed-hook)
+ (unless (eq erc-track-position-in-mode-line nil)
(if (null erc-modified-channels-alist)
(setq erc-modified-channels-object (erc-modified-channels-object nil))
;; erc-modified-channels-alist contains all the data we need. To
@@ -768,7 +806,7 @@ Use `erc-make-mode-line-buffer-name' to create buttons."
(when (featurep 'xemacs)
(erc-modified-channels-object nil))
(setq erc-modified-channels-object
- (erc-modified-channels-object strings)))))
+ (erc-modified-channels-object strings))))))
(defun erc-modified-channels-remove-buffer (buffer)
"Remove BUFFER from `erc-modified-channels-alist'."
@@ -802,8 +840,7 @@ is in `erc-mode'."
(if (and (not (erc-buffer-visible (current-buffer)))
(not (member this-channel erc-track-exclude))
(not (and erc-track-exclude-server-buffer
- (string= this-channel
- (buffer-name (erc-server-buffer)))))
+ (erc-server-buffer-p)))
(not (erc-message-type-member
(or (erc-find-parsed-property)
(point-min))
@@ -847,10 +884,10 @@ is in `erc-mode'."
(erc-modified-channels-display)))
;; Else if the active buffer is the current buffer, remove it
;; from our list.
- (when (or (erc-buffer-visible (current-buffer))
+ (when (and (or (erc-buffer-visible (current-buffer))
(and this-channel
- (assq (current-buffer) erc-modified-channels-alist)
(member this-channel erc-track-exclude)))
+ (assq (current-buffer) erc-modified-channels-alist))
;; Remove it from mode-line if buffer is visible or
;; channel was added to erc-track-exclude recently.
(erc-modified-channels-remove-buffer (current-buffer))
@@ -887,6 +924,29 @@ That means the number of unseen messages in a channel."
(sort erc-modified-channels-alist
(lambda (a b) (> (nth 1 a) (nth 1 b))))))
+(defun erc-track-face-priority (face)
+ "Return a number indicating the priority of FACE in
+`erc-track-faces-priority-list'. Lower number means higher
+priority.
+
+If face is not in `erc-track-faces-priority-list', it will have a
+higher number than any other face in that list."
+ (let ((count 0))
+ (catch 'done
+ (dolist (item erc-track-faces-priority-list)
+ (if (eq item face)
+ (throw 'done t)
+ (setq count (1+ count)))))
+ count))
+
+(defun erc-track-sort-by-importance ()
+ "Sort erc-modified-channels-alist by importance.
+That means the position of the face in `erc-track-faces-priority-list'."
+ (setq erc-modified-channels-alist
+ (sort erc-modified-channels-alist
+ (lambda (a b) (< (erc-track-face-priority (cddr a))
+ (erc-track-face-priority (cddr b)))))))
+
(defun erc-track-get-active-buffer (arg)
"Return the buffer name of ARG in `erc-modified-channels-alist'.
Negative arguments index in the opposite direction. This direction is
@@ -898,7 +958,8 @@ relative to `erc-track-switch-direction'"
(oldest 'newest)
(newest 'oldest)
(mostactive 'leastactive)
- (leastactive 'mostactive)))
+ (leastactive 'mostactive)
+ (importance 'oldest)))
(setq arg (- arg)))
(setq offset (case dir
((oldest leastactive)
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index c26bdf2a19f..2c5786adff3 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -66,7 +66,7 @@
;;; Code:
-(defconst erc-version-string "Version 5.2"
+(defconst erc-version-string "Version 5.3 (devel)"
"ERC version. This is used by function `erc-version'.")
(eval-when-compile (require 'cl))
@@ -836,8 +836,9 @@ See `erc-server-flood-margin' for other flood-related parameters.")
;; Script parameters
(defcustom erc-startup-file-list
- '("~/.emacs.d/.ercrc.el" "~/.emacs.d/.ercrc"
- "~/.ercrc.el" "~/.ercrc" ".ercrc.el" ".ercrc")
+ (list (concat erc-user-emacs-directory ".ercrc.el")
+ (concat erc-user-emacs-directory ".ercrc")
+ "~/.ercrc.el" "~/.ercrc" ".ercrc.el" ".ercrc")
"List of files to try for a startup script.
The first existent and readable one will get executed.
@@ -1460,7 +1461,7 @@ Turning on `erc-mode' runs the hook `erc-mode-hook'."
(defconst erc-default-server "irc.freenode.net"
"IRC server to use if it cannot be detected otherwise.")
-(defconst erc-default-port "6667"
+(defconst erc-default-port 6667
"IRC port to use if it cannot be detected otherwise.")
(defcustom erc-join-buffer 'buffer
@@ -1491,6 +1492,14 @@ This only has effect when `erc-join-buffer' is set to `frame'."
:group 'erc-buffers
:type 'boolean)
+(defcustom erc-reuse-frames t
+ "*Determines whether new frames are always created.
+Non-nil means that a new frame is not created to display an ERC
+buffer if there is already a window displaying it. This only has
+effect when `erc-join-buffer' is set to `frame'."
+ :group 'erc-buffers
+ :type 'boolean)
+
(defun erc-channel-p (channel)
"Return non-nil if CHANNEL seems to be an IRC channel name."
(cond ((stringp channel)
@@ -1888,14 +1897,16 @@ removed from the list will be disabled."
((eq erc-join-buffer 'bury)
nil)
((eq erc-join-buffer 'frame)
- (funcall '(lambda (frame)
+ (when (or (not erc-reuse-frames)
+ (not (get-buffer-window buffer t)))
+ ((lambda (frame)
(raise-frame frame)
(select-frame frame))
(make-frame (or erc-frame-alist
default-frame-alist)))
(switch-to-buffer buffer)
(when erc-frame-dedicated-flag
- (set-window-dedicated-p (selected-window) t)))
+ (set-window-dedicated-p (selected-window) t))))
(t
(if (active-minibuffer-window)
(display-buffer buffer)
@@ -2155,16 +2166,48 @@ Arguments are the same as for `erc'."
"Open an SSL stream to an IRC server.
The process will be given the name NAME, its target buffer will be
BUFFER. HOST and PORT specify the connection target."
- (when (require 'tls)
- (let ((proc (open-tls-stream name buffer host port)))
+ (when (condition-case nil
+ (require 'ssl)
+ (error (message "You don't have ssl.el. %s"
+ "Try using `erc-tls' instead.")
+ nil))
+ (let ((proc (open-ssl-stream name buffer host port)))
;; Ugly hack, but it works for now. Problem is it is
;; very hard to detect when ssl is established, because s_client
;; doesn't give any CONNECTIONESTABLISHED kind of message, and
;; most IRC servers send nothing and wait for you to identify.
- ;; Disabled when switching to tls.el -- jas
- ;(sit-for 5)
+ (sit-for 5)
proc)))
+(defun erc-tls (&rest r)
+ "Interactively select TLS connection parameters and run ERC.
+Arguments are the same as for `erc'."
+ (interactive (erc-select-read-args))
+ (let ((erc-server-connect-function 'erc-open-tls-stream))
+ (apply 'erc r)))
+
+(defun erc-open-tls-stream (name buffer host port)
+ "Open an TLS stream to an IRC server.
+The process will be given the name NAME, its target buffer will be
+BUFFER. HOST and PORT specify the connection target."
+ (when (condition-case nil
+ (require 'tls)
+ (error (message "You don't have tls.el. %s"
+ "Try using `erc-ssl' instead.")
+ nil))
+ (open-tls-stream name buffer host port)))
+
+;;; Displaying error messages
+
+(defun erc-error (&rest args)
+ "Pass ARGS to `format', and display the result as an error message.
+If `debug-on-error' is set to non-nil, then throw a real error with this
+message instead, to make debugging easier."
+ (if debug-on-error
+ (apply #'error args)
+ (apply #'message args)
+ (beep)))
+
;;; Debugging the protocol
(defvar erc-debug-irc-protocol nil
@@ -2228,7 +2271,7 @@ If ARG is non-nil, show the *erc-protocol* buffer."
(interactive "P")
(let* ((buf (get-buffer-create "*erc-protocol*")))
(with-current-buffer buf
- (erc-view-mode-enter 1)
+ (erc-view-mode-enter)
(when (null (current-local-map))
(let ((inhibit-read-only t))
(insert (erc-make-notice "This buffer displays all IRC protocol traffic exchanged with each server.\n"))
@@ -2456,6 +2499,14 @@ See also `erc-server-send'."
(match-string 1 arglist)
arglist)))
+(defun erc-command-no-process-p (str)
+ "Return non-nil if STR is an ERC command that can be run when the process
+is not alive, nil otherwise."
+ (let ((fun (erc-extract-command-from-line str)))
+ (and fun
+ (symbolp (car fun))
+ (get (car fun) 'process-not-needed))))
+
(defun erc-command-name (cmd)
"For CMD being the function name of a ERC command, something like
erc-cmd-FOO, this returns a string /FOO."
@@ -2565,6 +2616,7 @@ VALUE is computed by evaluating the rest of LINE in Lisp."
(defalias 'erc-cmd-VAR 'erc-cmd-SET)
(defalias 'erc-cmd-VARIABLE 'erc-cmd-SET)
(put 'erc-cmd-SET 'do-not-parse-args t)
+(put 'erc-cmd-SET 'process-not-needed t)
(defun erc-cmd-default (line)
"Fallback command.
@@ -2623,6 +2675,7 @@ If no USER argument is specified, list the contents of `erc-ignore-list'."
"Clear the window content."
(recenter 0)
t)
+(put 'erc-cmd-CLEAR 'process-not-needed t)
(defun erc-cmd-OPS ()
"Show the ops in the current channel."
@@ -2656,6 +2709,7 @@ If no USER argument is specified, list the contents of `erc-ignore-list'."
(erc-display-message
nil 'notice 'active 'country-unknown ?d tld))
t))
+(put 'erc-cmd-COUNTRY 'process-not-needed t)
(defun erc-cmd-AWAY (line)
"Mark the user as being away, the reason being indicated by LINE.
@@ -2736,6 +2790,7 @@ For a list of user commands (/join /part, ...):
t))
(defalias 'erc-cmd-H 'erc-cmd-HELP)
+(put 'erc-cmd-HELP 'process-not-needed t)
(defun erc-cmd-JOIN (channel &optional key)
"Join the channel given in CHANNEL, optionally with KEY.
@@ -2973,6 +3028,7 @@ the matching is case-sensitive."
(occur line)
t)
(put 'erc-cmd-LASTLOG 'do-not-parse-args t)
+(put 'erc-cmd-LASTLOG 'process-not-needed t)
(defun erc-send-message (line &optional force)
"Send LINE to the current channel or user and display it.
@@ -3195,20 +3251,34 @@ the message given by REASON."
(defalias 'erc-cmd-EXIT 'erc-cmd-QUIT)
(defalias 'erc-cmd-SIGNOFF 'erc-cmd-QUIT)
(put 'erc-cmd-QUIT 'do-not-parse-args t)
+(put 'erc-cmd-QUIT 'process-not-needed t)
(defun erc-cmd-GQUIT (reason)
"Disconnect from all servers at once with the same quit REASON."
(erc-with-all-buffers-of-server nil #'erc-open-server-buffer-p
- (erc-cmd-QUIT reason)))
+ (erc-cmd-QUIT reason))
+ (when erc-kill-queries-on-quit
+ ;; if the query buffers have not been killed within 4 seconds,
+ ;; kill them
+ (run-at-time
+ 4 nil
+ (lambda ()
+ (dolist (buffer (erc-buffer-list (lambda (buf)
+ (not (erc-server-buffer-p buf)))))
+ (kill-buffer buffer)))))
+ t)
(defalias 'erc-cmd-GQ 'erc-cmd-GQUIT)
(put 'erc-cmd-GQUIT 'do-not-parse-args t)
+(put 'erc-cmd-GQUIT 'process-not-needed t)
(defun erc-cmd-RECONNECT ()
"Try to reconnect to the current IRC server."
- (let ((buffer (or (erc-server-buffer) (current-buffer)))
+ (let ((buffer (erc-server-buffer))
(process nil))
- (with-current-buffer (if (bufferp buffer) buffer (current-buffer))
+ (unless (buffer-live-p buffer)
+ (setq buffer (current-buffer)))
+ (with-current-buffer buffer
(setq erc-server-quitting nil)
(setq erc-server-reconnecting t)
(setq erc-server-reconnect-count 0)
@@ -3218,6 +3288,7 @@ the message given by REASON."
(erc-server-reconnect))
(setq erc-server-reconnecting nil)))
t)
+(put 'erc-cmd-RECONNECT 'process-not-needed t)
(defun erc-cmd-SERVER (server)
"Connect to SERVER, leaving existing connection intact."
@@ -3225,9 +3296,9 @@ the message given by REASON."
(condition-case nil
(erc :server server :nick (erc-current-nick))
(error
- (message "Cannot find host %s." server)
- (beep)))
+ (erc-error "Cannot find host %s." server)))
t)
+(put 'erc-cmd-SERVER 'process-not-needed t)
(eval-when-compile
(defvar motif-version-string)
@@ -4411,33 +4482,65 @@ See also `erc-channel-begin-receiving-names'."
erc-channel-users)
(setq erc-channel-new-member-names nil))
+(defun erc-parse-prefix ()
+ "Return an alist of valid prefix character types and their representations.
+Example: (operator) o => @, (voiced) v => +."
+ (let ((str (or (cdr (assoc "PREFIX" (erc-with-server-buffer
+ erc-server-parameters)))
+ ;; provide a sane default
+ "(ov)@+"))
+ types chars)
+ (when (string-match "^(\\([^)]+\\))\\(.+\\)$" str)
+ (setq types (match-string 1 str)
+ chars (match-string 2 str))
+ (let ((len (min (length types) (length chars)))
+ (i 0)
+ (alist nil))
+ (while (< i len)
+ (setq alist (cons (cons (elt types i) (elt chars i))
+ alist))
+ (setq i (1+ i)))
+ alist))))
+
(defun erc-channel-receive-names (names-string)
"This function is for internal use only.
Update `erc-channel-users' according to NAMES-STRING.
NAMES-STRING is a string listing some of the names on the
channel."
- (let (names name op voice)
- ;; We need to delete "" because in XEmacs, (split-string "a ")
- ;; returns ("a" "").
- (setq names (delete "" (split-string names-string)))
- (let ((erc-channel-members-changed-hook nil))
- (dolist (item names)
- (cond ((string-match "^@\\(.*\\)$" item)
- (setq name (match-string 1 item)
- op 'on
- voice 'off))
- ((string-match "^+\\(.*\\)$" item)
- (setq name (match-string 1 item)
- op 'off
- voice 'on))
- (t (setq name item
- op 'off
- voice 'off)))
- (puthash (erc-downcase name) t
- erc-channel-new-member-names)
- (erc-update-current-channel-member
- name name t op voice)))
+ (let (prefix op-ch voice-ch names name op voice)
+ (setq prefix (erc-parse-prefix))
+ (setq op-ch (cdr (assq ?o prefix))
+ voice-ch (cdr (assq ?v prefix)))
+ ;; We need to delete "" because in XEmacs, (split-string "a ")
+ ;; returns ("a" "").
+ (setq names (delete "" (split-string names-string)))
+ (let ((erc-channel-members-changed-hook nil))
+ (dolist (item names)
+ (let ((updatep t)
+ ch)
+ (if (rassq (elt item 0) prefix)
+ (cond ((= (length item) 1)
+ (setq updatep nil))
+ ((eq (elt item 0) op-ch)
+ (setq name (substring item 1)
+ op 'on
+ voice 'off))
+ ((eq (elt item 0) voice-ch)
+ (setq name (substring item 1)
+ op 'off
+ voice 'on))
+ (t (setq name (substring item 1)
+ op 'off
+ voice 'off)))
+ (setq name item
+ op 'off
+ voice 'off))
+ (when updatep
+ (puthash (erc-downcase name) t
+ erc-channel-new-member-names)
+ (erc-update-current-channel-member
+ name name t op voice)))))
(run-hooks 'erc-channel-members-changed-hook)))
(defcustom erc-channel-members-changed-hook nil
@@ -4529,15 +4632,15 @@ See also: `erc-update-user' and `erc-update-channel-member'."
(setq changed t)
(setf (erc-channel-user-op cuser)
(cond ((eq op 'on) t)
- ((eq op 'off) nil)
- (t op))))
+ ((eq op 'off) nil)
+ (t op))))
(when (and voice
(not (eq (erc-channel-user-voice cuser) voice)))
(setq changed t)
(setf (erc-channel-user-voice cuser)
(cond ((eq voice 'on) t)
- ((eq voice 'off) nil)
- (t voice))))
+ ((eq voice 'off) nil)
+ (t voice))))
(when update-message-time
(setf (erc-channel-user-last-message-time cuser) (current-time)))
(setq user-changed
@@ -4559,11 +4662,11 @@ See also: `erc-update-user' and `erc-update-channel-member'."
(erc-server-user-buffers user))))
(setq cuser (make-erc-channel-user
:op (cond ((eq op 'on) t)
- ((eq op 'off) nil)
- (t op))
+ ((eq op 'off) nil)
+ (t op))
:voice (cond ((eq voice 'on) t)
- ((eq voice 'off) nil)
- (t voice))
+ ((eq voice 'off) nil)
+ (t voice))
:last-message-time
(if update-message-time (current-time))))
(puthash (erc-downcase nick) (cons user cuser)
@@ -4892,39 +4995,37 @@ Specifically, return the position of `erc-insert-marker'."
(interactive)
(save-restriction
(widen)
- (cond
- ((< (point) (erc-beg-of-input-line))
- (message "Point is not in the input area")
- (beep))
- ((not (erc-server-buffer-live-p))
- (message "ERC: No process running")
- (beep))
- (t
- (erc-set-active-buffer (current-buffer))
+ (if (< (point) (erc-beg-of-input-line))
+ (erc-error "Point is not in the input area")
(let ((inhibit-read-only t)
(str (erc-user-input))
(old-buf (current-buffer)))
-
- ;; Kill the input and the prompt
- (delete-region (erc-beg-of-input-line)
- (erc-end-of-input-line))
-
- (unwind-protect
- (erc-send-input str)
- ;; Fix the buffer if the command didn't kill it
- (when (buffer-live-p old-buf)
- (with-current-buffer old-buf
- (save-restriction
- (widen)
- (goto-char (point-max))
- (set-marker (process-mark erc-server-process) (point))
- (set-marker erc-insert-marker (point))
- (let ((buffer-modified (buffer-modified-p)))
- (erc-display-prompt)
- (set-buffer-modified-p buffer-modified))))))
-
- ;; Only when last hook has been run...
- (run-hook-with-args 'erc-send-completed-hook str))))))
+ (if (and (not (erc-server-buffer-live-p))
+ (not (erc-command-no-process-p str)))
+ (erc-error "ERC: No process running")
+ (erc-set-active-buffer (current-buffer))
+
+ ;; Kill the input and the prompt
+ (delete-region (erc-beg-of-input-line)
+ (erc-end-of-input-line))
+
+ (unwind-protect
+ (erc-send-input str)
+ ;; Fix the buffer if the command didn't kill it
+ (when (buffer-live-p old-buf)
+ (with-current-buffer old-buf
+ (save-restriction
+ (widen)
+ (goto-char (point-max))
+ (when (processp erc-server-process)
+ (set-marker (process-mark erc-server-process) (point)))
+ (set-marker erc-insert-marker (point))
+ (let ((buffer-modified (buffer-modified-p)))
+ (erc-display-prompt)
+ (set-buffer-modified-p buffer-modified))))))
+
+ ;; Only when last hook has been run...
+ (run-hook-with-args 'erc-send-completed-hook str))))))
(defun erc-user-input ()
"Return the input of the user in the current buffer."
@@ -4985,7 +5086,8 @@ This returns non-nil only if we actually send anything."
(erc-put-text-property beg (point)
'face 'erc-command-indicator-face)
(insert "\n"))
- (set-marker (process-mark erc-server-process) (point))
+ (when (processp erc-server-process)
+ (set-marker (process-mark erc-server-process) (point)))
(set-marker erc-insert-marker (point))
(save-excursion
(save-restriction
@@ -5004,7 +5106,8 @@ current position."
(erc-put-text-property beg (point)
'face 'erc-input-face))
(insert "\n")
- (set-marker (process-mark erc-server-process) (point))
+ (when (processp erc-server-process)
+ (set-marker (process-mark erc-server-process) (point)))
(set-marker erc-insert-marker (point))
(save-excursion
(save-restriction