el/dot-emacs.el: Unbreak `mdw-fontify-rust' so this file actually compiles.
[profile] / el / dot-emacs.el
index 12c3b21..ac57d78 100644 (file)
@@ -87,15 +87,16 @@ This may be at the expense of cool features.")
 ;; If individual bits of this file go tits-up, we don't particularly want
 ;; the whole lot to stop right there and then, because it's bloody annoying.
 
-(defmacro trap (&rest forms)
-  "Execute FORMS without allowing errors to propagate outside."
-  (declare (indent 0)
-          (debug t))
-  `(condition-case err
-       ,(if (cdr forms) (cons 'progn forms) (car forms))
-     (error (message "Error (trapped): %s in %s"
-                    (error-message-string err)
-                    ',forms))))
+(eval-and-compile
+  (defmacro trap (&rest forms)
+    "Execute FORMS without allowing errors to propagate outside."
+    (declare (indent 0)
+            (debug t))
+    `(condition-case err
+        ,(if (cdr forms) (cons 'progn forms) (car forms))
+       (error (message "Error (trapped): %s in %s"
+                      (error-message-string err)
+                      ',forms)))))
 
 ;; Configuration reading.
 
@@ -252,6 +253,18 @@ fringes is not taken out of the allowance for WIDTH, unlike
       (other-window 1))
     (select-window win)))
 
+(defun mdw-frame-width-quantized-p (frame-width column-width)
+  "Return whether the FRAME-WIDTH was chosen specifically for COLUMN-WIDTH."
+  (let ((sb-width (mdw-horizontal-window-overhead)))
+    (zerop (mod (+ frame-width sb-width)
+               (+ column-width sb-width)))))
+
+(defun mdw-frame-width-for-columns (columns width)
+  "Return the preferred width for a frame with so many COLUMNS of WIDTH."
+  (let ((sb-width (mdw-horizontal-window-overhead)))
+    (- (* columns (+ width sb-width))
+       sb-width)))
+
 (defun mdw-set-frame-width (columns &optional width)
   "Set the current frame to be the correct width for COLUMNS columns.
 
@@ -261,11 +274,9 @@ can be set interactively with a prefix argument.)"
 P")
   (setq width (if width (prefix-numeric-value width)
                (mdw-preferred-column-width)))
-  (let ((sb-width (mdw-horizontal-window-overhead)))
-    (set-frame-width (selected-frame)
-                    (- (* columns (+ width sb-width))
-                       sb-width))
-    (mdw-divvy-window width)))
+  (set-frame-width (selected-frame)
+                  (mdw-frame-width-for-columns columns width))
+  (mdw-divvy-window width))
 
 (defcustom mdw-frame-width-fudge
   (cond ((<= emacs-major-version 20) 1)
@@ -662,30 +673,48 @@ Evil key bindings are defined in `mdw-evil-keymap-keys'."
 (defvar mdw-designated-window nil
   "The window chosen by `mdw-designate-window', or nil.")
 
-(defun mdw-designate-window (cancel)
-  "Use the selected window for the next pop-up buffer.
-With a prefix argument, clear the designated window."
-  (interactive "P")
-  (cond (cancel
-        (setq mdw-designated-window nil)
-        (message "Window designation cleared."))
-       (t
-        (setq mdw-designated-window (selected-window))
-        (message "Window designated."))))
+(defun mdw-designated-window-display-buffer-function (buffer not-this-window)
+  "Display buffer function to use the designated window."
+  (unless mdw-designated-window (error "No designated window!"))
+  (prog1 mdw-designated-window
+    (with-selected-window mdw-designated-window (switch-to-buffer buffer))
+    (setq mdw-designated-window nil
+         display-buffer-function nil)))
 
 (defun mdw-display-buffer-in-designated-window (buffer alist)
   "Display function to use the designated window."
   (prog1 mdw-designated-window
     (when mdw-designated-window
-      (select-window mdw-designated-window)
-      (switch-to-buffer buffer nil t))
+      (with-selected-window mdw-designated-window
+       (switch-to-buffer buffer nil t)))
     (setq mdw-designated-window nil)))
 
-(setq display-buffer-base-action
-      (let* ((action display-buffer-base-action)
-            (funcs (car action))
-            (alist (cdr action)))
-       (cons (cons 'mdw-display-buffer-in-designated-window funcs) alist)))
+(defun mdw-designate-window (cancel)
+  "Use the selected window for the next pop-up buffer.
+With a prefix argument, clear the designated window."
+  (interactive "P")
+  (let ((window (selected-window)))
+    (cond (cancel
+          (setq mdw-designated-window nil)
+          (unless (mdw-emacs-version-p 24)
+            (setq display-buffer-function nil))
+          (message "Window designation cleared."))
+         ((window-dedicated-p window)
+          (error "Window is dedicated to its buffer."))
+         (t
+          (setq mdw-designated-window window)
+          (unless (mdw-emacs-version-p 24)
+            (setq display-buffer-function
+                    #'mdw-designated-window-display-buffer-function))
+          (message "Window designated.")))))
+
+(when (mdw-emacs-version-p 24)
+  (setq display-buffer-base-action
+         (let* ((action display-buffer-base-action)
+                (funcs (car action))
+                (alist (cdr action)))
+           (cons (cons 'mdw-display-buffer-in-designated-window funcs)
+                 alist))))
 
 (defun mdw-clobber-other-windows-showing-buffer (buffer-or-name)
   "Arrange that no windows on other frames are showing BUFFER-OR-NAME."
@@ -728,6 +757,70 @@ Pretend they don't exist.  They might be on other display devices."
 (setq even-window-sizes nil
       even-window-heights nil)
 
+(setq display-buffer-reuse-frames nil)
+
+(defun mdw-last-window-in-frame-p (window)
+  "Return whether WINDOW is the last in its frame."
+  (catch 'done
+    (while window
+      (let ((next (window-next-sibling window)))
+       (while (and next (window-minibuffer-p next))
+         (setq next (window-next-sibling next)))
+       (if next (throw 'done nil)))
+      (setq window (window-parent window)))
+    t))
+
+(defun mdw-display-buffer-in-tolerable-window (buffer alist)
+  "Try finding a tolerable window in which to display BUFFER.
+Begone, foul DWIMmerlaik!
+
+This is all totally subject to arbitrary change in the future, but the
+emphasis is on predictability rather than crazy DWIMmery."
+  (let* ((selected (selected-window)) chosen
+        (full-height-p (window-full-height-p selected))
+        (full-width-p (window-full-width-p selected)))
+    (cond
+
+     ((and full-height-p full-width-p)
+      ;; We're basically the only window in the frame.  If we want to get
+      ;; anywhere, we'll have to split the window.
+
+      (let ((width (window-width selected))
+           (preferred-width (mdw-preferred-column-width)))
+       (if (and (>= width (mdw-frame-width-for-columns 2 preferred-width))
+                (mdw-frame-width-quantized-p width preferred-width))
+           (setq chosen (split-window-right preferred-width))
+         (setq chosen (split-window-below)))
+       (display-buffer-record-window 'window chosen buffer)))
+
+     ((mdw-last-window-in-frame-p selected)
+      ;; This is the last window in the frame.  I don't think I want to
+      ;; clobber the first window, so rebound and clobber the previous one
+      ;; instead.  (This obviously has the same effect if there are only two
+      ;; windows, but seems more useful if there are three.)
+
+      (setq chosen (previous-window selected 'never nil))
+      (display-buffer-record-window 'reuse chosen buffer))
+
+     (t
+      ;; There's another window in front of us.  Let's use that one.
+      (setq chosen (next-window selected 'never nil)))
+      (display-buffer-record-window 'reuse chosen buffer))
+
+    (if (eq chosen selected)
+       (error "Failed to select a different window!"))
+
+    (when chosen
+      (with-selected-window chosen (switch-to-buffer buffer)))
+    chosen))
+
+;; Hack the display actions so that they do something sensible.
+(setq display-buffer-fallback-action
+       '((display-buffer--maybe-same-window
+          display-buffer-reuse-window
+          display-buffer-pop-up-window
+          mdw-display-buffer-in-tolerable-window)))
+
 ;; Rename buffers along with files.
 
 (defvar mdw-inhibit-rename-buffer nil
@@ -1042,8 +1135,8 @@ Use this to arrange for per-server settings."
 (defadvice gnus-other-frame (around mdw-hack-frame-width compile activate)
   "Always arrange for mail/news frames to be 80 columns wide."
   (let ((default-frame-alist (cons `(width . ,(+ 80 mdw-frame-width-fudge))
-                                  (cl-delete 'width default-frame-alist
-                                             :key #'car))))
+                                  (delete* 'width default-frame-alist
+                                           :key #'car))))
     ad-do-it))
 
 ;; Preferred programs.
@@ -1528,8 +1621,8 @@ case."
                        (line-height . 10.55)
                        (space-width . 5.1)
                        (avg-char-width . 5.1)))
-                    (cl-remove 'CourierCondensed ps-font-info-database
-                               :key #'car)))))
+                    (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
@@ -1799,6 +1892,23 @@ doesn't match any of the regular expressions in
   (t :inverse-video t))
 (mdw-define-face viper-search (t :inherit isearch))
 
+(mdw-define-face compilation-error
+  (((class color)) :foreground "red" :weight bold)
+  (t :weight bold))
+(mdw-define-face compilation-warning
+  (((class color)) :foreground "orange" :weight bold)
+  (t :weight bold))
+(mdw-define-face compilation-info
+  (((class color)) :foreground "green" :weight bold)
+  (t :weight bold))
+(mdw-define-face compilation-line-number
+  (t :weight bold))
+(mdw-define-face compilation-column-number
+  (((min-colors 64)) :foreground "lightgrey"))
+(setq compilation-message-face 'mdw-virgin-face)
+(setq compilation-enter-directory-face 'font-lock-comment-face)
+(setq compilation-leave-directory-face 'font-lock-comment-face)
+
 (mdw-define-face holiday-face
   (t :background "red"))
 (mdw-define-face calendar-today-face
@@ -1849,18 +1959,18 @@ doesn't match any of the regular expressions in
   (t :weight bold))
 (mdw-define-face font-lock-variable-name-face
   (t :slant italic))
-(mdw-define-face font-lock-comment-delimiter-face
-  (((min-colors 64)) :slant italic :foreground "SeaGreen1")
-  (((class color)) :foreground "green")
-  (t :weight bold))
 (mdw-define-face font-lock-comment-face
   (((min-colors 64)) :slant italic :foreground "SeaGreen1")
   (((class color)) :foreground "green")
   (t :weight bold))
+(mdw-define-face font-lock-comment-delimiter-face
+  (t :inherit font-lock-comment-face))
 (mdw-define-face font-lock-string-face
   (((min-colors 64)) :foreground "SkyBlue1")
   (((class color)) :foreground "cyan")
   (t :weight bold))
+(mdw-define-face font-lock-doc-face
+  (t :inherit font-lock-string-face))
 
 (mdw-define-face message-separator
   (t :background "red" :foreground "white" :weight bold))
@@ -2229,6 +2339,18 @@ doesn't match any of the regular expressions in
 (add-hook 'post-command-hook 'mdw-update-terminal-title)
 
 ;;;--------------------------------------------------------------------------
+;;; Ediff hacking.
+
+(defvar mdw-ediff-previous-windows)
+(defun mdw-ediff-setup ()
+  (setq mdw-ediff-previous-windows (current-window-configuration)))
+(defun mdw-ediff-suspend-or-quit ()
+  (set-window-configuration mdw-ediff-previous-windows))
+(add-hook 'ediff-before-setup-hook 'mdw-ediff-setup)
+(add-hook 'ediff-quit-hook 'mdw-ediff-suspend-or-quit t)
+(add-hook 'ediff-suspend-hook 'mdw-ediff-suspend-or-quit t)
+
+;;;--------------------------------------------------------------------------
 ;;; C programming configuration.
 
 ;; Make C indentation nice.
@@ -2272,7 +2394,10 @@ indentation anyway."
   (let ((output nil))
     (dolist (item first)
       (let ((key (car item)) (value (cdr item)))
-       (if (string-suffix-p "-alist" (symbol-name key))
+       (if (let* ((key-name (symbol-name key))
+                  (key-len (length key-name)))
+             (and (>= key-len 6)
+                  (string= (subseq key-name (- key-len 6)) "-alist")))
            (push (cons key
                        (mdw-merge-style-alists value
                                                (cdr (assoc key second))))
@@ -2283,7 +2408,7 @@ indentation anyway."
        (push item output)))
     (nreverse output)))
 
-(cl-defmacro mdw-define-c-style (name (&optional parent) &rest assocs)
+(defmacro* mdw-define-c-style (name (&optional parent) &rest assocs)
   "Define a C style, called NAME (a symbol) based on PARENT, setting ASSOCs.
 A function, named `mdw-define-c-style/NAME', is defined to actually install
 the style using `c-add-style', and added to the hook
@@ -3154,7 +3279,8 @@ name, as a symbol."
 
             ;; And anything else is punctuation.
             (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-                  '(0 mdw-punct-face)))))
+                  '(0 mdw-punct-face)))
+           font-lock-syntactic-face-function nil))
 
   ;; Hack key bindings.
   (local-set-key [?{] 'mdw-self-insert-and-indent)
@@ -4833,7 +4959,7 @@ align the other subforms beneath it.  Otherwise, indent them
               (eq lisp-indent-backquote-substitution-mode 'corrected))
       (save-excursion
        (goto-char (elt state 1))
-       (cl-incf loop-indentation
+       (incf loop-indentation
                 (cond ((eq (char-before) ?,) -1)
                       ((and (eq (char-before) ?@)
                             (progn (backward-char)
@@ -5205,6 +5331,11 @@ rather than baking the list into the function."
                      nil))))
 (setq magit-display-buffer-function 'mdw-display-magit-buffer)
 
+(defun mdw-display-magit-file-buffer (buffer)
+  "Show a file buffer from a diff."
+  (select-window (display-buffer buffer)))
+(setq magit-display-file-buffer-function 'mdw-display-magit-file-buffer)
+
 ;;;--------------------------------------------------------------------------
 ;;; GUD, and especially GDB.