;; .emacs -*- mode: emacs-lisp -*- (add-to-list 'load-path (expand-file-name "/usr/share/emacs/site-lisp")) (add-to-list 'load-path (expand-file-name "~/emacs/share/emacs/site-lisp")) (add-to-list 'load-path (expand-file-name "~/elisp")) (add-to-list 'load-path (expand-file-name "~/mc/elisp")) (add-to-list 'load-path "/usr/share/emacs/site-lisp/coq") ;; This was installed by package-install.el. ;; This provides support for the package system and ;; interfacing with ELPA, the package archive. ;; Move this code earlier if you want to reference ;; packages in your .emacs. (when (load (expand-file-name "~/.emacs.d/elpa/package.el")) (package-initialize)) ;;; This could be better. One shouldn't need to mark the region, for ;;; example. (defun jimb-fix-comment (start end) (interactive "r") (save-excursion (goto-char start) (forward-line 1) (if (>= (point) end) ;; Single-line comment. (progn (goto-char start) (skip-syntax-forward "-") (unless (looking-at "// ") (error "Line doesn't start with a C++-style comment.")) (delete-char 3) (insert "/* ") (end-of-line) (delete-horizontal-space) (insert " */")) ;; Multi-line comment. (goto-char start) (skip-syntax-forward "-") (unless (looking-at "//") (error "Line doesn't start with a C++-style comment.")) (let ((column (current-column))) (insert "/*\n") (indent-to-column column) (beginning-of-line) (while (< (point) end) (skip-syntax-forward "-") (unless (looking-at "// ") (error "Line doesn't start with a C++-style comment.")) (replace-match " * ") (forward-line 1)) (insert " */\n") (forward-line -1) (indent-to-column column))))) ;;; Give save-some-buffers the ability to revert buffers. (defun save-some-buffers-revert-action (buffer) (with-current-buffer buffer (revert-buffer t)) t) (add-to-list 'save-some-buffers-action-alist (list ?r 'save-some-buffers-revert-action "revert changes to this buffer")) ;;; A better OCaml mode ;(add-to-list 'load-path (expand-file-name "~/elisp/tuareg-mode-1.45.6")) ;(setq auto-mode-alist (cons '("\\.ml\\w?" . tuareg-mode) auto-mode-alist)) ;(autoload 'tuareg-mode "tuareg" "Major mode for editing Caml code" t) ;(autoload 'camldebug "camldebug" "Run the Caml debugger" t) ;;; Load this from the source tree, since I'm hacking on it. (add-to-list 'load-path (expand-file-name "~/idutils/idutils-4.2/lisp")) (autoload 'gid "idutils" "Run gid." t) ;;; A stupid, bad mode for editing MediaWiki markup. (autoload 'wiki-mode "wiki-mode" "A major mode for editing MediaWiki text." t) ;;; Use Steve Yegge's js2-mode, not javascript mode. (setq auto-mode-alist (rassq-delete-all 'javascript-mode auto-mode-alist)) (autoload 'js2-mode "js2-mode" nil t) (add-to-list 'auto-mode-alist '("\\.js$" . js2-mode)) ;;; Treat *.mm files as Objective C++, not nroff. (add-to-list 'auto-mode-alist '("\\.mm$" . objc-mode)) ;;; Mercurial Queues support. (require 'mercurial-queues) (add-to-list 'auto-mode-alist '(".hg/patches/series$" . mq-series-mode)) ;;; Beeps. ;(require 'jimb-sound) ;(js-set-beep-sound-file "/usr/share/sounds/question.wav") ; a gentle 'tink' ;(setq visible-bell t) ; fallback ;;;; Beep when a compilation is done. (defun beep-beep () (beep t) (sit-for 0.2) (beep t) (beep t)) (defun jimb-compilation-finish (buffer status) (beep-beep)) (add-hook 'compilation-finish-functions 'jimb-compilation-finish) ;; Display code coverage reports with long lines truncated. (defun jimb-truncate-long-gcov-lines-hook () (if (and buffer-file-name (string-match "\\.gcov$" buffer-file-name)) (setq truncate-lines t))) (add-hook 'compilation-mode-hook 'jimb-truncate-long-gcov-lines-hook) ;;; JavaScript (require 'jimb-js) ;;; Bugzilla. (require 'bugzilla) ;;; ERC ;;; missing from source (autoload 'erc-tls "erc" "IRC over TLS." t) ;;; Haskell (load (expand-file-name "~/elisp/haskell-mode-2.4/haskell-site-file")) ;;; psvn (setq svn-status-verbose nil) (autoload 'svn-status "psvn" "Until vc-directory grows up." t) ;;; columns (autoload 'columnify "columns" "Reformat the lines in the current region into a columnar list." t) ;;; before-and-after patch queue pairs (defun jimb-swap-substrings (s1 s2 string) "Return STRING with S1 changed to S2 and vice versa." (replace-regexp-in-string (concat (regexp-quote s1) "\\|" (regexp-quote s2)) (lambda (match) (if (string-equal match "push") "pop" "push")) string nil t)) (defun jimb-push-pop-find-file-other-window () "Find a file by the same name as the current, with 'push' changed to 'pop'. This works like find-file-other-window, except that the default filename is that of the current buffer, with 'push' changed to 'pop' and vice versa." (interactive) (let* ((current (buffer-file-name)) (swapped (jimb-swap-substrings "push" "pop" current))) (if (string-equal current swapped) (error "Filename has no 'push' or 'pop': %s" current)) (find-file-other-window swapped))) ;;; Org mode (add-to-list 'auto-mode-alist '("\\.org$" . org-mode)) (global-set-key "\C-cl" 'org-store-link) (global-set-key "\C-ca" 'org-agenda) ;;; balance-mode (autoload 'balance-mode "balance" "Minor mode for editing balance sheets. The buffer can contain arbitrary text, marked up with tags that denote credits, debits, and where to show the current total." t) ;;; Coq (setq auto-mode-alist (cons '("\\.v$" . coq-mode) auto-mode-alist)) (autoload 'coq-mode "coq" "Major mode for editing Coq vernacular." t) (autoload 'run-coq "coq-inferior" "Run an inferior Coq process." t) (autoload 'run-coq-other-window "coq-inferior" "Run an inferior Coq process in a new window." t) (autoload 'run-coq-other-frame "coq-inferior" "Run an inferior Coq process in a new frame." t) ;; System Tap is a little like C. (add-to-list 'auto-mode-alist '("\\.stp$" . c-mode)) ;; uClibc uses an '.oS' extension for PIC object files. (add-to-list 'completion-ignored-extensions ".oS") (add-to-list 'completion-ignored-extensions ".os") ;;; uncomment this line to disable loading of "default.el" at startup ;; (setq inhibit-default-init t) (ffap-bindings) (global-set-key "\C-x\C-m" 'compile) (global-set-key "\C-x\C-y" 'bury-buffer) (global-set-key "\C-xl" 'goto-line) (global-set-key "\C-x\C-l" 'what-line) (global-set-key "\C-cc" 'compare-windows) (global-set-key "\C-cq" 'jimb-push-pop-find-file-other-window) (global-set-key [M-return] 'apply-macro-to-region-lines) (global-unset-key "\M-g") ;;; Use rst-mode for Structured text. (autoload 'rst-mode "rst" "Major mode for editing reStructuredText documents." t) (add-to-list 'auto-mode-alist '("\\.rst$" . rst-mode)) (add-to-list 'auto-mode-alist '("\\.rest$" . rst-mode)) (add-to-list 'auto-mode-alist '("\\.mak$" . makefile-mode)) (require 'jimb-frames) ;;;; Easily convert regexp isearches to whole-symbol searches. (defun jimb-isearch-regexp-whole-symbol () "Wrap the current regexp in \_< and \_> operators, to search for a whole symbol." (interactive) (unless isearch-regexp (setq isearch-regexp t isearch-word nil isearch-success t isearch-adjusted t)) (if (not (string-match "\\`\\\\_<.*\\\\_>\\'" isearch-string)) (setq isearch-string (concat "\\_<" isearch-string "\\_>") isearch-message (mapconcat 'isearch-text-char-description isearch-string "") ;; Don't move cursor in reverse search. isearch-yank-flag t)) (isearch-search-and-update)) (define-key isearch-mode-map "\M-e" 'jimb-isearch-regexp-whole-symbol) ;;;; Offer to update copyright years. (add-hook 'write-file-hook 'copyright-update) ;;;; I like auto-fill-mode. (add-hook 'text-mode-hook 'auto-fill-mode) ;;; Count words in region. (defun jimb-count-words (start end) "Count the words between point and mark." (interactive "r") (let ((count 0)) (save-excursion (goto-char start) (while (re-search-forward "\\<" end t) (setq count (1+ count)) (forward-char 1))) (message "Region has %d words." count))) (defun jimb-count-xml-words (start end) (interactive "r") "Count the words between point and mark, ignoring XML tags." (let ((count 0)) (save-excursion (goto-char start) (while (re-search-forward "\\<" end t) (if (not (looking-at "[a-z0-9]+>")) (setq count (1+ count))) (forward-char 1))) (message "Region has %d words." count))) ;;;; Set tab width properly for ocdremote and uClibc source code (defun custom-tab-width () "Check the filename; if we seem to be in ocdremote, set a tab width of 4." (if buffer-file-name (save-match-data (let ((aname (abbreviate-file-name buffer-file-name))) (cond ((string-match "/\\(wc-\\)?ocdremote.*/" aname) (setq tab-width 4))))))) (add-hook 'c-mode-common-hook 'custom-tab-width) (defun parse-vi-options () "Check the first line of the buffer for VI settings. You can add this function to 'find-file-hook'." (save-excursion (goto-char (point-min)) (if (looking-at ".*\\bvi: set ") (progn (if (looking-at ".*vi: set .*\\bts=\\([0-9]+\\)\\b") (setq tab-width (string-to-int (match-string 1)))) (if (looking-at ".*vi: set .*\\bsw=\\([0-9]+\\)\\b") (setq c-basic-offset (string-to-int (match-string 1)))))))) (add-hook 'find-file-hook 'parse-vi-options) (defun jimb-current-line () "Return the contents of the current line, as a string. This includes the final newline, if any." (save-excursion (forward-line 0) (let ((start (point))) (forward-line 1) (buffer-substring start (point))))) (defun jimb-gcc-cleanup () "Reformat the GCC invocation on the current line for legibility." (interactive) (let ((case-fold-search nil)) (save-excursion (let ((line (jimb-current-line))) (set-buffer (get-buffer-create "*GCC invocation*")) (erase-buffer) (insert line) ;; Break the line after each flag (and value, if any). (goto-char (point-min)) (while (< (point) (point-max)) (if (looking-at "-\\([IoLTe]\\|include\\|isysroot\\)\\s-+\\S-+\\s-*") (goto-char (match-end 0)) (re-search-forward "\\s-+" nil 'at-limit)) (insert "\n")) ;; Pop up the results in a new window, with point at the top. (goto-char (point-min)) (display-buffer (current-buffer)))))) ;;;; Remove newlines that are not paragraph separators from the region (defun jimb-paragraph-no-newlines (start end) "Collapse paragraphs into single lines. A paragraph is a series of non-indented, non-empty lines." (interactive "*r") (save-excursion (goto-char start) (while (and (< (point) end) (re-search-forward "^\\S-.*\\(\n\\)\\S-" end t)) (goto-char (match-beginning 1)) (skip-syntax-backward "-") (delete-region (point) (match-end 1)) (insert " ") (beginning-of-line) ;ugh ))) ;;;; Indent Linux kernel code properly. (defun linux-c-mode () "C mode with adjusted defaults for use with the Linux kernel." (interactive) (c-mode) (c-set-style "linux")) (require 'google-c-style) (require 'mozilla-c-style) (mozilla-auto-select-style) ;; turn on font-lock mode (global-font-lock-mode t) ; I tend to give temporary patches these names, with a ~ at the end. (add-to-list 'auto-mode-alist '("/[pq][0-9]?\\'" . diff-mode)) (defun jimb-diff-mode-hook () (define-key diff-mode-map "\M-q" nil)) (add-hook 'diff-mode-hook 'jimb-diff-mode-hook) (require 'diff-find-mq-file) ;; Indent with-syntax properly in Scheme (put 'with-syntax 'scheme-indent-function 'scheme-let-indent) ;;;;; Alternate dired-view command (require 'alt-dired-view) (add-to-list 'dired-view-handler-alist '("\\.ps$" . dired-view-pdf)) ;;;;; We use emacsclient as our $EDITOR. (server-start) ;;;;; We like page-ext. (require 'page-ext) ;;;; Our own patch processing code. (require 'jimb-patch) (require 'patchutils) ;;;; Timecard mode. (autoload 'timecard-mode "timecard" "A major mode for keeping track of where the time goes." t) (global-set-key "\C-ct" 'jimb-find-timecard) (global-set-key "\C-cb" 'jimb-backup-notes) (global-set-key "\C-c4t" 'jimb-find-timecard-other-window) (defun jimb-find-timecard () (interactive) (find-file "~/NOTES")) (defun jimb-backup-notes () (interactive) (let ((command "rsync ~/NOTES sp.red-bean.com:")) (message "Backing up notes: %s" command) (shell-command command))) (defun jimb-find-timecard-other-window () (interactive) (find-file-other-window "~/diary")) ;; ;;;;; Zen IRC ;; ;; (autoload 'zenirc (expand-file-name "~/.zenirc") "Waste time." t) ;; ;;;; Sending mail. (require 'sendmail) (setq message-send-mail-function 'sendmail-send-it) (setq send-mail-function 'sendmail-send-it) (setq sendmail-program "/usr/bin/msmtp") (setq message-default-headers "Bcc: jimb@mozilla.com\n") ;;; Some custom commands for message mode. (defun jimb-insert-citation-line () "Insert a simple citation line, obscuring email addresses." (when message-reply-headers (let ((addr (mail-header-from message-reply-headers))) (while (string-match "@" addr) (setq addr (replace-match " at " t t addr))) (insert addr " writes:") (newline) (newline)))) (setq message-citation-line-function 'jimb-insert-citation-line) (defun jimb-message-red-bean () "Change the 'from' address in the current buffer to . This works only in message-mode buffers." (interactive) (save-excursion (if (message-position-on-field "From") (let ((end (point))) (re-search-backward "^From:[ \t]*") (goto-char (match-end 0)) (delete-region (point) end))) (insert "Jim Blandy "))) ;;; Use a named function instead of a lambda, to simplify changing the ;;; hook definition and to help add-hook properly recognize when the ;;; hook has already been added when we do change it. (defun jimb-message-hook () (define-key message-mode-map "\C-cb" 'jimb-message-red-bean)) (add-hook 'message-mode-hook 'jimb-message-hook) (defmacro jimb-log-time (name &rest body) "Log the time required to evaluate BODY in *scratch*, referring to it by NAME." (declare (indent defun)) `(let ((jimb-log-time-start (float-time)) (jimb-log-message ,name) (jimb-log-value (let ((jimb-log-time-nesting-level (1+ jimb-log-time-nesting-level))) ,@body))) (jimb-log-time-log jimb-log-message jimb-log-time-start (float-time)) jimb-log-value)) (defvar jimb-log-time-nesting-level 0) (defun jimb-log-time-log (msg start end) (save-excursion (set-buffer (get-buffer-create "*jimb-log-time*")) (goto-char (point-max)) (insert-char ? (* jimb-log-time-nesting-level 3)) (insert (format "%.5fs: %s\n" (- end start) msg)))) (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. '(add-log-full-name "Jim Blandy") '(add-log-mailing-address "jimb@red-bean.com") '(auto-raise-tool-bar-buttons t t) '(auto-resize-tool-bars t t) '(browse-url-browser-function (quote browse-url-firefox)) '(canlock-password "569e99838ad4e7168a08f42942713814fea2ddc1") '(change-log-default-name nil) '(compilation-scroll-output (quote first-error)) '(compile-command "make") '(diff-switches "-u") '(enable-recursive-minibuffers t) '(erc-autojoin-channels-alist (quote (("denied.to" "#ptp") ("mozilla.org" "#jslang" "#staffmeeting" "#planning" "#static" "#developers" "#jsapi" "#content" "#mozpdx" "#devtools") ("freenode.net" "#gdb" "#red-bean" "#osi")))) '(erc-autojoin-mode t) '(erc-join-buffer (quote bury)) '(erc-keywords (quote ("emacs"))) '(erc-nick (quote ("jimb" "jimblandy"))) '(erc-port 6667) '(erc-server "irc.mozilla.org:6697") '(erc-server-reconnect-timeout 10) '(erc-track-exclude-types (quote ("JOIN" "KICK" "NICK" "PART" "QUIT" "MODE" "333" "353"))) '(erc-user-full-name "Jim Blandy") '(ffap-require-prefix t) '(fill-column 75) '(garbage-collection-messages t) '(grep-highlight-matches nil) '(indent-tabs-mode nil) '(js2-cleanup-whitespace nil) '(mail-user-agent (quote gnus-user-agent)) '(mark-even-if-inactive t) '(menu-bar-mode nil nil (menu-bar)) '(minibuffer-message-timeout 2 t) '(mouse-wheel-scroll-amount (quote (1))) '(org-agenda-files (quote ("~/dwarf/NOTES" "~/NOTES"))) '(pages-directory-buffer-narrowing-p nil) '(scheme-program-name "mzscheme") '(sentence-end-double-space nil) '(smtpmail-smtp-service "smtp") '(tool-bar-button-margin 1 t) '(tool-bar-mode nil) '(user-mail-address "jimb@mozilla.com") '(x-select-enable-clipboard t)) (put 'narrow-to-region 'disabled nil) (put 'scroll-left '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. '(default ((t (:inherit nil :stipple nil :background "#ffffff" :foreground "#000000" :inverse-video nil :box nil :strike-through nil :overline nil :underline nil :slant normal :weight normal :height 94 :width normal :foundry "unknown" :family "DejaVu Sans Mono")))))