$Id: emacs,v 1.222 2006/03/02 22:51:16 gmorris Exp $
(defun my-initialize ()
"Set up the system-dependent variables."
(interactive)
(let ((host (downcase (system-name))))
(setq my-system
(cond
((string-match "^\\(cass\\|capc\\)" host) "cass")
((string-match ".*\\.ast\\.cam\\.ac\\.uk" host) "xray")
((string-match "^\\(furness\\|rgm22\\)" host) "furn")
((string-match ".*\\.slac\\.stanford\\.edu" host) "slac")
((string-match "grasmoor" host) "gras")
((string-match "kipac-dell*" host) "kdell")
((string-match ".*\\.stanford\\.edu" host) "stanford")
((string-match "\\.gnu\\.org" host) "gnu")
(t "unkn"))))
(setq my-emacs-type (if (boundp 'my-emacs-type) my-emacs-type
(if (or (member "gnus" command-line-args)
(member "vm" command-line-args))
'mail
'main))
my-printer (or (getenv "PRINTER") "lp2")
my-user "gmorris"
my-emacsdir (expand-file-name "~/.emacs.d/")
my-backupdir (expand-file-name "backups" my-emacsdir)
my-sitelisp (file-truename
(expand-file-name
"~/scratch/software/share/emacs/site-lisp")))
(cond
((string-equal my-system "xray"))
((string-equal my-system "slac")
(setq my-printer "ki-hp4200"))
((string-equal my-system "stanford")
(setq my-user "rgm"
my-sitelisp (expand-file-name "~/elisp")))
((string-equal my-system "kdell")
(setq my-printer "hptheory"))
((string-equal my-system "gras")
(setq my-user "gm"))
((string-equal my-system "gnu")
(setq my-printer "InvalidPrinter"
my-user "rgm"
my-sitelisp (expand-file-name "~/elisp")))
((string-equal my-system "furn")
(setq my-printer "lp0"
my-user "gm"
my-sitelisp "/usr/local/share/emacs/site-lisp")))
(and (zerop (user-uid)) (setq my-user "root")))
(my-initialize)
(or (string-equal (user-real-login-name) my-user)
(error "Init-file belongs to %s, load aborted" my-user))
(defun my-lockfile-name ()
"Return name of `my-lockfile' as a string.
Mail lockfiles go in home directory, others in temporary directory."
(let (dot dir type)
(if (equal my-emacs-type 'mail)
(setq dot "."
dir "~"
type "-mail")
(setq dot ""
dir temporary-file-directory
type ""))
(expand-file-name
(format "%semacs%s%s.lock" dot (user-uid) type)
dir)))
(setq my-lockfile (my-lockfile-name))
(defun my-lockfile-host ()
"Extract the hostname from `my-lockfile'."
(with-temp-buffer
(insert-file-contents my-lockfile)
(buffer-substring (point-min) (point-max))))
(defun my-lockfile-create ()
"Create `my-lockfile'."
(with-temp-file my-lockfile
(insert (substring (downcase system-name)
0 (string-match "\\." system-name)))))
(defun my-lockfile-delete ()
"Delete `my-lockfile'."
(when (file-exists-p my-lockfile)
(delete-file my-lockfile)))
(if (file-exists-p my-lockfile)
(if (equal my-emacs-type 'mail)
(progn
TODO (put 'gnus 'disabled t)
(error "Mail Emacs already running on %s" (my-lockfile-host)))
(setq my-emacs-type 'secondary))
(my-lockfile-create)
(add-hook 'my-before-kill-emacs-hook 'my-lockfile-delete))
TODO(when (equal my-emacs-type 'mail)
(require 'private (expand-file-name "private.el" my-emacsdir) t))
(setq my-normal-cursor-colour "Orchid")
(when window-system
(if (boundp 'tool-bar-button-margin)
(setq tool-bar-button-margin 3
tool-bar-button-relief 2))
(setq ruler-mode-show-tab-stops t)
(let ((resvar
(shell-command-to-string
"/usr/X11R6/bin/xdpyinfo |awk '$1 ~ /dimensions/ {print $2; exit}'"
)))
(setq default-frame-alist
`(
(background-color . ,(if (string-equal my-user "root") "Black"
"DarkSlateGrey"))
(foreground-color . ,(if (string-equal my-user "root") "White"
"Wheat"))
,(cons 'width (frame-width))
,(cons 'height (frame-height))
(cursor-color . ,my-normal-cursor-colour)
(mouse-color . ,my-normal-cursor-colour)
))))
TODO(setq inhibit-startup-buffer-menu t inhibit-startup-echo-area-message my-user
initial-scratch-message nil)
(if (or (not window-system)
(not (fboundp 'fancy-splash-screens))
(equal my-emacs-type 'mail))
(setq inhibit-startup-message t)
(defun my-splash ()
"Show the splash screen."
(interactive)
(fancy-splash-screens))
(setq fancy-splash-delay 10
fancy-splash-max-time 600)
(let* ((quote "~/scripts/quote.bash")
(image (expand-file-name "images/gnuspiritflare.xpm" my-emacsdir))
(text
(and (file-executable-p quote) (shell-command-to-string quote))))
(and (file-exists-p image) (setq fancy-splash-image image))
(when text
(setq fancy-splash-text nil) (add-to-list
'fancy-splash-text
(list :face '(variable-pitch :foreground "lawngreen" :weight bold)
"\n\nWelcome to the brave GNU world...\n\n"
:face '(variable-pitch :foreground "lawngreen")
"Startup: " (current-time-string) "\n\n"
text)))))
(setq make-backup-files t version-control nil kept-old-versions 2
kept-new-versions 2
backup-by-copying nil
backup-by-copying-when-linked t
backup-by-copying-when-mismatch nil
backup-by-copying-when-privileged-mismatch 200
delete-old-versions t delete-auto-save-files t auto-save-default t auto-save-interval 200 auto-save-timeout 30)
(unless (file-directory-p my-emacsdir)
(make-directory my-emacsdir)
(set-file-modes my-emacsdir 448))
(if (boundp 'backup-directory-alist)
(let ((dir my-backupdir))
(or (file-directory-p dir) (make-directory dir))
(setq backup-directory-alist `(("." . ,dir))
version-control t)))
(if (boundp 'confirm-kill-emacs) (setq confirm-kill-emacs 'yes-or-no-p))
(let ((dir (expand-file-name "saves" my-emacsdir)))
(or (file-directory-p dir) (make-directory dir))
(setq auto-save-list-file-prefix (expand-file-name "saves-" dir)))
(defvar my-backup-disable-list nil
"List of directories/files which should not be backed up.
If an element is a file, it is not backed up.
If an element is a directory, nothing under that directory is backed up.
File elements may be regexps.")
TODO(defun my-backup-enable-predicate (name)
"Function to use for `backup-enable-predicate'.
First runs `normal-backup-enable-predicate'. If that is non-nil,
checks against the elements of `my-backup-disable-list', if non-nil.
Returns t to enable backup, nil otherwise."
(when (normal-backup-enable-predicate name)
(not
(when (listp my-backup-disable-list)
(catch 'found
(let (comp)
(dolist (elem my-backup-disable-list)
(setq comp (compare-strings elem 0 nil name 0 nil))
(and
TODO (if (string-equal elem (file-name-as-directory elem))
(and (not (eq comp t)) (< comp (- (length elem))))
(string-match elem name))
(throw 'found t)))))))))
(and (fboundp 'normal-backup-enable-predicate)
(setq backup-enable-predicate 'my-backup-enable-predicate))
(setq my-enable-cursor-indications t
my-read-only-cursor-colour "cyan"
my-overwrite-cursor-colour "green")
(defun my-set-cursor-colour ()
"Set the cursor colour.
Intended for use with `post-command-hook'.
Adapted from `cua--update-indications' and `cua--post-command-handler'."
(condition-case nil
(if my-enable-cursor-indications
(let ((cursor
(cond (buffer-read-only my-read-only-cursor-colour)
(overwrite-mode my-overwrite-cursor-colour)
(t my-normal-cursor-colour))))
(and cursor (stringp cursor)
(not (string-equal cursor
(frame-parameter nil 'cursor-color)))
(set-cursor-color cursor))))
(error nil)))
(add-hook 'post-command-hook 'my-set-cursor-colour)
(if (boundp 'yank-excluded-properties)
(add-to-list 'yank-excluded-properties 'face))
(put 'truncate-lines 'permanent-local t)
(setq eval-expression-debug-on-error nil
enable-local-variables t
enable-local-eval 'query)
(fset 'yes-or-no-p 'y-or-n-p)
(define-key query-replace-map " " 'undefined) (define-key query-replace-map [delete] 'undefined) (define-key query-replace-map [backspace] 'undefined)
(setq mouse-yank-at-point t column-number-mode t
next-line-add-newlines nil require-final-newline t buffers-menu-max-size 25 message-log-max 1000
line-number-display-limit 10000000 default-buffer-file-coding-system 'undecided-unix
mouse-buffer-menu-mode-mult 4
track-eol nil
display-buffer-reuse-frames t
history-delete-duplicates t
even-window-heights nil
custom-buffer-style 'brackets
cursor-in-non-selected-windows t
highlight-nonselected-windows t compile-auto-highlight t
imenu-max-items 50
imenu-scanning-message nil x-select-enable-clipboard nil
focus-follows-mouse nil
scroll-preserve-screen-position t
scroll-step 1 kill-ring-max 100)
(if (boundp 'show-nonbreak-escape) (setq show-nonbreak-escape t))
(defadvice set-mark-command (after no-bloody-t-m-m activate)
"Prevent consecutive marks activating bloody `transient-mark-mode'."
(if (eq transient-mark-mode 'lambda)
(setq transient-mark-mode nil)))
(defadvice mouse-set-region-1 (after no-bloody-t-m-m activate)
"Prevent mouse commands activating bloody `transient-mark-mode'."
(if (eq transient-mark-mode 'only)
(setq transient-mark-mode nil)))
(if (boundp 'mouse-1-click-follows-link)
(setq mouse-1-click-follows-link nil))
(setq large-file-warning-threshold (* 20 1024 1024))
TODO(when (string-match "^\\(xray\\|slac\\)$" my-system)
(setq undo-limit 40000
undo-strong-limit (floor (* 1.5 undo-limit)))
(if (boundp 'undo-outer-limit) (setq undo-outer-limit 400000)))
(setq special-display-buffer-names '("*info*")
special-display-regexps '(".*-diff\\*" "\\*Man .*\\*")
special-display-frame-alist
`((unsplittable . nil)
,(cons 'height (frame-height)))
same-window-buffer-names (delete "*info*" same-window-buffer-names))
(mapcar (lambda (e) (if (string-match "\\\\*info\\\\*" e)
(setq same-window-regexps
(delete e same-window-regexps))))
same-window-regexps)
(mapcar (lambda (pair) (if (boundp (car pair))
(set (car pair) (cdr pair))))
'((mode-line-in-non-selected-windows . t)
(default-indicate-buffer-boundaries . 'left)
(overflow-newline-into-fringe . t)))
(when (boundp 'show-trailing-whitespace)
(define-minor-mode show-trailing-whitespace
"Toggle display of trailing whitespace.
With optional numeric argument ARG, activate trailing whitespace display if
ARG is positive, otherwise deactivate it."
:init-value nil
:lighter " WS")
(defun my-show-trailing-whitespace ()
"Activate `show-trailing-whitespace' mode."
(show-trailing-whitespace 1))
(mapcar (lambda (hook) (add-hook hook 'my-show-trailing-whitespace))
'(sh-mode-hook emacs-lisp-mode-hook f90-mode-hook
fortran-mode-hook awk-mode-hook
change-log-mode-hook c-mode-hook
tcl-mode-hook)))
(setq bookmark-default-file (expand-file-name "bookmarks" my-emacsdir))
(setq save-place-file (expand-file-name "places" my-emacsdir))
(when (and (not (equal my-emacs-type 'mail))
(require 'saveplace nil t))
(setq-default save-place t)
(setq save-place-limit 200
save-place-version-control 'never))
(let (func arg)
(mapcar (lambda (elem)
(setq func (car elem)
arg (cdr elem))
(and (fboundp func) (funcall func arg)))
'((tool-bar-mode . -1)
(blink-cursor-mode . -1)
(reveal-mode . 1)
(file-name-shadow-mode . 1)
(minibuffer-electric-default-mode . 1)
(size-indication-mode . 1)
(auto-image-file-mode . 1)
(auto-compression-mode . 1))))
TODO(when (boundp 'jka-compr-compression-info-list)
(add-to-list 'jka-compr-compression-info-list
'["\\.ASZ\\'" "zipping" "gzip" ("-c" "-q")
"unzipping" "gzip" ("-c" "-q" "-d") t t "\037\213"])
(require 'jka-compr)
(jka-compr-uninstall)
(jka-compr-install))
TODO(add-hook 'after-revert-hook
(lambda () (when (bound-and-true-p auto-revert-mode)
(goto-char (point-max)))))
(setq apropos-sort-by-scores t)
(setq tooltip-delay 0.5
tooltip-short-delay 0.1
tooltip-recent-second 1
tooltip-hide-delay 5)
(when (featurep 'tooltip)
(if (boundp 'tooltip-gud-tips-p) (setq tooltip-gud-tips-p t))
(if (fboundp 'tooltip-gud-tips-setup) (tooltip-gud-tips-setup)))
(defun my-face-set (face props)
"If FACE is a face, set its properties to PROPS."
(when (facep face)
(face-spec-set face props)))
(my-face-set 'tooltip
'((t (:foreground "black" :inherit default
:background "light goldenrod yellow"))))
(when (fboundp 'propertize)
(defface display-time-mail-face '((t (:background "cornflower blue")))
"If display-time-use-mail-icon is non-nil, its background colour is that
of this face. Should be distinct from mode-line. Note that this does not seem
to affect display-time-mail-string as claimed.")
(setq
display-time-day-and-date t
display-time-24hr-format t
display-time-interval 10
display-time-mail-file (expand-file-name my-user "/var/spool/mail/")
display-time-use-mail-icon t
display-time-mail-face 'display-time-mail-face
display-time-mail-icon
(let ((file (expand-file-name "images/letter.xpm" my-emacsdir)))
(if (file-exists-p file)
`(image :type xpm
:file ,file
:ascent center
:color-symbols
(list
(cons "BG" (face-attribute
'display-time-mail-face :background))))))
my-display-time-icon
(let ((file (expand-file-name "images/clock.xpm" my-emacsdir)))
(if (file-exists-p file)
`(image :type xpm
:file ,file
:ascent center)))
display-time-string-forms
`(
(propertize "*"
'display
(if (and my-display-time-icon (display-graphic-p))
(append
my-display-time-icon
(list
:color-symbols
(list
(cons "FG" "slate grey")))))
'help-echo (format-time-string "%H:%M, %A %B %e %Y"))
(if mail
(concat " "
(propertize
"MAIL"
'display
(and display-time-use-mail-icon (display-graphic-p)
display-time-mail-icon)
'help-echo "mouse-2: read mail"
'local-map
(make-mode-line-mouse-map 'mouse-2 read-mail-command)))
"")))
(put 'working-mode-line-message 'risky-local-variable t)
(display-time-mode 1))
TODO(defvar my-display-mail-file (getenv "MAIL")
"File to be monitored by `my-display-mail' functions.")
(defvar my-display-mail-interval 10
"Interval in seconds between checks of `my-display-mail-file' status.")
(setq my-display-mail-file (expand-file-name my-user "/var/spool/mail/")
my-display-mail-interval 10)
(defun my-display-mail-file-nonempty-p (file)
"Return non-nil if FILE has size > 0."
(and (file-exists-p file)
(< 0 (nth 7 (file-attributes (file-chase-links file))))))
(defun my-display-mail-popup ()
"Display a popup the first time mail arrives."
(if (my-display-mail-file-nonempty-p my-display-mail-file) (when (not my-display-mail-new-p) (setq my-display-mail-new-p t)
(if (x-popup-dialog t
'(" New Mail! "
("OK" . nil) ("Off" . t)))
(my-display-mail-deactivate)))
(setq my-display-mail-new-p nil)))
(defun my-display-mail-activate ()
"Activate the popup mail display."
(interactive)
(my-display-mail-deactivate)
(setq my-display-mail-new-p nil
my-display-mail-timer
(run-at-time 60 my-display-mail-interval 'my-display-mail-popup)))
(defun my-display-mail-deactivate ()
"Deactivate the popup mail display."
(interactive)
(and (boundp 'my-display-mail-timer) (timerp my-display-mail-timer)
(cancel-timer my-display-mail-timer)))
(and window-system
(not (equal my-emacs-type 'secondary))
(string-equal my-system "xray")
(> (length (getenv "DISPLAY")) 4)
(my-display-mail-activate))
(setq time-stamp-active t
time-stamp-warn-inactive t
time-stamp-format "%3a %02d-%3b-%:y %02H:%02M:%02S %u on %s")
(unless (equal my-emacs-type 'mail)
(add-hook (if (boundp 'before-save-hook) 'before-save-hook
'write-file-hooks) 'time-stamp))
(when (and (not (equal my-emacs-type 'mail))
(require 'help-fns nil t))
(if (fboundp 'help-default-arg-highlight)
(fset 'help-default-arg-highlight '(lambda (arg) arg)))
(defface help-highlight-face
'((t (:underline t)))
"Face used by `help-make-xrefs' to highlight cross-references.
Default is underline. Don't make it too gaudy!")
(setq help-highlight-face 'help-highlight-face))
(defface occur-match-face
'((t (:foreground "pink" :weight bold)))
"Face used by `occur' to highlight matching regexps.
See variable `list-matching-lines-face' (default bold).")
(defface occur-buffer-name-face
'((t (:foreground "yellow")))
"Face used by `occur' to highlight buffer name.
See variable `list-matching-lines-buffer-name-face' (default underline).")
(setq list-matching-lines-face 'occur-match-face
list-matching-lines-buffer-name-face 'occur-buffer-name-face)
(my-face-set 'completions-first-difference
'((t (:foreground "cyan" :weight bold))))
(my-face-set 'completions-common-part
'((t (:foreground "grey" :weight normal))))
(my-face-set 'minibuffer-prompt '((t (:foreground "cyan"))))
(defmacro my-make-hook-fn (hook &rest body)
"Add a function to HOOK, with body BODY."
(if (fboundp 'declare) (declare (indent 1)))
(let ((fn (intern (format "my-%s-fn" hook))))
`(progn
(defun ,fn ()
,(format "Function added to `%s'." hook)
,@body)
(add-hook ',hook ',fn))))
(my-make-hook-fn Info-mode-hook
(my-face-set 'info-node '((t (:foreground "white" :weight bold))))
(my-face-set 'info-xref-visited
'((t (:foreground "violet" :weight normal :underline nil))))
(my-face-set 'info-xref '((t (:foreground "cyan" :weight normal
:underline nil)))))
(when window-system
(if (facep 'mode-line)
(set-face-attribute 'mode-line nil :foreground "DarkSlateGrey" :background "Wheat"))
TODO (my-face-set 'mode-line-highlight
'((t :background "light sky blue" :foreground "black")))
(when (facep 'fringe)
(cond ((equal my-emacs-type 'mail)
(set-face-attribute 'fringe nil
:foreground "lawngreen"
:background "SeaGreen4"))
((equal my-emacs-type 'secondary)
(set-face-attribute 'fringe nil
:foreground "lawngreen"
:background "slategrey"))
(t
(set-face-attribute 'fringe nil
:foreground "lawngreen"
:background "SteelBlue4"))))
(if (facep 'tool-bar) (set-face-background 'tool-bar "DarkSlateGrey"))
(if (facep 'trailing-whitespace)
(set-face-background 'trailing-whitespace "SeaGreen1"))
(my-face-set 'minibuffer-prompt '((t (:foreground "cyan"))))
(my-face-set 'escape-glyph '((t (:foreground "cyan" :weight bold))))
(when (fboundp 'set-face-attribute)
(face-spec-set 'italic
'((t (:slant italic :underline nil :family "helvetica"))))
(face-spec-set 'bold-italic
'((t (:slant italic :underline nil
:weight bold :family "helvetica"))))))
(my-make-hook-fn custom-mode-hook
(when window-system
(my-face-set 'custom-button-face
'((t (:box (:line-width 2 :style released-button)
:foreground "wheat" :background "DarkSlateGrey"))))
(my-face-set 'custom-button-pressed-face
'((t (:box (:line-width 2 :style pressed-button)
:foreground "wheat" :background "DarkSlateGrey"
))))))
(eval-after-load "font-lock"
'(progn
(face-spec-set 'font-lock-builtin-face
'((t (:foreground "LightSteelBlue"))))
(face-spec-set 'font-lock-comment-face
'((t (:foreground "OrangeRed"))))
(face-spec-set 'font-lock-constant-face
'((t (:foreground "Aquamarine"))))
(face-spec-set 'font-lock-function-name-face
'((t (:foreground "LightSkyBlue" :weight bold))))
(face-spec-set 'font-lock-keyword-face
'((t (:foreground "Cyan"))))
(face-spec-set 'font-lock-string-face
'((t (:foreground "LightSalmon")))) (face-spec-set 'font-lock-type-face
'((t (:foreground "PaleGreen" ))))
(face-spec-set 'font-lock-variable-name-face
'((t (:foreground "LightGoldenrod" :weight bold))))
(face-spec-set 'font-lock-warning-face
'((t (:foreground "pink" :weight bold))))
(my-face-set 'font-lock-regexp-backslash
'((t :foreground "sienna")))
(my-face-set 'font-lock-regexp-backslash-construct
'((t :inherit 'bold)))))
(set-face-background 'highlight "Blue")
(let (ext mode)
(mapcar (lambda (elem)
(when elem
(setq ext (regexp-quote (car elem))
mode (cdr elem))
(add-to-list 'auto-mode-alist `(,(concat ext "\\'") . ,mode))))
`((".awk" . awk-mode)
(".bash" . shell-script-mode)
(".tcsh" . shell-script-mode)
("README" . text-mode)
(".notes" . text-mode)
(".texinfo" . texinfo-mode)
(".cps" . ps-mode)
,(if (string-equal my-system "cass") '(".html" . html-mode)))))
(let (dir flag default-directory)
(mapcar (lambda (elem)
(setq dir (car elem)
flag (cdr elem)
default-directory dir)
(when (and dir (file-directory-p dir))
(add-to-list 'load-path dir)
(and flag
(fboundp 'normal-top-level-add-subdirs-to-load-path)
(normal-top-level-add-subdirs-to-load-path))))
`(
,(if (string-match "^\\(cass\\|kdell\\)$" my-system)
'("/usr/local/share/emacs/site-lisp" . t))
("/usr/share/emacs/site-lisp" . t)
("/usr/share/emacs21/site-lisp" . t)
(,my-sitelisp . t)
(,(expand-file-name "~/elisp") . ,(< emacs-major-version 21)))))
(when (locate-library "debian-startup")
(load-library "debian-startup")
(debian-startup 'emacs21))
(if (boundp 'tags-table-list)
(mapcar (lambda (dir)
(and (file-directory-p dir)
(file-exists-p (expand-file-name "TAGS" dir))
(add-to-list 'tags-table-list dir)))
(list (expand-file-name "lisp" source-directory)
(expand-file-name "lwlib" source-directory) (expand-file-name "src" source-directory) my-sitelisp
(expand-file-name "../" doc-directory))))
(put 'narrow-to-region 'disabled nil) (put 'narrow-to-page 'disabled nil) (put 'narrow-to-defun 'disabled nil)
(put 'downcase-region 'disabled nil)
(put 'upcase-region 'disabled nil)
(put 'rmail 'disabled t)
(unless (equal my-emacs-type 'mail)
(put 'gnus 'disabled t))
(defadvice find-file (around confirm-new-file activate)
"If file does not exist, prompt."
(let ((file (ad-get-arg 0)))
(if (or (not (interactive-p))
(find-buffer-visiting file)
(string-match "\\`/\\(\\[\\|[[:alnum:]]+@?:\\)" file)
(file-directory-p file)
(file-expand-wildcards file)
(yes-or-no-p
(format "`%s' does not exist, create buffer? " file)))
ad-do-it)))
(defadvice switch-to-buffer (around confirm-new-buffer activate)
"If buffer does not exist, prompt."
(let ((buff (ad-get-arg 0)))
(if (or (not (interactive-p))
(get-buffer buff)
(yes-or-no-p
(format "Buffer `%s' does not exist, create? " buff)))
ad-do-it)))
(defvar my-before-kill-emacs-hook nil
"Hook to run before `save-buffers-kill-emacs'.")
(defadvice save-buffers-kill-emacs (around before-kill-hook activate)
"Run `my-before-kill-emacs-hook' before save-buffers-kill-emacs."
(when (yes-or-no-p "Really exit Emacs? ")
(run-hooks 'my-before-kill-emacs-hook)
(setq confirm-kill-emacs nil) ad-do-it))
(defun my-process-running (name)
"Return non-nil if a process called NAME is running under current user."
(string-match (format "[ \t]%s$" (regexp-quote name))
(shell-command-to-string
(format "ps -u %s" (user-uid)))))
(defun my-get-track (&optional stat)
"Call the appropriate my-player-get-track function."
(interactive "P")
(cond ((my-process-running "orpheus")
(my-orpheus-get-track))
((my-process-running "gqmpeg")
(my-gqmpeg-get-track stat))
((my-process-running "xmms")
(my-xmms-get-track stat))
((string-equal my-system "slac")
(let ((h (my-get-remote-host)))
(and h
(string-equal h "171.64.56.172")
(my-get-remote-track))))))
(defun my-get-remote-host ()
"Try to get the IP address of the remote ssh host."
(let ((str (getenv "SSH_CLIENT")))
(when str
(string-match "^\\([0-9.]+\\)" str)
(match-string 1 str))))
(defun my-get-remote-track (&optional host)
"Use music-playing.bash script on HOST to get current track.
With no HOST, use `my-get-remote-host'."
(interactive (list (read-from-minibuffer "Enter host name: ")))
(when
(if host
(zerop (shell-command (format "/bin/ping -c1 %s" host))) (setq host (my-get-remote-host)))
TODO (with-temp-buffer
(insert
(shell-command-to-string
(format "ssh %s 'PATH=~/bin:$PATH; bin/music-playing -p'" host)))
(goto-char (point-min))
(let ((artist "?")
(track "?")
(player "?")
result)
(if (re-search-forward "^Track :[ \t]*\\(.*\\)" (point-max) t)
(setq track (match-string 1)))
(if (re-search-forward "^Artist:[ \t]*\\(.*\\)" (point-max) t)
(setq artist (match-string 1)))
(if (re-search-forward "^Player:[ \t]*\\(.*\\)" (point-max) t)
(setq player (match-string 1)))
(unless (string-equal track "silence")
(setq result (format "%s - %s" artist track)))
(if (interactive-p) (message "%s" result)
result)))))
(defun my-xmms-get-track (&optional stat)
"Return as a string the current xmms track, or nil if no track.
With optional STAT, append the track status."
(interactive "P")
(let ((file "/tmp/xmms-info")
track status result)
(when (and (file-exists-p file)
(my-process-running "xmms"))
(with-temp-buffer
(insert (shell-command-to-string (format "cat %s " file)))
(goto-char (point-min))
(when stat
(re-search-forward "^Status:[ \t]*\\(.*\\)" (point-max) t)
(setq status (downcase (or (match-string 1) "?"))))
(re-search-forward "^Title:[ \t]*\\(.*\\)" (point-max) t)
(setq track (or (match-string 1) "?")
result (if stat
(format "%s (%s)" track status)
(format "%s" track)))))
(if (interactive-p) (message "%s" result)
result)))
(defun my-gqmpeg-get-track (&optional stat)
"Return as a string the current gqmpeg track, or nil if no track.
With optional argument STAT, append the track status."
(interactive "P")
(let ((artist "?")
(track "?")
status result)
(when (and (executable-find "gqmpeg")
(my-process-running "gqmpeg"))
(with-temp-buffer
(shell-command "gqmpeg --status" t)
(goto-char (point-min))
(setq result (re-search-forward
"\\(process not active\\|retrieval failed\\)"
(point-max) t))
(if (re-search-forward "^name:\"\\(.*\\)\"" (point-max) t)
(setq track (match-string 1)))
(if (re-search-forward "^artist:\"\\(.*\\)\"" (point-max) t)
(setq artist (match-string 1)))
(when (and stat
(re-search-forward "^time: \\([a-z]+\\)" (point-max) t))
(setq status (match-string 1)
status (cond
((string-equal "play" status) "playing")
((string-equal "stop" status) "stopped")
((string-equal "pause" status) "paused")
(t "?"))))
(setq result (if result nil
(if stat
(format "%s - %s (%s)" artist track status)
(format "%s - %s" artist track))))))
(if (interactive-p) (message "%s" result)
result)))
(defun my-orpheus-get-track ()
"Return as a string the current orpheus track, or nil if no track."
(interactive)
(let ((file "~/.orpheus/currently_playing")
(artist "?")
(track "?")
(result "?"))
(when (and (file-exists-p file)
(my-process-running "orpheus"))
(with-temp-buffer
(insert-file-contents file)
(goto-char (point-min))
(if (or (looking-at "\\([^:]+\\): \\(.*\\)")
(looking-at "\\(.*\\) - \\(.*\\)"))
(setq artist (match-string 1)
track (match-string 2)
result (format "%s - %s" artist track))
(setq result (buffer-substring (point-min) (point-max)))))
(if (interactive-p) (message "%s" result)
result))))
(defun my-mail-obfuscate-address (user fake)
"Supply with USER and address FAKE in the form \"falsename@truedomain\".
Returns the true address \"user@truedomain\".
A little paranoia to protect email addresses from harvesting,
if they are needed in Lisp code that may be distributed on-line."
(string-match "^\\(\\w+\\)@" fake)
(replace-match user t nil fake 1))
(find-function-setup-keys)
(defvar my-defun-re
(regexp-opt '("defun" "defsubst" "defmacro" "defadvice") 'paren)
"Regular expression used to identify a defun.")
(defun my-jump-to-defun (func)
"Jump to the definition of function FUNC in the current buffer, if found.
Return the position of the defun, or nil if not found."
(interactive
NB ? (let ((fn (function-called-at-point)))
(list (completing-read (if fn
(format "Find defun for (default %s): " fn)
"Find defun for: ")
obarray 'fboundp t nil nil (symbol-name fn)))))
(let (place)
(save-excursion
(goto-char (point-min))
(if (re-search-forward
(concat "^[ \t]*(" my-defun-re "[ \t]+"
(regexp-quote func) "[ \t]+") (point-max) t)
(setq place (point))))
(if (not place)
(if (interactive-p) (message "No defun found for `%s'" func))
(when (interactive-p)
(push-mark)
(goto-char place)
(message "Found defun for `%s'" func))
place)))
(defun my-ps-toggle-landscape ()
"Toggle the value of ps-landscape-mode, or set to nil if not bound."
(interactive)
(if (not (boundp 'ps-landscape-mode))
(setq ps-landscape-mode nil)
(setq ps-landscape-mode (not ps-landscape-mode))))
(defun my-copy-line-as-kill ()
"Copy-as-kill from point to end-of-line."
(interactive)
(copy-region-as-kill (point) (line-end-position))
(message "Copied from point to end of line"))
(defun my-stamp (&optional arg)
"Insert current date, user, and system information.
With optional argument ARG, use \"*Creation: -- *\" format."
(interactive "*P")
(let ((string (format "<%s %s on %s>"
(format-time-string "%a %d-%b-%Y %T")
user-login-name
system-name)))
(if arg (setq string (format "*Creation: %s*" string)))
(if (interactive-p)
(insert string)
string)))
TODO(defun my-filestamp (&optional time)
"Insert the <filename> ... <filename ends here> boilerplate.
With optional prefix arg TIME, insert timestamp info as well."
(interactive "*P")
(save-excursion
(let* ((comment-start (or comment-start "#"))
(name (file-name-nondirectory buffer-file-name))
(c (string-to-char comment-start))
(cc (if (eq major-mode 'c-mode)
(replace-regexp-in-string " +$" "" comment-start)
(make-string 3 c)))
(string (format "%s %s" cc name))
oldname)
(goto-char (point-max))
(if (re-search-backward (format "^%s \\(.*\\) ends here"
(regexp-quote cc))
(line-beginning-position -5) t)
(unless (string-equal (setq oldname (match-string 1)) name)
(replace-match name nil nil nil 1))
(insert "\n\n" string " ends here" comment-end "\n"))
(goto-char (point-min))
(if (looking-at (format "^\\(#!\\|\\(%s\\)*[ \t]*-\\*- \\)"
(replace-regexp-in-string "[ \t]*$" ""
comment-start)))
(forward-line 1))
(save-excursion
(and oldname
(re-search-forward (format "%s \\(%s\\)" cc oldname) nil t)
(replace-match name nil nil nil 1)))
(unless (looking-at (regexp-quote string))
TODO (if (eq major-mode 'c-mode) (setq cc " *"))
(insert string "\n"
(if time
(concat cc "\n"
cc " "
(if (or vc-mode
(file-directory-p "CVS"))
(concat "*$I" "d$*")
(my-timestamp)) "\n"
cc " " (my-stamp t) "\n")
"") cc "\n")))))
(defun my-timestamp ()
"Insert the \"Time-stamp: <>\" string at point."
(interactive)
(if (interactive-p) (insert "*Time-stamp: <>*")
"*Time-stamp: <>*"))
TODO(defun my-random-colour (&optional arg)
"Return a random colour as a (lower-case) string.
Excludes colours that end in numbers. With optional prefix arg, insert
colour into buffer at point as a Status: header."
(interactive "P")
(if arg (barf-if-buffer-read-only))
(let* ((cols (defined-colors))
(ncols (length cols))
col)
(if cols
(while (or (not col) (string-match "[0-9]$" col))
(setq col (nth (random ncols) cols)))
(setq col "black"))
(setq col (downcase col))
(if arg
(save-excursion
(if (progn (goto-char (line-beginning-position))
(looking-at ".*Status: \\(.*\\)$"))
(if (string-equal col (match-string 1))
(my-random-colour arg)
(replace-match col nil nil nil 1))
(insert "Status: " col "\n")))
(if (interactive-p) (message "%s" col)
col))))
(defun my-random-string (&optional n)
"Return a string of random characters of length N (default 10)."
(let ((x ""))
(dotimes (i (or n 10) x)
(setq x (format "%s%c" x (+ 33 (random 94)))))))
(defun my-print-chars ()
"Print the character codes and their characters in a buffer."
(interactive)
(let ((buff (generate-new-buffer "*chars*")))
(with-current-buffer buff
(dotimes (i 128)
(insert (format "%d %c\n" i i)))
(set-buffer-modified-p nil))
(display-buffer buff)))
TODO(defadvice kill-buffer (around buffer-offer-save activate)
"Confirm kill if `buffer-offer-save' is non-nil."
(let ((buff (or (ad-get-arg 0) (current-buffer))))
(when (or (not (interactive-p))
(not (buffer-modified-p))
(not (with-current-buffer buff
buffer-offer-save))
(yes-or-no-p (format "Really kill buffer `%s'? " buff)))
ad-do-it)))
(defun my-scratch-setup (&optional sbuff)
"Set some properties of the \"*scratch*\" buffer.
With optional buffer name SBUFF, use that instead of \"*scratch*\"."
(or sbuff (setq sbuff "*scratch*"))
(when (get-buffer sbuff)
(with-current-buffer sbuff
(funcall initial-major-mode)
(let ((default-directory my-backupdir))
(auto-save-mode 1))
(setq buffer-offer-save t
show-trailing-whitespace nil))))
(defun my-scratch (&optional arg)
"(Make and) goto scratch buffer.
With optional prefix argument ARG, run `my-scratch-setup' (normally only
run if buffer is created)."
(interactive "P")
(let* ((buff "*scratch*")
(exists (get-buffer buff)))
(switch-to-buffer (get-buffer-create buff))
(if (or arg (not exists))
(my-scratch-setup buff))))
(defun my-scratch-offer-save ()
"Offer to save the scratch buffer.
Also, delete the scratch auto-save file if it exists, so not left with
a scratch auto-save file after every Emacs instance.
Intended for use with `my-before-kill-emacs-hook'."
(let ((buff "*scratch*")
file)
(when (get-buffer buff)
(with-current-buffer buff
(when buffer-offer-save
(save-some-buffers nil
(lambda () (string-equal (buffer-name) buff)))
(setq buffer-offer-save nil))
(and (setq file buffer-auto-save-file-name)
(file-exists-p file)
(delete-file file))
(setq buffer-auto-save-file-name nil)))))
(unless (equal my-emacs-type 'mail)
(add-hook 'after-init-hook 'my-scratch-setup)
(add-hook 'my-before-kill-emacs-hook 'my-scratch-offer-save))
TODO(defvar my-scratch-auto-save-directory
(if (file-directory-p my-backupdir)
my-backupdir
"~")
"Directory used by `my-scratch-auto-save'.")
(defvar my-scratch-auto-save-interval 120
"Interval in seconds before scratch buffer is auto-saved.")
(defvar my-scratch-auto-save-timer nil
"Timer for `my-scratch-auto-save-mode'.")
(defun my-scratch-auto-save ()
"Auto-save the scratch buffer to `my-scratch-auto-save-directory'."
(let ((buff "*scratch*")
(dir my-scratch-auto-save-directory)
(file (format "scratch-%s-%s" (format-time-string "%Y_%m_%d")
(emacs-pid)))
(str "Saving scratch..."))
(when (get-buffer buff)
(or (file-directory-p dir)
(error "Directory `%s' does not exist" dir))
(mapc (lambda (file) (delete-file file))
(file-expand-wildcards (expand-file-name
(format "scratch-*-%s" (emacs-pid))
dir)))
(with-current-buffer buff
(save-restriction
(widen)
(unless (zerop (buffer-size))
(write-region (point-min) (point-max)
(expand-file-name file dir) nil 'shutup))))
)))
(define-minor-mode my-scratch-auto-save-mode
"Toggle periodic saving of the scratch buffer.
With optional numeric argument ARG, activate saving only if ARG
is positive."
:global t
(if my-scratch-auto-save-mode
(or my-scratch-auto-save-timer (setq my-scratch-auto-save-timer
(run-with-timer my-scratch-auto-save-interval
my-scratch-auto-save-interval
'my-scratch-auto-save)))
(if (timerp my-scratch-auto-save-timer)
(cancel-timer my-scratch-auto-save-timer))))
(or (equal my-emacs-type 'mail)
(my-scratch-auto-save-mode 1))
(defun my-messages ()
"Switch to the `*Messages*' buffer."
(interactive)
(switch-to-buffer "*Messages*"))
(defun my-delete-trailing-whitespace ()
"Delete all trailing whitespace in buffer.
Return values are suitable for use with `write-file-functions'."
(condition-case nil
(progn
(when (memq major-mode '(text-mode sh-mode emacs-lisp-mode
f90-mode awk-mode c-mode))
(message "Cleaning up whitespace...")
(delete-trailing-whitespace)
(message "Cleaning up whitespace...done")
nil))
(error (message "Cleaning up whitespace...ERROR")
t)))
(defun my-comment-region (start end)
"Just like `comment-region', but uses 3 comment characters."
(interactive "*r")
(comment-region start end (or (eq major-mode 'c-mode) 3)))
(defun my-comment-indent-region (start end)
"Indent all the trailing comments in the region.
No new comments will be inserted."
(interactive "*r")
(or comment-start (error "No comment syntax defined"))
(let ((cstart (regexp-quote (substring
comment-start 0
(string-match "[ \t]+$" comment-start)))))
(save-excursion
(save-restriction
(narrow-to-region start end)
(goto-char (point-min))
(while (not (eobp))
(skip-chars-forward " \t")
(or (looking-at cstart) (and (re-search-forward cstart (line-end-position) t)
(comment-indent))) (forward-line 1))))))
(defun my-get-image-size (file &optional pixels)
"Get the size of the specified image file. Values rounded UP to integers.
With optional argument `pixels', return values in pixels.
Output is (width height)."
(interactive (list (read-file-name "Enter file name: " nil nil t)))
(if (file-exists-p file) (let* ((fullname (expand-file-name file))
(img-type (image-type-from-file-header fullname))
(img (create-image fullname))
(img-size (and img (image-size img pixels)))
(img-width (car img-size))
(img-height (cdr img-size)))
(or (memq img-type image-types)
(error "File %s is not of a recognized image type" file))
(or pixels
(setq img-width (round (+ img-width 0.5))
img-height (round (+ img-height 0.5))))
(if (interactive-p)
(message "Width: %s, Height: %s" img-width img-height)
(list img-width img-height)))
(error "File %s not found" file)))
(defun my-longest-line (&optional goto)
"Find visual length (ie in columns) of longest line in buffer.
If optional argument GOTO is non-nil, go to that line."
(interactive "p") NB (let ((maxlen 0)
(line 1)
len maxline)
(save-excursion
(goto-char (point-min))
(goto-char (line-end-position))
(setq len (current-column))
(if (eobp) (setq maxlen len
maxline line)
(while (zerop (forward-line))
(goto-char (line-end-position))
(setq line (1+ line)
len (current-column))
(if (> len maxlen)
(setq maxlen len
maxline line)))))
(if (not (interactive-p))
maxlen
(message "Longest line is line %s (%s)" maxline maxlen)
(if goto (goto-line maxline)))))
(defvar my-frame-parameters nil
"Internal variable used by `my-frame-height'.")
(make-variable-buffer-local 'my-frame-parameters)
(defun my-resize-frame (&optional prefix)
"Increase width of current frame to length of the longest line,
if necessary and possible within the size of the display.
If called again, restore the original width.
If called with a prefix, restore frame size to default.
If called in a frame displaying an image, adjust width AND height as
per that of the image."
(interactive "P")
(let ((frame (selected-frame)))
(if prefix (progn
(set-frame-width frame (cdr (assoc 'width default-frame-alist)))
(set-frame-height frame
(1- (cdr (assoc 'height default-frame-alist))))
(setq my-frame-parameters nil)) (if my-frame-parameters (progn
(set-frame-width frame (cdr (assoc 'width my-frame-parameters)))
(set-frame-height frame (cdr (assoc 'height my-frame-parameters)))
(set-frame-position frame (cdr (assoc 'left my-frame-parameters))
(frame-parameter nil 'top))
(setq my-frame-parameters nil)) (setq my-frame-parameters `((height . ,(frame-height))
(width . ,(frame-width))
(left . ,(frame-parameter frame 'left))))
(let* ((pix-col (/ (frame-pixel-width) 1.0 (frame-width)))
(maxpix (display-pixel-width))
(maxcols (truncate (/ maxpix pix-col)))
(maxrows (truncate
(/ (display-pixel-height)
(/ (frame-pixel-height) 1.0 (frame-height)))))
(new-width (my-longest-line))
(old-height (cdr (assoc 'height my-frame-parameters)))
(new-height old-height)
(old-width (cdr (assoc 'width my-frame-parameters)))
new-left templist)
(and auto-image-file-mode
(string-match (image-file-name-regexp)
(or (buffer-file-name) "dummy"))
(setq templist (my-get-image-size (buffer-file-name))
new-width (car templist)
new-height (min maxrows (cadr templist))))
(setq new-width (1+ (min maxcols new-width))
new-left (max 0 (truncate (- maxpix (* new-width pix-col) 60))))
(when (> new-width old-width)
(set-frame-width frame new-width)
(if (< new-left (cdr (assoc 'left (frame-parameters))))
(set-frame-position frame new-left
(frame-parameter frame 'top))))
(if (> new-height old-height)
(set-frame-height frame new-height)))))))
TODO(defun my-maximize-frame ()
"Maximize the current frame."
(interactive)
(let ((maxcols (truncate
(/ (display-pixel-width)
(/ (frame-pixel-width) 1.0 (frame-width)))))
(maxrows (truncate
(/ (display-pixel-height)
(/ (frame-pixel-height) 1.0 (frame-height)))))
(frame (selected-frame)))
(set-frame-size frame maxcols maxrows)
(set-frame-position frame 0 0)))
(defun my-justify-region (margin start end)
"Justify a region of text.
With optional prefix argument MARGIN, first re-fill to that column."
(interactive "*p\nr")
(let ((fill-column (or margin fill-column)))
(save-excursion
(save-restriction
(narrow-to-region
(progn (goto-char start) (line-beginning-position))
(progn (goto-char end) (line-end-position)))
(goto-char (point-min))
(while (not (eobp))
(if margin (my-refill-paragraph ()))
(forward-paragraph 1)
(previous-line 1) (let ((parend (point)))
(backward-paragraph 1) (while (< (point) parend) (justify-current-line nil)
(forward-line 1)))
(justify-current-line nil t) (forward-line 1))))))
(defun my-count-words-region (start end)
"Count the number of words in the region."
(interactive "r")
(save-excursion
(save-restriction
(narrow-to-region start end)
(goto-char (point-min))
(let ((count 0))
(while (forward-word 1)
(setq count (1+ count)))
(if (interactive-p) (message "Region contains %d words." count)
count)))))
(defun my-unindent-line ()
"Delete indentation of current line."
(interactive)
(save-excursion
(forward-line 0)
(delete-horizontal-space)))
(defun my-unindent-region (start end)
"Delete indentation of current region."
(interactive "*r")
(save-excursion
(save-restriction
(narrow-to-region
(progn (goto-char start) (line-beginning-position))
(progn (goto-char end) (line-end-position)))
(goto-char (point-min))
(while (not (eobp))
(my-unindent-line)
(forward-line 1)))))
(defun my-listtostring (list)
"Converts a list of strings into single string."
(mapconcat 'identity list ""))
(defun my-refill-paragraph (arg)
"Fill current paragraph"
(interactive "*P")
(let (beg end)
(forward-paragraph 1)
(setq end (copy-marker (- (point) 2)))
(backward-paragraph 1)
(setq beg (point-marker))
(forward-char)
(while (< (point) end)
(delete-indentation 1)
(end-of-line))
(funcall (if (memq major-mode '(c-mode c++-mode))
'c-fill-paragraph
'fill-paragraph)
(and arg (prefix-numeric-value arg)))
(if (memq major-mode '(c-mode c++-mode))
(c-recomment-region beg (+ end 2)))
(set-marker beg nil)
(set-marker end nil)))
(defun my-unfill-paragraph (arg)
"Unfill current paragraph"
(interactive "*P")
(forward-paragraph 1)
(let ((end (copy-marker (- (point) 2))))
(backward-paragraph 1)
(forward-char)
(while (< (point) end)
(delete-indentation 1)
(end-of-line))
(set-marker end nil)))
(defun my-prepend (start end s &optional append)
"Add a string in front of all lines in the region.
If APPEND is non-nil, add the string to the end of lines."
(interactive "*r\nMEnter a string: ")
(save-excursion
(save-restriction
(narrow-to-region
(progn (goto-char start) (line-beginning-position))
(progn (goto-char end) (line-end-position)))
(goto-char (point-min))
(beginning-of-line)
(while (not (eobp))
(if append (end-of-line))
(insert s)
(forward-line 1)))))
(defun my-unprepend (start end s)
"Remove a regexp from the front of all lines in the region."
(interactive "*r\nMEnter a regexp: ")
(save-excursion
(save-restriction
(narrow-to-region
(progn (goto-char start) (line-beginning-position))
(progn (goto-char end) (line-end-position)))
(goto-char (point-min))
(while (not (eobp))
(if (looking-at s)
(delete-region (match-beginning 0) (match-end 0)))
(forward-line 1)))))
(defun my-append (start end s)
"Append a string to the end of all lines in region"
(interactive "*r\nMEnter a string: ")
(my-prepend start end s t))
(defun my-unappend (start end s)
"Remove string from end of each line in region"
(interactive "*r\nMEnter a string: ")
(save-excursion
(save-restriction
(narrow-to-region
(progn (goto-char start) (line-beginning-position))
(progn (goto-char end) (line-end-position)))
(goto-char (point-min))
(while (not (eobp))
(end-of-line)
(when (> (point) (line-beginning-position)) (backward-char 1) (when (looking-at (substring s -1))
(forward-char 1) (if (search-backward-regexp s (line-beginning-position) t)
(delete-region (match-beginning 0) (match-end 0)))))
(forward-line 1)))))
(defun my-deltw (start end)
"Remove trailing whitespace from all lines in the region."
(interactive "*r")
(save-excursion
(save-restriction
(narrow-to-region start end)
(goto-char (point-min))
(while (re-search-forward "[ \t]+$" nil t)
(delete-horizontal-space) ))))
(defun my-shell-backspace ()
"Backspace in shell-mode that will not delete the command prompt."
(interactive)
(and (> (point) (line-beginning-position)) (delete-backward-char 1)))
(defun my-indent-region (start end)
"Indent all text in region as per tab-key."
(interactive "*r")
(save-excursion
(save-restriction
(narrow-to-region
(progn (goto-char start) (line-beginning-position))
(progn (goto-char end) (line-end-position)))
(goto-char (point-min))
(while (not (eobp))
(indent-for-tab-command)
(forward-line 1)))))
(defun my-indent-relative (start end)
"Indent all lines in region to level of first, using tabs and spaces"
(interactive "*r")
(save-excursion
(save-restriction
(narrow-to-region
(progn (goto-char start) (line-beginning-position))
(progn (goto-char end) (line-end-position)))
(goto-char (point-min))
(let ((col (skip-chars-forward " \t"))) (while (zerop (forward-line 1))
(indent-to col))))))
(my-make-hook-fn minibuffer-exit-hook
(let ((buff "*Completions*"))
(if (get-buffer buff) (kill-buffer buff))))
(setq custom-buffer-done-function 'kill-buffer)
(defun my-member-match (re list)
"Return non-nil if regexp RE matches an element of LIST.
The value is actually the tail of LIST whose car matches RE.
The value of `case-fold-search' is obeyed."
(catch 'found
(mapcar (lambda (elem)
(if (string-match re elem)
(throw 'found (member elem list))))
list)
nil))
(defvar my-clean-buffers-names
'("\\*Completions" "\\*Compile-Log" "\\*.*[Oo]utput\\*$"
"\\*Apropos" "\\*compilation" "\\*Customize" "\\*Calc"
"\\*BBDB\\*" "\\*Occur\\*" "\\*trace of SMTP" "\\*vc" "\\*cvs"
"\\*WoMan-Log" "\\*tramp" "\\*desktop\\*")
"List of regexps matching names of buffers to kill.")
(defvar my-clean-buffers-modes
'(help-mode) "List of modes whose buffers will be killed.")
(defun my-clean-buffers ()
"Kills buffers as per `my-clean-buffer-list' and `my-clean-buffer-modes'."
(interactive)
(let (string buffname)
(mapcar (lambda (buffer)
(and (setq buffname (buffer-name buffer))
(or (catch 'found
(mapcar '(lambda (name)
(if (string-match name buffname)
(throw 'found t)))
my-clean-buffers-names)
nil)
(save-excursion
(set-buffer buffname)
(catch 'found
(mapcar '(lambda (mode)
(if (eq major-mode mode)
(throw 'found t)))
my-clean-buffers-modes)
nil)))
(kill-buffer buffname)
(setq string (concat string
(and string ", ") buffname))))
(buffer-list))
(if string (message "Deleted: %s" string)
(message "No buffers deleted"))))
(defvar my-file-name-history-exclude-re
'("~/VM/.+" "/bbdb$" )
"List of regexps matching files to exclude from `file-name-history'.")
(defun my-file-name-history-prune ()
"Trim the contents of the variable `file-name-history'."
(let (file)
(mapcar (lambda (re)
(while (setq file (my-member-match re file-name-history))
(setq file-name-history
(delete (car file) file-name-history))))
my-file-name-history-exclude-re)))
(defadvice find-file (after prune-history activate)
"Run `my-file-name-history-prune'."
(my-file-name-history-prune))
(defun my-faceset (face fg &optional bg bold)
"Give FACE foreground FG, and optional background BG. Make bold if BOLD,
else make unbold. For example: (my-faceset 'dircolors-face-package \"Red\" t)"
(set-face-foreground face fg)
(if bg
(if (stringp bg) (set-face-background bg) (make-face-bold face)))
(if bold (make-face-bold face) (make-face-unbold face)))
(defun my-file-perm-check (mode atype utype)
"Return non-nil if integer file MODE allows access ATYPE for user UTYPE.
ATYPE is a single character, either r(ead), w(rite), x(ecute);
UTYPE is a single character, either u(ser), g(roup), o(other)."
(let ((case-fold-search t)
(mask))
(cond ((char-equal atype ?r)
(setq mask #o4))
((char-equal atype ?w)
(setq mask #o2))
((char-equal atype ?x)
(setq mask #o1))
(t (error "Bad ATYPE `%c'" atype)))
(cond ((char-equal utype ?u)
(setq mask (* mask (expt 2 6))))
((char-equal utype ?g)
(setq mask (* mask (expt 2 3))))
((char-equal utype ?o))
(t (error "Bad UTYPE `%c'" utype)))
(not (zerop (logand mode mask)))))
(unless window-system
(if (string-equal my-system "slac")
(progn
TODOFIXME (define-key function-key-map "\e[4~" [end])
(if (string-equal system-type "darwin")
(define-key function-key-map "\e[1~" [home])))
(when (string-equal (getenv "TERM") "xterm-color")
(keyboard-translate ?\C-h ?\C-?)
(global-set-key "\C-xh" 'help-command) (global-set-key "\eOH" 'beginning-of-buffer) (global-set-key "\eOF" 'end-of-buffer))))
(global-unset-key "\C-xf")
(global-set-key "\C-hw" 'woman)
(fset 'list-buffers 'buffer-menu)
(global-set-key [(f5)] 'make-frame)
(global-set-key [(control f5)] 'delete-frame)
(global-set-key [(f7)] 'repeat-complex-command)
(global-set-key [(f8)] 'my-resize-frame)
(global-set-key [(f9)] 'my-comment-region)
(global-set-key [(control f9)] 'uncomment-region)
(global-set-key [(f12)] 'revert-buffer)
(global-set-key "\C-ca" 'align)
(global-set-key "\C-cA" 'auto-fill-mode)
(global-set-key "\C-cc" 'my-comment-indent-region)
(global-set-key "\C-cf" 'flyspell-mode)
(global-set-key "\C-cg" 'goto-line)
(global-set-key "\C-ch" 'hscroll-mode)
(global-set-key "\C-ci" 'iso-accents-mode)
(global-set-key "\C-cJ" 'fill-region)
(global-set-key "\C-ck" 'my-copy-line-as-kill)
(global-set-key "\C-cm" 'my-messages)
(if (fboundp 'my-splash) (global-set-key "\C-cq" 'my-splash))
(global-set-key "\C-cr" 'my-indent-relative)
(global-set-key "\C-cs" 'my-scratch)
(if (fboundp 'toggle-truncate-lines)
(global-set-key "\C-ct" 'toggle-truncate-lines))
(global-set-key "\C-cF" 'my-filestamp)
(global-set-key "\C-cT" 'my-timestamp)
(global-set-key "\C-cu" 'my-url-selection)
(global-set-key "\C-cU" 'my-unindent-line)
(global-set-key "\C-cV" 'my-unindent-region)
(global-set-key "\C-cW" 'my-websearch-selection)
(global-set-key [end] 'end-of-buffer) (global-set-key [home] 'beginning-of-buffer) (global-set-key [?\C-^] 'join-line)
(defadvice comment-dwim (around activate-trans-mark disable)
"If point is at the beginning of a line, assume we wanted to call
`comment-region', and activate `transient-mark-mode' so that `comment-dwim'
will do the Right Thing."
(let ((transient-mark-mode (= (line-beginning-position) (point))))
ad-do-it))
(when (boundp 'vc-menu-map)
(add-to-list 'minor-mode-map-alist
`(vc-mode keymap
(menu-bar keymap
(VC menu-item "VC" ,vc-menu-map))))
(when (boundp 'cvs-global-menu)
(define-key-after vc-menu-map [pcl-cvs-sep] '("--"))
(mapc (lambda (e) (if (listp e)
(define-key-after vc-menu-map `[,(car e)]
(cdr e))))
(cdr cvs-global-menu))))
(defun my-menu-bar-find-file (file doc help)
"Make a menu-item to visit a file read-only.
FILE is the file to visit, relative to `data-directory'.
DOC is the text to use the menu entry.
HELP is the text to use for the tooltip."
`(menu-item ,doc
(lambda () (interactive)
(find-file-read-only
(expand-file-name ,file data-directory)))
:help ,help))
(let ((last 'emacs-problems) file doc this)
(mapcar (lambda (elem)
(setq file (car elem)
doc (cdr elem)
NB this (intern (concat "emacs-" (downcase file))))
(define-key-after menu-bar-help-menu `[,this]
(my-menu-bar-find-file file doc doc)
last)
(setq last this))
'(("TODO" . "Emacs TODO List")
("DEBUG" . "Emacs Debugging Information")
("JOKES" . "Emacs Jokes")
("future-bug" . "Emacs Future Bug"))))
(defmacro my-menu-bar-make-local-mm-toggle (fname doc help &optional props)
"Make a menu-item for a local minor mode toggle.
FNAME is the minor mode's name (variable and function).
DOC is the text to use the menu entry.
HELP is the text to use for the tooltip.
PROPS are additional properties."
`'(menu-item ,doc ,fname
,@(if props props)
:help ,help
:button (:toggle . (and (boundp ',fname)
,fname))))
(or (fboundp 'menu-bar-make-mm-toggle) (defmacro menu-bar-make-mm-toggle (fname doc help &optional props) ""
`'(menu-item ,doc ,fname
,@(if props props)
:help ,help
:button (:toggle . (and (default-boundp ',fname)
(default-value ',fname))))))
(when (boundp 'menu-bar-options-menu)
(define-key-after menu-bar-options-menu [show-trailing-whitespace]
(my-menu-bar-make-local-mm-toggle
show-trailing-whitespace
"Trailing Whitespace Highlighting"
"Highlight whitespace at line ends (Show Trailing Whitespace)")
'highlight-paren-mode)
(define-key-after menu-bar-options-menu [toggle-auto-image]
(menu-bar-make-mm-toggle auto-image-file-mode
"Automatic Display of Image Files"
"Visit image files as images")
'toggle-auto-compression)
(define-key-after menu-bar-options-menu [debug-on-signal]
(menu-bar-make-toggle
toggle-debug-on-signal debug-on-signal
"Enter Debugger on Signal" "Debug on Signal %s"
"Enter Lisp debugger regardless of condition handlers")
'debug-on-error)
(if (boundp 'menu-bar-showhide-menu)
(define-key menu-bar-showhide-menu [ruler]
(my-menu-bar-make-local-mm-toggle ruler-mode
"Ruler" "Turn ruler on/off"))
(define-key-after menu-bar-options-menu [tool-bar-separator]
'("--") 'debug-on-quit)
(define-key-after menu-bar-options-menu [tool-bar]
(menu-bar-make-mm-toggle tool-bar-mode "Toggle Tool Bar"
"Toggle display of the tool-bar")
'tool-bar-separator)
(define-key-after menu-bar-options-menu [display-time]
(menu-bar-make-mm-toggle
display-time-mode "Toggle Display Time/Mail"
"Toggle display of the time and mail indicator"))))
(global-font-lock-mode 1)
(setq font-lock-maximum-decoration t
font-lock-global-modes '(not shell-mode text-mode)
font-lock-verbose t
font-lock-maximum-size '((t . 1048576) (vm-mode . 5250000)))
(let (mode comment)
(mapcar (lambda (elem)
(setq mode (car elem)
comment (cdr elem))
(font-lock-add-keywords
mode
`((,comment ("\\<\\(GM\\|NB\\|TODO\\|FIXME\\)\\>" nil nil
(0 'font-lock-warning-face t)))
(,comment ("[* ]\\*\\([$a-zA-Z].*\\)\\*" nil nil
(1 'font-lock-warning-face t)))
(,comment ("`\\([^`']+\\)'" nil nil
(1 'font-lock-constant-face t))))))
'((awk-mode . "#")
(sh-mode . "#")
(fortran-mode . "^C")
(f90-mode . "!")
(tcl-mode . "#")
(makefile-mode . "#")
(python-mode . "#"))))
(setq font-lock-support-mode
(if (require 'jit-lock nil t)
'((vm-mode . fast-lock-mode) (t . jit-lock-mode))
'fast-lock-mode))
(setq jit-lock-stealth-verbose nil
jit-lock-stealth-time 2
jit-lock-stealth-load 90
jit-lock-stealth-nice 0.5
jit-lock-defer-contextually 'syntax-driven)
(setq fast-lock-minimum-size 50000 fast-lock-verbose 50000 fast-lock-save-events '(save-buffer)
fast-lock-save-others nil fast-lock-cache-directories `(,(expand-file-name "flc" my-emacsdir)))
(let (dir)
(mapcar (lambda (elem)
(setq dir (if (listp elem) (cdr elem) elem))
(or (file-directory-p dir) (make-directory elem)))
fast-lock-cache-directories))
(setq tab-stop-list '(4 8 12 16 20 24 28 32 36)
backward-delete-char-untabify-method nil)
(setq-default indent-tabs-mode nil)
(setq-default abbrev-mode t)
(setq save-abbrevs t
abbrev-file-name (expand-file-name "abbrevs" my-emacsdir)
minor-mode-alist
(delq (assq 'abbrev-mode minor-mode-alist) minor-mode-alist))
(if (file-exists-p abbrev-file-name) (quietly-read-abbrev-file))
(defun my-abbrevs-save ()
"Save the abbreviations file if it has changed.
Intended for use with `my-before-kill-emacs-hook'."
(when (and abbrevs-changed save-abbrevs)
(write-abbrev-file abbrev-file-name)
(setq abbrevs-changed nil)))
(add-hook 'my-before-kill-emacs-hook 'my-abbrevs-save)
(setq bookmark-save-flag 1)
(setq printer-name my-printer
ps-printer-name-option "-P"
ps-printer-name nil ps-print-color-p nil ps-paper-type (cond
((string-equal my-system "slac") 'letter)
(t 'a4))
ps-header-lines 2
ps-right-header '("/pagenumberstring load" my-ps-header-fn)
ps-spool-duplex t
ps-multibyte-buffer 'bdf-font-except-latin)
(defun my-ps-header-fn ()
"Format the date and time as I prefer for PS header."
(format-time-string "%T %x"))
(if (file-directory-p "/usr/local/share/fonts/intlfonts/bdf")
(add-to-list 'bdf-directory-list "/usr/local/share/fonts/intlfonts/bdf"))
(when (and (require 'printing nil t)
(executable-find "lpstat"))
(with-temp-buffer
(call-process "lpstat" nil t nil "-p")
(goto-char (point-min))
(let (pr-string pr-name)
(while (re-search-forward "^printer \\([[:alnum:]]+\\) .*enabled"
nil t)
(setq pr-string (match-string 1)
pr-symbol (intern pr-string))
(add-to-list 'pr-txt-printer-alist
(list pr-symbol "lpr" nil "-P" pr-string) t))))
TODO (setq pr-txt-printer-alist
(append `((default "lpr" nil "-P" ,my-printer))
(delete (assoc 'default pr-txt-printer-alist)
pr-txt-printer-alist))
pr-ps-printer-alist pr-txt-printer-alist
pr-menu-lock nil)
(pr-update-menus t))
(setq spook-phrase-default-count 8)
(let ((file (expand-file-name "spook.lines" my-emacsdir)))
(if (file-exists-p file) (setq spook-phrases-file file)))
(defun my-spook-string (&optional number length)
"Return as a string the output of `spook'.
Optional argument NUMBER is the number of spook phrases to
return. If unspecified, `spook-default-phrase-count' will be
used. If LENGTH is present, output will not be longer than this
many characters."
(with-temp-buffer
(let ((spook-phrase-default-count (or number spook-phrase-default-count))
start end)
(spook)
(setq start (1+ (point-min))
end (1- (point-max)))
(buffer-substring start
(if (and length (< length end))
(progn
(goto-char length)
(or (re-search-backward " " start t)
length))
end)))))
(when (and (equal my-emacs-type 'mail)
(require 'spookmime nil t))
(autoload 'mail-header-extract "mailheader")
(defun my-spookmime-mml-make-boundary (&optional this-msg-count)
"Like `spookmime-mml-make-boundary', but only with an X-Spook header."
(if (save-excursion
(goto-char (point-min))
(assoc 'x-spook (mail-header-extract)))
(spookmime-mml-make-boundary this-msg-count)
(mml-make-boundary this-msg-count)))
(setq mml-boundary-function 'my-spookmime-mml-make-boundary)
(ad-deactivate 'vm-mime-make-multipart-boundary)
(defadvice vm-mime-make-multipart-boundary (around spookmime activate)
"Use Spookmime, but only if there is an X-Spook header."
(if (save-excursion
(goto-char (point-min))
(assoc 'x-spook (mail-header-extract)))
(setq ad-return-value (spookmime-make-mime-boundary))
ad-do-it)))
(when (equal my-emacs-type 'mail)
(setq feedmail-buffer-eating-function 'feedmail-buffer-to-smtpmail
feedmail-deduce-envelope-from nil
send-mail-function 'smtpmail-send-it
message-send-mail-function 'smtpmail-send-it smtpmail-default-smtp-server "localhost"
smtpmail-debug-info nil
mail-interactive nil
smtpmail-queue-mail nil
smtpmail-queue-dir "~/VM/queue/"
mail-use-rfc822 t
mail-specify-envelope-from nil
mail-envelope-from 'header)
(cond ((string-equal my-system "xray")
(setq smtpmail-local-domain nil smtpmail-default-smtp-server "xalph3.ast.cam.ac.uk"
NB smtpmail-sendto-domain "ast.cam.ac.uk"))
((string-equal my-system "slac")
(setq smtpmail-default-smtp-server "smtpserv.slac.stanford.edu"
))
((string-equal my-system "stanford")
(setq smtpmail-default-smtp-server "smtp.stanford.edu")))
(setq smtpmail-smtp-server smtpmail-default-smtp-server)
(when (require 'smtpmod nil t)
(setq smtpmod-enable-flag t
smtpmod-fqdn (if (boundp 'smtpmail-default-smtp-server)
smtpmail-default-smtp-server
'real)
smtpmod-user-mail-address 'copy))
(setq
user-mail-address (cond ((string-equal my-system "furn")
"gm@localhost")
((string-match "^\\(xray\\|cass\\)$" my-system)
(my-mail-obfuscate-address
"gmorris" "generic@ast.cam.ac.uk"))
((string-equal my-system "slac")
(my-mail-obfuscate-address
"gmorris" "generic@slac.stanford.edu"))
((string-equal my-system "stanford")
(my-mail-obfuscate-address
"rgm" "generic@stanford.edu"))
((string-equal my-system "gnu")
(my-mail-obfuscate-address
"rgm" "generic@gnu.org")))
gnus-nntp-server nil gnus-select-method (cond ((string-equal my-system "slac")
'(nntp "news.slac.stanford.edu"))
((string-equal my-system "stanford")
'(nntp "news.stanford.edu"))
((string-match "^\\(cass\\|xray\\)" my-system)
'(nntp "nntp-serv.cam.ac.uk"))
(t '(nntp "news.gmane.org")))
gnus-home-directory "~/Gnus/"
gnus-read-newsrc-file nil
gnus-save-newsrc-file nil
gnus-startup-file (expand-file-name ".newsrc" gnus-home-directory)
nnfolder-directory (expand-file-name "Mail" gnus-home-directory)
nnfolder-active-file (expand-file-name "active" nnfolder-directory)
smiley-regexp-alist
'(("\\(:-*[<?]+\\)\\W" 1 "FaceAngry")
("\\(:-+\\]+\\)\\W" 1 "FaceGoofy")
("\\(:-*D\\)\\W" 1 "FaceGrinning")
("\\(:-*[)>}?]+\\)\\W" 1 "FaceHappy")
("\\(=[)?]+\\)\\W" 1 "FaceHappy")
("\\(:-*[/\\\"]\\)[^/]\\W" 1 "FaceIronic")
("[^.0-9]\\([8|]-*[|Oo%]\\)\\W" 1 "FaceKOed")
("\\([:|]-*#+\\)\\W" 1 "FaceNyah")
("\\(:-*[({]+\\)\\W" 1 "FaceSad")
("\\(=[({]+\\)\\W" 1 "FaceSad")
("\\(:-*[Oo\*]\\)\\W" 1 "FaceStartled")
("\\(:-*|\\)\\W" 1 "FaceStraight")
("\\(:-*p\\)\\W" 1 "FaceTalking")
("\\(:-*d\\)\\W" 1 "FaceTasty")
("\\(;-*[>)}?]+\\)\\W" 1 "FaceWinking")
("\\(:-*[Vv?]\\)\\W" 1 "FaceWry")
("\\([:|]-*P\\)\\W" 1 "FaceYukky")))
)
(let ((galeon (executable-find "galeon")))
(when (and galeon (file-executable-p galeon))
(setq browse-url-netscape-program galeon)
(when (fboundp 'browse-url-galeon)
(setq browse-url-browser-function 'browse-url-galeon
browse-url-galeon-program galeon
browse-url-new-window-flag t
browse-url-galeon-new-window-is-tab t))))
(setq vc-initial-comment t vc-default-init-version "1.1"
vc-handled-backends '(RCS CVS)
vc-make-backup-files t
TODO vc-cvs-stay-local (not (string-equal my-system "kdell"))
vc-keep-workfiles t
vc-command-messages t
vc-follow-symlinks t
vc-dired-terse-display t
diff-switches '("-c" "-w")
vc-cvs-diff-switches nil vc-cvs-global-switches '("-z3"))
(setq change-log-version-info-enabled nil
add-log-full-name "Glenn Morris"
add-log-mailing-address (my-mail-obfuscate-address
"rgm" "generic@gnu.org")
add-log-keep-changes-together t
log-edit-confirm 'changed
log-edit-changelog-full-paragraphs nil)
(setq cvs-auto-remove-handled t)
(my-make-hook-fn cvs-mode-hook
(face-spec-set 'cvs-msg-face '((t (:foreground "pink"))))
(face-spec-set 'cvs-header-face
'((t (:foreground "aquamarine" :weight bold))))
(face-spec-set 'cvs-need-action-face '((t (:foreground "yellow2"))))
(face-spec-set 'cvs-unknown-face '((t (:foreground "red" :weight bold))))
(face-spec-set 'cvs-handled-face '((t (:foreground "lawngreen")))))
(my-make-hook-fn log-view-mode-hook
(face-spec-set 'log-view-file-face
'((t (:foreground "aquamarine" :weight bold))))
(face-spec-set 'log-view-message-face
'((t (:foreground "yellow2")))))
TODO
(my-make-hook-fn log-edit-mode-hook
(local-set-key "\C-ca" 'my-log-edit-add-entry))
(defun my-empty-buffer (&optional buffer)
"Return non-nil if buffer is empty (ie nothing but whitespace).
Operate on the current buffer, or that specified by optional BUFFER argument."
(if buffer
(or (get-buffer buffer)
(error "Buffer `%s' not found" buffer))
(setq buffer (buffer-name))
(save-excursion
(set-buffer buffer)
(goto-char (point-min))
(not (re-search-forward "[^ \t\n]" (point-max) t)))))
(my-make-hook-fn log-edit-done-hook
(if (my-empty-buffer)
(or
(catch 'found
(dolist (file (log-edit-files) t)
(or (string-equal "ChangeLog" (file-name-nondirectory file))
(throw 'found nil))))
(yes-or-no-p "Really commit with empty log? ")
(error "Commit aborted"))
(save-excursion
(goto-char (point-max))
(re-search-backward "[^ \t]" nil t) (delete-blank-lines)))
(let ((dbuff "*vc-diff*")
(file (car (log-edit-files)))
diff-buff)
(when (and file (get-buffer dbuff))
(setq file (find-buffer-visiting file))
(with-current-buffer dbuff
(save-excursion
(goto-char (point-max))
(setq diff-buff (car (diff-find-source-location)))))
(if (equal diff-buff file)
(kill-buffer dbuff)))))
(setq diff-default-read-only t)
(my-make-hook-fn diff-mode-hook
(if window-system
(progn
(face-spec-set
'diff-file-header-face '((t (:weight bold :foreground "aquamarine"))))
(face-spec-set
'diff-header-face
'((t (:weight bold :foreground "cyan" :background "grey45"))))
(face-spec-set
'diff-hunk-header-face
'((t (:weight bold :foreground "azure" :background "grey45"))))
(face-spec-set 'diff-context-face '((t (:foreground "grey70"))))
(face-spec-set 'diff-nonexistent-face '((t (:foreground "red"))))
(face-spec-set 'diff-changed-face '((t (:foreground "DarkSlateGray1"))))
(face-spec-set 'diff-added-face '((t (:foreground "DarkOliveGreen1"))))
(face-spec-set 'diff-removed-face '((t (:foreground "khaki1"))))
(face-spec-set 'diff-function-face '((t (:foreground "IndianRed1")))))
(face-spec-set 'diff-context-face '((t (:inherit default))))))
(setq ediff-use-long-help-message t)
(setq completion-ignored-extensions
(delete ".bbl" completion-ignored-extensions)
completion-ignored-extensions
(delete ".log" completion-ignored-extensions))
(setq compilation-scroll-output t
compilation-ask-about-save nil)
(unless (equal my-emacs-type 'mail)
(setq calendar-latitude +52.1
calendar-longitude +0.1
calendar-location-name "Cambridge"
calendar-remove-frame-by-deleting t
calendar-week-start-day 1
european-calendar-style t
mark-diary-entries-in-calendar t
mark-holidays-in-calendar t
view-calendar-holidays-initially nil)
(require 'cal-x) (setq calendar-setup 'calendar-only)
(add-hook 'today-visible-calendar-hook 'calendar-mark-today)
(add-hook 'list-diary-entries-hook 'sort-diary-entries t)
(my-make-hook-fn initial-calendar-window-hook
(face-spec-set 'calendar-today-face '((t (:background "steelblue"))))
(face-spec-set 'diary-face
'((t (:foreground "aquamarine" :weight bold))))
(face-spec-set 'holiday-face '((t (:underline t)))))
(defadvice exit-calendar (after kill-calendar-buffer activate)
"Kill the calendar buffer on exit."
(mapcar (lambda (buff) (and (get-buffer buff) (kill-buffer buff)))
'("*Calendar*" "*Fancy Diary Entries*")))
)
(unless (equal my-emacs-type 'mail)
(setq diary-file (file-chase-links (expand-file-name "diary" my-emacsdir))
diary-list-include-blanks nil
diary-header-line-flag nil
mark-diary-entries-in-calendar t
diary-mail-addr (my-mail-obfuscate-address "gmorris+diary"
"generic@ast.cam.ac.uk")
diary-mail-days 7)
(add-hook 'diary-display-hook 'fancy-diary-display)
(defadvice fancy-diary-display (after view-mode activate)
"Switch the fancy-diary-buffer to read-only."
(if (get-buffer fancy-diary-buffer)
(save-excursion
(set-buffer fancy-diary-buffer)
(local-set-key "q" 'View-kill-and-leave) (view-mode 1)))))
(unless (equal my-emacs-type 'mail)
(setq appt-display-diary nil
appt-display-mode-line t
appt-display-duration 10 appt-display-interval 3 appt-message-warning-time 12 appt-audible t)
(if (fboundp 'appt-activate)
(progn
(setq appt-display-format 'window)
(appt-activate 1)
(my-face-set 'appt-mode-line
'((t :foreground "deepskyblue2" :weight bold))))
(setq appt-issue-message t
appt-msg-window t
appt-visible nil)
(add-hook 'diary-hook 'appt-make-list)))
(add-hook 'text-mode-hook 'turn-on-auto-fill)
(setq-default fill-column 70)
(setq ispell-program-name "/usr/bin/ispell")
(setq-default ispell-local-dictionary "british")
(setq flyspell-issue-welcome-flag nil)
(my-make-hook-fn text-mode-hook
(when (and (boundp 'hs-minor-mode)
hs-minor-mode)
(hs-minor-mode -1)))
(my-make-hook-fn enriched-mode-hook
(define-key enriched-mode-map [return] 'newline)
(face-spec-set 'excerpt '((t (:slant italic :family "helvetica")))))
(setq sentence-end-double-space nil
sentence-end (if sentence-end-double-space
"[.?!][]\"')]*\\($\\| $\\|\t\\| \\)[ \t\n]*"
"[.?!][]\"')]*\\($\\|\t\\| \\)[ \t\n]*"))
(defun my-sentence-end-double-space ()
"Set `sentence-end-double-space' to t, and set `sentence-end' to match.
Make these variables buffer-local."
(set (make-local-variable 'sentence-end-double-space) t)
(set (make-local-variable 'sentence-end)
"[.?!][]\"')]*\\($\\| $\\|\t\\| \\)[ \t\n]*"))
(mapcar (lambda (mode) (add-hook (intern (format "%s-mode-hook" mode))
'my-sentence-end-double-space))
'(emacs-lisp log-edit change-log texinfo Texinfo))
(defun my-duplicate-words-find () "Find consecutive groups of one or more repeated words."
(interactive)
(if (search-forward-regexp
"\\(\\<\\w+\\>\\(?:[ \t]+\\<\\w+\\>\\)*\\)[ \t\n]*\\1\\>" nil t)
(dotimes (i 2)
(save-excursion
(sit-for 0.1)
(goto-char (match-beginning 0))
(sit-for 0.1)))
(if (interactive-p) (message "No more duplicates"))))
(defface my-Man-overstrike-face '((t (:foreground "white" :weight normal)))
"Face used for overstrike in man pages.")
(defface my-Man-underline-face '((t (:foreground "yellow")))
"Face used for overstrike in man pages.")
(setq Man-overstrike-face 'my-Man-overstrike-face
Man-underline-face 'my-Man-underline-face)
(setq woman-cache-filename (expand-file-name "woman.cache" my-emacsdir)
woman-bold-headings nil
woman-imenu-title "WoMan-imenu"
woman-imenu t
woman-use-own-frame t woman-topic-at-point nil
woman-fill-frame t)
(defun my-woman-pre-format-fn ()
"Function added to `woman-pre-format-hook'."
(copy-face 'my-Man-overstrike-face 'woman-bold-face)
(copy-face 'my-Man-underline-face 'woman-italic-face)
(face-spec-set 'woman-addition-face '((t (:foreground "orange"))))
(face-spec-set 'woman-unknown-face '((t (:foreground "cyan")))))
(add-hook 'woman-pre-format-hook 'my-woman-pre-format-fn)
(add-hook 'woman-post-format-hook (lambda () (setq woman-frame nil)))
(my-make-hook-fn tcl-mode-hook
(imenu-add-menubar-index)
(my-face-set 'tcl-escaped-newline
'((t (:foreground "pink" :weight bold)))))
(font-lock-add-keywords
'python-mode (list (cons
(concat "\\<"
(regexp-opt '("False" "True" "None"
"NotImplemented" "Ellipsis") t)
"\\>")
'font-lock-constant-face)
'("\\(^\\|[^\\]\\)\\(\\\\\\\\\\)*\\(\\\\\\)$"
3 font-lock-warning-face)
TODO '("\\<\\([[:alpha:]_][.[:alnum:]_]*\\)\\>[ \t]*=[ \t]"
1 font-lock-variable-name-face)
(list
(concat "[ \t]"
(regexp-opt '("<" ">" "==" ">=" "<=" "<>" "!="
"&" "|" "%" "+=") t)
"[ \t]")
1 font-lock-constant-face)
(list
(concat "\\<"
(regexp-opt '("global" "import"
"len" "pass" "print") t)
"\\>")
1 font-lock-builtin-face)))
(defun my-python-set-magic ()
"Insert the #! line in a python script."
(interactive "*")
(executable-set-magic "/usr/bin/python" nil t))
(my-make-hook-fn python-mode-hook
(imenu-add-menubar-index)
(require 'executable)
(font-lock-add-keywords nil executable-font-lock-keywords)
(local-set-key "\C-c:" 'my-python-set-magic))
(setq-default c-default-style "k&r")
(font-lock-add-keywords
'c-mode
`(("/\\*" ("\\<\\(GM\\|NB\\|TODO\\)\\>"
nil nil (0 'font-lock-warning-face t)))
("/\\*" ("\\*\\([^ ][^*]*[^ ]*\\)\\*[^//]"
nil nil (1 'font-lock-warning-face t)))
("/\\*" ("`\\([^`']+\\)'" nil nil (1 'font-lock-constant-face t)))
(,(regexp-opt '("&&" "||" "<=" ">=" "==" "!=" "++" "--" "+=" "-=" "*=" "/=") t) .
font-lock-constant-face)))
(add-hook 'c-mode-hook 'imenu-add-menubar-index)
(my-make-hook-fn c-mode-hook
(hs-minor-mode 1)
(mapc (lambda (key) (local-set-key key 'self-insert-command))
'("{" "}" "(" ")" "," ";"))
(or (file-expand-wildcards "[Mm]akefile")
(if buffer-file-name
(setq compile-command (format "gcc -Wall %s" buffer-file-name)))))
(setq fortran-comment-indent-style nil fortran-continuation-string "&"
fortran-comment-region "C"
fortran-blink-matching-if t
fortran-break-before-delimiters nil)
(add-hook 'fortran-mode-hook 'imenu-add-menubar-index)
(my-make-hook-fn fortran-mode-hook
(hs-minor-mode 1)
(set (make-local-variable 'comment-padding) nil)
GM )
(unless (equal 'my-emacs-type 'mail)
(add-to-list 'auto-mode-alist '("\\.f95\\'" . f90-mode))
(setq f90-beginning-ampersand nil start f90-indented-comment-re "!!" f90-comment-region "!!! " f90-program-indent 2 f90-type-indent 3 f90-do-indent 3 f90-if-indent 3 f90-continuation-indent 5
f90-break-before-delimiters nil
f90-directive-comment-re "!\\(hpf\\|\\$OMP\\)")
(add-hook 'f90-mode-hook 'turn-on-auto-fill)
(add-hook 'f90-mode-hook 'f90-add-imenu-menu)
(defun my-f90-mode-init-fn ()
"Run the first time f90-mode is loaded."
(unless (and (boundp 'my-f90-mode-init-flag)
my-f90-mode-init-flag)
(setq my-f90-mode-init-flag t)
(when (require 'compile nil t)
(add-to-list 'compilation-error-regexp-alist
'("^\\w+: \\(.+\\), line \\([0-9]+\\):" 1 2)))
(defface f95-keyword-face
'((t (:foreground "plum1")))
"F95 keywords face.")
(defface f95-function-face
'((t (:foreground "azure1")))
"F95 function name face.")
(defvar f95-font-lock-keywords
(list
'("\\<\\(pure\\|elemental\\)\\>" . 'f95-keyword-face)
'("^[^!]*\\<\\(null\\|cpu_time\\|elsewhere\\)\\>[ \t]*("
1 'f95-function-face t)
'("^[^!]*\\<\\(end[ \t]*forall\\)\\>"
1 'f95-function-face t)
'("^[^!]*\\<\\(forall\\)\\>"
1 'f95-function-face t)
'("\\<\\(\\(max\\|min\\)loc\\|ceiling\\|floor\\)\\>[ \t]*("
("\\<dim\\>" nil nil (0 'f95-keyword-face))))
"Highlights extra F95 keywords.")
(defun my-f90-in-declaration ()
"Return non-nil if current line contains `::' construct."
(save-excursion
(beginning-of-line)
(re-search-forward "::" (line-end-position) t)))
(when (require 'align nil t)
(setq align-to-tab-stop nil my-f90-align-rules-list
`((f90-bracket-in-declaration
(regexp . "\\(\\s-+\\)([^ :]+).*::"))
(f90-comma-in-declaration (regexp . "\\(\\s-*\\),\\s-+.*::") (spacing . 0))
(f90-dimension-in-declaration
(regexp . "\\(\\s-*\\),\\s-*dimension.*::")
(spacing . 0)
(case-fold . t))
(f90-alloc-in-declaration
(regexp . "\\(\\s-*\\),\\s-*allocatable.*::")
(spacing . 0)
(case-fold . t))
(f90-intent-in-declaration
(regexp . "\\(\\s-*\\),\\s-*intent.*::")
(spacing . 0)
(case-fold . t))
(f90-parameter-in-declaration
(regexp . "\\(\\s-*\\),\\s-*parameter.*::")
(spacing . 0)
(case-fold . t))
(f90-save-in-declaration
(regexp . "\\(\\s-*\\),\\s-*save.*::")
(spacing . 0)
(case-fold . t))
(f90-colon-in-declaration (regexp . "\\(\\s-+\\):: "))
(f90-left-bracket
(regexp . "\\(\\s-*\\)(\\S+")
(spacing . 0)
(repeat . t)
(valid . ,(function (lambda ()
(not (my-f90-in-declaration))))))
(f90-assignment
(regexp . "\\(\\s-+\\)[=<>]\\(\\s-+\\)\\S-") (group . (1 2))
(spacing . (1 1))
(repeat . t))
(f90-comma-colon
(regexp . "\\(\\s-*\\)[,;]\\s-+") (spacing . 0) (repeat . t)
(valid . ,(function (lambda ()
(not (my-f90-in-declaration))))))
(f90-trailing-comment
(regexp . "\\(\\s-+\\)!\\s-+")
(spacing . 10))))
(add-to-list 'align-open-comment-modes 'f90-mode)
(add-to-list 'align-dq-string-modes 'f90-mode)
(add-to-list 'align-sq-string-modes 'f90-mode))
(font-lock-add-keywords
'f90-mode
`(("^#\\(\\w+\\)\\([ \t]+\\w+\\)?" (1 font-lock-builtin-face)
(2 font-lock-variable-name-face nil t))
(,(regexp-opt '("<=" ">=" "==" "/=") t) . font-lock-constant-face)))
(define-abbrev [f90-mode-abbrev-table] "`ife" "" 'f90-skeleton-elif)
(setq abbrevs-changed nil)
(define-skeleton f90-skeleton-elif
"Insert an F90 elif block."
nil
> "if (" _ ") then"\n
\n
-3"else" \n
\n
-3"end if"\n)
(defconst f90-end-block-re
(concat "^[ \t0-9]*\\<end\\>[ \t]*"
(regexp-opt '("do" "if" "forall" "function" "interface"
"module" "program" "select" "subroutine"
"type" "where" ) t)
"[ \t]*\\sw*")
"Regexp matching the end of a \"block\" of F90 code.")
(defconst f90-start-block-re
(concat
"^[ \t0-9]*" "\\(\\("
"\\(\\sw+[ \t]*:[ \t]*\\)?" "\\(do\\|select[ \t]*case\\|if[ \t]*(.*\n?.*)[ \t]*then\\|"
"\\(where\\|forall\\)[ \t]*(.*)[ \t]*\\(!\\|$\\)\\)\\)"
"\\|"
"program\\|interface\\|module\\|type\\|function\\|subroutine"
"\\)"
"[ \t]*")
"Regexp matching the start of a \"block\" of F90 code.
A simple regexp cannot do this in fully correct fashion, so this
tries to strike a compromise between complexity and flexibility.")
(add-to-list 'hs-special-modes-alist
`(f90-mode ,f90-start-block-re ,f90-end-block-re
"!" f90-end-of-block nil))
))
(my-make-hook-fn f90-mode-hook
(my-f90-mode-init-fn)
(make-variable-buffer-local 'compile-command)
(setq comment-column 35
comment-start "! "
f90-font-lock-keywords-4
(append f90-font-lock-keywords-3 f95-font-lock-keywords)
compile-command
(if buffer-file-name
(if (file-exists-p "Makefile")
(format "make %s"
(file-name-sans-extension
(file-name-nondirectory
buffer-file-name)))
(format "ifort -warn all -std90 %s" buffer-file-name)))
align-mode-rules-list my-f90-align-rules-list)
(define-key f90-mode-map [?\C-^] 'f90-join-lines)
(hs-minor-mode 1)
(when (boundp 'comment-auto-fill-only-comments)
(setq comment-auto-fill-only-comments t)
NB ))
)
(if (executable-find "clisp") (setq inferior-lisp-program "clisp"))
(when (and (not (equal my-emacs-type 'mail))
(file-directory-p "~/elisp/slime")
(add-to-list 'load-path "~/elisp/slime" t))
(autoload 'slime "slime" "" t)
(defadvice slime (before slime-setup activate)
"Call `slime-setup' first."
(slime-setup))
(let ((dir (file-name-as-directory
(expand-file-name "../../../doc/HyperSpec" my-sitelisp))))
(if (file-directory-p dir)
(setq common-lisp-hyperspec-root dir))))
(font-lock-add-keywords
'emacs-lisp-mode
'((";" ("\\<\\(GM\\|NB\\|TODO\\|FIXME\\)\\>" nil nil
(0 'font-lock-warning-face t)))
(";" ("[* ]\\*[ \t]*\\(\\w.*\\)\\*" nil nil
(1 'font-lock-warning-face t)))))
(unless (equal my-emacs-type 'mail)
(mapcar (lambda (elem)
(add-hook 'emacs-lisp-mode-hook elem))
'(imenu-add-menubar-index turn-on-eldoc-mode checkdoc-minor-mode))
(defun my-eldoc-argument-case-fn (string)
"Function to use for variable `eldoc-argument-case'."
(propertize (upcase string) 'face 'font-lock-keyword-face))
TODO (setq eldoc-argument-case 'my-eldoc-argument-case-fn)
(my-make-hook-fn emacs-lisp-mode-hook
(local-set-key "\C-cd" 'my-jump-to-defun)
(hs-minor-mode 1)
(if (eq major-mode 'emacs-lisp-mode)
(setq mode-name "Elisp"))
(when (boundp 'comment-auto-fill-only-comments)
(setq comment-auto-fill-only-comments t)
(kill-local-variable 'normal-auto-fill-function)))
(my-make-hook-fn lisp-interaction-mode-hook
(setq mode-name "Lisp Int"))
)
(setq eval-expression-print-level 10
eval-expression-print-length 100)
(my-make-hook-fn makefile-mode-hook
(imenu-add-menubar-index)
(font-lock-add-keywords nil
'(("ifeq[ \t]*(" (" +" nil nil
(0 'makefile-space-face)))))
(when (fboundp 'makefile-gmake-mode)
(set (make-local-variable 'font-lock-type-face) 'default)
TODO (font-lock-add-keywords nil
'(
("\\(\\$\\)\\([@%<?^+*]\\)"
(1 'default t)
(2 font-lock-constant-face t))
("$[({]\\([[:alnum:]_.]+\\)[})]"
(1 font-lock-constant-face t t))
) t)))
(eval-after-load "make-mode"
'(progn
(my-face-set 'makefile-shell-face
'((t :background "unspecified" :inherit 'default )))
(my-face-set 'makefile-targets-face
'((t :underline nil
:inherit 'font-lock-function-name-face)))))
(when (fboundp 'makefile-gmake-mode)
(add-to-list 'auto-mode-alist '("[Mm]akefile\\'" . makefile-gmake-mode)))
(my-make-hook-fn awk-mode-hook
(set (make-local-variable 'c-block-comment-prefix) "#")
(set (make-local-variable 'c-syntactic-indentation)
(if (locate-library "cc-awk") t))
(set (make-local-variable 'c-basic-offset) 4)
(local-set-key "}" 'self-insert-command)
(local-set-key "{" 'self-insert-command)
(font-lock-add-keywords
nil `(("^#!.*\\(gawk.*\\)$" . (1 font-lock-keyword-face t)) ("\\$\\([0-9]+\\|nf\\)" . (1 font-lock-variable-name-face))
("\\(^\\|[^\\]\\)\\(\\\\\\\\\\)*\\(\\\\\\)$"
3 font-lock-warning-face) (,(regexp-opt '("&&" "||" "<=" ">=" "==" "!="
"++" "--" "+=" "-=" "*=" "/="
"~" "!~") t) .
font-lock-constant-face))))
TODO(setq sgml-font-lock-keywords
'(("<\\([!?][a-z][-.a-z0-9]*\\)" 1 font-lock-keyword-face)
("<\\(/?[a-z][-.a-z0-9]*\\)" 1 font-lock-function-name-face)
("[&%][a-z][-.a-z0-9]*;?" . font-lock-variable-name-face)
("<!-- * -->" . font-lock-comment-face)))
(font-lock-add-keywords 'html-mode
'(("\\<TODO\\>" 0 font-lock-warning-face t)))
(setq executable-prefix "#!" sh-here-document-word "EOF"
sh-shell-file "/bin/bash"
sh-indent-comment t)
(defface makefile-space-face
'((((class color)) (:background "hotpink"))
(t (:reverse-video t)))
"Face to use for highlighting leading spaces in Font-Lock mode.")
(defun my-sh-mode-font-lock-heredoc-space (lim)
"Match leading space in a heredoc."
(if (eq (get-text-property (point) 'face) 'sh-heredoc-face)
(re-search-forward "^ +" (min lim (line-end-position)) t)))
(font-lock-add-keywords
'sh-mode
`((,(format "[ \t]%s\\([ \t]\\|$\\)"
(regexp-opt '("||" "&&" "!=" "==" "<=" ">="
"-eq" "-ne" "-lt" "-gt" "-le" "-ge") t))
. font-lock-constant-face)
("^\t+" (0 'makefile-space-face t))
NB ))
(my-make-hook-fn sh-mode-hook
TODO (set (make-local-variable 'file-precious-flag) t)
(imenu-add-menubar-index)
(modify-syntax-entry ?= ".") (set (make-variable-buffer-local 'adaptive-fill-regexp)
"[ \t]*\\(#+[ \t]+\\)*")
(setq mode-name "Sh-script" tab-width 4)
(my-face-set 'sh-heredoc-face
'((t (:weight normal :foreground "green yellow"))))
(my-face-set 'sh-escaped-newline
'((t (:foreground "pink" :weight bold))))
(when (boundp 'comment-auto-fill-only-comments)
(setq comment-auto-fill-only-comments t))
(when (> emacs-major-version 21)
(add-to-list (if (boundp 'sh-font-lock-keywords-var)
'sh-font-lock-keywords-var
'sh-font-lock-keywords)
'(bash sh-append sh
("\\<\\(declare\\|export\\|typeset\\)\\>.*\\<-[fF]\\>"
("\\<\\(\\sw+\\)\\>" nil nil
(1 font-lock-function-name-face)))
("\\<\\(declare\\|local\\|typeset\\)\\>"
("[ \t]+\\([A-Za-z_][A-Za-z0-9_]*\\)\\>" nil nil
(1 font-lock-variable-name-face)))
("\\<let\\>"
("[ \t]*\\(+\\+\\|--\\)\\([A-Za-z_][A-Za-z0-9_]*\\)\\>"
nil nil
(1 font-lock-constant-face)
(2 font-lock-variable-name-face)))
("\\<let\\>"
("\\<\\([A-Za-z_][A-Za-z0-9_]*\\)\
\\([|^&%*/+-]=\\|--\\|+\\+\\)"
nil nil
(1 font-lock-variable-name-face)
(2 font-lock-constant-face)))
("for[ \t]*(("
("\\<\\([A-Za-z_][A-Za-z0-9_]*\\)\
\\([ \t]*[<>]=?\\|--\\|+\\+\\)"
nil nil
(1 font-lock-variable-name-face)
(2 font-lock-constant-face)))
("\\<\\(export\\|read\\)\\>"
("[ \t]+\\([A-Za-z_][A-Za-z0-9_]*\\)\\>" nil nil
(1 font-lock-variable-name-face)))
("[ \t]*\\([<>](\\)[^)]+\\()\\)"
(1 font-lock-builtin-face)
(2 font-lock-builtin-face))
("\\(^\\|[; \t]\\)\\(\\[\\[?\\)[ \t]"
(2 font-lock-builtin-face)) ("[ \t]\\(\\]\\]?\\)[; \t\n]"
(1 font-lock-builtin-face)) ("\\(\\[\\[\\|\\]\\]\\)" . font-lock-warning-face)))))
(and (fboundp 'executable-make-buffer-file-executable-if-script-p)
(add-hook 'after-save-hook
'executable-make-buffer-file-executable-if-script-p))
(defadvice tab-to-tab-stop (around sh-indent-tabs disable) NB "In sh-mode, allow indentation to insert tabs in heredocs."
(if (and (eq major-mode 'sh-mode)
(eq (get-text-property (point) 'face) sh-heredoc-face))
(let ((indent-tabs-mode t))
ad-do-it)
ad-do-it))
(defun my-function-closing-comment (&optional always)
"Insert a closing comment giving the name of the current shell/awk function.
Requires the function `paren-backward-sexp' from mic-paren.
Unless the optional argument ALWAYS is non-nil, a closing comment
is only inserted if the function body is 4 or more lines long."
(interactive "*P")
TODO (when (fboundp 'paren-backward-sexp)
(let ((pos (point))
(n 0))
(beginning-of-line)
(when (save-excursion
(and (re-search-forward "[ \t]*}" (line-end-position) t)
(paren-backward-sexp)
(or always
(save-excursion
(while (and (<= (point) pos)
(zerop (forward-line 1)))
(setq n (1+ n)))
(> n 5)))
(progn
(beginning-of-line)
(and (looking-at "^[ \t]*{") (forward-line -1))
(cond
((eq major-mode 'sh-mode)
(looking-at "^[ \t]*\\(?:function\\)?[ \t]+\
\\([[:alnum:]_]+\\)[ \t]*()[ \t]*{?[ \t]*\\($\\|#.*\\)"))
((eq major-mode 'awk-mode)
(or
(looking-at "^[ \t]*function[ \t]+\
\\([[:alnum:]_]+\\)[ \t]*(")
(looking-at "^\\(BEGIN\\|END\\)[ \t]+\\\\")))
(t
(message "Don't know what to do for `%s'" major-mode)
nil))
)))
(setq fname (format "%c %s %s"
(string-to-char (or comment-start "#"))
(if (and (equal major-mode 'awk-mode)
(member (match-string-no-properties 1)
'("BEGIN" "END")))
"end"
"function")
(match-string-no-properties 1)))
(re-search-forward "^[ \t]*}[ \t]*\\(.*\\)" (line-end-position) t)
(unless (string-equal (match-string 1) fname)
(replace-match fname nil nil nil 1)
(comment-indent)))
(goto-char pos))))
(defadvice sh-indent-line (before my-function-closing-comment activate)
"Run `my-function-closing-comment' before indenting."
(my-function-closing-comment))
TODO(defadvice c-indent-command (before my-function-closing-comment activate)
"Run `my-function-closing-comment' before indenting in AWK mode."
(if (equal major-mode 'awk-mode)
(my-function-closing-comment)))
(defface my-eshell-code-face
'((t (:foreground "Green")))
"Eshell face for code (.c, .f90 etc) files.")
(defface my-eshell-img-face
'((t (:foreground "magenta" :weight bold)))
"Eshell face for image (.jpg etc) files.")
(defface my-eshell-movie-face
'((t (:foreground "white" :weight bold)))
"Eshell face for movie (.mpg etc) files.")
(defface my-eshell-music-face
'((t (:foreground "magenta")))
"Eshell face for music (.mp3 etc) files.")
(defface my-eshell-ps-face
'((t (:foreground "cyan")))
"Eshell face for PostScript (.ps, .pdf etc) files.")
(setq my-eshell-code-list '("f90" "f" "c" "bash" "sh" "csh" "awk" "el")
my-eshell-img-list
'("jpg" "jpeg" "png" "gif" "bmp" "ppm" "tga" "xbm" "xpm" "tif" "fli")
my-eshell-movie-list '("mpg" "avi" "gl" "dl")
my-eshell-music-list '("mp3" "ogg")
my-eshell-ps-list '("ps" "eps" "cps" "pdf")
eshell-ls-highlight-alist nil)
(let (list face)
(mapcar (lambda (elem)
(setq list (car elem)
face (cdr elem))
(add-to-list 'eshell-ls-highlight-alist
(cons `(lambda (file attr)
(string-match
(concat "\\." (regexp-opt ,list t) "$")
file))
face)))
'((my-eshell-code-list . my-eshell-code-face)
(my-eshell-img-list . my-eshell-img-face)
(my-eshell-movie-list . my-eshell-movie-face)
(my-eshell-music-list . my-eshell-music-face)
(my-eshell-ps-list . my-eshell-ps-face))))
(defun my-tidy-pwd (string)
"Replace leading ~ by $HOME in output of pwd."
(replace-regexp-in-string "^~" (getenv "HOME") string))
(defun my-eshell-prompt-function ()
"Return the prompt for eshell."
(format "[%s@%s %s]%s "
(eshell-user-name)
(replace-regexp-in-string "\\..*" "" (system-name))
(eshell/basename (eshell/pwd))
(if (zerop (user-uid)) "#" "$")))
(defun my-eshell-line-discard ()
"Eshell implementation of C-u."
(interactive)
(eshell-bol)
(kill-line))
(defun my-eshell-clear-buffer ()
(interactive)
(let ((eshell-buffer-maximum-lines 0))
(eshell-truncate-buffer)))
(defalias 'eshell/clear 'my-eshell-clear-buffer)
(setq eshell-directory-name (expand-file-name "eshell" my-emacsdir)
eshell-pwd-convert-function 'my-tidy-pwd
eshell-prompt-function 'my-eshell-prompt-function
eshell-prompt-regexp "^\\[.*\\][#$] "
eshell-ask-to-save-history 'always
eshell-banner-message `(format-time-string
"Eshell startup: %T, %A %d %B %Y\n\n"))
(my-make-hook-fn eshell-first-time-mode-hook