;;;--------------------------------------------------------------------------
;;; Check command-line.
+(defgroup mdw nil
+ "Customization for mdw's Emacs configuration."
+ :prefix "mdw-")
+
(defun mdw-check-command-line-switch (switch)
(let ((probe nil) (next command-line-args) (found nil))
(while next
;;; Some general utilities.
(eval-when-compile
- (unless (fboundp 'make-regexp)
- (load "make-regexp"))
+ (unless (fboundp 'make-regexp) (load "make-regexp"))
(require 'cl))
(defmacro mdw-regexps (&rest list)
;; Width configuration.
-(defvar mdw-column-width
+(defcustom mdw-column-width
(string-to-number (or (mdw-config 'emacs-width) "77"))
- "Width of Emacs columns.")
-(defvar mdw-text-width mdw-column-width
- "Expected width of text within columns.")
-(put 'mdw-text-width 'safe-local-variable 'integerp)
+ "Width of Emacs columns."
+ :type 'integer)
+(defcustom mdw-text-width mdw-column-width
+ "Expected width of text within columns."
+ :type 'integer
+ :safe 'integerp)
;; Local variables hacking.
(select-window win)))
(defun mdw-set-frame-width (columns &optional width)
+ "Set the current frame to be the correct width for COLUMNS columns.
+
+If WIDTH is non-nil, then it provides the width for the new columns. (This
+can be set interactively with a prefix argument.)"
(interactive "nColumns:
P")
(setq width (if width (prefix-numeric-value width)
sb-width))
(mdw-divvy-window width)))
-(defvar mdw-frame-width-fudge
+(defcustom mdw-frame-width-fudge
(cond ((<= emacs-major-version 20) 1)
((= emacs-major-version 26) 3)
(t 0))
"The number of extra columns to add to the desired frame width.
-This is sadly necessary because Emacs 26 is broken in this regard.")
+This is sadly necessary because Emacs 26 is broken in this regard."
+ :type 'integer)
+
+(defcustom mdw-frame-colour-alist
+ '((black . ("#000000" . "#ffffff"))
+ (red . ("#2a0000" . "#ffffff"))
+ (green . ("#002a00" . "#ffffff"))
+ (blue . ("#00002a" . "#ffffff")))
+ "Alist mapping symbol names to (FOREGROUND . BACKGROUND) colour pairs."
+ :type '(alist :key-type symbol :value-type (cons color color)))
+
+(defun mdw-set-frame-colour (colour &optional frame)
+ (interactive "xColour name or (FOREGROUND . BACKGROUND) pair:
+")
+ (when (and colour (symbolp colour))
+ (let ((entry (assq colour mdw-frame-colour-alist)))
+ (unless entry (error "Unknown colour `%s'" colour))
+ (setf colour (cdr entry))))
+ (set-frame-parameter frame 'background-color (car colour))
+ (set-frame-parameter frame 'foreground-color (cdr colour)))
;; Don't raise windows unless I say so.
-(defvar mdw-inhibit-raise-frame nil
- "*Whether `raise-frame' should do nothing when the frame is mapped.")
+(defcustom mdw-inhibit-raise-frame nil
+ "Whether `raise-frame' should do nothing when the frame is mapped."
+ :type 'boolean)
(defadvice raise-frame
(around mdw-inhibit (&optional frame) activate compile)
;; Functions for sexp diary entries.
+(defvar mdw-diary-for-org-mode-p nil
+ "Display diary along with the agenda?")
+
(defun mdw-not-org-mode (form)
"As FORM, but not in Org mode agenda."
(and (not mdw-diary-for-org-mode-p)
(nth 2 when))))))))
(eq w d)))
-(defvar mdw-diary-for-org-mode-p nil)
-
(defadvice org-agenda-list (around mdw-preserve-links activate)
(let ((mdw-diary-for-org-mode-p t))
ad-do-it))
-(defvar diary-time-regexp nil)
+(defcustom diary-time-regexp nil
+ "Regexp matching times in the diary buffer."
+ :type 'regexp)
(defadvice diary-add-to-list (before mdw-trim-leading-space compile activate)
"Trim leading space from the diary entry string."
;; Fighting with Org-mode's evil key maps.
-(defvar mdw-evil-keymap-keys
+(defcustom mdw-evil-keymap-keys
'(([S-up] . [?\C-c up])
([S-down] . [?\C-c down])
([S-left] . [?\C-c left])
(([M-right] [?\e right]) . [C-right]))
"Defines evil keybindings to clobber in `mdw-clobber-evil-keymap'.
The value is an alist mapping evil keys (as a list, or singleton)
-to good keys (in the same form).")
+to good keys (in the same form)."
+ :type '(alist :key-type (choice key-sequence (repeat key-sequence))
+ :value-type key-sequence))
(defun mdw-clobber-evil-keymap (keymap)
"Replace evil key bindings in the KEYMAP.
(dolist (key replacements)
(define-key keymap key binding))))))
-(defvar mdw-org-latex-defs
+(defcustom mdw-org-latex-defs
'(("strayman"
"\\documentclass{strayman}
\\usepackage[utf8]{inputenc}
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
("\\paragraph{%s}" . "\\paragraph*{%s}")
- ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))))
+ ("\\subparagraph{%s}" . "\\subparagraph*{%s}")))
+ "Additional LaTeX class definitions."
+ :type '(alist :key-type string
+ :value-type (list string
+ (alist :inline t
+ :key-type string
+ :value-type string))))
(eval-after-load "org-latex"
'(setq org-export-latex-classes
;; AUTHINFO GENERIC kludge.
-(defvar nntp-authinfo-generic nil
+(defcustom nntp-authinfo-generic nil
"Set to the `NNTPAUTH' string to pass on to `authinfo-kludge'.
-Use this to arrange for per-server settings.")
+Use this to arrange for per-server settings."
+ :type '(choice (const :tag "Use `NNTPAUTH' environment variable" nil)
+ string)
+ :safe 'stringp)
(defun nntp-open-authinfo-kludge (buffer)
"Open a connection to SERVER using `authinfo-kludge'."
;; Now actually do the thing.
(call-process "uuencode" file t nil name))
-(defvar np-file "~/.np"
- "*Where the `now-playing' file is.")
+(defcustom np-file "~/.np"
+ "Where the `now-playing' file is."
+ :type 'file
+ :safe 'stringp)
(defun np (&optional arg)
"Grabs a `now-playing' string."
(let ((auto-revert-check-vc-info t))
(auto-revert-buffers)))
-(defun comint-send-and-indent ()
- (interactive)
- (comint-send-input)
- (and mdw-auto-indent
- (indent-for-tab-command)))
-
-(defadvice comint-line-beginning-position
- (around mdw-calculate-it-properly () activate compile)
- "Calculate the actual line start for multi-line input."
- (if (or comint-use-prompt-regexp
- (eq (field-at-pos (point)) 'output))
- ad-do-it
- (setq ad-return-value
- (constrain-to-field (line-beginning-position) (point)))))
-
;;;--------------------------------------------------------------------------
;;; Dired hacking.
(eval-after-load 'w3m
'(define-key w3m-mode-map [?\e ?\r] 'w3m-view-this-url-new-session))
-(defvar mdw-good-url-browsers
+(defcustom mdw-good-url-browsers
'(browse-url-mozilla
browse-url-generic
(w3m . mdw-w3m-browse-url)
browse-url-w3)
"List of good browsers for mdw-good-url-browsers.
Each item is a browser function name, or a cons (CHECK . FUNC).
-A symbol FOO stands for (FOO . FOO).")
+A symbol FOO stands for (FOO . FOO)."
+ :type '(repeat (choice function (cons function function))))
(defun mdw-good-url-browser ()
"Return a good URL browser.
;; Useful variables.
-(defvar mdw-fill-prefix nil
- "*Used by `mdw-line-prefix' and `mdw-fill-paragraph'.
+(defcustom mdw-fill-prefix nil
+ "Used by `mdw-line-prefix' and `mdw-fill-paragraph'.
If there's no fill prefix currently set (by the `fill-prefix'
variable) and there's a match from one of the regexps here, it
gets used to set the fill-prefix for the current operation.
(make-variable-buffer-local 'mdw-fill-prefix)
-(defvar mdw-hanging-indents
+(defcustom mdw-hanging-indents
(concat "\\(\\("
"\\([*o+]\\|-[-#]?\\|[0-9]+\\.\\|\\[[0-9]+\\]\\|([a-zA-Z])\\)"
"[ \t]+"
"\\)?\\)")
- "*Standard regexp matching parts of a hanging indent.
-This is mainly useful in `auto-fill-mode'.")
+ "Standard regexp matching parts of a hanging indent.
+This is mainly useful in `auto-fill-mode'."
+ :type 'regexp)
;; Utility functions.
(match . 1)
(pad . ,(or mat 2))))))
+;;;--------------------------------------------------------------------------
+;;; Printing.
+
+;; Teach PostScript about a condensed variant of Courier. I'm using 85% of
+;; the usual width, which happens to match `mdwfonts', and David Carlisle's
+;; `pslatex'. (Once upon a time, I used 80%, but decided consistency with
+;; `pslatex' was useful.)
+(setq ps-user-defined-prologue "
+/CourierCondensed /Courier
+/CourierCondensed-Bold /Courier-Bold
+/CourierCondensed-Oblique /Courier-Oblique
+/CourierCondensed-BoldOblique /Courier-BoldOblique
+ 4 { findfont [0.85 0 0 1 0 0] makefont definefont pop } repeat
+")
+
+;; Hack `ps-print''s settings.
+(eval-after-load 'ps-print
+ '(progn
+
+ ;; Notice that the comment-delimiters should be in italics too.
+ (pushnew 'font-lock-comment-delimiter-face ps-italic-faces)
+
+ ;; Select more suitable colours for the main kinds of tokens. The
+ ;; colours set on the Emacs faces are chosen for use against a dark
+ ;; background, and work very badly on white paper.
+ (ps-extend-face '(font-lock-comment-face "darkgreen" nil italic))
+ (ps-extend-face '(font-lock-comment-delimiter-face "darkgreen" nil italic))
+ (ps-extend-face '(font-lock-string-face "RoyalBlue4" nil))
+ (ps-extend-face '(mdw-punct-face "sienna" nil))
+ (ps-extend-face '(mdw-number-face "OrangeRed3" nil))
+
+ ;; Teach `ps-print' about my condensed varsions of Courier.
+ (setq ps-font-info-database
+ (append '((CourierCondensed
+ (fonts (normal . "CourierCondensed")
+ (bold . "CourierCondensed-Bold")
+ (italic . "CourierCondensed-Oblique")
+ (bold-italic . "CourierCondensed-BoldOblique"))
+ (size . 10.0)
+ (line-height . 10.55)
+ (space-width . 5.1)
+ (avg-char-width . 5.1)))
+ (cl-remove 'CourierCondensed ps-font-info-database
+ :key #'car)))))
+
+;; Arrange to strip overlays from the buffer before we print . This will
+;; prevent `flyspell' from interfering with the printout. (It would be less
+;; bad if `ps-print' could merge the `flyspell' overlay face with the
+;; underlying `font-lock' face, but it can't (and that seems hard). So
+;; instead we have this hack.
+;;
+;; The basic trick is to copy the relevant text from the buffer being printed
+;; into a temporary buffer and... just print that. The text properties come
+;; with the text and end up in the new buffer, and the overlays get lost
+;; along the way. Only problem is that the headers identifying the file
+;; being printed get confused, so remember the original buffer and reinstate
+;; it when constructing the headers.
+(defvar mdw-printing-buffer)
+
+(defadvice ps-generate-header
+ (around mdw-use-correct-buffer () activate compile)
+ "Print the correct name of the buffer being printed."
+ (with-current-buffer mdw-printing-buffer
+ ad-do-it))
+
+(defadvice ps-generate
+ (around mdw-strip-overlays (buffer from to genfunc) activate compile)
+ "Strip overlays -- in particular, from `flyspell' -- before printout."
+ (with-temp-buffer
+ (let ((mdw-printing-buffer buffer))
+ (insert-buffer-substring buffer from to)
+ (ad-set-arg 0 (current-buffer))
+ (ad-set-arg 1 (point-min))
+ (ad-set-arg 2 (point-max))
+ ad-do-it)))
+
;;;--------------------------------------------------------------------------
;;; Other common declarations.
;; Common mode settings.
-(defvar mdw-auto-indent t
- "Whether to indent automatically after a newline.")
+(defcustom mdw-auto-indent t
+ "Whether to indent automatically after a newline."
+ :type 'boolean
+ :safe 'booleanp)
(defun mdw-whitespace-mode (&optional arg)
"Turn on/off whitespace mode, but don't highlight trailing space."
;; Backup file handling.
-(defvar mdw-backup-disable-regexps nil
- "*List of regular expressions: if a file name matches any of
-these then the file is not backed up.")
+(defcustom mdw-backup-disable-regexps nil
+ "List of regular expressions: if a file name matches any of
+these then the file is not backed up."
+ :type '(repeat regexp))
(defun mdw-backup-enable-predicate (name)
"[mdw]'s default backup predicate.
;;;--------------------------------------------------------------------------
;;; Fullscreen-ness.
-(defvar mdw-full-screen-parameters
+(defcustom mdw-full-screen-parameters
'((menu-bar-lines . 0)
- ;(vertical-scroll-bars . nil)
+ ;;(vertical-scroll-bars . nil)
)
- "Frame parameters to set when making a frame fullscreen.")
+ "Frame parameters to set when making a frame fullscreen."
+ :type '(alist :key-type symbol))
-(defvar mdw-full-screen-save
+(defcustom mdw-full-screen-save
'(width height)
- "Extra frame parameters to save when setting fullscreen.")
+ "Extra frame parameters to save when setting fullscreen."
+ :type '(repeat symbol))
(defun mdw-toggle-full-screen (&optional frame)
"Show the FRAME fullscreen."
(((class color)) :background "cyan")
(t :inverse-video t))
+(mdw-define-face viper-minibuffer-emacs (t nil))
+(mdw-define-face viper-minibuffer-insert (t nil))
+(mdw-define-face viper-minibuffer-vi (t nil))
+(mdw-define-face viper-replace-overlay
+ (((min-colors 64)) :background "darkred")
+ (((class color)) :background "red")
+ (t :inverse-video t))
+(mdw-define-face viper-search (t :inherit isearch))
+
(mdw-define-face holiday-face
(t :background "red"))
(mdw-define-face calendar-today-face
(((class color)) :background "blue")
(((type tty) (class mono)) :inverse-video t))
-(defvar mdw-point-overlay-fringe-display '(vertical-bar . vertical-bar))
+(defcustom mdw-point-overlay-fringe-display '(vertical-bar . vertical-bar)
+ "Bitmaps to display in the left and right fringes in the current line."
+ :type '(cons symbol symbol))
(defun mdw-configure-point-overlay ()
(let ((ov (make-overlay 0 0)))
(statement-cont . +)
(statement-case-intro . +)))
-(mdw-define-c-style mdw-trustonic-basic-c (mdw-c)
+(mdw-define-c-style mdw-trustonic-c (mdw-c)
(c-basic-offset . 4)
+ (c-offsets-alist (access-label . -2)))
+
+(mdw-define-c-style mdw-trustonic-alec-c (mdw-trustonic-c)
(comment-column . 0)
(c-indent-comment-alist (anchored-comment . (column . 0))
(end-block . (space . 1))
(cpp-end-block . (space . 1))
(other . (space . 1)))
- (c-offsets-alist (access-label . -2)))
-
-(mdw-define-c-style mdw-trustonic-c (mdw-trustonic-basic-c)
(c-offsets-alist (arglist-cont-nonempty . mdw-c-indent-arglist-nested)))
(defun mdw-set-default-c-style (modes style)
(setq-default cperl-indent-level 2
cperl-continued-statement-offset 2
+ cperl-indent-region-fix-constructs nil
cperl-continued-brace-offset 0
cperl-brace-offset -2
cperl-brace-imaginary-offset 0
;; Miscellaneous fiddling.
(mdw-standard-fill-prefix "\\([ \t]*#+[ \t]*\\)")
(setq indent-tabs-mode nil)
+ (set (make-local-variable 'forward-sexp-function) nil)
;; Now define fontification things.
(make-local-variable 'font-lock-keywords)
;;;--------------------------------------------------------------------------
;;; HTML, CSS, and other web foolishness.
-(setq-default css-indent-offset 2)
+(setq-default css-indent-offset 8)
;;;--------------------------------------------------------------------------
;;; SGML hacking.
;;;--------------------------------------------------------------------------
;;; Configuration files.
-(defvar mdw-conf-quote-normal nil
- "*Control syntax category of quote characters `\"' and `''.
+(defcustom mdw-conf-quote-normal nil
+ "Control syntax category of quote characters `\"' and `''.
If this is `t', consider quote characters to be normal
punctuation, as for `conf-quote-normal'. If this is `nil' then
leave quote characters as quotes. If this is a list, then
consider the quote characters in the list to be normal
punctuation. If this is a single quote character, then consider
-that character only to be normal punctuation.")
+that character only to be normal punctuation."
+ :type '(choice boolean character (repeat character))
+ :safe 'mdw-conf-quote-normal-acceptable-value-p)
(defun mdw-conf-quote-normal-acceptable-value-p (value)
"Is the VALUE is an acceptable value for `mdw-conf-quote-normal'?"
(or (booleanp value)
(every (lambda (v) (memq v '(?\" ?')))
(if (listp value) value (list value)))))
-(put 'mdw-conf-quote-normal 'safe-local-variable
- 'mdw-conf-quote-normal-acceptable-value-p)
(defun mdw-fix-up-quote ()
"Apply the setting of `mdw-conf-quote-normal'."
;; Special indentation.
-(defvar mdw-lisp-loop-default-indent 2)
-(defvar mdw-lisp-setf-value-indent 2)
+(defcustom mdw-lisp-loop-default-indent 2
+ "Default indent for simple `loop' body."
+ :type 'integer
+ :safe 'integerp)
+(defcustom mdw-lisp-setf-value-indent 2
+ "Default extra indent for `setf' values."
+ :type 'integer :safe 'integerp)
(setq lisp-simple-loop-indentation 0
lisp-loop-keyword-indentation 0
(current-column))))
;; Don't really care about this.
- (when (and (eq lisp-indent-backquote-substitution-mode 'corrected))
+ (when (and (boundp 'lisp-indent-backquote-substitution-mode)
+ (eq lisp-indent-backquote-substitution-mode 'corrected))
(save-excursion
(goto-char (elt state 1))
(cl-incf loop-indentation
(setq ad-return-value
(list
- (cond ((not (lisp-extended-loop-p (elt state 1)))
+ (cond ((condition-case ()
+ (save-excursion
+ (goto-char (elt state 1))
+ (forward-char 1)
+ (forward-sexp 2)
+ (backward-sexp 1)
+ (not (looking-at "\\(:\\|\\sw\\)")))
+ (error nil))
(+ baseline-indent lisp-simple-loop-indentation))
((looking-at "^\\s-*\\(:?\\sw+\\|;\\)")
(+ baseline-indent lisp-loop-keyword-indentation))
;; SLIME setup.
-(defvar mdw-friendly-name "[mdw]"
- "How I want to be addressed.")
+(defcustom mdw-friendly-name "[mdw]"
+ "How I want to be addressed."
+ :type 'string
+ :safe 'stringp)
(defadvice slime-user-first-name
(around mdw-use-friendly-name compile activate)
(if mdw-friendly-name (setq ad-return-value mdw-friendly-name)
ad-do-it))
-(trap
- (if (not mdw-fast-startup)
- (progn
- (require 'slime-autoloads)
- (slime-setup '(slime-autodoc slime-c-p-c)))))
+(eval-and-compile
+ (trap
+ (if (not mdw-fast-startup)
+ (progn
+ (require 'slime-autoloads)
+ (slime-setup '(slime-autodoc slime-c-p-c))))))
(let ((stuff '((cmucl ("cmucl"))
(sbcl ("sbcl") :coding-system utf-8-unix)
(auto-fill-mode -1)
(setq tab-width 8))
+(defun comint-send-and-indent ()
+ (interactive)
+ (comint-send-input)
+ (and mdw-auto-indent
+ (indent-for-tab-command)))
+
+(defadvice comint-line-beginning-position
+ (around mdw-calculate-it-properly () activate compile)
+ "Calculate the actual line start for multi-line input."
+ (if (or comint-use-prompt-regexp
+ (eq (field-at-pos (point)) 'output))
+ ad-do-it
+ (setq ad-return-value
+ (constrain-to-field (line-beginning-position) (point)))))
+
(defun term-send-meta-right () (interactive) (term-send-raw-string "\e\e[C"))
(defun term-send-meta-left () (interactive) (term-send-raw-string "\e\e[D"))
(defun term-send-ctrl-uscore () (interactive) (term-send-raw-string "\C-_"))
(interactive "sHost: ")
(ansi-term (list "ssh" host) (format "ssh@%s" host)))
-(defvar git-grep-command
+(defcustom git-grep-command
"env GIT_PAGER=cat git grep --no-color -nH -e "
- "*The default command for \\[git-grep].")
+ "The default command for \\[git-grep]."
+ :type 'string)
(defvar git-grep-history nil)
magit-diff-refresh-popup
magit-diff-mode-refresh-popup
magit-revision-mode-refresh-popup))
- (magit-define-popup-switch popup ?R "Reverse diff" "-R"))))
+ (magit-define-popup-switch popup ?R "Reverse diff" "-R"))
+ (magit-define-popup-switch 'magit-rebase-popup ?r
+ "Rebase merges" "--rebase-merges")))
(defadvice magit-wip-commit-buffer-file
(around mdw-just-this-buffer activate compile)
"Don't make windows dedicated. Seriously."
(set-window-dedicated-p (or window (selected-window)) nil))
+;;;--------------------------------------------------------------------------
+;;; SQL stuff.
+
+(setq sql-postgres-options '("-n" "-P" "pager=off")
+ sql-postgres-login-params
+ '((user :default "mdw")
+ (database :default "mdw")
+ (server :default "db.distorted.org.uk")))
+
;;;--------------------------------------------------------------------------
;;; Man pages.