2011-02-02

extending ERC with your own commands

ERC is the leading Emacs-based IRC-client; I already discussed ERC before. I have been using ERC a lot in recent times, as it's an essential way to communicate at work with team members in remote locations. There are other IRC-clients – most people around me seem to use either irssi or xchat, but these don't integrate so well with my emacs-based workflow, the easy with which it can be extended to do exactly what I want; in this although they have their own strenghts. One of the great strengths of ERC is article I give some examples.

Apart from chatting, you can send commands (long list) to the IRC-server, for example to request information about other users, change your 'nick', leave the channel, and so on. As in most IRC-clients, you can send these commands with ERC by prefixing them with /, so you'd type:

/nick ninjaturtle

to change your nickname.

The nice thing about ERC is how easy it to add your own commands to this. In your .emacs (after loading ERC), you can add something like:

(defun erc-cmd-MYSYSTEM ()
  "show some information about my system"
  (let ((str (shell-command-to-string "uname -a")))
    (when str (erc-send-message str))))

Or, add add a function called erc-cmd-XXXX (with the XXXX being the command name in capitals, will add command XXXX, which you can invoke with /XXXX or /xxxx). So, with the above function, I can now do something like:

ERC> /mysystem
<djcb> Linux cthulhu 2.6.35-25-generic #44 SMP Fri Jan 21 17:40:48 UTC
       2011 i686 GNU/Linux

Let's look at some other (somewhat) useful command: /calc; again, just a small example, I'm sure something can come up with something a bit more elegant - perhaps using emacs' built-in calc.

(defun erc-cmd-CALC (&rest args)
  "calculate value of some expression using bc"
  (let ((expr (mapconcat 'identity args " ")))
    (when (length expr)
      (let ((result (shell-command-to-string (concat "echo '" expr "' | bc "))))
        (when result (erc-send-message (concat expr " = " result)))))))
ERC> /calc 2 * (3 + 4) / 7
<djcb> 2 * (3 + 4) / 7  = 2

Now, a small warning, just because it's easy to dump the output of, say, cowsay in an IRC-channel using your own /cowsay command, does not mean it is a good idea – in fact, using something like that is guaranteed to get you kicked out fairly quickly from many channels.

That being said, I'm sure many people have come up with much more clever things than the examples here; feel free to share your inventions in the comments!

4 comments:

Anonymous said...

Have you ever tried rcirc? It's builtin to Emacs, too (yes, Emacs inclues 2 irc clients).

It's much, much, much simpler than ERC. Like 1 file, I think. Easy to extend and read. Highly recommended.

http://www.emacswiki.org/emacs/rcirc

thisirs said...

A quite complicated hack to have comma separated nickname list when replying to several people.
So
blahnick: fooni< TAB >
becomes
blahnick, foonick:

(defun pcomplete-erc-command-name ()
"Returns the command name of the first argument."
(let ((cmd (pcomplete-arg 'first)))
(cond
((member (substring cmd 0 -1)
(pcomplete-erc-nicks))
"NICKLIST")
((eq (elt cmd 0) ?/)
(upcase (substring cmd 1)))
(t "SAY"))))

(defun is-nick-p (nick)
(member (substring nick 0 -1)
(pcomplete-erc-nicks)))

(defun pcomplete/erc-mode/NICKLIST ()
(while (and (pcomplete-test 'is-nick-p)
(or (= pcomplete-index pcomplete-last) (pcomplete-test 'is-nick-p 0)))
(let ((start erc-input-marker))
(save-excursion
(goto-char (pcomplete-begin 0))
(while (re-search-backward ": " start t)
(replace-match ", "))))
(pcomplete-here (pcomplete-erc-nicks ": ")))
(while (pcomplete-here (pcomplete-erc-nicks))))

Brendan Miller said...

Have you had luck with any emacs based jabber clients? I tend to use jabber much more than IRC.

djcb said...

@Brendan Miller: I am using jabber indirectly, using bitlbee. This works quite well for jabber, incl. gtalk/facebook etc.