dot/gpg.conf.m4, dot/gpg-agent.conf, Makefile: Adopt GnuPG configuration.
[profile] / dot / ercrc.el
index 118a2cc..6a708ac 100644 (file)
@@ -2,19 +2,39 @@
 ;;;
 ;;; ERC configuration
 
-(load "~/.erc-auth.el")
 (setq erc-nick "mdw"
       erc-user-full-name "Mark Wooding")
 
-(if (not (memq 'truncate erc-modules))
-    (setq erc-modules (cons 'truncate erc-modules)))
+(dolist (module '(replace truncate))
+  (if (not (memq module erc-modules))
+      (setq erc-modules (cons module erc-modules))))
 
 (setq erc-fill-column 76
       erc-timestamp-right-column 68
       erc-fill-prefix "   "
       erc-max-buffer-size (* 60 3000))
 
-(load "~/.erc-local.el")
+;; Filter out emoji, which cause severe display confusion.
+(defun mdw-replace-wide-characters (string)
+  (with-output-to-string
+    (let ((i 0)
+         (state nil))
+      (while (< i (length string))
+       (let ((ch (aref string i)))
+         (cond ((and (= (char-width ch) 1)
+                     (not (or (<= #x1f200 ch #x1ffff)
+                              (= ch #x2693))))
+                (when state (princ "*]") (setf state nil))
+                (write-char ch))
+               (t
+                (princ (if state "*" "[*"))
+                (princ (format "#x%x" ch))
+                (setf state t))))
+       (setq i (1+ i)))
+      (when state (princ "*]")))))
+
+(setq erc-replace-alist
+      '(("[[:nonascii:]+]" . mdw-replace-wide-characters)))
 
 (setq erc-track-exclude-types '("NICK" "JOIN" "PART"))
 
 (setq erc-autojoin t
       erc-autojoin-domain-only nil
       erc-autojoin-channels-alist
-      '(("irc.ssdis.loc" "#devel" "#jukebox" "#nextgen")
-       ("cam.irc.devel.ncipher.com"
-        "#devel" "#jukebox" "#nextgen" "#sec-team")
-       ("chiark.greenend.org.uk" "#chiark")
-       ("irc.distorted.org.uk" "#distorted" "#jukebox")))
-
-(defvar mdw-erc-auto-greet-bots-alist
-  `(("irc.ssdis.loc" "fastness"
-     ,(format "identpass mwooding %s" mdw-fastness-password))
-    ("cam.irc.devel.ncipher.com" "fastness"
-     ,(format "identpass mwooding %s" mdw-fastness-password))
-    ("chiark.greenend.org.uk" "blight"
-     ,(format "identpass mdw %s" mdw-blight-password))
-    ("tunnel.chiark.greenend.org.uk" "blight"
-     ,(format "identpass mdw %s" mdw-blight-password))
-    ("irc.distorted.org.uk" "blight"
-     ,(format "identpass mdw %s" mdw-distorted-password)))
+      '(("chiark.greenend.org.uk" "#chiark")
+       ("irc.distorted.org.uk" "#distorted" "#jukebox")
+       ("irc.hstg.corp.good.com" "#hstg")))
+(erc-autojoin-mode 1)
+
+(defvar mdw-erc-auto-greet-bots-alist nil
   "*Alist of (SERVER-REGEXP BOT-NICK MESSAGE-FORM).
 Evaluate MESSAGE-FORM and sent to BOT-NICK when connected to a server which
 matches SERVER-REGEXP.")
 
+(defvar mdw-erc-ircop-alist nil
+  "*Alist of (SERVER-REGEXP ACCT PASSWD).
+Login details for claiming server admin rights.")
+
+(defun mdw-remprop-nondestructive (indic plist)
+  "Return a plist like PLIST, only without the first entry for INDIC.
+The PLIST is not itself modified."
+  (if (getf plist indic)
+      (let* ((head (cons nil nil))
+            (tail head))
+       (while (and plist (not (eq (car plist) indic)))
+         (let* ((i (pop plist)) (v (pop plist))
+                (vv (cons v nil)) (ii (cons i vv)))
+           (rplacd tail ii)
+           (setq tail vv)))
+       (rplacd tail (cddr plist))
+       (cdr head))
+    plist))
+
+(defun* mdw-cons-replace
+    (item list &rest keys &key (key '#'identity) &allow-other-keys)
+  "Return LIST, with ITEM at the start, replacing any existing matching item.
+Specifically, any item in the list satisfying the test are removed
+\(nondestructively), and then the new ITEM is added to the front."
+  (cons item (apply #'remove* (funcall key item) list :key key
+                   (mdw-remprop-nondestructive :key keys))))
+
+(defmacro* mdw-pushnew-replace (item place &rest keys)
+  "Add ITEM to the list PLACE, replacing any existing matching item.
+Specifically, any item in the list satisfying the test are removed
+\(nondestructively), and then the new ITEM is added to the front.
+
+Evaluation order for the keywords is a bit screwy: don't rely on it."
+  (cond ((fboundp 'cl-callf2)
+        `(cl-callf2 mdw-cons-replace ,item ,place ,@keys))
+       ((fboundp 'cl-setf-do-modify)
+        ;; `cl-setf-do-modify' returns a list (LETS STORE FETCH).
+        (let ((setf-things (cl-setf-do-modify place (cons 'list keys))))
+          `(let (,@(car setf-things))
+             ,(cl-setf-do-store (cadr setf-things)
+                                `(mdw-cons-replace ,item ,place
+                                                   ,@keys)))))
+       (t (error "Don't know how to hack places on this Emacs."))))
+
+(defun mdw-define-bot-greeting (server bot greeting)
+  "Define a new bot greeting."
+  (mdw-pushnew-replace (list server bot greeting)
+                      mdw-erc-auto-greet-bots-alist
+                      :test #'string= :key #'car))
+(defun mdw-add-ircop-credentials (server acct passwd)
+  "Define a new set of `ircop' credentials."
+  (mdw-pushnew-replace (list server acct passwd)
+                      mdw-erc-ircop-alist
+                      :test #'string= :key #'car))
+
+(defun mdw-assoc-regexp (regexp alist)
+  "Return the association in ALIST whose car matches REGEXP."
+  (let ((answer nil))
+    (dolist (l alist)
+      (when (string-match (car l) regexp)
+       (setq answer l)))
+    answer))
+
 (defun mdw-erc-auto-greet-bots (server nick)
   "Send greeting message to bots."
-  (dolist (l mdw-erc-auto-greet-bots-alist)
-    (when (string-match (car l) server)
-      (let ((bot (cadr l))
-           (message (caddr l)))
+  (let ((a (mdw-assoc-regexp server mdw-erc-auto-greet-bots-alist)))
+    (when a
+      (let ((bot (cadr a))
+           (message (caddr a)))
        (erc-server-send (concat "PRIVMSG " bot " :" message))))))
 (add-hook 'erc-after-connect 'mdw-erc-auto-greet-bots)
+
+(defun erc-cmd-GREET ()
+  "Send greeting messages, according to `mdw-erc-auto-greet-bots-alist'."
+  (mdw-erc-auto-greet-bots erc-session-server (erc-current-nick)))
+
+(defun erc-cmd-IRCOP ()
+  "Claim `ircop' privileges."
+  (let ((a (mdw-assoc-regexp erc-session-server mdw-erc-ircop-alist)))
+    (when a
+      (let ((acct (cadr a))
+           (passwd (caddr a)))
+       (erc-server-send (concat "OPER " acct " " passwd))))))
+
+(load "~/.erc-auth.el")
+(load "~/.erc-local.el")