X-Git-Url: https://git.distorted.org.uk/~mdw/profile/blobdiff_plain/772a7a3be0f3d56dc8f416c50ff91af40949720a..a63efb6728ba8d0fd07a24235755c1345a9b897c:/el/dot-emacs.el diff --git a/el/dot-emacs.el b/el/dot-emacs.el index cd8b407..e290e5a 100644 --- a/el/dot-emacs.el +++ b/el/dot-emacs.el @@ -293,6 +293,56 @@ it's currently off." (or transient-mark-mode (setq transient-mark-mode 'only)) (set-mark (mark t))))) +;; Improved compilation machinery. + +(setq compile-command + (let ((ncpu (with-temp-buffer + (insert-file-contents "/proc/cpuinfo") + (buffer-string) + (count-matches "^processor\\s-*:")))) + (format "make -j%d -k" (* 2 ncpu)))) + +(defun mdw-compilation-buffer-name (mode) + (concat "*" (downcase mode) ": " + (abbreviate-file-name default-directory) "*")) +(setq compilation-buffer-name-function 'mdw-compilation-buffer-name) + +(eval-after-load "compile" + '(progn + (define-key compilation-shell-minor-mode-map "\C-c\M-g" 'recompile))) + +(defun mdw-compile (command &optional directory comint) + "Initiate a compilation COMMAND, maybe in a different DIRECTORY. +The DIRECTORY may be nil to not change. If COMINT is t, then +start an interactive compilation. + +Interactively, prompt for the command if the variable +`compilation-read-command' is non-nil, or if requested through +the prefix argument. Prompt for the directory, and run +interactively, if requested through the prefix. + +Use a prefix of 4, 6, 12, or 14, or type C-u between one and three times, to +force prompting for a directory. + +Use a prefix of 2, 6, 10, or 14, or type C-u three times, to force +prompting for the command. + +Use a prefix of 8, 10, 12, or 14, or type C-u twice or three times, +to force interactive compilation." + (interactive + (let* ((prefix (prefix-numeric-value current-prefix-arg)) + (command (eval compile-command)) + (dir (and (plusp (logand prefix #x54)) + (read-directory-name "Compile in directory: ")))) + (list (if (or compilation-read-command + (plusp (logand prefix #x42))) + (compilation-read-command command) + command) + dir + (plusp (logand prefix #x58))))) + (let ((default-directory (or directory default-directory))) + (compile command comint))) + ;; Functions for sexp diary entries. (defun mdw-not-org-mode (form) @@ -768,6 +818,17 @@ options." (ad-set-arg 0 dir) ad-do-it))) +(defun mdw-dired-run (args &optional syncp) + (interactive (let ((file (dired-get-filename t))) + (list (read-string (format "Arguments for %s: " file)) + current-prefix-arg))) + (funcall (if syncp 'shell-command 'async-shell-command) + (concat (shell-quote-argument (dired-get-filename nil)) + " " args))) + +(eval-after-load "dired" + '(define-key dired-mode-map "X" 'mdw-dired-run)) + ;;;-------------------------------------------------------------------------- ;;; URL viewing. @@ -1239,6 +1300,9 @@ doesn't match any of the regular expressions in (mdw-define-face comint-highlight-input (t nil)) +(mdw-define-face ido-subdir + (t :foreground "cyan" :weight bold)) + (mdw-define-face dired-directory (t :foreground "cyan" :weight bold)) (mdw-define-face dired-symlink @@ -1421,6 +1485,28 @@ doesn't match any of the regular expressions in (mdw-define-face ediff-odd-diff-Ancestor (((class color) (type x)) :background "#320")) +(mdw-define-face magit-hash + (((class color) (type x)) :foreground "grey40") + (((class color) (type tty)) :foreground "blue")) +(mdw-define-face magit-diff-hunk-heading + (((class color) (type x)) :foreground "grey70" :background "grey25") + (((class color) (type tty)) :foreground "yellow")) +(mdw-define-face magit-diff-hunk-heading-highlight + (((class color) (type x)) :foreground "grey70" :background "grey35") + (((class color) (type tty)) :foreground "yellow" :background "blue")) +(mdw-define-face magit-diff-added + (((class color) (type x)) :foreground "#ddffdd" :background "#335533") + (((class color) (type tty)) :foreground "green")) +(mdw-define-face magit-diff-added-highlight + (((class color) (type x)) :foreground "#cceecc" :background "#336633") + (((class color) (type tty)) :foreground "green" :background "blue")) +(mdw-define-face magit-diff-removed + (((class color) (type x)) :foreground "#ffdddd" :background "#553333") + (((class color) (type tty)) :foreground "red")) +(mdw-define-face magit-diff-removed-highlight + (((class color) (type x)) :foreground "#eecccc" :background "#663333") + (((class color) (type tty)) :foreground "red" :background "blue")) + (mdw-define-face dylan-header-background (((class color) (type x)) :background "NavyBlue") (t :background "blue")) @@ -1803,6 +1889,10 @@ name, as a symbol." (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)" '(0 mdw-punct-face)))))) +(define-derived-mode sod-mode c-mode "Sod" + "Major mode for editing Sod code.") +(push '("\\.sod$" . sod-mode) auto-mode-alist) + ;;;-------------------------------------------------------------------------- ;;; AP calc mode. @@ -2341,13 +2431,13 @@ name, as a symbol." (list ;; Handle the keywords defined above. - (list (concat "\\<\\(" rust-keywords "\\)\\>") + (list (concat "\\_<\\(" rust-keywords "\\)\\_>") '(0 font-lock-keyword-face)) - (list (concat "\\<\\(" rust-builtins "\\)\\>") + (list (concat "\\_<\\(" rust-builtins "\\)\\_>") '(0 font-lock-variable-name-face)) ;; Handle numbers too. - (list (concat "\\<\\(" + (list (concat "\\_<\\(" "[0-9][0-9_]*" "\\(" "\\(\\.[0-9_]+\\)?[eE][-+]?[0-9_]+" "\\|" "\\.[0-9_]+" @@ -2359,7 +2449,7 @@ name, as a symbol." "\\|" "0b[01_]+" "\\)" "\\([ui]\\(8\\|16\\|32\\|64\\|s\\|size\\)\\)?" - "\\)\\>") + "\\)\\_>") '(0 mdw-number-face)) ;; And anything else is punctuation. @@ -2544,10 +2634,10 @@ strip numbers instead." (defun mdw-fontify-pyrex () (mdw-fontify-pythonic (mdw-regexps "and" "as" "assert" "break" "cdef" "class" "continue" - "ctypedef" "def" "del" "elif" "else" "except" "exec" + "ctypedef" "def" "del" "elif" "else" "enum" "except" "exec" "extern" "finally" "for" "from" "global" "if" "import" "in" "is" "lambda" "not" "or" "pass" "print" - "raise" "return" "struct" "try" "while" "with" + "property" "raise" "return" "struct" "try" "while" "with" "yield"))) ;;;-------------------------------------------------------------------------- @@ -3072,7 +3162,7 @@ strip numbers instead." (local-set-key [?$] 'self-insert-command) ;; Make `tab' be useful, given that tab stops in TeX don't work well. - (local-set-key "\C-i" 'indent-relative) + (local-set-key "\C-\M-i" 'indent-relative) (setq indent-tabs-mode nil) ;; Set fill prefix. @@ -3591,6 +3681,9 @@ that character only to be normal punctuation.") "\\([ \t]*\\([>#|:] ?\\)*[ \t]*\\)" 3) (auto-fill-mode 1)) +(eval-after-load "flyspell" + '(define-key flyspell-mode-map "\C-\M-i" nil)) + ;;;-------------------------------------------------------------------------- ;;; Outline and hide/show modes. @@ -3668,8 +3761,12 @@ This allows you to pass a list of arguments through `ansi-term'." git-grep-command 'git-grep-history))) (grep command-args)) +;;;-------------------------------------------------------------------------- +;;; Magit configuration. + (setq magit-diff-refine-hunk 'all magit-view-git-manual-method 'man + magit-log-margin '(nil age magit-log-margin-width t 18) magit-wip-after-save-local-mode-lighter "" magit-wip-after-apply-mode-lighter "" magit-wip-before-change-mode-lighter "") @@ -3678,7 +3775,20 @@ This allows you to pass a list of arguments through `ansi-term'." (magit-wip-after-save-mode 1) (magit-wip-after-apply-mode 1) (magit-wip-before-change-mode 1) - (add-to-list 'magit-no-confirm 'safe-with-wip))) + (add-to-list 'magit-no-confirm 'safe-with-wip) + (push '(:eval (if (or magit-wip-after-save-local-mode + magit-wip-after-apply-mode + magit-wip-before-change-mode) + (format " wip:%s%s%s" + (if magit-wip-after-apply-mode "A" "") + (if magit-wip-before-change-mode "C" "") + (if magit-wip-after-save-local-mode "S" "")))) + minor-mode-alist) + (dolist (popup '(magit-diff-popup + magit-diff-refresh-popup + magit-diff-mode-refresh-popup + magit-revision-mode-refresh-popup)) + (magit-define-popup-switch popup ?R "Reverse diff" "-R")))) (setq magit-repolist-columns '(("Name" 16 magit-repolist-column-ident nil) @@ -3714,6 +3824,205 @@ there is sadness." (if (> n 0) 'bold 'shadow)))))) ;;;-------------------------------------------------------------------------- +;;; MPC configuration. + +(eval-when-compile (trap (require 'mpc))) + +(setq mpc-browser-tags '(Artist|Composer|Performer Album|Playlist)) + +(defun mdw-mpc-now-playing () + (interactive) + (require 'mpc) + (save-excursion + (set-buffer (mpc-proc-cmd (mpc-proc-cmd-list '("status" "currentsong")))) + (mpc--status-callback)) + (let ((state (cdr (assq 'state mpc-status)))) + (cond ((member state '("stop")) + (message "mpd stopped.")) + ((member state '("play" "pause")) + (let* ((artist (cdr (assq 'Artist mpc-status))) + (album (cdr (assq 'Album mpc-status))) + (title (cdr (assq 'Title mpc-status))) + (file (cdr (assq 'file mpc-status))) + (duration-string (cdr (assq 'Time mpc-status))) + (time-string (cdr (assq 'time mpc-status))) + (time (and time-string + (string-to-number + (if (string-match ":" time-string) + (substring time-string + 0 (match-beginning 0)) + (time-string))))) + (duration (and duration-string + (string-to-number duration-string))) + (pos (and time duration + (format " [%d:%02d/%d:%02d]" + (/ time 60) (mod time 60) + (/ duration 60) (mod duration 60)))) + (fmt (cond ((and artist title) + (format "`%s' by %s%s" title artist + (if album (format ", from `%s'" album) + ""))) + (file + (format "`%s' (no tags)" file)) + (t + "(no idea what's playing!)")))) + (if (string= state "play") + (message "mpd playing %s%s" fmt (or pos "")) + (message "mpd paused in %s%s" fmt (or pos ""))))) + (t + (message "mpd in unknown state `%s'" state))))) + +(defmacro mdw-define-mpc-wrapper (func bvl interactive &rest body) + `(defun ,func ,bvl + (interactive ,@interactive) + (require 'mpc) + ,@body + (mdw-mpc-now-playing))) + +(mdw-define-mpc-wrapper mdw-mpc-play-or-pause () nil + (if (member (cdr (assq 'state (mpc-cmd-status))) '("play")) + (mpc-pause) + (mpc-play))) + +(mdw-define-mpc-wrapper mdw-mpc-next () nil (mpc-next)) +(mdw-define-mpc-wrapper mdw-mpc-prev () nil (mpc-prev)) +(mdw-define-mpc-wrapper mdw-mpc-stop () nil (mpc-stop)) + +(defun mdw-mpc-louder (step) + (interactive (list (if current-prefix-arg + (prefix-numeric-value current-prefix-arg) + +10))) + (mpc-proc-cmd (format "volume %+d" step))) + +(defun mdw-mpc-quieter (step) + (interactive (list (if current-prefix-arg + (prefix-numeric-value current-prefix-arg) + +10))) + (mpc-proc-cmd (format "volume %+d" (- step)))) + +(defun mdw-mpc-hack-lines (arg interactivep func) + (if (and interactivep (use-region-p)) + (let ((from (region-beginning)) (to (region-end))) + (goto-char from) + (beginning-of-line) + (funcall func) + (forward-line) + (while (< (point) to) + (funcall func) + (forward-line))) + (let ((n (prefix-numeric-value arg))) + (cond ((minusp n) + (unless (bolp) + (beginning-of-line) + (funcall func) + (incf n)) + (while (minusp n) + (forward-line -1) + (funcall func) + (incf n))) + (t + (beginning-of-line) + (while (plusp n) + (funcall func) + (forward-line) + (decf n))))))) + +(defun mdw-mpc-select-one () + (when (and (get-char-property (point) 'mpc-file) + (not (get-char-property (point) 'mpc-select))) + (mpc-select-toggle))) + +(defun mdw-mpc-unselect-one () + (when (get-char-property (point) 'mpc-select) + (mpc-select-toggle))) + +(defun mdw-mpc-select (&optional arg interactivep) + (interactive (list current-prefix-arg t)) + (mdw-mpc-hack-lines arg interactivep 'mdw-mpc-select-one)) + +(defun mdw-mpc-unselect (&optional arg interactivep) + (interactive (list current-prefix-arg t)) + (mdw-mpc-hack-lines arg interactivep 'mdw-mpc-unselect-one)) + +(defun mdw-mpc-unselect-backwards (arg) + (interactive "p") + (mdw-mpc-hack-lines (- arg) t 'mdw-mpc-unselect-one)) + +(defun mdw-mpc-unselect-all () + (interactive) + (setq mpc-select nil) + (mpc-selection-refresh)) + +(defun mdw-mpc-next-line (arg) + (interactive "p") + (beginning-of-line) + (forward-line arg)) + +(defun mdw-mpc-previous-line (arg) + (interactive "p") + (beginning-of-line) + (forward-line (- arg))) + +(defun mdw-mpc-playlist-add (&optional arg interactivep) + (interactive (list current-prefix-arg t)) + (let ((mpc-select mpc-select)) + (when (or arg (and interactivep (use-region-p))) + (setq mpc-select nil) + (mdw-mpc-hack-lines arg interactivep 'mdw-mpc-select-one)) + (setq mpc-select (reverse mpc-select)) + (mpc-playlist-add))) + +(defun mdw-mpc-playlist-delete (&optional arg interactivep) + (interactive (list current-prefix-arg t)) + (setq mpc-select (nreverse mpc-select)) + (mpc-select-save + (when (or arg (and interactivep (use-region-p))) + (setq mpc-select nil) + (mpc-selection-refresh) + (mdw-mpc-hack-lines arg interactivep 'mdw-mpc-select-one)) + (mpc-playlist-delete))) + +(defun mdw-mpc-hack-tagbrowsers () + (setq-local mode-line-format + '("%e" + mode-line-frame-identification + mode-line-buffer-identification))) +(add-hook 'mpc-tagbrowser-mode-hook 'mdw-mpc-hack-tagbrowsers) + +(defun mdw-mpc-hack-songs () + (setq-local header-line-format + ;; '("MPC " mpc-volume " " mpc-current-song) + (list (propertize " " 'display '(space :align-to 0)) + ;; 'mpc-songs-format-description + '(:eval + (let ((deactivate-mark) (hscroll (window-hscroll))) + (with-temp-buffer + (mpc-format mpc-songs-format 'self hscroll) + ;; That would be simpler than the hscroll handling in + ;; mpc-format, but currently move-to-column does not + ;; recognize :space display properties. + ;; (move-to-column hscroll) + ;; (delete-region (point-min) (point)) + (buffer-string))))))) +(add-hook 'mpc-songs-mode-hook 'mdw-mpc-hack-songs) + +(eval-after-load "mpc" + '(progn + (define-key mpc-mode-map "m" 'mdw-mpc-select) + (define-key mpc-mode-map "u" 'mdw-mpc-unselect) + (define-key mpc-mode-map "\177" 'mdw-mpc-unselect-backwards) + (define-key mpc-mode-map "\e\177" 'mdw-mpc-unselect-all) + (define-key mpc-mode-map "n" 'mdw-mpc-next-line) + (define-key mpc-mode-map "p" 'mdw-mpc-previous-line) + (define-key mpc-mode-map "/" 'mpc-songs-search) + (setq mpc-songs-mode-map (make-sparse-keymap)) + (set-keymap-parent mpc-songs-mode-map mpc-mode-map) + (define-key mpc-songs-mode-map "l" 'mpc-playlist) + (define-key mpc-songs-mode-map "+" 'mdw-mpc-playlist-add) + (define-key mpc-songs-mode-map "-" 'mdw-mpc-playlist-delete) + (define-key mpc-songs-mode-map "\r" 'mpc-songs-jump-to))) + +;;;-------------------------------------------------------------------------- ;;; Inferior Emacs Lisp. (setq comint-prompt-read-only t)