Revision: emacs@sv.gnu.org/emacs--devo--0--patch-22

Creator:  Michael Olson <mwolson@gnu.org>

Install ERC.
This commit is contained in:
Miles Bader 2006-01-29 13:08:58 +00:00
parent 33c7860d38
commit 597993cf44
53 changed files with 28894 additions and 8 deletions

View file

@ -1,3 +1,8 @@
2006-01-29 Michael Olson <mwolson@gnu.org>
* Makefile.in (install-arch-indep, uninstall): Add ERC.
* info/dir (ERC): New entry.
2006-01-29 Eli Zaretskii <eliz@gnu.org>
* info/dir: Fix last change.

View file

@ -497,7 +497,7 @@ install-arch-indep: mkdir info
chmod a+r ${infodir}/dir); \
fi; \
cd ${srcdir}/info ; \
for f in ada-mode* autotype* calc* ccmode* cl* dired-x* ebrowse* ediff* efaq* eintr* elisp* emacs* emacs-mime* emacs-xtra* eshell* eudc* flymake* forms* gnus* idlwave* info* message* mh-e* newsticker* org* pcl-cvs* pgg* reftex* sc* ses* sieve* speedbar* tramp* vip* widget* woman* smtpmail* url* rcirc*; do \
for f in ada-mode* autotype* calc* ccmode* cl* dired-x* ebrowse* ediff* efaq* eintr* elisp* emacs* emacs-mime* emacs-xtra* eshell* eudc* flymake* forms* gnus* idlwave* info* message* mh-e* newsticker* org* pcl-cvs* pgg* reftex* sc* ses* sieve* speedbar* tramp* vip* widget* woman* smtpmail* url* rcirc* erc*; do \
(cd $${thisdir}; \
${INSTALL_DATA} ${srcdir}/info/$$f ${infodir}/$$f; \
chmod a+r ${infodir}/$$f); \
@ -507,7 +507,7 @@ install-arch-indep: mkdir info
thisdir=`/bin/pwd`; \
if [ `(cd ${srcdir}/info && /bin/pwd)` != `(cd ${infodir} && /bin/pwd)` ]; \
then \
for f in ada-mode autotype calc ccmode cl dired-x ebrowse ediff efaq elisp eintr emacs emacs-mime emacs-xtra eshell eudc flymake forms gnus idlwave info message mh-e newsticker org pcl-cvs pgg reftex sc ses sieve speedbar tramp vip viper widget woman smtpmail url rcirc; do \
for f in ada-mode autotype calc ccmode cl dired-x ebrowse ediff efaq elisp eintr emacs emacs-mime emacs-xtra eshell eudc flymake forms gnus idlwave info message mh-e newsticker org pcl-cvs pgg reftex sc ses sieve speedbar tramp vip viper widget woman smtpmail url rcirc erc; do \
(cd $${thisdir}; \
${INSTALL_INFO} --info-dir=${infodir} ${infodir}/$$f); \
done; \
@ -573,7 +573,7 @@ uninstall:
done
(cd ${archlibdir} && rm -f fns-*)
-rm -rf ${libexecdir}/emacs/${version}
(cd ${infodir} && rm -f cl* ada-mode* autotype* calc* ccmode* ebrowse* efaq* eintr elisp* eshell* eudc* idlwave* message* pcl-cvs* reftex* speedbar* tramp* widget* woman* dired-x* ediff* emacs* emacs-xtra* flymake* forms* gnus* info* mh-e* newsticker* org* sc* ses* vip* smtpmail* url* rcirc*)
(cd ${infodir} && rm -f cl* ada-mode* autotype* calc* ccmode* ebrowse* efaq* eintr elisp* eshell* eudc* idlwave* message* pcl-cvs* reftex* speedbar* tramp* widget* woman* dired-x* ediff* emacs* emacs-xtra* flymake* forms* gnus* info* mh-e* newsticker* org* sc* ses* vip* smtpmail* url* rcirc* erc*)
(cd ${man1dir} && rm -f emacs${manext} emacsclient${manext} etags${manext} ctags${manext})
(cd ${bindir} && rm -f $(EMACSFULL) $(EMACS))

View file

@ -1,3 +1,7 @@
2006-01-29 Michael Olson <mwolson@gnu.org>
* NEWS: Add entry for ERC.
2006-01-27 Chong Yidong <cyd@stupidchicken.com>
* TODO: Make SYNC_INPUT the default.

599
etc/ERC-NEWS Normal file
View file

@ -0,0 +1,599 @@
ERC NEWS -*- outline -*-
* Changes since ERC 5.0.4
** Improve XEmacs compatibility.
** Namespace changes
*** Now ERC doesn't use global variable space.
Renamed all variables that didn't start with "erc-".
o `away' is now `erc-away'
o `current-nick' is now `erc-server-current-nick'
o `last-peers' is now `erc-server-last-peers'
o `last-ping-time' is now `erc-server-last-ping-time'
o `last-sent-time' is now `erc-server-last-sent-time'
o `lines-sent' is now `erc-server-lines-sent'
o `quitting' is now `erc-server-quitting'
*** Remove the `with-erc-channel-buffer' function.
** Bugfixes
*** Don't inadvertently destroy face properties.
*** Load erc scripts in a safer way.
*** Don't insert a timestamp if text at point is invisible.
*** Don't hide messages from those in `erc-fools' by default.
Color their nicks instead.
*** Use a more foolproof method of encoding and decoding strings
before sending to a channel.
** Backend changes
*** Renamed some server-specific variables
o `erc-announced-server-name' is now `erc-server-announced-name'
o `erc-auto-reconnect' is now `erc-server-auto-reconnect'
o `erc-connect-function' is now `erc-server-connect-function'
o `erc-default-coding-system' is now `erc-server-coding-system'
o `erc-duplicate-timeout' is now `erc-server-duplicate-timeout'
o `erc-duplicates' is now `erc-server-duplicates'
o `erc-lag' is now `erc-server-lag'
o `erc-prevent-duplicates' is now `erc-server-prevent-duplicates'
o `erc-previous-read' is now `erc-server-filter-data'
o `erc-process' is now `erc-server-process'
o `erc-ping-handler' is now `erc-server-send-ping-handler'
o `erc-ping-interval' is now `erc-server-send-ping-interval'
*** Renamed some functions
o `erc-connect' is now `erc-server-connect'
o `erc-process-filter' is now `erc-server-filter-function'
o `erc-send-command' is now `erc-server-send'
o `erc-send-single-line' is now `erc-send-input'
o `erc-setup-periodical-server-ping' is now
`erc-server-setup-periodical-server-ping'
o `erc-split-command is now `erc-split-line'
*** New options
o erc-server-flood-margin, erc-server-flood-penalty: New options
that allow tweaking of flood control.
o erc-split-line-length: The maximum line length of a single
message.
*** New variables
o erc-server-flood-last-message, erc-server-flood-queue,
erc-server-flood-timer: Flood control.
o erc-server-processing-p: Indicate when we're currently processing
a message.
*** Remove some options
o `erc-flood-limit'
o `erc-flood-limit2'
** New customization group `erc-server' for dealing with IRC servers.
** ERC can now be installed by doing `make install' from the command line.
** ERC now has a manual in erc.texi.
Type `make doc' to generate HTML and Info versions of it.
** ERC no longer depends on cl.el.
Only the macros in cl-macs.el are used.
** Fix an edge case when quitting as new messages come in.
** Make flood protection toggle-able as on/off, removing the 'strict option.
** If possible, re-use channel buffers when reconnecting to a server.
** Text in ERC buffers is now read-only by default.
To get the previous behavior,
** Changes and additions to modules
*** Auto-join (erc-autojoin.el)
**** Recognize the Azzurra server.
*** BBDB (erc-bbdb.el)
**** When the user types /WHOIS, ask for a record to merge to.
**** Store the displayed name of a BitlBee contact.
The new `erc-bbdb-bitlbee-name-field' option specifies the field to use
to store this information.
**** Don't prompt for a name on /JOIN or /NICK.
*** Button (erc-button.el)
**** Fix customization of `erc-button-alist'
**** New option `erc-button-nickname-face' determines the face to use
when coloring ERC nicknames.
*** Channel tracking (erc-track.el)
**** Remove channels from the modified channels list if not currently
connected. This should remove residue from the mode line after
quitting ERC.
**** Recognize buttonized text
*** Highlighting (erc-match.el)
**** Highlight current nickname by default.
**** Added the option of beeping when certain matches occur.
Add `erc-beep-on-match' to `erc-text-matched-hook' to enable
beeping. Set the new variable `erc-beep-match-types' which match
types that make beeps.
*** Nicklist (erc-nicklist.el)
**** Fix a couple of errors.
**** Make sure a stray mouse click doesn't trigger an error.
**** Insert icons from the /images directory next to nicks.
This indicates their away status. The location is customizable via
the new `erc-nicklist-icons-directory' option.
If you do not want these icons, set `erc-nicklist-use-icons' to nil.
*** Nickserv identification (erc-nickserv.el)
**** Recognize Azzurra and OFTC networks.
*** Old completion (erc-complete.el)
**** Disable by default.
*** Programmable completion (erc-pcomplete.el)
**** Enable by default.
*** Timestamps (erc-stamp.el)
**** On Emacs22, align right timestamps perfectly, even if variable-width
characters are used. If we aren't using Emacs22, move text farther
away from the right margin when variable-width characters are used.
It is considered better to misalign the stamp by a bit than to go past
the right margin.
**** Enable by default
** New modules
*** Spell-checking (erc-spelling.el)
**** Use flyspell in ERC.
*** Viper compatibility (erc-viper.el)
**** Helps ERC work correctly in viper-mode.
* Fixes since ERC 5.0.3
** Fix a problem with undo in channels.
* Fixes since ERC 5.0.2
** Fix typo in the `ctcp-request-to' entry of the English catalog.
** Debugging with edegug has been made easier in all of the
erc-with-* and with-erc* macros.
** Non-ASCII character sets should be better supported when sending
and processing messages.
** A load failure with erc-autoaway.el and Emacs21 has been fixed.
** A few XEmacs warnings were fixed.
** Changes and additions to modules
*** Backend (erc-backend.el)
**** Move the check for hidden messages into `erc-display-message'
so there isn't so much replicated code.
**** Add `definition-name' property to constructed symbols so that
`find-function' and `find-variable' will be able to locate them.
**** Make sure logs are inserted info the correct channel buffers.
There was previously an error when using `erc-insert-log-on-open' in
combination with autojoin to multiple channels.
*** Button (erc-button.el)
**** The layering of `erc-button-face' on other faces in ERC buffers
has been improved.
*** Channel tracking (erc-track.el)
**** Use optimal amount of whitespace around modified channels
indicator. Previously, there was an additional unnecessary space.
**** Fix an error that occurred when unchecked buffers existed when
invoking /QUIT.
* Fixes since ERC 5.0.1
** If a channel key is required for a certain channel, ERC will prompt
for one if `erc-prompt-for-channel-key' is non-nil.
** ERC doesn't try to reconnect if the network connection is refused
when using `open-network-stream-nowait' as the `erc-connect-function'.
** Messages from multiple servers will not go to the currently active
buffer. The messages from each server will be contained in the most
recently active channel/server buffer that corresponds with the
server.
** Some text messages were cleaned up slightly.
** Button faces should no longer "cover" other faces.
** Made some XEmacs compatibility fixes.
** Nicknames containing a backslash are now correctly highlighted as
current-nick and buttonized as nicks.
** `erc-server-select' doesn't offer networks without servers as a
choice anymore.
** Non-ASCII character support has been improved.
** Changes and additions to modules
*** Menu (erc-menu.el)
**** You can now save logs and truncate buffers from the menu-bar.
* Fixes since ERC 5.0
** Narrowing in ERC buffers no longer causes formatting errors.
** The BBDB module now loads correctly when customizing `erc-modules'.
** The value of `erc-button-face' is now respected.
** Fixed a bug which caused a read-only error during connection.
** Server buffers are now tracked correctly.
This means that `erc-track-priority-faces-only', `erc-track-exclude',
and `erc-track-exclude-types' now work with server buffers.
* Changes since ERC 4.0
** Channel members are now stored as a hash-table.
`erc-server-users' and `erc-channel-users' are now hash-tables, rather
than alists. This significantly increases performance, especially in
large channels. Each channel member is stored as an `erc-server-user'
struct, with additional information about the channels they are on
stored in an `erc-channel-user' struct. Code using old alist-style
channel members needs to be updated to work with hash-tables.
This new code also removes the need for erc-members.el, which has been
removed.
** The way ERC deals with input from the server has changed.
All server response code is now in a new file, erc-backend.el. There
should be no real user visible changes. There are, however, a few
major changes for implementers, and module writers:
*** The PARSED response that all handlers get called with is
no longer a vector, but an `erc-response' struct.
This means LESS MAGIC NUMBERS in the ERC source code, but a few
changes in how you get at parsed responses.
The sender is accessed via `erc-response.sender'.
The command is accessed via `erc-response.command'.
The arguments to the command (everything after the command and
before the colon) are accessed via `erc-response.command-args'.
This is a /list/ of arguments in the order they appear in the
unparsed response.
The contents of the response is accessed via
`erc-response.contents'.
Should, for some reason, you want to do something with the
/unparsed/ response, you can get it via `erc-response.unparsed'.
*** The `erc-server-hook-list' mechanism is gone.
All server response handlers should be defined with
`define-erc-response-handler'. This defines functions and
corresponding hook variables.
The mapping of server commands to hook variables is no longer
done via `erc-event-to-hook', but through an #'equal hashtable,
`erc-server-responses'. In order to find a hook you do:
(erc-get-hook command)
See the docstring of `define-erc-response-handler' for more
information.
*** ALL hook variables have been renamed.
In accordance with recommendations in the Emacs Lisp manual,
the hook variables are no longer called `erc-server-FOO-hook',
but rather `erc-server-FOO-functions'. This is to indicate
that the functions they call take arguments.
All the modules in ERC have been updated to reflect this change,
but external module authors should beware.
** The values of `erc-mode-line-format' and `erc-header-line-format'
are now defined as strings to be formatted using `format-spec'.
`erc-mode-line-format' does not replace the whole mode-line anymore,
only `mode-line-buffer-identification' is set. This way, personal
mode-line configurations are not modified and all key bindings work as
expected. The process status (connecting, closed) is now shown in
`mode-line-process'.
** Customization of ERC variables has been made easier. Variables
have been split into more groups for better organization.
** New variables
o `erc-send-whitespace-lines' - Set this to send lines even if they
are empty.
o `erc-manual-set-nick-on-bad-nick-p' - If the nickname you chose is
already taken or not allowed, your nick is not changed and you can
try again manually if this is non-nil.
o `erc-mode-line-away-status-format' - You can now set what is shown
in the mode-line when you are away.
o `erc-header-line-uses-help-echo-p' - The header-line now uses the
help-echo property. You can set this to nil to disable it.
o `erc-format-query-as-channel-p' - Set this to nil to have messages
in the query buffer formatted like private messages.
o `erc-show-channel-key-p' - The channel key is now shown with the
other channel modes in the header line. Set this to nil if you
want it hidden.
o `erc-prompt-for-channel-key' - Set this if you want to be prompted
for the channel key (channel's mode is +k) when you call
`erc-join-channel' interactively.
o `erc-kill-server-buffer-on-quit' - If non-nil, kill the server
buffer automatically when you quit.
** New hooks
o `erc-join-hook' - Called when you join a channel.
o `erc-kick-hook' - Called when you are kicked from a channel. The
channel's buffer is sent as an argument to functions called from
this hook.
o `erc-nick-changed-functions' - Whenever your nickname changes
successfully, the functions in this hook are run with the
arguments NEW-NICK and OLD-NICK.
** New command /WHOAMI - Do a /WHOIS on your current nickname.
** The key binding for changing channel modes is now C-c C-o.
** Removed variables
o `erc-echo-notices-in-minibuffer-flag' and
`erc-echo-notices-in-current-buffer' - You should use
`erc-echo-notice-hook' and `erc-echo-notice-always-hook' instead.
o `erc-prompt-interactive-input' has been removed (commented out)
because nickname completion does not work with it.
o All INFO buffer-related variables and functions have been removed.
** You can now disable modules by setting `erc-modules' with the
customization interface.
** Changes and additions to modules
*** Autoaway (erc-autoaway.el)
**** New variable `erc-autoaway-no-auto-back-regexp' - Add text which,
when you type anything matching it, will not automatically discard
your away status when `erc-auto-discard-away' is non-nil.
*** Filling (erc-fill.el)
**** New variable `erc-fill-variable-maximum-indentation' - Don't
indent more than this many characters when indenting a message from a
user with a long nickname.
*** Goodies (erc-goodies.el)
**** Miscellaneous small modules have been moved from erc.el.
The functions erc-add-scroll-to-bottom, erc-make-read-only,
erc-send-distinguish-noncommands, erc-interpret-controls, erc-unmorse,
erc-smiley, and erc-occur, which were defined in the main erc.el file
have been moved to erc-goodies.el and have mostly been translated to
the modules scrolltobottom, readonly, noncommands, irccontrols, smiley
and unmorse.
**** New variables
o `erc-input-line-position' - The line number to use with
`erc-scroll-to-bottom'.
o `erc-beep-p' - Beep if there is a \C-g control character in a
message.
*** Channel lists (erc-list.el)
**** New variable `erc-chanlist-highlight-face' - A face used for
highlighting the current line.
*** Highlighting (erc-match.el)
**** `erc-current-nick-highlight-type' has new options: 'keyword and
'nick-or-keyword.
*** Menu (erc-menu.el)
**** The `IRC' menu is now automatically added to `erc-mode' buffers.
*** Networks (erc-nets.el)
**** The functions for determining current network are in this file.
There were a couple of functions spread about in different files which
each had a different way of determining the current network. The
methods have been combined, and the big list of known networks
(`erc-networks-alist') is being put to use. You can access the
network's name by calling the new function `erc-network'. This
returns the name of the current network as a symbol or 'Unknown if it
could not determine which network it is.
*** Nicklist (erc-nicklist.el)
**** ERC has a new way of displaying nicknames in a channel.
The new file erc-nicklist.el defines a new command `erc-nicklist'
which pops up a small Emacs window showing the nicknames of all
members of the current channel. The implementation is not complete
and is rather proof-of-concept for now. The result is something a bit
like erc-speedbar, but not quite as invasive, and doesn't require use
of a new frame.
*** Internet services / Nickserv (erc-nickserv.el)
**** Network detection is now taken care of by erc-nets.el.
The function `erc-current-network' is deprecated, use `erc-network'
instead. The variable `erc-networks' has been removed, use
`erc-networks-alist'. The network symbols used in
`erc-nickserv-alist' now match those in `erc-networks-alist'.
**** New variable `erc-nickserv-identify-mode' - Choose which method
to use for automatic identification: you can wait for Nickserv to ask
you to identify (the default), or send an identify message
automatically after you change your nickname.
*** Speedbar (erc-speedbar.el)
**** New variable `erc-speedbar-sort-users-type' - Sort users in a
channel by activity, alphabetically, or not at all.
*** Timestamps (erc-stamp.el)
**** `erc-timestamp-only-if-changed-flag' now works when
`erc-insert-timestamp-function' is set to 'erc-insert-timestamp-left.
**** New variable `erc-timestamp-intangible' - Set this to nil if
timestamps should not have the 'intangible property.
*** Channel tracking (erc-track.el)
**** Using faces to indicate channel activity in the modeline now works
in XEmacs.
**** New variables
o `erc-track-priority-faces-only' - Ignore changes in a channel
unless there is a face from the `erc-track-faces-priority-list' in
the message.
o `erc-track-exclude-server-buffer' - Ignore changes in the server
buffer.
o `erc-track-position-in-mode-line' - Set the position in the
mode-line where modified channels are shown (only works in GNU
Emacs versions above 21.3).
* Changes since ERC 3.0.cvs.20030119
** The module system has again changed a lot. You can now customize
the variable `erc-modules' and define once and for all which
extension modules you want to use. This unfortunately may require
you to change your current erc initialisation code a bit, if you
have some existing customsations. On the other hand, this change
makes the configuration of extension modules a lot easier for new
users. In theory, you should be able to configure all aspects of
ERC by using the customize interface, you should no longer really
need to write Lisp code for trivial customizations.
By default, the following modules are now loaded: (pcomplete
netsplit fill track ring button autojoin)
Please use M-x customize-variable RET erc-modules RET to change the
default if it does not suite your needs.
** THe symbol used in `erc-nickserv-passwords' for debian.org IRC servers
(formerly called OpenProjects, now FreeNode) has changed from
openprojects to freenode. You may need to update your configuration
for a successful automatic nickserv identification.
* Changes since ERC 2.93.cvs.20020819
** New module erc-dcc:
This finally implements DCC. It requires server sockets to fully work
in both directions. This feature is currently only available in Emacs
21.3.50 (CVS). Here is a short list of what should work though.
** Compatibility:
* Emacs 21.2, DCC get, and accepting DCC chat offers.
* XEmacs 21, Only accepting DCC chat offers.
** erc is switching to global-minor-modes for activation of submodules.
This allows you to customize such a mode and get automatic loading of
the module. No longer putting a lot of require statments in .emacs.
At least this is the long-term plan, not all modules are converted
yet.
** The most important user visible change is that you now need to activate
erc-completion-mode, to get TAB completion. The new completion code
is based on pcomplete. To get the old code, manually load
erc-complete and bind TAB to erc-complete in erc-mode-map.
To activate completion on startup, put (erc-completion-mode 1) in your
.emacs file.
Same applies to timestamps. You no longer need to (require
'erc-stamp), you can customize the variable `erc-timestamp-mode', and
the rest should be automatic.
arch-tag: 2b21b387-6cdc-4192-889c-6743cfffdcb1

View file

@ -1504,6 +1504,17 @@ colors as on X.
* New Modes and Packages in Emacs 22.1
** ERC is now part of the Emacs distribution.
ERC is a powerful, modular, and extensible IRC client for Emacs.
To see what modules are available, type
M-x customize-option erc-modules RET.
To start an IRC session, type M-x erc-select, and follow the prompts
for server, port, and nick.
---
** Rcirc is now part of the Emacs distribution.
Rcirc is an Internet relay chat (IRC) client. It supports

View file

@ -41,6 +41,8 @@ Emacs
* CC mode: (ccmode). Emacs mode for editing C, C++, Objective-C,
Java, Pike, and IDL code.
* Ebrowse: (ebrowse). A C++ class browser for Emacs.
* ERC: (erc). Powerful, modular, and extensible IRC client
for Emacs.
* Flymake: (flymake). An on-the-fly syntax checker for Emacs.
* IDLWAVE: (idlwave). Major mode and shell for IDL and WAVE/CL files.

327
lisp/erc/ChangeLog Normal file
View file

@ -0,0 +1,327 @@
2006-01-28 Michael Olson <mwolson@gnu.org>
* erc-*.el, erc.texi, NEWS: Add Arch taglines as per Emacs
guidelines.
* erc-*.el: Space out copyright years like the rest of Emacs. Use
the Emacs copyright statement. Refer to ourselves as ERC rather
than "Emacs IRC Client", since there are now several IRC clients
for Emacs.
* erc-compat.el (erc-emacs-build-time): Define as a variable.
* erc-log.el (erc-log-setup-logging): Use write-file-functions.
* erc-ibuffer.el: Require 'erc.
* erc-stamp.el (erc-insert-aligned): Only use the special text
property when window-system is X.
* erc.texi: Adapt for inclusion in Emacs.
2006-01-28 Johan Bockgård <bojohan@users.sourceforge.net>
* erc.el (erc-format-message): More `cl' breakage; don't use
`oddp'.
2006-01-27 Michael Olson <mwolson@gnu.org>
* debian/changelog: Update for new release.
* debian/control (Description): Update.
* debian/rules: Concatenate ChangeLog for 2005.
* Makefile (MISC): Include ChangeLog.2005 and erc.texi.
(debrelease, release): Copy images directory.
* NEWS: Spelling fixes. Add items for recent changes.
* erc.el (erc): Move call to erc-update-modules before the call to
erc-mode. This should fix a timestamp display issue.
(erc-version-string): Release ERC 5.1.
2006-01-26 Michael Olson <mwolson@gnu.org>
* erc-stamp.el (erc-insert-aligned): New function that inserts
text in an perfectly-aligned way relative to the right margin. It
only works well with Emacs22. A sane fallback is provided for
other versions of Emacs.
(erc-insert-timestamp-right): Use the new function.
2006-01-25 Edward O'Connor <ted@oconnor.cx>
* erc.el (erc-modules): Ensure that `erc-button-mode' gets enabled
before `erc-match-mode'.
* erc-match.el (match): Append `erc-match-message' to
`erc-insert-modify-hook'.
2006-01-25 Michael Olson <mwolson@gnu.org>
* FOR-RELEASE: Mark last release requirement as done.
* Makefile (realclean, distclean): Remove docs.
* erc.texi: Take care of all pre-5.1 items.
* erc-backend.el (erc-server-send, erc-server-send-queue): Wrap
`process-send-string' in `condition-case' to avoid an error when
quitting ERC.
* erc-stamp.el (erc-insert-timestamp-right): Try to deal with
variable-width characters in the timestamp and on the same line.
The latter is a kludge, but it seems to work with most of the
input I've thrown at it so far. It's certainly better than going
past the end of line consistently when we have variable-width
characters on the same line. When `erc-timestamp-intangible' is
non-nil, add intangible properties to the whitespace as well, so
that hitting <end> does what you'd expect.
* erc.el (erc-flood-protect, erc-toggle-flood-control): Update
this to only use boolean values for `erc-flood-protect'. Update
documentation.
(erc-cmd-QUIT): Set the active buffer to be the server buffer, so
that any QUIT-related messages go there.
(erc): Try to be more clever about re-using channel buffers when
automatically re-connecting. Thanks to e1f for noticing.
2006-01-23 Michael Olson <mwolson@gnu.org>
* ChangeLog.2005: Remove erroneous line.
* FOR-RELEASE: Make that the Makefile tweaking is complete.
(NEWS): Mark as done.
* Makefile (MANUAL): New option indicating the name of the manual.
(PREFIX, ELISPDIR, INFODIR): New options that specify the
directories to install lisp code and info manuals to. PREFIX is
used only by ELISPDIR and INFODIR.
(all): Call `lisp' and create the manual.
(lisp): Compile lisp code.
(%.info, %.html): New rules that make Info files and HTML files,
respectively, from a TexInfo source.
(doc): Create both the Info and HTML versions of the manual. This
is for the user -- we never call it automatically.
(install-info): Install Info files.
(install-bin): Install compiled and source Lisp files.
(todo): Remove, since it seems pointless.
* NEWS: Update.
* README: Add Installation instructions. Tweak layout.
* erc.texi: Work on some pre-5.1 items.
* erc-stamp.el, erc-track.el: Move some functions and options in
order to get rid of a few compiler warnings.
* erc.el (erc-modules): Enable readonly by default. This will
prevent new users from accidentally removing old messages, which
could be disconcerting. Also enable stamp by default, since
timestamps are a fairly standard feature among IRC clients.
* erc-button.el: Munge whitespace.
* erc-identd.el (erc-identd-start): Instead of throwing an error,
just try to use the obsolete function.
2006-01-22 Michael Olson <mwolson@gnu.org>
* erc-backend.el (erc-decode-string-from-target): Make sure that
we have a string as an argument. If not, coerce it to the empty
string. Hopefully, this will work painlessly around an edge case
related to quitting ERC around the same time a message comes in.
2006-01-22 Johan Bockgård <bojohan@users.sourceforge.net>
* erc-track.el: Use `(eval-when-compile (require 'cl))' (for
`case'). Doc fixes.
(erc-find-parsed-property): Simplify.
(erc-track-get-active-buffer): Fix logic. Simplify.
(erc-track-switch-buffer): Remove unused variable `dir'. Simplify.
* erc-speak.el: Doc fixes.
(erc-speak-region): `propertize' --> `erc-propertize'.
* erc-dcc.el (erc-dcc-chat-parse-output): `propertize' -->
`erc-propertize'.
* erc-button.el (erc-button-add-button): Take erc-fill-prefix into
account when wrapping URLs.
* erc-bbdb.el (erc-bbdb-elide-display): Doc fix.
* erc-backend.el (define-erc-response-handler): Doc fix.
2006-01-22 Michael Olson <mwolson@gnu.org>
* erc.el (erc-update-modules): Use `require' instead of `load',
but prevent it from causing errors, in order to preserve the
previous behavior.
2006-01-21 Michael Olson <mwolson@gnu.org>
* FOR-RELEASE (Source): Mark cl task as done.
* Makefile (erc-auto.el): Call erc-generate-autoloads rather than
generate-autoloads.
(erc-auto.el, %.elc): Don't show command, just its output.
* NEWS: Add items from 2005-01-01 to 2005-08-13.
* debian/copyright (Copyright): Update.
* erc-auto.in (erc-generate-autoloads): Rename from
generate-autoloads.
* erc.el, erc-autoaway.el, erc-backend.el: Use
erc-server-process-alive instead of erc-process-alive.
* erc.el, erc-backend.el, erc-ezbounce.el, erc-list.el,
erc-log.el, erc-match.el, erc-nets.el, erc-netsplit.el,
erc-nicklist.el, erc-nickserv.el, erc-notify.el, erc-pcomplete.el:
Use (eval-when-compile 'cl), so that compilation doesn't fail.
* erc-fill.el, erc-truncate.el: Whitespace munging.
* erc.el: Update copyright notice. Remove eval-after-load code.
(erc-with-buffer): Docfix.
(erc-once-with-server-event, erc-once-with-server-event-global)
(erc-with-buffer, erc-with-all-buffers-of-server): Use erc-gensym
instead of gensym.
(erc-banlist-update): Use erc-delete-if instead of delete-if.
(erc): Call `erc-update-modules' here.
* erc-backend.el: Require 'erc-compat to minimize compiler
warnings.
(erc-decode-parsed-server-response): Docfix.
(erc-server-process-alive): Move here from erc.el and rename from
`erc-process-alive'.
(erc-server-send, erc-remove-channel-users): Make sure process is
alive before sending data to it.
* erc-bbdb.el: Update copyright years.
(erc-bbdb-whois): Remove overexuberant comment.
* erc-button.el: Require erc-fill, since we make liberal use of
`erc-fill-column'.
* erc-compat.el (erc-const-expr-p, erc-list*, erc-assert): New
functions, the latter of which provides an `assert' equivalent.
(erc-remove-if-not): New function that provides a simple
implementation of `remove-if-not'.
(erc-gensym): New function that provides a simple implementation
of `gensym'.
(erc-delete-if): New function that provides a simple
implementation of `delete-if'.
(erc-member-if): New function that provides a simple
implementation of `member-if'.
(field-end): Remove this, since it is unused, and later versions
of XEmacs have this function already.
(erc-function-arglist): Moved here from erc.el.
(erc-delete-dups): New compatibility function for dealing with
XEmacs.
(erc-subseq): New function copied from cl-extra.el.
* erc-dcc.el: Require pcomplete during compilation to avoid
compiler warnings.
(erc-unpack-int, erc-dcc-send-filter)
(erc-dcc-get-filter): Use erc-assert instead of assert.
(pcomplete/erc-mode/DCC): Use erc-remove-if-not instead of
remove-if-not.
* erc-match.el (erc-log-matches): Fix compiler warning.
* erc-nicklist.el: Update copyright notice.
(erc-nicklist-menu): Change use of caadr to (car (cadr ...)).
(erc-nicklist-bitlbee-connected-p): Remove.
(erc-nicklist-insert-medium-name-or-icon): Accept channel
argument. Use it to determine whether we are on bitlbee. Now
that bitlbee names its channel "&bitlbee", this is trivial.
(erc-nicklist-insert-contents): Pass channel as specified above.
Don't try to determine whether we are on bitlbee here.
(erc-nicklist-channel-users-info): Use erc-remove-if-not instead
of remove-if-not.
(erc-nicklist-search-for-nick): Use erc-member-if instead of
member-if.
* erc-notify.el (erc-notify-QUIT): Use erc-delete-if with a
partially-evaluated lambda expression instead of `delete' and
`find'.
* erc-track.el: Use erc-assert.
(erc-track-modified-channels): Remove use of `return'.
(erc-track-modified-channels): Use `cadr' instead of `second',
since otherwise we would need yet another eval-when-compile line.
2006-01-19 Michael Olson <mwolson@gnu.org>
* erc-backend.el (erc-process-sentinel-1): Remove attempt to
detect SIGPIPE, since it doesn't work.
2006-01-10 Diane Murray <disumu@x3y2z1.net>
* erc-spelling.el: Updated copyright years.
(define-erc-module): Enable/disable `flyspell-mode' for all open
ERC buffers as well.
(erc-spelling-dictionaries): Reworded customize description.
* erc.el (erc-command-symbol): New function.
(erc-extract-command-from-line): Use `erc-command-symbol'. This
fixes a bug where "Symbol's function definition is void:
erc-cmd-LIST" would be shown after typing /list at the prompt (the
command was interned because erc-menu.el uses it and is enabled by
default whereas erc-list.el is not).
* NEWS: Started a list of renamed variables.
* erc.el: Reworded the message sent when defining variable
aliases.
(erc-command-indicator-face): Doc fix.
(erc-modules): Enable the match module by default which makes
current nickname highlighting on as the default.
* erc-button.el: Updated copyright years.
(erc-button): New face.
(erc-button-face): Use `erc-button'.
(erc-button-nickname-face): New customizable variable.
(erc-button-add-nickname-buttons, erc-button-add-buttons-1): Send
new argument to `erc-button-add-button'.
(erc-button-add-button): Doc fix. Added new argument to function
definition, NICK-P. If it's a nickname, use
`erc-button-nickname-face', otherwise use `erc-button-face'. This
makes channel tracking and buttons work better together when
`erc-button-buttonize-nicks' is enabled, since there is a nickname
on just about every line.
* erc-track.el (erc-track-use-faces): Doc fix.
(erc-track-faces-priority-list): Added `erc-button' to list.
(erc-track-priority-faces-only): Doc fix.
2006-01-09 Diane Murray <disumu@x3y2z1.net>
* erc-button.el (erc-button-url-regexp): Use `concat' so the
regexp is not one long line.
(erc-button-alist): Fixed so that customizing works correctly.
Reorganized. Removed lambda functions with more than two lines.
Doc fix.
(erc-button-describe-symbol, erc-button-beats-to-time): New
functions. Moved from `erc-button-alist'.
2006-01-07 Michael Olson <mwolson@gnu.org>
* erc-backend.el (erc-process-sentinel-1): Don't try to re-open a
process if a SIGPIPE occurs. This happens when a new message
comes in at the same time a /quit is requested.
(erc-process-sentinel): Use string-match rather than string= to do
these comparisons. Matching literal newlines makes me nervous.
* erc-track.el (erc-track-remove-from-mode-line): Handle case
where global-mode-string is not a list. Emacs22 permits this.
Copyright (C) 2006 Free Software Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted provided the copyright notice and this notice are preserved.
;; arch-tag: 865a75f6-2bcb-46df-bf0c-b514dadf688a

1042
lisp/erc/ChangeLog.2001 Normal file

File diff suppressed because it is too large Load diff

2601
lisp/erc/ChangeLog.2002 Normal file

File diff suppressed because it is too large Load diff

2145
lisp/erc/ChangeLog.2003 Normal file

File diff suppressed because it is too large Load diff

2074
lisp/erc/ChangeLog.2004 Normal file

File diff suppressed because it is too large Load diff

1222
lisp/erc/ChangeLog.2005 Normal file

File diff suppressed because it is too large Load diff

207
lisp/erc/erc-autoaway.el Normal file
View file

@ -0,0 +1,207 @@
;;; erc-autoaway.el --- Provides autoaway for ERC
;; Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
;; Author: Jorgen Schaefer <forcer@forcix.cx>
;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcAutoAway
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; TODO:
;; - Legacy names: erc-auto-discard-away, erc-auto-set-away
;;; Code:
(require 'erc)
(defgroup erc-autoaway nil
"Set yourself automatically away after some idletime and set
yourself back when you type something."
:group 'erc)
(defvar erc-autoaway-idletimer nil
"The Emacs idletimer.
This is only used when `erc-autoaway-use-emacs-idle' is non-nil.")
(defcustom erc-autoaway-use-emacs-idle nil
"*If non-nil, the idle time refers to idletime in Emacs.
If nil, the idle time refers to idletime on IRC only.
The time itself is specified by `erc-autoaway-idle-seconds'.
See `erc-autoaway-mode' for more information on the various
definitions of being idle.
Note that using Emacs idletime is currently broken for most versions,
since process activity (as happens all the time on IRC) makes Emacs
non-idle. Emacs idle-time and user idle-time are just not the same."
:group 'erc-autoaway
:type 'boolean)
;;;###autoload (autoload 'erc-autoaway-mode "erc-autoaway")
(define-erc-module autoaway nil
"In ERC autoaway mode, you can be set away automatically.
If `erc-auto-set-away' is set, then you will be set away after
the number of seconds specified in `erc-autoaway-idle-seconds'.
There are several kinds of being idle:
IRC idle time measures how long since you last sent something (see
`erc-autoaway-last-sent-time'). This is the default.
Emacs idle time measures how long Emacs has been idle. This is
currently not useful, since Emacs is non-idle when it handles
ping-pong with IRC servers. See `erc-autoaway-use-emacs-idle' for
more information.
User idle time measures how long you have not been sending any
commands to Emacs, or to your system. Emacs currently provides no way
to measure user idle time.
If `erc-auto-discard-away' is set, then typing anything, will
set you no longer away.
Related variables: `erc-public-away-p' and `erc-away-nickname'."
;; Enable:
((add-hook 'erc-send-completed-hook 'erc-autoaway-reset-idletime)
(add-hook 'erc-server-001-functions 'erc-autoaway-reset-idletime)
(add-hook 'erc-timer-hook 'erc-autoaway-possibly-set-away)
(when erc-autoaway-use-emacs-idle
(erc-autoaway-reestablish-idletimer)))
;; Disable:
((remove-hook 'erc-send-completed-hook 'erc-autoaway-reset-idletime)
(remove-hook 'erc-server-001-functions 'erc-autoaway-reset-idletime)
(remove-hook 'erc-timer-hook 'erc-autoaway-possibly-set-away)
(when erc-autoaway-idletimer
(erc-cancel-timer erc-autoaway-idletimer)
(setq erc-autoaway-idletimer nil))))
(defcustom erc-auto-set-away t
"*If non-nil, set away after `erc-autoaway-idle-seconds' seconds of idling.
ERC autoaway mode can set you away when you idle, and set you no
longer away when you type something. This variable controls whether
you will be set away when you idle. See `erc-auto-discard-away' for
the other half."
:group 'erc-autoaway
:type 'boolean)
(defcustom erc-auto-discard-away t
"*If non-nil, sending anything when away automatically discards away state.
ERC autoaway mode can set you away when you idle, and set you no
longer away when you type something. This variable controls whether
you will be set no longer away when you type something. See
`erc-auto-set-away' for the other half.
See also `erc-autoaway-no-auto-discard-regexp'."
:group 'erc-autoaway
:type 'boolean)
(defcustom erc-autoaway-no-auto-discard-regexp "^/g?away.*$"
"*Input that matches this will not automatically discard away status.
See `erc-auto-discard-away'."
:group 'erc-autoaway
:type 'regexp)
(eval-when-compile (defvar erc-autoaway-idle-seconds))
(defun erc-autoaway-reestablish-idletimer ()
"Reestablish the emacs idletimer.
You have to call this function each time you change
`erc-autoaway-idle-seconds', if `erc-autoaway-use-emacs-idle' is set."
(interactive)
(when erc-autoaway-idletimer
(erc-cancel-timer erc-autoaway-idletimer))
(setq erc-autoaway-idletimer
(run-with-idle-timer erc-autoaway-idle-seconds
t
'erc-autoaway-set-away
erc-autoaway-idle-seconds)))
(defcustom erc-autoaway-idle-seconds 1800
"*Number of seconds after which ERC will set you automatically away.
If you are changing this variable using lisp instead of customizing it,
you have to run `erc-autoaway-reestablish-idletimer' afterwards."
:group 'erc-autoaway
:set (lambda (sym val)
(set-default sym val)
(when erc-autoaway-use-emacs-idle
(erc-autoaway-reestablish-idletimer)))
:type 'number)
(defcustom erc-autoaway-message
"I'm gone (autoaway after %i seconds of idletime)"
"*Message ERC will use when he sets you automatically away.
It is used as a `format' string with the argument of the idletime in
seconds."
:group 'erc-autoaway
:type 'string)
(defvar erc-autoaway-last-sent-time (erc-current-time)
"The last time the user sent something.")
(defun erc-autoaway-reset-idletime (line &rest stuff)
"Reset the stored idletime for the user.
This is one global variable since a user talking on one net can talk
on another net too."
(when (and erc-auto-discard-away
(stringp line)
(not (string-match erc-autoaway-no-auto-discard-regexp line)))
(erc-autoaway-set-back line))
(setq erc-autoaway-last-sent-time (erc-current-time)))
(defun erc-autoaway-set-back (line)
"Discard the away state globally."
(when (erc-away-p)
(setq erc-autoaway-last-sent-time (erc-current-time))
(erc-cmd-GAWAY "")))
(defun erc-autoaway-possibly-set-away (current-time)
"Set autoaway when `erc-auto-set-away' is true and the idletime is
exceeds `erc-autoaway-idle-seconds'."
;; A test for (erc-server-process-alive) is not necessary, because
;; this function is called from `erc-timer-hook', which is called
;; whenever the server sends something to the client.
(when (and erc-auto-set-away
(not (erc-away-p)))
(let ((idle-time (erc-time-diff erc-autoaway-last-sent-time
current-time)))
(when (>= idle-time erc-autoaway-idle-seconds)
(erc-display-message
nil 'notice nil
(format "Setting automatically away after %i seconds of idle-time"
idle-time))
(erc-autoaway-set-away idle-time)))))
(defun erc-autoaway-set-away (idle-time)
"Set the away state globally."
;; Note that the idle timer runs, even when Emacs is inactive. In
;; order to prevent flooding when we connect, we test for an
;; existing process.
(when (and (erc-server-process-alive)
(not (erc-away-p)))
(erc-cmd-GAWAY (format erc-autoaway-message idle-time))))
(provide 'erc-autoaway)
;;; erc-autoaway.el ends here
;;
;; Local Variables:
;; indent-tabs-mode: t
;; tab-width: 8
;; End:
;; arch-tag: 16fc241e-8358-4b56-9fe2-116bdd0ba3bc

139
lisp/erc/erc-autojoin.el Normal file
View file

@ -0,0 +1,139 @@
;;; erc-autojoin.el --- autojoin channels on connect and reconnects
;; Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
;; Author: Alex Schroeder <alex@gnu.org>
;; Keywords: irc
;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcAutoJoin
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; This allows us to customize an `erc-autojoin-channels-alist'. As
;; we /JOIN and /PART channels, this alist is updated to reflect our
;; current setup, so that when we reconnect, we rejoin the same
;; channels. The alist can be customized, so that the customized
;; value will be used when we reconnect in our next Emacs session.
;;; Code:
(require 'erc)
;;; Minor Mode
(defgroup erc-autojoin nil
"Enable autojoining."
:group 'erc)
;;;###autoload (autoload 'erc-autojoin-mode "erc-autojoin" nil t)
(define-erc-module autojoin nil
"Makes ERC autojoin on connects and reconnects."
((add-hook 'erc-after-connect 'erc-autojoin-channels)
(add-hook 'erc-server-JOIN-functions 'erc-autojoin-add)
(add-hook 'erc-server-PART-functions 'erc-autojoin-remove))
((remove-hook 'erc-after-connect 'erc-autojoin-channels)
(remove-hook 'erc-server-JOIN-functions 'erc-autojoin-add)
(remove-hook 'erc-server-PART-functions 'erc-autojoin-remove)))
(defcustom erc-autojoin-channels-alist nil
"Alist of channels to autojoin on IRC networks.
Every element in the alist has the form (SERVER . CHANNELS).
SERVER is a regexp matching the server, and channels is the
list of channels to join.
Customize this variable to set the value for your first connect.
Once you are connected and join and part channels, this alist
keeps track of what channels you are on, and will join them
again when you get disconnected. When you restart Emacs, however,
those changes are lost, and the customization you saved the last
time is used again."
:group 'erc-autojoin
:type '(repeat (cons :tag "Server"
(regexp :tag "Name")
(repeat :tag "Channels"
(string :tag "Name")))))
(defcustom erc-autojoin-domain-only t
"Truncate host name to the domain name when joining a server.
If non-nil, and a channel on the server a.b.c is joined, then
only b.c is used as the server for `erc-autojoin-channels-alist'.
This is important for networks that redirect you to other
servers, presumably in the same domain."
:group 'erc-autojoin
:type 'boolean)
(defun erc-autojoin-channels (server nick)
"Autojoin channels in `erc-autojoin-channels-alist'."
(dolist (l erc-autojoin-channels-alist)
(when (string-match (car l) server)
(dolist (chan (cdr l))
(erc-server-send (concat "join " chan))))))
(defun erc-autojoin-add (proc parsed)
"Add the channel being joined to `erc-autojoin-channels-alist'."
(let* ((chnl (erc-response.contents parsed))
(nick (car (erc-parse-user (erc-response.sender parsed))))
(server (with-current-buffer (process-buffer proc)
(or erc-server-announced-name erc-session-server))))
(when (erc-current-nick-p nick)
(when (and erc-autojoin-domain-only
(string-match "[^.]+\\.\\([^.]+\\.[^.]+\\)$" server))
(setq server (match-string 1 server)))
(let ((elem (assoc server erc-autojoin-channels-alist)))
(if elem
(unless (member chnl (cdr elem))
(setcdr elem (cons chnl (cdr elem))))
(setq erc-autojoin-channels-alist
(cons (list server chnl)
erc-autojoin-channels-alist))))))
;; We must return nil to tell ERC to continue running the other
;; functions.
nil)
;; (erc-parse-user "kensanata!~user@dclient217-162-233-228.hispeed.ch")
(defun erc-autojoin-remove (proc parsed)
"Remove the channel being left from `erc-autojoin-channels-alist'."
(let* ((chnl (car (erc-response.command-args parsed)))
(nick (car (erc-parse-user (erc-response.sender parsed))))
(server (with-current-buffer (process-buffer proc)
(or erc-server-announced-name erc-session-server))))
(when (erc-current-nick-p nick)
(when (and erc-autojoin-domain-only
(string-match "[^.]+\\.\\([^.]+\\.[^.]+\\)$" server))
(setq server (match-string 1 server)))
(let ((elem (assoc server erc-autojoin-channels-alist)))
(when elem
(setcdr elem (delete chnl (cdr elem)))
(unless (cdr elem)
(setq erc-autojoin-channels-alist
(delete elem erc-autojoin-channels-alist)))))))
;; We must return nil to tell ERC to continue running the other
;; functions.
nil)
(provide 'erc-autojoin)
;;; erc-autojoin.el ends here
;;
;; Local Variables:
;; indent-tabs-mode: t
;; tab-width: 8
;; End:
;; arch-tag: d62d8b15-8e31-49d6-8a73-12f11e717414

1786
lisp/erc/erc-backend.el Normal file

File diff suppressed because it is too large Load diff

504
lisp/erc/erc-button.el Normal file
View file

@ -0,0 +1,504 @@
;; erc-button.el --- A way of buttonizing certain things in ERC buffers
;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2006 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@delysid.org>
;; Keywords: irc, button, url, regexp
;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcButton
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; Heavily borrowed from gnus-art.el. Thanks to the original authors.
;; This buttonizes nicks and other stuff to make it all clickable.
;; To enable, add to your ~/.emacs:
;; (require 'erc-button)
;; (erc-button-mode 1)
;;
;; Todo:
;; * Rewrite all this to do the same, but use button.el from GNU Emacs
;; if it's available for xemacs too. Why? button.el is much faster,
;; and much more elegant, and solves the problem we get with large buffers
;; and a large erc-button-marker-list.
;;; Code:
(require 'erc)
(require 'wid-edit)
(require 'erc-fill)
;;; Minor Mode
(defgroup erc-button nil
"Define how text can be turned into clickable buttons."
:group 'erc)
;;;###autoload (autoload 'erc-button-mode "erc-button" nil t)
(define-erc-module button nil
"This mode buttonizes all messages according to `erc-button-alist'."
((add-hook 'erc-insert-modify-hook 'erc-button-add-buttons 'append)
(add-hook 'erc-send-modify-hook 'erc-button-add-buttons 'append)
(add-hook 'erc-complete-functions 'erc-button-next))
((remove-hook 'erc-insert-modify-hook 'erc-button-add-buttons)
(remove-hook 'erc-send-modify-hook 'erc-button-add-buttons)
(remove-hook 'erc-complete-functions 'erc-button-next)))
;; Make XEmacs use `erc-button-face'.
(when (featurep 'xemacs)
(add-hook 'erc-mode-hook
(lambda () (set (make-local-variable 'widget-button-face) nil))))
;;; Variables
(defface erc-button '((t (:bold t)))
"ERC button face."
:group 'erc-faces)
(defcustom erc-button-face 'erc-button
"Face used for highlighting buttons in ERC buffers.
A button is a piece of text that you can activate by pressing
`RET' or `mouse-2' above it. See also `erc-button-keymap'."
:type 'face
:group 'erc-faces)
(defcustom erc-button-nickname-face 'erc-nick-default-face
"Face used for ERC nickname buttons."
:type 'face
:group 'erc-faces)
(defcustom erc-button-mouse-face 'highlight
"Face used for mouse highlighting in ERC buffers.
Buttons will be displayed in this face when the mouse cursor is
above them."
:type 'face
:group 'erc-faces)
(defcustom erc-button-url-regexp
(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_=#$@~`%&*+\\/]")
"Regular expression that matches URLs."
:group 'erc-button
:type 'regexp)
(defcustom erc-button-wrap-long-urls nil
"If non-nil, \"long\" URLs matching `erc-button-url-regexp' will be wrapped.
If this variable is a number, consider URLs longer than its value to
be \"long\". If t, URLs will be considered \"long\" if they are
longer than `erc-fill-column'."
:group 'erc-button
:type '(choice integer boolean))
(defcustom erc-button-buttonize-nicks t
"Flag indicating whether nicks should be buttonized or not."
:group 'erc-button
:type 'boolean)
(defcustom erc-button-rfc-url "http://www.faqs.org/rfcs/rfc%s.html"
"*URL used to browse rfc references.
%s is replaced by the number."
:group 'erc-button
:type 'string)
(defcustom erc-button-google-url "http://www.google.com/search?q=%s"
"*URL used to browse Google search references.
%s is replaced by the search string."
:group 'erc-button
:type 'string)
(defcustom erc-button-alist
;; Since the callback is only executed when the user is clicking on
;; a button, it makes no sense to optimize performance by
;; bytecompiling lambdas in this alist. On the other hand, it makes
;; things hard to maintain.
'(('nicknames 0 erc-button-buttonize-nicks erc-nick-popup 0)
(erc-button-url-regexp 0 t browse-url 0)
("<URL: *\\([^<> ]+\\) *>" 0 t browse-url 1)
("(\\(\\([^~\n \t@][^\n \t@]*\\)@\\([a-zA-Z0-9.:-]+\\)\\)" 1 t finger 2 3)
;; emacs internal
("[`]\\([a-zA-Z][-a-zA-Z_0-9]+\\)[']" 1 t erc-button-describe-symbol 1)
;; pseudo links
("\\bInfo:[\"]\\([^\"]+\\)[\"]" 0 t Info-goto-node 1)
("\\b\\(Ward\\|Wiki\\|WardsWiki\\|TheWiki\\):\\([A-Z][a-z]+\\([A-Z][a-z]+\\)+\\)"
0 t (lambda (page)
(browse-url (concat "http://c2.com/cgi-bin/wiki?" page)))
2)
("EmacsWiki:\\([A-Z][a-z]+\\([A-Z][a-z]+\\)+\\)" 0 t erc-browse-emacswiki 1)
("Lisp:\\([a-zA-Z.+-]+\\)" 0 t erc-browse-emacswiki-lisp 1)
("\\bGoogle:\\([^ \t\n\r\f]+\\)"
0 t (lambda (keywords)
(browse-url (format erc-button-google-url keywords)))
1)
("\\brfc[#: ]?\\([0-9]+\\)"
0 t (lambda (num)
(browse-url (format erc-button-rfc-url num)))
1)
;; other
("\\s-\\(@\\([0-9][0-9][0-9]\\)\\)" 1 t erc-button-beats-to-time 2))
"*Alist of regexps matching buttons in ERC buffers.
Each entry has the form (REGEXP BUTTON FORM CALLBACK PAR...), where
REGEXP is the string matching text around the button or a symbol
indicating a variable holding that string, or a list of
strings, or an alist with the strings in the car. Note that
entries in lists or alists are considered to be nicks or other
complete words. Therefore they are enclosed in \\< and \\>
while searching. REGEXP can also be the quoted symbol
'nicknames, which matches the nickname of any user on the
current server.
BUTTON is the number of the regexp grouping actually matching the
button, This is ignored if REGEXP is 'nicknames.
FORM is a lisp expression which must eval to true for the button to
be added,
CALLBACK is the function to call when the user push this button.
CALLBACK can also be a symbol. Its variable value will be used
as the callback function.
PAR is a number of a regexp grouping whose text will be passed to
CALLBACK. There can be several PAR arguments. If REGEXP is
'nicknames, these are ignored, and CALLBACK will be called with
the nickname matched as the argument."
:group 'erc-button
:type '(repeat
(list :tag "Button"
(choice :tag "Matches"
regexp
(variable :tag "Variable containing regexp")
(const :tag "Nicknames" 'nicknames))
(integer :tag "Number of the regexp section that matches")
(choice :tag "When to buttonize"
(const :tag "Always" t)
(sexp :tag "Only when this evaluates to non-nil"))
(function :tag "Function to call when button is pressed")
(repeat :tag "Sections of regexp to send to the function"
:inline t
(integer :tag "Regexp section number")))))
(defcustom erc-emacswiki-url "http://www.emacswiki.org/cgi-bin/wiki.pl?"
"*URL of the EmacsWiki Homepage."
:group 'erc-button
:type 'string)
(defcustom erc-emacswiki-lisp-url "http://www.emacswiki.org/elisp/"
"*URL of the EmacsWiki ELisp area."
:group 'erc-button
:type 'string)
(defvar erc-button-keymap
(let ((map (make-sparse-keymap)))
(define-key map (kbd "RET") 'erc-button-press-button)
(if (featurep 'xemacs)
(define-key map (kbd "<button2>") 'erc-button-click-button)
(define-key map (kbd "<mouse-2>") 'erc-button-click-button))
(define-key map (kbd "TAB") 'erc-button-next)
(set-keymap-parent map erc-mode-map)
map)
"Local keymap for ERC buttons.")
(defvar erc-button-syntax-table
(let ((table (make-syntax-table)))
(modify-syntax-entry ?\( "w" table)
(modify-syntax-entry ?\) "w" table)
(modify-syntax-entry ?\[ "w" table)
(modify-syntax-entry ?\] "w" table)
(modify-syntax-entry ?\{ "w" table)
(modify-syntax-entry ?\} "w" table)
(modify-syntax-entry ?` "w" table)
(modify-syntax-entry ?' "w" table)
(modify-syntax-entry ?^ "w" table)
(modify-syntax-entry ?- "w" table)
(modify-syntax-entry ?_ "w" table)
(modify-syntax-entry ?| "w" table)
(modify-syntax-entry ?\\ "w" table)
table)
"Syntax table used when buttonizing messages.
This syntax table should make all the legal nick characters word
constituents.")
(defun erc-button-add-buttons ()
"Find external references in the current buffer and make buttons of them.
\"External references\" are things like URLs, as
specified by `erc-button-alist'."
(interactive)
(save-excursion
(with-syntax-table erc-button-syntax-table
(let ((buffer-read-only nil)
(inhibit-point-motion-hooks t)
(inhibit-field-text-motion t)
(alist erc-button-alist)
entry regexp data)
(erc-button-remove-old-buttons)
(dolist (entry alist)
(if (equal (car entry) (quote (quote nicknames)))
(erc-button-add-nickname-buttons entry)
(progn
(setq regexp (or (and (stringp (car entry)) (car entry))
(and (boundp (car entry))
(symbol-value (car entry)))))
(cond ((stringp regexp)
(erc-button-add-buttons-1 regexp entry))
((and (listp regexp) (stringp (car regexp)))
(dolist (r regexp)
(erc-button-add-buttons-1
(concat "\\<" (regexp-quote r) "\\>")
entry)))
((and (listp regexp) (listp (car regexp))
(stringp (caar regexp)))
(dolist (elem regexp)
(erc-button-add-buttons-1
(concat "\\<" (regexp-quote (car elem)) "\\>")
entry)))))))))))
(defun erc-button-add-nickname-buttons (entry)
"Search through the buffer for nicknames, and add buttons."
(let ((form (nth 2 entry))
(fun (nth 3 entry))
bounds word)
(when (or (eq t form)
(eval form))
(goto-char (point-min))
(while (forward-word 1)
(setq bounds (bounds-of-thing-at-point 'word))
(setq word (buffer-substring-no-properties
(car bounds) (cdr bounds)))
(if (erc-get-server-user word)
(erc-button-add-button (car bounds) (cdr bounds)
fun t (list word)))))))
(defun erc-button-add-buttons-1 (regexp entry)
"Search through the buffer for matches to ENTRY and add buttons."
(goto-char (point-min))
(while (re-search-forward regexp nil t)
(let ((start (match-beginning (nth 1 entry)))
(end (match-end (nth 1 entry)))
(form (nth 2 entry))
(fun (nth 3 entry))
(data (mapcar 'match-string (nthcdr 4 entry))))
(when (or (eq t form)
(eval form))
(erc-button-add-button start end fun nil data regexp)))))
(defun erc-button-remove-old-buttons ()
"Remove all existing buttons.
This is called with narrowing in effect, just before the text is
buttonized again. Removing a button means to remove all the properties
that `erc-button-add-button' adds, except for the face."
(remove-text-properties
(point-min) (point-max)
'(erc-callback nil
erc-data nil
mouse-face nil
keymap nil)))
(defun erc-button-add-button (from to fun nick-p &optional data regexp)
"Create a button between FROM and TO with callback FUN and data DATA.
NICK-P specifies if this is a nickname button.
REGEXP is the regular expression which matched for this button."
;; Really nasty hack to <URL: > ise urls, and line-wrap them if
;; they're going to be wider than `erc-fill-column'.
;; This could be a lot cleaner, but it works for me -- lawrence.
(let (fill-column)
(when (and erc-button-wrap-long-urls
(string= regexp erc-button-url-regexp)
(> (- to from)
(setq fill-column (- (if (numberp erc-button-wrap-long-urls)
erc-button-wrap-long-urls
erc-fill-column)
(length erc-fill-prefix)))))
(setq to (prog1 (point-marker) (insert ">"))
from (prog2 (goto-char from) (point-marker) (insert "<URL: ")))
(let ((pos (copy-marker from)))
(while (> (- to pos) fill-column)
(goto-char (+ pos fill-column))
(insert "\n" erc-fill-prefix) ; This ought to figure out
; what type of filling we're
; doing, and indent accordingly.
(move-marker pos (point))))))
(if nick-p
(when erc-button-nickname-face
(erc-button-add-face from to erc-button-nickname-face))
(when erc-button-face
(erc-button-add-face from to erc-button-face)))
(add-text-properties
from to
(nconc (and erc-button-mouse-face
(list 'mouse-face erc-button-mouse-face))
(list 'erc-callback fun)
(list 'keymap erc-button-keymap)
(list 'rear-nonsticky t)
(and data (list 'erc-data data))))
(widget-convert-button 'link from to :action 'erc-button-press-button
:suppress-face t
;; Make XEmacs use our faces.
:button-face (if nick-p
erc-button-nickname-face
erc-button-face)
;; Make XEmacs behave with mouse-clicks, for
;; some reason, widget stuff overrides the
;; 'keymap text-property.
:mouse-down-action 'erc-button-click-button))
(defun erc-button-add-face (from to face)
"Add FACE to the region between FROM and TO."
;; If we just use `add-text-property', then this will overwrite any
;; face text property already used for the button. It will not be
;; merged correctly. If we use overlays, then redisplay will be
;; very slow with lots of buttons. This is why we manually merge
;; face text properties.
(let ((old (erc-list (get-text-property from 'face)))
(pos from)
(end (next-single-property-change from 'face nil to))
new)
;; old is the face at pos, in list form. It is nil if there is no
;; face at pos. If nil, the new face is FACE. If not nil, the
;; new face is a list containing FACE and the old stuff. end is
;; where this face changes.
(while (< pos to)
(setq new (if old (cons face old) face))
(put-text-property pos end 'face new)
(setq pos end
old (erc-list (get-text-property pos 'face))
end (next-single-property-change pos 'face nil to)))))
;; widget-button-click calls with two args, we ignore the first.
;; Since Emacs runs this directly, rather than with
;; widget-button-click, we need to fake an extra arg in the
;; interactive spec.
(defun erc-button-click-button (ignore event)
"Call `erc-button-press-button'."
(interactive "P\ne")
(save-excursion
(mouse-set-point event)
(erc-button-press-button)))
;; XEmacs calls this via widget-button-press with a bunch of arguments
;; which we don't care about.
(defun erc-button-press-button (&rest ignore)
"Check text at point for a callback function.
If the text at point has a `erc-callback' property,
call it with the value of the `erc-data' text property."
(interactive)
(let* ((data (get-text-property (point) 'erc-data))
(fun (get-text-property (point) 'erc-callback)))
(unless fun
(message "No button at point"))
(when (and fun (symbolp fun) (not (fboundp fun)))
(error "Function %S is not bound" fun))
(apply fun data)))
(defun erc-button-next ()
"Go to the next button in this buffer."
(interactive)
(let ((here (point)))
(when (< here (erc-beg-of-input-line))
(while (and (get-text-property here 'erc-callback)
(not (= here (point-max))))
(setq here (1+ here)))
(while (and (not (get-text-property here 'erc-callback))
(not (= here (point-max))))
(setq here (1+ here)))
(if (< here (point-max))
(goto-char here)
(error "No next button"))
t)))
(defun erc-browse-emacswiki (thing)
"Browse to thing in the emacs-wiki."
(browse-url (concat erc-emacswiki-url thing)))
(defun erc-browse-emacswiki-lisp (thing)
"Browse to THING in the emacs-wiki elisp area."
(browse-url (concat erc-emacswiki-lisp-url thing)))
;;; Nickname buttons:
(defcustom erc-nick-popup-alist
'(("DeOp" . (erc-cmd-DEOP nick))
("Kick" . (erc-cmd-KICK (concat nick " "
(read-from-minibuffer
(concat "Kick " nick ", reason: ")))))
("Msg" . (erc-cmd-MSG (concat nick " "
(read-from-minibuffer
(concat "Message to " nick ": ")))))
("Op" . (erc-cmd-OP nick))
("Query" . (erc-cmd-QUERY nick))
("Whois" . (erc-cmd-WHOIS nick))
("Lastlog" . (erc-cmd-LASTLOG nick)))
"*An alist of possible actions to take on a nickname.
An entry looks like (\"Action\" . SEXP) where SEXP is evaluated with
the variable `nick' bound to the nick in question.
Examples:
(\"DebianDB\" .
(shell-command
(format
\"ldapsearch -x -P 2 -h db.debian.org -b dc=debian,dc=org ircnick=%s\"
nick)))"
:group 'erc-button
:type '(repeat (cons (string :tag "Op")
sexp)))
(defun erc-nick-popup (nick)
(let* ((completion-ignore-case t)
(action (completing-read (concat "What action to take on '" nick "'? ")
erc-nick-popup-alist))
(code (cdr (assoc action erc-nick-popup-alist))))
(when code
(erc-set-active-buffer (current-buffer))
(eval code))))
;;; Callback functions
(defun erc-button-describe-symbol (symbol-name)
"Describe SYMBOL-NAME.
Use `describe-function' for functions, `describe-variable' for variables,
and `apropos' for other symbols."
(let ((symbol (intern-soft symbol-name)))
(cond ((and symbol (fboundp symbol))
(describe-function symbol))
((and symbol (boundp symbol))
(describe-variable symbol))
(t (apropos symbol-name)))))
(defun erc-button-beats-to-time (beats)
"Display BEATS in a readable time format."
(let* ((seconds (- (* (string-to-number beats) 86.4)
3600
(- (car (current-time-zone)))))
(hours (mod (floor seconds 3600) 24))
(minutes (mod (round seconds 60) 60)))
(message (format "@%s is %d:%02d local time"
beats hours minutes))))
(provide 'erc-button)
;;; erc-button.el ends here
;; Local Variables:
;; indent-tabs-mode: nil
;; End:
;; arch-tag: 7d23bed4-2f30-4273-a03f-d7a274c605c4

207
lisp/erc/erc-compat.el Normal file
View file

@ -0,0 +1,207 @@
;;; erc-compat.el --- ERC compatibility code for XEmacs
;; Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
;; Author: Alex Schroeder <alex@gnu.org>
;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?EmacsIRCClient
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; This mostly defines stuff that cannot be worked around easily.
;;; Code:
(require 'format-spec)
;;;###autoload (autoload 'erc-define-minor-mode "erc-compat")
(defalias 'erc-define-minor-mode 'define-minor-mode)
(put 'erc-define-minor-mode 'edebug-form-spec 'define-minor-mode)
(defun erc-decode-coding-string (s coding-system)
"Decode S using CODING-SYSTEM."
(decode-coding-string s coding-system t))
(defun erc-encode-coding-string (s coding-system)
"Encode S using CODING-SYSTEM.
Return the same string, if the encoding operation is trivial.
See `erc-encoding-coding-alist'."
(encode-coding-string s coding-system t))
(defalias 'erc-propertize 'propertize)
(defalias 'erc-view-mode-enter 'view-mode-enter)
(defalias 'erc-function-arglist 'help-function-arglist)
(defalias 'erc-delete-dups 'delete-dups)
(defalias 'erc-replace-regexp-in-string 'replace-regexp-in-string)
(defvar erc-emacs-build-time
(if (stringp emacs-build-time)
emacs-build-time
(format-time-string "%Y-%m-%d" emacs-build-time))
"Time at which Emacs was dumped out.")
;; 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)
"Replace the subexpression SUBEXP of the last match in STRING with NEWTEXT.
MATCH is the text which matched the subexpression (see `match-string').
START is the beginning position of the last match (see `match-beginning').
See `replace-match' for explanations of FIXEDCASE and LITERAL."
(cond ((featurep 'xemacs)
(string-match match string start)
(replace-match newtext fixedcase literal string))
(t (replace-match newtext fixedcase literal string subexp))))
(defalias 'erc-cancel-timer 'cancel-timer)
(defalias 'erc-make-obsolete 'make-obsolete)
(defalias 'erc-make-obsolete-variable 'make-obsolete-variable)
;; Provde an equivalent of `assert', based on the code from cl-macs.el
(defun erc-const-expr-p (x)
(cond ((consp x)
(or (eq (car x) 'quote)
(and (memq (car x) '(function function*))
(or (symbolp (nth 1 x))
(and (eq (and (consp (nth 1 x))
(car (nth 1 x))) 'lambda) 'func)))))
((symbolp x) (and (memq x '(nil t)) t))
(t t)))
(put 'erc-assertion-failed 'error-conditions '(error))
(put 'erc-assertion-failed 'error-message "Assertion failed")
(defun erc-list* (arg &rest rest)
"Return a new list with specified args as elements, cons'd to last arg.
Thus, `(list* A B C D)' is equivalent to `(nconc (list A B C) D)', or to
`(cons A (cons B (cons C D)))'."
(cond ((not rest) arg)
((not (cdr rest)) (cons arg (car rest)))
(t (let* ((n (length rest))
(copy (copy-sequence rest))
(last (nthcdr (- n 2) copy)))
(setcdr last (car (cdr last)))
(cons arg copy)))))
(defmacro erc-assert (form &optional show-args string &rest args)
"Verify that FORM returns non-nil; signal an error if not.
Second arg SHOW-ARGS means to include arguments of FORM in message.
Other args STRING and ARGS... are arguments to be passed to `error'.
They are not evaluated unless the assertion fails. If STRING is
omitted, a default message listing FORM itself is used."
(let ((sargs
(and show-args
(delq nil (mapcar
(function
(lambda (x)
(and (not (erc-const-expr-p x)) x)))
(cdr form))))))
(list 'progn
(list 'or form
(if string
(erc-list* 'error string (append sargs args))
(list 'signal '(quote erc-assertion-failed)
(erc-list* 'list (list 'quote form) sargs))))
nil)))
;; Provide a simpler replacement for `member-if'
(defun erc-member-if (predicate list)
"Find the first item satisfying PREDICATE in LIST.
Return the sublist of LIST whose car matches."
(let ((ptr list))
(catch 'found
(while ptr
(when (funcall predicate (car ptr))
(throw 'found ptr))
(setq ptr (cdr ptr))))))
;; Provide a simpler replacement for `delete-if'
(defun erc-delete-if (predicate seq)
"Remove all items satisfying PREDICATE in SEQ.
This is a destructive function: it reuses the storage of SEQ
whenever possible."
;; remove from car
(while (when (funcall predicate (car seq))
(setq seq (cdr seq))))
;; remove from cdr
(let ((ptr seq)
(next (cdr seq)))
(while next
(when (funcall predicate (car next))
(setcdr ptr (if (consp next)
(cdr next)
nil)))
(setq ptr (cdr ptr))
(setq next (cdr ptr))))
seq)
;; Provide a simpler replacement for `remove-if-not'
(defun erc-remove-if-not (predicate seq)
"Remove all items not satisfying PREDICATE in SEQ.
This is a non-destructive function; it makes a copy of SEQ to
avoid corrupting the original SEQ."
(let (newseq)
(dolist (el seq)
(when (funcall predicate el)
(setq newseq (cons el newseq))))
(nreverse newseq)))
;; Provide a simpler replacement for `gensym'.
(defvar *erc-sym-counter* 0)
(defun erc-gensym ()
"Generate a new uninterned symbol."
(let ((num (prog1 *erc-sym-counter*
(setq *erc-sym-counter* (1+ *erc-sym-counter*)))))
(make-symbol (format "*erc-sym-%d*" num))))
;; Copied from cl-extra.el
(defun erc-subseq (seq start &optional end)
"Return the subsequence of SEQ from START to END.
If END is omitted, it defaults to the length of the sequence.
If START or END is negative, it counts from the end."
(if (stringp seq) (substring seq start end)
(let (len)
(and end (< end 0) (setq end (+ end (setq len (length seq)))))
(if (< start 0) (setq start (+ start (or len (setq len (length seq))))))
(cond ((listp seq)
(if (> start 0) (setq seq (nthcdr start seq)))
(if end
(let ((res nil))
(while (>= (setq end (1- end)) start)
(push (pop seq) res))
(nreverse res))
(copy-sequence seq)))
(t
(or end (setq end (or len (length seq))))
(let ((res (make-vector (max (- end start) 0) nil))
(i 0))
(while (< start end)
(aset res i (aref seq start))
(setq i (1+ i) start (1+ start)))
res))))))
(provide 'erc-compat)
;;; erc-compat.el ends here
;;
;; Local Variables:
;; indent-tabs-mode: t
;; tab-width: 8
;; End:
;; arch-tag: 8948ffe0-aff8-4ad8-a196-368ebbfd58ff

222
lisp/erc/erc-complete.el Normal file
View file

@ -0,0 +1,222 @@
;;; erc-complete.el --- Provides Nick name completion for ERC
;; Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
;; Author: Alex Schroeder <alex@gnu.org>
;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcCompletion
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; This file is obsolete. Use completion from erc-pcomplete instead.
;; This file is based on hippie-expand, while the new file is based on
;; pcomplete. There is no autoload cookie in this file. If you want
;; to use the code in this file, add the following to your ~/.emacs:
;; (autoload 'erc-complete "erc-complete" "Complete nick at point." t)
;;; Code:
(require 'erc)
(require 'erc-match); for erc-pals
(require 'hippie-exp); for the hippie expand stuff
;;;###autoload
(defun erc-complete ()
"Complete nick at point.
See `erc-try-complete-nick' for more technical info.
This function is obsolete, use `erc-pcomplete' instead."
(interactive)
(let ((hippie-expand-try-functions-list '(erc-try-complete-nick)))
(hippie-expand nil)))
(defgroup erc-old-complete nil
"Nick completion. Obsolete, use erc-pcomplete instead."
:group 'erc)
(defcustom erc-nick-completion 'all
"Determine how the list of nicks is determined during nick completion.
See `erc-complete-nick' for information on how to activate this.
pals: Use `erc-pals'.
all: All channel members.
You may also provide your own function that returns a list of completions.
One example is `erc-nick-completion-exclude-myself',
or you may use an arbitrary lisp expression."
:type '(choice (const :tag "List of pals" pals)
(const :tag "All channel members" all)
(const :tag "All channel members except yourself"
erc-nick-completion-exclude-myself)
(repeat :tag "List" (string :tag "Nick"))
function
sexp)
:group 'erc-old-complete)
(defcustom erc-nick-completion-ignore-case t
"*Non-nil means don't consider case significant in nick completion.
Case will be automatically corrected when non-nil.
For instance if you type \"dely TAB\" the word completes and changes to
\"delYsid\"."
:group 'erc-old-complete
:type 'boolean)
(defun erc-nick-completion-exclude-myself ()
"Get a list of all the channel members except you.
This function returns a list of all the members in the channel, except
your own nick. This way if you're named foo and someone is called foobar,
typing \"f o TAB\" will directly give you foobar. Use this with
`erc-nick-completion'."
(delete
(erc-current-nick)
(mapcar (function car) (erc-get-channel-user-list))))
(defcustom erc-nick-completion-postfix ": "
"*When `erc-complete' is used in the first word after the prompt,
add this string when a unique expansion was found."
:group 'erc-old-complete
:type 'string)
(defun erc-command-list ()
"Returns a list of strings of the defined user commands."
(let ((case-fold-search nil))
(mapcar (lambda (x)
(concat "/" (downcase (substring (symbol-name x) 8))))
(apropos-internal "erc-cmd-[A-Z]+"))))
(defun erc-try-complete-nick (old)
"Complete nick at point.
This is a function to put on `hippie-expand-try-functions-list'.
Then use \\[hippie-expand] to expand nicks.
The type of completion depends on `erc-nick-completion'."
(cond ((eq erc-nick-completion 'pals)
(try-complete-erc-nick old erc-pals))
((eq erc-nick-completion 'all)
(try-complete-erc-nick old (append
(mapcar (function car)
(erc-get-channel-user-list))
(erc-command-list))))
((functionp erc-nick-completion)
(try-complete-erc-nick old (funcall erc-nick-completion)))
(t
(try-complete-erc-nick old erc-nick-completion))))
(defvar try-complete-erc-nick-window-configuration nil
"The window configuration for `try-complete-erc-nick'.
When called the first time, a window config is stored here,
and when completion is done, the window config is restored
from here. See `try-complete-erc-nick-restore' and
`try-complete-erc-nick'.")
(defun try-complete-erc-nick-restore ()
"Restore window configuration."
(if (not try-complete-erc-nick-window-configuration)
(when (get-buffer "*Completions*")
(delete-windows-on "*Completions*"))
(set-window-configuration
try-complete-erc-nick-window-configuration)
(setq try-complete-erc-nick-window-configuration nil)))
(defun try-complete-erc-nick (old completions)
"Try to complete current word depending on `erc-try-complete-nick'.
The argument OLD has to be nil the first call of this function, and t
for subsequent calls (for further possible completions of the same
string). It returns t if a new completion is found, nil otherwise. The
second argument COMPLETIONS is a list of completions to use. Actually,
it is only used when OLD is nil. It will be copied to `he-expand-list'
on the first call. After that, it is no longer used.
Window configurations are stored in
`try-complete-erc-nick-window-configuration'."
(let (expansion
final
(alist (if (consp (car completions))
completions
(mapcar (lambda (s)
(if (and (erc-complete-at-prompt)
(and (not (= (length s) 0))
(not (eq (elt s 0) ?/))))
(list (concat s erc-nick-completion-postfix))
(list (concat s " "))))
completions))) ; make alist if required
(completion-ignore-case erc-nick-completion-ignore-case))
(he-init-string (he-dabbrev-beg) (point))
;; If there is a string to complete, complete it using alist.
;; expansion is the possible expansion, or t. If expansion is t
;; or if expansion is the "real" thing, we are finished (final is
;; t). Take care -- expansion can also be nil!
(unless (string= he-search-string "")
(setq expansion (try-completion he-search-string alist)
final (or (eq t expansion)
(and expansion
(eq t (try-completion expansion alist))))))
(cond ((not expansion)
;; There is no expansion at all.
(try-complete-erc-nick-restore)
(he-reset-string)
nil)
((eq t expansion)
;; The user already has the correct expansion.
(try-complete-erc-nick-restore)
(he-reset-string)
t)
((and old (string= expansion he-search-string))
;; This is the second time around and nothing changed,
;; ie. the user tried to expand something incomplete
;; without making a choice -- hitting TAB twice, for
;; example.
(try-complete-erc-nick-restore)
(he-reset-string)
nil)
(final
;; The user has found the correct expansion.
(try-complete-erc-nick-restore)
(he-substitute-string expansion)
t)
(t
;; We found something but we are not finished. Show a
;; completions buffer. Substitute what we found and return
;; t.
(setq try-complete-erc-nick-window-configuration
(current-window-configuration))
(with-output-to-temp-buffer "*Completions*"
(display-completion-list (all-completions he-search-string alist)))
(he-substitute-string expansion)
t))))
(defun erc-at-beginning-of-line-p (point &optional bol-func)
(save-excursion
(funcall (or bol-func
'erc-bol))
(equal point (point))))
(defun erc-complete-at-prompt ()
"Returns t if point is directly after `erc-prompt' when doing completion."
(erc-at-beginning-of-line-p (he-dabbrev-beg)))
(provide 'erc-complete)
;;; erc-complete.el ends here
;;
;; Local Variables:
;; indent-tabs-mode: t
;; tab-width: 8
;; End:
;; arch-tag: 3be13ee8-8fdb-41ab-83c2-6582c757b91e

1135
lisp/erc/erc-dcc.el Normal file

File diff suppressed because it is too large Load diff

180
lisp/erc/erc-ezbounce.el Normal file
View file

@ -0,0 +1,180 @@
;;; erc-ezbounce.el --- Handle EZBounce bouncer commands
;; Copyright (C) 2002, 2004 Free Software Foundation, Inc.
;; Author: Andreas Fuchs <asf@void.at>
;; Keywords: comm
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;;; Code:
(require 'erc)
(eval-when-compile (require 'cl))
(defgroup erc-ezbounce nil
"Interface to the EZBounce IRC bouncer (a virtual IRC server)"
:group 'erc)
(defcustom erc-ezb-regexp "^ezbounce!srv$"
"Regexp used by the EZBouncer to identify itself to the user."
:group 'erc-ezbounce
:type 'string)
(defcustom erc-ezb-login-alist '()
"Alist of logins suitable for the server we're connecting to.
The alist's format is as follows:
(((server . port) . (username . password))
((server . port) . (username . password))
...)"
:group 'erc-ezbounce
:type '(repeat
(cons (cons :tag "Server"
string
string)
(cons :tag "Login"
string
string))))
(defvar erc-ezb-action-alist '(("^\\[awaiting login/pass command\\]$" . erc-ezb-identify)
("^\\[use /quote CONN <server> to connect\\]$" . erc-ezb-select)
("^ID +IRC NICK +TO +TIME$" . erc-ezb-init-session-list)
("^$" . erc-ezb-end-of-session-list)
(".*" . erc-ezb-add-session))
"Alist of actions to take on NOTICEs from EZBounce.")
(defvar erc-ezb-session-list '()
"List of detached EZBounce sessions.")
(make-variable-buffer-local 'erc-ezb-session-list)
(defvar erc-ezb-inside-session-listing nil
"Indicate whether current notices are expected to be EZB session listings.")
;;;###autoload
(defun erc-cmd-ezb (line &optional force)
"Send EZB commands to the EZBouncer verbatim."
(erc-server-send (concat "EZB " line)))
(put 'erc-cmd-EZB 'do-not-parse-args t)
;;;###autoload
(defun erc-ezb-get-login (server port)
"Return an appropriate EZBounce login for SERVER and PORT.
Look up entries in `erc-ezb-login-alist'. If the username or password
in the alist is `nil', prompt for the appropriate values."
(let ((login (cdr (assoc (cons server port) erc-ezb-login-alist))))
(when login
(let ((username (car login))
(password (cdr login)))
(when (null username)
(setq username (read-from-minibuffer (format "EZBounce user name for %s:%s: " server port))))
(when (null password)
(setq password (read-passwd (format "EZBounce password for %s:%s: " server port))))
(cons username password)))))
;;;###autoload
(defun erc-ezb-lookup-action (message)
(let ((function-alist erc-ezb-action-alist)
found)
(while (and (not found)
function-alist)
(let ((regexp (caar function-alist))
(function (cdar function-alist)))
(when (string-match regexp message)
(setq found function))
(setq function-alist (cdr function-alist))))
found))
;;;###autoload
(defun erc-ezb-notice-autodetect (proc parsed)
"React on an EZBounce NOTICE request."
(let* ((sender (erc-response.sender parsed))
(message (erc-response.contents parsed))
(function (erc-ezb-lookup-action message)))
(when (and (string-match erc-ezb-regexp sender)
function)
(funcall function message)))
nil)
;;;###autoload
(defun erc-ezb-identify (message)
"Identify to the EZBouncer server."
(let ((login (erc-ezb-get-login erc-session-server (erc-port-to-string erc-session-port))))
(unless (null login)
(let ((username (car login))
(pass (cdr login)))
(erc-server-send (concat "LOGIN " username " " pass))))))
;;;###autoload
(defun erc-ezb-init-session-list (message)
"Reset the EZBounce session list to NIL."
(setq erc-ezb-session-list nil)
(setq erc-ezb-inside-session-listing t))
;;;###autoload
(defun erc-ezb-end-of-session-list (message)
"Indicate the end of the EZBounce session listing."
(setq erc-ezb-inside-session-listing nil))
;;;###autoload
(defun erc-ezb-add-session (message)
"Add an EZBounce session to the session list."
(when (and erc-ezb-inside-session-listing
(string-match "^\\([^ ]+\\) +\\([^ ]+\\) +\\([^ ]+\\) +\\([^ ]+\\)$" message))
(let ((id (match-string 1 message))
(nick (match-string 2 message))
(to (match-string 3 message)))
(add-to-list 'erc-ezb-session-list (list id nick to)))))
;;;###autoload
(defun erc-ezb-select (message)
"Select an IRC server to use by EZBounce, in ERC style."
(unless (and erc-ezb-session-list
(erc-ezb-select-session))
(let* ((server (read-from-minibuffer
"IRC server: " "" nil nil 'erc-server-history-list))
(port
(erc-string-to-port
(read-from-minibuffer "IRC port: "
(erc-port-to-string "6667")))))
(erc-server-send (format "CONN %s %s" server port)))))
;;;###autoload
(defun erc-ezb-select-session ()
"Select a detached EZBounce session."
(let ((session (completing-read "Existing Session (RET to enter a new one): "
erc-ezb-session-list)))
(if (string= session "")
nil
(erc-server-send (format "REATTACH %s" session)))))
;;;###autoload
(defun erc-ezb-initialize ()
"Add EZBouncer convenience functions to ERC."
(add-hook 'erc-server-NOTICE-functions 'erc-ezb-notice-autodetect))
(provide 'erc-ezbounce)
;; arch-tag: e972aa7b-a9f4-4d16-a489-074ec7a1002e
;;; erc-ezbounce.el ends here

197
lisp/erc/erc-fill.el Normal file
View file

@ -0,0 +1,197 @@
;;; erc-fill.el --- Filling IRC messages in various ways
;; Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
;; Author: Andreas Fuchs <asf@void.at>
;; Mario Lang <mlang@delysid.org>
;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcFilling
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; This package implements filling of messages sent and received. Use
;; `erc-fill-mode' to switch it on. Customize `erc-fill-function' to
;; change the style.
;;; Code:
(require 'erc)
(require 'erc-stamp); for the timestamp stuff
(defgroup erc-fill nil
"Filling means to reformat long lines in different ways."
:group 'erc)
;;;###autoload (autoload 'erc-fill-mode "erc-fill" nil t)
(erc-define-minor-mode erc-fill-mode
"Toggle ERC fill mode.
With numeric arg, turn ERC fill mode on if and only if arg is
positive. In ERC fill mode, messages in the channel buffers are
filled."
nil nil nil
:global t :group 'erc-fill
(if erc-fill-mode
(erc-fill-enable)
(erc-fill-disable)))
(defun erc-fill-enable ()
"Setup hooks for `erc-fill-mode'."
(interactive)
(add-hook 'erc-insert-modify-hook 'erc-fill)
(add-hook 'erc-send-modify-hook 'erc-fill))
(defun erc-fill-disable ()
"Cleanup hooks, disable `erc-fill-mode'."
(interactive)
(remove-hook 'erc-insert-modify-hook 'erc-fill)
(remove-hook 'erc-send-modify-hook 'erc-fill))
(defcustom erc-fill-prefix nil
"Values used as `fill-prefix' for `erc-fill-variable'.
nil means fill with space, a string means fill with this string."
:group 'erc-fill
:type '(choice (const nil) string))
(defcustom erc-fill-function 'erc-fill-variable
"Function to use for filling messages.
Variable Filling with an `erc-fill-prefix' of nil:
<shortnick> this is a very very very long message with no
meaning at all
Variable Filling with an `erc-fill-prefix' of four spaces:
<shortnick> this is a very very very long message with no
meaning at all
Static Filling with `erc-fill-static-center' of 27:
<shortnick> foo bar baz
<a-very-long-nick> foo bar baz quuuuux
<shortnick> this is a very very very long message with no
meaning at all
These two styles are implemented using `erc-fill-variable' and
`erc-fill-static'. You can, of course, define your own filling
function. Narrowing to the region in question is in effect while your
function is called."
:group 'erc-fill
:type '(choice (const :tag "Variable Filling" erc-fill-variable)
(const :tag "Static Filling" erc-fill-static)
function))
(defcustom erc-fill-static-center 27
"Column around which all statically filled messages will be
centered. This column denotes the point where the ' ' character
between <nickname> and the entered text will be put, thus aligning
nick names right and text left."
:group 'erc-fill
:type 'integer)
(defcustom erc-fill-variable-maximum-indentation 17
"If we indent a line after a long nick, don't indent more then this
characters. Set to nil to disable."
:group 'erc-fill
:type 'integer)
(defcustom erc-fill-column 78
"The column at which a filled paragraph is broken."
:group 'erc-fill
:type 'integer)
;;;###autoload
(defun erc-fill ()
"Fill a region using the function referenced in `erc-fill-function'.
You can put this on `erc-insert-modify-hook' and/or `erc-send-modify-hook'."
(unless (erc-string-invisible-p (buffer-substring (point-min) (point-max)))
(when erc-fill-function
(funcall erc-fill-function))))
(defun erc-fill-static ()
"Fills a text such that messages start at column `erc-fill-static-center'."
(save-match-data
(goto-char (point-min))
(looking-at "^\\(\\S-+\\)")
(let ((nick (match-string 1)))
(let ((fill-column (- erc-fill-column (erc-timestamp-offset)))
(fill-prefix (make-string erc-fill-static-center 32)))
(insert (make-string (max 0 (- erc-fill-static-center
(length nick) 1))
32))
(erc-fill-regarding-timestamp))
(erc-restore-text-properties))))
(defun erc-fill-variable ()
"Fill from `point-min' to `point-max'."
(let ((fill-prefix erc-fill-prefix)
(fill-column (or erc-fill-column fill-column)))
(goto-char (point-min))
(if fill-prefix
(let ((first-line-offset (make-string (erc-timestamp-offset) 32)))
(insert first-line-offset)
(fill-region (point-min) (point-max) t t)
(goto-char (point-min))
(delete-char (length first-line-offset)))
(save-match-data
(let* ((nickp (looking-at "^\\(\\S-+\\)"))
(nick (if nickp
(match-string 1)
""))
(fill-column (- erc-fill-column (erc-timestamp-offset)))
(fill-prefix (make-string (min (+ 1 (length nick))
(- fill-column 1)
(or erc-fill-variable-maximum-indentation
fill-column))
32)))
(erc-fill-regarding-timestamp))))
(erc-restore-text-properties)))
(defun erc-fill-regarding-timestamp ()
"Fills a text such that messages start at column `erc-fill-static-center'."
(fill-region (point-min) (point-max) t t)
(goto-char (point-min))
(forward-line)
(indent-rigidly (point) (point-max) (erc-timestamp-offset)))
(defun erc-timestamp-offset ()
"Get length of timestamp if inserted left."
(if (and (boundp 'erc-timestamp-format)
erc-timestamp-format
(eq erc-insert-timestamp-function 'erc-insert-timestamp-left)
(not erc-hide-timestamps))
(length (format-time-string erc-timestamp-format))
0))
(defun erc-restore-text-properties ()
"Restore the property 'erc-parsed for the region."
(let* ((parsed-posn (text-property-not-all (point-min) (point-max)
'erc-parsed nil))
(parsed-prop (when parsed-posn
(get-text-property parsed-posn 'erc-parsed))))
(put-text-property (point-min) (point-max) 'erc-parsed parsed-prop)))
(provide 'erc-fill)
;;; erc-fill.el ends here
;; Local Variables:
;; indent-tabs-mode: nil
;; End:
;; arch-tag: 89224581-c2c2-4e26-92e5-e3a390dc516a

522
lisp/erc/erc-goodies.el Normal file
View file

@ -0,0 +1,522 @@
;; erc-goodies.el --- Collection of ERC modules
;; Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation
;; Author: Jorgen Schaefer <forcer@forcix.cx>
;; Most code is taken verbatim from erc.el, see there for the original
;; authors.
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; This provides some small but still useful modes for ERC.
;;; Code:
(require 'erc)
;; Imenu Autoload
(add-hook 'erc-mode-hook
(lambda ()
(setq imenu-create-index-function 'erc-create-imenu-index)))
(autoload 'erc-create-imenu-index "erc-imenu" "Imenu index creation function")
;;; Automatically scroll to bottom
(defcustom erc-input-line-position nil
"Specify where to position the input line when using `erc-scroll-to-bottom'.
This should be an integer specifying the line of the buffer on which
the input line should stay. A value of \"-1\" would keep the input
line positioned on the last line in the buffer. This is passed as an
argument to `recenter'."
:group 'erc-display
:type '(choice integer (const nil)))
(define-erc-module scrolltobottom nil
"This mode causes the prompt to stay at the end of the window.
You have to activate or deactivate it in already created windows
separately."
((add-hook 'erc-mode-hook 'erc-add-scroll-to-bottom))
((remove-hook 'erc-mode-hook 'erc-add-scroll-to-bottom)))
(defun erc-add-scroll-to-bottom ()
"A hook function for `erc-mode-hook' to recenter output at bottom of window.
If you find that ERC hangs when using this function, try customizing
the value of `erc-input-line-position'.
This works whenever scrolling happens, so it's added to
`window-scroll-functions' rather than `erc-insert-post-hook'."
;;(make-local-hook 'window-scroll-functions)
(add-hook 'window-scroll-functions 'erc-scroll-to-bottom nil t))
(defun erc-scroll-to-bottom (window display-start)
"Recenter WINDOW so that `point' is on the last line.
This is added to `window-scroll-functions' by `erc-add-scroll-to-bottom'.
You can control which line is recentered to by customizing the
variable `erc-input-line-position'.
DISPLAY-START is ignored."
(if (and window (window-live-p window))
;; Temporarily bind resize-mini-windows to nil so that users who have it
;; set to a non-nil value will not suffer from premature minibuffer
;; shrinkage due to the below recenter call. I have no idea why this
;; 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)
(save-restriction
(widen)
(when (and erc-insert-marker
;; we're editing a line. Scroll.
(> (point) erc-insert-marker))
(save-excursion
(goto-char (point-max))
(recenter (or erc-input-line-position -1))
(sit-for 0))))))))
;;; Make read only
(define-erc-module readonly nil
"This mode causes all inserted text to be read-only."
((add-hook 'erc-insert-post-hook 'erc-make-read-only)
(add-hook 'erc-send-post-hook 'erc-make-read-only))
((remove-hook 'erc-insert-post-hook 'erc-make-read-only)
(remove-hook 'erc-send-post-hook 'erc-make-read-only)))
(defun erc-make-read-only ()
"Make all the text in the current buffer read-only.
Put this function on `erc-insert-post-hook' and/or `erc-send-post-hook'."
(put-text-property (point-min) (point-max) 'read-only t)
(put-text-property (point-min) (point-max) 'front-sticky t)
(put-text-property (point-min) (point-max) 'rear-nonsticky t))
;; Distingush non-commands
(defvar erc-noncommands-list '(erc-cmd-ME
erc-cmd-COUNTRY
erc-cmd-SV
erc-cmd-SM
erc-cmd-SMV
erc-cmd-LASTLOG)
"List of commands that are aliases for CTCP ACTION or for erc messages.
If a command's function symbol is in this list, the typed command
does not appear in the ERC buffer after the user presses ENTER.")
(define-erc-module noncommands nil
"This mode distinguishies non-commands.
Commands listed in `erc-insert-this' know how to display
themselves."
((add-hook 'erc-send-pre-hook 'erc-send-distinguish-noncommands))
((remove-hook 'erc-send-pre-hook 'erc-send-distinguish-noncommands)))
(defun erc-send-distinguish-noncommands (str)
"If STR is an ERC non-command, set `erc-insert-this' to nil."
(let* ((command (erc-extract-command-from-line str))
(cmd-fun (and command
(car command))))
(when (and cmd-fun
(not (string-match "\n.+$" str))
(memq cmd-fun erc-noncommands-list))
(setq erc-insert-this nil))))
;;; IRC control character processing.
(defgroup erc-control-characters nil
"Dealing with control characters"
:group 'erc)
(defcustom erc-interpret-controls-p t
"*If non-nil, display IRC colours and other highlighting effects.
If this is set to the symbol `remove', ERC removes all IRC colors and
highlighting effects. When this variable is non-nil, it can cause Emacs to run
slowly on systems lacking sufficient CPU speed. In chatty channels, or in an
emergency (message flood) it can be turned off to save processing time. See
`erc-toggle-interpret-controls'."
:group 'erc-control-characters
:type '(choice (const :tag "Highlight control characters" t)
(const :tag "Remove control characters" remove)
(const :tag "Display raw control characters" nil)))
(defcustom erc-interpret-mirc-color nil
"*If non-nil, erc will interpret mIRC color codes."
:group 'erc-control-characters
:type 'boolean)
(defcustom erc-beep-p nil
"Beep if C-g is in the server message.
The value `erc-interpret-controls-p' must also be t for this to work."
:group 'erc-control-characters
:type 'boolean)
(defface erc-bold-face '((t (:bold t)))
"ERC bold face."
:group 'erc-faces)
(defface erc-inverse-face
'((t (:foreground "White" :background "Black")))
"ERC inverse face."
:group 'erc-faces)
(defface erc-underline-face '((t (:underline t)))
"ERC underline face."
:group 'erc-faces)
(defface fg:erc-color-face0 '((t (:foreground "White")))
"ERC face."
:group 'erc-faces)
(defface fg:erc-color-face1 '((t (:foreground "black")))
"ERC face."
:group 'erc-faces)
(defface fg:erc-color-face2 '((t (:foreground "blue4")))
"ERC face."
:group 'erc-faces)
(defface fg:erc-color-face3 '((t (:foreground "green4")))
"ERC face."
:group 'erc-faces)
(defface fg:erc-color-face4 '((t (:foreground "red")))
"ERC face."
:group 'erc-faces)
(defface fg:erc-color-face5 '((t (:foreground "brown")))
"ERC face."
:group 'erc-faces)
(defface fg:erc-color-face6 '((t (:foreground "purple")))
"ERC face."
:group 'erc-faces)
(defface fg:erc-color-face7 '((t (:foreground "orange")))
"ERC face."
:group 'erc-faces)
(defface fg:erc-color-face8 '((t (:foreground "yellow")))
"ERC face."
:group 'erc-faces)
(defface fg:erc-color-face9 '((t (:foreground "green")))
"ERC face."
:group 'erc-faces)
(defface fg:erc-color-face10 '((t (:foreground "lightblue1")))
"ERC face."
:group 'erc-faces)
(defface fg:erc-color-face11 '((t (:foreground "cyan")))
"ERC face."
:group 'erc-faces)
(defface fg:erc-color-face12 '((t (:foreground "blue")))
"ERC face."
:group 'erc-faces)
(defface fg:erc-color-face13 '((t (:foreground "deeppink")))
"ERC face."
:group 'erc-faces)
(defface fg:erc-color-face14 '((t (:foreground "gray50")))
"ERC face."
:group 'erc-faces)
(defface fg:erc-color-face15 '((t (:foreground "gray90")))
"ERC face."
:group 'erc-faces)
(defface bg:erc-color-face0 '((t (:background "White")))
"ERC face."
:group 'erc-faces)
(defface bg:erc-color-face1 '((t (:background "black")))
"ERC face."
:group 'erc-faces)
(defface bg:erc-color-face2 '((t (:background "blue4")))
"ERC face."
:group 'erc-faces)
(defface bg:erc-color-face3 '((t (:background "green4")))
"ERC face."
:group 'erc-faces)
(defface bg:erc-color-face4 '((t (:background "red")))
"ERC face."
:group 'erc-faces)
(defface bg:erc-color-face5 '((t (:background "brown")))
"ERC face."
:group 'erc-faces)
(defface bg:erc-color-face6 '((t (:background "purple")))
"ERC face."
:group 'erc-faces)
(defface bg:erc-color-face7 '((t (:background "orange")))
"ERC face."
:group 'erc-faces)
(defface bg:erc-color-face8 '((t (:background "yellow")))
"ERC face."
:group 'erc-faces)
(defface bg:erc-color-face9 '((t (:background "green")))
"ERC face."
:group 'erc-faces)
(defface bg:erc-color-face10 '((t (:background "lightblue1")))
"ERC face."
:group 'erc-faces)
(defface bg:erc-color-face11 '((t (:background "cyan")))
"ERC face."
:group 'erc-faces)
(defface bg:erc-color-face12 '((t (:background "blue")))
"ERC face."
:group 'erc-faces)
(defface bg:erc-color-face13 '((t (:background "deeppink")))
"ERC face."
:group 'erc-faces)
(defface bg:erc-color-face14 '((t (:background "gray50")))
"ERC face."
:group 'erc-faces)
(defface bg:erc-color-face15 '((t (:background "gray90")))
"ERC face."
:group 'erc-faces)
(defun erc-get-bg-color-face (n)
"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)
(when (> n 16)
(erc-log (format " Wrong color: %s" n))
(setq n (mod n 16)))
(cond
((and (>= n 0) (< n 16))
(intern (concat "bg:erc-color-face" (number-to-string n))))
(t (erc-log (format " Wrong color: %s" n)) 'default))))
(defun erc-get-fg-color-face (n)
"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)
(when (> n 16)
(erc-log (format " Wrong color: %s" n))
(setq n (mod n 16)))
(cond
((and (>= n 0) (< n 16))
(intern (concat "fg:erc-color-face" (number-to-string n))))
(t (erc-log (format " Wrong color: %s" n)) 'default))))
(define-erc-module irccontrols nil
"This mode enables the interpretation of IRC control chars."
((add-hook 'erc-insert-modify-hook 'erc-controls-highlight)
(add-hook 'erc-send-modify-hook 'erc-controls-highlight))
((remove-hook 'erc-insert-modify-hook 'erc-controls-highlight)
(remove-hook 'erc-send-modify-hook 'erc-controls-highlight)))
(defun erc-controls-interpret (str)
"Return a copy of STR after dealing with IRC control characters.
See `erc-interpret-controls-p' and `erc-interpret-mirc-color' for options."
(when str
(let ((s str))
(cond ((eq erc-interpret-controls-p 'remove)
(erc-controls-strip s))
(erc-interpret-controls-p
(let ((boldp nil)
(inversep nil)
(underlinep nil)
(fg nil)
(bg nil))
(while (string-match erc-controls-highlight-regexp s)
(let ((control (match-string 1 s))
(fg-color (match-string 2 s))
(bg-color (match-string 4 s))
(start (match-beginning 0))
(end (+ (match-beginning 0)
(length (match-string 5 s)))))
(setq s (erc-replace-match-subexpression-in-string
"" s control 1 start))
(cond ((and erc-interpret-mirc-color (or fg-color bg-color))
(setq fg fg-color)
(setq bg bg-color))
((string= control "\C-b")
(setq boldp (not boldp)))
((string= control "\C-v")
(setq inversep (not inversep)))
((string= control "\C-_")
(setq underlinep (not underlinep)))
((string= control "\C-c")
(setq fg nil
bg nil))
((string= control "\C-g")
(when erc-beep-p
(ding)))
((string= control "\C-o")
(setq boldp nil
inversep nil
underlinep nil
fg nil
bg nil))
(t nil))
(erc-controls-propertize
start end boldp inversep underlinep fg bg s)))
s))
(t s)))))
(defun erc-controls-strip (str)
"Return a copy of STR with all IRC control characters removed."
(when str
(let ((s str))
(while (string-match erc-controls-remove-regexp s)
(setq s (replace-match "" nil nil s)))
s)))
(defvar erc-controls-remove-regexp
"\C-b\\|\C-_\\|\C-v\\|\C-g\\|\C-o\\|\C-c[0-9]?[0-9]?\\(,[0-9][0-9]?\\)?"
"Regular expression which matches control characters to remove.")
(defvar erc-controls-highlight-regexp
(concat "\\(\C-b\\|\C-v\\|\C-_\\|\C-g\\|\C-o\\|"
"\C-c\\([0-9][0-9]?\\)?\\(,\\([0-9][0-9]?\\)\\)?\\)"
"\\([^\C-b\C-v\C-_\C-c\C-g\C-o\n]*\\)")
"Regular expression which matches control chars and the text to highlight.")
(defun erc-controls-highlight ()
"Highlight IRC control chars in the buffer.
This is useful for `erc-insert-modify-hook' and
`erc-send-modify-hook'. Also see `erc-interpret-controls-p' and
`erc-interpret-mirc-color'."
(goto-char (point-min))
(cond ((eq erc-interpret-controls-p 'remove)
(while (re-search-forward erc-controls-remove-regexp nil t)
(replace-match "")))
(erc-interpret-controls-p
(let ((boldp nil)
(inversep nil)
(underlinep nil)
(fg nil)
(bg nil))
(while (re-search-forward erc-controls-highlight-regexp nil t)
(let ((control (match-string 1))
(fg-color (match-string 2))
(bg-color (match-string 4))
(start (match-beginning 0))
(end (+ (match-beginning 0) (length (match-string 5)))))
(replace-match "" nil nil nil 1)
(cond ((and erc-interpret-mirc-color (or fg-color bg-color))
(setq fg fg-color)
(setq bg bg-color))
((string= control "\C-b")
(setq boldp (not boldp)))
((string= control "\C-v")
(setq inversep (not inversep)))
((string= control "\C-_")
(setq underlinep (not underlinep)))
((string= control "\C-c")
(setq fg nil
bg nil))
((string= control "\C-g")
(when erc-beep-p
(ding)))
((string= control "\C-o")
(setq boldp nil
inversep nil
underlinep nil
fg nil
bg nil))
(t nil))
(erc-controls-propertize start end
boldp inversep underlinep fg bg)))))
(t nil)))
(defun erc-controls-propertize (from to boldp inversep underlinep fg bg
&optional str)
"Prepend properties from IRC control characters between FROM and TO.
If optional argument STR is provided, apply to STR, otherwise prepend properties
to a region in the current buffer."
(font-lock-prepend-text-property
from
to
'face
(append (if boldp
'(erc-bold-face)
nil)
(if inversep
'(erc-inverse-face)
nil)
(if underlinep
'(erc-underline-face)
nil)
(if fg
(list (erc-get-fg-color-face fg))
nil)
(if bg
(list (erc-get-bg-color-face bg))
nil))
str)
str)
(defun erc-toggle-interpret-controls (&optional arg)
"Toggle interpretation of control sequences in messages.
If ARG is positive, interpretation is turned on.
Else interpretation is turned off."
(interactive "P")
(cond ((and (numberp arg) (> arg 0))
(setq erc-interpret-controls-p t))
(arg (setq erc-interpret-controls-p nil))
(t (setq erc-interpret-controls-p (not erc-interpret-controls-p))))
(message "ERC color interpretation %s"
(if erc-interpret-controls-p "ON" "OFF")))
;; Smiley
(define-erc-module smiley nil
"This mode translates text-smileys such as :-) into pictures.
This requires the function `smiley-region', which is defined in
smiley.el, which is part of Gnus."
((add-hook 'erc-insert-modify-hook 'erc-smiley)
(add-hook 'erc-send-modify-hook 'erc-smiley))
((remove-hook 'erc-insert-modify-hook 'erc-smiley)
(remove-hook 'erc-send-modify-hook 'erc-smiley)))
(defun erc-smiley ()
"Smilify a region.
This function should be used with `erc-insert-modify-hook'."
(when (fboundp 'smiley-region)
(smiley-region (point-min) (point-max))))
;; Unmorse
(define-erc-module unmorse nil
"This mode causes morse code in the current channel to be unmorsed."
((add-hook 'erc-insert-modify-hook 'erc-unmorse))
((remove-hook 'erc-insert-modify-hook 'erc-unmorse)))
(defun erc-unmorse ()
"Unmorse some text.
Add this to `erc-insert-modify-hook' if you happen to be on a
channel that has weird people talking in morse to each other.
See also `unmorse-region'."
(goto-char (point-min))
(when (re-search-forward "[.-]+\\([.-]+[/ ]\\)+[.-]+" nil t)
(unmorse-region (match-beginning 0) (match-end 0))))
;;; erc-occur
(defun erc-occur (string &optional proc)
"Search for STRING in all buffers related to current server.
If called interactively and prefix argument is given, search on all connected
servers. If called from a program, PROC specifies the server process."
(interactive
(list (read-string "Search for: ")
(if current-prefix-arg
nil erc-server-process)))
(if (fboundp 'multi-occur)
(multi-occur (erc-buffer-list nil proc) string)
(error "`multi-occur' is not defined as a function")))
(provide 'erc-goodies)
;; arch-tag: d987ae26-9e28-4c72-9596-e617309fb582
;;; erc-goodies.el ends here

184
lisp/erc/erc-ibuffer.el Normal file
View file

@ -0,0 +1,184 @@
;;; erc-ibuffer.el --- ibuffer integration with ERC
;; Copyright (C) 2002, 2004 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@delysid.org>
;; Keywords: comm
;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcIbuffer
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; This file contains code related to Ibuffer and ERC. Totally alpha,
;; needs work. Usage: Type / C-e C-h when in Ibuffer-mode to see new
;; limiting commands
;;; Code:
(require 'ibuffer)
(require 'erc)
(defgroup erc-ibuffer nil
"The Ibuffer group for ERC."
:group 'erc)
(defcustom erc-ibuffer-keyword-char ?k
"Char used to indicate a channel which had keyword traffic lately (hidden)."
:group 'erc-ibuffer
:type 'character)
(defcustom erc-ibuffer-pal-char ?p
"Char used to indicate a channel which had pal traffic lately (hidden)."
:group 'erc-ibuffer
:type 'character)
(defcustom erc-ibuffer-fool-char ?f
"Char used to indicate a channel which had fool traffic lately (hidden)."
:group 'erc-ibuffer
:type 'character)
(defcustom erc-ibuffer-dangerous-host-char ?d
"Char used to indicate a channel which had dangerous-host traffic lately (hidden)."
:group 'erc-ibuffer
:type 'character)
(ibuffer-define-limiter erc-server
(:documentation
"Toggle current view to buffers which are related to ERC servers."
:description "erc servers"
:reader
(let ((regexp (read-from-minibuffer "Limit by server (regexp) (RET for all): ")))
(if (string= regexp "")
".*"
regexp)))
(with-current-buffer buf
(and (eq major-mode 'erc-mode)
(string-match qualifier (or erc-server-announced-name
erc-session-server)))))
(ibuffer-define-column erc-modified (:name "M")
(if (and (boundp 'erc-track-mode)
erc-track-mode)
(let ((entry (assq (current-buffer) erc-modified-channels-alist)))
(if entry
(if (> (length entry) 1)
(cond ((eq 'pal (nth 1 entry))
(string erc-ibuffer-pal-char))
((eq 'fool (nth 1 entry))
(string erc-ibuffer-fool-char))
((eq 'keyword (nth 1 entry))
(string erc-ibuffer-keyword-char))
((eq 'dangerous-host (nth 1 entry))
(string erc-ibuffer-dangerous-host-char))
(t "$"))
(string ibuffer-modified-char))
" "))
" "))
(ibuffer-define-column erc-server-name (:name "Server")
(if (and (boundp 'erc-server-process) (processp erc-server-process))
(with-current-buffer (process-buffer erc-server-process)
(or erc-server-announced-name erc-session-server))
""))
(ibuffer-define-column erc-target (:name "Target")
(if (eq major-mode 'erc-mode)
(cond ((and (boundp 'erc-server-process) (processp erc-server-process)
(eq (current-buffer) (process-buffer erc-server-process)))
(concat "Server " erc-session-server ":"
(erc-port-to-string erc-session-port)))
((erc-channel-p (erc-default-target))
(concat (erc-default-target)))
((erc-default-target)
(concat "Query: " (erc-default-target)))
(t "(parted)"))
(buffer-name)))
(ibuffer-define-column erc-topic (:name "Topic")
(if (and (eq major-mode 'erc-mode)
erc-channel-topic)
(erc-controls-interpret erc-channel-topic)
""))
(ibuffer-define-column
erc-members (:name "Users")
(if (and (eq major-mode 'erc-mode)
(boundp 'erc-channel-users)
(hash-table-p erc-channel-users)
(> (hash-table-size erc-channel-users) 0))
(number-to-string (hash-table-size erc-channel-users))
""))
(ibuffer-define-column erc-away (:name "A")
(if (and (boundp 'erc-server-process)
(processp erc-server-process)
(with-current-buffer (process-buffer erc-server-process)
erc-away))
"A"
" "))
(ibuffer-define-column
erc-op (:name "O")
(if (and (eq major-mode 'erc-mode)
(erc-channel-user-op-p (erc-current-nick)))
"@"
" "))
(ibuffer-define-column erc-voice (:name "V")
(if (and (eq major-mode 'erc-mode)
(erc-channel-user-voice-p (erc-current-nick)))
"+"
" "))
(ibuffer-define-column erc-channel-modes (:name "Mode")
(if (and (eq major-mode 'erc-mode)
(or (> (length erc-channel-modes) 0)
erc-channel-user-limit))
(concat (apply 'concat
"(+" erc-channel-modes)
(if erc-channel-user-limit
(format "l %d" erc-channel-user-limit)
"")
")")
(if (not (eq major-mode 'erc-mode))
mode-name
"")))
(ibuffer-define-column erc-nick (:name "Nick")
(if (eq major-mode 'erc-mode)
(erc-current-nick)
""))
(defvar erc-ibuffer-formats '((mark erc-modified erc-away erc-op erc-voice " " (erc-nick 8 8) " " (erc-target 18 40) (erc-members 5 5 :center) (erc-channel-modes 6 16 :center) " " (erc-server-name 20 30) " " (erc-topic 10 -1))
(mark erc-modified erc-away erc-op erc-voice " " (erc-target 18 40) (erc-members 5 5 :center) (erc-channel-modes 9 20 :center) " " (erc-topic 10 -1))))
(setq ibuffer-formats (append ibuffer-formats erc-ibuffer-formats))
(defvar erc-ibuffer-limit-map nil
"Prefix keymap to use for ERC related limiting.")
(define-prefix-command 'erc-ibuffer-limit-map)
(define-key 'erc-ibuffer-limit-map (kbd "s") 'ibuffer-limit-by-erc-server)
(define-key ibuffer-mode-map (kbd "/ \C-e") 'erc-ibuffer-limit-map)
(provide 'erc-ibuffer)
;;; erc-ibuffer.el ends here
;;
;; Local Variables:
;; indent-tabs-mode: t
;; tab-width: 8
;; End:
;; arch-tag: fbad56a5-8595-45e0-a8c8-d8bb91e26944

87
lisp/erc/erc-identd.el Normal file
View file

@ -0,0 +1,87 @@
;;; erc-identd.el --- RFC1413 (identd authentication protocol) server
;; Copyright (C) 2003 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
;; Keywords: comm, processes
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; You can have a local identd server (running on port 8113; I use DNAT
;; to bind 113->8113) if you add this to .emacs.el:
;; (add-hook 'erc-connect-pre-hook 'erc-identd-start)
;; (add-hook 'erc-disconnected-hook 'erc-identd-stop)
;;; Code:
(defvar erc-identd-process nil)
(defun erc-identd-filter (proc string)
"This filter implements RFC1413 (identd authentication protocol)."
(let ((erc-identd-process proc))
(when (string-match "\\([0-9]+\\)\\s-*,\\s-*\\([0-9]+\\)" string)
(let ((port-on-server (match-string 1 string))
(port-on-client (match-string 2 string)))
(send-string erc-identd-process
(format "%s, %s : USERID : %s : %s\n"
port-on-server port-on-client
system-type (user-login-name)))
(process-send-eof erc-identd-process)))))
(defun erc-identd-start (&optional port)
"Start an identd server listening to port 8113.
Port 113 (auth) will need to be redirected to port 8113 on your
machine -- using iptables, or a program like redir which can be
run from inetd. The idea is to provide a simple identd server
when you need one, without having to install one globally on your
system."
(interactive (list (read-string "Serve identd requests on port: " "8113")))
(if (null port)
(setq port 8113)
(if (stringp port)
(setq port (string-to-number port))))
(if erc-identd-process
(delete-process erc-identd-process))
(if (fboundp 'make-network-process)
(setq erc-identd-process
(make-network-process :name "identd"
:buffer (generate-new-buffer "identd")
:service port :server t :noquery t
:filter 'erc-identd-filter))
(open-network-stream-server "identd" (generate-new-buffer "identd")
port nil 'erc-identd-filter)))
(defun erc-identd-stop (&rest ignore)
(interactive)
(when erc-identd-process
(delete-process erc-identd-process)
(setq erc-identd-process nil)))
(provide 'erc-identd)
;;; erc-identd.el ends here
;;
;; Local Variables:
;; indent-tabs-mode: t
;; tab-width: 8
;; End:
;; arch-tag: e0b5f926-0f35-40b9-8ddb-ca06b62a7544

143
lisp/erc/erc-imenu.el Normal file
View file

@ -0,0 +1,143 @@
;;; erc-imenu.el -- Imenu support for ERC
;; Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@delysid.org>
;; Keywords: comm
;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcImenu
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; This file contains code related to Ibuffer and ERC. Totally alpha,
;; needs work. Usage: Type / C-e C-h when in Ibuffer-mode to see new
;; limiting commands
;;; Code:
;; Author: Mario Lang <mlang@delysid.org>
;; This file is not part of GNU Emacs. But the same license applies.
;;; Commentary:
;; This package defines the function `erc-create-imenu-index'. ERC
;; uses this for `imenu-create-index-function', and autoloads it.
;; Therefore, nothing needs to be done to use this package.
;;; Code:
(require 'erc)
(require 'imenu)
(defun erc-unfill-notice ()
"Return text from point to a computed end as a string unfilled.
Don't rely on this function, read it first!"
(let ((str (buffer-substring
(save-excursion
(re-search-forward (regexp-quote erc-notice-prefix)))
(progn
(while (save-excursion
(forward-line 1)
(looking-at " "))
(forward-line 1))
(end-of-line) (point)))))
(with-temp-buffer
(insert str)
(goto-char (point-min))
(while (re-search-forward "\n +" nil t)
(replace-match " "))
(buffer-substring (point-min) (point-max)))))
;;;###autoload
(defun erc-create-imenu-index ()
(let ((index-alist '())
(notice-alist '())
(join-alist '())
(left-alist '())
(quit-alist '())
(message-alist '())
(mode-change-alist '())
(topic-change-alist '())
prev-pos)
(goto-char (point-max))
(imenu-progress-message prev-pos 0)
(while (if (bolp)
(> (forward-line -1)
-1)
(progn (forward-line 0)
t))
(imenu-progress-message prev-pos nil t)
(save-match-data
(when (looking-at (concat (regexp-quote erc-notice-prefix)
"\\(.+\\)$"))
(let ((notice-text ;; Ugly hack, but seems to work.
(save-excursion (erc-unfill-notice)))
(pos (point)))
(push (cons notice-text pos) notice-alist)
(or
(when (string-match "^\\(.*\\) has joined channel" notice-text)
(push (cons (match-string 1 notice-text) pos) join-alist))
(when (string-match "^\\(.+\\) has left channel" notice-text)
(push (cons (match-string 1 notice-text) pos) left-alist))
(when (string-match "^\\(.+\\) has quit\\(.*\\)$" notice-text)
(push (cons (concat (match-string 1 notice-text)
(match-string 2 notice-text))
(point))
quit-alist))
(when (string-match
"^\\(\\S-+\\) (.+) has changed mode for \\S-+ to \\(.*\\)$"
notice-text)
(push (cons (concat (match-string 1 notice-text) ": "
(match-string 2 notice-text))
(point))
mode-change-alist))
(when (string-match
"^\\(\\S-+\\) (.+) has set the topic for \\S-+: \\(.*\\)$"
notice-text)
(push (cons (concat (match-string 1 notice-text) ": "
(match-string 2 notice-text)) pos)
topic-change-alist)))))
(when (looking-at "<\\(\\S-+\\)> \\(.+\\)$")
(let ((from (match-string 1))
(message-text (match-string 2)))
(push (cons (concat from ": " message-text) (point))
message-alist)))))
(and notice-alist (push (cons "notices" notice-alist) index-alist))
(and join-alist (push (cons "joined" join-alist) index-alist))
(and left-alist (push (cons "parted" left-alist) index-alist))
(and quit-alist (push (cons "quit" quit-alist) index-alist))
(and mode-change-alist (push (cons "mode-change" mode-change-alist)
index-alist))
(and message-alist (push (cons "messages" message-alist) index-alist))
(and topic-change-alist (push (cons "topic-change" topic-change-alist)
index-alist))
index-alist))
(provide 'erc-imenu)
;;; erc-imenu.el ends here
;;
;; Local Variables:
;; indent-tabs-mode: t
;; tab-width: 8
;; End:
;; arch-tag: 35c69082-ca29-43f7-a050-8da5f400de81

213
lisp/erc/erc-lang.el Normal file
View file

@ -0,0 +1,213 @@
;;; erc-lang.el --- provide the LANG command to ERC
;; Copyright (C) 2002, 2004 Free Software Foundation, Inc.
;; Author: Alex Schroeder <alex@gnu.org>
;; Maintainer: Alex Schroeder <alex@gnu.org>
;; Version: 1.0.0
;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcLang
;; Keywords: comm languages processes
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; This provides two commands: `language' is for everyday use, and
;; `erc-cmd-LANG' provides the /LANG command to ERC.
;;; Code:
(require 'erc)
(defvar iso-638-languages
'(("aa" . "Afar")
("ab" . "Abkhazian")
("af" . "Afrikaans")
("am" . "Amharic")
("ar" . "Arabic")
("as" . "Assamese")
("ay" . "Aymara")
("az" . "Azerbaijani")
("ba" . "Bashkir")
("be" . "Byelorussian")
("bg" . "Bulgarian")
("bh" . "Bihari")
("bi" . "Bislama")
("bn" . "Bengali; Bangla")
("bo" . "Tibetan")
("br" . "Breton")
("ca" . "Catalan")
("co" . "Corsican")
("cs" . "Czech")
("cy" . "Welsh")
("da" . "Danish")
("de" . "German")
("dz" . "Bhutani")
("el" . "Greek")
("en" . "English")
("eo" . "Esperanto")
("es" . "Spanish")
("et" . "Estonian")
("eu" . "Basque")
("fa" . "Persian")
("fi" . "Finnish")
("fj" . "Fiji")
("fo" . "Faroese")
("fr" . "French")
("fy" . "Frisian")
("ga" . "Irish")
("gd" . "Scots Gaelic")
("gl" . "Galician")
("gn" . "Guarani")
("gu" . "Gujarati")
("ha" . "Hausa")
("he" . "Hebrew (formerly iw)")
("hi" . "Hindi")
("hr" . "Croatian")
("hu" . "Hungarian")
("hy" . "Armenian")
("ia" . "Interlingua")
("id" . "Indonesian (formerly in)")
("ie" . "Interlingue")
("ik" . "Inupiak")
("is" . "Icelandic")
("it" . "Italian")
("iu" . "Inuktitut")
("ja" . "Japanese")
("jw" . "Javanese")
("ka" . "Georgian")
("kk" . "Kazakh")
("kl" . "Greenlandic")
("km" . "Cambodian")
("kn" . "Kannada")
("ko" . "Korean")
("ks" . "Kashmiri")
("ku" . "Kurdish")
("ky" . "Kirghiz")
("la" . "Latin")
("ln" . "Lingala")
("lo" . "Laothian")
("lt" . "Lithuanian")
("lv" . "Latvian, Lettish")
("mg" . "Malagasy")
("mi" . "Maori")
("mk" . "Macedonian")
("ml" . "Malayalam")
("mn" . "Mongolian")
("mo" . "Moldavian")
("mr" . "Marathi")
("ms" . "Malay")
("mt" . "Maltese")
("my" . "Burmese")
("na" . "Nauru")
("ne" . "Nepali")
("nl" . "Dutch")
("no" . "Norwegian")
("oc" . "Occitan")
("om" . "(Afan) Oromo")
("or" . "Oriya")
("pa" . "Punjabi")
("pl" . "Polish")
("ps" . "Pashto, Pushto")
("pt" . "Portuguese")
("qu" . "Quechua")
("rm" . "Rhaeto-Romance")
("rn" . "Kirundi")
("ro" . "Romanian")
("ru" . "Russian")
("rw" . "Kinyarwanda")
("sa" . "Sanskrit")
("sd" . "Sindhi")
("sg" . "Sangho")
("sh" . "Serbo-Croatian")
("si" . "Sinhalese")
("sk" . "Slovak")
("sl" . "Slovenian")
("sm" . "Samoan")
("sn" . "Shona")
("so" . "Somali")
("sq" . "Albanian")
("sr" . "Serbian")
("ss" . "Siswati")
("st" . "Sesotho")
("su" . "Sundanese")
("sv" . "Swedish")
("sw" . "Swahili")
("ta" . "Tamil")
("te" . "Telugu")
("tg" . "Tajik")
("th" . "Thai")
("ti" . "Tigrinya")
("tk" . "Turkmen")
("tl" . "Tagalog")
("tn" . "Setswana")
("to" . "Tonga")
("tr" . "Turkish")
("ts" . "Tsonga")
("tt" . "Tatar")
("tw" . "Twi")
("ug" . "Uighur")
("uk" . "Ukrainian")
("ur" . "Urdu")
("uz" . "Uzbek")
("vi" . "Vietnamese")
("vo" . "Volapuk")
("wo" . "Wolof")
("xh" . "Xhosa")
("yi" . "Yiddish (formerly ji)")
("yo" . "Yoruba")
("za" . "Zhuang")
("zh" . "Chinese")
("zu" . "Zulu"))
"Alist of ISO language codes and language names.
This is based on the technical contents of ISO 639:1988 (E/F)
\"Code for the representation of names of languages\".
Typed by Keld.Simonsen@dkuug.dk 1990-11-30
<ftp://dkuug.dk/i18n/ISO_639>
Minor corrections, 1992-09-08 by Keld Simonsen
Sundanese corrected, 1992-11-11 by Keld Simonsen
Telugu corrected, 1995-08-24 by Keld Simonsen
Hebrew, Indonesian, Yiddish corrected 1995-10-10 by Michael Everson
Inuktitut, Uighur, Zhuang added 1995-10-10 by Michael Everson
Sinhalese corrected, 1995-10-10 by Michael Everson
Faeroese corrected to Faroese, 1995-11-18 by Keld Simonsen
Sangro corrected to Sangho, 1996-07-28 by Keld Simonsen
Two-letter lower-case symbols are used.
The Registration Authority for ISO 639 is Infoterm, Osterreichisches
Normungsinstitut (ON), Postfach 130, A-1021 Vienna, Austria.")
(defun language (code)
"Return the language name for the ISO CODE."
(interactive (list (completing-read "ISO language code: "
iso-638-languages)))
(message (cdr (assoc code iso-638-languages))))
(defun erc-cmd-LANG (language)
"Display the language name for the language code given by LANGUAGE."
(let ((lang (cdr (assoc language iso-638-languages))))
(erc-display-message
nil 'notice 'active
(or lang (concat line ": No such domain"))))
t)
(provide 'erc-lang)
;; arch-tag: 8ffb1563-cc03-4517-b067-16309d4ff97b
;;; erc-lang.el ends here

396
lisp/erc/erc-list.el Normal file
View file

@ -0,0 +1,396 @@
;;; erc-list.el --- Provide a faster channel listing mechanism
;; Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
;; Copyright (C) 2004 Brian Palmer
;; Author: Mario Lang <mlang@lexx.delysid.org>
;; Keywords: comm
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; This file provides a simple derived mode for viewing Channel lists.
;; It also serves as a demonstration of how the new server hook facility
;; can be used.
;;; Code:
(require 'erc)
(require 'erc-nets)
(require 'sort)
(unless (fboundp 'make-overlay)
(require 'overlay))
(eval-when-compile (require 'cl))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; User customizable variables.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defgroup erc-list nil
"Display IRC channels in another window when using /LIST"
:group 'erc)
(defcustom erc-chanlist-progress-message t
"*Show progress message while accumulating channel list."
:group 'erc-list
:type 'boolean)
(defcustom erc-no-list-networks nil
"*A list of network names on which the /LIST command refuses to work."
:group 'erc-list
:type '(repeat string))
(defcustom erc-chanlist-frame-parameters nil
"*If nil, the channel list is displayed in a new window; if non-nil,
this variable holds the frame parameters used to make a frame to
display the channel list."
:group 'erc-list
:type 'list)
(defcustom erc-chanlist-hide-modeline nil
"*If nil, the channel list buffer has a modeline, otherwise the modeline is hidden."
:group 'erc-list
:type 'boolean)
(defface erc-chanlist-header-face '((t (:bold t)))
"Face used for the headers in erc's channel list."
:group 'erc-faces)
(defface erc-chanlist-odd-line-face '((t (:inverse-video t)))
"Face used for the odd lines in erc's channel list."
:group 'erc-faces)
(defface erc-chanlist-even-line-face '((t (:inverse-video nil)))
"Face used for the even lines in erc's channel list."
:group 'erc-faces)
(defface erc-chanlist-highlight '((t (:foreground "red")))
"Face used to highlight the current line in the channel list."
:group 'erc-faces)
;; This should perhaps be a defface that inherits values from the highlight face
;; but xemacs does not support inheritance
(defcustom erc-chanlist-highlight-face 'erc-chanlist-highlight
"Face used for highlighting the current line in a list."
:type 'face
:group 'erc-faces)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; All variables below this line are for internal use only.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar erc-chanlist-channel-line-regexp "^\\([#&\\*][^ \t\n]*\\)\\s-+[0-9]+"
"Regexp that matches a channel line in the channel list buffer.")
(defvar erc-chanlist-buffer nil)
(make-variable-buffer-local 'erc-chanlist-buffer)
(defvar erc-chanlist-last-time 0
"A time value used to throttle the progress indicator.")
(defvar erc-chanlist-frame nil
"The frame displaying the most recent channel list buffer.")
(defvar erc-chanlist-sort-state 'channel
"The sort mode of the channel list buffer. Either 'channel or 'users.")
(make-variable-buffer-local 'erc-chanlist-sort-state)
(defvar erc-chanlist-highlight-overlay nil
"The overlay used for erc chanlist highlighting")
(make-variable-buffer-local 'erc-chanlist-highlight-overlay)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Define erc-chanlist-mode.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defcustom erc-chanlist-mode-hook nil
"Hook run by erc-chanlist-mode."
:group 'erc-list
:type 'hook)
(define-derived-mode erc-chanlist-mode fundamental-mode "ERC Channel List"
"Mode for viewing a channel list of a particular server.
\\{erc-chanlist-mode-map}"
(local-set-key "\C-c\C-j" 'erc-join-channel)
(local-set-key "j" 'erc-chanlist-join-channel)
(local-set-key "n" 'next-line)
(local-set-key "p" 'previous-line)
(local-set-key "q" 'erc-chanlist-quit)
(local-set-key "s" 'erc-chanlist-toggle-sort-state)
(local-set-key "t" 'toggle-truncate-lines)
(setq erc-chanlist-sort-state 'channel)
(setq truncate-lines t)
(add-hook 'post-command-hook 'erc-chanlist-post-command-hook 'append 'local))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Functions.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;###autoload
(defun erc-cmd-LIST (&rest channel)
"Display a buffer containing a list of channels on the current server.
Optional argument CHANNEL specifies a single channel to list (instead of every
available channel)."
(interactive
(remove "" (split-string
(read-from-minibuffer "List channels (RET for all): ") " ")))
(if (and (null channel)
(erc-member-ignore-case (erc-network-name) erc-no-list-networks))
(erc-display-line "ERC is configured not to allow the /LIST command on this network!"
(current-buffer))
(erc-display-line (erc-make-notice (concat "Listing channel"
(if channel
"."
"s. This may take a while."))))
(erc-chanlist channel))
t)
;;;###autoload
(defun erc-chanlist (&optional channels)
"Show a channel listing of the current server in a special mode.
Please note that this function only works with IRC servers which conform
to RFC and send the LIST header (#321) at start of list transmission."
(interactive)
(with-current-buffer (erc-server-buffer)
(erc-once-with-server-event
321
'(progn
(add-hook 'erc-server-322-functions 'erc-chanlist-322 nil t)
(erc-once-with-server-event
323
'(progn
(remove-hook 'erc-server-322-functions 'erc-chanlist-322 t)
(let ((buf erc-chanlist-buffer))
(if (not (buffer-live-p buf))
(error "`erc-chanlist-buffer' does not refer to a live buffer"))
(set-buffer buf)
(buffer-disable-undo)
(let (buffer-read-only
(sort-fold-case t))
(sort-lines nil (point-min) (point-max))
(setq erc-chanlist-sort-state 'channel)
(let ((sum (count-lines (point-min) (point-max))))
(goto-char (point-min))
(insert (substitute-command-keys
(concat "'\\[erc-chanlist-toggle-sort-state]' toggle sort mode.\n"
"'\\[erc-chanlist-quit]' kill this buffer.\n"
"'\\[toggle-truncate-lines]' toggle line truncation.\n"
"'\\[erc-chanlist-join-channel]' join the channel listed on the current line.\n\n")))
(insert (format "%d channels (sorted by %s).\n\n"
sum (if (eq erc-chanlist-sort-state 'channel)
"channel name"
"number of users"))))
(insert (format "%-25s%5s %s\n------------------------ ----- ----------------------------\n"
"Channel"
"Users"
"Topic"))
;; Display the channel list buffer.
(if erc-chanlist-frame-parameters
(progn
(if (or (null erc-chanlist-frame)
(not (frame-live-p erc-chanlist-frame)))
(setq erc-chanlist-frame
(make-frame `((name . ,(format "Channels on %s"
erc-session-server))
,@erc-chanlist-frame-parameters))))
(select-frame erc-chanlist-frame)
(switch-to-buffer buf)
(erc-prettify-channel-list))
(pop-to-buffer buf)
(erc-prettify-channel-list))))
(goto-char (point-min))
(search-forward-regexp "^------" nil t)
(forward-line 1)
(erc-chanlist-highlight-line)
(message "")
t))
(setq erc-chanlist-buffer (get-buffer-create
(format "*Channels on %s*"
(erc-response.sender parsed))))
(with-current-buffer erc-chanlist-buffer
(setq buffer-read-only nil)
(erase-buffer)
(erc-chanlist-mode)
(setq erc-server-process proc)
(if erc-chanlist-hide-modeline
(setq mode-line-format nil))
(setq buffer-read-only t))
t))
;; Now that we've setup our callbacks, pull the trigger.
(if (interactive-p)
(message "Collecting channel list for server %s" erc-session-server))
(erc-server-send (if (null channels)
"LIST"
(concat "LIST "
(mapconcat #'identity channels ","))))))
(defun erc-chanlist-322 (proc parsed)
"Process an IRC 322 message.
The message carries information about one channel for the LIST
command."
(multiple-value-bind (channel num-users)
(cdr (erc-response.command-args parsed))
(let ((topic (erc-response.contents parsed)))
(with-current-buffer erc-chanlist-buffer
(save-excursion
(goto-char (point-max))
(let (buffer-read-only)
(insert (format "%-26s%4s %s\n" (erc-controls-strip channel)
num-users
(erc-controls-strip topic))))
;; Maybe display a progress indicator in the minibuffer.
(when (and erc-chanlist-progress-message
(> (erc-time-diff
erc-chanlist-last-time (erc-current-time))
3))
(setq erc-chanlist-last-time (erc-current-time))
(message "Accumulating channel list ... %c"
(aref [?/ ?| ?\\ ?- ?! ?O ?o] (random 7))))
;; Return success to prevent other hook functions from being run.
t)))))
(defun erc-chanlist-post-command-hook ()
"Keep the current line highlighted."
(ignore-errors
(save-excursion
(beginning-of-line)
(if (looking-at erc-chanlist-channel-line-regexp)
(erc-chanlist-highlight-line)
(erc-chanlist-dehighlight-line)))))
(defun erc-chanlist-highlight-line ()
"Highlight the current line."
(unless erc-chanlist-highlight-overlay
(setq erc-chanlist-highlight-overlay
(make-overlay (point-min) (point-min)))
;; Detach it from the buffer.
(delete-overlay erc-chanlist-highlight-overlay)
(overlay-put erc-chanlist-highlight-overlay
'face erc-chanlist-highlight-face)
;; Expressly put it at a higher priority than the text
;; properties used for faces later on. Gnu emacs promises that
;; right now overlays are higher priority than text properties,
;; but why take chances?
(overlay-put erc-chanlist-highlight-overlay 'priority 1))
(move-overlay erc-chanlist-highlight-overlay (point) (1+ (point-at-eol))))
(defun erc-chanlist-dehighlight-line ()
"Remove the line highlighting."
(delete-overlay erc-chanlist-highlight-overlay))
(defun erc-prettify-channel-list ()
"Make the channel list buffer look pretty.
When this function runs, the current buffer must be the channel
list buffer, or it does nothing."
(if (eq major-mode 'erc-chanlist-mode)
(save-excursion
(let ((inhibit-read-only t))
(goto-char (point-min))
(when (search-forward-regexp "^-------" nil t)
(add-text-properties
(point-min) (1+ (point-at-eol)) '(face erc-chanlist-header-face))
(forward-line 1))
(while (not (eobp))
(add-text-properties
(point) (1+ (point-at-eol)) '(face erc-chanlist-odd-line-face))
(forward-line 1)
(unless (eobp)
(add-text-properties
(point) (1+ (point-at-eol)) '(face erc-chanlist-even-line-face)))
(forward-line 1))))))
(defun erc-chanlist-toggle-sort-state ()
"Toggle the channel list buffer sorting method.
Either sort by channel names or by number of users in each channel."
(interactive)
(let ((inhibit-read-only t)
(sort-fold-case t))
(save-excursion
(goto-char (point-min))
(search-forward-regexp "^-----" nil t)
(forward-line 1)
(unless (eobp)
(if (eq erc-chanlist-sort-state 'channel)
(progn
(sort-numeric-fields 2 (point) (point-max))
(reverse-region (point) (point-max))
(setq erc-chanlist-sort-state 'users))
(sort-lines nil (point) (point-max))
(setq erc-chanlist-sort-state 'channel))
(goto-char (point-min))
(if (search-forward-regexp "^[0-9]+ channels (sorted by \\(.*\\)).$"
nil t)
(replace-match (if (eq erc-chanlist-sort-state 'channel)
"channel name"
"number of users")
nil nil nil 1))
(goto-char (point-min))
(search-forward-regexp "^-----" nil t)
(forward-line 1)
(recenter -1)
(erc-prettify-channel-list)))))
(defun erc-chanlist-quit ()
"Quit Chanlist mode.
Kill the channel list buffer, window, and frame (if there's a frame
devoted to the channel list)."
(interactive)
(kill-buffer (current-buffer))
(if (eq (selected-frame) erc-chanlist-frame)
(delete-frame)
(delete-window)))
(defun erc-chanlist-join-channel ()
"Join the channel listed on the current line of the channel list buffer.
Private channels, which are shown as asterisks (*), are ignored."
(interactive)
(save-excursion
(beginning-of-line)
(when (looking-at erc-chanlist-channel-line-regexp)
(let ((channel-name (match-string 1)))
(when (and (stringp channel-name)
(not (string= channel-name "*")))
(run-at-time 0.5 nil 'erc-join-channel channel-name))))))
(provide 'erc-list)
;;; erc-list.el ends here
;;
;; Local Variables:
;; indent-tabs-mode: t
;; tab-width: 8
;; End:
;; arch-tag: 4a13196a-a61b-465a-9926-044dfbc7e5ff

358
lisp/erc/erc-log.el Normal file
View file

@ -0,0 +1,358 @@
;;; erc-log.el --- Logging facilities for ERC.
;; Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
;; Author: Lawrence Mitchell <wence@gmx.li>
;; Keywords: IRC, chat, client, Internet, logging
;; Created 2003-04-26
;; Logging code taken from erc.el and modified to use markers.
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; This file implements log file writing support for ERC.
;; Quick start:
;;
;; (setq erc-enable-logging t)
;; (setq erc-log-channels-directory "/path/to/logfiles") ; must be writable
;;
;; 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".
;;
;; The second method will save buffers on /part, /quit, or killing the
;; channel buffer. To do this, add the following to your .emacs:
;;
;; (require 'erc-log)
;;
;; You may optionally want the following code, to save all ERC buffers
;; without confirmation when exiting emacs:
;;
;; (defadvice save-buffers-kill-emacs (before save-logs (&rest args) activate)
;; (save-some-buffers t (lambda ()
;; (when (and (eq major-mode 'erc-mode)
;; (not (null buffer-file-name))) t))))
;;
;; If you only want to save logs for some buffers, customise the
;; variable `erc-enable-logging'.
;; How it works:
;;
;; If logging is enabled, at some point, `erc-save-buffer-in-logs'
;; will be called. The "end" of the buffer is taken from
;; `erc-insert-marker', while `erc-last-saved-position' holds the
;; position the buffer was last saved at (as a marker, or if the
;; buffer hasn't been saved before, as the number 1 (point-min)).
;; The region between `erc-last-saved-position' and
;; `erc-insert-marker' is saved to the current buffer's logfile, and
;; `erc-last-saved-position' is updated to reflect this.
;;; History:
;; 2003-04-26: logging code pulled out of erc.el. Switched to using
;; markers.
;;; TODO:
;; * Erc needs a generalised make-safe-file-name function, so that
;; generated file names don't contain any invalid file characters.
;;
;; * Really, we need to lock the logfiles somehow, so that if a user
;; is running multiple emacsen and/or on the same channel as more
;; than one user, only one process writes to the logfile. This is
;; especially needed for those logfiles with no nick in them, as
;; these would become corrupted.
;; For a single emacs process, the problem could be solved using a
;; variable which contained the names of buffers already being
;; logged. This would require that logging be buffer-local,
;; possibly not a bad thing anyway, since many people don't want to
;; log the server buffer.
;; For multiple emacsen the problem is trickier. On some systems,
;; on could use the function `lock-buffer' and `unlock-buffer'.
;; However, file locking isn't implemented on all platforms, for
;; example, there is none on w32 systems.
;; A third possibility might be to fake lockfiles. However, this
;; might lead to problems if an emacs crashes, as the lockfile
;; would be left lying around.
;;; Code:
(require 'erc)
(eval-when-compile (require 'cl))
(defgroup erc-log nil
"Logging facilities for ERC."
:group 'erc)
(defcustom erc-generate-log-file-name-function 'erc-generate-log-file-name-long
"*A function to generate a log filename.
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'."
:group 'erc-log
:type '(choice (const erc-generate-log-file-name-long)
(const erc-generate-log-file-name-short)
(const erc-generate-log-file-name-with-date)
(symbol)))
(defcustom erc-save-buffer-on-part nil
"*Save the channel buffer content using `erc-save-buffer-in-logs' on PART."
:group 'erc-log
:type 'boolean)
(defcustom erc-truncate-buffer-on-save nil
"Truncate any ERC (channel, query, server) buffer when it is saved."
:group 'erc-log
:type 'boolean)
(defcustom erc-enable-logging t
"If non-nil, ERC will log IRC conversations.
This can either be a boolean value of nil or t, or a function.
If the value is a function, it will be called with one argument, the
name of the current ERC buffer. One possible function, which saves
all but server buffers is `erc-log-all-but-server-buffers'.
This variable is buffer local. Setting it via \\[customize] sets the
default value.
Log files are stored in `erc-log-channels-directory'."
:group 'erc-log
:type '(choice boolean
function))
(make-variable-buffer-local 'erc-enable-logging)
(defcustom erc-log-channels-directory "~/log"
"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."
:group 'erc-log
:type '(choice directory
(const nil)))
(defcustom erc-log-insert-log-on-open t
"*Insert log file contents into the buffer if a log file exists."
:group 'erc-log
:type 'boolean)
(defcustom erc-save-queries-on-quit nil
"Save all query (also channel) buffers of the server on QUIT.
See the variable `erc-save-buffer-on-part' for details."
:group 'erc-log
:type 'boolean)
(defcustom erc-log-file-coding-system (if (featurep 'xemacs)
'binary
'emacs-mule)
"*The coding system ERC should use for writing log files.
This should ideally, be a \"catch-all\" coding system, like
`emacs-mule', or `iso-2022-7bit'."
:group 'erc-log)
;;;###autoload (autoload 'erc-log-mode "erc-log" nil t)
(define-erc-module log nil
"Automatically logs things you receive on IRC into files.
Files are stored in `erc-log-channels-directory'; file name
format is defined through a formatting function on
`erc-generate-log-file-name-function'.
Since automatic logging is not always a Good Thing (especially if
people say things in different coding systems), you can turn logging
behaviour on and off with the variable `erc-enable-logging', which can
also be a predicate function. To only log when you are not set away, use:
\(setq erc-enable-logging
(lambda (buffer)
(with-current-buffer buffer
(not erc-away))))"
;; enable
((add-hook 'erc-insert-post-hook
'erc-save-buffer-in-logs)
(add-hook 'erc-send-post-hook
'erc-save-buffer-in-logs))
;; disable
((remove-hook 'erc-insert-post-hook
'erc-save-buffer-in-logs)
(remove-hook 'erc-send-post-hook
'erc-save-buffer-in-logs)))
(when erc-enable-logging
(add-hook 'erc-kill-buffer-hook
'erc-save-buffer-in-logs)
(add-hook 'erc-kill-channel-hook
'erc-save-buffer-in-logs)
(add-hook 'erc-quit-hook
'erc-conditional-save-queries)
(add-hook 'erc-part-hook
'erc-conditional-save-buffer))
(define-key erc-mode-map "\C-c\C-l" 'erc-save-buffer-in-logs)
;;;functionality referenced from erc.el
(defun erc-log-setup-logging ()
"Setup the buffer-local logging variables in the current buffer.
This function is destined to be run from `erc-connect-pre-hook'."
(when (erc-logging-enabled)
(auto-save-mode -1)
(setq buffer-offer-save t
buffer-file-name "")
(set (make-local-variable 'write-file-functions)
'(erc-save-buffer-in-logs))
(when erc-log-insert-log-on-open
(ignore-errors (insert-file-contents (erc-current-logfile))
(move-marker erc-last-saved-position
(1- (point-max)))))))
;;; Append, so that 'erc-initialize-log-marker keeps running first.
(add-hook 'erc-connect-pre-hook 'erc-log-setup-logging 'append)
(defun erc-log-all-but-server-buffers (buffer)
"Returns t if logging should be enabled in BUFFER.
Returns nil iff `erc-server-buffer-p' returns t."
(save-excursion
(save-window-excursion
(set-buffer buffer)
(not (erc-server-buffer-p)))))
(defun erc-save-query-buffers (process)
"Save all buffers process."
(erc-with-all-buffers-of-server process
nil
(erc-save-buffer-in-logs)))
(defun erc-conditional-save-buffer (buffer)
"Save Query BUFFER if `erc-save-queries-on-quit' is t."
(when erc-save-buffer-on-part
(erc-save-buffer-in-logs buffer)))
(defun erc-conditional-save-queries (process)
"Save Query buffers of PROCESS if `erc-save-queries-on-quit' is t."
(when erc-save-queries-on-quit
(erc-save-query-buffers process)))
;;;###autoload
(defun erc-logging-enabled (&optional buffer)
"Return non-nil if logging is enabled for BUFFER.
If BUFFER is nil, the value of `current-buffer' is used.
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)
(if (functionp erc-enable-logging)
(funcall erc-enable-logging (or buffer (current-buffer)))
erc-enable-logging)))
(defun erc-current-logfile (&optional buffer)
"Return the logfile to use for BUFFER.
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
(downcase (funcall erc-generate-log-file-name-function
(or buffer (current-buffer))
(or (erc-default-target) (buffer-name buffer))
(erc-current-nick)
erc-session-server erc-session-port))
erc-log-channels-directory))
(defun erc-generate-log-file-name-with-date (buffer &rest ignore)
"This function computes a short log file name.
The name of the log file is composed of BUFFER and the current date.
This function is a possible value for `erc-generate-log-file-name-function'."
(concat (buffer-name buffer) "-" (format-time-string "%Y-%m-%d") ".txt"))
(defun erc-generate-log-file-name-short (buffer &rest ignore)
"This function computes a short log file name.
In fact, it only uses the buffer name of the BUFFER argument, so
you can affect that using `rename-buffer' and the-like. This
function is a possible value for
`erc-generate-log-file-name-function'."
(concat (buffer-name buffer) ".txt"))
(defun erc-generate-log-file-name-long (buffer target nick server port)
"Generates a log-file name in the way ERC always did it.
This results in a file name of the form #channel!nick@server:port.txt.
This function is a possible value for `erc-generate-log-file-name-function'."
(let ((file (concat
(if target (concat target "!"))
nick "@" server ":" (cond ((stringp port) port)
((numberp port)
(number-to-string port))) ".txt")))
;; we need a make-safe-file-name function.
(convert-standard-filename file)))
;;;###autoload
(defun erc-save-buffer-in-logs (&optional buffer)
"Append BUFFER contents to the log file, if logging is enabled.
If BUFFER is not provided, current buffer is used.
Logging is enabled if `erc-logging-enabled' returns non-nil.
This is normally done on exit, to save the unsaved portion of the
buffer, since only the text that runs off the buffer limit is logged
automatically.
You can save every individual message by putting this function on
`erc-insert-post-hook'."
(interactive)
(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))
(save-excursion
(with-current-buffer buffer
(save-restriction
(widen)
;; early on in the initalisation, 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)
(if (and erc-truncate-buffer-on-save (interactive-p))
(progn
(let ((inhibit-read-only t)) (erase-buffer))
(move-marker erc-last-saved-position (point-max))
(erc-display-prompt))
(move-marker erc-last-saved-position
;; If we place erc-last-saved-position at
;; erc-insert-marker, because text gets
;; inserted /before/ erc-insert-marker,
;; the log file will not be saved
;; (erc-last-saved-position will always
;; be equal to erc-insert-marker).
(1- (marker-position erc-insert-marker)))))
(set-buffer-modified-p nil))))))
t)
(provide 'erc-log)
;;; erc-log.el ends here
;;
;; Local Variables:
;; indent-tabs-mode: t
;; tab-width: 8
;; End:
;; arch-tag: 54072f99-9f0a-4846-8908-2ccde92221de

658
lisp/erc/erc-match.el Normal file
View file

@ -0,0 +1,658 @@
;;; erc-match.el --- Highlight messages matching certain regexps
;; Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
;; Author: Andreas Fuchs <asf@void.at>
;; Keywords: comm, faces
;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcMatch
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; This file includes stuff to work with pattern matching in ERC. If
;; you were used to customizing erc-fools, erc-keywords, erc-pals,
;; erc-dangerous-hosts and the like, this file contains these
;; customizable variables.
;; Usage:
;; Put (erc-match-mode 1) into your ~/.emacs file.
;;; Code:
(require 'erc)
(eval-when-compile (require 'cl))
;; Customisation:
(defgroup erc-match nil
"Keyword and Friend/Foe/... recognition.
Group containing all things concerning pattern matching in ERC
messages."
:group 'erc)
;;;###autoload (autoload 'erc-match-mode "erc-match")
(define-erc-module match nil
"This mode checks whether messages match certain patterns. If so,
they are hidden or highlighted. This is controlled via the variables
`erc-pals', `erc-fools', `erc-keywords', `erc-dangerous-hosts', and
`erc-current-nick-highlight-type'. For all these highlighting types,
you can decide whether the entire message or only the sending nick is
highlighted."
((add-hook 'erc-insert-modify-hook 'erc-match-message 'append))
((remove-hook 'erc-insert-modify-hook 'erc-match-message)))
;; Remaining customizations
(defcustom erc-pals nil
"List of pals on IRC."
:group 'erc-match
:type '(repeat regexp))
(defcustom erc-fools nil
"List of fools on IRC."
:group 'erc-match
:type '(repeat regexp))
(defcustom erc-keywords nil
"List of keywords to highlight in all incoming messages.
Each entry in the list is either a regexp, or a cons cell with the
regexp in the car and the face to use in the cdr. If no face is
specified, `erc-keyword-face' is used."
:group 'erc-match
:type '(repeat (choice regexp
(list regexp face))))
(defcustom erc-dangerous-hosts nil
"List of regexps for hosts to highlight.
Useful to mark nicks from dangerous hosts."
:group 'erc-match
:type '(repeat regexp))
(defcustom erc-current-nick-highlight-type 'keyword
"*Determines how to highlight text in which your current nickname appears
\(does not apply to text sent by you\).
The following values are allowed:
nil - do not highlight the message at all
'keyword - highlight all instances of current nickname in message
'nick - highlight the nick of the user who typed your nickname
'nick-or-keyword - highlight the nick of the user who typed your nickname,
or all instances of the current nickname if there was
no sending user
'all - highlight the entire message where current nickname occurs
Any other value disables highlighting of current nickname altogether."
:group 'erc-match
:type '(choice (const nil)
(const nick)
(const keyword)
(const nick-or-keyword)
(const all)))
(defcustom erc-pal-highlight-type 'nick
"*Determines how to highlight messages by pals.
See `erc-pals'.
The following values are allowed:
nil - do not highlight the message at all
'nick - highlight pal's nickname only
'all - highlight the entire message from pal
Any other value disables pal highlighting altogether."
:group 'erc-match
:type '(choice (const nil)
(const nick)
(const all)))
(defcustom erc-fool-highlight-type 'nick
"*Determines how to highlight messages by fools.
See `erc-fools'.
The following values are allowed:
nil - do not highlight the message at all
'nick - highlight fool's nickname only
'all - highlight the entire message from fool
Any other value disables fool highlighting altogether."
:group 'erc-match
:type '(choice (const nil)
(const nick)
(const all)))
(defcustom erc-keyword-highlight-type 'keyword
"*Determines how to highlight messages containing keywords.
See variable `erc-keywords'.
The following values are allowed:
'keyword - highlight keyword only
'all - highlight the entire message containing keyword
Any other value disables keyword highlighting altogether."
:group 'erc-match
:type '(choice (const nil)
(const keyword)
(const all)))
(defcustom erc-dangerous-host-highlight-type 'nick
"*Determines how to highlight messages by nicks from dangerous-hosts.
See `erc-dangerous-hosts'.
The following values are allowed:
'nick - highlight nick from dangerous-host only
'all - highlight the entire message from dangerous-host
Any other value disables dangerous-host highlighting altogether."
:group 'erc-match
:type '(choice (const nil)
(const nick)
(const all)))
(defcustom erc-log-matches-types-alist '((keyword . "ERC Keywords"))
"Alist telling ERC where to log which match types.
Valid match type keys are:
- keyword
- pal
- dangerous-host
- fool
- current-nick
The other element of each cons pair in this list is the buffer name to
use for the logged message."
:group 'erc-match
:type '(repeat (cons (choice :tag "Key"
(const keyword)
(const pal)
(const dangerous-host)
(const fool)
(const current-nick))
(string :tag "Buffer name"))))
(defcustom erc-log-matches-flag 'away
"Flag specifying when matched message logging should happen.
When nil, don't log any matched messages.
When t, log messages.
When 'away, log messages only when away."
:group 'erc-match
:type '(choice (const nil)
(const away)
(const t)))
(defcustom erc-log-match-format "%t<%n:%c> %m"
"Format for matched Messages.
This variable specifies how messages in the corresponding log buffers will
be formatted. The various format specs are:
%t Timestamp (uses `erc-timestamp-format' if non-nil or \"[%Y-%m-%d %H:%M] \")
%n Nickname of sender
%u Nickname!user@host of sender
%c Channel in which this was received
%m Message"
:group 'erc-match
:type 'string)
(defcustom erc-beep-match-types '(current-nick)
"Types of matches to beep for when a match occurs.
The function `erc-beep-on-match' needs to be added to `erc-text-matched-hook'
for beeping to work."
:group 'erc-match
:type '(choice (repeat :tag "Beep on match" (choice
(const current-nick)
(const keyword)
(const pal)
(const dangerous-host)
(const fool)))
(const :tag "Don't beep" nil)))
(defcustom erc-text-matched-hook '(erc-log-matches)
"Hook run when text matches a given match-type.
Functions in this hook are passed as arguments:
\(match-type nick!user@host message) where MATCH-TYPE is a symbol of:
current-nick, keyword, pal, dangerous-host, fool"
:options '(erc-log-matches erc-hide-fools erc-beep-on-match)
:group 'erc-match
:type 'hook)
;; Internal variables:
;; This is exactly the same as erc-button-syntax-table. Should we
;; just put it in erc.el
(defvar erc-match-syntax-table
(let ((table (make-syntax-table)))
(modify-syntax-entry ?\( "w" table)
(modify-syntax-entry ?\) "w" table)
(modify-syntax-entry ?\[ "w" table)
(modify-syntax-entry ?\] "w" table)
(modify-syntax-entry ?\{ "w" table)
(modify-syntax-entry ?\} "w" table)
(modify-syntax-entry ?` "w" table)
(modify-syntax-entry ?' "w" table)
(modify-syntax-entry ?^ "w" table)
(modify-syntax-entry ?- "w" table)
(modify-syntax-entry ?_ "w" table)
(modify-syntax-entry ?| "w" table)
(modify-syntax-entry ?\\ "w" table)
table)
"Syntax table used when highlighting messages.
This syntax table should make all the legal nick characters word
constituents.")
;; Faces:
(defface erc-current-nick-face '((t (:bold t :foreground "DarkTurquoise")))
"ERC face for occurrences of your current nickname."
:group 'erc-faces)
(defface erc-dangerous-host-face '((t (:foreground "red")))
"ERC face for people on dangerous hosts.
See `erc-dangerous-hosts'."
:group 'erc-faces)
(defface erc-pal-face '((t (:bold t :foreground "Magenta")))
"ERC face for your pals.
See `erc-pals'."
:group 'erc-faces)
(defface erc-fool-face '((t (:foreground "dim gray")))
"ERC face for fools on the channel.
See `erc-fools'."
:group 'erc-faces)
(defface erc-keyword-face '((t (:bold t :foreground "pale green")))
"ERC face for your keywords.
Note that this is the default face to use if
`erc-keywords' does not specify another."
:group 'erc-faces)
;; Functions:
(defun erc-add-entry-to-list (list prompt &optional completions)
"Add an entry interactively to a list.
LIST must be passed as a symbol
The query happens using PROMPT.
Completion is performed on the optional alist COMPLETIONS."
(let ((entry (completing-read
prompt
completions
(lambda (x)
(not (erc-member-ignore-case (car x) (symbol-value list)))))))
(if (erc-member-ignore-case entry (symbol-value list))
(error (format "\"%s\" is already on the list" entry))
(set list (cons entry (symbol-value list))))))
(defun erc-remove-entry-from-list (list prompt)
"Remove an entry interactively from a list.
LIST must be passed as a symbol.
The elements of LIST can be strings, or cons cells where the
car is the string."
(let* ((alist (mapcar (lambda (x)
(if (listp x)
x
(list x)))
(symbol-value list)))
(entry (completing-read
prompt
alist
nil
t)))
(if (erc-member-ignore-case entry (symbol-value list))
;; plain string
(set list (delete entry (symbol-value list)))
;; cons cell
(set list (delete (assoc entry (symbol-value list))
(symbol-value list))))))
;;;###autoload
(defun erc-add-pal ()
"Add pal interactively to `erc-pals'."
(interactive)
(erc-add-entry-to-list 'erc-pals "Add pal: " (erc-get-server-nickname-alist)))
;;;###autoload
(defun erc-delete-pal ()
"Delete pal interactively to `erc-pals'."
(interactive)
(erc-remove-entry-from-list 'erc-pals "Delete pal: "))
;;;###autoload
(defun erc-add-fool ()
"Add fool interactively to `erc-fools'."
(interactive)
(erc-add-entry-to-list 'erc-fools "Add fool: "
(erc-get-server-nickname-alist)))
;;;###autoload
(defun erc-delete-fool ()
"Delete fool interactively to `erc-fools'."
(interactive)
(erc-remove-entry-from-list 'erc-fools "Delete fool: "))
;;;###autoload
(defun erc-add-keyword ()
"Add keyword interactively to `erc-keywords'."
(interactive)
(erc-add-entry-to-list 'erc-keywords "Add keyword: "))
;;;###autoload
(defun erc-delete-keyword ()
"Delete keyword interactively to `erc-keywords'."
(interactive)
(erc-remove-entry-from-list 'erc-keywords "Delete keyword: "))
;;;###autoload
(defun erc-add-dangerous-host ()
"Add dangerous-host interactively to `erc-dangerous-hosts'."
(interactive)
(erc-add-entry-to-list 'erc-dangerous-hosts "Add dangerous-host: "))
;;;###autoload
(defun erc-delete-dangerous-host ()
"Delete dangerous-host interactively to `erc-dangerous-hosts'."
(interactive)
(erc-remove-entry-from-list 'erc-dangerous-hosts "Delete dangerous-host: "))
(defun erc-match-current-nick-p (nickuserhost msg)
"Check whether the current nickname is in MSG.
NICKUSERHOST will be ignored."
(with-syntax-table erc-match-syntax-table
(and msg
(string-match (concat "\\b"
(regexp-quote (erc-current-nick))
"\\b")
msg))))
(defun erc-match-pal-p (nickuserhost msg)
"Check whether NICKUSERHOST is in `erc-pals'.
MSG will be ignored."
(and nickuserhost
(erc-list-match erc-pals nickuserhost)))
(defun erc-match-fool-p (nickuserhost msg)
"Check whether NICKUSERHOST is in `erc-fools' or MSG is directed at a fool."
(and msg nickuserhost
(or (erc-list-match erc-fools nickuserhost)
(erc-match-directed-at-fool-p msg))))
(defun erc-match-keyword-p (nickuserhost msg)
"Check whether any keyword of `erc-keywords' matches for MSG.
NICKUSERHOST will be ignored."
(and msg
(erc-list-match
(mapcar (lambda (x)
(if (listp x)
(car x)
x))
erc-keywords)
msg)))
(defun erc-match-dangerous-host-p (nickuserhost msg)
"Check whether NICKUSERHOST is in `erc-dangerous-hosts'.
MSG will be ignored."
(and nickuserhost
(erc-list-match erc-dangerous-hosts nickuserhost)))
(defun erc-match-directed-at-fool-p (msg)
"Check whether MSG is directed at a fool.
In order to do this, every entry in `erc-fools' will be used.
In any of the following situations, MSG is directed at an entry FOOL:
- MSG starts with \"FOOL: \" or \"FOO, \"
- MSG contains \", FOOL.\" (actually, \"\\s. FOOL\\s.\")"
(let ((fools-beg (mapcar (lambda (entry)
(concat "^" entry "[:,] "))
erc-fools))
(fools-end (mapcar (lambda (entry)
(concat "\\s. " entry "\\s."))
erc-fools)))
(or (erc-list-match fools-beg msg)
(erc-list-match fools-end msg))))
(defun erc-get-parsed-vector (point)
"Return the whole parsed vector on POINT."
(get-text-property point 'erc-parsed))
(defun erc-get-parsed-vector-nick (vect)
"Return nickname in the parsed vector VECT."
(let* ((untreated-nick (and vect (erc-response.sender vect)))
(maybe-nick (when untreated-nick
(car (split-string untreated-nick "!")))))
(when (and (not (null maybe-nick))
(erc-is-valid-nick-p maybe-nick))
untreated-nick)))
(defun erc-get-parsed-vector-type (vect)
"Return message type in the parsed vector VECT."
(and vect
(erc-response.command vect)))
(defun erc-match-message ()
"Mark certain keywords in a region.
Use this defun with `erc-insert-modify-hook'."
;; This needs some refactoring.
(goto-char (point-min))
(let* ((to-match-nick-dep '("pal" "fool" "dangerous-host"))
(to-match-nick-indep '("keyword" "current-nick"))
(vector (erc-get-parsed-vector (point-min)))
(nickuserhost (erc-get-parsed-vector-nick vector))
(nickname (and nickuserhost
(nth 0 (erc-parse-user nickuserhost))))
(old-pt (point))
(nick-beg (and nickname
(re-search-forward (regexp-quote nickname)
(point-max) t)
(match-beginning 0)))
(nick-end (when nick-beg
(match-end 0)))
(message (buffer-substring (if (and nick-end
(<= (+ 2 nick-end) (point-max)))
(+ 2 nick-end)
(point-min))
(point-max))))
(when vector
(mapc
(lambda (match-type)
(goto-char (point-min))
(let* ((match-prefix (concat "erc-" match-type))
(match-pred (intern (concat "erc-match-" match-type "-p")))
(match-htype (eval (intern (concat match-prefix
"-highlight-type"))))
(match-regex (if (string= match-type "current-nick")
(regexp-quote (erc-current-nick))
(eval (intern (concat match-prefix "s")))))
(match-face (intern (concat match-prefix "-face"))))
(when (funcall match-pred nickuserhost message)
(cond
;; Highlight the nick of the message
((and (eq match-htype 'nick)
nick-end)
(erc-put-text-property
nick-beg nick-end
'face match-face (current-buffer)))
;; Highlight the nick of the message, or the current
;; nick if there's no nick in the message (e.g. /NAMES
;; output)
((and (string= match-type "current-nick")
(eq match-htype 'nick-or-keyword))
(if nick-end
(erc-put-text-property
nick-beg nick-end
'face match-face (current-buffer))
(goto-char (+ 2 (or nick-end
(point-min))))
(while (re-search-forward match-regex nil t)
(erc-put-text-property (match-beginning 0) (match-end 0)
'face match-face))))
;; Highlight the whole message
((eq match-htype 'all)
(erc-put-text-property
(point-min) (point-max)
'face match-face (current-buffer)))
;; Highlight all occurrences of the word to be
;; highlighted.
((and (string= match-type "keyword")
(eq match-htype 'keyword))
(mapc (lambda (elt)
(let ((regex elt)
(face match-face))
(when (consp regex)
(setq regex (car elt)
face (cdr elt)))
(goto-char (+ 2 (or nick-end
(point-min))))
(while (re-search-forward regex nil t)
(erc-put-text-property
(match-beginning 0) (match-end 0)
'face face))))
match-regex))
;; Highlight all occurrences of our nick.
((and (string= match-type "current-nick")
(eq match-htype 'keyword))
(goto-char (+ 2 (or nick-end
(point-min))))
(while (re-search-forward match-regex nil t)
(erc-put-text-property (match-beginning 0) (match-end 0)
'face match-face)))
;; Else twiddle your thumbs.
(t nil))
(run-hook-with-args
'erc-text-matched-hook
(intern match-type)
(or nickuserhost
(concat "Server:" (erc-get-parsed-vector-type vector)))
message))))
(if nickuserhost
(append to-match-nick-dep to-match-nick-indep)
to-match-nick-indep)))))
(defun erc-log-matches (match-type nickuserhost message)
"Log matches in a separate buffer, determined by MATCH-TYPE.
The behaviour of this function is controlled by the variables
`erc-log-matches-types-alist' and `erc-log-matches-flag'. Specify the
match types which should be logged in the former, and
deactivate/activate match logging in the latter. See
`erc-log-match-format'."
(let ((match-buffer-name (cdr (assq match-type
erc-log-matches-types-alist)))
(nick (nth 0 (erc-parse-user nickuserhost))))
(when (and
(or (eq erc-log-matches-flag t)
(and (eq erc-log-matches-flag 'away)
erc-away))
match-buffer-name)
(let ((line (format-spec erc-log-match-format
(format-spec-make
?n nick
?t (format-time-string
(or (and (boundp 'erc-timestamp-format)
erc-timestamp-format)
"[%Y-%m-%d %H:%M] "))
?c (or (erc-default-target) "")
?m message
?u nickuserhost))))
(with-current-buffer (erc-log-matches-make-buffer match-buffer-name)
(toggle-read-only -1)
(point-max)
(insert line)
(toggle-read-only 1))))))
(defun erc-log-matches-make-buffer (name)
"Create or get a log-matches buffer named NAME and return it."
(let* ((buffer-already (get-buffer name))
(buffer (or buffer-already
(get-buffer-create name))))
(with-current-buffer buffer
(unless buffer-already
(insert " == Type \"q\" to dismiss messages ==\n")
(erc-view-mode-enter nil (lambda (buffer)
(when (y-or-n-p "Discard messages?")
(kill-buffer buffer)))))
buffer)))
(defun erc-log-matches-come-back (proc parsed)
"Display a notice that messages were logged while away."
(when (and erc-away
(eq erc-log-matches-flag 'away))
(mapc
(lambda (match-type)
(let ((buffer (get-buffer (cdr match-type)))
(buffer-name (cdr match-type)))
(when buffer
(let* ((last-msg-time (erc-emacs-time-to-erc-time
(with-current-buffer buffer
(get-text-property (1- (point-max))
'timestamp))))
(away-time (erc-emacs-time-to-erc-time erc-away)))
(when (and away-time last-msg-time
(erc-time-gt last-msg-time away-time))
(erc-display-message
nil 'notice 'active
(format "You have logged messages waiting in \"%s\"."
buffer-name))
(erc-display-message
nil 'notice 'active
(format "Type \"C-c C-k %s RET\" to view them."
buffer-name)))))))
erc-log-matches-types-alist))
nil)
; This handler must be run _before_ erc-process-away is.
(add-hook 'erc-server-305-functions 'erc-log-matches-come-back nil)
(defun erc-go-to-log-matches-buffer ()
"Interactively open an erc-log-matches buffer."
(interactive)
(let ((buffer-name (completing-read "Switch to ERC Log buffer: "
(mapcar (lambda (x)
(cons (cdr x) t))
erc-log-matches-types-alist)
(lambda (buffer-cons)
(get-buffer (car buffer-cons))))))
(switch-to-buffer buffer-name)))
(define-key erc-mode-map "\C-c\C-k" 'erc-go-to-log-matches-buffer)
(defun erc-hide-fools (match-type nickuserhost message)
"Hide foolish comments.
This function should be called from `erc-text-matched-hook'."
(when (eq match-type 'fool)
(erc-put-text-properties (point-min) (point-max)
'(invisible intangible)
(current-buffer))))
(defun erc-beep-on-match (match-type nickuserhost message)
"Beep when text matches.
This function is meant to be called from `erc-text-matched-hook'."
(when (member match-type erc-beep-match-types)
(beep)))
(provide 'erc-match)
;;; erc-match.el ends here
;;
;; Local Variables:
;; indent-tabs-mode: t
;; tab-width: 8
;; End:
;; arch-tag: 1f1f595e-abcc-4b0b-83db-598a1d3f0f82

121
lisp/erc/erc-menu.el Normal file
View file

@ -0,0 +1,121 @@
;; erc-menu.el -- Menu-bar definitions for ERC
;; Copyright (C) 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@delysid.org>
;; Keywords: comm, processes, menu
;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcMenu
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; Loading this file defines a menu for ERC.
;;; Code:
(require 'easymenu)
(defvar erc-menu-definition
(list "IRC"
["Connect to server..." erc-select t]
["Disconnect from server..." erc-quit-server erc-server-connected]
"-"
["List channels..." erc-cmd-LIST
(and erc-server-connected (fboundp 'erc-cmd-LIST))]
["Join channel..." erc-join-channel erc-server-connected]
["Start a query..." erc-cmd-QUERY erc-server-connected]
"-"
["List users in channel" erc-channel-names erc-channel-users]
["List channel operators" erc-cmd-OPS erc-channel-users]
["Input action..." erc-input-action (erc-default-target)]
["Set topic..." erc-set-topic
(and (and (erc-default-target) (not (erc-query-buffer-p)))
(or (not (member "t" erc-channel-modes))
(erc-channel-user-op-p (erc-current-nick))))]
(list "Channel modes"
["Change mode..." erc-insert-mode-command
(erc-channel-user-op-p (erc-current-nick))]
["No external send" (erc-toggle-channel-mode "n")
:active (erc-channel-user-op-p (erc-current-nick))
:style toggle :selected (member "n" erc-channel-modes)]
["Topic set by channel operator" (erc-toggle-channel-mode "t")
:style toggle :selected (member "t" erc-channel-modes)
:active (erc-channel-user-op-p (erc-current-nick))]
["Invite only" (erc-toggle-channel-mode "i")
:style toggle :selected (member "i" erc-channel-modes)
:active (erc-channel-user-op-p (erc-current-nick))]
["Private" (erc-toggle-channel-mode "p")
:style toggle :selected (member "p" erc-channel-modes)
:active (erc-channel-user-op-p (erc-current-nick))]
["Secret" (erc-toggle-channel-mode "s")
:style toggle :selected (member "s" erc-channel-modes)
:active (erc-channel-user-op-p (erc-current-nick))]
["Moderated" (erc-toggle-channel-mode "m")
:style toggle :selected (member "m" erc-channel-modes)
:active (erc-channel-user-op-p (erc-current-nick))]
["Set a limit..." erc-set-channel-limit
(erc-channel-user-op-p (erc-current-nick))]
["Set a key..." erc-set-channel-key
(erc-channel-user-op-p (erc-current-nick))])
["Leave this channel..." erc-part-from-channel erc-channel-users]
"-"
(list "Pals, fools and other keywords"
["Add pal..." erc-add-pal]
["Delete pal..." erc-delete-pal]
["Add fool..." erc-add-fool]
["Delete fool..." erc-delete-fool]
["Add keyword..." erc-add-keyword]
["Delete keyword..." erc-delete-keyword]
["Add dangerous host..." erc-add-dangerous-host]
["Delete dangerous host..." erc-delete-dangerous-host])
"-"
(list "IRC services"
["Identify to NickServ..." erc-nickserv-identify
(and erc-server-connected (functionp 'erc-nickserv-identify))])
"-"
["Save buffer in log" erc-save-buffer-in-logs
(fboundp 'erc-save-buffer-in-logs)]
["Truncate buffer" erc-truncate-buffer (fboundp 'erc-truncate-buffer)]
"-"
["Customize ERC" (customize-group 'erc) t]
["Enable/Disable ERC Modules" (customize-variable 'erc-modules) t]
["Show ERC version" erc-version t])
"ERC menu definition.")
;; `erc-mode-map' must be defined before doing this
(eval-after-load "erc"
'(progn
(easy-menu-define erc-menu erc-mode-map "ERC menu" erc-menu-definition)
(easy-menu-add erc-menu erc-mode-map)
;; for some reason the menu isn't automatically added to the menu bar
(when (featurep 'xemacs)
(add-hook 'erc-mode-hook
(lambda () (easy-menu-add erc-menu erc-mode-map))))))
(provide 'erc-menu)
;;; erc-menu.el ends here
;;
;; Local Variables:
;; indent-tabs-mode: t
;; tab-width: 8
;; End:
;; arch-tag: 671219f2-b082-4753-a185-1d0c7e0c05bd

861
lisp/erc/erc-nets.el Normal file
View file

@ -0,0 +1,861 @@
;;; erc-nets.el --- IRC networks
;; Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@lexx.delysid.org>
;; Keywords: comm
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; This file deals with IRC networks.
;;
;; Usage:
;;
;; Put into your .emacs:
;;
;; (require 'erc-nets)
;;
;; M-x erc-server-select provides an alternative way to connect to servers by
;; choosing networks.
;; You can use (eq (erc-network) 'Network) if you'd like to set variables or do
;; certain actions according to which network you're connected to.
;; If a network you use is not listed in `erc-networks-alist', you can put
;; (add-to-list 'erc-networks-alist '(Network "irc.server-name.net")) in your
;; config file.
;;; Code:
(require 'erc)
(eval-when-compile (require 'cl))
;; Variables
(defgroup erc-networks nil
"IRC Networks"
:group 'erc)
(defcustom erc-server-alist
'(("4-irc: Random server" 4-irc "4-irc.com" 6667)
("A5KNet: Random server" A5KNet "irc.a5knet.com" ((6660 6669)))
("AbleNet: Random server" AbleNet "irc.ablenet.org" 6667)
("Accessirc: Random server" Accessirc "irc.accessirc.net" 6667)
("Acestar: Random server" Acestar "irc.acestar.org" 6667)
("Action-IRC: Random server" Action-IRC "irc.action-irc.net" ((6660 6669)))
("AfterNET: Random server" AfterNET "irc.afternet.org" 6667)
("Alternativenet: Random server" Alternativenet "irc.altnet.org" 6667)
("AmigaNet: Random server" AmigaNet "irc.amiganet.org" 6667)
("AngelEyez: Random server" AngelEyez "irc.angeleyez.net" ((6666 7000)))
("AnotherNet: Random server" Anothernet "irc.another.net" (6667 7000 ))
("ArabChat: Random server" ArabChat "irc.arabchat.org" ((6660 6667)))
("AsiaTalk: Random server" AsiaTalk "irc.asiatalk.org" ((6667 6669) 7000 ))
("AstroLink: Random server" AstroLink "irc.astrolink.org" ((6660 6667)))
("Asylumnet: Random server" Asylumnet "irc.asylum-net.org" ((6661 6669) 7000 7777 ))
("Austnet: Random AU server" Austnet "au.austnet.org" 6667)
("Austnet: Random NZ server" Austnet "nz.austnet.org" 6667)
("Austnet: Random SG server" Austnet "sg.austnet.org" 6667)
("Austnet: Random US server" Austnet "us.austnet.org" 6667)
("AwesomeChat: Random server" AwesomeChat "irc.awesomechat.net" ((6661 6669)))
("Awesomechristians: Random server" Awesomechristians "irc.awesomechristians.com" 7000)
("Axenet: Random server" Axenet "irc.axenet.org" ((6660 6667)))
("BeyondIRC: Random server" Beyondirc "irc.beyondirc.net" ((6660 6669)))
("BGIRC: Random server" BGIRC "irc.bulgaria.org" ((6666 6669) 7000 ))
("Blabbernet: Random server" Blabbernet "irc.blabber.net" (6667 7000 ))
("Blitzed: Random server" Blitzed "irc.blitzed.org" (6667 7000 ))
("Brasirc: Random server" Brasirc "irc.brasirc.net" ((6666 6667)))
("Brasirc: BR, PA, Belem" Brasirc "irc.libnet.com.br" ((6666 6668) 7777 8002 ))
("BRASnet: Random European server" BRASnet "eu.brasnet.org" ((6665 6669)))
("BRASnet: Random US server" BRASnet "us.brasnet.org" ((6665 6669)))
("BubbleNet: Random server" BubbleNet "irc.bubblenet.org" ((6667 6669)))
("CCnet: Random server" CCnet "irc.cchat.net" (6667 7000 ))
("CCnet: US, TX, Dallas" CCnet "irc2.cchat.net" (6667 7000 ))
("Chat-Net: Random server" Chat-Net "irc.chat-net.org" 6667)
("Chat-Solutions: Random server" Chat-Solutions "irc.chat-solutions.org" 6667)
("Chatcafe: Random server" Chatcafe "irc.chatcafe.net" 6667)
("Chatchannel: Random server" Chatchannel "irc.chatchannel.org" ((6666 6669) 7000 ))
("ChatCircuit: Random server" ChatCircuit "irc.chatcircuit.com" 6668)
("Chatlink: Random server" Chatlink "irc.chatlink.org" 6667)
("Chatnet: Random AU server" Chatnet "au.chatnet.org" 6667)
("Chatnet: Random EU server" Chatnet "eu.chatnet.org" 6667)
("Chatnet: Random US server" Chatnet "us.chatnet.org" 6667)
("ChatNut: Random server" ChatNut "irc.chatnut.net" (6667 7000 ))
("Chatpinoy: Random server" Chatpinoy "irc.chatpinoy.com" 6667)
("ChatPR: Random server" ChatPR "irc.chatpr.org" 6667)
("Chatroom: Random server" Chatroom "irc.chatroom.org" 6667)
("Chatster: Random server" Chatster "irc.chatster.org" 6667)
("ChatX: Random server" ChatX "irc.chatx.net" 6667)
("China263: Random server" China263 "irc.263.net" 6667)
("Cineplex1: Random server" Cineplex1 "irc.cineplex1.com" ((6666 6668)))
("CNN: CNN News discussions" CNN "chat.cnn.com" ((6667 6669) 7000 ))
("CobraNet: Random server" CobraNet "irc.cobra.net" 6667)
("Coolchat: Random server" Coolchat "irc.coolchat.net" 6667)
("Criten: Random server" Criten "irc.criten.net" 6667)
("Cyberchat: Random server" Cyberchat "irc.cyberchat.org" (6667 6668 ))
("CyGanet: Random server" CyGanet "irc.cyga.net" 6667)
("DALnet: AS, MY, Coins" DALnet "coins.dal.net" ((6663 6668) 7000 ))
("DALnet: CA, ON, Sodre" DALnet "sodre.on.ca.dal.net" ((6661 6669) 7000 ))
("DALnet: EU, DE, Nexgo" DALnet "nexgo.de.eu.dal.net" ((6664 6669) 7000 ))
("DALnet: EU, NO, Powertech" DALnet "powertech.no.eu.dal.net" ((6666 6667) 7000 ))
("DALnet: EU, SE, Borg" DALnet "borg.se.eu.dal.net" (6667 7000 ))
("DALnet: EU, SE, Ced" DALnet "ced.se.eu.dal.net" (6667 7000 ))
("DALnet: US, GA, Astro" DALnet "astro.ga.us.dal.net" ((6661 6669) 7000 ))
("DALnet: US, GA, Dragons" DALnet "dragons.ga.us.dal.net" ((6661 6669) 7000 ))
("DALnet: US, GA, Elysium" DALnet "elysium.ga.us.dal.net" ((6661 6669) 7000 ))
("DALnet: US, MA, Twisted" DALnet "twisted.ma.us.dal.net" ((6660 6669) 7001 7002 ))
("DALnet: US, MO, Global" DALnet "global.mo.us.dal.net" ((6661 6669) 7000 ))
("DALnet: US, NJ, Liberty" DALnet "liberty.nj.us.dal.net" ((6662 6669) 7000 ))
("DALnet: US, VA, Wombat" DALnet "wombat.va.us.dal.net" ((6661 6669) 7000 ))
("DALnet: Random EU server" DALnet "irc.eu.dal.net" 6667)
("DALnet: Random US server" DALnet "irc.dal.net" ((6660 6667)))
("Dark-Tou-Net: Random server" Dark-Tou-Net "irc.d-t-net.de" 6667)
("Darkfire: Random server" Darkfire "irc.darkfire.net" (6667 7000 8000 ))
("DarkMyst: Random server" DarkMyst "irc.darkmyst.org" 6667)
("Darkserv: Random server" Darkserv "irc.darkserv.net" 6667)
("Darksystem: Random server" Darksystem "irc.darksystem.com" 6667)
("Darktree: Random server" Darktree "irc.darktree.net" 6667)
("DayNet: Random server" DayNet "irc.daynet.org" 6667)
("Deepspace: Disability network" Deepspace "irc.deepspace.org" 6667)
("Different: Random server" Different "irc.different.net" 6667)
("Digarix: Random server" Digarix "irc.digarix.net" 6667)
("Digatech: Random server" Digatech "irc.digatech.net" 6667)
("Digital-Base: Random server" Digital-Base "irc.digital-base.net" ((6660 7000)))
("Digitalirc: Random server" Digitalirc "irc.digitalirc.net" 6667)
("Discussioni: Random server" Discussioni "irc.discussioni.org" ((6666 6669)))
("DorukNet: TR, Istanbul" DorukNet "irc.doruk.net.tr" ((6660 6669) 7000 8888 ))
("Dreamcast: Random server" Dreamcast "irc0.dreamcast.com" 6667)
("DWChat: Random server" DWChat "irc.dwchat.net" 6667)
("Dynastynet: Random server" Dynastynet "irc.dynastynet.net" 6667)
("EFnet: CA, AB, Edmonton (arcti)" EFnet "irc.arcti.ca" 6667)
("EFnet: CA, AB, Edmonton (mpls)" EFnet "irc.mpls.ca" ((6660 6669)))
("EFnet: CA, ON, Toronto" EFnet "irc2.magic.ca" 6667)
("EFnet: CA, QB, Montreal" EFnet "irc.qeast.net" 6667)
("EFnet: EU, DK, Aarhus" EFnet "irc.inet.tele.dk" 6667)
("EFnet: EU, FI, Helsinki" EFnet "efnet.cs.hut.fi" 6667)
("EFnet: EU, FR, Paris" EFnet "irc.isdnet.fr" ((6667 6669)))
("EFnet: EU, NL, Amsterdam" EFnet "efnet.vuurwerk.nl" 6667)
("EFnet: EU, NO, Homelien" EFnet "irc.homelien.no" (5190 (6666 6667) (7000 7001) ))
("EFnet: EU, NO, Oslo" EFnet "irc.daxnet.no" ((6666 7000)))
("EFnet: EU, PL, Warszawa" EFnet "irc.efnet.pl" 6667)
("EFnet: EU, RU, Moscow" EFnet "irc.rt.ru" ((6661 6669)))
("EFnet: EU, SE, Dalarna" EFnet "irc.du.se" ((6666 6669)))
("EFnet: EU, SE, Gothenberg" EFnet "irc.hemmet.chalmers.se" ((6666 7000)))
("EFnet: EU, SE, Sweden" EFnet "irc.light.se" 6667)
("EFnet: EU, UK, London (carrier)" EFnet "irc.carrier1.net.uk" ((6666 6669)))
("EFnet: EU, UK, London (demon)" EFnet "efnet.demon.co.uk" ((6665 6669)))
("EFnet: ME, IL, Inter" EFnet "irc.inter.net.il" ((6665 6669)))
("EFnet: US, AZ, Phoenix" EFnet "irc.easynews.com" (6660 (6665 6667) 7000 ))
("EFnet: US, CA, San Jose" EFnet "irc.concentric.net" ((6665 6668)))
("EFnet: US, CA, San Luis Obispo" EFnet "irc.prison.net" ((6666 6667)))
("EFnet: US, GA, Atlanta" EFnet "irc.mindspring.com" ((6660 6669)))
("EFnet: US, MI, Ann Arbor" EFnet "irc.umich.edu" 6667)
("EFnet: US, MN, Twin Cities" EFnet "irc.umn.edu" ((6665 6669)))
("EFnet: US, NY, Mineola" EFnet "irc.lightning.net" ((6665 7000)))
("EFnet: US, NY, New York (east)" EFnet "irc.east.gblx.net" 6667)
("EFnet: US, NY, New York (flamed)" EFnet "irc.flamed.net" ((6665 6669)))
("EFnet: US, TX, Houston" EFnet "ircd.lagged.org" ((6660 6669)))
("EFnet: US, VA, Ashburn" EFnet "irc.secsup.uu.net" ((6665 6669) 8080 ))
("EFnet: Random AU server" EFnet "au.rr.efnet.net" 6667)
("EFnet: Random CA server" EFnet "ca.rr.efnet.net" 6667)
("EFnet: Random EU server" EFnet "eu.rr.efnet.net" 6667)
("EFnet: Random US server" EFnet "us.rr.efnet.net" 6667)
("EgyptianIRC: Random server" EgyptianIRC "irc.egyptianirc.net" ((6667 6669)))
("Eircnet: Random server" Eircnet "irc.eircnet.org" ((6660 6669) 7000 ))
("Eleethal: Random server" Eleethal "irc.eleethal.com" ((6660 6669) 7000 ))
("EntertheGame: Random server" EntertheGame "irc.enterthegame.com" ((6667 6669)))
("EpiKnet: Random server" EpiKnet "irc.epiknet.org" ((6660 6669) 7000 7001 ))
("EsperNet: Random server" EsperNet "irc.esper.net" (5555 (6667 6669) ))
("Esprit: Random server" Esprit "irc.esprit.net" 6667)
("euIRC: Random server" euIRC "irc.euirc.net" ((6665 6669)))
("Evilzinc: Random server" Evilzinc "irc.evilzinc.net" ((6660 6669) 7000 8000 ))
("ExodusIRC: Random server" ExodusIRC "irc.exodusirc.net" ((6660 6669)))
("FDFnet: Random server" FDFnet "irc.fdfnet.net" ((6666 6668) 9999 ))
("FEFnet: Random server" FEFnet "irc.fef.net" 6667)
("Financialchat: Random server" Financialchat "irc.financialchat.com" ((6667 6669) 7000 ))
("Forestnet: Random server" Forestnet "irc.forestnet.org" (6667 7000 ))
("ForeverChat: Random server" ForeverChat "irc.foreverchat.net" ((6660 6669) 7000 ))
("Fraggers: Random server" Fraggers "irc.fraggers.co.uk" ((6661 6669) (7000 7001) ))
("FreedomChat: Random server" FreedomChat "chat.freedomchat.net" 6667)
("FreedomIRC: Random server" FreedomIRC "irc.freedomirc.net" 6667)
("Freenode: Random server" freenode "irc.freenode.net" 6667)
("Freenode: Random EU server" freenode "irc.eu.freenode.net" 6667)
("Freenode: Random US server" freenode "irc.us.freenode.net" 6667)
("FunNet: Random server" FunNet "irc.funnet.org" 6667)
("Galaxynet: Random server" GalaxyNet "irc.galaxynet.org" ((6662 6668) 7000 ))
("Galaxynet: AU, NZ, Auckland" GalaxyNet "auckland.nz.galaxynet.org" ((6661 6669)))
("Galaxynet: EU, BE, Online" GalaxyNet "online.be.galaxynet.org" ((6661 6669)))
("Galaxynet: US, FL, Florida" GalaxyNet "gymnet.us.galaxynet.org" ((6661 6669)))
("Gamesnet: Random east US server" Gamesnet "east.gamesnet.net" 6667)
("Gamesnet: Random west US server" Gamesnet "west.gamesnet.net" 6667)
("GammaForce: Random server" GammaForce "irc.gammaforce.org" ((6660 6669) 7000 ))
("GIKInet: Random server" GIKInet "irc.giki.edu.pk" 6667)
("GizNet: Random server" GizNet "irc.giznet.org" ((6666 6669) 7000 ))
("Globalchat: Random server" Globalchat "irc.globalchat.org" 6667)
("GlobIRC: Random server" GlobIRC "irc.globirc.net" ((6666 6668) 9999 ))
("Goldchat: Random server" Goldchat "irc.goldchat.nl" ((6660 6669) 7000 ))
("Goodchatting: Random server" Goodchatting "irc.goodchatting.com" ((6661 6669) 7000 ))
("GravityLords: Random server" GravityLords "irc.gravitylords.net" 6667)
("Grnet: Random EU server" GRnet "gr.irc.gr" (6667 7000 ))
("Grnet: Random server" GRnet "srv.irc.gr" (6667 7000 ))
("Grnet: Random US server" GRnet "us.irc.gr" (6667 7000 ))
("GulfChat: Random server" GulfChat "irc.gulfchat.net" ((6660 6669)))
("HabberNet: Random server" HabberNet "irc.habber.net" 6667)
("HanIRC: Random server" HanIRC "irc.hanirc.org" 6667)
("Hellenicnet: Random server" Hellenicnet "irc.mirc.gr" (6667 7000 ))
("IceNet: Random server" IceNet "irc.icenet.org.za" 6667)
("ICQnet: Random server" ICQnet "irc.icq.com" 6667)
("Infatech: Random server" Infatech "irc.infatech.net" ((6660 6669)))
("Infinity: Random server" Infinity "irc.infinity-irc.org" 6667)
("Infomatrix: Random server" Infomatrix "irc.infomatrix.net" 6667)
("Inside3D: Random server" Inside3D "irc.inside3d.net" ((6661 6669)))
("InterlinkChat: Random server" InterlinkChat "irc.interlinkchat.net" ((6660 6669) 7000 ))
("IRC-Chile: Random server" IRC-Chile "irc.cl" 6667)
("IRC-Hispano: Random server" IRC-Hispano "irc.irc-hispano.org" 6667)
("IRCchat: Random server" IRCchat "irc.ircchat.tk" 6667)
("IRCGate: Random server" IRCGate "irc.ircgate.net" ((6667 6669)))
("IRCGeeks: Random server" IRCGeeks "irc.ircgeeks.org" ((6660 6669)))
("IRChat: Random server" IRChat "irc.irchat.net" ((6660 6669)))
("IrcLordz: Random server" IrcLordz "irc.irclordz.com" 6667)
("IrcMalta: Random server" IrcMalta "irc.ircmalta.org" ((6660 6667)))
("IRCnet: EU, FR, Random" IRCnet "irc.fr.ircnet.net" 6667)
("IRCnet: EU, IT, Random" IRCnet "irc.ircd.it" ((6665 6669)))
("IRCnet: AS, IL, Haifa" IRCnet "ircnet.netvision.net.il" ((6661 6668)))
("IRCnet: AS, JP, Tokyo" IRCnet "irc.tokyo.wide.ad.jp" 6667)
("IRCnet: AS, TW, Seed" IRCnet "irc.seed.net.tw" 6667)
("IRCnet: EU, AT, Linz" IRCnet "linz.irc.at" ((6666 6668)))
("IRCnet: EU, AT, Wien" IRCnet "vienna.irc.at" ((6666 6669)))
("IRCnet: EU, BE, Brussels" IRCnet "irc.belnet.be" 6667)
("IRCnet: EU, BE, Zaventem" IRCnet "ircnet.wanadoo.be" ((6661 6669)))
("IRCnet: EU, CZ, Prague" IRCnet "irc.felk.cvut.cz" 6667)
("IRCnet: EU, DE, Berlin" IRCnet "irc.fu-berlin.de" ((6665 6669)))
("IRCnet: EU, DE, Dusseldorf" IRCnet "irc.freenet.de" ((6665 6669)))
("IRCnet: EU, DE, Stuttgart" IRCnet "irc.belwue.de" ((6665 6669)))
("IRCnet: EU, DK, Copenhagen" IRCnet "irc.ircnet.dk" 6667)
("IRCnet: EU, EE, Tallinn" IRCnet "irc.estpak.ee" ((6666 6668)))
("IRCnet: EU, FI, Helsinki" IRCnet "irc.cs.hut.fi" 6667)
("IRCnet: EU, GR, Thessaloniki" IRCnet "irc.ee.auth.gr" ((6666 6669)))
("IRCnet: EU, HU, Budapest" IRCnet "irc.elte.hu" 6667)
("IRCnet: EU, IS, Reykjavik (ircnet)" IRCnet "irc.ircnet.is" ((6661 6669)))
("IRCnet: EU, IS, Reykjavik (simnet)" IRCnet "irc.simnet.is" ((6661 6669)))
("IRCnet: EU, IT, Rome" IRCnet "irc.tin.it" ((6665 6669)))
("IRCnet: EU, NL, Amsterdam (nlnet)" IRCnet "irc.nl.uu.net" ((6660 6669)))
("IRCnet: EU, NL, Amsterdam (xs4all)" IRCnet "irc.xs4all.nl" ((6660 6669)))
("IRCnet: EU, NL, Enschede" IRCnet "irc.snt.utwente.nl" ((6660 6669)))
("IRCnet: EU, NL, Nijmegen" IRCnet "irc.sci.kun.nl" ((6660 6669)))
("IRCnet: EU, NO, Oslo" IRCnet "irc.ifi.uio.no" 6667)
("IRCnet: EU, NO, Trondheim" IRCnet "irc.pvv.ntnu.no" 6667)
("IRCnet: EU, PL, Lublin" IRCnet "lublin.irc.pl" ((6666 6668)))
("IRCnet: EU, PL, Warsaw" IRCnet "warszawa.irc.pl" ((6666 6668)))
("IRCnet: EU, RU, Moscow" IRCnet "irc.msu.ru" 6667)
("IRCnet: EU, SE, Lulea" IRCnet "irc.ludd.luth.se" ((6661 6669)))
("IRCnet: EU, UK, London (Demon)" IRCnet "ircnet.demon.co.uk" ((6665 6669)))
("IRCnet: EU, UK, London (Easynet)" IRCnet "ircnet.easynet.co.uk" ((6666 6669)))
("IRCnet: US, NY, New York" IRCnet "irc.stealth.net" ((6660 6669)))
("IRCnet: Random AU server" IRCnet "au.ircnet.org" 6667)
("IRCnet: Random EU server" IRCnet "eu.ircnet.org" ((6665 6668)))
("IRCnet: Random US server" IRCnet "us.ircnet.org" ((6665 6668)))
("IRCSoulZ: Random server" IRCSoulZ "irc.ircsoulz.net" 6667)
("IRCSul: BR, PR, Maringa" IRCSul "irc.wnet.com.br" 6667)
("IrcTalk: Random server" IrcTalk "irc.irctalk.net" ((6660 6669)))
("Irctoo: Random server" Irctoo "irc.irctoo.net" 6667)
("IRCtown: Random server" IRCtown "irc.irctown.net" ((6666 6669) 7000 ))
("IRCworld: Random server" IRCworld "irc.ircworld.org" 6667)
("ircXtreme: Random server" ircXtreme "irc.ircXtreme.net" ((6660 6669)))
("Israelnet: Random server" Israelnet "irc.israel.net" 6667)
("K0wNet: Random server" K0wNet "irc.k0w.net" ((6660 6669)))
("KDFSnet: Random server" KDFSnet "irc.kdfs.net" ((6667 6669)))
("Kemik: Random server" Kemik "irc.kemik.net" 6667)
("Kewl.Org: Random server" Kewl.Org "irc.kewl.org" (6667 7000 ))
("Kickchat: Random server" Kickchat "irc.kickchat.com" ((6660 6669) 7000 ))
("Kidsworld: Random server" KidsWorld "irc.kidsworld.org" ((6666 6669)))
("Knightnet: AF, ZA, Durban" Knightnet "orc.dbn.za.knightnet.net" (6667 5555 ))
("Knightnet: US, CA, Goldengate" Knightnet "goldengate.ca.us.knightnet.net" (6667 5555 ))
("Konfido.Net: Random server" Konfido.Net "irc.konfido.net" 6667)
("KreyNet: Random server" Kreynet "irc.krey.net" 6667)
("Krono: Random server" Krono "irc.krono.net" ((6660 6669) 7000 ))
("Krushnet: Random server" Krushnet "irc.krushnet.org" 6667)
("LagNet: Random server" LagNet "irc.lagnet.org.za" 6667)
("LagNet: AF, ZA, Cape Town" LagNet "reaper.lagnet.org.za" 6667)
("LagNet: AF, ZA, Johannesburg" LagNet "mystery.lagnet.org.za" 6667)
("Librenet: Random server" Librenet "irc.librenet.net" 6667)
("LinkNet: Random server" LinkNet "irc.link-net.org" ((6667 6669)))
("Liquidized: Random server" Liquidized "irc.liquidized.net" (6667 7000 ))
("M-IRC: Random server" M-IRC "irc.m-sys.org" ((6667 6669)))
("MagicStar: Random server" MagicStar "irc.magicstar.net" 6667)
("Mavra: Random server" Mavra "irc.mavra.net" 6667)
("MediaDriven: Random server" MediaDriven "irc.mediadriven.com" ((6667 6669)))
("mIRC-X: Random server" mIRC-X "irc.mircx.com" (6667 7000 ))
("Morat: Random server" Morat "irc.morat.net" 6667)
("MusicCity: Random server" MusicCity "chat.musiccity.com" 6667)
("Mysteria: Random server" Mysteria "irc.mysteria.net" (6667 7000 ))
("Mysterychat: Random server" Mysterychat "irc.mysterychat.net" ((6667 6669)))
("Mystical: Random server" Mystical "irc.mystical.net" (6667 7000 ))
("Narancs: Random server" Narancs "irc.narancs.com" ((6667 6669) 7000 ))
("Net-France: Random server" Net-France "irc.net-france.com" 6667)
("Nevernet: Random server" Nevernet "irc.nevernet.net" 6667)
("Newnet: Random server" Newnet "irc.newnet.net" ((6665 6667)))
("Nexusirc: Random server" Nexusirc "irc.nexusirc.org" 6667)
("Nightstar: Random server" NightStar "irc.nightstar.net" ((6665 6669)))
("NitrousNet: Random server" NitrousNet "irc.nitrousnet.net" 6667)
("Novernet: Random server" Novernet "irc.novernet.com" ((6665 6669) 7000 ))
("Nullrouted: Random server" Nullrouted "irc.nullrouted.org" ((6666 6669) 7000 ))
("NullusNet: Random server" NullusNet "irc.nullus.net" 6667)
("OpChat: Random server" OpChat "irc.opchat.org" ((6667 6669)))
("Othernet: Random server" Othernet "irc.othernet.org" 6667)
("Othernet: US, FL, Miami" Othernet "miami.fl.us.othernet.org" 6667)
("Othernet: US, MO, StLouis" Othernet "stlouis.mo.us.othernet.org" 6667)
("Otherside: Random server" OtherSide "irc.othersideirc.net" 6667)
("Outsiderz: Random server" Outsiderz "irc.outsiderz.com" 6667)
("OzOrg: AU, Perth" OzOrg "iinet.perth.oz.org" 6667)
("Peacefulhaven: Random server" Peacefulhaven "irc.peacefulhaven.net" ((6660 6669) 7000 ))
("PhazedIRC: Random server" PhazedIRC "irc.phazedirc.net" 6667)
("Philchat: Random server" Philchat "irc.philchat.net" 6667)
("phrozN: Random server" phrozN "irc.phrozn.net" 6667)
("PiNet: Random server" PiNet "irc.praetorians.org" ((6665 6669)))
("Pinoycentral: Random server" Pinoycentral "chat.abs-cbn.com" 6667)
("Planetarion: Random server" Planetarion "irc.planetarion.com" 6667)
("POLNet: Random server" POLNet "irc.ircnet.pl" 6667)
("Psionics: CA, PQ, Montreal" Psionics "chat.psionics.net" ((6660 6669)))
("PTirc: Random server" PTirc "irc.ptirc.com.pt" 6667)
("PTlink: Random server" PTlink "irc.ptlink.net" 6667)
("PTnet: Random server" PTnet "irc.ptnet.org" 6667)
("QChat: Random server" QChat "irc.qchat.net" 6667)
("QuakeNet: Random German server" QuakeNet "de.quakenet.org" ((6667 6669)))
("QuakeNet: Random server" QuakeNet "irc.quakenet.eu.org" ((6667 6669)))
("QuakeNet: Random Swedish server" QuakeNet "se.quakenet.org" ((6667 6669)))
("QuakeNet: Random UK server" QuakeNet "uk.quakenet.org" ((6667 6669)))
("QuakeNet: Random US server" QuakeNet "us.quakenet.org" ((6667 6669)))
("Realirc: Random server" Realirc "irc.realirc.org" 6667)
("RealmNET: Random server" RealmNET "irc.realmnet.com" 6667)
("Rebelchat: Random server" Rebelchat "irc.rebelchat.org" 6667)
("Red-Latina: Random server" Red-Latina "irc.red-latina.org" 6667)
("RedLatona: Random server" RedLatona "irc.redlatona.net" (6667 6668 ))
("Relicnet: Random server" Relicnet "irc.relic.net" 6667)
("Rezosup: Random server" Rezosup "irc.rezosup.org" 6667)
("Risanet: Random server" Risanet "irc.risanet.com" ((6667 6669)))
("Rubiks: Random server" Rubiks "irc.rubiks.net" 6667)
("Rusnet: EU, RU, Tomsk" Rusnet "irc.tsk.ru" ((6667 6669) (7770 7775) ))
("Rusnet: EU, RU, Vladivostok" Rusnet "irc.vladivostok.ru" ((6667 6669) (7770 7775) ))
("Rusnet: EU, UA, Kiev" Rusnet "irc.kar.net" ((6667 6669) (7770 7775) ))
("Sandnet: Random server" Sandnet "irc.sandnet.net" ((6660 6669) 7000 ))
("Scunc: Random server" Scunc "irc.scunc.net" 6667)
("SerbianCafe: Random server" SerbianCafe "irc.serbiancafe.ws" ((6665 6669)))
("SexNet: Random server" SexNet "irc.sexnet.org" 6667)
("ShadowFire: Random server" ShadowFire "irc.shadowfire.org" 6667)
("ShadowWorld: Random server" ShadowWorld "irc.shadowworld.net" 6667)
("SkyNet: Random server" SkyNet "irc.bronowski.pl" ((6666 6668)))
("Slashnet: Random server" Slashnet "irc.slashnet.org" 6667)
("SolarStone: Random server" SolarStone "irc.solarstone.net" ((6660 6669)))
("Sorcerynet: Random server" Sorcery "irc.sorcery.net" (6667 7000 9000 ))
("Sorcerynet: EU, SE, Karlskrona" Sorcery "nexus.sorcery.net" (6667 7000 9000 ))
("Sorcerynet: US, CA, Palo Alto" Sorcery "kechara.sorcery.net" (6667 7000 9000 ))
("SourceIRC: Random server" SourceIRC "irc.sourceirc.net" ((6667 6669) 7000 ))
("SpaceTronix: Random server" SpaceTronix "irc.spacetronix.net" ((6660 6669) 7000 ))
("Spirit-Harmony: Random server" Spirit-Harmony "irc.spirit-harmony.com" ((6661 6669)))
("StarChat: Random server" StarChat "irc.starchat.net" ((6667 6669) 7000 ))
("StarEquinox: Random server" StarEquinox "irc.starequinox.net" ((6660 6669)))
("StarLink: Random server" Starlink "irc.starlink.net" ((6660 6669)))
("StarLink-irc: Random server" starlink-irc "irc.starlink-irc.org" 6667)
("StarWars-IRC: Random server" StarWars-IRC "irc.starwars-irc.net" ((6663 6667)))
("Stormdancing: Random server" Stormdancing "irc.stormdancing.net" ((6664 6669) 7000 9000 ))
("Superchat: Random server" Superchat "irc.superchat.org" ((6660 6668)))
("Sysopnet: Random server" Sysopnet "irc.sysopnet.org" ((6666 6668)))
("Telstra: Random server" Telstra "irc.telstra.com" ((6667 6669)))
("TR-net: EU, TR, Ankara" TR-net "irc.dominet.com.tr" 6667)
("TR-net: EU, Tr, Istanbul" TR-net "irc.teklan.com.tr" 6667)
("Tri-net: Random server" Tri-net "irc.tri-net.org" 6667)
("TriLink: Random server" TriLink "irc.ft4u.net" 6667)
("TurkishChat: Random server" TurkishChat "irc.turkishchat.org" ((6660 6669) 7000 ))
("UberNinja: Random server" UberNinja "irc.uberninja.net" ((6667 6669)))
("UICN: Random server" UICN "irc.uicn.net" 6667)
("UltraIRC: Random server" UltraIRC "irc.ultrairc.net" 6667)
("UnderChat: Random server" UnderChat "irc.underchat.it" ((6660 6669) 7000 ))
("Undernet: CA, ON, Toronto" Undernet "toronto.on.ca.undernet.org" ((6661 6669)))
("Undernet: CA, QC, Montreal" Undernet "montreal.qu.ca.undernet.org" ((6660 6669)))
("Undernet: EU, AT, Graz" Undernet "graz.at.eu.undernet.org" ((6661 6669)))
("Undernet: EU, BE, Antwerp" Undernet "flanders.be.eu.undernet.org" ((6660 6669)))
("Undernet: EU, BE, Brussels" Undernet "brussels.be.eu.undernet.org" 6667)
("Undernet: EU, CH, Geneva" Undernet "geneva.ch.eu.undernet.org" ((6660 6669) 7777 8000 ))
("Undernet: EU, FR, Caen" Undernet "caen.fr.eu.undernet.org" ((6666 6669)))
("Undernet: EU, NL, Diemen" Undernet "diemen.nl.eu.undernet.org" ((6660 6669)))
("Undernet: EU, NL, Haarlem" Undernet "haarlem.nl.eu.undernet.org" ((6660 6669)))
("Undernet: EU, NO, Oslo" Undernet "oslo.no.eu.undernet.org" ((6660 6669)))
("Undernet: EU, SE, Stockholm" Undernet "stockholm.se.eu.undernet.org" ((6666 6669)))
("Undernet: EU, UK, Surrey" Undernet "surrey.uk.eu.undernet.org" ((6660 6669)))
("Undernet: US, AZ, Mesa" Undernet "mesa.az.us.undernet.org" ((6665 6667)))
("Undernet: US, CA, San Diego" Undernet "sandiego.ca.us.undernet.org" ((6660 6670)))
("Undernet: US, DC, Washington" Undernet "washington.dc.us.undernet.org" ((6660 6669)))
("Undernet: US, KS, Manhattan" Undernet "manhattan.ks.us.undernet.org" ((6660 6669)))
("Undernet: US, NV, Las Vegas" Undernet "lasvegas.nv.us.undernet.org" ((6660 6669)))
("Undernet: US, TX, Austin" Undernet "austin.tx.us.undernet.org" ((6660 6669)))
("Undernet: US, UT, Saltlake" Undernet "saltlake.ut.us.undernet.org" ((6660 6669)))
("Undernet: US, VA, Arlington" Undernet "arlington.va.us.undernet.org" ((6660 6669)))
("Undernet: US, VA, McLean" Undernet "mclean.va.us.undernet.org" ((6666 6669)))
("Undernet: Random EU server" Undernet "eu.undernet.org" 6667)
("Undernet: Random US server" Undernet "us.undernet.org" 6667)
("UnderZ: Random server" UnderZ "irc.underz.org" ((6667 6668)))
("UniChat: Random server" UniChat "irc.uni-chat.net" 6667)
("UnionLatina: Random server" UnionLatina "irc.unionlatina.org" 6667)
("Univers: Random server" Univers "irc.univers.org" ((6665 6669)))
("UnixR: Random server" UnixR "irc.unixr.net" ((6667 6669)))
("Vidgamechat: Random server" Vidgamechat "irc.vidgamechat.com" 6667)
("VirtuaNet: Random server" VirtuaNet "irc.virtuanet.org" ((6660 6669) 7000 ))
("Vitamina: Random server" Vitamina "irc.vitamina.ca" 6667)
("Voila: Random server" Voila "irc.voila.fr" 6667)
("Wahou: Random server" Wahou "irc.wahou.org" ((6665 6669)))
("Warpednet: Random server" Warpednet "irc.warped.net" 6667)
("Weaklinks: Random server" Weaklinks "irc.weaklinks.net" ((6667 6669)))
("Webnet: Random server" Webnet "irc.webchat.org" ((6667 6669) 7000 ))
("Webnet: US, CA, Santa Clara" Webnet "webmaster.ca.us.webchat.org" ((6661 6669)))
("WinChat: Random server" WinChat "irc.winchat.net" ((6661 6669)))
("WinIRC: Random server" WinIRC "irc.winirc.org" ((6667 6669) 4400 ))
("WorldIRC: Random server" WorldIRC "irc.worldirc.org" ((6660 6667)))
("WyldRyde: Random server" WyldRyde "irc.wyldryde.net" ((6666 6669)))
("XentoniX: Random server" XentoniX "irc.xentonix.net" ((6661 6669)))
("Xevion: Random server" Xevion "irc.xevion.net" (6667 7000 ))
("XNet: Random server" XNet "irc.xnet.org" 6667)
("XWorld: Random server" XWorld "irc.xworld.org" 6667)
("ZAnet Net: Random server" ZAnetNet "irc.zanet.net" 6667)
("ZAnet Org: UK, London" ZAnetOrg "mystic.zanet.org.za" 6667)
("ZiRC: Random server" ZiRC "irc.zirc.org" ((6660 6669)))
("ZUHnet: Random server" ZUHnet "irc.zuh.net" 6667)
("Zurna: Random server" Zurna "irc.zurna.net" 6667))
"Alist of irc servers. (NAME NET HOST PORTS) where
NAME is a name for that server,
NET is a symbol indicating to which network from `erc-networks-alist' this
server corresponds,
HOST is the servers hostname and
PORTS is either a number, a list of numbers, or a list of port ranges."
:group 'erc-networks
:type 'sexp)
(defcustom erc-networks-alist
'((4-irc "4-irc.com")
(A5KNet "a5knet.com")
(AbleNet "ablenet.org")
(Accessirc "accessirc.net")
(Acestar "acestar.org")
(Action-IRC "action-irc.net")
(AfterNET "afternet.org")
(Alternativenet "altnet.org")
(AmigaNet "amiganet.org")
(AngelEyez "angeleyez.net")
(Anothernet "another.net")
(ArabChat "arabchat.org")
(AsiaTalk "asiatalk.org")
(AstroLink "astrolink.org")
(Asylumnet "asylumnet.org")
(Austnet "austnet.org")
(AwesomeChat "awesomechat.net")
(Awesomechristians "awesomechristians.com")
(Axenet "axenet.org")
(Beyondirc "beyondirc.net")
(BGIRC "bulgaria.org")
(Blabbernet "blabber.net")
(Blitzed "blitzed.org")
(BrasIRC "brasirc.net")
(BRASnet "brasnet.org")
(BubbleNet "bubblenet.org")
(CCnet "christian-chat.net")
(Chat-Net "chat-net.org")
(Chat-Solutions "chat-solutions.org")
(Chatcafe "chatcafe.net")
(Chatchannel "chatchannel.org")
(ChatCircuit "chatcircuit.com")
(Chatlink "chatlink.org")
(Chatnet "chatnet.org")
(ChatNut "chatnut.net")
(Chatpinoy "chatpinoy.com")
(ChatPR "chatpr.org")
(Chatroom "chatroom.org")
(Chatster "chatster.org")
(ChatX "chatx.net")
(China263 "263.net")
(Cineplex1 "cineplex1.com")
(CNN "cnn.com")
(CobraNet "cobra.net")
(Coolchat "coolchat.net")
(Criten "criten.net")
(Cyberchat "cyberchat.org")
(CyGanet "cyga.net")
(DALnet "dal.net")
(Dark-Tou-Net "d-t-net.de")
(Darkfire "darkfire.net")
(DarkMyst "darkmyst.org")
(Darkserv "darkserv.net")
(Darksystem "darksystem.com")
(Darktree "darktree.net")
(DayNet "daynet.org")
(Deepspace "deepspace.org")
(Different "different.net")
(Digarix "digarix.net")
(Digatech "digatech.net")
(Digital-Base "digital-base.net")
(Digitalirc "digitalirc.net")
(Discussioni "discussioni.org")
(DorukNet "doruk.net.tr")
(DWChat "dwchat.net")
(Dynastynet "dynastynet.net")
(EFnet nil)
(EgyptianIRC "egyptianirc.net")
(Eircnet "eircnet.org")
(Eleethal "eleethal.com")
(EntertheGame "enterthegame.com")
(EpiKnet "epiknet.org")
(EsperNet "esper.net")
(Esprit "esprit.net")
(euIRC "euirc.net")
(Evilzinc "evilzinc.net")
(ExodusIRC "exodusirc.net")
(FDFnet "fdfnet.net")
(FEFnet "fef.net")
(Financialchat "financialchat.com")
(Forestnet "forestnet.org")
(ForeverChat "foreverchat.net")
(Fraggers "fraggers.co.uk")
(FreedomChat "freedomchat.net")
(FreedomIRC "freedomirc.net")
(freenode "freenode.net")
(FunNet "funnet.org")
(GalaxyNet "galaxynet.org")
(Gamesnet "gamesnet.net")
(GammaForce "gammaforce.org")
(GIKInet "giki.edu.pk")
(GizNet "giznet.org")
(Globalchat "globalchat.org")
(GlobIRC "globirc.net")
(Goldchat "goldchat.nl")
(Goodchatting "goodchatting.com")
(GravityLords "gravitylords.net")
(GRnet "irc.gr")
(GulfChat "gulfchat.net")
(HabberNet "habber.net")
(HanIRC "hanirc.org")
(Hellenicnet "mirc.gr")
(IceNet "icenet.org.za")
(ICQnet "icq.com")
(iip "anon.iip")
(Infatech "infatech.net")
(Infinity "infinity-irc.org")
(Infomatrix "infomatrix.net")
(Inside3D "inside3d.net")
(InterlinkChat "interlinkchat.net")
(IRC-Chile "irc.cl")
(IRC-Hispano "irc-hispano.org")
(IRCchat "ircchat.tk")
(IRCGate "ircgate.net")
(IRCGeeks "ircgeeks.org")
(IRChat "irchat.net")
(IrcLordz "irclordz.com")
(IrcMalta "ircmalta.org")
(IRCnet nil)
(IRCSoulZ "ircsoulz.net")
(IRCSul "wnet.com.br")
(IrcTalk "irctalk.net")
(Irctoo "irctoo.net")
(IRCtown "irc.irctown.net")
(IRCworld "ircworld.org")
(ircXtreme "ircXtreme.net")
(Israelnet "israel.net")
(K0wNet "k0w.net")
(KDFSnet "kdfs.net")
(Kemik "kemik.net")
(Kewl\.Org "kewl.org")
(Kickchat "kickchat.com")
(KidsWorld "kidsworld.org")
(Knightnet "knightnet.net")
(Konfido\.Net "konfido.net")
(Kreynet "krey.net")
(Krono "krono.net")
(Krushnet "krushnet.org")
(LagNet "lagnet.org.za")
(Librenet "librenet.net")
(LinkNet "link-net.org")
(Liquidized "liquidized.net")
(M-IRC "m-sys.org")
(MagicStar "magicstar.net")
(Mavra "mavra.net")
(MediaDriven "mediadriven.com")
(mIRC-X "mircx.com")
(Morat "morat.net")
(MusicCity "musiccity.com")
(Mysteria "mysteria.net")
(Mysterychat "mysterychat.net")
(Mystical "mystical.net")
(Narancs "narancs.com")
(Net-France "net-france.com")
(Nevernet "nevernet.net")
(Newnet "newnet.net")
(Nexusirc "nexusirc.org")
(NightStar "nightstar.net")
(NitrousNet "nitrousnet.net")
(Novernet "novernet.com")
(Nullrouted "nullrouted.org")
(NullusNet "nullus.net")
(OpChat "opchat.org")
(Openprojects "openprojects.net")
(Othernet "othernet.org")
(OtherSide "othersideirc.net")
(Outsiderz "outsiderz.com")
(OzOrg "oz.org")
(Peacefulhaven "peacefulhaven.net")
(PhazedIRC "phazedirc.net")
(Philchat "philchat.net")
(phrozN "phrozn.net")
(PiNet "praetorians.org")
(Pinoycentral "abs-cbn.com")
(Planetarion "planetarion.com")
(POLNet "ircnet.pl")
(Psionics "psionics.net")
(PTirc "ptirc.com.pt")
(PTlink "ptlink.net")
(PTnet "ptnet.org")
(QChat "qchat.net")
(QuakeNet "quakenet.org")
(Realirc "realirc.org")
(RealmNET "realmnet.com")
(Rebelchat "rebelchat.org")
(Red-Latina "red-latina.org")
(RedLatona "redlatona.net")
(Relicnet "relic.net")
(Rezosup "rezosup.org")
(Risanet "risanet.com")
(Rubiks "rubiks.net")
(Rusnet "nil")
(Sandnet "sandnet.net")
(Scunc "scunc.net")
(SerbianCafe "serbiancafe.ws")
(SexNet "sexnet.org")
(ShadowFire "shadowfire.org")
(ShadowWorld "shadowworld.net")
(SkyNet "bronowski.pl")
(SlashNET "slashnet.org")
(SolarStone "solarstone.net")
(Sorcery "sorcery.net")
(SourceIRC "sourceirc.net")
(SpaceTronix "spacetronix.net")
(Spirit-Harmony "spirit-harmony.com")
(StarChat "starchat.net")
(StarEquinox "starequinox.net")
(Starlink "starlink.net")
(starlink-irc "starlink-irc.org")
(StarWars-IRC "starwars-irc.net")
(Stormdancing "stormdancing.net")
(Superchat "superchat.org")
(Sysopnet "sysopnet.org")
(Telstra "telstra.com")
(TR-net "dominet.com.tr")
(Tri-net "tri-net.org")
(TriLink "ft4u.net")
(TurkishChat "turkishchat.org")
(UberNinja "uberninja.net")
(UICN "uicn.net")
(UltraIRC "ultrairc.net")
(UnderChat "underchat.it")
(Undernet "undernet.org")
(UnderZ "underz.org")
(UniChat "irc.uni-chat.net")
(UnionLatina "unionlatina.org")
(Univers "univers.org")
(UnixR "unixr.net")
(Vidgamechat "vidgamechat.com")
(VirtuaNet "virtuanet.org")
(Vitamina "vitamina.ca")
(Voila "voila.fr")
(Wahou "wf-net.org")
(Warpednet "warped.net")
(Weaklinks "weaklinks.net")
(Webnet "webchat.org")
(WinChat "winchat.net")
(WinIRC "winirc.org")
(WorldIRC "worldirc.org")
(WyldRyde "wyldryde.net")
(XentoniX "xentonix.net")
(Xevion "xevion.net")
(XNet "xnet.org")
(XWorld "xworld.org")
(ZAnetNet "zanet.net")
(ZAnetOrg "zanet.org.za")
(ZiRC "zirc.org")
(ZUHnet "zuh.net")
(Zurna "zurna.net"))
"Alist of IRC networks. (NET MATCHER) where
NET is a symbol naming that IRC network and
MATCHER is used to find a corresponding network to a server while connected to
it. If it is regexp, it's used to match against `erc-server-announced-name'.
It can also be a function (predicate). Then it is executed with the
server buffer as current-buffer."
:group 'erc-networks
:type '(repeat
(list :tag "Network"
(symbol :tag "Network name")
(choice :tag "Network's common server ending"
(regexp)
(const :tag "Network has no common server ending" nil)))))
(defvar erc-network nil
"The name of the network you are connected to (a symbol).")
(make-variable-buffer-local 'erc-network)
;; Functions:
;;;###autoload
(defun erc-determine-network ()
"Return the name of the network or \"Unknown\" as a symbol. Use the
server parameter NETWORK if provided, otherwise parse the server name and
search for a match in `erc-networks-alist'."
;; The server made it easy for us and told us the name of the NETWORK
(if (assoc "NETWORK" erc-server-parameters)
(intern (cdr (assoc "NETWORK" erc-server-parameters)))
(or
;; Loop through `erc-networks-alist' looking for a match.
(let ((server (or erc-server-announced-name erc-session-server)))
(loop for (name matcher) in erc-networks-alist
when (and matcher
(string-match (concat matcher "\\'") server))
do (return name)))
'Unknown)))
(defun erc-network ()
"Return the value of `erc-network' for the current server."
(with-current-buffer (erc-server-buffer) erc-network))
(defun erc-current-network ()
"Deprecated. Use `erc-network' instead. Return the name of this server's
network as a symbol."
(with-current-buffer (erc-server-buffer)
(intern (downcase (symbol-name erc-network)))))
(erc-make-obsolete 'erc-current-network 'erc-network
"Obsolete since erc-nets 1.5")
(defun erc-network-name ()
"Returns the name of the current network as a string."
(with-current-buffer (erc-server-buffer) (symbol-name erc-network)))
(defun erc-set-network-name (proc parsed)
"Set `erc-network' to the value returned by `erc-determine-network'."
(unless erc-server-connected
(setq erc-network (erc-determine-network)))
nil)
(defun erc-unset-network-name (nick ip reason)
"Set `erc-network' to nil."
(setq erc-network nil)
nil)
(add-hook 'erc-server-375-functions 'erc-set-network-name)
(add-hook 'erc-server-422-functions 'erc-set-network-name)
(add-hook 'erc-disconnected-hook 'erc-unset-network-name)
(defun erc-ports-list (ports)
"Return a list of PORTS.
PORTS should be a list of either:
A number, in which case it is returned a list.
Or a pair of the form (LOW HIGH), in which case, a list of all the
numbers between LOW and HIGH (inclusive) is returned.
As an example:
(erc-ports-list '(1)) => (1)
(erc-ports-list '((1 5))) => (1 2 3 4 5)
(erc-ports-list '(1 (3 5))) => (1 3 4 5)"
(let (result)
(dolist (p ports)
(cond ((numberp p)
(push p result))
((listp p)
(setq result (nconc (loop for i from (cadr p) downto (car p)
collect i)
result)))))
(nreverse result)))
;;;###autoload
(defun erc-server-select ()
"Interactively select a server to connect to using `erc-server-alist'."
(interactive)
(let* ((completion-ignore-case t)
(net (intern
(completing-read "Network: "
(erc-delete-dups
(mapcar (lambda (x)
(list (symbol-name (nth 1 x))))
erc-server-alist)))))
(srv (assoc
(completing-read "Server: "
(delq nil
(mapcar (lambda (x)
(when (equal (nth 1 x) net)
x))
erc-server-alist)))
erc-server-alist))
(host (nth 2 srv))
(ports (if (listp (nth 3 srv))
(erc-ports-list (nth 3 srv))
(list (nth 3 srv))))
(port (nth (random (length ports)) ports)))
(erc host port erc-nick erc-user-full-name t)))
;;; The following experimental
;; It does not work yet, help me with it if you
;; think it is worth the effort.
(defvar erc-settings
'((pals freenode ("kensanata" "shapr" "anti\\(fuchs\\|gone\\)"))
(format-nick-function (freenode "#emacs") erc-format-@nick))
"Experimental: Alist of configuration options.
The format is (VARNAME SCOPE VALUE) where
VARNAME is a symbol identifying the configuration option,
SCOPE is either a symbol which identifies an entry from
`erc-networks-alist' or a list (NET TARGET) where NET is a network symbol and
TARGET is a string identifying the channel/query target.
VALUE is the options value.")
(defun erc-get (var &optional net target)
(let ((items erc-settings)
elt val)
(while items
(setq elt (car items)
items (cdr items))
(when (eq (car elt) var)
(cond ((and net target (listp (nth 1 elt))
(eq net (car (nth 1 elt)))
(string-equal target (nth 1 (nth 1 elt))))
(setq val (nth 2 elt)
items nil))
((and net (eq net (nth 1 elt)))
(setq val (nth 2 elt)
items nil))
((and (not net) (not target) (not (nth 1 elt)))
(setq val (nth 2 elt)
items nil)))))
val))
(erc-get 'pals 'freenode)
(provide 'erc-nets)
;;; erc-nets.el ends here
;;
;; Local Variables:
;; indent-tabs-mode: t
;; tab-width: 8
;; End:
;; arch-tag: 68cccabd-f66b-456c-9abe-5f993a2dc91c

212
lisp/erc/erc-netsplit.el Normal file
View file

@ -0,0 +1,212 @@
;;; erc-netsplit.el --- Reduce JOIN/QUIT messages on netsplits
;; Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@delysid.org>
;; Keywords: comm
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; This module hides quit/join messages if a netsplit occurs.
;; To enable, add the following to your ~/.emacs:
;; (require 'erc-netsplit)
;; (erc-netsplit-mode 1)
;;; Code:
(require 'erc)
(eval-when-compile (require 'cl))
(defgroup erc-netsplit nil
"Netsplit detection tries to automatically figure when a
netsplit happens, and filters the QUIT messages. It also keeps
track of netsplits, so that it can filter the JOIN messages on a netjoin too."
:group 'erc)
;;;###autoload (autoload 'erc-netsplit-mode "erc-netsplit")
(define-erc-module netsplit nil
"This mode hides quit/join messages if a netsplit occurs."
((erc-netsplit-install-message-catalogs)
(add-hook 'erc-server-JOIN-functions 'erc-netsplit-JOIN)
(add-hook 'erc-server-MODE-functions 'erc-netsplit-MODE)
(add-hook 'erc-server-QUIT-functions 'erc-netsplit-QUIT)
(add-hook 'erc-timer-hook 'erc-netsplit-timer))
((remove-hook 'erc-server-JOIN-functions 'erc-netsplit-JOIN)
(remove-hook 'erc-server-MODE-functions 'erc-netsplit-MODE)
(remove-hook 'erc-server-QUIT-functions 'erc-netsplit-QUIT)
(remove-hook 'erc-timer-hook 'erc-netsplit-timer)))
(defcustom erc-netsplit-show-server-mode-changes-flag nil
"Set to t to enable display of server mode changes."
:group 'erc-netsplit
:type 'boolean)
(defcustom erc-netsplit-debug nil
"If non-nil, debug messages will be shown in the
sever buffer."
:group 'erc-netsplit
:type 'boolean)
(defcustom erc-netsplit-regexp "^[^ @!\"]+\\.[^ @!]+ [^ @!]+\\.[^ @!\"]+$"
"This regular expression should match quit reasons produced
by netsplits."
:group 'erc-netsplit
:type 'regexp)
(defcustom erc-netsplit-hook nil
"Run whenever a netsplit is detected the first time.
Args: PROC is the process the netsplit originated from and
SPLIT is the netsplit (e.g. \"server.name.1 server.name.2\")."
:group 'erc-hooks
:type 'hook)
(defcustom erc-netjoin-hook nil
"Run whenever a netjoin is detected the first time.
Args: PROC is the process the netjoin originated from and
SPLIT is the netsplit (e.g. \"server.name.1 server.name.2\")."
:group 'erc-hooks
:type 'hook)
(defvar erc-netsplit-list nil
"This is a list of the form
\((\"a.b.c.d e.f.g\" TIMESTAMP FIRST-JOIN \"nick1\" ... \"nickn\") ...)
where FIRST-JOIN is t or nil, depending on whether or not the first
join from that split has been detected or not.")
(make-variable-buffer-local 'erc-netsplit-list)
(defun erc-netsplit-install-message-catalogs ()
(erc-define-catalog
'english
'((netsplit . "netsplit: %s")
(netjoin . "netjoin: %s, %N were split")
(netjoin-done . "netjoin: All lost souls are back!")
(netsplit-none . "No netsplits in progress")
(netsplit-wholeft . "split: %s missing: %n %t"))))
(defun erc-netsplit-JOIN (proc parsed)
"Show/don't show rejoins."
(let ((nick (erc-response.sender parsed))
(no-next-hook nil))
(dolist (elt erc-netsplit-list)
(if (member nick (nthcdr 3 elt))
(progn
(if (not (caddr elt))
(progn
(erc-display-message
parsed 'notice (process-buffer proc)
'netjoin ?s (car elt) ?N (length (nthcdr 3 elt)))
(setcar (nthcdr 2 elt) t)
(run-hook-with-args 'erc-netjoin-hook proc (car elt))))
;; need to remove this nick, perhaps the whole entry here.
;; Note that by removing the nick now, we can't tell if further
;; join messages (for other channels) should also be
;; suppressed.
(if (null (nthcdr 4 elt))
(progn
(erc-display-message
parsed 'notice (process-buffer proc)
'netjoin-done ?s (car elt))
(setq erc-netsplit-list (delq elt erc-netsplit-list)))
(delete nick elt))
(setq no-next-hook t))))
no-next-hook))
(defun erc-netsplit-MODE (proc parsed)
"Hide mode changes from servers."
;; regexp matches things with a . in them, and no ! or @ in them.
(when (string-match "^[^@!]+\\.[^@!]+$" (erc-response.sender parsed))
(and erc-netsplit-debug
(erc-display-message
parsed 'notice (process-buffer proc)
"[debug] server mode change."))
(not erc-netsplit-show-server-mode-changes-flag)))
(defun erc-netsplit-QUIT (proc parsed)
"Detect netsplits."
(let ((split (erc-response.contents parsed))
(nick (erc-response.sender parsed))
ass)
(when (string-match erc-netsplit-regexp split)
(setq ass (assoc split erc-netsplit-list))
(if ass
;; element for this netsplit exists already
(progn
(setcdr (nthcdr 2 ass) (cons nick (nthcdr 3 ass)))
(when (caddr ass)
;; There was already a netjoin for this netsplit, it
;; seems like the old one didn't get finished...
(erc-display-message
parsed 'notice (process-buffer proc)
'netsplit ?s split)
(setcar (nthcdr 2 ass) t)
(run-hook-with-args 'erc-netsplit-hook proc split)))
;; element for this netsplit does not yet exist
(setq erc-netsplit-list
(cons (list split
(erc-current-time)
nil
nick)
erc-netsplit-list))
(erc-display-message
parsed 'notice (process-buffer proc)
'netsplit ?s split)
(run-hook-with-args 'erc-netsplit-hook proc split))
t)))
(defun erc-netsplit-timer (now)
"Clean cruft from `erc-netsplit-list' older than 10 minutes."
(dolist (elt erc-netsplit-list)
(when (> (erc-time-diff (cadr elt) now) 600)
(when erc-netsplit-debug
(erc-display-message
nil 'notice (current-buffer)
(concat "Netsplit: Removing " (car elt))))
(setq erc-netsplit-list (delq elt erc-netsplit-list)))))
;;;###autoload
(defun erc-cmd-WHOLEFT ()
"Show who's gone."
(with-current-buffer (erc-server-buffer)
(if (null erc-netsplit-list)
(erc-display-message
nil 'notice 'active
'netsplit-none)
(dolist (elt erc-netsplit-list)
(erc-display-message
nil 'notice 'active
'netsplit-wholeft ?s (car elt)
?n (mapconcat 'erc-extract-nick (nthcdr 3 elt) " ")
?t (if (caddr elt)
"(joining)"
"")))))
t)
(defalias 'erc-cmd-WL 'erc-cmd-WHOLEFT)
(provide 'erc-netsplit)
;;; erc-netsplit.el ends here
;;
;; Local Variables:
;; indent-tabs-mode: t
;; tab-width: 8
;; End:
;; arch-tag: 61a85cb0-7e7b-4312-a4f6-313c7a25a6e8

411
lisp/erc/erc-nicklist.el Normal file
View file

@ -0,0 +1,411 @@
;;; erc-nicklist.el --- Display channel nicknames in a side buffer.
;; Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
;; Filename: erc-nicklist.el
;; Author: Lawrence Mitchell <wence@gmx.li>
;; Created: 2004-04-30
;; Keywords: IRC chat client Internet
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;;
;; This provides a minimal mIRC style nicklist buffer for ERC. To
;; activate, do M-x erc-nicklist RET in the channel buffer you want
;; the nicklist to appear for. To close and quit the nicklist
;; buffer, do M-x erc-nicklist-quit RET.
;;
;; TODO:
;; o Somehow associate nicklist windows with channel windows so they
;; appear together, and if one gets buried, then the other does.
;;
;; o Make "Query" and "Message" work.
;;
;; o Prettify the actual list of nicks in some way.
;;
;; o Add a proper erc-module that people can turn on and off, figure
;; out a way of creating the nicklist window at an appropriate time
;; --- probably in `erc-join-hook'.
;;
;; o Ensure XEmacs compatibility --- the mouse-menu support is likely
;; broken.
;;
;; o Add option to display in a separate frame --- will again need to
;; be able to associate the nicklist with the currently active
;; channel buffer or something similar.
;;
;; o Allow toggling of visibility of nicklist via ERC commands.
;;; History:
;;
;; Changes by Edgar Gonçalves <edgar.goncalves@inesc-id.pt>
;; Jun 25 2005:
;; - images are changed to a standard set of names.
;; - /images now contain gaim's status icons.
;; May 31 2005:
;; - tooltips are improved. they try to access bbdb for a nice nick!
;; Apr 26 2005:
;; - erc-nicklist-channel-users-info was fixed (sorting bug)
;; - Away names don't need parenthesis when using icons
;; Apr 26 2005:
;; - nicks can display icons of their connection type (msn, icq, for now)
;; Mar 15 2005:
;; - nicks now are different for unvoiced and op users
;; - nicks now have tooltips displaying more info
;; Mar 18 2005:
;; - queries now work ok, both on menu and keyb shortcut RET.
;; - nicklist is now sorted ignoring the case. Voiced nicks will
;; appear according to `erc-nicklist-voiced-position'.
;;; Code:
(require 'erc)
(condition-case nil
(require 'erc-bbdb)
(error nil))
(eval-when-compile (require 'cl))
(defgroup erc-nicklist nil
"Display a list of nicknames in a separate window."
:group 'erc)
(defcustom erc-nicklist-use-icons t
"*If non-nil, display an icon instead of the name of the chat medium.
By \"chat medium\", we mean IRC, AOL, MSN, ICQ, etc."
:group 'erc-nicklist
:type 'boolean)
(defcustom erc-nicklist-icons-directory
(concat default-directory "images/")
"*Directory of the PNG files for chat icons.
Icons are displayed if `erc-nicklist-use-icons' is non-nil."
:group 'erc-nicklist
:type 'string)
(defcustom erc-nicklist-voiced-position 'bottom
"*Position of voiced nicks in the nicklist.
The value can be `top', `bottom' or nil (don't sort)."
:group 'erc-nicklist
:type '(choice
(const :tag "Top" 'top)
(const :tag "Bottom" 'bottom)
(const :tag "Mixed" nil)))
(defcustom erc-nicklist-window-size 20.0
"*The size of the nicklist window.
This specifies a percentage of the channel window width.
A negative value means the nicklist window appears on the left of the
channel window, and vice versa."
:group 'erc-nicklist
:type 'float)
(defun erc-nicklist-buffer-name (&optional buffer)
"Return the buffer name for a nicklist associated with BUFFER.
If BUFFER is nil, use the value of `current-buffer'."
(format " *%s-nicklist*" (buffer-name (or buffer (current-buffer)))))
(defun erc-nicklist-make-window ()
"Create an ERC nicklist window.
See also `erc-nicklist-window-size'."
(let ((width (floor (* (window-width) (/ erc-nicklist-window-size 100.0))))
(buffer (erc-nicklist-buffer-name))
window)
(split-window-horizontally (- width))
(setq window (next-window))
(set-window-buffer window (get-buffer-create buffer))
(with-current-buffer buffer
(set-window-dedicated-p window t))))
(defvar erc-nicklist-images-alist '()
"Alist that maps a connection type to an icon.")
(defun erc-nicklist-insert-medium-name-or-icon (host channel is-away)
"Inserts an icon or a string identifying the current host type.
This is configured using `erc-nicklist-use-icons' and
`erc-nicklist-icons-directory'."
;; identify the network (for bitlebee usage):
(let ((bitlbee-p (save-match-data
(string-match "\\`&bitlbee\\b"
(buffer-name channel)))))
(cond ((and bitlbee-p
(string= "login.icq.com" host))
(if erc-nicklist-use-icons
(if is-away
(insert-image (cdr (assoc 'icq-away
erc-nicklist-images-alist)))
(insert-image (cdr (assoc 'icq
erc-nicklist-images-alist))))
(insert "ICQ")))
(bitlbee-p
(if erc-nicklist-use-icons
(if is-away
(insert-image (cdr (assoc 'msn-away
erc-nicklist-images-alist)))
(insert-image (cdr (assoc 'msn
erc-nicklist-images-alist))))
(insert "MSN")))
(t
(if erc-nicklist-use-icons
(if is-away
(insert-image (cdr (assoc 'irc-away
erc-nicklist-images-alist)))
(insert-image (cdr (assoc 'irc
erc-nicklist-images-alist))))
(insert "IRC"))))
(insert " ")))
(defun erc-nicklist-search-for-nick (finger-host)
"Return the bitlbee-nick field for this contact given FINGER-HOST.
Seach for the BBDB record of this contact. If not found, return nil."
(when (boundp 'erc-bbdb-bitlbee-name-field)
(let ((record (car
(erc-member-if
#'(lambda (r)
(let ((fingers (bbdb-record-finger-host r)))
(when fingers
(string-match finger-host
(car (bbdb-record-finger-host r))))))
(bbdb-records)))))
(when record
(bbdb-get-field record erc-bbdb-bitlbee-name-field)))))
(defun erc-nicklist-insert-contents (channel)
"Insert the nicklist contents, with text properties and the optional images."
(setq buffer-read-only nil)
(erase-buffer)
(dolist (u (erc-nicklist-channel-users-info channel))
(let* ((server-user (car u))
(channel-user (cdr u))
(nick (erc-server-user-nickname server-user))
(host (erc-server-user-host server-user))
(login (erc-server-user-login server-user))
(full-name(erc-server-user-full-name server-user))
(info (erc-server-user-info server-user))
(channels (erc-server-user-buffers server-user))
(op (erc-channel-user-op channel-user))
(voice (erc-channel-user-voice channel-user))
(bbdb-nick (erc-nicklist-search-for-nick (concat login "@" host)))
(away-status (if voice "" "\n(Away)"))
(balloon-text (concat bbdb-nick (if (string= "" bbdb-nick)
"" "\n")
"Login: " login "@" host
away-status)))
(erc-nicklist-insert-medium-name-or-icon host channel (not voice))
(unless (or voice erc-nicklist-use-icons)
(setq nick (concat "(" nick ")")))
(when op
(setq nick (concat nick " (OP)")))
(insert (erc-propertize nick
'erc-nicklist-nick nick
'mouse-face 'highlight
'erc-nicklist-channel channel
'help-echo balloon-text)
"\n")))
(erc-nicklist-mode))
(defun erc-nicklist ()
"Create an ERC nicklist buffer."
(interactive)
(let ((channel (current-buffer)))
(unless (or (not erc-nicklist-use-icons)
erc-nicklist-images-alist)
(setq erc-nicklist-images-alist
`((msn . ,(create-image (concat erc-nicklist-icons-directory
"msn-online.png")))
(msn-away . ,(create-image (concat erc-nicklist-icons-directory
"msn-offline.png")))
(irc . ,(create-image (concat erc-nicklist-icons-directory
"irc-online.png")))
(irc-away . ,(create-image (concat erc-nicklist-icons-directory
"irc-offline.png")))
(icq . ,(create-image (concat erc-nicklist-icons-directory
"icq-online.png")))
(icq-away . ,(create-image (concat erc-nicklist-icons-directory
"icq-offline.png"))))))
(erc-nicklist-make-window)
(with-current-buffer (get-buffer (erc-nicklist-buffer-name channel))
(erc-nicklist-insert-contents channel)))
(add-hook 'erc-channel-members-changed-hook #'erc-nicklist-update))
(defun erc-nicklist-update ()
"Update the ERC nicklist buffer."
(let ((b (get-buffer (erc-nicklist-buffer-name)))
(channel (current-buffer)))
(when b
(with-current-buffer b
(erc-nicklist-insert-contents channel)))))
(defvar erc-nicklist-mode-map
(let ((map (make-sparse-keymap)))
(define-key map (kbd "<down-mouse-3>") 'erc-nicklist-menu)
(define-key map "\C-j" 'erc-nicklist-kbd-menu)
(define-key map "q" 'erc-nicklist-quit)
(define-key map (kbd "RET") 'erc-nicklist-kbd-cmd-QUERY)
map)
"Keymap for `erc-nicklist-mode'.")
(define-derived-mode erc-nicklist-mode fundamental-mode
"Nicklist"
"Major mode for the ERC nicklist buffer."
(setq buffer-read-only t))
(defun erc-nicklist-call-erc-command (command point buffer window)
"Call an ERC COMMAND.
Depending on what COMMAND is, it's called with one of POINT, BUFFER,
or WINDOW as arguments."
(when command
(let* ((p (text-properties-at point))
(b (plist-get p 'erc-nicklist-channel)))
(if (memq command '(erc-nicklist-quit ignore))
(funcall command window)
;; EEEK! Horrble, but it's the only way we can ensure the
;; response goes to the correct buffer.
(erc-set-active-buffer b)
(switch-to-buffer-other-window b)
(funcall command (plist-get p 'erc-nicklist-nick))))))
(defun erc-nicklist-cmd-QUERY (user &optional server)
"Opens a query buffer with USER."
;; FIXME: find a way to switch to that buffer afterwards...
(let ((send (if server
(format "QUERY %s %s" user server)
(format "QUERY %s" user))))
(erc-cmd-QUERY user)
t))
(defun erc-nicklist-kbd-cmd-QUERY (&optional window)
(interactive)
(let* ((p (text-properties-at (point)))
(server (plist-get p 'erc-nicklist-channel))
(nick (plist-get p 'erc-nicklist-nick))
(nick (or (and (string-match "(\\(.*\\))" nick)
(match-string 1 nick))
nick))
(nick (or (and (string-match "\\+\\(.*\\)" nick)
(match-string 1 nick))
nick))
(send (format "QUERY %s %s" nick server)))
(switch-to-buffer-other-window server)
(erc-cmd-QUERY nick)))
(defvar erc-nicklist-menu
(let ((map (make-sparse-keymap "Action")))
(define-key map [erc-cmd-WHOIS]
'("Whois" . erc-cmd-WHOIS))
(define-key map [erc-cmd-DEOP]
'("Deop" . erc-cmd-DEOP))
(define-key map [erc-cmd-MSG]
'("Message" . erc-cmd-MSG)) ;; TODO!
(define-key map [erc-nicklist-cmd-QUERY]
'("Query" . erc-nicklist-kbd-cmd-QUERY))
(define-key map [ignore]
'("Cancel" . ignore))
(define-key map [erc-nicklist-quit]
'("Close nicklist" . erc-nicklist-quit))
map)
"Menu keymap for the ERC nicklist.")
(defun erc-nicklist-quit (&optional window)
"Delete the ERC nicklist.
Deletes WINDOW and stops updating the nicklist buffer."
(interactive)
(let ((b (window-buffer window)))
(with-current-buffer b
(set-buffer-modified-p nil)
(kill-this-buffer)
(remove-hook 'erc-channel-members-changed-hook 'erc-nicklist-update))))
(defun erc-nicklist-kbd-menu ()
"Show the ERC nicklist menu."
(interactive)
(let* ((point (point))
(window (selected-window))
(buffer (current-buffer)))
(with-current-buffer buffer
(erc-nicklist-call-erc-command
(car (x-popup-menu point
erc-nicklist-menu))
point
buffer
window))))
(defun erc-nicklist-menu (&optional arg)
"Show the ERC nicklist menu.
ARG is a parametrized event (see `interactive')."
(interactive "e")
(let* ((point (nth 1 (cadr arg)))
(window (car (cadr arg)))
(buffer (window-buffer window)))
(with-current-buffer buffer
(erc-nicklist-call-erc-command
(car (x-popup-menu arg
erc-nicklist-menu))
point
buffer
window))))
(defun erc-nicklist-channel-users-info (channel)
"Return a nick-sorted list of all users on CHANNEL.
Result are elements in the form (SERVER-USER . CHANNEL-USER). The
list has all the voiced users according to
`erc-nicklist-voiced-position'."
(let* ((nicks (erc-sort-channel-users-alphabetically
(with-current-buffer channel (erc-get-channel-user-list)))))
(if erc-nicklist-voiced-position
(let ((voiced-nicks (erc-remove-if-not
#'(lambda (x)
(null (erc-channel-user-voice (cdr x))))
nicks))
(devoiced-nicks (erc-remove-if-not
#'(lambda (x)
(erc-channel-user-voice
(cdr x)))
nicks)))
(cond ((eq erc-nicklist-voiced-position 'top)
(append devoiced-nicks voiced-nicks))
((eq erc-nicklist-voiced-position 'bottom)
(append voiced-nicks devoiced-nicks))))
nicks)))
(provide 'erc-nicklist)
;;; erc-nicklist.el ends here
;;
;; Local Variables:
;; indent-tabs-mode: t
;; tab-width: 8
;; End:
;; arch-tag: db37a256-87a7-4544-bd90-e5f16c9f5ca5

337
lisp/erc/erc-nickserv.el Normal file
View file

@ -0,0 +1,337 @@
;;; erc-nickserv.el --- Identify to NickServ
;; Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; There are two ways to go about identifying yourself automatically to
;; NickServ with this module. The more secure way is to listen for identify
;; requests from the user NickServ. Another way is to identify yourself to
;; NickServ directly after a successful connection and every time you change
;; your nickname. This method is rather insecure, though, because no checks
;; are made to test if NickServ is the real NickServ for a given network or
;; server.
;; As a default, ERC has the data for the official nickname services on the
;; networks Austnet, BrasNET, Dalnet, freenode, GalaxyNet, and Slashnet.
;; You can add more by using M-x customize-variable RET erc-nickserv-alist.
;; Usage:
;;
;; Put into your .emacs:
;;
;; (require 'erc-nickserv)
;; (erc-services-mode 1)
;;
;; Add your nickname and NickServ password to `erc-nickserv-passwords'.
;; Using the freenode network as an example:
;;
;; (setq erc-nickserv-passwords '((freenode (("nickname" "password")))))
;;
;; The default automatic identification mode is autodetection of NickServ
;; identify requests. Set the variable `erc-nickserv-identify-mode' if
;; you'd like to change this behavior. You can also change the way
;; automatic identification is handled by using:
;;
;; M-x erc-nickserv-identify-mode
;;
;; If you'd rather not identify yourself automatically but would like access
;; to the functions contained in this file, just load this file without
;; enabling `erc-services-mode'.
;;
;;; Code:
(require 'erc)
(require 'erc-nets)
(eval-when-compile (require 'cl))
;; Customization:
(defgroup erc-services nil
"Configuration for IRC services.
On some networks, there exists a special type of automated irc bot,
called Services. Those usually allow you to register your nickname,
post/read memos to other registered users who are currently offline,
and do various other things.
This group allows you to set variables to somewhat automate
communication with those Services."
:group 'erc)
;;;###autoload (autoload 'erc-services-mode "erc-nickserv" nil t)
(define-erc-module services nickserv
"This mode automates communication with services."
((erc-nickserv-identify-mode erc-nickserv-identify-mode))
((remove-hook 'erc-server-NOTICE-functions
'erc-nickserv-identify-autodetect)
(remove-hook 'erc-after-connect
'erc-nickserv-identify-on-connect)
(remove-hook 'erc-nick-changed-functions
'erc-nickserv-identify-on-nick-change)))
;;;###autoload
(defun erc-nickserv-identify-mode (mode)
"Set up hooks according to which MODE the user has chosen."
(interactive
(list (intern (completing-read
"Choose Nickserv identify mode (RET to disable): "
'(("autodetect") ("nick-change")) nil t))))
(cond ((eq mode 'autodetect)
(setq erc-nickserv-identify-mode 'autodetect)
(add-hook 'erc-server-NOTICE-functions
'erc-nickserv-identify-autodetect)
(remove-hook 'erc-nick-changed-functions
'erc-nickserv-identify-on-nick-change)
(remove-hook 'erc-after-connect
'erc-nickserv-identify-on-connect))
((eq mode 'nick-change)
(setq erc-nickserv-identify-mode 'nick-change)
(add-hook 'erc-after-connect
'erc-nickserv-identify-on-connect)
(add-hook 'erc-nick-changed-functions
'erc-nickserv-identify-on-nick-change)
(remove-hook 'erc-server-NOTICE-functions
'erc-nickserv-identify-autodetect))
(t
(setq erc-nickserv-identify-mode nil)
(remove-hook 'erc-server-NOTICE-functions
'erc-nickserv-identify-autodetect)
(remove-hook 'erc-after-connect
'erc-nickserv-identify-on-connect)
(remove-hook 'erc-nick-changed-functions
'erc-nickserv-identify-on-nick-change))))
(defcustom erc-nickserv-identify-mode 'autodetect
"The mode which is used when identifying to Nickserv.
Possible settings are:.
'autodetect - Identify when the real Nickserv sends an identify request.
'nick-change - Identify when you change your nickname.
nil - Disables automatic Nickserv identification.
You can also use M-x erc-nickserv-identify-mode to change modes."
:group 'erc-services
:type '(choice (const autodetect)
(const nick-change)
(const nil))
:set (lambda (sym val)
(set-default sym val)
(erc-nickserv-identify-mode val)))
(defcustom erc-prompt-for-nickserv-password t
"Ask for the password when identifying to NickServ."
:group 'erc-services
:type 'boolean)
(defcustom erc-nickserv-passwords nil
"Passwords used when identifying to NickServ automatically.
Example of use:
(setq erc-nickserv-passwords
'((freenode ((\"nick-one\" . \"password\")
(\"nick-two\" . \"password\")))
(DALnet ((\"nick\" . \"password\")))))"
:group 'erc-services
:type '(repeat
(list :tag "Network"
(choice :tag "Network name"
(const freenode)
(const DALnet)
(const GalaxyNet)
(const SlashNET)
(const BRASnet)
(const iip)
(const Austnet)
(symbol :tag "Network name"))
(repeat :tag "Nickname and password"
(cons :tag "Identity"
(string :tag "Nick")
(string :tag "Password"))))))
;; Variables:
(defcustom erc-nickserv-alist
'((DALnet
"NickServ!service@dal.net"
"/msg\\s-NickServ@services.dal.net\\s-IDENTIFY\\s-<password>"
"NickServ@services.dal.net"
"IDENTIFY"
nil)
(freenode
"NickServ!NickServ@services."
"/msg\\s-NickServ\\s-IDENTIFY\\s-<password>"
"NickServ"
"IDENTIFY"
nil)
(GalaxyNet
"NS!nickserv@galaxynet.org"
"Please\\s-change\\s-nicks\\s-or\\s-authenticate."
"NS@services.galaxynet.org"
"AUTH"
t)
(SlashNET
"NickServ!services@services.slashnet.org"
"/msg\\s-NickServ\\s-IDENTIFY\\s-password"
"NickServ@services.slashnet.org"
"IDENTIFY"
nil)
(iip
"Trent@anon.iip"
"type\\s-/squery\\s-Trent\\s-identify\\s-<password>"
"Trent@anon.iip"
"IDENTIFY"
nil
"SQUERY")
(BRASnet
"NickServ!services@brasnet.org"
"/NickServ\\s-IDENTIFY\\s-senha"
"NickServ"
"IDENTIFY"
nil
"")
(Austnet
"NickOP!service@austnet.org"
"/msg\\s-NickOP@austnet.org\\s-identify\\s-<password>"
"nickop@austnet.org"
"identify"
nil)
(Azzurra
"NickServ!service@azzurra.org"
"/ns\\s-IDENTIFY\\s-password"
"NickServ"
"IDENTIFY"
nil)
(OFTC
"NickServ!services@services.oftc.net"
"/msg\\s-NickServ\\s-IDENTIFY\\s-\^_password"
"NickServ"
"IDENTIFY"
nil))
"Alist of NickServer details, sorted by network.
Every element in the list has the form
\(SYMBOL NICKSERV REGEXP NICK KEYWORD USE-CURRENT ANSWER)
SYMBOL is a network identifier, a symbol, as used in `erc-networks-alist'.
NICKSERV is the description of the nickserv in the form nick!user@host.
REGEXP is a regular expression matching the message from nickserv.
NICK is nickserv's nickname. Use nick@server where necessary/possible.
KEYWORD is the keyword to use in the reply message to identify yourself.
USE-CURRENT indicates whether the current nickname must be used when
identifying.
ANSWER is the command to use for the answer. The default is 'privmsg.
This last element is optional."
:group 'erc-services
:type '(repeat
(list :tag "Nickserv data"
(symbol :tag "Network name")
(string :tag "Nickserv's nick!user@host")
(regexp :tag "Identify request sent by Nickserv")
(string :tag "Identify to")
(string :tag "Identify keyword")
(boolean :tag "Use current nick in identify message?")
(choice :tag "Command to use (optional)"
(string :tag "Command")
(const :tag "No special command necessary" nil)))))
;; Functions:
(defun erc-nickserv-identify-autodetect (proc parsed)
"Check for a NickServ identify request everytime a notice is received.
Make sure it is the real NickServ for this network and that it has
specifically asked the user to IDENTIFY.
If `erc-prompt-for-nickserv-password' is non-nil, prompt the user for the
password for this nickname, otherwise try to send it automatically."
(unless (and (null erc-nickserv-passwords)
(null erc-prompt-for-nickserv-password))
(let* ((network (erc-network))
(nickserv (nth 1 (assoc network erc-nickserv-alist)))
(identify-regex (nth 2 (assoc network erc-nickserv-alist)))
(sspec (erc-response.sender parsed))
(nick (car (erc-response.command-args parsed)))
(msg (erc-response.contents parsed)))
;; continue only if we're sure it's the real nickserv for this network
;; and it's asked us to identify
(when (and nickserv (equal sspec nickserv)
(string-match identify-regex msg))
(erc-log "NickServ IDENTIFY request detected")
(erc-nickserv-call-identify-function nick)
nil))))
(defun erc-nickserv-identify-on-connect (server nick)
"Identify to Nickserv after the connection to the server is established."
(unless (and (null erc-nickserv-passwords)
(null erc-prompt-for-nickserv-password))
(erc-nickserv-call-identify-function nick)))
(defun erc-nickserv-identify-on-nick-change (nick old-nick)
"Identify to Nickserv whenever your nick changes."
(unless (and (null erc-nickserv-passwords)
(null erc-prompt-for-nickserv-password))
(erc-nickserv-call-identify-function nick)))
(defun erc-nickserv-call-identify-function (nickname)
"Call `erc-nickserv-identify' interactively or run it with NICKNAME's
password.
The action is determined by the value of `erc-prompt-for-nickserv-password'."
(if erc-prompt-for-nickserv-password
(call-interactively 'erc-nickserv-identify)
(when erc-nickserv-passwords
(erc-nickserv-identify
(cdr (assoc nickname
(nth 1 (assoc (erc-network)
erc-nickserv-passwords))))))))
;;;###autoload
(defun erc-nickserv-identify (password)
"Send an \"identify <PASSWORD>\" message to NickServ.
When called interactively, read the password using `read-passwd'."
(interactive
(list (read-passwd
(format "NickServ password for %s on %s (RET to cancel): "
(erc-current-nick)
(or (and (erc-network)
(symbol-name (erc-network)))
"Unknown network")))))
(when (and password (not (string= "" password)))
(let* ((erc-auto-discard-away nil)
(network (erc-network))
(nickserv-info (assoc network erc-nickserv-alist))
(nickserv (or (nth 3 nickserv-info) "NickServ"))
(identify-word (or (nth 4 nickserv-info) "IDENTIFY"))
(nick (if (nth 5 nickserv-info)
(concat (erc-current-nick) " ")
""))
(msgtype (or (nth 6 nickserv-info) "PRIVMSG")))
(erc-message msgtype
(concat nickserv " " identify-word " " nick password)))))
(provide 'erc-nickserv)
;;; erc-nickserv.el ends here
;;
;; Local Variables:
;; indent-tabs-mode: t
;; tab-width: 8
;; End:
;; arch-tag: d401c8aa-d938-4255-96a9-3efb64c47e58

254
lisp/erc/erc-notify.el Normal file
View file

@ -0,0 +1,254 @@
;;; erc-notify.el --- Online status change notification
;; Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@lexx.delysid.org>
;; Keywords: comm
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; This module defines a new command, /NOTIFY
;; See the docstring of `erc-cmd-NOTIFY' for details.
;;; Code:
(require 'erc)
(require 'erc-nets)
(eval-when-compile
(require 'cl)
(require 'pcomplete))
;;;; Customizable variables
(defgroup erc-notify nil
"Track online status of certain nicknames."
:group 'erc)
(defcustom erc-notify-list nil
"*List of nicknames you want to be notified about online/offline
status change."
:group 'erc-notify
:type '(repeat string))
(defcustom erc-notify-interval 60
"*Time interval (in seconds) for checking online status of notificated
people."
:group 'erc-notify
:type 'integer)
(defcustom erc-notify-signon-hook nil
"*Hook run after someone on `erc-notify-list' has signed on.
Two arguments are passed to the function, SERVER and NICK, both
strings."
:group 'erc-notify
:type 'hook
:options '(erc-notify-signon))
(defcustom erc-notify-signoff-hook nil
"*Hook run after someone on `erc-notify-list' has signed off.
Two arguments are passed to the function, SERVER and NICK, both
strings."
:group 'erc-notify
:type 'hook
:options '(erc-notify-signoff))
(defun erc-notify-signon (server nick)
(message "%s signed on at %s" nick server))
(defun erc-notify-signoff (server nick)
(message "%s signed off from %s" nick server))
;;;; Internal variables
(defvar erc-last-ison nil
"Last ISON information received through `erc-notify-timer'.")
(make-variable-buffer-local 'erc-last-ison)
(defvar erc-last-ison-time 0
"Last time ISON was sent to the server in `erc-notify-timer'.")
(make-variable-buffer-local 'erc-last-ison-time)
;;;; Setup
(defun erc-notify-install-message-catalogs ()
(erc-define-catalog
'english
'((notify_current . "Notificated people online: %l")
(notify_list . "Current notify list: %l")
(notify_on . "Detected %n on IRC network %m")
(notify_off . "%n has left IRC network %m"))))
;;;###autoload (autoload 'erc-notify-mode "erc-notify" nil t)
(define-erc-module notify nil
"Periodically check for the online status of certain users and report
changes."
((add-hook 'erc-timer-hook 'erc-notify-timer)
(add-hook 'erc-server-JOIN-functions 'erc-notify-JOIN)
(add-hook 'erc-server-NICK-functions 'erc-notify-NICK)
(add-hook 'erc-server-QUIT-functions 'erc-notify-QUIT))
((remove-hook 'erc-timer-hook 'erc-notify-timer)
(remove-hook 'erc-server-JOIN-functions 'erc-notify-JOIN)
(remove-hook 'erc-server-NICK-functions 'erc-notify-NICK)
(remove-hook 'erc-server-QUIT-functions 'erc-notify-QUIT)))
;;;; Timer handler
(defun erc-notify-timer (now)
(when (and erc-notify-list
(> (erc-time-diff
erc-last-ison-time now)
erc-notify-interval))
(erc-once-with-server-event
303
'(let* ((server (erc-response.sender parsed))
(ison-list (delete "" (split-string
(erc-response.contents parsed))))
(new-list ison-list)
(old-list (with-current-buffer (erc-server-buffer)
erc-last-ison)))
(while new-list
(when (not (erc-member-ignore-case (car new-list) old-list))
(run-hook-with-args 'erc-notify-signon-hook server (car new-list))
(erc-display-message
parsed 'notice proc
'notify_on ?n (car new-list) ?m (erc-network-name)))
(setq new-list (cdr new-list)))
(while old-list
(when (not (erc-member-ignore-case (car old-list) ison-list))
(run-hook-with-args 'erc-notify-signoff-hook server (car old-list))
(erc-display-message
parsed 'notice proc
'notify_off ?n (car old-list) ?m (erc-network-name)))
(setq old-list (cdr old-list)))
(setq erc-last-ison ison-list)
t))
(erc-server-send
(concat "ISON " (mapconcat 'identity erc-notify-list " ")))
(setq erc-last-ison-time now)))
(defun erc-notify-JOIN (proc parsed)
"Check if channel joiner is on `erc-notify-list' and not on `erc-last-ison'.
If this condition is satisfied, produce a notify_on message and add the nick
to `erc-last-ison' to prevent any further notifications."
(let ((nick (erc-extract-nick (erc-response.sender parsed))))
(when (and (erc-member-ignore-case nick erc-notify-list)
(not (erc-member-ignore-case nick erc-last-ison)))
(add-to-list 'erc-last-ison nick)
(run-hook-with-args 'erc-notify-signon-hook
(or erc-server-announced-name erc-session-server)
nick)
(erc-display-message
parsed 'notice proc
'notify_on ?n nick ?m (erc-network-name)))
nil))
(defun erc-notify-NICK (proc parsed)
"Check if new nick is on `erc-notify-list' and not on `erc-last-ison'.
If this condition is satisfied, produce a notify_on message and add the nick
to `erc-last-ison' to prevent any further notifications."
(let ((nick (erc-response.contents parsed)))
(when (and (erc-member-ignore-case nick erc-notify-list)
(not (erc-member-ignore-case nick erc-last-ison)))
(add-to-list 'erc-last-ison nick)
(run-hook-with-args 'erc-notify-signon-hook
(or erc-server-announced-name erc-session-server)
nick)
(erc-display-message
parsed 'notice proc
'notify_on ?n nick ?m (erc-network-name)))
nil))
(defun erc-notify-QUIT (proc parsed)
"Check if quitter is on `erc-notify-list' and on `erc-last-ison'.
If this condition is satisfied, produce a notify_off message and remove the
nick from `erc-last-ison' to prevent any further notifications."
(let ((nick (erc-extract-nick (erc-response.sender parsed))))
(when (and (erc-member-ignore-case nick erc-notify-list)
(erc-member-ignore-case nick erc-last-ison))
(setq erc-last-ison (erc-delete-if `(lambda (el)
(string= ,(erc-downcase nick)
(erc-downcase el)))
erc-last-ison))
(run-hook-with-args 'erc-notify-signoff-hook
(or erc-server-announced-name erc-session-server)
nick)
(erc-display-message
parsed 'notice proc
'notify_off ?n nick ?m (erc-network-name)))
nil))
;;;; User level command
;;;###autoload
(defun erc-cmd-NOTIFY (&rest args)
"Change `erc-notify-list' or list current notify-list members online.
Without args, list the current list of notificated people online,
with args, toggle notify status of people."
(cond
((null args)
;; Print current notificated people (online)
(let ((ison (with-current-buffer (erc-server-buffer) erc-last-ison)))
(if (not ison)
(erc-display-message
nil 'notice 'active "No ison-list yet!")
(erc-display-message
nil 'notice 'active
'notify_current ?l ison))))
((string= (car args) "-l")
(erc-display-message nil 'notice 'active
'notify_list ?l (mapconcat 'identity erc-notify-list
" ")))
(t
(while args
(if (erc-member-ignore-case (car args) erc-notify-list)
(progn
(setq erc-notify-list (delete (car args) erc-notify-list))
;; Remove the nick from the value of erc-last-ison in
;; every server buffer. This prevents seeing a signoff
;; notification for a nick that you have just _removed_
;; from your notify list.
(dolist (buf (erc-buffer-list))
(with-current-buffer buf
(if (erc-server-buffer-p)
(setq erc-last-ison (delete (car args) erc-last-ison))))))
(setq erc-notify-list (cons (erc-string-no-properties (car args))
erc-notify-list)))
(setq args (cdr args)))
(erc-display-message
nil 'notice 'active
'notify_list ?l (mapconcat 'identity erc-notify-list " "))))
t)
;;;###autoload
(defun pcomplete/erc-mode/NOTIFY ()
(pcomplete-here (pcomplete-erc-all-nicks)))
(erc-notify-install-message-catalogs)
(provide 'erc-notify)
;;; erc-notify.el ends here
;;
;; Local Variables:
;; indent-tabs-mode: t
;; tab-width: 8
;; End:
;; arch-tag: 0fb19dd0-1359-458a-89b7-81dc195a588e

108
lisp/erc/erc-page.el Normal file
View file

@ -0,0 +1,108 @@
;; erc-page.el - CTCP PAGE support for ERC
;; Copyright (C) 2002, 2004 Free Software Foundation
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; Requiring this file will make ERC react to CTCP PAGE messages
;; received, and it will provide a new /PAGE command to send such
;; messages yourself. To enable it, customize the variable
;; `erc-page-mode'.
;;; Code:
(require 'erc)
;;;###autoload (autoload 'erc-page-mode "erc-page")
(define-erc-module page ctcp-page
"Process CTCP PAGE requests from IRC."
nil nil)
(erc-define-catalog-entry 'english 'CTCP-PAGE "Page from %n (%u@%h): %m")
(defgroup erc-page nil
"React to CTCP PAGE messages."
:group 'erc)
(defcustom erc-page-function nil
"A function to process a \"page\" request.
If nil, this prints the page message in the minibuffer and calls
`beep'. If non-nil, it must be a function that takes two arguments:
SENDER and MSG, both strings.
Example for your ~/.emacs file:
\(setq erc-page-function
(lambda (sender msg)
(play-sound-file \"/home/alex/elisp/erc/sounds/ni.wav\")
(message \"IRC Page from %s: %s\" sender msg)))"
:group 'erc-page
:type '(choice (const nil)
(function)))
(defcustom erc-ctcp-query-PAGE-hook '(erc-ctcp-query-PAGE)
"List of functions to be called when a CTCP PAGE is received.
This is called from `erc-process-ctcp-query'. The functions are called
with six arguments: PROC NICK LOGIN HOST TO MSG. Note that you can
also set `erc-page-function' to a function, which only gets two arguments,
SENDER and MSG, so that might be easier to use."
:group 'erc-page
:type '(repeat function))
(defun erc-ctcp-query-PAGE (proc nick login host to msg)
"Deal with an CTCP PAGE query, if `erc-page-mode' is non-nil.
This will call `erc-page-function', if defined, or it will just print
a message and `beep'. In addition to that, the page message is also
inserted into the server buffer."
(when (and erc-page-mode
(string-match "PAGE\\(\\s-+.*\\)?$" msg))
(let* ((m (match-string 1 msg))
(page-msg (if m (erc-controls-interpret (substring m 1))
"[no message]"))
text)
(if m (setq m (substring m 1)))
(setq text (erc-format-message 'CTCP-PAGE
?n nick ?u login
?h host ?m page-msg))
(if erc-page-function
(funcall erc-page-function nick page-msg)
;; if no function is defined
(message "%s" text)
(beep))
;; insert text into buffer
(erc-display-message
nil 'notice nil text)))
nil)
(defun erc-cmd-PAGE (line &optional force)
"Send a CTCP page to the user given as the first word in LINE.
The rest of LINE is the message to send. Note that you will only
receive pages if `erc-page-mode' is on."
(when (string-match "^\\s-*\\(\\S-+\\) ?\\(.*\\)" line)
(let ((nick (match-string 1 line))
(msg (match-string 2 line)))
(erc-cmd-CTCP nick "PAGE" msg))))
(put 'erc-cmd-PAGE 'do-not-parse-args t)
(provide 'erc-page)
;; arch-tag: 82fd2e0e-6060-4dd2-9788-8c1411e844de
;;; erc-page.el ends here

275
lisp/erc/erc-pcomplete.el Normal file
View file

@ -0,0 +1,275 @@
;;; erc-pcomplete.el --- Provides programmable completion for ERC
;; Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
;; Author: Sacha Chua <sacha@free.net.ph>
;; Keywords: comm, convenience
;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcCompletion
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; This file replaces erc-complete.el. It provides nick completion
;; for ERC based on pcomplete. If you do not have pcomplete, you may
;; try to use erc-complete.el.
;;
;; To use, (require 'erc-auto) or (require 'erc-pcomplete), then
;; (erc-pcomplete-mode 1)
;;
;; If you want nickname completions ordered such that the most recent
;; speakers are listed first, set
;; `erc-pcomplete-order-nickname-completions' to `t'.
;;
;; See CREDITS for other contributors.
;;
;;; Code:
(require 'pcomplete)
(require 'erc)
(require 'erc-compat)
(require 'time-date)
(eval-when-compile (require 'cl))
(defgroup erc-pcomplete nil
"Programmable completion for ERC"
:group 'erc)
(defcustom erc-pcomplete-nick-postfix ": "
"*When `pcomplete' is used in the first word after the prompt,
add this string to nicks completed."
:group 'erc-pcomplete
:type 'string)
(defcustom erc-pcomplete-order-nickname-completions t
"If t, channel nickname completions will be ordered such that
the most recent speakers are listed first."
:group 'erc-pcomplete
:type 'boolean)
;;;###autoload (autoload 'erc-completion-mode "erc-pcomplete" nil t)
(define-erc-module pcomplete Completion
"In ERC Completion mode, the TAB key does completion whenever possible."
((add-hook 'erc-mode-hook 'pcomplete-erc-setup)
(add-hook 'erc-complete-functions 'erc-pcomplete)
(erc-buffer-list #'pcomplete-erc-setup))
((remove-hook 'erc-mode-hook 'pcomplete-erc-setup)
(remove-hook 'erc-complete-functions 'erc-pcomplete)))
(defun erc-pcomplete ()
"Complete the nick before point."
(interactive)
(when (> (point) (erc-beg-of-input-line))
(let ((last-command (if (eq last-command 'erc-complete-word)
'pcomplete
last-command)))
(call-interactively 'pcomplete))
t))
;;; Setup function
(defun pcomplete-erc-setup ()
"Setup `erc-mode' to use pcomplete."
(set (make-local-variable 'pcomplete-ignore-case)
t)
(set (make-local-variable 'pcomplete-use-paring)
nil)
(set (make-local-variable 'pcomplete-suffix-list)
'(? ?:))
(set (make-local-variable 'pcomplete-parse-arguments-function)
'pcomplete-parse-erc-arguments)
(set (make-local-variable 'pcomplete-command-completion-function)
'pcomplete/erc-mode/complete-command)
(set (make-local-variable 'pcomplete-command-name-function)
'pcomplete-erc-command-name)
(set (make-local-variable 'pcomplete-default-completion-function)
(lambda () (pcomplete-here (pcomplete-erc-nicks)))))
;;; Programmable completion logic
(defun pcomplete/erc-mode/complete-command ()
(pcomplete-here
(append
(pcomplete-erc-commands)
(pcomplete-erc-nicks erc-pcomplete-nick-postfix))))
(defvar erc-pcomplete-ctcp-commands
'("ACTION" "CLIENTINFO" "ECHO" "FINGER" "PING" "TIME" "USERINFO" "VERSION"))
(defun pcomplete/erc-mode/CTCP ()
(pcomplete-here (pcomplete-erc-nicks))
(pcomplete-here erc-pcomplete-ctcp-commands))
(defun pcomplete/erc-mode/CLEARTOPIC ()
(pcomplete-here (pcomplete-erc-channels)))
(defun pcomplete/erc-mode/DEOP ()
(while (pcomplete-here (pcomplete-erc-ops))))
(defun pcomplete/erc-mode/DESCRIBE ()
(pcomplete-here (pcomplete-erc-nicks)))
(defun pcomplete/erc-mode/IDLE ()
(while (pcomplete-here (pcomplete-erc-nicks))))
(defun pcomplete/erc-mode/KICK ()
(pcomplete-here (pcomplete-erc-channels))
(pcomplete-here (pcomplete-erc-nicks)))
(defun pcomplete/erc-mode/LOAD ()
(pcomplete-here (pcomplete-entries)))
(defun pcomplete/erc-mode/MODE ()
(pcomplete-here (pcomplete-erc-channels))
(while (pcomplete-here (pcomplete-erc-nicks))))
(defun pcomplete/erc-mode/ME ()
(while (pcomplete-here (pcomplete-erc-nicks))))
(defun pcomplete/erc-mode/SAY ()
(pcomplete-here (pcomplete-erc-nicks))
(pcomplete-here (pcomplete-erc-nicks))
(while (pcomplete-here (pcomplete-erc-nicks))))
(defun pcomplete/erc-mode/MSG ()
(pcomplete-here (append (pcomplete-erc-all-nicks)
(pcomplete-erc-channels)))
(while (pcomplete-here (pcomplete-erc-nicks))))
(defun pcomplete/erc-mode/NAMES ()
(while (pcomplete-here (pcomplete-erc-channels))))
(defalias 'pcomplete/erc-mode/NOTICE 'pcomplete/erc-mode/MSG)
(defun pcomplete/erc-mode/OP ()
(while (pcomplete-here (pcomplete-erc-not-ops))))
(defun pcomplete/erc-mode/PART ()
(pcomplete-here (pcomplete-erc-channels)))
(defalias 'pcomplete/erc-mode/LEAVE 'pcomplete/erc-mode/PART)
(defun pcomplete/erc-mode/QUERY ()
(pcomplete-here (append (pcomplete-erc-all-nicks)
(pcomplete-erc-channels)))
(while (pcomplete-here (pcomplete-erc-nicks)))
)
(defun pcomplete/erc-mode/SOUND ()
(while (pcomplete-here (pcomplete-entries))))
(defun pcomplete/erc-mode/TOPIC ()
(pcomplete-here (pcomplete-erc-channels)))
(defun pcomplete/erc-mode/WHOIS ()
(while (pcomplete-here (pcomplete-erc-nicks))))
(defun pcomplete/erc-mode/UNIGNORE ()
(pcomplete-here (with-current-buffer (erc-server-buffer) erc-ignore-list)))
;;; Functions that provide possible completions.
(defun pcomplete-erc-commands ()
"Returns a list of strings of the defined user commands."
(let ((case-fold-search nil))
(mapcar (lambda (x)
(concat "/" (downcase (substring (symbol-name x) 8))))
(apropos-internal "erc-cmd-[A-Z]+"))))
(defun pcomplete-erc-ops ()
"Returns a list of nicks with ops."
(let (ops)
(maphash (lambda (nick cdata)
(if (and (cdr cdata)
(erc-channel-user-op (cdr cdata)))
(setq ops (cons nick ops))))
erc-channel-users)
ops))
(defun pcomplete-erc-not-ops ()
"Returns a list of nicks without ops."
(let (not-ops)
(maphash (lambda (nick cdata)
(if (and (cdr cdata)
(not (erc-channel-user-op (cdr cdata))))
(setq not-ops (cons nick not-ops))))
erc-channel-users)
not-ops))
(defun pcomplete-erc-nicks (&optional postfix)
"Returns a list of nicks in the current channel."
(let ((users (erc-get-channel-user-list)))
(if erc-pcomplete-order-nickname-completions
(setq users (erc-sort-channel-users-by-activity users)))
(mapcar (lambda (x)
(concat (erc-server-user-nickname (car x)) postfix))
users)))
(defun pcomplete-erc-all-nicks (&optional postfix)
"Returns a list of all nicks on the current server."
(let (nicks)
(with-current-buffer (process-buffer erc-server-process)
(maphash (lambda (nick user)
(setq nicks (cons (concat nick postfix) nicks)))
erc-server-users))
nicks))
(defun pcomplete-erc-channels ()
"Returns a list of channels associated with the current server."
(mapcar (lambda (buf) (with-current-buffer buf (erc-default-target)))
(erc-channel-list erc-server-process)))
;;; Functions for parsing
(defun pcomplete-erc-command-name ()
"Returns the command name of the first argument."
(if (eq (elt (pcomplete-arg 'first) 0) ?/)
(upcase (substring (pcomplete-arg 'first) 1))
"SAY"))
(defun pcomplete-parse-erc-arguments ()
"Returns a list of parsed whitespace-separated arguments.
These are the words from the beginning of the line after the prompt
up to where point is right now."
(let* ((start erc-input-marker)
(end (point))
args beginnings)
(save-excursion
(if (< (skip-chars-backward " \t\n" start) 0)
(setq args '("")
beginnings (list end)))
(setq end (point))
(while (< (skip-chars-backward "^ \t\n" start) 0)
(setq beginnings (cons (point) beginnings)
args (cons (buffer-substring-no-properties
(point) end)
args))
(skip-chars-backward " \t\n" start)
(setq end (point))))
(cons args beginnings)))
(provide 'erc-pcomplete)
;;; erc-pcomplete.el ends here
;;
;; Local Variables:
;; indent-tabs-mode: nil
;; End:
;; arch-tag: 32a7703b-be87-45a4-82f3-9eed5a628911

93
lisp/erc/erc-replace.el Normal file
View file

@ -0,0 +1,93 @@
;; erc-replace.el -- wash and massage messages inserted into the buffer
;; Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
;; Author: Andreas Fuchs <asf@void.at>
;; Maintainer: Mario Lang (mlang@delysid.org)
;; Keywords: IRC, client, Internet
;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcReplace
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; This module allows you to systematically replace text in incoming
;; messages. Load erc-replace, and customize `erc-replace-alist'.
;; Then add to your ~/.emacs:
;; (require 'erc-replace)
;; (erc-replace-mode 1)
;;; Code:
(require 'erc)
(defgroup erc-replace nil
"Replace text from incoming messages"
:group 'erc)
(defcustom erc-replace-alist nil
"Alist describing text to be replaced in incoming messages.
This is useful for filters.
The alist has elements of the form (FROM . TO). FROM can be a regular
expression or a variable, or any sexp, TO can be a string or a
function to call, or any sexp. If a function, it will be called with
one argument, the string to be replaced, and it should return a
replacement string."
:group 'erc-replace
:type '(repeat (cons :tag "Search & Replace"
(choice :tag "From"
regexp
variable
sexp)
(choice :tag "To"
string
function
sexp))))
(defun erc-replace-insert ()
"Function to run from `erc-insert-modify-hook'.
It replaces text according to `erc-replace-alist'."
(mapcar (lambda (elt)
(goto-char (point-min))
(let ((from (car elt))
(to (cdr elt)))
(unless (stringp from)
(setq from (eval from)))
(while (re-search-forward from nil t)
(cond ((stringp to)
(replace-match to))
((and (symbolp to) (fboundp to))
(replace-match (funcall to (match-string 0))))
(t
(eval to))))))
erc-replace-alist))
;;;###autoload (autoload 'erc-replace-mode "erc-replace")
(define-erc-module replace nil
"This mode replaces incoming text according to `erc-replace-alist'."
((add-hook 'erc-insert-modify-hook
'erc-replace-insert))
((remove-hook 'erc-insert-modify-hook
'erc-replace-insert)))
(provide 'erc-replace)
;; arch-tag: dd904a59-d8a6-47f8-ac3a-76b698289a18
;;; erc-replace.el ends here

148
lisp/erc/erc-ring.el Normal file
View file

@ -0,0 +1,148 @@
;; erc-ring.el -- Command history handling for erc using ring.el
;; Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
;; Author: Alex Schroeder <alex@gnu.org>
;; Keywords: comm
;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcHistory
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; This file implements an input ring -- a history of the stuff you
;; wrote. To activate:
;;
;; (require 'erc-auto) or (require 'erc-ring)
;; (erc-ring-mode 1)
;;
;; Use M-n and M-p to navigate the ring
;;; Code:
(require 'erc)
(require 'comint)
(require 'ring)
;;;###autoload (autoload 'erc-ring-mode "erc-ring" nil t)
(define-erc-module ring nil
"Stores input in a ring so that previous commands and messages can
be recalled using M-p and M-n."
((add-hook 'erc-send-pre-hook 'erc-add-to-input-ring)
(define-key erc-mode-map "\M-p" 'erc-previous-command)
(define-key erc-mode-map "\M-n" 'erc-next-command))
((remove-hook 'erc-send-pre-hook 'erc-add-to-input-ring)
(define-key erc-mode-map "\M-p" 'undefined)
(define-key erc-mode-map "\M-n" 'undefined)))
(defvar erc-input-ring nil "Input ring for erc.")
(make-variable-buffer-local 'erc-input-ring)
(defvar erc-input-ring-index nil
"Position in the input ring for erc.
If nil, the input line is blank and the user is conceptually 'after'
the most recently added item in the ring. If an integer, the input
line is non-blank and displays the item from the ring indexed by this
variable.")
(make-variable-buffer-local 'erc-input-ring-index)
(defun erc-input-ring-setup ()
"Do the setup required so that we can use comint style input rings.
Call this function when setting up the mode."
(setq erc-input-ring (make-ring comint-input-ring-size))
(setq erc-input-ring-index nil))
(defun erc-add-to-input-ring (s)
"Add string S to the input ring and reset history position."
(unless erc-input-ring (erc-input-ring-setup))
(ring-insert erc-input-ring s)
(setq erc-input-ring-index nil))
(defun erc-clear-input-ring ()
"Remove all entries from the input ring, then call garbage-collect.
You might use this for security purposes if you have typed a command
containing a password."
(interactive)
(setq erc-input-ring (make-ring comint-input-ring-size)
erc-input-ring-index nil)
(garbage-collect)
(message "ERC input ring cleared."))
(defun erc-previous-command ()
"Replace current command with the previous one from the history."
(interactive)
(unless erc-input-ring (erc-input-ring-setup))
;; if the ring isn't empty
(when (> (ring-length erc-input-ring) 0)
(if (and erc-input-ring-index
(= (ring-length erc-input-ring) (1+ erc-input-ring-index)))
(progn
(erc-replace-current-command "")
(setq erc-input-ring-index nil))
;; If we are not viewing old input and there's text in the input
;; area, push it on the history ring before moving back through
;; the input history, so it will be there when we return to the
;; front.
(if (null erc-input-ring-index)
(when (> (point-max) erc-input-marker)
(erc-add-to-input-ring (buffer-substring erc-input-marker
(point-max)))
(setq erc-input-ring-index 0)))
(setq erc-input-ring-index (if erc-input-ring-index
(ring-plus1 erc-input-ring-index
(ring-length erc-input-ring))
0))
(erc-replace-current-command (ring-ref erc-input-ring
erc-input-ring-index)))))
(defun erc-next-command ()
"Replace current command with the next one from the history."
(interactive)
(unless erc-input-ring (erc-input-ring-setup))
;; if the ring isn't empty
(when (> (ring-length erc-input-ring) 0)
(if (and erc-input-ring-index
(= 0 erc-input-ring-index))
(progn
(erc-replace-current-command "")
(setq erc-input-ring-index nil))
(setq erc-input-ring-index (ring-minus1 (or erc-input-ring-index 0)
(ring-length erc-input-ring)))
(erc-replace-current-command (ring-ref erc-input-ring
erc-input-ring-index)))))
(defun erc-replace-current-command (s)
"Replace current command with string S."
;; delete line
(let ((inhibit-read-only t))
(delete-region
(progn (goto-char erc-insert-marker) (erc-bol))
(goto-char (point-max)))
(insert s)))
(provide 'erc-ring)
;;; erc-ring.el ends here
;; Local Variables:
;; indent-tabs-mode: nil
;; End:
;; arch-tag: b77924a8-a80e-489d-84cd-b351761ea5c8

149
lisp/erc/erc-sound.el Normal file
View file

@ -0,0 +1,149 @@
;;; erc-sound.el --- CTCP SOUND support for ERC
;; Copyright (C) 2002, 2003 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; This used to be in erc.el, I (Jorgen) just extracted it from there
;; and put it in this file. Bugs and features are those of the
;; original author.
;;; Code:
(require 'erc)
;;;###autoload (autoload 'erc-sound-mode "erc-sound")
(define-erc-module sound ctcp-sound
"In ERC sound mode, the client will respond to CTCP SOUND requests
and play sound files as requested."
;; Enable:
((define-key erc-mode-map "\C-c\C-s" 'erc-toggle-sound))
;; Disable:
((define-key erc-mode-map "\C-c\C-s" 'undefined)))
(erc-define-catalog-entry 'english 'CTCP-SOUND "%n (%u@%h) plays %s:%m")
(defgroup erc-sound nil
"Make ERC play bells and whistles while chatting with people."
:group 'erc)
(defcustom erc-play-sound t
"*Play sound on SOUND ctcp requests (used in ICQ chat)."
:group 'erc-sound
:type 'boolean)
(defcustom erc-sound-path nil
"List of directories that contain sound samples to play on SOUND events."
:group 'erc-sound
:type '(repeat directory))
(defcustom erc-default-sound nil
"Play this sound if the requested file was not found."
:group 'erc-sound
:type '(choice (const nil)
file))
(defcustom erc-play-command "play"
"Command for playing sound samples."
:group 'erc-sound
:type 'string)
(defun erc-cmd-SOUND (line &optional force)
"Play the sound given in LINE."
(cond
((string-match "^\\s-*\\(\\S-+\\)\\(\\s-.*\\)?$" line)
(let ((file (match-string 1 line))
(msg (match-string 2 line))
(tgt (erc-default-target)))
(if (null msg)
(setq msg "")
;; remove the first white space
(setq msg (substring msg 1)))
(if tgt
(progn
(erc-send-ctcp-message tgt (format "SOUND %s %s" file msg) force)
(if erc-play-sound (erc-play-sound file)))
(erc-display-message nil 'error (current-buffer) 'no-target))
t))
(t nil)))
(defvar erc-ctcp-query-SOUND-hook '(erc-ctcp-query-SOUND))
(defun erc-ctcp-query-SOUND (proc nick login host to msg)
(when (string-match "^SOUND\\s-+\\(\\S-+\\)\\(\\(\\s-+.*\\)\\|\\(\\s-*\\)\\)$" msg)
(let ((sound (match-string 1 msg))
(comment (match-string 2 msg)))
(when erc-play-sound (erc-play-sound sound))
(erc-display-message
nil 'notice nil
'CTCP-SOUND ?n nick ?u login ?h host ?s sound ?m comment)))
nil)
(defun erc-play-sound (file)
"Plays a sound file located in one of the directories in `erc-sound-path'
with a command `erc-play-command'."
(let ((filepath (erc-find-file file erc-sound-path)))
(if (and (not filepath) erc-default-sound)
(setq filepath erc-default-sound))
(cond ((and filepath (file-exists-p filepath))
(if (and (fboundp 'device-sound-enabled-p)
(device-sound-enabled-p))
; For XEmacs
(play-sound-file filepath)
; (start-process "erc-sound" nil erc-play-command filepath)
(start-process "erc-sound" nil "/bin/tcsh" "-c"
(concat erc-play-command " " filepath))))
(t (beep)))
(erc-log (format "Playing sound file %S" filepath))))
;(defun erc-play-sound (file)
; "Plays a sound file located in one of the directories in `erc-sound-path'
; with a command `erc-play-command'."
; (let ((filepath nil)
; (paths erc-sound-path))
; (while (and paths
; (progn (setq filepath (expand-file-name file (car paths)))
; (not (file-exists-p filepath))))
; (setq paths (cdr paths)))
; (if (and (not (and filepath (file-exists-p filepath)))
; erc-default-sound)
; (setq filepath erc-default-sound))
; (cond ((and filepath (file-exists-p filepath))
;; (start-process "erc-sound" nil erc-play-command filepath)
; (start-process "erc-sound" nil "/bin/tcsh" "-c"
; (concat erc-play-command " " filepath))
; )
; (t (beep)))
; (erc-log (format "Playing sound file %S" filepath))))
(defun erc-toggle-sound (&optional arg)
"Toggles playing sounds on and off. With positive argument,
turns them on. With any other argument turns sounds off."
(interactive "P")
(cond ((and (numberp arg) (> arg 0))
(setq erc-play-sound t))
(arg (setq erc-play-sound nil))
(t (setq erc-play-sound (not erc-play-sound))))
(message "ERC sound is %s" (if erc-play-sound "ON" "OFF")))
(provide 'erc-sound)
;; arch-tag: 53657d1d-007f-4a20-91c1-588e71cf0cee
;;; erc-sound.el ends here

369
lisp/erc/erc-speedbar.el Normal file
View file

@ -0,0 +1,369 @@
;;; erc-speedbar.el --- Speedbar support for ERC
;; Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@delysid.org>
;; Contributor: Eric M. Ludlam <eric@siege-engine.com>
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; This module provides integration of ERC into the Speedbar.
;;; TODO / ideas:
;; * Write intelligent update function:
;; update-channel, update-nick, remove-nick-from-channel, ...
;; * Use indicator-strings for op/voice
;; * Extract/convert face notes field from bbdb if available and show
;; it using sb-image.el
;;
;;; Code:
(require 'erc)
(require 'speedbar)
(condition-case nil (require 'dframe) (error nil))
;;; Customization:
(defgroup erc-speedbar nil
"Integration of ERC in the Speedbar"
:group 'erc)
(defcustom erc-speedbar-sort-users-type 'activity
"How channel nicknames are sorted.
'activity - Sort users by channel activity
'alphabetical - Sort users alphabetically
nil - Do not sort users"
:group 'erc-speedbar
:type '(choice (const :tag "Sort users by channel activity" activity)
(const :tag "Sort users alphabetically" alphabetical)
(const :tag "Do not sort users" nil)))
(defvar erc-speedbar-key-map nil
"Keymap used when in erc display mode.")
(defun erc-install-speedbar-variables ()
"Install those variables used by speedbar to enhance ERC."
(if erc-speedbar-key-map
nil
(setq erc-speedbar-key-map (speedbar-make-specialized-keymap))
;; Basic tree features
(define-key erc-speedbar-key-map "e" 'speedbar-edit-line)
(define-key erc-speedbar-key-map "\C-m" 'speedbar-edit-line)
(define-key erc-speedbar-key-map "+" 'speedbar-expand-line)
(define-key erc-speedbar-key-map "=" 'speedbar-expand-line)
(define-key erc-speedbar-key-map "-" 'speedbar-contract-line))
(speedbar-add-expansion-list '("ERC" erc-speedbar-menu-items
erc-speedbar-key-map
erc-speedbar-server-buttons))
(speedbar-add-mode-functions-list
'("ERC" (speedbar-item-info . erc-speedbar-item-info))))
(defvar erc-speedbar-menu-items
'(["Goto buffer" speedbar-edit-line t]
["Expand Node" speedbar-expand-line
(save-excursion (beginning-of-line)
(looking-at "[0-9]+: *.\\+. "))]
["Contract Node" speedbar-contract-line
(save-excursion (beginning-of-line)
(looking-at "[0-9]+: *.-. "))])
"Additional menu-items to add to speedbar frame.")
;; Make sure our special speedbar major mode is loaded
(if (featurep 'speedbar)
(erc-install-speedbar-variables)
(add-hook 'speedbar-load-hook 'erc-install-speedbar-variables))
;;; ERC hierarchy display method
;;;###autoload
(defun erc-speedbar-browser ()
"Initialize speedbar to display an ERC browser.
This will add a speedbar major display mode."
(interactive)
(require 'speedbar)
;; Make sure that speedbar is active
(speedbar-frame-mode 1)
;; Now, throw us into Info mode on speedbar.
(speedbar-change-initial-expansion-list "ERC")
(speedbar-get-focus))
(defun erc-speedbar-buttons (buffer)
"Create buttons for speedbar in BUFFER."
(erase-buffer)
(let (serverp chanp)
(with-current-buffer buffer
(setq serverp (eq buffer (process-buffer erc-server-process)))
(setq chanp (erc-channel-p (erc-default-target)))
(setq queryp (erc-query-buffer-p)))
(cond (serverp
(erc-speedbar-channel-buttons nil 0 buffer))
(chanp
(erc-speedbar-insert-target buffer 0)
(forward-line -1)
(erc-speedbar-expand-channel "+" buffer 0))
(queryp
(erc-speedbar-insert-target buffer 0))
(t (ignore)))))
(defun erc-speedbar-server-buttons (directory depth)
"Insert the initial list of servers you are connected to."
(let ((servers (erc-buffer-list
(lambda ()
(eq (current-buffer)
(process-buffer erc-server-process))))))
(when servers
(speedbar-with-writable
(dolist (server servers)
(speedbar-make-tag-line
'bracket ?+ 'erc-speedbar-expand-server server
(buffer-name server) 'erc-speedbar-goto-buffer server nil
depth))
t))))
(defun erc-speedbar-expand-server (text server indent)
(cond ((string-match "+" text)
(speedbar-change-expand-button-char ?-)
(if (speedbar-with-writable
(save-excursion
(end-of-line) (forward-char 1)
(erc-speedbar-channel-buttons nil (1+ indent) server)))
(speedbar-change-expand-button-char ?-)
(speedbar-change-expand-button-char ??)))
((string-match "-" text) ;we have to contract this node
(speedbar-change-expand-button-char ?+)
(speedbar-delete-subblock indent))
(t (error "Ooops... not sure what to do")))
(speedbar-center-buffer-smartly))
(defun erc-speedbar-channel-buttons (directory depth server-buffer)
(when (get-buffer server-buffer)
(let* ((proc (with-current-buffer server-buffer erc-server-process))
(targets (erc-buffer-list
(lambda ()
(not (eq (process-buffer erc-server-process)
(current-buffer))))
proc)))
(when targets
(speedbar-with-writable
(dolist (target targets)
(erc-speedbar-insert-target target depth))
t)))))
(defun erc-speedbar-insert-target (buffer depth)
(if (with-current-buffer buffer
(erc-channel-p (erc-default-target)))
(speedbar-make-tag-line
'bracket ?+ 'erc-speedbar-expand-channel buffer
(buffer-name buffer) 'erc-speedbar-goto-buffer buffer nil
depth)
;; Query target
(speedbar-make-tag-line
nil nil nil nil
(buffer-name buffer) 'erc-speedbar-goto-buffer buffer nil
depth)))
(defun erc-speedbar-expand-channel (text channel indent)
"For the line matching TEXT, in CHANNEL, expand or contract a line.
INDENT is the current indentation level."
(cond
((string-match "+" text)
(speedbar-change-expand-button-char ?-)
(speedbar-with-writable
(save-excursion
(end-of-line) (forward-char 1)
(let ((modes (with-current-buffer channel
(concat (apply 'concat
erc-channel-modes)
(cond
((and erc-channel-user-limit
erc-channel-key)
(if erc-show-channel-key-p
(format "lk %.0f %s"
erc-channel-user-limit
erc-channel-key)
(format "kl %.0f" erc-channel-user-limit)))
(erc-channel-user-limit
;; Emacs has no bignums
(format "l %.0f" erc-channel-user-limit))
(erc-channel-key
(if erc-show-channel-key-p
(format "k %s" erc-channel-key)
"k"))
(t "")))))
(topic (erc-controls-interpret
(with-current-buffer channel erc-channel-topic))))
(speedbar-make-tag-line
'angle ?i nil nil
(concat "Modes: +" modes) nil nil nil
(1+ indent))
(unless (string= topic "")
(speedbar-make-tag-line
'angle ?i nil nil
(concat "Topic: " topic) nil nil nil
(1+ indent)))
(let ((names (cond ((eq erc-speedbar-sort-users-type 'alphabetical)
(erc-sort-channel-users-alphabetically
(with-current-buffer channel
(erc-get-channel-user-list))))
((eq erc-speedbar-sort-users-type 'activity)
(erc-sort-channel-users-by-activity
(with-current-buffer channel
(erc-get-channel-user-list))))
(t (with-current-buffer channel
(erc-get-channel-user-list))))))
(when names
(speedbar-with-writable
(dolist (entry names)
(erc-speedbar-insert-user entry ?+ (1+ indent))))))))))
((string-match "-" text)
(speedbar-change-expand-button-char ?+)
(speedbar-delete-subblock indent))
(t (error "Ooops... not sure what to do")))
(speedbar-center-buffer-smartly))
(defun erc-speedbar-insert-user (entry exp-char indent)
"Insert one user based on the channel member list ENTRY.
EXP-CHAR is the expansion character to use.
INDENT is the current indentation level."
(let* ((user (car entry))
(cuser (cdr entry))
(nick (erc-server-user-nickname user))
(host (erc-server-user-host user))
(info (erc-server-user-info user))
(login (erc-server-user-login user))
(name (erc-server-user-full-name user))
(voice (and cuser (erc-channel-user-voice cuser)))
(op (and cuser (erc-channel-user-op cuser)))
(nick-str (concat (if op "@" "") (if voice "+" "") nick))
(finger (concat login (when (or login host) "@") host))
(sbtoken (list finger name info)))
(if (or login host name info) ; we want to be expandable
(speedbar-make-tag-line
'bracket ?+ 'erc-speedbar-expand-user sbtoken
nick-str nil sbtoken nil
indent)
(when (equal exp-char ?-)
(forward-line -1)
(erc-speedbar-expand-user "+" (list finger name info) indent))
(speedbar-make-tag-line
'statictag ?? nil nil
nick-str nil nil nil
indent))))
(defun erc-speedbar-update-channel (buffer)
"Update the speedbar information about a ERC buffer. The update
is only done when the channel is actually expanded already."
;; This is only a rude hack and doesn't care about multiserver usage
;; yet, consider this a brain storming, better ideas?
(with-current-buffer speedbar-buffer
(save-excursion
(goto-char (point-min))
(when (re-search-forward (concat "^1: *.+. *"
(regexp-quote (buffer-name buffer)))
nil t)
(beginning-of-line)
(speedbar-delete-subblock 1)
(erc-speedbar-expand-channel "+" buffer 1)))))
(defun erc-speedbar-expand-user (text token indent)
(cond ((string-match "+" text)
(speedbar-change-expand-button-char ?-)
(speedbar-with-writable
(save-excursion
(end-of-line) (forward-char 1)
(let ((finger (nth 0 token))
(name (nth 1 token))
(info (nth 2 token)))
(when finger
(speedbar-make-tag-line
nil nil nil nil
finger nil nil nil
(1+ indent)))
(when name
(speedbar-make-tag-line
nil nil nil nil
name nil nil nil
(1+ indent)))
(when info
(speedbar-make-tag-line
nil nil nil nil
info nil nil nil
(1+ indent)))))))
((string-match "-" text)
(speedbar-change-expand-button-char ?+)
(speedbar-delete-subblock indent))
(t (error "Ooops... not sure what to do")))
(speedbar-center-buffer-smartly))
(defun erc-speedbar-goto-buffer (text buffer indent)
"When user clicks on TEXT, goto an ERC buffer.
The INDENT level is ignored."
(if (featurep 'dframe)
(progn
(dframe-select-attached-frame speedbar-frame)
(let ((bwin (get-buffer-window buffer 0)))
(if bwin
(progn
(select-window bwin)
(raise-frame (window-frame bwin)))
(if dframe-power-click
(let ((pop-up-frames t))
(select-window (display-buffer buffer)))
(dframe-select-attached-frame speedbar-frame)
(switch-to-buffer buffer)))))
(let ((bwin (get-buffer-window buffer 0)))
(if bwin
(progn
(select-window bwin)
(raise-frame (window-frame bwin)))
(if speedbar-power-click
(let ((pop-up-frames t)) (select-window (display-buffer buffer)))
(select-frame speedbar-attached-frame)
(switch-to-buffer buffer))))))
(defun erc-speedbar-line-text ()
"Return the text for the item on the current line."
(beginning-of-line)
(when (re-search-forward "[]>] " nil t)
(buffer-substring-no-properties (point) (point-at-eol))))
(defun erc-speedbar-item-info ()
"Display information about the current buffer on the current line."
(let ((data (speedbar-line-token))
(txt (erc-speedbar-line-text)))
(cond ((and data (listp data))
(message "%s: %s" txt (car data)))
((bufferp data)
(message "Channel: %s" txt))
(t
(message "%s" txt)))))
(provide 'erc-speedbar)
;;; erc-speedbar.el ends here
;;
;; Local Variables:
;; indent-tabs-mode: t
;; tab-width: 8
;; End:
;; arch-tag: 7a6558a4-3308-4bf5-a284-e1d042c933c6

93
lisp/erc/erc-spelling.el Normal file
View file

@ -0,0 +1,93 @@
;;; erc-spelling.el --- use flyspell in ERC
;; Copyright (C) 2005, 2006 Free Software Foundation, Inc.
;; Author: Jorgen Schaefer <forcer@forcix.cx>
;; Keywords: irc
;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcSpelling
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; This is an ERC module to enable flyspell mode in ERC buffers. This
;; ensures correct behavior of flyspell, and even sets up a
;; channel-local dictionary if so required.
;;; Code:
(require 'erc)
(require 'flyspell)
;;;###autoload (autoload 'erc-spelling-mode "erc-spelling" nil t)
(define-erc-module spelling nil
"Enable flyspell mode in ERC buffers."
;; Use erc-connect-pre-hook instead of erc-mode-hook as pre-hook is
;; called AFTER the server buffer is initialized.
((add-hook 'erc-connect-pre-hook 'erc-spelling-init)
(mapc (lambda (buffer)
(with-current-buffer buffer (erc-spelling-init)))
(erc-buffer-list)))
((remove-hook 'erc-connect-pre-hook 'erc-spelling-init)
(mapc (lambda (buffer)
(with-current-buffer buffer (flyspell-mode 0)))
(erc-buffer-list))))
(defcustom erc-spelling-dictionaries nil
"An alist mapping buffer names to dictionaries.
The `car' of every cell is a buffer name, the `cadr' is the
string name of an associated dictionary.
The dictionary is inherited from server buffers, so if you want a
default dictionary for some server, you can use a server buffer
name here."
:type '(choice (const nil)
(repeat (cons (string :tag "Buffer name")
(string :tag "Dictionary"))))
:group 'erc-spelling)
(defun erc-spelling-init ()
"Enable flyspell mode in an ERC buffer."
(let ((name (downcase (buffer-name)))
(dicts erc-spelling-dictionaries))
(while (and dicts
(not (string= name (downcase (caar dicts)))))
(setq dicts (cdr dicts)))
(setq ispell-local-dictionary
(if dicts
(cadr (car dicts))
(let ((server (erc-server-buffer)))
(if server
(with-current-buffer server
ispell-local-dictionary)
nil)))))
(setq flyspell-generic-check-word-p 'erc-spelling-flyspell-verify)
(flyspell-mode 1))
(put 'erc-mode
'flyspell-mode-predicate
'erc-spelling-flyspell-verify)
(defun erc-spelling-flyspell-verify ()
"Flyspell only the input line, nothing else."
(> (point)
erc-input-marker))
(provide 'erc-spelling)
;; arch-tag: 04ae1c46-0fd1-4e1a-8b80-55bfa471c945
;;; erc-spelling.el ends here

335
lisp/erc/erc-stamp.el Normal file
View file

@ -0,0 +1,335 @@
;;; erc-stamp.el --- Timestamping for Emacs IRC CLient
;; Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@delysid.org>
;; Keywords: comm, processes, timestamp
;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcStamp
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; The code contained in this module is responsible for inserting
;; timestamps into ERC buffers. In order to actually activate this,
;; you must call `erc-timestamp-mode'.
;; You can choose between two different ways of inserting timestamps.
;; Customize `erc-insert-timestamp-function' and
;; `erc-insert-away-timestamp-function'.
;;; Code:
(require 'erc)
(require 'erc-compat)
(defgroup erc-stamp nil
"For long conversation on IRC it is sometimes quite
useful to have individual messages timestamp. This
group provides settings related to the format and display
of timestamp information in `erc-mode' buffer.
For timestamping to be activated, you just need to load `erc-stamp'
in your .emacs file or interactively using `load-library'."
:group 'erc)
(defcustom erc-timestamp-format "[%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\".
If nil, timestamping is turned off."
:group 'erc-stamp
:type '(choice (const nil)
(string)))
(defcustom erc-insert-timestamp-function 'erc-insert-timestamp-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."
:group 'erc-stamp
:type '(choice (const :tag "Right" erc-insert-timestamp-right)
(const :tag "Left" erc-insert-timestamp-left)
function))
(defcustom erc-away-timestamp-format "<%H:%M>"
"*Timestamp format used when marked as being away.
If nil, timestamping is turned off when away unless `erc-timestamp-format'
is set.
If `erc-timestamp-format' is set, this will not be used."
:group 'erc-stamp
:type '(choice (const nil)
(string)))
(defcustom erc-insert-away-timestamp-function 'erc-insert-timestamp-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)
(const :tag "Left" erc-insert-timestamp-left)
function))
(defcustom erc-hide-timestamps nil
"*If non-nil, timestamps will be invisible.
This is useful for logging, because, although timestamps will be
hidden, they will still be present in the logs."
:group 'erc-stamp
:type 'boolean)
(defcustom erc-echo-timestamps nil
"*If non-nil, print timestamp in the minibuffer when point is moved.
Using this variable, you can turn off normal timestamping,
and simply move point to an irc message to see its timestamp
printed in the minibuffer."
:group 'erc-stamp
:type 'boolean)
(defcustom erc-echo-timestamp-format "Timestamped %A, %H:%M:%S"
"*Format string to be used when `erc-echo-timestamps' is non-nil.
This string specifies the format of the timestamp being echoed in
the minibuffer."
:group 'erc-stamp
:type 'string)
(defcustom erc-timestamp-intangible t
"*Whether the timestamps should be intangible, i.e. prevent the point
from entering them and instead jump over them."
:group 'erc-stamp
:type 'boolean)
(defface erc-timestamp-face '((t (:bold t :foreground "green")))
"ERC timestamp face."
:group 'erc-faces)
;;;###autoload (autoload 'erc-timestamp-mode "erc-stamp" nil t)
(define-erc-module stamp timestamp
"This mode timestamps messages in the channel buffers."
((add-hook 'erc-mode-hook 'erc-munge-invisibility-spec)
(add-hook 'erc-insert-modify-hook 'erc-add-timestamp t)
(add-hook 'erc-send-modify-hook 'erc-add-timestamp t))
((remove-hook 'erc-mode-hook 'erc-munge-invisibility-spec)
(remove-hook 'erc-insert-modify-hook 'erc-add-timestamp)
(remove-hook 'erc-send-modify-hook 'erc-add-timestamp)))
(defun erc-add-timestamp ()
"Add timestamp and text-properties to message.
This function is meant to be called from `erc-insert-modify-hook'
or `erc-send-modify-hook'."
(unless (get-text-property (point) 'invisible)
(let ((ct (current-time)))
(if (fboundp erc-insert-timestamp-function)
(funcall erc-insert-timestamp-function
(erc-format-timestamp ct erc-timestamp-format))
(error "Timestamp function unbound"))
(when (and (fboundp erc-insert-away-timestamp-function)
erc-away-timestamp-format
(with-current-buffer (erc-server-buffer) erc-away)
(not erc-timestamp-format))
(funcall erc-insert-away-timestamp-function
(erc-format-timestamp ct erc-away-timestamp-format)))
(add-text-properties (point-min) (point-max)
(list 'timestamp ct))
(add-text-properties (point-min) (point-max)
(list 'point-entered 'erc-echo-timestamp)))))
(defvar erc-timestamp-last-inserted nil
"Last timestamp inserted into the buffer.")
(make-variable-buffer-local 'erc-timestamp-last-inserted)
(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
string of spaces which is the same size as the timestamp is added to
the beginning of the line in its place. If you use
`erc-insert-timestamp-right', nothing gets inserted in place of the
timestamp."
:group 'erc-stamp
:type 'boolean)
(defcustom erc-timestamp-right-column nil
"*If non-nil, the column at which the timestamp is inserted,
if the timestamp is to be printed to the right. If nil,
`erc-insert-timestamp-right' will use other means to determine
the correct column."
:group 'erc-stamp
:type '(choice
(integer :tag "Column number")
(const :tag "Unspecified" nil)))
(defun erc-insert-timestamp-left (string)
"Insert timestamps at the beginning of the line."
(goto-char (point-min))
(let* ((ignore-p (and erc-timestamp-only-if-changed-flag
(string-equal string erc-timestamp-last-inserted)))
(len (length string))
(s (if ignore-p (make-string len ? ) string)))
(unless ignore-p (setq erc-timestamp-last-inserted string))
(erc-put-text-property 0 len 'field 'erc-timestamp s)
(insert s)))
(defun erc-insert-aligned (string pos &optional fallback)
"Insert STRING based on a fraction of the width of the buffer.
Fraction is roughly (/ POS (window-width)).
If the current version of Emacs doesn't support this, use
\(- POS FALLBACK) to determine how many spaces to insert."
(if (or (featurep 'xemacs)
(< emacs-major-version 22)
(not (eq window-system 'x)))
(insert (make-string (- pos fallback) ? ) string)
(insert " ")
(let ((offset (floor (* (/ (1- pos) (window-width) 1.0)
(nth 2 (window-inside-pixel-edges))))))
(put-text-property (1- (point)) (point) 'display
`(space :align-to (,offset))))
(insert string)))
(defun erc-insert-timestamp-right (string)
"Insert timestamp on the right side of the screen.
STRING is the timestamp to insert. The function is a possible value
for `erc-insert-timestamp-function'.
If `erc-timestamp-only-if-changed-flag' is nil, a timestamp is always
printed. If this variable is non-nil, a timestamp is only printed if
it is different from the last.
If `erc-timestamp-right-column' is set, its value will be used as the
column at which the timestamp is to be printed. If it is nil, and
`erc-fill-mode' is active, then the timestamp will be printed just
before `erc-fill-column'. Otherwise, if the current buffer is
shown in a window, that window's width is used. If the buffer is
not shown, and `fill-column' is set, then the timestamp will be
printed just `fill-column'. As a last resort, the timestamp will
be printed just before the window-width."
(unless (and erc-timestamp-only-if-changed-flag
(string-equal string erc-timestamp-last-inserted))
(setq erc-timestamp-last-inserted string)
(goto-char (point-max))
(forward-char -1);; before the last newline
(let* ((current-window (get-buffer-window (current-buffer)))
(pos (cond
(erc-timestamp-right-column
(+ erc-timestamp-right-column (length string)))
((and (boundp 'erc-fill-mode)
erc-fill-mode
(boundp 'erc-fill-column))
(1+ erc-fill-column))
(current-window
(- (window-width current-window)
1))
(fill-column
(1+ fill-column))
(t
(- (window-width)
1))))
(from (point))
(col (current-column))
indent)
;; deal with variable-width characters
(setq pos (- pos (string-width string))
;; the following is a kludge that works with most
;; international input
col (+ col (ceiling (/ (- col (- (point) (point-at-bol))) 1.6))))
(if (< col pos)
(erc-insert-aligned string pos col)
(newline)
(setq from (point))
(indent-to pos)
(insert string))
(erc-put-text-property from (1+ (point)) 'field 'erc-timestamp)
(erc-put-text-property from (1+ (point)) 'rear-nonsticky t)
(when erc-timestamp-intangible
(erc-put-text-property from (1+ (point)) 'intangible t)))))
;; for testing: (setq erc-timestamp-only-if-changed-flag nil)
(defun erc-format-timestamp (time format)
"Return TIME formatted as string according to FORMAT.
Return the empty string if FORMAT is nil."
(if format
(let ((ts (format-time-string format time)))
(erc-put-text-property 0 (length ts) 'face 'erc-timestamp-face ts)
(erc-put-text-property 0 (length ts) 'invisible 'timestamp ts)
(erc-put-text-property 0 (length ts)
'isearch-open-invisible 'timestamp ts)
;; N.B. Later use categories instead of this harmless, but
;; inelegant, hack. -- BPT
(when erc-timestamp-intangible
(erc-put-text-property 0 (length ts) 'intangible t ts))
ts)
""))
;; This function is used to munge `buffer-invisibility-spec to an
;; appropriate value. Currently, it only handles timestamps, thus its
;; location. If you add other features which affect invisibility,
;; please modify this function and move it to a more appropriate
;; location.
(defun erc-munge-invisibility-spec ()
(if erc-hide-timestamps
(setq buffer-invisibility-spec
(if (listp buffer-invisibility-spec)
(cons 'timestamp buffer-invisibility-spec)
(list 't 'timestamp)))
(setq buffer-invisibility-spec
(if (listp buffer-invisibility-spec)
(remove 'timestamp buffer-invisibility-spec)
(list 't)))))
(defun erc-hide-timestamps ()
"Hide timestamp information from display."
(interactive)
(setq erc-hide-timestamps t)
(erc-munge-invisibility-spec))
(defun erc-show-timestamps ()
"Show timestamp information on display.
This function only works if `erc-timestamp-format' was previously
set, and timestamping is already active."
(interactive)
(setq erc-hide-timestamps nil)
(erc-munge-invisibility-spec))
(defun erc-echo-timestamp (before now)
"Print timestamp text-property of an IRC message.
Argument BEFORE is where point was before it got moved and
NOW is position of point currently."
(when erc-echo-timestamps
(let ((stamp (get-text-property now 'timestamp)))
(when stamp
(message (format-time-string erc-echo-timestamp-format
stamp))))))
(provide 'erc-stamp)
;;; erc-stamp.el ends here
;;
;; Local Variables:
;; indent-tabs-mode: t
;; tab-width: 8
;; End:
;; arch-tag: 9f6d31bf-61ba-45c5-bdbf-56331486ea27

839
lisp/erc/erc-track.el Normal file
View file

@ -0,0 +1,839 @@
;;; erc-track.el --- Track modified channel buffers
;; Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@delysid.org>
;; Keywords: comm, faces
;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcChannelTracking
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; Highlights keywords and pals (friends), and hides or highlights fools
;; (using a dark color). Add to your ~/.emacs:
;; (require 'erc-track)
;; (erc-track-mode 1)
;; Todo:
;; * Add extensibility so that custom functions can track
;; custom modification types.
(eval-when-compile (require 'cl))
(require 'erc)
(require 'erc-compat)
(require 'erc-match)
;;; Code:
(defgroup erc-track nil
"Track active buffers and show activity in the modeline."
:group 'erc)
(defcustom erc-track-visibility t
"Where do we look for buffers to determine their visibility?
The value of this variable determines, when a buffer is considered
visible or invisible. New messages in invisible buffers are tracked,
while switching to visible buffers when they are tracked removes them
from the list. See also `erc-track-when-inactive-mode'.
Possible values are:
t - all frames
visible - all visible frames
nil - only the selected frame
selected-visible - only the selected frame if it is visible
Activity means that there was no user input in the last 10 seconds."
:group 'erc-track
:type '(choice (const :tag "All frames" t)
(const :tag "All visible frames" visible)
(const :tag "Only the selected frame" nil)
(const :tag "Only the selected frame if it was active"
active)))
(defcustom erc-track-exclude nil
"A list targets (channel names or query targets) which should not be tracked."
:group 'erc-track
:type '(repeat string))
(defcustom erc-track-exclude-types '("NICK")
"*List of message types to be ignored.
This list could look like '(\"JOIN\" \"PART\")."
:group 'erc-track
:type 'erc-message-type)
(defcustom erc-track-exclude-server-buffer nil
"*If true, don't perform tracking on the server buffer; this is
useful for excluding all the things like MOTDs from the server and
other miscellaneous functions."
:group 'erc-track
:type 'boolean)
(defcustom erc-track-shorten-start 1
"This number specifies the minimum number of characters a channel name in
the mode-line should be reduced to."
:group 'erc-track
:type 'number)
(defcustom erc-track-shorten-cutoff 4
"All channel names longer than this value will be shortened."
:group 'erc-track
:type 'number)
(defcustom erc-track-shorten-aggressively nil
"*If non-nil, channel names will be shortened more aggressively.
Usually, names are not shortened if this will save only one character.
Example: If there are two channels, #linux-de and #linux-fr, then
normally these will not be shortened. When shortening aggressively,
however, these will be shortened to #linux-d and #linux-f.
If this variable is set to `max', then channel names will be shortened
to the max. Usually, shortened channel names will remain unique for a
given set of existing channels. When shortening to the max, the shortened
channel names will be unique for the set of active channels only.
Example: If there are tow active channels #emacs and #vi, and two inactive
channels #electronica and #folk, then usually the active channels are
shortened to #em and #v. When shortening to the max, however, #emacs is
not compared to #electronica -- only to #vi, therefore it can be shortened
even more and the result is #e and #v.
This setting is used by `erc-track-shorten-names'."
:group 'erc-track
:type '(choice (const :tag "No" nil)
(const :tag "Yes" t)
(const :tag "Max" max)))
(defcustom erc-track-shorten-function 'erc-track-shorten-names
"*This function will be used to reduce the channel names before display.
It takes one argument, CHANNEL-NAMES which is a list of strings.
It should return a list of strings of the same number of elements.
If nil instead of a function, shortening is disabled."
:group 'erc-track
:type '(choice (const :tag "Disabled")
function))
(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.
\(e.g. `erc-pal-face' is used if a pal sent a message to that channel.)"
:group 'erc-track
:type 'boolean)
(defcustom erc-track-faces-priority-list
'(erc-error-face erc-current-nick-face erc-keyword-face erc-pal-face
erc-nick-msg-face erc-direct-msg-face erc-button erc-dangerous-host-face
erc-default-face erc-action-face erc-nick-default-face erc-fool-face
erc-notice-face erc-input-face erc-prompt-face)
"A list of faces used to highlight active buffer names in the modeline.
If a message contains one of the faces in this list, the buffer name will
be highlighted using that face. The first matching face is used."
:group 'erc-track
:type '(repeat face))
(defcustom erc-track-priority-faces-only nil
"Only track text highlighted with a priority face.
If you would like to ignore changes in certain channels where there
are no faces corresponding to your `erc-track-faces-priority-list', set
this variable. You can set a list of channel name strings, so those
will be ignored while all other channels will be tracked as normal.
Other options are 'all, to apply this to all channels or nil, to disable
this feature.
Note: If you have a lot of faces listed in `erc-track-faces-priority-list',
setting this variable might not be very useful."
:group 'erc-track
:type '(choice (const nil)
(repeat string)
(const all)))
(defcustom erc-track-position-in-mode-line 'before-modes
"Where to show modified channel information in the mode-line.
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'."
: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))
:set (lambda (sym val)
(set sym val)
(when (and (boundp 'erc-track-mode)
erc-track-mode)
(erc-track-remove-from-mode-line)
(erc-track-add-to-mode-line val))))
(defun erc-modified-channels-object (strings)
"Generate a new `erc-modified-channels-object' based on STRINGS.
If STRINGS is nil, we initialize `erc-modified-channels-object' to
an appropriate initial value for this flavor of Emacs."
(if strings
(if (featurep 'xemacs)
(let ((e-m-c-s '("[")))
(push (cons (extent-at 0 (car strings)) (car strings))
e-m-c-s)
(dolist (string (cdr strings))
(push "," e-m-c-s)
(push (cons (extent-at 0 string) string)
e-m-c-s))
(push "] " e-m-c-s)
(reverse e-m-c-s))
(concat (if (eq erc-track-position-in-mode-line 'after-modes)
"[" " [")
(mapconcat 'identity (nreverse strings) ",")
(if (eq erc-track-position-in-mode-line 'before-modes)
"] " "]")))
(if (featurep 'xemacs) '() "")))
(defvar erc-modified-channels-object (erc-modified-channels-object nil)
"Internal object used for displaying modified channels in the mode line.")
(put 'erc-modified-channels-object 'risky-local-variable t); allow properties
(defvar erc-modified-channels-alist nil
"An ALIST used for tracking channel modification activity.
Each element looks like (BUFFER COUNT FACE) where BUFFER is a buffer
object of the channel the entry corresponds to, COUNT is a number
indicating how often activity was noticed, and FACE is the face to use
when displaying the buffer's name. See `erc-track-faces-priority-list',
and `erc-track-showcount'.
Entries in this list should only happen for buffers where activity occurred
while the buffer was not visible.")
(defcustom erc-track-showcount nil
"If non-nil, count of unseen messages will be shown for each channel."
:type 'boolean
:group 'erc-track)
(defcustom erc-track-showcount-string ":"
"The string to display between buffer name and the count in the mode line.
The default is a colon, resulting in \"#emacs:9\"."
:type 'string
:group 'erc-track)
(defcustom erc-track-switch-from-erc t
"If non-nil, `erc-track-switch-buffer' will return to the last non-erc buffer
when there are no more active channels."
:type 'boolean
:group 'erc-track)
(defcustom erc-track-switch-direction 'oldest
"Direction `erc-track-switch-buffer' should switch.
oldest - find oldest active buffer
newest - find newest active buffer
leastactive - find buffer with least unseen messages
mostactive - find buffer with most unseen messages."
:group 'erc-track
:type '(choice (const oldest)
(const newest)
(const leastactive)
(const mostactive)))
(defun erc-track-remove-from-mode-line ()
"Remove `erc-track-modified-channels' from the mode-line"
(when (boundp 'mode-line-modes)
(setq mode-line-modes
(remove '(t erc-modified-channels-object) mode-line-modes)))
(when (consp global-mode-string)
(setq global-mode-string
(delq 'erc-modified-channels-object global-mode-string))))
(defun erc-track-add-to-mode-line (position)
"Add `erc-track-modified-channels' to POSITION in the mode-line.
See `erc-track-position-in-mode-line' for possible values."
;; CVS Emacs has a new format string, and global-mode-string
;; is very far to the right.
(cond ((and (eq position 'before-modes)
(boundp 'mode-line-modes))
(add-to-list 'mode-line-modes
'(t erc-modified-channels-object)))
((and (eq position 'after-modes)
(boundp 'mode-line-modes))
(add-to-list 'mode-line-modes
'(t erc-modified-channels-object) t))
(t
(when (not global-mode-string)
(setq global-mode-string '(""))) ; Padding for mode-line wart
(add-to-list 'global-mode-string
'erc-modified-channels-object
t))))
;;; Shortening of names
(defun erc-track-shorten-names (channel-names)
"Call `erc-unique-channel-names' with the correct parameters.
This function is a good value for `erc-track-shorten-function'.
The list of all channels is returned by `erc-all-buffer-names'.
CHANNEL-NAMES is the list of active channel names.
Only channel names longer than `erc-track-shorten-cutoff' are
actually shortened, and they are only shortened to a minimum
of `erc-track-shorten-start' characters."
(erc-unique-channel-names
(erc-all-buffer-names)
channel-names
(lambda (s)
(> (length s) erc-track-shorten-cutoff))
erc-track-shorten-start))
(defvar erc-default-recipients)
(defun erc-all-buffer-names ()
"Return all channel or query buffer names.
Note that we cannot use `erc-channel-list' with a nil argument,
because that does not return query buffers."
(save-excursion
(let (result)
(dolist (buf (buffer-list))
(set-buffer buf)
(when (or (eq major-mode 'erc-mode) (eq major-mode 'erc-dcc-chat-mode))
(setq result (cons (buffer-name) result))))
result)))
(defun erc-unique-channel-names (all active &optional predicate start)
"Return a list of unique channel names.
ALL is the list of all channel and query buffer names.
ACTIVE is the list of active buffer names.
PREDICATE is a predicate that should return non-nil if a name needs
no shortening.
START is the minimum length of the name used."
(if (eq 'max erc-track-shorten-aggressively)
;; Return the unique substrings of all active channels.
(erc-unique-substrings active predicate start)
;; Otherwise, determine the unique substrings of all channels, and
;; for every active channel, return the corresponding substring.
;; Given the names of the active channels, we now need to find the
;; corresponding short name from the list of all substrings. To
;; avoid problems when there are two channels and one is a
;; substring of the other (notorious examples are #hurd and
;; #hurd-bunny), every candidate gets the longest possible
;; substring.
(let ((all-substrings (sort
(erc-unique-substrings all predicate start)
(lambda (a b) (> (length a) (length b)))))
result)
(dolist (channel active)
(let ((substrings all-substrings)
candidate
winner)
(while (and substrings (not winner))
(setq candidate (car substrings)
substrings (cdr substrings))
(when (and (string= candidate
(substring channel
0
(min (length candidate)
(length channel))))
(not (member candidate result)))
(setq winner candidate)))
(setq result (cons winner result))))
(nreverse result))))
(defun erc-unique-substrings (strings &optional predicate start)
"Return a list of unique substrings of STRINGS."
(if (or (not (numberp start))
(< start 0))
(setq start 2))
(mapcar
(lambda (str)
(let* ((others (delete str (copy-sequence strings)))
(maxlen (length str))
(i (min start
(length str)))
candidate
done)
(if (and (functionp predicate) (not (funcall predicate str)))
;; do not shorten if a predicate exists and it returns nil
str
;; Start with smallest substring candidate, ie. length 1.
;; Then check all the others and see whether any of them starts
;; with the same substring. While there is such another
;; element in the list, increase the length of the candidate.
(while (not done)
(if (> i maxlen)
(setq done t)
(setq candidate (substring str 0 i)
done (not (erc-unique-substring-1 candidate others))))
(setq i (1+ i)))
(if (and (= (length candidate) (1- maxlen))
(not erc-track-shorten-aggressively))
str
candidate))))
strings))
(defun erc-unique-substring-1 (candidate others)
"Return non-nil when any string in OTHERS starts with CANDIDATE."
(let (result other (maxlen (length candidate)))
(while (and others
(not result))
(setq other (car others)
others (cdr others))
(when (and (>= (length other) maxlen)
(string= candidate (substring other 0 maxlen)))
(setq result other)))
result))
;;; Test:
(erc-assert
(and
;; verify examples from the doc strings
(equal (let ((erc-track-shorten-aggressively nil))
(erc-unique-channel-names
'("#emacs" "#vi" "#electronica" "#folk")
'("#emacs" "#vi")))
'("#em" "#vi")) ; emacs is different from electronica
(equal (let ((erc-track-shorten-aggressively t))
(erc-unique-channel-names
'("#emacs" "#vi" "#electronica" "#folk")
'("#emacs" "#vi")))
'("#em" "#v")) ; vi is shortened by one letter
(equal (let ((erc-track-shorten-aggressively 'max))
(erc-unique-channel-names
'("#emacs" "#vi" "#electronica" "#folk")
'("#emacs" "#vi")))
'("#e" "#v")) ; emacs need not be different from electronica
(equal (let ((erc-track-shorten-aggressively nil))
(erc-unique-channel-names
'("#linux-de" "#linux-fr")
'("#linux-de" "#linux-fr")))
'("#linux-de" "#linux-fr")) ; shortening by one letter is too aggressive
(equal (let ((erc-track-shorten-aggressively t))
(erc-unique-channel-names
'("#linux-de" "#linux-fr")
'("#linux-de" "#linux-fr")))
'("#linux-d" "#linux-f")); now we want to be aggressive
;; specific problems
(equal (let ((erc-track-shorten-aggressively nil))
(erc-unique-channel-names
'("#dunnet" "#lisp" "#sawfish" "#fsf" "#guile"
"#testgnome" "#gnu" "#fsbot" "#hurd" "#hurd-bunny"
"#emacs")
'("#hurd-bunny" "#hurd" "#sawfish" "#lisp")))
'("#hurd-" "#hurd" "#s" "#l"))
(equal (let ((erc-track-shorten-aggressively nil))
(erc-unique-substrings
'("#emacs" "#vi" "#electronica" "#folk")))
'("#em" "#vi" "#el" "#f"))
(equal (let ((erc-track-shorten-aggressively t))
(erc-unique-substrings
'("#emacs" "#vi" "#electronica" "#folk")))
'("#em" "#v" "#el" "#f"))
(equal (let ((erc-track-shorten-aggressively nil))
(erc-unique-channel-names
'("#emacs" "#burse" "+linux.de" "#starwars"
"#bitlbee" "+burse" "#ratpoison")
'("+linux.de" "#starwars" "#burse")))
'("+l" "#s" "#bu"))
(equal (let ((erc-track-shorten-aggressively nil))
(erc-unique-channel-names
'("fsbot" "#emacs" "deego")
'("fsbot")))
'("fs"))
(equal (let ((erc-track-shorten-aggressively nil))
(erc-unique-channel-names
'("fsbot" "#emacs" "deego")
'("fsbot")
(lambda (s)
(> (length s) 4))
1))
'("f"))
(equal (let ((erc-track-shorten-aggressively nil))
(erc-unique-channel-names
'("fsbot" "#emacs" "deego")
'("fsbot")
(lambda (s)
(> (length s) 4))
2))
'("fs"))
(let ((erc-track-shorten-aggressively nil))
(equal (erc-unique-channel-names '("deego" "#hurd" "#hurd-bunny" "#emacs")
'("#hurd" "#hurd-bunny"))
'("#hurd" "#hurd-")))
;; general examples
(let ((erc-track-shorten-aggressively t))
(and (equal (erc-unique-substring-1 "abc" '("ab" "abcd")) "abcd")
(not (erc-unique-substring-1 "a" '("xyz" "xab")))
(equal (erc-unique-substrings '("abc" "xyz" "xab"))
'("ab" "xy" "xa"))
(equal (erc-unique-substrings '("abc" "abcdefg"))
'("abc" "abcd"))))
(let ((erc-track-shorten-aggressively nil))
(and (equal (erc-unique-substring-1 "abc" '("ab" "abcd")) "abcd")
(not (erc-unique-substring-1 "a" '("xyz" "xab")))
(equal (erc-unique-substrings '("abc" "xyz" "xab"))
'("abc" "xyz" "xab"))
(equal (erc-unique-substrings '("abc" "abcdefg"))
'("abc" "abcd"))))))
;;; Module
;;;###autoload (autoload 'erc-track-mode "erc-track" nil t)
(define-erc-module track track-modified-channels
"This mode tracks ERC channel buffers with activity."
((erc-track-add-to-mode-line erc-track-position-in-mode-line)
(setq erc-modified-channels-object (erc-modified-channels-object nil))
(erc-update-mode-line)
(if (featurep 'xemacs)
(defadvice switch-to-buffer (after erc-update (&rest args) activate)
(erc-modified-channels-update))
(add-hook 'window-configuration-change-hook 'erc-modified-channels-update))
(add-hook 'erc-insert-post-hook 'erc-track-modified-channels)
(add-hook 'erc-disconnected-hook 'erc-modified-channels-update))
((erc-track-remove-from-mode-line)
(if (featurep 'xemacs)
(ad-disable-advice 'switch-to-buffer 'after 'erc-update)
(remove-hook 'window-configuration-change-hook
'erc-modified-channels-update))
(remove-hook 'erc-disconnected-hook 'erc-modified-channels-update)
(remove-hook 'erc-insert-post-hook 'erc-track-modified-channels)))
;;;###autoload (autoload 'erc-track-when-inactive-mode "erc-track" nil t)
(define-erc-module track-when-inactive nil
"This mode enables channel tracking even for visible buffers,
if you are inactivity."
((if (featurep 'xemacs)
(defadvice switch-to-buffer (after erc-update-when-inactive (&rest args) activate)
(erc-user-is-active))
(add-hook 'window-configuration-change-hook 'erc-user-is-active))
(add-hook 'erc-send-completed-hook 'erc-user-is-active)
(add-hook 'erc-server-001-functions 'erc-user-is-active))
((erc-track-remove-from-mode-line)
(if (featurep 'xemacs)
(ad-disable-advice 'switch-to-buffer 'after 'erc-update-when-inactive)
(remove-hook 'window-configuration-change-hook 'erc-user-is-active))
(remove-hook 'erc-send-completed-hook 'erc-user-is-active)
(remove-hook 'erc-server-001-functions 'erc-user-is-active)
(remove-hook 'erc-timer-hook 'erc-user-is-active)))
;;; Visibility
(defvar erc-buffer-activity nil
"Last time the user sent something.")
(defvar erc-buffer-activity-timeout 10
"How many seconds of inactivity by the user
to consider when `erc-track-visibility' is set to
only consider active buffers visible.")
(defun erc-user-is-active (&rest ignore)
"Set `erc-buffer-activity'."
(setq erc-buffer-activity (erc-current-time))
(erc-track-modified-channels))
(defun erc-buffer-visible (buffer)
"Return non-nil when the buffer is visible."
(if erc-track-when-inactive-mode
(when erc-buffer-activity; could be nil
(and (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)))
;;; Tracking the channel modifications
(defvar erc-modified-channels-update-inside nil
"Variable to prevent running `erc-modified-channels-update' multiple
times. Without it, you cannot debug `erc-modified-channels-display',
because the debugger also cases changes to the window-configuration.")
(defun erc-modified-channels-update (&rest args)
"This function updates the information in `erc-modified-channels-alist'
according to buffer visibility. It calls
`erc-modified-channels-display' at the end. This should usually be
called via `window-configuration-change-hook'.
ARGS are ignored."
(interactive)
(unless erc-modified-channels-update-inside
(let ((erc-modified-channels-update-inside t))
(mapcar (lambda (elt)
(let ((buffer (car elt)))
(when (or (not (bufferp buffer))
(not (buffer-live-p buffer))
(erc-buffer-visible buffer)
(not (with-current-buffer buffer
erc-server-connected)))
(erc-modified-channels-remove-buffer buffer))))
erc-modified-channels-alist)
(erc-modified-channels-display)
(force-mode-line-update t))))
(defun erc-make-mode-line-buffer-name (string buffer &optional faces count)
"Return STRING as a button that switches to BUFFER when clicked.
If FACES are provided, color STRING with them."
;; We define a new sparse keymap every time, because 1. this data
;; structure is very small, the alternative would require us to
;; defvar a keymap, 2. the user is not interested in customizing it
;; (really?), 3. the defun needs to switch to BUFFER, so we would
;; need to save that value somewhere.
(let ((map (make-sparse-keymap))
(name (if erc-track-showcount
(concat string
erc-track-showcount-string
(int-to-string count))
(copy-sequence string))))
(define-key map (vector 'mode-line 'mouse-2)
`(lambda (e)
(interactive "e")
(save-selected-window
(select-window
(posn-window (event-start e)))
(switch-to-buffer ,buffer))))
(define-key map (vector 'mode-line 'mouse-3)
`(lambda (e)
(interactive "e")
(save-selected-window
(select-window
(posn-window (event-start e)))
(switch-to-buffer-other-window ,buffer))))
(put-text-property 0 (length name) 'local-map map name)
(when (and faces erc-track-use-faces)
(put-text-property 0 (length name) 'face faces name))
name))
(defun erc-modified-channels-display ()
"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))
(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
;; better understand what is going on, we split things up into
;; four lists: BUFFERS, COUNTS, SHORT-NAMES, and FACES. These
;; four lists we use to create a new
;; `erc-modified-channels-object' using
;; `erc-make-mode-line-buffer-name'.
(let* ((buffers (mapcar 'car erc-modified-channels-alist))
(counts (mapcar 'cadr erc-modified-channels-alist))
(faces (mapcar 'cddr erc-modified-channels-alist))
(long-names (mapcar #'(lambda (buf)
(or (buffer-name buf)
""))
buffers))
(short-names (if (functionp erc-track-shorten-function)
(funcall erc-track-shorten-function
long-names)
long-names))
strings)
(while buffers
(when (car short-names)
(setq strings (cons (erc-make-mode-line-buffer-name
(car short-names)
(car buffers)
(car faces)
(car counts))
strings)))
(setq short-names (cdr short-names)
buffers (cdr buffers)
counts (cdr counts)
faces (cdr faces)))
(when (featurep 'xemacs)
(erc-modified-channels-object nil))
(setq erc-modified-channels-object
(erc-modified-channels-object strings)))))
(defun erc-modified-channels-remove-buffer (buffer)
"Remove BUFFER from `erc-modified-channels-alist'."
(interactive "bBuffer: ")
(setq erc-modified-channels-alist
(delete (assq buffer erc-modified-channels-alist)
erc-modified-channels-alist))
(when (interactive-p)
(erc-modified-channels-display)))
(defun erc-track-find-face (faces)
"Return the face to use in the modeline from the faces in FACES.
If `erc-track-faces-priority-list' is set, the one from FACES who is
first in that list will be used."
(let ((candidates erc-track-faces-priority-list)
candidate face)
(while (and candidates (not face))
(setq candidate (car candidates)
candidates (cdr candidates))
(when (memq candidate faces)
(setq face candidate)))
face))
(defun erc-track-modified-channels ()
"Hook function for `erc-insert-post-hook' to check if the current
buffer should be added to the modeline as a hidden, modified
channel. Assumes it will only be called when current-buffer
is in `erc-mode'."
(let ((this-channel (or (erc-default-target)
(buffer-name (current-buffer)))))
(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)))))
(not (erc-message-type-member
(or (erc-find-parsed-property)
(point-min))
erc-track-exclude-types)))
;; If the active buffer is not visible (not shown in a
;; window), and not to be excluded, determine the kinds of
;; faces used in the current message, and unless the user
;; wants to ignore changes in certain channels where there
;; are no faces corresponding to `erc-track-faces-priority-list',
;; and the faces in the current message are found in said
;; priority list, add the buffer to the erc-modified-channels-alist,
;; if it is not already there. If the buffer is already on the list
;; (in the car), change its face attribute (in the cddr) if
;; necessary. See `erc-modified-channels-alist' for the
;; exact data structure used.
(let ((faces (erc-faces-in (buffer-string))))
(unless (and
(or (eq erc-track-priority-faces-only 'all)
(member this-channel erc-track-priority-faces-only))
(not (catch 'found
(dolist (f faces)
(when (member f erc-track-faces-priority-list)
(throw 'found t))))))
(if (not (assq (current-buffer) erc-modified-channels-alist))
;; Add buffer, faces and counts
(setq erc-modified-channels-alist
(cons (cons (current-buffer)
(cons 1 (erc-track-find-face faces)))
erc-modified-channels-alist))
;; Else modify the face for the buffer, if necessary.
(when faces
(let* ((cell (assq (current-buffer)
erc-modified-channels-alist))
(old-face (cddr cell))
(new-face (erc-track-find-face
(if old-face
(cons old-face faces)
faces))))
(setcdr cell (cons (1+ (cadr cell)) new-face)))))
;; And display it
(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))
(and this-channel
(assq (current-buffer) erc-modified-channels-alist)
(member this-channel erc-track-exclude)))
;; 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))
(erc-modified-channels-display)))))
(defun erc-faces-in (str)
"Return a list of all faces used in STR."
(let ((i 0)
(m (length str))
(faces (erc-list (get-text-property 0 'face str))))
(while (and (setq i (next-single-property-change i 'face str m))
(not (= i m)))
(dolist (face (erc-list (get-text-property i 'face str)))
(add-to-list 'faces face)))
faces))
(erc-assert
(let ((str "is bold"))
(put-text-property 3 (length str)
'face '(bold erc-current-nick-face)
str)
(erc-faces-in str)))
(defun erc-find-parsed-property ()
"Find the next occurrence of the `erc-parsed' text property."
(text-property-not-all (point-min) (point-max) 'erc-parsed nil))
;;; Buffer switching
(defvar erc-track-last-non-erc-buffer nil
"Stores the name of the last buffer you were in before activating
`erc-track-switch-buffers'")
(defun erc-track-sort-by-activest ()
"Sort erc-modified-channels-alist by activity.
That means the number of unseen messages in a channel."
(setq erc-modified-channels-alist
(sort erc-modified-channels-alist
(lambda (a b) (> (nth 1 a) (nth 1 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
relative to `erc-track-switch-direction'"
(let ((dir erc-track-switch-direction)
offset)
(when (< arg 0)
(setq dir (case dir
(oldest 'newest)
(newest 'oldest)
(mostactive 'leastactive)
(leastactive 'mostactive)))
(setq arg (- arg)))
(setq offset (case dir
((oldest leastactive)
(- (length erc-modified-channels-alist) arg))
(t (1- arg))))
;; normalise out of range user input
(cond ((>= offset (length erc-modified-channels-alist))
(setq offset (1- (length erc-modified-channels-alist))))
((< offset 0)
(setq offset 0)))
(car (nth offset erc-modified-channels-alist))))
(defun erc-track-switch-buffer (arg)
"Switch to the next active ERC buffer, or if there are no active buffers,
switch back to the last non-ERC buffer visited. Next is defined by
`erc-track-switch-direction', a negative argument will reverse this."
(interactive "p")
(when erc-track-mode
(cond (erc-modified-channels-alist
;; if we're not in erc-mode, set this buffer to return to
(unless (eq major-mode 'erc-mode)
(setq erc-track-last-non-erc-buffer (current-buffer)))
;; and jump to the next active channel
(switch-to-buffer (erc-track-get-active-buffer arg)))
;; if no active channels, switch back to what we were doing before
((and erc-track-last-non-erc-buffer
erc-track-switch-from-erc
(buffer-live-p erc-track-last-non-erc-buffer))
(switch-to-buffer erc-track-last-non-erc-buffer)))))
;; These bindings are global, because they pop us from any other
;; buffer to an active ERC buffer!
(global-set-key (kbd "C-c C-@") 'erc-track-switch-buffer)
(global-set-key (kbd "C-c C-SPC") 'erc-track-switch-buffer)
(provide 'erc-track)
;;; erc-track.el ends here
;;
;; Local Variables:
;; indent-tabs-mode: t
;; tab-width: 8
;; End:
;; arch-tag: 11b439f5-e5d7-4c6c-bb3f-eda98f9b0ac1

121
lisp/erc/erc-truncate.el Normal file
View file

@ -0,0 +1,121 @@
;;; erc-truncate.el --- Functions for truncating ERC buffers
;; Copyright (C) 2003, 2004 Free Software Foundation, Inc.
;; Author: Andreas Fuchs <asf@void.at>
;; Keywords: IRC, chat, client, Internet, logging
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; This implements buffer truncation (and optional log file writing
;; support for the Emacs IRC client. Use `erc-truncate-mode' to switch
;; on. Use `erc-enable-logging' to enable logging of the stuff which
;; is getting truncated.
;;; Code:
(require 'erc)
(defgroup erc-truncate nil
"Truncate buffers when they reach a certain size"
:group 'erc)
(defcustom erc-max-buffer-size 30000
"*Maximum size in chars of each ERC buffer.
Used only when auto-truncation is enabled.
\(see `erc-truncate-buffer' and `erc-insert-post-hook')."
:group 'erc-truncate
:type 'integer)
;;;###autoload (autoload 'erc-truncate-mode "erc-truncate" nil t)
(define-erc-module truncate nil
"Truncate a query buffer if it gets too large.
This prevents the query buffer from getting too large, which can
bring any grown emacs to its knees after a few days worth of
tracking heavy-traffic channels."
;;enable
((add-hook 'erc-insert-post-hook 'erc-truncate-buffer))
;; disable
((remove-hook 'erc-insert-post-hook 'erc-truncate-buffer)))
;;;###autoload
(defun erc-truncate-buffer-to-size (size &optional buffer)
"Truncates the buffer to the size SIZE.
If BUFFER is not provided, the current buffer is assumed. The deleted
region is logged if `erc-logging-enabled' returns non-nil."
;; If buffer is non-nil, but get-buffer does not return anything,
;; then this is a bug. If buffer is a buffer name, get the buffer
;; object. If buffer is nil, use the current buffer.
(if (not buffer)
(setq buffer (current-buffer))
(unless (get-buffer buffer)
(error "erc-truncate-buffer-to-size: %S is not a buffer" buffer)))
(when (> (buffer-size buffer) (+ size 512))
(save-excursion
(set-buffer buffer)
;; Note that when erc-insert-post-hook runs, the buffer is
;; narrowed to the new message. So do this delicate widening.
;; I am not sure, I think this was not recommended behaviour in
;; Emacs 20.
(save-restriction
(widen)
(let ((end (- erc-insert-marker size)))
;; truncate at line boundaries
(goto-char end)
(beginning-of-line)
(setq end (point))
;; try to save the current buffer using
;; `erc-save-buffer-in-logs'. We use this, in case the
;; user has both `erc-save-buffer-in-logs' and
;; `erc-truncate-buffer' in `erc-insert-post-hook'. If
;; this is the case, only the non-saved part of the current
;; buffer should be saved. Rather than appending the
;; deleted part of the buffer to the log file.
;;
;; Alternatively this could be made conditional on:
;; (not (memq 'erc-save-buffer-in-logs
;; erc-insert-post-hook))
;; Comments?
(when (and (boundp 'erc-enable-logging)
erc-enable-logging
(erc-logging-enabled buffer))
(erc-save-buffer-in-logs))
;; disable undoing for the truncating
(buffer-disable-undo)
(let ((inhibit-read-only t))
(delete-region (point-min) end)))
(buffer-enable-undo)))))
;;;###autoload
(defun erc-truncate-buffer ()
"Truncates the current buffer to `erc-max-buffer-size'.
Meant to be used in hooks, like `erc-insert-post-hook'."
(interactive)
(erc-truncate-buffer-to-size erc-max-buffer-size))
(provide 'erc-truncate)
;;; erc-truncate.el ends here
;;
;; Local Variables:
;; indent-tabs-mode: t
;; tab-width: 8
;; End:
;; arch-tag: 22a2ea78-871f-4870-8f1e-efe534170311

74
lisp/erc/erc-viper.el Normal file
View file

@ -0,0 +1,74 @@
;;; erc-viper.el --- Viper compatibility hacks for ERC
;; Copyright (C) 2005 Free Software Foundation, Inc.
;; Author: Edward O'Connor <ted@oconnor.cx>
;; Keywords: emulation
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; Viper is a VI emulation mode for Emacs. ERC and Viper don't quite get
;; along by default; the code in this file fixes that. A simple
;; (require 'erc-viper)
;; in your ~/.ercrc.el should be all it takes for you to use ERC and
;; Viper together happily.
;;; Code:
(require 'viper)
;; We need this for `erc-mode-hook' and `erc-buffer-list'. Perhaps it
;; would be better to use an `eval-after-load', so that there could be
;; some autodetection / loading of this file from within erc.el?
(require 'erc)
;; Fix RET in ERC buffers, by telling Viper to pass RET through to the
;; normal keymap.
(add-to-list 'viper-major-mode-modifier-list
'(erc-mode insert-state viper-comint-mode-modifier-map))
(add-to-list 'viper-major-mode-modifier-list
'(erc-mode vi-state viper-comint-mode-modifier-map))
(viper-apply-major-mode-modifiers)
;; Ensure that ERC buffers come up in insert state.
(add-to-list 'viper-insert-state-mode-list 'erc-mode)
;; Fix various local variables in Viper.
(add-hook 'erc-mode-hook 'viper-comint-mode-hook)
;; Fix ERC buffers that already exist (buffers in which `erc-mode-hook'
;; has already been run).
(mapc (lambda (buf)
(with-current-buffer buf
(viper-comint-mode-hook)
;; If there *is* a final newline in this buffer, delete it, as
;; it interferes with ERC /-commands.
(let ((last (1- (point-max))))
(when (eq (char-after last) ?\n)
(goto-char last)
(delete-char 1)))))
(erc-buffer-list))
(provide 'erc-viper)
;; arch-tag: 659fa645-e9ad-428c-ad53-8304d9f900f6
;;; erc-viper.el ends here

130
lisp/erc/erc-xdcc.el Normal file
View file

@ -0,0 +1,130 @@
;;; erc-xdcc.el --- XDCC file-server support for ERC
;; Copyright (C) 2003, 2004 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@delysid.org>
;; Keywords: comm, processes
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; This file provides a very simple XDCC file server for the Emacs IRC Client.
;;; Code:
(require 'erc-dcc)
(defcustom erc-xdcc-files nil
"*List of files to offer via XDCC.
Your friends should issue \"/ctcp yournick XDCC list\" to see this."
:group 'erc-dcc
:type '(repeat file))
(defcustom erc-xdcc-verbose-flag t
"*Report XDCC CTCP requests in the server buffer."
:group 'erc-dcc
:type 'boolean)
(defcustom erc-xdcc-handler-alist
'(("help" . erc-xdcc-help)
("list" . erc-xdcc-list)
("send" . erc-xdcc-send))
"*Sub-command handler alist for XDCC CTCP queries."
:group 'erc-dcc
:type '(alist :key-type (string :tag "Sub-command") :value-type function))
(defcustom erc-xdcc-help-text
'(("Hey " nick ", wondering how this works? Pretty easy.")
("Available commands: XDCC ["
(mapconcat 'car erc-xdcc-handler-alist "|") "]")
("Type \"/ctcp " (erc-current-nick)
" XDCC list\" to see the list of offered files, then type \"/ctcp "
(erc-current-nick) " XDCC send #\" to get a particular file number."))
"*Help text sent in response to XDCC help command.
A list of messages, each consisting of strings and expressions, expressions
being evaluated and should return stings."
:group 'erc-dcc
:type '(repeat (repeat :tag "Message" (choice string sexp))))
;;;###autoload
(defun erc-xdcc-add-file (file)
"Add a file to `erc-xdcc-files'."
(interactive "fFilename to add to XDCC: ")
(if (file-exists-p file)
(add-to-list 'erc-xdcc-files file)))
(defun erc-xdcc-reply (proc nick msg)
(process-send-string proc
(format "PRIVMSG %s :%s\n" nick msg)))
;; CTCP query handlers
(defvar erc-ctcp-query-XDCC-hook '(erc-xdcc)
"Hook called whenever a CTCP XDCC message is received.")
(defun erc-xdcc (proc nick login host to query)
"Handle incoming CTCP XDCC queries."
(when erc-xdcc-verbose-flag
(erc-display-message nil 'notice proc
(format "XDCC %s (%s@%s) sends %S" nick login host query)))
(let* ((args (cdr (delete "" (split-string query " "))))
(handler (cdr (assoc (downcase (car args)) erc-xdcc-handler-alist))))
(if (and handler (functionp handler))
(funcall handler proc nick login host (cdr args))
(erc-xdcc-reply
proc nick
(format "Unknown XDCC sub-command, try \"/ctcp %s XDCC help\""
(erc-current-nick))))))
(defun erc-xdcc-help (proc nick login host args)
"Send basic help information to NICK."
(mapc
(lambda (msg)
(erc-xdcc-reply proc nick
(mapconcat (lambda (elt) (if (stringp elt) elt (eval elt))) msg "")))
erc-xdcc-help-text))
(defun erc-xdcc-list (proc nick login host args)
"Show the contents of `erc-xdcc-files' via privmsg to NICK."
(if (null erc-xdcc-files)
(erc-xdcc-reply proc nick "No files offered, sorry")
(erc-xdcc-reply proc nick "Num Filename")
(erc-xdcc-reply proc nick "--- -------------")
(let ((n 0))
(dolist (file erc-xdcc-files)
(erc-xdcc-reply proc nick
(format "%02d. %s"
(setq n (1+ n))
(erc-dcc-file-to-name file)))))))
(defun erc-xdcc-send (proc nick login host args)
"Send a file to NICK."
(let ((n (string-to-number (car args)))
(len (length erc-xdcc-files)))
(cond
((= len 0)
(erc-xdcc-reply proc nick "No files offered, sorry"))
((or (< n 1) (> n len))
(erc-xdcc-reply proc nick (format "%d out of range" n)))
(t (erc-dcc-send-file nick (nth (1- n) erc-xdcc-files) proc)))))
(provide 'erc-xdcc)
;; arch-tag: a13b62fe-2399-4562-af4e-f18a8dd4b9c8
;;; erc-xdcc.el ends here

6144
lisp/erc/erc.el Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,11 @@
2006-01-29 Michael Olson <mwolson@gnu.org>
* makefile.w32-in ($(infodir)/erc, erc.dvi): New targets.
* Makefile.in (INFO_TARGETS, DVI_TARGETS): Add ERC.
* faq.texi (New in Emacs 22): Mention ERC.
2006-01-28 Luc Teirlinck <teirllm@auburn.edu>
* rcirc.texi: Capitalize dir entry for consistency with the entry

View file

@ -42,7 +42,7 @@ INFO_TARGETS = ../info/emacs ../info/emacs-xtra ../info/ccmode ../info/cl \
../info/idlwave ../info/eudc ../info/ebrowse ../info/pcl-cvs \
../info/woman ../info/eshell ../info/org ../info/url \
../info/speedbar ../info/tramp ../info/ses ../info/smtpmail \
../info/flymake ../info/newsticker ../info/rcirc
../info/flymake ../info/newsticker ../info/rcirc ../info/erc
DVI_TARGETS = emacs.dvi calc.dvi cc-mode.dvi cl.dvi dired-x.dvi \
ediff.dvi forms.dvi gnus.dvi message.dvi emacs-mime.dvi \
gnus.dvi message.dvi sieve.dvi pgg.dvi mh-e.dvi \
@ -50,7 +50,7 @@ DVI_TARGETS = emacs.dvi calc.dvi cc-mode.dvi cl.dvi dired-x.dvi \
ada-mode.dvi autotype.dvi idlwave.dvi eudc.dvi ebrowse.dvi \
pcl-cvs.dvi woman.dvi eshell.dvi org.dvi url.dvi \
speedbar.dvi tramp.dvi ses.dvi smtpmail.dvi flymake.dvi \
newsticker.dvi emacs-xtra.dvi rcirc.dvi
newsticker.dvi emacs-xtra.dvi rcirc.dvi erc.dvi
INFOSOURCES = info.texi
# The following rule does not work with all versions of `make'.
@ -332,6 +332,11 @@ newsticker.dvi: newsticker.texi
rcirc.dvi: rcirc.texi
$(ENVADD) $(TEXI2DVI) ${srcdir}/rcirc.texi
../info/erc: erc.texi
cd $(srcdir); $(MAKEINFO) erc.texi
erc.dvi: erc.texi
$(ENVADD) $(TEXI2DVI) ${srcdir}/erc.texi
mostlyclean:
rm -f *.log *.cp *.fn *.ky *.pg *.vr core *.tp *.core gnustmp.*

624
man/erc.texi Normal file
View file

@ -0,0 +1,624 @@
\input texinfo
@c %**start of header
@setfilename ../info/erc
@settitle ERC Manual
@c %**end of header
@dircategory Emacs
@direntry
* ERC: (erc). Powerful, modular, and extensible IRC client for Emacs.
@end direntry
@syncodeindex fn cp
@copying
This manual is for ERC version 5.1.
Copyright @copyright{} 2005, 2006 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.2 or
any later version published by the Free Software Foundation; with no
Invariant Sections, Front-Cover texts, or Back-Cover Texts.
@end quotation
@end copying
@titlepage
@title ERC manual
@subtitle a full-featured IRC client
@subtitle for GNU Emacs and XEmacs
@c The following two commands
@c start the copyright page.
@page
@vskip 0pt plus 1filll
@insertcopying
@end titlepage
@c So the toc is printed at the start
@contents
@ifnottex
@node Top, Introduction, (dir), (dir)
@comment node-name, next, previous, up
@top ERC
@insertcopying
@end ifnottex
@menu
* Introduction:: What is ERC?
* Obtaining ERC:: How to get ERC releases and development
versions.
* Installation:: Compiling and installing ERC.
* Getting Started:: Quick Start guide to using ERC.
* Keystroke Summary:: Keystrokes used in ERC buffers.
* Modules:: Available modules for ERC.
* Advanced Usage:: Cool ways of using ERC.
* Getting Help and Reporting Bugs::
* History:: The history of ERC.
* Concept Index:: Search for terms.
@detailmenu
--- The Detailed Node Listing ---
Obtaining ERC
* Releases:: Released versions of ERC.
* Development:: Latest unreleased development changes.
@end detailmenu
@end menu
@node Introduction, Obtaining ERC, Top, Top
@comment node-name, next, previous, up
@chapter Introduction
ERC is a powerful, modular, and extensible IRC client for Emacs.
It comes with the following capabilities enabled by default.
@itemize @bullet
@item Flood control
@item Timestamps
@item Join channels automatically
@item Buttonize URLs, nicknames, and other text
@item Wrap long lines
@item Highlight or remove IRC control characters
@item Highlight pals, fools, and other keywords
@item Detect netsplits
@item Complete nicknames and commands in a programmable fashion
@item Make displayed lines read-only
@item Input history
@item Track channel activity in the mode-line
@end itemize
@node Obtaining ERC, Installation, Introduction, Top
@comment node-name, next, previous, up
@chapter Obtaining ERC
@menu
* Releases:: Released versions of ERC.
* Development:: Latest unreleased development changes.
@end menu
These sections may be skipped if you are using the version of ERC that
comes with Emacs.
@node Releases, Development, Obtaining ERC, Obtaining ERC
@comment node-name, next, previous, up
@section Releases
Choose to install a release if you want to minimize risk.
Errors are corrected in development first. User-visible changes will be
announced on the @email{erc-help@@lists.sourceforge.net} mailing list.
@pxref{Getting Help and Reporting Bugs}.
@cindex releases, Debian package
@cindex Debian package for ERC
Debian users can get ERC via apt-get. The @file{erc} package is
available in the official Debian repository.
@cindex releases, from source
Alternatively, you can download the latest release from
@uref{http://sourceforge.net/project/showfiles.php?group_id=30118}.
@node Development, , Releases, Obtaining ERC
@comment node-name, next, previous, up
@section Development
@cindex development
Choose the development version if you want to live on the bleeding edge
of ERC development or try out new features before release.
@subsection Using CVS
@cindex CVS, using
ERC is primarily developed using a CVS repository on sourceforge.net.
To check out a copy of the latest changes, do the following.
@example
cvs -d:pserver:anonymous@@cvs.sourceforge.net:/cvsroot/erc login
cvs -z3 -d:pserver:anonymous@@cvs.sourceforge.net:/cvsroot/erc co -P erc
@end example
@cindex CVS snapshot
Alternatively, the latest CVS snapshot may be downloaded in the
following forms.
@itemize @bullet
@item http://mwolson.org/static/dist/erc-latest.tar.gz
@item http://mwolson.org/static/dist/erc-latest.zip
@end itemize
@subsection Using the GNU Arch Revision Control System
@cindex arch revision control system, using
The Arch revision control system allows you to retrieve previous
versions and select specific features and bug fixes.
Michael Olson maintains an official Arch branch for ERC which stays
current with the CVS repository for ERC. If you would like to
contribute to ERC development, and would prefer to use a modern Revision
Control System, feel free to make your own branch.
If you are new to Arch, you might find this tutorial helpful:
@uref{http://www.mwolson.org/projects/ArchTutorial.html}.
Downloading ERC with Arch and staying up-to-date involves the following
steps.
@enumerate
@item Install arch
@itemize @bullet
@item Debian: @kbd{apt-get install tla}.
@item Other distributions: see @uref{ftp://ftp.gnu.org/gnu/gnu-arch/}.
@end itemize
@item Register the archive.
@example
tla register-archive -f http://www.mwolson.org/archives/2006
@end example
@item Download the ERC source code.
@example
# Download ERC into the @file{erc} directory.
tla get mwolson@@gnu.org--2006/erc--cvs--0 erc
@end example
@item List upstream changes that are missing from your local copy.
Do this whenever you want to see whether new changes have been committed
to ERC.
@example
# Change to the source directory you are interested in.
cd erc/
# Display the summary of changes
tla missing --summary
@end example
@cindex updating ERC with Arch
@item Update to the latest version by replaying missing changes.
@example
cd erc
tla replay
@end example
@end enumerate
There are other ways to interact with the ERC archive.
@itemize
@item Browse arch repository: @uref{http://www.mwolson.org/archives/}
@item Latest development snapshot: @uref{http://www.mwolson.org/static/dist/erc-latest.tar.gz}
@end itemize
The latest development snapshot will be kept up-to-date since it is
updated at the same time as the Arch repository.
@node Installation, Getting Started, Obtaining ERC, Top
@comment node-name, next, previous, up
@chapter Installation
ERC may be compiled and installed on your machine.
This section may be skipped if you are using the version of ERC that
comes with Emacs.
@subsubheading Compilation
This is an optional step, since Emacs Lisp source code does not
necessarily have to be byte-compiled. It will yield a speed increase,
though.
A working copy of Emacs or XEmacs is needed in order to compile ERC. By
default, the program that is installed with the name @command{emacs}
will be used.
If you want to use the @command{xemacs} binary to perform the
compilation, you would need to edit @file{Makefile} in the top-level
directory as follows. You can put either a full path to an Emacs or
XEmacs binary or just the command name, as long as it is in the
@env{PATH}.
@example
EMACS = xemacs
SITEFLAG = -no-site-file
@end example
Running @code{make} should compile the ERC source files in the
@file{lisp} directory.
@subsubheading Installation
ERC may be installed into your file hierarchy by doing the following.
Edit the @file{Makefile} file so that @env{ELISPDIR} points to where you
want the source and compiled ERC files to be installed and
@env{INFODIR} indicates where to put the ERC manual. Of course, you
will want to edit @env{EMACS} and @env{SITEFLAG} as shown in the
Compilation section if you are using XEmacs.
If you are installing ERC on a Debian system, you might want to change
the value of @env{INSTALLINFO} as specified in @file{Makefile}.
Run @code{make} as a normal user.
Run @code{make install} as the root user if you have chosen installation
locations that require this.
@node Getting Started, Keystroke Summary, Installation, Top
@comment node-name, next, previous, up
@chapter Getting Started
@cindex settings
@c PRE5_2: Mention .ercrc.el
To use ERC, add the directory containing its files to your
@code{load-path} variable, in your @file{.emacs} file. Then, load ERC
itself along with any extra modules you desire. An example follows.
@lisp
(require 'erc)
(require 'erc-spelling)
@end lisp
Once this is loaded, the command @kbd{M-x erc-select} will start ERC and
prompt for the server to connect to.
@c PRE5_2: Sample session, including:
@c - connect to Freenode
@c - /join #emacs
@c - see messages flying past, point out topic lines, messages, channel
@c members
@c - identifying your nick with NickServ (most IRC servers have this)
@c - talking to the channel
@c - open a /query buffer to talk to someone (must identify first in
@c FreeNode)
@node Keystroke Summary, Modules, Getting Started, Top
@comment node-name, next, previous, up
@chapter Keys Used in ERC
@cindex keystrokes
This is a summary of keystrokes available in every ERC buffer.
@table @kbd
@item C-a or <home> (`erc-bol')
Go to beginning of line or end of prompt.
@item RET (`erc-send-current-line')
Send the current line
@item TAB (`erc-complete-word')
If at prompt, complete the current word.
Otherwise, move to the next link or button.
@item M-TAB (`ispell-complete-word')
Complete the given word, using ispell.
@item C-c C-a (`erc-bol')
Go to beginning of line or end of prompt.
@item C-c C-b (`erc-iswitchb')
Use `iswitchb-read-buffer' to prompt for a ERC buffer to switch to.
@item C-c C-c (`erc-toggle-interpret-controls')
Toggle interpretation of control sequences in messages.
@item C-c C-d (`erc-input-action')
Interactively input a user action and send it to IRC.
@item C-c C-e (`erc-toggle-ctcp-autoresponse')
Toggle automatic CTCP replies (like VERSION and PING).
@item C-c C-f (`erc-toggle-flood-control')
Toggle use of flood control on sent messages.
@item C-c TAB (`erc-invite-only-mode')
Turn on the invite only mode (+i) for the current channel.
@item C-c C-j (`erc-join-channel')
Join channel. If point is at the beginning of a channel name, use that
as default.
@item C-c C-k (`erc-go-to-log-matches-buffer')
Interactively open an erc-log-matches buffer
@item C-c C-l (`erc-save-buffer-in-logs')
Append buffer contents to the log file, if logging is enabled.
@item C-c C-n (`erc-channel-names')
Run "/names #channel" in the current channel.
@item C-c C-o (`erc-get-channel-mode-from-keypress')
Read a key sequence and call the corresponding channel mode function.
After doing C-c C-o type in a channel mode letter.
C-g means quit.
RET let's you type more than one mode at a time.
If "l" is pressed, `erc-set-channel-limit' gets called.
If "k" is pressed, `erc-set-channel-key' gets called.
Anything else will be sent to `erc-toggle-channel-mode'.
@item C-c C-p (`erc-part-from-channel')
Part from the current channel and prompt for a reason.
@item C-c C-q (`erc-quit-server')
Disconnect from current server after prompting for reason.
@item C-c C-r (`erc-remove-text-properties-region')
Clears the region (start,end) in object from all colors, etc.
@item C-c C-t (`erc-set-topic')
Prompt for a topic for the current channel.
@item C-c C-u (`erc-kill-input')
Kill current input line using `erc-bol' followed by `kill-line'.
@end table
@node Modules, Advanced Usage, Keystroke Summary, Top
@comment node-name, next, previous, up
@chapter Modules
@cindex modules
One way to add functionality to ERC is to customize which of its many
modules are loaded.
There is a spiffy customize interface, which may be reached by typing
@kbd{M-x customize-option erc-modules RET}. Alternatively, set
@code{erc-modules} manually and then call @code{erc-update-modules}.
The following is a list of available modules.
@table @code
@cindex modules, autoaway
@item autoaway
Set away status automatically.
@cindex modules, autojoin
@item autojoin
Join channels automatically
@cindex modules, bbdb
@item bbdb
Integrate with the Big Brother Database
@cindex modules, button
@item button
Buttonize URLs, nicknames, and other text
@cindex modules, fill
@item fill
Wrap long lines
@cindex modules, irccontrols
@item irccontrols
Highlight or remove IRC control characters
@cindex modules, log
@item log
Save buffers in logs
@cindex modules, match
@item match
Highlight pals, fools, and other keywords
@cindex modules, netsplit
@item netsplit
Detect netsplits
@cindex modules, noncommands
@item noncommands
Don't display non-IRC commands after evaluation
@cindex modules, notify
@item notify
Notify when the online status of certain users changes
@cindex modules, pcomplete
@item pcomplete
Complete nicknames and commands (programmable)
@cindex modules, readonly
@item readonly
Make displayed lines read-only
@cindex modules, replace
@item replace
Replace text in messages
@cindex modules, ring
@item ring
Enable an input history
@cindex modules, scrolltobottom
@item scrolltobottom
Scroll to the bottom of the buffer
@cindex modules, services
@item services
Identify to Nickserv (IRC Services) automatically
@cindex modules, smiley
@item smiley
Convert smileys to pretty icons
@cindex modules, sound
@item sound
Play sounds when you receive CTCP SOUND requests
@cindex modules, spell
@item spell
Check spelling
@cindex modules, stamp
@item stamp
Add timestamps to messages
@cindex modules, track
@item track
Track channel activity in the mode-line
@cindex modules, truncate
@item truncate
Truncate buffers to a certain size
@cindex modules, unmorse
@item unmorse
Translate morse code in messages
@end table
@c PRE5_2: Document every option of every module in its own subnode
@node Advanced Usage, Getting Help and Reporting Bugs, Modules, Top
@comment node-name, next, previous, up
@chapter Advanced Usage
@cindex advanced topics
Write me.
@c PRE5_2: (Node) Document every ERC option
@c PRE5_2: (Node) Tips and tricks
@c PRE5_2: (Node) Sample configs
@node Getting Help and Reporting Bugs, History, Advanced Usage, Top
@comment node-name, next, previous, up
@chapter Getting Help and Reporting Bugs
@cindex help, getting
@cindex bugs, reporting
After you have read this guide, if you still have questions about ERC,
or if you have bugs to report, there are several places you can go.
@itemize @bullet
@item
@uref{http://www.emacswiki.org/cgi-bin/wiki/EmacsIRCClient} is the
emacswiki.org page for ERC. Anyone may add tips, hints, or bug
descriptions to it.
@item
You can join the mailing list at @email{erc-help@@lists.sourceforge.net}
using the subscription form at
@uref{http://lists.sourceforge.net/lists/listinfo/erc-help}.
This mailing list is also available via Gmane
(@url{http://gmane.org/}). The group is called
@samp{gmane.emacs.erc.general}. This provides additional methods for
accessing the mailing list, adding content to it, and searching it.
@item
You can visit the IRC Freenode channel @samp{#emacs}. Many of the
contributors are frequently around and willing to answer your
questions.
@end itemize
@node History, Concept Index, Getting Help and Reporting Bugs, Top
@comment node-name, next, previous, up
@chapter History
@cindex history, of ERC
ERC was originally written by Alexander L. Belikoff
@email{abel@@bfr.co.il} and Sergey Berezin
@email{sergey.berezin@@cs.cmu.edu}. They stopped development around
december 1999. Their last released version was ERC 2.0.
P.S.: If one of the original developers of ERC reads this, we'd like to
receive additional information for this file and hear comments in
general.
@itemize
@item 2001
In June 2001, Mario Lang @email{mlang@@delysid.org} and Alex Schroeder
@email{alex@@gnu.org} took over development and created a ERC Project at
sourceforge.net.
In reaction to a mail about the new erc development, Sergey Berezin
said, "First of all, I'm glad that my version of ERC is being used out
there. The thing is, I do not have free time and enough incentive
anymore to work on ERC, so I would be happy if you guys take over the
project entirely."
So we happily hacked away on ERC, and soon after (september 2001)
released the next "stable" version, 2.1.
Most of the development of the new ERC happend on #emacs on
irc.openprojects.net. Over time, many people contributed code, ideas,
bugfixes. And not to forget alot of alpha/beta/gamma testing.
See the @file{CREDITS} file for a list of contributors.
@item 2003
ERC 3.0 is released.
@item 2004
ERC 4.0 is released.
@item 2005
ERC 5.0 is released. Michael Olson @email{mwolson@@gnu.org} becomes
the release manager and eventually the maintainer.
After some discussion between him and the Emacs developers, it is
decided to include ERC in Emacs.
@item 2006
ERC 5.1 is released.
@end itemize
@node Concept Index, , History, Top
@comment node-name, next, previous, up
@unnumbered Index
@printindex cp
@bye
@ignore
arch-tag: cf9cfaff-fc12-4297-ad15-ec2493002b1e
@end ignore

View file

@ -1146,7 +1146,7 @@ operation on X. Mouse wheel support is now enabled by default.
@cindex New modes
Many new modes and packages have been included in Emacs, such as Leim,
Calc, Tramp and URL, as well as IDO, CUA, rcirc, conf-mode,
Calc, Tramp and URL, as well as IDO, CUA, rcirc, ERC, conf-mode,
python-mode, table, tumme, SES, ruler, Flymake, Org, etc.
@cindex Documentation

View file

@ -42,7 +42,7 @@ INFO_TARGETS = $(infodir)/emacs $(infodir)/emacs-xtra $(infodir)/ccmode \
$(infodir)/woman $(infodir)/eshell $(infodir)/org \
$(infodir)/url $(infodir)/speedbar $(infodir)/tramp \
$(infodir)/ses $(infodir)/smtpmail $(infodir)/flymake \
$(infodir)/newsticker $(infodir)/rcirc
$(infodir)/newsticker $(infodir)/rcirc $(infodir)/erc
DVI_TARGETS = emacs.dvi calc.dvi cc-mode.dvi cl.dvi dired-x.dvi \
ediff.dvi forms.dvi gnus.dvi message.dvi emacs-mime.dvi \
gnus.dvi message.dvi sieve.dvi pgg.dvi mh-e.dvi \
@ -50,7 +50,7 @@ DVI_TARGETS = emacs.dvi calc.dvi cc-mode.dvi cl.dvi dired-x.dvi \
ada-mode.dvi autotype.dvi idlwave.dvi eudc.dvi ebrowse.dvi \
pcl-cvs.dvi woman.dvi eshell.dvi org.dvi url.dvi \
speedbar.dvi tramp.dvi ses.dvi smtpmail.dvi flymake.dvi \
newsticker.dvi emacs-xtra.dvi rcirc.dvi
newsticker.dvi emacs-xtra.dvi rcirc.dvi erc.dvi
INFOSOURCES = info.texi
# The following rule does not work with all versions of `make'.
@ -336,6 +336,11 @@ $(infodir)/rcirc: rcirc.texi
rcirc.dvi: rcirc.texi
$(ENVADD) $(TEXI2DVI) $(srcdir)/rcirc.texi
$(infodir)/erc: erc.texi
$(MAKEINFO) erc.texi
erc.dvi: erc.texi
$(ENVADD) $(TEXI2DVI) $(srcdir)/erc.texi
mostlyclean:
- $(DEL) *.log *.cp *.fn *.ky *.pg *.vr core *.tp *.core gnustmp.*