;;; -*- lexical-binding: t; -*- ;;; No limit in printing, since I oft want to print the results of ;;; evaluating expressions. (set 'eval-expression-print-length nil) ;; A value of nil means no limit. (set 'eval-expression-print-level nil) ;; A value of nil means no limit. ;;; resize horizontally (set 'fit-window-to-buffer-horizontally t) ;;; Important in order to read passwords (setq epg-pinentry-mode 'loopback) ;;; disable some default modes (tool-bar-mode -1) (menu-bar-mode -1) (scroll-bar-mode -1) (blink-cursor-mode -1) ;;; I use one single space to end a sentence. (set 'sentence-end-double-space nil) ;;; Say y instead of yes (fset 'yes-or-no-p 'y-or-n-p) ;;; Recursive minibuffers is almost indispensable for me. (set 'enable-recursive-minibuffers t) ;;; Use spaces instead of tabs (set-default 'indent-tabs-mode nil) ;;; Don't make noise when saving files (setq save-silently t) ;;; no title on the frame (setq frame-title-format "" icon-title-format "") ;;; major mode of the scratch buffer (set 'initial-major-mode 'emacs-lisp-mode) ;;; echo quickly (setq echo-keystrokes 0.002) ;;; Scroll conservatively please (setq scroll-conservatively 30) ;;; remember my minibuffer (require 'savehist) (set 'savehist-file (expand-file-name "savehist" load-file-directory)) (set 'history-length 1024) (set 'history-delete-duplicates t) (set 'savehist-save-minibuffer-history t) (savehist-mode) ;;; a large file threshold (set 'large-file-warning-threshold (* 1024 1024 1024)) ;;; don't use a GUI dialog box as that is distracting to me (setq use-dialog-box nil) ;;; don't make noise ;;; and when two buffers have the same base name, include more parts to distinguish them (setq uniquify-buffer-name-style 'forward ring-bell-function #'ignore visible-bell nil) ;;; mac specific settings (setq ns-right-alternate-modifier 'none ns-pop-up-frames nil ns-use-native-fullscreen nil ns-use-proxy-icon nil) ;;; where to find the C source code of Emacs. (setq find-function-C-source-directory "/Users/durand/w.emacs.d/emacs/src/") ;;; frame parameters (setq initial-frame-alist '((width . 118))) (set-frame-width nil 118) (add-to-list 'default-frame-alist '(width . 118)) (add-to-list 'default-frame-alist '(height . 35)) (add-to-list 'default-frame-alist '(font . "Droid Sans Mono for Powerline-20")) (add-to-list 'default-frame-alist '(ns-transparent-titlebar . t)) (add-to-list 'default-frame-alist '(ns-appearance . dark)) (add-to-list 'default-frame-alist '(fullscreen . maximized)) (setq frame-resize-pixelwise t) (setq revert-without-query '(".*")) (set-face-attribute 'variable-pitch nil :family "Avenir" :height 1.0) ;;; Adjust default size ;;;###autoload (defvar durand-frame-width-pixel 1420 "Default frame width in pixels. Set the frame to this width in order to fill my screen.") ;;;###autoload (defvar durand-frame-height-pixel 842 "Default frame height in pixels. Set the frame to this height in order to fill my screen.") ;;;###autoload (defun durand-adjust-font-size (delta) "Increase the default font size by DELTA. If DELTA is negative, decrease the size by (- DELTA). This will maintain the frame's width and height as well." (let* ((width durand-frame-width-pixel) (height durand-frame-height-pixel) (current-font (face-attribute 'default :font)) (font-name (aref (query-font current-font) 0)) (current-height (progn (string-match "[[:alpha:]-*]+\\([[:digit:]]+\\)" font-name) (string-to-number (match-string 1 font-name)))) (new-name (replace-match (number-to-string (+ delta current-height)) nil nil font-name 1))) (set-face-attribute 'default nil :font new-name) (set-frame-width (selected-frame) width nil t) (set-frame-height (selected-frame) height nil t))) (durand-hide-minor-mode buffer-face-mode face-remap " BF") ;;; disable line numbers, as that is a performace killer for me. (setq-default display-line-numbers-type nil) (global-display-line-numbers-mode -1) ;;; display-buffer-alist (setq display-buffer-alist `((,(rx (seq bos "*Help*" eos)) (display-buffer-in-side-window) (side . bottom) (slot . 1) (window-height . 0.37)) (,(rx (seq bos "*Messages*" eos)) (display-buffer-in-side-window) (side . bottom) (slot . -1) (window-height . 0.37)) (,(rx (seq bos "magit: ")) (display-buffer-same-window)) (,(rx (seq bos "*Flymake")) (display-buffer-at-bottom) (window-height . 0.2)) (,(rx (seq bos "*Man " (one-or-more not-newline) "*" eos)) (display-buffer-in-tab durand-display-in-one-window) (tab-name . "man page")))) ;;; Custom kill buffer function ;;;###autoload (defun durand-kill-current-buffer (&optional arg) "Kill the current buffer. If the optional ARG is non-nil, and if there are more than one window, then also delete the selected window." (interactive "P") (cond ((window-minibuffer-p (selected-window)) ;; this is the same as calling `abort-recursive-edit'. (throw 'exit t)) (t (kill-buffer (current-buffer)))) (cond ((and arg (not (one-window-p t))) (delete-window (selected-window))))) (define-key global-map (vector ?\s-k) #'durand-kill-current-buffer) ;;; Repeating pops ;;;###autoload (setq set-mark-command-repeat-pop t) ;;; I prefer going to the top first. ;; But I don't really like always going to the top. I am still ;; thinking about solutions. (setq recenter-positions (list 'middle 'top 'bottom)) ;;; Pulse the current line ;;;###autoload (defface prot-pulse-line '((default :extend t) (((class color) (min-colors 88) (background light)) :background "#8eecf4") (((class color) (min-colors 88) (background dark)) :background "#004065") (t :inverse-video t)) "Default face for `durand-pulse-pulse-line'. I stole from Protesilaos' dotemacs.") (require 'pulse) ;;;###autoload (defun durand-pulse-pulse-line (&optional face) "Temporarily highlight the current line with optional FACE." (interactive) (let ((start (cond ((= (point) (point-max)) (save-excursion (forward-line -1) (point))) ((save-excursion (forward-line 0) (point))))) (end (save-excursion (forward-line 1) (point))) (pulse-delay .04) (face (or face 'prot-pulse-line))) (pulse-momentary-highlight-region start end face))) (define-key global-map (vector 's-escape) #'durand-pulse-pulse-line) ;;;###autoload (defun durand-pulse-recenter-top () "Recenter to the top and pulse the line." (interactive) (recenter 0) (durand-pulse-pulse-line)) ;;; auto-fill for texts (set 'adaptive-fill-mode t) (add-hook 'text-mode-hook #'auto-fill-mode) ;;; Hide auto-fill mode in the mode line. ;; The original value is " Fill" (durand-hide-minor-mode auto-fill-function) ;;; Hide auto-revert-mode ;; The original is auto-revert-mode-text (durand-hide-minor-mode auto-revert-mode autorevert) ;;; enable all commands (set 'disabled-command-function nil) ;;; Comments relateed (require 'newcomment) (set 'comment-empty-lines nil) (set 'comment-fill-column nil) (set 'comment-multi-line t) (set 'comment-style 'multi-line) ;;; Toggle line numbers (define-key global-map (vector 'f9) #'durand-display-line-numbers) ;;;###autoload (defun durand-display-line-numbers (&optional arg) "Display absolute line numbers or not. With a positive ARG, display in relative style. With a negative ARG, display in visual style. With zero ARG, disable line numbers. See `display-line-numbers' for details." (interactive "P") (setq display-line-numbers (cond ((null arg) (not display-line-numbers)) ((> (prefix-numeric-value arg) 0) 'relative) ((< (prefix-numeric-value arg) 0) 'visual)))) ;;; Windows ;;;###autoload (defun durand-enlarge-window (&optional delta horizontal) "Make the seleted window DELTA lines taller. This is a thin wrapper around the default `enlarge-window'. If DELTA is nil, it defaults to 1. If HORIZONTAL is non-nil, this will make the seleted window DELTA lines wider instead. If DELTA is negative, shrink instead of enlarge. Also, if DELTA is 0, then maximize the selected window." (interactive "P") (cond ((eq delta 0) (enlarge-window (cond (horizontal (frame-width)) ((frame-height))) horizontal)) ((enlarge-window (prefix-numeric-value delta) horizontal)))) ;;;###autoload (defun durand-shrink-window (&optional delta horizontal) "Make the seleted window DELTA lines smaller. This is a thin wrapper around the default `shrink-window'. If DELTA is nil, it defaults to 1. If HORIZONTAL is non-nil, this will make the seleted window DELTA lines smaller instead. If DELTA is negative, enlarge instead of shrink. Also, if DELTA is 0, then minimize the selected window." (interactive "p") (cond ((eq delta 0) (shrink-window (cond (horizontal (frame-width)) ((frame-height))) horizontal)) ((shrink-window (prefix-numeric-value delta) horizontal)))) ;;;###autoload (defun durand-enlarge-window-horizontally (&optional delta) "Make selected window DELTA columns wider. This is a thin wrapper around the default `enlarge-window-horizontally'. DELTA defaults to 1. If DELTA is 0, then maximize the selected window horizontally." (interactive "p") (cond ((eq delta 0) (enlarge-window-horizontally (frame-width))) ((enlarge-window-horizontally (prefix-numeric-value delta))))) ;;;###autoload (defun durand-shrink-window-horizontally (&optional delta) "Make selected window DELTA columns wider. This is a thin wrapper around the default `shrink-window-horizontally'. DELTA defaults to 1. If DELTA is 0, then maximize the selected window horizontally." (interactive "p") (cond ((eq delta 0) (shrink-window-horizontally (frame-width))) ((shrink-window-horizontally (prefix-numeric-value delta))))) (define-key global-map (vector ?\s-o) #'other-window) (define-key global-map (vector ?\s-&) #'delete-other-windows) (define-key global-map (vector ?\s-é) #'split-window-below) ;; The following binds the key ?\s-" represented as a number, since ;; otherwise it would be interpreted as a string quote. (define-key global-map (vector 8388642) #'split-window-right) (define-key global-map (vector ?\s-à) #'delete-window) (define-key global-map (vector ?\C-+) #'durand-enlarge-window) (define-key global-map (vector ?\C-=) #'durand-shrink-window) (define-key global-map (vector ?\C-x ?\{) #'durand-shrink-window-horizontally) (define-key global-map (vector ?\C-x ?\}) #'durand-enlarge-window-horizontally) (define-key global-map (vector ?\s-f) #'find-file) (define-key global-map (vector ?\s-F) #'find-file-other-window) (define-key global-map (vector ?\s-d) #'dired) (define-key global-map (vector ?\s-D) #'dired-other-window) (define-key global-map (vector ?\s-v) #'durand-focus-completion-or-minibuffer) ;; I like to use winner mode now (require 'winner) (winner-mode 1) ;;; Escape triggers super (define-key input-decode-map (vector 27) nil) (define-key input-decode-map (vector 27) #'event-apply-control-modifier) (define-key key-translation-map (vector 27) #'event-apply-control-modifier) ;;; Don't ask me to confirm! ;;;###autoload (defun durand-bookmark-completing-read (prompt &optional default) "Prompting with PROMPT, read a bookmark name in completion. PROMPT will get a \": \" stuck on the end no matter what, so you probably don't want to include one yourself. Optional arg DEFAULT is a string to return if the user input is empty. If DEFAULT is nil then return empty string for empty input. Don't ask me to confirm my choice. --- Durand" (bookmark-maybe-load-default-file) ; paranoia (if (listp last-nonmenu-event) (bookmark-menu-popup-paned-menu t prompt (if bookmark-sort-flag (sort (bookmark-all-names) 'string-lessp) (bookmark-all-names))) (let* ((completion-ignore-case bookmark-completion-ignore-case) (default (unless (equal "" default) default)) (prompt (concat prompt (if default (format " (%s): " default) ": ")))) (completing-read prompt (lambda (string pred action) (if (eq action 'metadata) '(metadata (category . bookmark)) (complete-with-action action bookmark-alist string pred))) nil t nil 'bookmark-history default)))) (advice-add 'bookmark-completing-read :override #'durand-bookmark-completing-read) (define-key global-map (vector ?\s-Z) #'undo-only) ;;; Save close ;;;###autoload (defun durand-confirm-execute (fun &rest args) "Ask for confirmation to execute FUN with ARGS." (cond ((y-or-n-p (format "Sure to execute %S" this-command)) (apply fun args)) ((message "No need to thank me. :-)")))) (advice-add #'save-buffers-kill-terminal :around #'durand-confirm-execute) ;;; Package management ;;;###autoload (defvar package-dir "/Users/durand/elisp_packages/" "The directory containing packages.") ;;;###autoload (defmacro use-package (package-path package-name &rest configs) "Add PACKAGE-PATH to `load-path' and require PACKAGE-NAME. The remaining CONFIGS are evaluated after the package is loaded." (declare (indent 2) (debug defun)) `(progn (add-to-list 'load-path (expand-file-name ,package-path ,package-dir)) (require ,package-name) ,@configs))