Finally do something about the famous "midnight bug"
[syinit] / 16-riece-sy.el
1 ;; 16-riece-sy.el --- Riece (IRC) Settings   -*- Emacs-Lisp -*-
2
3 ;; Copyright (C) 2007 - 2012 Steve Youngs
4
5 ;;     Author: Steve Youngs <steve@sxemacs.org>
6 ;; Maintainer: Steve Youngs <steve@sxemacs.org>
7 ;;    Created: <2007-12-02>
8 ;; Time-stamp: <Saturday Jun 23, 2012 12:30:35 steve>
9 ;;   Download: <http://bastard.steveyoungs.com/~steve/SXEmacs/inits/>
10 ;;   HTMLised: <http://bastard.steveyoungs.com/~steve/SXEmacs/htmlinits/16-riece-sy.html>
11 ;;   Git Repo: git clone http://git.sxemacs.org/syinit
12 ;;   Keywords: init, compile
13
14 ;; This file is part of SYinit
15
16 ;; Redistribution and use in source and binary forms, with or without
17 ;; modification, are permitted provided that the following conditions
18 ;; are met:
19 ;;
20 ;; 1. Redistributions of source code must retain the above copyright
21 ;;    notice, this list of conditions and the following disclaimer.
22 ;;
23 ;; 2. Redistributions in binary form must reproduce the above copyright
24 ;;    notice, this list of conditions and the following disclaimer in the
25 ;;    documentation and/or other materials provided with the distribution.
26 ;;
27 ;; 3. Neither the name of the author nor the names of any contributors
28 ;;    may be used to endorse or promote products derived from this
29 ;;    software without specific prior written permission.
30 ;;
31 ;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
32 ;; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
33 ;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
34 ;; DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
35 ;; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
36 ;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
37 ;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
38 ;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
39 ;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
40 ;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
41 ;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42
43 ;;; Commentary:
44 ;;
45 ;;   My Riece settings.
46 ;;
47 ;;   Riece is a very nice IRC client for emacs.  Unlike ERC which
48 ;;   tries to be like "traditional" IRC clients, Riece is much more
49 ;;   emacs like.
50 ;;
51
52 ;;; Credits:
53 ;;
54 ;;   The HTML version of this file was created with Hrvoje Niksic's
55 ;;   htmlize.el which is part of the XEmacs "text-modes" package.
56 ;;
57
58 ;;; Todo:
59 ;;
60 ;;     
61
62 ;;; Code:
63 (require 'riece-options)
64 (require 'riece-biff)
65 (require 'riece-log)
66 (require 'riece)
67
68 ;; Misc setq's
69 (setq riece-alias-percent-hack-mask "*.net"
70       riece-biff-check-channels '("#sxemacs"
71                                   ;"#harmattan"
72                                   ;"#meego"
73                                   ;"#n9"
74                                   "#emchat"
75                                   ;"#xwem"
76                                   ;"#fresse"
77                                   "#xemacs")
78       riece-channel-buffer-mode t
79       riece-default-channel-binding nil
80       riece-default-coding-system 'binary
81       riece-gather-channel-modes t
82       riece-ignore-discard-message nil
83       riece-keywords '("JackaLX" "jackalx" "Eicq" "eicq" "EMchat" "emchat"
84                        "SXEmacs" "sxemacs" "XWEM" "xwem" "XLIB" "xlib" "tla"
85                        "arch" "xtla" "XEtla" "xetla" "eMoney" "emoney"
86                        "JackaLX_N9" "jackalx_n9")
87       riece-layout '"bottom-right"
88       riece-retry-with-new-nickname t
89       riece-server-alist
90       '(("irc.sxemacs.org" :host "irc.sxemacs.org")
91         ("irc.au.freenode.net" :host "irc.au.freenode.net")
92         ("azimov.freenode.net" :host "azimov.freenode.net")
93         ("brin.freenode.net" :host "brin.freenode.net")
94         ("irc.freenode.org" :host "irc.freenode.org")
95         ("irc.freenode.net" :host "irc.freenode.net")
96         ("kornbluth.freenode.net" :host "kornbluth.freenode.net")
97         ("orwell.freenode.net" :host "orwell.freenode.net")
98         ("calvino.freenode.net" :host "calvino.freenode.net")
99         ("wells.freenode.net" :host "wells.freenode.net")
100         ("zelazny.freenode.net" :host "zelazny.freenode.net")
101         ("anthony.freenode.net" :host "anthony.freenode.net")
102         ("irc.nac.net" :host "irc.nac.net")
103         ("irc.efnet.org" :host "irc.efnet.org")
104         ("irc.efnet.net" :host "irc.efnet.net"))
105       riece-user-agent 'emacs-riece-config
106       riece-user-list-buffer-mode t)
107
108 ;; Addons
109 (riece-command-insinuate-addon 'riece-yank)
110 (riece-command-insinuate-addon 'riece-hangman)
111 (riece-command-insinuate-addon 'riece-keepalive)
112 (riece-command-insinuate-addon 'riece-shrink-buffer)
113 (riece-command-insinuate-addon 'riece-xfaceb)
114 (riece-command-insinuate-addon 'riece-button)
115 (riece-command-insinuate-addon 'riece-epg)
116
117 (riece-command-enable-addon 'riece-hangman)
118
119 ;; Leave this OFF it is too annoying.  Fun, but annoying.
120 ;; (riece-command-insinuate-addon 'riece-doctor)
121 ;; (riece-command-enable-addon 'riece-doctor)
122
123 ;; A few handy functions that extend Riece's features a bit.
124 (defvar riece-unread-channels)
125 (defun sy-riece-clear-unread-chans ()
126   "Get rid of the unread mark on all channels."
127   (interactive)
128   (let ((current riece-current-channel))
129     (setq riece-unread-channels nil)
130     (riece-switch-to-channel current)))
131
132 (defun sy-riece-relist-chans-clear-blanks ()
133   "Relist the channel buffer removing any blanks in the sequence.
134
135 When you part from a channel/user you are left with a gap in the
136 sequence of channel numbers in the channels buffer.  This removes
137 those gaps."
138   (interactive)
139   (let ((current riece-current-channel))
140     (setq riece-current-channels
141           (remove-if #'null riece-current-channels))
142     (riece-switch-to-channel current)))
143
144 (defun sy-riece-command-memoserv (command)
145   "Send COMMAND, a string, to MEMOSERV.
146
147 With prefix arg, also /join."
148   (interactive "sMemoserv: ")
149   (when current-prefix-arg
150     (riece-command-join ["MemoServ" ""]))
151   (riece-send-string (format "MEMOSERV %s\r\n" command)))
152
153 (defun sy-riece-command-chanserv (command)
154   "Send COMMAND, a string, to CHANSERV.
155
156 With prefix arg, also /join."
157   (interactive "sChanserv: ")
158   (when current-prefix-arg
159     (riece-command-join ["ChanServ" ""]))
160   (riece-send-string (format "CHANSERV %s\r\n" command)))
161
162 (defun sy-riece-command-nickserv (command)
163   "Send COMMAND, a string, to NICKSERV.
164
165 With prefix arg, also /join."
166   (interactive "sNickserv: ")
167   (when current-prefix-arg
168     (riece-command-join ["NickServ" ""]))
169   (riece-send-string (format "NICKSERV %s\r\n" command)))
170
171 (defun sy-riece-command-seenserv (command)
172   "Send COMMAND, a string, to SEENSERV.
173
174 With prefix arg, also /join."
175   (interactive "sSeenserv: ")
176   (when current-prefix-arg
177     (riece-command-join ["SeenServ" ""]))
178   (riece-send-string (format "SEENSERV %s\r\n" command)))
179
180 (defun sy-riece-command-quick-op ()
181   "Request Ops from ChanServ in the current channel."
182   (interactive)
183   (let ((chan (riece-identity-prefix riece-current-channel)))
184     (sy-riece-command-chanserv (format "OP %s" chan))))
185
186 (defun sy-riece-command-mute-user (&optional user unmute)
187   "Set mode +q on USER, effectively muting them.
188
189 Optional prefix arg, UNMUTE to let them speak again."
190   (interactive "i\nP")
191   (let ((user (or user
192                   (completing-read
193                    "(Un)Mute user: "
194                    (riece-with-server-buffer
195                        (riece-identity-server riece-current-channel)
196                      (riece-channel-get-users (riece-identity-prefix
197                                                riece-current-channel)))))))
198     (riece-send-string 
199      (format "MODE %s %sq %s\r\n"
200              (riece-identity-prefix riece-current-channel)
201              (if (or unmute
202                      current-prefix-arg)
203                  "-"
204                "+")
205              user))))
206
207 (defun sy-riece-list-banned (channel)
208   "List the banned users on CHANNEL, current if omitted."
209   (interactive "P")
210   (let ((channel (if current-prefix-arg
211                      (vector (read-string "Channel: ") "")
212                    riece-current-channel)))
213     (riece-send-string
214      (format "MODE %s b\r\n" (riece-identity-prefix channel)))))
215
216 (defun sy-riece-command-ban-user (&optional user unban)
217   "Ban USER from current channel.
218
219 Optional prefix arg, UNBAN removes the ban."
220   (interactive "i\nP")
221   (let ((user (or user
222                   (completing-read
223                    "(Un)Ban user: "
224                    (riece-with-server-buffer
225                        (riece-identity-server riece-current-channel)
226                      (riece-channel-get-users (riece-identity-prefix
227                                                riece-current-channel))))))
228         reason)
229     (if (or unban
230             current-prefix-arg)
231         (riece-send-string
232          (format "MODE %s -b %s\r\n"
233                  (riece-identity-prefix riece-current-channel)
234                  user))
235       (setq reason (read-string "Reason: " nil nil
236                                 "Need a reason?  Look in a mirror!"))
237       (riece-send-string
238        (format "MODE %s +b %s\r\n"
239                (riece-identity-prefix riece-current-channel)
240                user))
241       (riece-command-kick user reason))))
242
243 ;; Share the muzak!
244 (defun sy-riece-say-now-playing (&optional notice)
245   "Say into the current channel what mp3 is playing.
246
247 With non-nil optional prefix arg, NOTICE, send it as a notice."
248   (interactive "P")
249   (let ((song (if **mpd-var-Title*
250                   (format "%s --- [%s]"
251                           **mpd-var-Title*
252                           **mpd-var-Artist*)
253                 "The Sounds of Silence --- [Marcel Marceau]")))
254     (riece-command-send-message (format "NP: %s" song) 
255                                 (if current-prefix-arg
256                                     'notice
257                                   nil))))
258
259 (defun sy-riece-say-all-purpose (&optional notice)
260   "Send the all-purpose answer to everything."
261   (interactive "P")
262   (riece-command-send-message "Adolf Hitler in fishnets"
263                               (if current-prefix-arg
264                                   'notice
265                                 nil)))
266   
267
268 ;; Tell the world what we're using.
269 (defun sy-riece-say-version (&optional notice)
270   "Say the version of Riece we are running.
271
272 With non-nil prefix arg, NOTICE, send as a notice."
273   (interactive "P")
274   (riece-command-send-message
275    (format "I'm using: %s" (riece-extended-version))
276    (if current-prefix-arg
277        'notice
278      nil)))
279
280 ;; say (foo) => bar
281 (defun sy-riece-send-form ()
282   "Sends a form and it's eval"
283   (interactive)
284   (let* ((form (read-string "sexp: "))
285          (value (eval (read form))))
286     (riece-command-send-message (format "%s => %s" form value)
287                                 (if current-prefix-arg
288                                     'notice
289                                   nil))))
290
291 (defun sy-make-rot13-translation-table ()
292   "Create a rot13 table."
293   (let ((i -1)
294         (table (make-string 256 0))
295         (a (char-to-int ?a))
296         (A (char-to-int ?A)))
297     (while (< (incf i) 256)
298       (aset table i i))
299     (concat
300      (substring table 0 A)
301      (substring table (+ A 13) (+ A 13 (- 26 13)))
302      (substring table A (+ A 13))
303      (substring table (+ A 26) a)
304      (substring table (+ a 13) (+ a 13 (- 26 13)))
305      (substring table a (+ a 13))
306      (substring table (+ a 26) 255))))
307
308 (defun sy-rot13-string (string)
309   "Convert TEXT to rot13-ese."
310   (let ((table (sy-make-rot13-translation-table)))
311     (with-temp-buffer
312       (insert string)
313       (translate-region (point-min) (point-max) table)
314       (buffer-string))))
315
316 (defun sy-riece-send-rot13 (text)
317   "Talk in rot13-ese."
318   (interactive "srot13: ")
319   (riece-command-send-message
320    (sy-rot13-string text)
321    (if current-prefix-arg
322        'notice
323      nil)))
324
325 (defun sy-morse-string (string)
326   "Return STRING in morse code."
327   (with-temp-buffer
328     (insert string)
329     (morse-region (point-min) (point-max))
330     (goto-char (point-min))
331     (while (re-search-forward "/" nil t)
332       (replace-match " "))
333     (buffer-string)))
334
335 (defun sy-riece-send-morse (text)
336   "Talk in morse code."
337   (interactive "sMorse: ")
338   (riece-command-send-message
339    (sy-morse-string text)
340    (if current-prefix-arg
341        'notice
342      nil)))
343
344 ;; Show off!
345 (autoload 'riece-command-ctcp-action "riece-ctcp" nil t)
346 (defun sy-riece-show-off ()
347   "Brag about how many channels/people we're talking to."
348   (interactive)
349   (sy-riece-relist-chans-clear-blanks)
350   (let* ((channels riece-current-channels)
351          (numchans (length channels))
352          (numppl 0)
353          currchan)
354     (while channels
355       (setq currchan (car channels))
356       (setq numppl (+ numppl
357                       (length (riece-with-server-buffer
358                                   (riece-identity-server currchan)
359                                 (riece-channel-get-users 
360                                  (riece-identity-prefix currchan))))))
361       (setq channels (cdr channels)))
362     (riece-command-ctcp-action
363      riece-current-channel
364      (format
365       "is in %d channels, talking to %d people :-P"
366       numchans numppl))))
367
368 ;; Brag about how long SXEmacs has been up
369 (defun sy-riece-sxe-uptime ()
370   "Display as action SXEmacs uptime."
371   (interactive)
372   (let* ((ut (uptime))
373          (days (car ut))
374          (hours (cadr ut))
375          (minutes (caddr ut))
376          (seconds (cadddr ut)))
377     (riece-command-ctcp-action
378      riece-current-channel
379      (concat "-=[ SXEmacs Uptime: "
380              (unless (zerop days)
381                (if (eq days 1)
382                    "1 day, "
383                  (concat (number-to-string days) " days, ")))
384              (unless (zerop hours)
385                (if (eq hours 1)
386                    "1 hour, "
387                  (concat (number-to-string hours) " hours, ")))
388              (unless (zerop minutes)
389                (if (eq minutes 1)
390                    "1 minute, "
391                  (concat (number-to-string minutes) " minutes, ")))
392              (if (zerop seconds)
393                  "and 0 seconds"
394                (if (eq seconds 1)
395                    "and 1 second."
396                  (concat "and "
397                          (number-to-string seconds)
398                          " seconds")))
399              " ]=-"))))
400       
401
402 ;; segassem desrever eikeeg ylbirreT
403 (defun sy-riece-reverse ()
404   ".sdrawkcab kaepS"
405   (interactive)
406   (let ((str (read-string "Say backwards: ")))
407     (riece-command-send-message
408      (concat (nreverse (string-to-list str))) nil)))
409
410 ;; .oO0{ what's he thinking? }
411 (defun sy-riece-think ()
412   "Send a .oO0{ think balloon action }."
413   (interactive)
414   (let ((think (read-string "What are you thinking? ")))
415     (riece-command-ctcp-action
416      riece-current-channel
417      (format ".oO0{ %s }" think))))
418
419 ;; When pictures speak louder than words...
420 (defun sy-riece-fuck-you (&optional upyours)
421   "For those occasions where... you know what I mean."
422   (interactive "P")
423   (let ((fuckyou "
424      _                         _
425     |_|                       |_|
426     | |         /^^^\\         | |
427    _| |_      (| \"o\" |)      _| |_
428  _| | | | _    (_---_)    _ | | | |_
429 | | | | |' |    _| |_    | `| | | | |
430 |          |   /     \\   |          |
431  \\        /  / /(. .)\\ \\  \\        /
432    \\    /  / /  | . |  \\ \\  \\    /
433      \\  \\/ /    ||Y||    \\ \\/  /
434       \\__/      || ||      \\__/
435                 () ()
436                 || ||
437                ooO Ooo")
438         (upyours "
439     .-.    
440     |U|    
441     | |    
442     | |    
443    _| |_   
444   | | | |-.
445  /|     ` |
446 | |       |
447 |         |
448 \\         /
449  |       | 
450  |       |")
451         (riece-yank-tick 0.1))
452     (with-temp-buffer
453       (if current-prefix-arg 
454           (insert upyours)
455         (insert fuckyou))
456       (kill-region (point-min) (point-max)))
457     (riece-command-yank nil nil)))
458
459 ;; Nick completion.  Lets face it, compared to other IRC clients like
460 ;; BitchX or even ERC, Riece's nick completion is pretty sucky. :-(
461 ;; This is my vain attempt to improve it.
462 (defun sy-riece-command-complete-user ()
463   "Like `riece-command-complete-user' but restrict to current chan.
464
465 This version of nick completion maintains the original case of the
466 nick being completed.  The version in Riece downcases the completion
467 \(could be a bug\).
468
469 If the completion is being inserted at column zero, `: ' is appended,
470 otherwise ` ' is added.
471
472 The following is not yet implemented, but I'd also like to be able to
473 complete from the middle of a nick...
474
475   Nickname     User Types      Expands To
476   --------     ----------      ----------
477   MyNick        nic<TAB>       MyNick:<SPC>"
478   (interactive)
479   (let* ((completion-ignore-case t)
480          (table (riece-with-server-buffer
481                     (riece-identity-server riece-current-channel)
482                   (riece-channel-get-users (riece-identity-prefix
483                                             riece-current-channel))))
484          (current (or (current-word) ""))
485          (completion (try-completion current table))
486          (all (all-completions current table)))
487     (if (eq completion t)
488         nil
489       (if (null completion)
490           (message "Can't find completion for \"%s\"" current)
491         (if (equal current completion)
492             (with-output-to-temp-buffer "*Help*"
493               (display-completion-list all))
494           (re-search-forward "\\>" nil t)
495           (delete-region (point) (- (point) (length current)))
496           (if (eq (point) (point-at-bol))
497               (insert completion ": ")
498             (insert completion " ")))))))
499
500 ;(defalias 'riece-command-complete-user 'sy-riece-command-complete-user)
501
502 ;; "schme" <marcus@sxemacs.org> funky cycling completion
503 ;; Reworked to support cycling in both directions using dllists, plus
504 ;; other misc improvements by me. --SY.
505 (defvar riece-me:completion-time 3
506   "Time in seconds before completion list is reset.")
507 (defvar riece-me:*completion-timer* (make-itimer)
508   "Completion timer.")
509 (defvar riece-me:*completion-list* nil
510   "Completion list.")
511
512 (defvar sy-riece-nick-syntax-table
513   (let ((table (copy-syntax-table text-mode-syntax-table)))
514     (modify-syntax-entry ?~  "w " table)
515     (modify-syntax-entry ?`  "w " table)
516     (modify-syntax-entry ?-  "w " table)
517     (modify-syntax-entry ?_  "w " table)
518     (modify-syntax-entry ?+  "w " table)
519     (modify-syntax-entry ?{  "w " table)
520     (modify-syntax-entry ?[  "w " table)
521     (modify-syntax-entry ?}  "w " table)
522     (modify-syntax-entry ?]  "w " table)
523     (modify-syntax-entry ?\\ "w " table)
524     (modify-syntax-entry ?|  "w " table)
525     (modify-syntax-entry ?:  "w " table)
526     (modify-syntax-entry ?\; "w " table)
527     (modify-syntax-entry ?'  "w " table)
528     (modify-syntax-entry ?<  "w " table)
529     (modify-syntax-entry ?,  "w " table)
530     (modify-syntax-entry ?>  "w " table)
531     table)
532   "Syntax table used in funky nick cycling completion.")
533
534 (defun sy-riece-init-completion-timer ()
535   "Initialise the completion timer."
536   (let ((timer riece-me:*completion-timer*))
537     (set-itimer-function timer #'(lambda ()
538                                    (setq riece-me:*completion-list* nil)))
539     (set-itimer-value timer riece-me:completion-time)))
540 (add-hook 'riece-after-login-hook #'sy-riece-init-completion-timer)
541
542 (defsubst sy-riece-cycle-list (list &optional reverse)
543   "Return a list of head of LIST, and LIST rotated 1 place forward.
544
545 If optional argument, REVERSE is non-nil, rotate the list in the other
546 direction."
547   (let ((list (apply #'dllist list))
548         name)
549     (if reverse
550         (dllist-rrotate list)
551       (dllist-lrotate list))
552     (setq name (dllist-car list))
553     (list name (dllist-to-list list))))
554
555 (defsubst sy-riece-set-completion-timer ()
556   "(Re)set completion timer's value."
557   (let ((timer riece-me:*completion-timer*))
558     (and (itimerp timer)
559          (set-itimer-value timer riece-me:completion-time))))
560
561 (defun sy-riece-complete-user-backwards ()
562   "Complete nick, cycling backwards.
563 See `riece-me:command-complete-user'."
564   (interactive)
565   (riece-me:command-complete-user 'reverse))
566
567 (add-hook 'riece-command-mode-hook
568           #'(lambda ()
569               (local-set-key [iso-left-tab] #'sy-riece-complete-user-backwards)))
570
571 (defun riece-me:command-complete-user (&optional reverse)
572   "Like `riece-command-complete-user' but restrict to current chan.
573
574 This completion does not pop up any completion buffers, instead it
575 cycles through the user names \"in-place\" with each successive TAB.
576
577 With non-nil optional argument, REVERSE, the cycling goes in the other
578 direction.
579
580 If the completion is being inserted at column zero, \": \" is appended,
581 otherwise \" \" is added. "
582   (interactive)
583   (unless riece-me:*completion-list*
584     (unless (itimer-live-p riece-me:*completion-timer*)
585       (sy-riece-set-completion-timer)
586       (activate-itimer riece-me:*completion-timer*))
587     (let* ((completion-ignore-case t)
588            (table (riece-with-server-buffer
589                       (riece-identity-server riece-current-channel)
590                     (riece-channel-get-users (riece-identity-prefix
591                                               riece-current-channel))))
592            (current (current-word))
593            (completion (try-completion current table))
594            (all (all-completions current table)))
595       (if (null completion)
596           (message "Can't find completion for \"%s\"" current)
597         (setq riece-me:*completion-list* all))))
598   (when riece-me:*completion-list*
599     (multiple-value-bind (completion newlist)
600         (sy-riece-cycle-list riece-me:*completion-list* reverse)
601       (setq riece-me:*completion-list* newlist)
602       (with-syntax-table sy-riece-nick-syntax-table
603         (unless (string= "" (current-word))
604           (backward-delete-word))
605         (insert completion)
606         (let ((nicksuffix " "))
607           (save-excursion
608             (backward-word)
609             (and (bolp)
610                  (setq nicksuffix ": ")))
611           (insert nicksuffix)))
612       (sy-riece-set-completion-timer))))
613
614 (defalias 'riece-command-complete-user 'riece-me:command-complete-user)
615 ;;;
616
617 (defun sy-riece-add-rem-biff-channel (&optional remove)
618   "Add the current channel to the list of channels for riece-biff.
619
620 With optional prefix arg, REMOVE, remove the current channel from the
621 biff list."
622   (interactive "P")
623   (if (or current-prefix-arg
624           remove)
625       ;; Remove chan.
626       (progn
627         (setq riece-biff-check-channels
628               (remove (riece-identity-prefix riece-current-channel)
629                       riece-biff-check-channels))
630         (message "Channel: %s removed from riece-biff channel list."
631                  (riece-identity-prefix riece-current-channel)))
632     ;; Add chan.
633     (add-to-list 'riece-biff-check-channels
634                  (riece-identity-prefix riece-current-channel))
635     (message "Channel: %s added to riece-biff channel list."
636              (riece-identity-prefix riece-current-channel))))
637
638
639 ;; Define keys for those functions.
640 (define-key riece-command-map (kbd "C-c C") #'sy-riece-clear-unread-chans)
641 (define-key riece-command-map (kbd "C-c r")
642   #'sy-riece-relist-chans-clear-blanks)
643 (define-key riece-command-map (kbd "C-c m") #'sy-riece-command-mute-user)
644 (define-key riece-command-map (kbd "C-b") #'sy-riece-command-ban-user)
645 (define-key riece-command-map (kbd "C-o") #'sy-riece-command-quick-op)
646 (define-key riece-command-map (kbd "C-c n") #'sy-riece-say-now-playing)
647 (define-key riece-command-map (kbd "C-c V") #'sy-riece-say-version)
648 (define-key riece-command-map (kbd "C-c s") #'sy-riece-show-off)
649 (define-key riece-command-map (kbd "C-c f") #'sy-riece-fuck-you)
650 (define-key riece-command-map (kbd "C-c b") #'sy-riece-add-rem-biff-channel)
651 (define-key riece-command-map (kbd "C-c ?") #'sy-riece-think)
652 (define-key riece-command-map (kbd "C-c R") #'sy-riece-reverse)
653 (define-key riece-command-map (kbd "C-c U") #'sy-riece-sxe-uptime)
654 (define-key riece-command-map [a] #'sy-riece-say-all-purpose)
655
656 ;; So I can start Riece in a new frame
657 (defvar riece-frame nil
658   "Frame for Riece.")
659
660 (defun sy-riece (&optional ask)
661   "Run Riece in a new frame.
662
663 With non-nil optional prefix ASK Riece will prompt for a server to
664 connect to."
665   (interactive "P")
666   (let ((riece-server (if current-prefix-arg
667                           nil
668                         "irc.sxemacs.org")))
669     (setq riece-frame (new-frame '((name . "RieceFrame"))))
670     (select-frame riece-frame)
671     (call-interactively 'riece)
672     (focus-frame riece-frame)))
673
674 (defun sy-riece-exit-hook ()
675   (when (frame-live-p riece-frame)
676     (delete-frame riece-frame))
677   (setq riece-frame nil))
678
679 (add-hook 'riece-exit-hook #'sy-riece-exit-hook)
680
681 ;; riece-startup-channel-list doesn't fit in with the way I do things
682 ;; and the way freenode functions.  It gets called too damned early.
683 ;; What follows is my attempt to make Riece behave better with logging
684 ;; into freenode, registering to nickserv, joining initial channels,
685 ;; and getting ops with chanserv.
686 (defvar sy-riece-startup-channel-list
687   '("#sxemacs"
688     "#emchat"
689     ;"#xwem"
690     ;"#fresse"
691     ;"#xemacs"
692     ;"#emacs"
693     "#harmattan"
694     "#meego"
695     "#n9"
696     ;"#e"
697     ;"#pulseaudio"
698     ;"#latex"
699     ;"#iptables"
700     ;"#netfilter"
701     ;"#postgresql"
702     ;"##c"
703     ;"##kernel"
704     ;"#linux-kernel"
705     ;"#glibc"
706     ;"#gcc"
707     ;"#zsh"
708     )
709   "List of channels to join after logging in and identifying to nickserv.")
710
711 ;; Set up channel coding systems
712 ;;
713 ;; This is a PITA... turn on utf and can't read iso-8859-1 special
714 ;; chars, turn it off and can't read utf.  Have I mentioned how much I
715 ;; hate this crap? --SY.
716 (mapcar
717  #'(lambda (chan)
718      (if (string-match #r"#\(sxemacs\|e\(mchat\|icq\)\|xwem\|fresse\)" chan)
719          (push (cons chan 'iso-8859-1) riece-channel-coding-system-alist)
720        (push (cons chan 'utf-8) riece-channel-coding-system-alist)))
721  sy-riece-startup-channel-list)
722
723 (defun sy-riece-login ()
724   (riece-send-string (format "PRIVMSG NickServ :identify %s\r\n"
725                              (getenv "IRCPASSWD")))
726   (sleep-for 3)
727   (let ((channel-list sy-riece-startup-channel-list)
728         entry identity)
729     (while channel-list
730       (unless (listp (setq entry (car channel-list)))
731         (setq entry (list (car channel-list))))
732       (if (equal (riece-identity-server
733                   (setq identity (riece-parse-identity (car entry))))
734                  riece-server-name)
735           (riece-command-join-channel identity (nth 1 entry)))
736       (setq channel-list (cdr channel-list))))
737   (riece-send-string "PRIVMSG ChanServ :op #sxemacs\r\n")
738   (riece-send-string "PRIVMSG ChanServ :op #emchat\r\n"))
739   ;(riece-send-string "PRIVMSG ChanServ :op #xwem\r\n")
740   ;(riece-send-string "PRIVMSG ChanServ :op #fresse\r\n")
741   ;(riece-send-string "PRIVMSG ChanServ :op #xemacs\r\n"))
742
743 (add-hook 'riece-after-login-hook #'sy-riece-login)
744
745 ;; Until I can find a solution to my hook problem (login hook not
746 ;; running to completion) I use this to finish the job
747 (defun sy-riece-cleanup-login ()
748   (interactive)
749   (riece-command-switch-to-channel-by-number 2)
750   (riece-part-channel riece-current-channel)
751   ;(riece-part-channel ["MemoServ" ""])
752   (riece-part-channel ["ChanServ" ""])
753   (riece-part-channel ["NickServ" ""])
754   (sy-riece-relist-chans-clear-blanks)
755   (riece-command-switch-to-channel-by-number 1))
756
757 ;(add-hook 'riece-after-login-hook #'sy-riece-cleanup-login 'append)
758
759 (define-key riece-command-map (kbd "C-c l") 'sy-riece-cleanup-login)
760
761 ;; Automatically clear Riece Biff indicator by switching to the right
762 ;; window/frame
763 (defun sy-riece-check-command-buffer ()
764   (and (get-buffer-window (or riece-command-buffer "*Command*"))
765        (riece-biff-clear)))
766
767 (defadvice switch-to-buffer (after riece-update (&rest args) activate)
768   "After switching buffers, check to see if riece-biff should be cleared.
769 The riece-biff modeline indicator will only be cleared if
770 `riece-command-buffer' is visible in the selected frame."
771   (sy-riece-check-command-buffer))
772
773 (add-hook 'select-frame-hook #'sy-riece-check-command-buffer)
774
775 ;; Easier switch to Riece when running on TTY.
776 (defun sy-switch-to-riece ()
777   "I use this to switch to Riece when I'm on a tty."
778   (interactive)
779   (when (buffer-live-p riece-command-buffer)
780     (pop-to-buffer riece-command-buffer)
781     (riece-command-configure-windows)))
782
783 (define-key global-tty-map [(control ?c) ?r] #'sy-switch-to-riece)
784
785 ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
786 (message "Riece settings loaded successfully")
787