emacs

Note: some of the snippets in here I don't use any more, but are kept here for reference

One day, I might organize this better. But in the mean time…

Spam filtering in Gnus

I use spam.el for spam filtering. I also want to whitelist everyone in my BBDB address book, so I wrote the following functions:

(defun hc:gnus-spam-if-not-in-bbdb ()
  "gnus fancy split function;
     if the senders address is not in bbdb, check if spam"
  (let ((who (or (message-fetch-field "from")
         (message-fetch-field "sender")
         (message-fetch-field "reply-to"))))
    (if (string-match all-my-addresses-regexp who)
    (spam-split)
      (if (gnus-if-not-in-bbdb t)
      (spam-split)))))

Note that I anti-whitelist my own addresses, using the all-my-addresses-regexp variable, because spammers sometimes make the From: header the same as the To: header.

The gnus-if-not-in-bbdb is based on a lisp recipe from my.gnus.org that I am no longer able to locate, and is defined as follows:

(defun gnus-if-not-in-bbdb (target)
  "gnus fancy split function;
     if the senders address is not in bbdb, return TARGET"
  (let ((who (bbdb-canonicalize-address
              (cadr (gnus-extract-address-components
                     (or (message-fetch-field "from")
                         (message-fetch-field "sender")
                         (message-fetch-field "reply-to")
                         "nobody@nowhere.nohow"
                         )))))
        )
    (unless (bbdb-search-simple nil who)
      target
      )
    )
  )

I use the SpamAssassin backend, so I have the following definitions. (I'm using spamc, communicating with spamd over a UNIX domain socket.)

(setq spam-use-spamassassin t)
(setq spam-split-group "spamkill")
(setq spam-spamassassin-path "spamc")
(setq spam-spamassassin-arguments '("-U" "/var/run/spamd_sock"))
(require 'spam)
(spam-initialize)

Gnus splitting and SpamAssassin

[DEPRECATED] spam.el from gnus now supports SpamAssassin, so this is no longer needed with recent versions of gnus.

You need to use fancy splitting for this.

Add this code to your .gnus file:

(defun hc:fancy-split-spamassassin ()
  (save-excursion
    (set-buffer " *nnmail incoming*")
    (call-process-region (point-min) (point-max) "spamc" t t nil "-f")
    (goto-char (point-min))
    (when (re-search-forward "^x-spam-flag: yes$" nil t) "spamkill")))

Then add a rule to your nnmail-split-fancy variable:

    (: hc:fancy-split-spamassassin)

Key bindings

Inspired by xkcd (but using Alt-mousewheel):

(global-set-key (kbd "<M-mouse-5>") 'undo)
(global-set-key (kbd "<M-mouse-4>") 'redo)

Match parentheses (e.g. on a close-paren, hit M-] to jump to the corresponding open-paren)

(global-set-key "\e[" 'forward-list)
(global-set-key "\e]" 'backward-list)

Cycle through windows with C-M-next (C-M-pgdn) and C-M-prior

(global-set-key [\C-\M-next] 'other-window)
(global-set-key [\C-\M-prior] (lambda nil (interactive) (other-window -1)))

Setting the mail server by my IP address

Since I'm on a laptop, my Internet connection changes, and so does my SMTP server. So in my .emacs, I check my IP address and set my SMTP server. (Obviously, you'd need to tailor this to your own IP addresses)

(let ((address (shell-command-to-string "ifconfig eth0 | awk '/inet addr/{split($2,x,\":\");print x[2]}'")))
  (cond ((string-match "^129\\.97\\." address)
     ;; UW
     (setq message-send-mail-function 'smtpmail-send-it
           send-mail-function 'smtpmail-send-it
           smtpmail-default-smtp-server "mail.math.uwaterloo.ca"
           smtpmail-smtp-server "mail.math.uwaterloo.ca"))
    ((string-equal "129.128.207.8\n" address)
     ;; U of A
     (setq message-send-mail-function 'smtpmail-send-it
           send-mail-function 'smtpmail-send-it
           smtpmail-default-smtp-server "mailbox.math.ualberta.ca"
           smtpmail-smtp-server "mailbox.math.ualberta.ca"))
    ;;((string-match "^24\\." address)
     ;; Rogers (in Waterloo) (their mail server uses AUTH SMTP - not
     ;; supported (yet) by Gnus)
     ;;(setq smtpmail-default-smtp-server "smtp.ktchnr.phub.net.cable.rogers.com")
     ;;(setq smtpmail-smtp-server "smtp.ktchnr.phub.net.cable.rogers.com"))
    ((string-match "^142\\." address)
     ;; Telus (in Edmonton)
     (setq message-send-mail-function 'smtpmail-send-it
           send-mail-function 'smtpmail-send-it
           smtpmail-default-smtp-server "smtp.telusplanet.net"
           smtpmail-smtp-server "smtp.telusplanet.net"))
    (t
     ;; anywhere else -- send through UW's server over ssh
     (setq message-send-mail-function 'feedmail-send-it
           send-mail-function 'feedmail-send-it
           feedmail-binmail-template "ssh hopper -e none /bin/mail %s"))))

Copying filenames from dired

Mark a bunch of files, and copy their filenames to the kill ring, and paste them into another buffer. I find it handy in eshell sometimes.

(defun my:dired-kill-ring-save-filenames (&optional arg)
  "Puts all marked (or next ARG) filenames to the kill ring."
  (interactive "P")
  (kill-new (mapconcat
         #'(lambda (x) x)
         (dired-map-over-marks (dired-get-filename 'verbatim)
                   arg) " ")))
;; dired-find-file is already mapped to "e" and "<RET>", so we can remap
;; "f" to dired-show-file-type, and map "w" to
;; my:dired-kill-ring-save-filenames
(add-hook 'dired-load-hook #'(lambda ()
                   (define-key dired-mode-map "w"
                 'my:dired-kill-ring-save-filenames)
                   (define-key dired-mode-map "f"
                 'dired-show-file-type)))

HTTP requests

I occasionally need to paste the result of an HTTP request into a buffer.

(defun insert-from-url (url)
  (interactive "MURL: ")
  (let ((url-request-method "GET")
        (dest (current-buffer))
        (src (url-retrieve-synchronously url)))
    (set-buffer src)
    (goto-char (point-min))
    (search-forward "\n\n")
    (set-buffer dest)
    (insert-buffer-substring src (match-end 0))))