;;; erc-init.el --- Various ERC hacks and configuration ;; This file is part of Michael Olson's Emacs settings. ;; The code in this file may be used, distributed, and modified ;; without restriction. ;; I use initsplit.el to separate customize settings on a per-project ;; basis. ;; Add working directories to load path (add-to-list 'load-path "/home/mwolson/proj/emacs/erc/git-erc") ;; Load ERC (require 'erc) ;; Load authentication info from an external source (load "~/.emacs.d/.erc-auth") ;;; New ERC commands (autoload 'doctor-doc "doctor") (autoload 'make-doctor-variables "doctor") (defvar erc-doctor-id "{Emacs doctor} ") (defun erc-cmd-DOCTOR (&optional last-sender &rest ignore) "Get the last message in the channel and doctor it." (let ((limit (- (point) 1000)) (pos (point)) data doctor-buffer last-message text) ;; Make sure limit is not negative (when (< limit 0) (setq limit 0)) ;; Search backwards for text from someone (while (and pos (not (and (setq data (get-text-property pos 'erc-parsed)) (string= (aref data 3) "PRIVMSG") (or (not last-sender) (string= (car (split-string (aref data 2) "!")) last-sender))))) (setq pos (previous-single-property-change pos 'erc-parsed nil limit)) (when (= pos limit) (error "No appropriate previous message to doctor"))) (when pos (setq last-sender (car (split-string (aref (get-text-property pos 'erc-parsed) 2) "!")) doctor-buffer (concat "*ERC Doctor: " last-sender "*") last-message (split-string ;; Remove punctuation from end of sentence (replace-regexp-in-string "[ .?!;,/]+$" "" (aref (get-text-property pos 'erc-parsed) 5))) text (mapcar (lambda (s) (intern (downcase s))) ;; Remove salutation if it exists (if (string-match (concat "^" erc-valid-nick-regexp "[:,]*$\\|[:,]+$") (car last-message)) (cdr last-message) last-message)))) (erc-send-message (concat erc-doctor-id ;; Only display sender if not in a query buffer (if (not (erc-query-buffer-p)) (concat last-sender ": ")) (save-excursion (if (get-buffer doctor-buffer) (set-buffer doctor-buffer) (set-buffer (get-buffer-create doctor-buffer)) (make-doctor-variables)) (erase-buffer) (doctor-doc text) (buffer-string)))))) (defun erc-cmd-EMMS (&rest ignore) "Display the current emms track to the current ERC buffer." (emms-player-mpd-show nil (lambda (buffer desc) (with-current-buffer buffer (erc-send-message desc))))) (defalias 'erc-cmd-NP 'erc-cmd-EMMS) (defun erc-cmd-UNAME (&rest ignore) "Display the result of running `uname -a' to the current ERC buffer." (let ((uname-output (replace-regexp-in-string "[ \n]+$" "" (shell-command-to-string "uname -a")))) (erc-send-message (concat "{uname -a} [" uname-output "]")))) (defun erc-cmd-UPTIME (&rest ignore) "Display the uptime of the system, as well as some load-related stuff, to the current ERC buffer." (let ((uname-output (replace-regexp-in-string ", load average: " "] {Load average} [" ;; Collapse spaces, remove (replace-regexp-in-string " +" " " ;; Remove beginning and trailing whitespace (replace-regexp-in-string "^ +\\|[ \n]+$" "" (shell-command-to-string "uptime")))))) (erc-send-message (concat "{Uptime} [" uname-output "]")))) (defun erc-cmd-WTF (term &rest ignore) "Look up definition for TERM." (let ((def (wtf-is term))) (if def (erc-send-message (concat "{Term} " (upcase term) " is " def)) (message (concat "No definition found for " (upcase term)))))) (defun erc-cmd-XMMS (&rest ignore) "Display the current xmms track to the current ERC buffer." (let* ((xmms-output (shell-command-to-string "xmms-shell -e current-track")) (case-fold-search t) (current-track (replace-regexp-in-string "[ \n]+$" "" (mapconcat 'identity (nthcdr 3 (split-string xmms-output " ")) " ")))) (if (null (string-match "current" xmms-output)) (message xmms-output) (erc-send-message (concat "NP: [" current-track "]"))))) (defun erc-cmd-YOW (&rest ignore) "Display some pinhead wisdom into the current ERC buffer. I'd rather not see it messaged to me, just sent out." (let ((yow-msg (replace-regexp-in-string "\n" "" (yow nil nil)))) (erc-send-message (concat "{Pinhead wisdom} " yow-msg)))) ;;; Misc. hacks ;; Change fill column according to the width of the current frame (defun my-erc-mode-stuff () "Set fill column according to `frame-width'." (set (make-local-variable 'erc-fill-column) (- (frame-width) 10)) (set (make-local-variable 'erc-timestamp-right-column) (1+ erc-fill-column))) (add-hook 'erc-mode-hook 'my-erc-mode-stuff) ;;; Notify me when a keyword is matched (someone wants to reach me) (defvar my-erc-page-message "%s is calling your name." "Format of message to display in dialog box") (defvar my-erc-page-nick-alist nil "Alist of nicks and the last time they tried to trigger a notification") (defvar my-erc-page-timeout 30 "Number of seconds that must elapse between notifications from the same person.") (defun my-erc-page-popup-notification (nick) (when window-system ;; must set default directory, otherwise start-process is unhappy ;; when this is something remote or nonexistent (let ((default-directory "~/")) ;; 8640000 milliseconds = 1 day (start-process "page-me" nil "notify-send" "-u" "normal" "-t" "8640000" "ERC" (format my-erc-page-message nick))))) (defun my-erc-page-allowed (nick &optional delay) "Return non-nil if a notification should be made for NICK. If DELAY is specified, it will be the minimum time in seconds that can occur between two notifications. The default is `my-erc-page-timeout'." (unless delay (setq delay my-erc-page-timeout)) (let ((cur-time (time-to-seconds (current-time))) (cur-assoc (assoc nick my-erc-page-nick-alist)) (last-time nil)) (if cur-assoc (progn (setq last-time (cdr cur-assoc)) (setcdr cur-assoc cur-time) (> (abs (- cur-time last-time)) delay)) (push (cons nick cur-time) my-erc-page-nick-alist) t))) (defun my-erc-page-me (match-type nick message) "Notify the current user when someone sends a message that matches a regexp in `erc-keywords'." (interactive) (when (and (eq match-type 'keyword) ;; I don't want to see anything from the erc server (not (string-match "\\`\\([sS]erver\\|localhost\\|root\\)" nick)) ;; or bots (not (string-match "\\(^CIA[^!]*\\|bot\\|serv\\)!" nick)) ;; or from those who abuse the system (my-erc-page-allowed nick)) (my-erc-page-popup-notification nick))) (add-hook 'erc-text-matched-hook 'my-erc-page-me) (defun my-erc-page-me-PRIVMSG (proc parsed) (let ((nick (car (erc-parse-user (erc-response.sender parsed)))) (target (car (erc-response.command-args parsed))) (msg (erc-response.contents parsed))) (when (and (erc-current-nick-p target) (not (erc-is-message-ctcp-and-not-action-p msg)) (my-erc-page-allowed nick)) (my-erc-page-popup-notification nick) nil))) (add-hook 'erc-server-PRIVMSG-functions 'my-erc-page-me-PRIVMSG) ;;; Remove trailing whitespace in messages (defun my-erc-remove-trailing-whitespace (proc parsed) "Remove trailing whitespace from the current message. Some IM clients use an OTR plug-in that sends some annoying trailing space to the screen, so we want to mop that up." (let ((msg (erc-response.contents parsed))) (when (stringp msg) (setf (erc-response.contents parsed) (erc-replace-regexp-in-string "[[:space:]]+\\'" "" msg)) nil))) (add-hook 'erc-server-PRIVMSG-functions 'my-erc-remove-trailing-whitespace) ;;; Key customizations (global-set-key "\C-cea" (lambda () (interactive) (erc :server "irc.arstechnica.com" :port "6667" :nick "mwolson" :full-name "http://mwolson.org"))) (global-set-key "\C-ceb" (lambda () (interactive) (erc :server "localhost" :port "6668" :nick "mwolson"))) (global-set-key "\C-cee" (lambda () (interactive) (erc :server "irc.servercentral.net" :port "ircd" :nick "mwolson"))) (global-set-key "\C-cef" (lambda () (interactive) ; (erc :server "irc.us.freenode.net" :port "ircd" (erc :server "niven.freenode.net" :port "ircd" :nick "mwolson"))) (global-set-key "\C-cer" (lambda () (interactive) (erc-tls :server "irc.rizon.net" :port "6697" :nick "mwolson" :full-name "mwolson"))) (global-set-key "\C-ceo" (lambda () (interactive) (erc :server "irc.oftc.net" :port "ircd" :nick "bigmike160"))) (global-set-key "\C-cez" (lambda () (interactive) (erc :server "irc.zirc.net" :port "ircd" :nick "bigmike160"))) ;; temporary ;; (global-set-key "\C-cet" #'(lambda nil ;; (interactive) ;; (message "%s" erc-autoaway-last-sent-time))) ;; Make C-c RET (or C-c C-RET) send messages instead of RET (define-key erc-mode-map (kbd "RET") nil) (define-key erc-mode-map (kbd "C-c RET") 'erc-send-current-line) (define-key erc-mode-map (kbd "C-c C-RET") 'erc-send-current-line) ;; Disable some commands that I never want to execute (define-key erc-mode-map "\C-c\C-c" nil) (define-key erc-mode-map "\C-c\C-e" nil) (define-key erc-mode-map "\C-c\C-f" nil) (define-key erc-mode-map "\C-c\C-p" nil) (define-key erc-mode-map "\C-c\C-q" nil) (define-key erc-mode-map "\C-c\C-r" nil) ;;; Customization variables (custom-set-variables '(erc-anonymous-login nil) '(erc-auto-query (quote bury)) '(erc-autoaway-idle-seconds 1200) '(erc-autojoin-channels-alist (quote (("servercentral.net" "#gp2xdev") ("mwolson.org" "&bitlbee") ("freenode.net" "#erc" "#hcoop" "##metaconference" "#muse" "#tyrian")))) '(erc-bbdb-auto-create-on-whois-p t) '(erc-bbdb-popup-type nil) '(erc-beep-match-types nil) '(erc-current-nick-highlight-type nil) '(erc-dcc-get-default-directory "~/sandbox/") '(erc-dcc-listen-host nil) '(erc-dcc-port-range (quote (6888 . 6889))) '(erc-dcc-public-host nil) '(erc-email-userid "mwolson") '(erc-enable-logging (quote erc-log-all-but-server-buffers)) '(erc-fool-highlight-type (quote all)) '(erc-fools (quote ("AnalphaBestie" "ayrnieu" "DISABLEDconsolers" "rahul" "\\bams\\b" "dalias" "jerware" "jeramey"))) '(erc-hide-prompt t) '(erc-hide-timestamps nil) '(erc-ignore-list (quote ("julian@pdpc/supporter/sustaining/ayrnieu"))) '(erc-interpret-mirc-color t) '(erc-join-buffer (quote bury)) '(erc-keywords (quote ("\\b\\(mike\\|mwolson\\)[!?.,;]*$" "\\(mike\\|mwolson\\)[:!?,;]+" "\\b\\([hH]ey\\|[hH]i\\) \\(mike\\|mwolson\\|man\\)\\b"))) '(erc-kill-buffer-on-part t) '(erc-kill-queries-on-quit t) '(erc-kill-server-buffer-on-quit t) '(erc-log-write-after-insert t) '(erc-modules (quote (autoaway autojoin button capab-identify completion dcc fill identd irccontrols list log match menu move-to-prompt netsplit networks noncommands notify readonly ring scrolltobottom services stamp spelling track))) '(erc-nick "mwolson") '(erc-nicklist-icons-directory "/home/mwolson/proj/emacs/erc/arch-head/images/") '(erc-notify-list (quote ("docelic" "forcer" "Smerdyakov" "johnw" "sachac" "strfryed" "disumu" "megacz"))) '(erc-notify-signoff-hook (quote (erc-notify-signoff))) '(erc-notify-signon-hook (quote (erc-notify-signon))) '(erc-pals (quote ("comcor" "deego" "docelic" "forcer" "johnsu01" "^johnw!" "^Luke!" "Sigma\\[Mtp\\]" "sachac" "strfryed"))) '(erc-part-reason (quote erc-part-reason-various)) '(erc-part-reason-various-alist (quote (("^np$" emms-show) ("zippy" erc-part-reason-zippy)))) '(erc-prompt-for-nickserv-password nil) '(erc-prompt-for-password nil) '(erc-query-display (quote bury)) '(erc-quit-reason (quote erc-quit-reason-various)) '(erc-quit-reason-various-alist (quote (("^np$" emms-show) ("zippy" erc-part-reason-zippy)))) '(erc-server "localhost") '(erc-server-send-ping-interval nil) '(erc-status-icon-file "/usr/local/share/emacs/23.0.50/etc/images/icons/hicolor/48x48/apps/emacs.png") '(erc-text-matched-hook (quote (my-erc-page-me erc-log-matches))) '(erc-timestamp-right-align-by-pixel t) '(erc-track-exclude-types (quote ("JOIN" "NICK" "PART" "QUIT" "333" "353"))) '(erc-track-remove-disconnected-buffers t) '(erc-track-switch-direction (quote importance)) '(erc-user-full-name (quote user-full-name)) '(erc-verbose-dcc nil) '(erc-whowas-on-nosuchnick t)) (custom-set-faces '(erc-default-face ((t (:foreground "dark blue" :slant oblique)))) '(erc-fool-face ((t (:foreground "LightBlue")))) '(erc-input-face ((t (:foreground "dim gray")))) '(erc-keyword-face ((t (:foreground "blue" :underline t :weight bold)))) '(erc-timestamp-face ((t (:foreground "dark green" :weight bold))))) ;; Do only certain channels temporarily ;; (setq erc-autojoin-channels-alist ;; '(("freenode.net" "#pulug" "#plugbot")) ;; erc-nick "mwolson`") ;; (setq erc-modules (quote (autojoin button fill irccontrols log ;; match netsplit noncommands ;; pcomplete readonly ring stamp ;; spelling track))) ;;; erc-init.el ends here