;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; Copyright (C) 2003-2007 Troels Henriksen ;;;; ;;;; Some parts are Copyright (C) the Free Software Foundation and other ;;;; people. ;;;; ;;;; This program is free software; you can redistribute it and/or ;;;; modify it under the terms of the GNU General Public License as ;;;; published by the Free Software Foundation; either version 2 of ;;;; the License, or (at your option) any later version. ;;;; ;;;; This program is distributed in the hope that it will be useful, ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;;; General Public License for more details. ;;;; ;;;; You should have received a copy of the GNU General Public License ;;;; along with this program; if not, write to the Free Software ;;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA ;;;; 02111-1307, USA. ;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; GNU EMACS CONFIGURATION FILE ;;;; ;;; Troels Henriksen's .emacs ;;; ;; 10 September 2004 (yeah right) ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; ;;;; IMPORTANT NOTICE: This .emacs is designed for Emacs 22, and is ;;;; likely *NOT* to work in other versions. ;;;; ;;;; The code within is probably not the cleanest around, and it is ;;;; designed for GNU/Linux systems and GNU Emacs, so portability is ;;;; probably non-existant. As usual, "use at own risk," but I guess ;;;; you already knew that. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; Utility Lisp functions: ;;;;;;;;;;;;;;;;;;;;;;;;;;;; (require 'cl) (defun noerr-require (feature) "`require' FEATURE, but don't invoke any Lisp errors. If FEATURE cannot be loaded, this function will print an error message through `message' and return nil. It otherwise behaves exactly as `require'." (ignore-errors (require feature (symbol-name feature) t))) (defmacro with-feature (feature &rest body) "Require FEATURE and execute BODY. If FEATURE can't be loaded, don't execute BODY." (when (noerr-require (car feature)) (push 'progn body))) (defmacro with-features (features &rest body) "Require FEATURES and execute BODY. If any of FEATURES cannot be loaded, don't execute BODY." (if features `(with-feature (,(first features)) (with-features ,(cdr features) ,@body)) `(progn ,@body))) ;;;; Generic Emacs options: ;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Loadpaths: (add-to-list 'load-path "~/emacs") (add-to-list 'load-path "~/emacs/imaxima-imath-0.97a/") (noerr-require 'gpl) (noerr-require 'gpl-copying) (noerr-require 'help-mode) (noerr-require 'grep) (noerr-require 'htmlfontify) (noerr-require 'ucs-tables) (noerr-require 'ispell) (noerr-require 'latex) (noerr-require 'w3m) (noerr-require 'margin) (noerr-require 'ubbc-mode) (noerr-require 'gnus) (with-feature (imaxima) (autoload 'imaxima "imaxima" "Image support for Maxima." t) (autoload 'imath-mode "imath" "Interactive Math minor mode." t)) (server-start) ; Convenient, at times. (display-time) ; Display time in modeline. (column-number-mode 1) ; Show column number on the mode-line. (line-number-mode 1) ; Show line number on the mode-line. (show-paren-mode 1) ; Paren-matching. (auto-fill-mode -1) ; Don't auto-fill by default. (global-font-lock-mode t) ; Font-lock by default. (setf pop-up-windows nil ; Don't change my windowconfiguration. pop-up-frames nil european-calendar-style t ; Use european date format. delete-auto-save-files t ; Delete unnecessary auto-save files. default-major-mode 'fundamental-mode ; At least this mode won't do anything stupid. scroll-step 1 ; Only move in small increments. scroll-conservatively 10000 frame-title-format "%b GNU Emacs" ; Make the frame a bit more useful. ;; Personal information. user-mail-address "athas@sigkill.dk" user-full-name "Troels Henriksen" user-company-name "Church of Emacs" mail-user-agent 'gnus-user-agent visible-bell t fill-column 70 dired-recursive-copies t enable-local-variables :safe undo-strong-limit 3000000 tab-width 2) (setq-default case-fold-search t show-trailing-whitespace t) (transient-mark-mode 0) (global-hl-line-mode 1) ;; Backup-files in the working directory sucks. (add-to-list 'backup-directory-alist (cons ".*" "~/backup")) ;; ido is actually better and more general than iswitchb... (with-feature (ido) (ido-mode 1) (setq ido-enable-flex-matching t) (defvar ido-enable-replace-completing-read nil "If t, use ido-completing-read instead of completing-read if possible. Set it to nil using let in around-advice for functions where the original completing-read is required. For example, if a function foo absolutely must use the original completing-read, define some advice like this: (defadvice foo (around original-completing-read-only activate) (let (ido-enable-replace-completing-read) ad-do-it))") ;; Replace completing-read wherever possible, unless directed otherwise (defadvice completing-read (around use-ido-when-possible activate) (if (or (not ido-enable-replace-completing-read) ; Manual override disable ido (boundp 'ido-cur-list)) ; Avoid infinite loop from ido calling this ad-do-it (let ((allcomp (all-completions "" collection predicate))) (if allcomp (setq ad-return-value (ido-completing-read prompt allcomp nil require-match initial-input hist def)) ad-do-it)))) (add-hook 'ido-define-mode-map-hook 'ido-my-keys) (defun ido-my-keys () "Add my keybindings for ido." (define-key ido-mode-map (kbd "C-w") 'backward-kill-word)) ;; Display ido results vertically, rather than horizontally (setq ido-decorations '("\n-> " "" "\n " "\n ..." "[" "]" " [No match]" " [Matched]" " [Not readable]" " [Too big]" " [Confirm]")) (defun ido-disable-line-trucation () (set (make-local-variable 'truncate-lines) nil)) (add-hook 'ido-minibuffer-setup-hook 'ido-disable-line-trucation)) ;; Do not use The Evil Tab, use Holy Spaces instead. (setq-default indent-tabs-mode nil) ;; Set up Twelf... (setq twelf-root "/home/athas/twelf/") (when (file-exists-p (concat twelf-root "emacs/twelf-init.el")) (load (concat twelf-root "emacs/twelf-init.el"))) (with-feature (ispell) (ispell-change-dictionary "british" t) ) ;;; Make Emacs a bitch to close (C-x C-c is sooo easy to hit): (add-to-list 'kill-emacs-query-functions (lambda () (y-or-n-p "Last chance, your work would be lost. "))) (add-to-list 'kill-emacs-query-functions (lambda () (y-or-n-p "Are you ABSOLUTELY certain that Emacs should close? "))) (add-to-list 'kill-emacs-query-functions (lambda () (y-or-n-p "Should Emacs really close? "))) ;;; Tease the vi-users: (defconst wq "This is not vi! Use C-x C-c instead.") (defconst w "This is not vi! Use C-x C-s instead.") (defconst q! "This is EMACS not vi! Use C-x C-c instead.") (defconst wq! "This is EMACS not vi! Use C-x C-c instead.") (with-feature (package) (add-to-list 'package-archives '("marmalade" . "http://marmalade-repo.org/packages/"))) ;;;; Generic Keybindings: ;;;;;;;;;;;;;;;;;;;;;;;;; (defmacro global-set-keys (&rest keycommands) "Register keys to commands. Analyze KEYCOMMANDS in pairs, and maps the corresponding keys to the corresponding functions." (let ((setkey-list nil)) (while keycommands (let ((key (car keycommands)) (command (cadr keycommands))) (push `(global-set-key (kbd ,key) ,command) setkey-list)) (setq keycommands (cddr keycommands))) (push 'progn setkey-list) setkey-list)) (defmacro set-keybinding-for-maps (key command &rest keymaps) "Register keys to commands in a nuber of keymaps. Maps KEY to COMMAND in the keymaps listed in KEYMAPS." (let ((defkey-list nil)) (while keymaps (let ((current-map (first keymaps))) (push `(define-key ,current-map (kbd ,key) ,command) defkey-list)) (setq keymaps (rest keymaps))) (push 'progn defkey-list) defkey-list)) (defmacro define-keys (keymap &rest args) `(progn ,@(let (defs) (while args (let ((key (first args)) (def (second args))) (push `(define-key ,keymap ,key ,def) defs)) (setf args (cddr args))) defs))) ;;; Keybindings: (global-set-keys ;; M-x strains my fingers. "\C-x\C-m" 'execute-extended-command "\C-c\C-m" 'execute-extended-command ;; Backspace is far away, making backward-kill-word hard to perform. "\C-w" 'backward-kill-word "\C-x\C-k" 'kill-region "\C-c\C-k" 'kill-region "M-p" 'backward-paragraph "M-n" 'forward-paragraph "\C-xw" 'goto-line "\C-x\C-b" 'buffer-menu "\C-cn" 'bs-cycle-next "\C-cp" 'bs-cycle-previous "\C-ce" 'eshell "\C-c\C-e" 'eshell "\C-ck" 'compile "\C-x!" 'shell-command "\C- " 'set-mark-command "\C-hg" 'apropos "" (lambda () (interactive) (find-file "~/.notes")) "" (lambda () (interactive) (find-file "~/.todo")) "" 'slime-scratch "C-x c s" 'slime-selector "C-x a r" 'align-regexp) (global-set-key (kbd "C-c TAB") 'lisp-complete-symbol) ;;; A lot of major modes do not allow quick exit, but they should. (defvar maps-for-quick-exit nil "List of keymaps that should have a key for quick exit defined.") (with-feature (help-mode) (push help-mode-map maps-for-quick-exit)) (with-feature (grep) (push grep-mode-map maps-for-quick-exit)) (push completion-list-mode-map maps-for-quick-exit) (dolist (map maps-for-quick-exit) (set-keybinding-for-maps "q" 'kill-this-buffer map)) (global-set-key (kbd "") 'other-window) (global-set-key "\C-\M-z" 'undo) ;;;; Visual Appearance: ;;;;;;;;;;;;;;;;;;;;;;; ;;; Disable X-fluff and remove stuff: (when (> (string-to-number emacs-version) 20) ; Why do I care? (tool-bar-mode -1) (menu-bar-mode -1) (scroll-bar-mode -1) (blink-cursor-mode -1)) ;;; Turn on mouse wheel scrolling (defun sd-mousewheel-scroll-up (event) "Scroll window under mouse up by five lines." (interactive "e") (let ((current-window (selected-window))) (unwind-protect (progn (select-window (posn-window (event-start event))) (scroll-up 5)) (select-window current-window)))) (defun sd-mousewheel-scroll-down (event) "Scroll window under mouse down by five lines." (interactive "e") (let ((current-window (selected-window))) (unwind-protect (progn (select-window (posn-window (event-start event))) (scroll-down 5)) (select-window current-window)))) (global-set-key (kbd "") 'sd-mousewheel-scroll-up) (global-set-key (kbd "") 'sd-mousewheel-scroll-down) ;; Define the way Emacs looks: (set-foreground-color "grey") (set-background-color "black") (set-cursor-color "red") (set-mouse-color "green") (set-border-color "light green") (set-face-background 'trailing-whitespace "turquoise") ;; Color theme overrides the above stuff. (with-features (color-theme zenburn) (color-theme-zenburn) ) ;;;; Programming: ;;;;;;;;;;;;;;;;; (with-feature (css-mode) (setq cssm-indent-level 2) (setq cssm-newline-before-closing-bracket t) (setq cssm-indent-function #'cssm-c-style-indenter) (setq cssm-mirror-mode nil)) (setq c-basic-offset 2) (noerr-require 'ld-script) (with-feature (moo-code) (add-to-list 'auto-mode-alist (cons "\\.moo" 'moo-code-mode)) ) (with-feature (nxml-mode) (add-to-list 'auto-mode-alist (cons (concat "\\."(regexp-opt '("xml" "xsd" "sch" "rng" "xslt" "svg" "rss") t) "\\'") 'nxml-mode)) ) (with-feature (maxima-mode) (add-to-list 'auto-mode-alist '("\.max" . maxima-mode)) ) (with-feature (octave-mode) (setq auto-mode-alist (cons '("\\.m$" . octave-mode) auto-mode-alist))) (add-to-list 'auto-mode-alist '("\.stumpwmrc" . lisp-mode)) (setq compilation-read-command nil) (global-set-key [f8] 'add-change-log-entry-other-window) (global-set-key "\C-c\C-c" 'eval-last-sexp) (add-hook 'change-log-mode-hook (lambda () (auto-fill-mode))) (with-feature (paredit) (add-hook 'emacs-lisp-mode-hook (lambda () (paredit-mode +1)))) ;;; Darcs - a revision control system. ;; I might accidentaly open a darcs-file, in that case, warn. (add-hook 'find-file-hook 'warn-if-darcs-file) (defun warn-if-darcs-file() (let ((f (buffer-file-name (current-buffer)))) (and f (string-match "_darcs" f) (if (y-or-n-p "This is a _darcs file, open the real file? ") (jump-to-real-file-from-darcs) (push '(:propertize "_DARCS-FILE:" face font-lock-warning-face) mode-line-buffer-identification))))) (defun jump-to-real-file-from-darcs() (interactive) (let* ((f (buffer-file-name (current-buffer))) (match (string-match "_darcs/current" f))) (and f match (find-alternate-file (concat (substring f 0 (match-beginning 0)) (substring f (match-end 0))))))) ;;; SLIME and generic Common Lisp. (push "/home/athas/code/cvsrepos/slime/" load-path) (push "/home/athas/code/cvsrepos/slime/contrib/" load-path) (with-features (slime paredit) ;;(setq inferior-lisp-program "/usr/bin/lisp") (setq inferior-lisp-program "~/bin/cvsbcl" slime-multiprocessing t slime-startup-animation nil slime-backend "/home/athas/code/cvsrepos/slime/swank-loader.lisp") (slime-setup '(slime-fancy slime-asdf)) (define-key paredit-mode-map (kbd "RET") nil) (define-key lisp-mode-shared-map (kbd "RET") 'paredit-newline) (define-key slime-repl-mode-map (kbd "C-M-d") 'down-list) (add-hook 'lisp-mode-hook (lambda () (slime-mode t))) (add-hook 'lisp-mode-hook (lambda () (paredit-mode +1))) (add-hook 'slime-repl-mode-hook (lambda () (paredit-mode +1))) (add-hook 'inferior-lisp-mode-hook (lambda () (inferior-slime-mode t))) (add-to-list 'auto-mode-alist '("\\.cl$" . lisp-mode)) (add-to-list 'auto-mode-alist '("\\.cmucl-init$" . lisp-mode)) (add-to-list 'auto-mode-alist '("\\.asd$" . lisp-mode)) (setq slime-complete-symbol-function 'slime-complete-symbol*) ;; I have a local copy of the Common Lisp HyperSpec (setq common-lisp-hyperspec-root "file:/home/athas/docs/HyperSpec/") (defvar hyperspec-browser-function 'w3m-browse-url "Function to display the relevant entry of the HyperSpec in a WWW browser. This is used by the command `trh-hyperspec-lookup'.") (define-key slime-mode-map "\C-c\C-dh" (lambda () (interactive) (let ((browse-url-browser-function hyperspec-browser-function)) (call-interactively 'slime-hyperspec-lookup)))) (global-set-key "\C-c\C-dh" '(lambda () (interactive) (let ((browse-url-browser-function hyperspec-browser-function)) (call-interactively 'slime-hyperspec-lookup)))) (setq lisp-simple-loop-indentation 1 lisp-loop-keyword-indentation 6 lisp-loop-forms-indentation 6) ) ;;; Erlang setup. (add-to-list 'load-path "~/emacs/erlang") (noerr-require 'erlang-start) ;;; Scheme setup. (setq scheme-program-name "mzscheme") (with-feature (quack) (set-face-foreground quack-pltish-defn-face "green") (define-key scheme-mode-map "\C-c\C-c" 'scheme-send-last-sexp) (define-key scheme-mode-map "\C-c\C-e" 'scheme-compile-definition-and-go) ) ;;; Haskell setup. (add-to-list 'load-path "~/emacs/haskell-mode-2.8.0/") (with-features (haskell-mode haskell-indent) (load "~/emacs/haskell-mode-2.8.0/haskell-site-file") (noerr-require 'inf-haskell) (add-hook 'haskell-mode-hook 'turn-on-haskell-indent) (remove-hook 'haskell-mode-hook 'turn-on-haskell-indentation) (setq haskell-indent-offset 2) (add-hook 'haskell-mode-hook '(lambda () (setq process-connection-type nil))) (setq haskell-program-name "ghci") (with-feature (mmm-haskell) (setq mmm-global-mode 'maybe) (add-to-list 'mmm-mode-ext-classes-alist '(latex-mode "\\.lhs$" haskell)) (add-to-list 'auto-mode-alist '("\\.lhs\\'" . latex-mode)) (eval-after-load "tex" '(progn (add-to-list 'LaTeX-command-style '("lhs" "lhslatex")) (add-to-list 'TeX-file-extensions "lhs"))))) (add-to-list 'load-path "~/emacs/sml-mode-4.1/") ;;; SML setup. (with-feature (sml-mode) ;; Use MOSML for DIKU. (setf sml-program-name "mosml") (setf sml-default-arg "-P full") (add-to-list 'auto-mode-alist '("\\.sml$" . sml-mode)) (add-to-list 'auto-mode-alist '("\\.ML$" . sml-mode)) (add-to-list 'auto-mode-alist '("\\.sig$" . sml-mode))) ;;;; Enable disabled options: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (put 'narrow-to-region 'disabled nil) ;;;; ERC-options: ;;;;;;;;;;;;;;;;; (with-feature (erc) (noerr-require 'erc-auto) (noerr-require 'erc-autojoin) (noerr-require 'erc-match) ;; Fix a potentially broken charset: (setq erc-default-coding-system '(utf-8 . undecided) erc-join-buffer 'bury) ;; Some stupid channels require obsolete charsets. (push '("#udvikleren.dk" . (iso-latin-1 . undecided)) erc-encoding-coding-alist) (push '("#linuxin.dk" . (iso-latin-1 . undecided)) erc-encoding-coding-alist) (push '("#piratgruppen.org" . (iso-latin-1 . undecided)) erc-encoding-coding-alist) ;; Display private messages in new buffers. (setq erc-auto-query 'buffer) (setq erc-paranoid t ; Show CTCP-messages. erc-email-userid "athas@@sigkill.dk" erc-user-full-name "Troels Henriksen" erc-prompt (lambda () (concat (buffer-name) ">")) erc-track-visibility 'visible) ;; Read-only: (add-hook 'erc-insert-post-hook 'erc-make-read-only) (add-hook 'erc-send-post-hook 'erc-make-read-only) ;; Spellchecking. (with-feature (flyspell) (erc-spelling-mode 1) (setq erc-spelling-dictionaries '(("irc.quakenet.org" "dansk") ("#eggsml" "dansk") ("#diku" "dansk") ("localhost" "dansk")))) ;; Hooks, put stuff here: (add-hook 'erc-mode-hook (lambda () ;; Use emacs-mule as coding system for all erc-buffers (for easy logging). (set (make-variable-buffer-local 'coding-system-for-write) 'emacs-mule))) ;; /hop command ala mIRC. ;; Generic slap. (defun erc-cmd-SLAPWITH (&rest rest) (erc-send-action (erc-default-target) (concat "slaps " (car rest) " around a bit with" (let (thing) (setq rest (cdr rest)) (while (not (equal (car rest) nil)) (setq thing (concat thing " " (car rest))) (setq rest (cdr rest))) thing) "."))) ;; So, I don't use Winamp, but I can at least print my Emacs-state. (defun erc-cmd-EMACS () (erc-send-action (erc-default-target) (apply 'concat "is editing " (nconc (mapcar (lambda (buffer) (concat "\"" (buffer-name buffer) "\" [" (save-excursion (set-buffer buffer) (symbol-name major-mode)) "], ")) (remove-if-not 'buffer-file-name (buffer-list))) (list "and that's it."))))) ;; Badass slap! (defun erc-cmd-SLAP (&rest nick) (erc-cmd-SLAPWITH (car nick) "a small 50lb Unix-manual")) ;; Yucky slap. :-( (defun erc-cmd-SLAPPENIS (&rest nick) (erc-cmd-SLAPWITH (car nick) (concat "his " (find-epenis) "cm long ePenis"))) (defun erc-cmd-EPENIS () "Calculates the size of your ePenis and writes it in `erc-default-target'" (erc-send-message (get-epenis))) (defun penisdyst (process response) (let ((user (car (erc-parse-user (erc-response.sender response))))) (when (and (string= "!penisdyst" (erc-response.contents response)) (or (string-equal "KasperTSW" user) (string-equal "Athas" user) (string-equal "WinAthas" user))) (save-excursion (set-buffer (first (erc-response.command-args response))) (erc-send-message (get-epenis))))) nil) (add-hook 'erc-server-PRIVMSG-functions 'penisdyst) (defun get-epenis () "Returns a string describing your ePenis." (let ((penis (find-epenis))) (concat "ePenis: " (graph-epenis (string-to-number penis) 4) " (" penis "cm)."))) (defun graph-epenis (length fraction) "Return ASCII image of epenis of length LENGTH, with one \"piece\" for each FRACTION in LENGTH." (concat "o" (make-string (floor (/ length fraction)) ?=) "8")) (defun find-epenis () "Return a string containing size of electronic penis. Returns the value in centimeters." (shell-command "cat /proc/uptime") ; Puts output in *Shell Command Output* (save-excursion (set-buffer "*Shell Command Output*") (goto-char (point-min)) (format "%.3f" (* 2.427 (log (string-to-int (buffer-substring (point-min) (search-forward "." (point-max))))))))) (defvar irc-nickname "YuleAthas" "Standard nickname for use on IRC") (defvar irc-port 6667 "Standard port to connect to IRC servers with.") (defvar irc-realname "Troels Henriksen" "Standard real name on IRC.") ;;; ERC really doesn't like connecting to the same IRC-server ;;; twice. Therefore, I set up a guard, to error out early, before any ;;; network connections are made, if ERC is already connected to the ;;; specified server. (defvar irc-connected-hosts nil "List of servers ERC is connected to.") (defun irc-connect (server &optional port) "Connect to SERVER via ERC, using default values for nickname, realname and port. Port can be specified as optional parameter PORT. The default values are specified in the variables `irc-nickname', `irc-port' and `irc-realname'." (when (find server irc-connected-hosts) (error "Already connected to server.")) (erc :server server :port (or port irc-port) :nick irc-nickname :full-name irc-realname) (push server irc-connected-hosts)) (defun irc-bitlbee () (interactive) (irc-connect "localhost" 6667)) (defun irc-quakenet () "Connect to the QuakeNet IRC-network using ERC." (interactive) (irc-connect "irc.quakenet.org")) (defun irc-freenode () "Connect to the Freenode IRC-network using ERC." (interactive) (irc-connect "irc.freenode.net" 8001)) (defun irc-efnet () "Connect to the EFNet IRC-network using ERC." (interactive) (irc-connect "irc.inet.tele.dk" 6661)) (defun irc-chatsociety () "Connect to the ChatSociety IRC-network using ERC." (interactive) (irc-connect "irc.chatsociety.net")) (defun irc-synirc () "Connect to the SynIRC IRC-network using ERC." (interactive) (irc-connect "irc.synirc.net")) (defun irc-zybourne () "Connect to the Zybourne IRC-network using ERC." (interactive) (irc-connect "irc.zybourne.net")) (defun irc-oftc () (interactive) (irc-connect "irc.oftc.net")) (defun irc-cleanup () "Kills all IRC buffers. For now, it kills all buffers in ERC-mode." (interactive) (save-window-excursion (let ((print-list) (obuffer (current-buffer))) (dolist (buffer (buffer-list)) (set-buffer buffer) (when (eq major-mode 'erc-mode) (set-buffer buffer) (progn (kill-buffer buffer)))) (setq irc-connected-hosts nil)))) (add-to-list 'kill-emacs-query-functions (lambda () (progn 'irc-cleanup t))) ; Just to clean up properly. ;; Wrapper function to connect. (defun irc () "Automatically connects to the IRC-servers irc.quakenet.org and irc.freenode.net using ERC." (interactive) (irc-quakenet) (irc-freenode) (irc-oftc) (irc-bitlbee)) ;; Set up highlight-options: (setq erc-keywords '("Athas" "YuleAthas" "Climacs" "climacs")) (erc-match-mode 1) ;; Make my prompt reflect the current channel: (setq erc-prompt (lambda () (if (and (boundp 'erc-default-recipients) (erc-default-target)) (erc-propertize (concat (erc-default-target) ">") 'read-only t 'rear-nonsticky t 'front-nonsticky t) (erc-propertize (concat "ERC>") 'read-only t 'rear-nonsticky t 'front-nonsticky t)))) ;; Auto-join of channels is a nice thing to have. (erc-autojoin-mode 1) (setq erc-autojoin-channels-alist '(("irc.inet.tele.dk" "#sslug") ("freenode.net" "#emacs" "#lisp" "#diku" "#haskell" "#ghc" "#xmonad" "#cat-v" "#eggsml") ("chatsociety.net" "#piratgruppen.org") ("quakenet.org" "#udvikleren.dk") ("zybourne.net" "#cobol") ("oftc.net" "#suckless") )) (setq erc-truncate-buffer-on-save nil) ;; Timestamps: (erc-timestamp-mode t) (setq erc-hide-timestamps nil erc-timestamp-only-if-changed-flag nil erc-timestamp-format "%R:%S " erc-fill-prefix " " erc-insert-timestamp-function 'erc-insert-timestamp-left) ;;; Logging ;; Set up logging: (setq erc-log-insert-log-on-open t) (setq erc-log-channels nil) (setq erc-enable-logging t) (setq erc-log-channels-directory "~/.irclogs/") (setq erc-generate-log-file-name-function 'erc-generate-log-file-name) (defun erc-generate-log-file-name (buffer target nick server port) "This function computes a somewhat short log file name. In fact, it only uses the target and server name, so you can affect that using `rename-buffer' and the-like. This function is a possible value for `erc-generate-log-file-name-function'." (let ((file (concat target "@" server ".txt"))) ;; we need a make-safe-file-name function. (convert-standard-filename file))) (setq erc-save-buffer-on-part t erc-save-queries-on-quit t erc-log-write-after-send t erc-log-write-after-insert t) (add-hook 'erc-insert-post-hook 'erc-save-buffer-in-logs) ;; When exiting emacs, save all logs without confirmation (defadvice save-buffers-kill-emacs (before save-logs (&rest args) activate) (save-some-buffers t (lambda () (when (and (eq major-mode 'erc-mode) (not (null buffer-file-name))) t)))) ) ;;;; Eshell: ;;;;;;;;;;;; (with-feature (eshell) (noerr-require 'esh-mode) (noerr-require 'em-cmpl) (setq eshell-history-size 16000) (add-to-list 'eshell-output-filter-functions 'eshell-handle-control-codes) ) ;;;; Auxilliary Functions: ;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; My own auxilliary functions are prefixed with trh-. ;;; I always end up with spurious whitespaces, this will remove them. (defun trh-remove-whitespace-around-point () "Removes whitespace from point up to, anc back to, the next non-whitespace. Will affect linebreaks, tabs and spaces" (interactive) (save-excursion (let ((orig-pos (point))) (delete-region (progn (skip-chars-forward " \t\n") (constrain-to-field nil orig-pos t)) (progn (skip-chars-backward " \t\n") (constrain-to-field nil orig-pos)))))) (global-set-key "\C-cr" 'trh-remove-whitespace-around-point) (defun trh-indent-whole-buffer () "Indents the whole buffer. Uses ``indent-region'' to indent the whole buffer." (interactive) (when (y-or-n-p "Are you sure you want to indent the entire buffer? ") (indent-region (point-min) (point-max) nil))) (global-set-key "\C-ci" 'trh-indent-whole-buffer) (defun trh-visit-all-buffers () "Will switch to, and close, all currently active buffers. This is designed to be used in conjuction with ERC." (interactive) (save-window-excursion (let ((print-list) (obuffer (current-buffer))) (dolist (buffer (buffer-list)) (switch-to-buffer buffer))))) (global-set-key "\C-cg" 'trh-visit-all-buffers) (defun trh-switch-to-gnus (&optional arg) "Switch to a Gnus related buffer. Candidates are buffers starting with *mail or *reply or *wide reply *Summary or *Group* Use a prefix argument to start Gnus if no candidate exists." (interactive "P") (let (candidate (alist '(("^\\*\\(mail\\|\\(wide \\)?reply\\)" t) ("^\\*Group") ("^\\*Summary") ("^\\*Article" nil (lambda () (buffer-live-p gnus-article-current-summary)))))) (catch 'none-found (dolist (item alist) (let (last (regexp (nth 0 item)) (optional (nth 1 item)) (test (nth 2 item))) (dolist (buf (buffer-list)) (when (and (string-match regexp (buffer-name buf)) (> (buffer-size buf) 0)) (setq last buf))) (cond ((and last (or (not test) (funcall test))) (setq candidate last)) (optional nil) (t (throw 'none-found t)))))) (cond (candidate (switch-to-buffer candidate)) (arg (gnus)) (t (error "Gnus does not appear to be running,"))))) (global-set-key (kbd "\C-cf") 'trh-switch-to-gnus) (defun trh-insert-shell-command-output (command) "Inserts the output of COMMAND at point. This function will garble the contents of *Shell Command Output* if the buffer already exists." (interactive "MCommand: ") (shell-command command) ; Puts output in *Shell Command Output* (insert-string (save-excursion (save-window-excursion (set-buffer "*Shell Command Output*") (buffer-substring (point-min) (point-max)))))) (global-set-key "\C-c!" 'trh-insert-shell-command-output) ;;; Surf is my preferred browser. (setq browse-url-generic-program "grani" browse-url-generic-args '() browse-url-browser-function 'browse-url-generic) (defun untabify-buffer () "Call `untabify' with the entire buffer as region." (interactive) (untabify (point-min) (point-max))) ;;;; Ugly Hacks and Workarounds: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; This section contains dubious code that provides short-term solutions to ;;; problems that annoy me. (defun mmm-parse-buffer () "Re-apply all applicable submode classes to current buffer. Clears all current submode regions, reapplies all past interactive mmm-ification, and applies `mmm-classes' and mode-extension classes." (interactive) (message "MMM-ifying buffer...") (save-excursion (mmm-apply-all)) (message "MMM-ifying buffer...done")) ;;;; What to do when starting computer: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun on-start () (irc) (gnus)) ;;;; Custom-set-variables: ;;;;;;;;;;;;;;;;;;;;;;;;;; (custom-set-variables ;; custom-set-variables was added by Custom. ;; If you edit it by hand, you could mess it up, so be careful. ;; Your init file should contain only one such instance. ;; If there is more than one, they won't work right. '(load-home-init-file t t)) (put 'downcase-region 'disabled nil) (custom-set-faces ;; custom-set-faces was added by Custom. ;; If you edit it by hand, you could mess it up, so be careful. ;; Your init file should contain only one such instance. ;; If there is more than one, they won't work right. '(mmm-code-submode-face ((t nil))) '(mmm-default-submode-face ((t nil)))) (defun toggle-linecomment () (interactive) (save-excursion (comment-or-uncomment-region (progn (beginning-of-line) (point)) (progn (end-of-line) (point)))))