;;; init.el --- A (reasonably) minimal init file for Emacs. -*- lexical-binding: t; -*- ;;; Commentary: ;;; Code: ;; ---------------------------------------------------------------------------- ;; Manage packages via `use-package`. ;; https://github.com/jwiegley/use-package (require 'package) (setq package-enable-at-startup nil) (setq package-archives '(("gnu" . "https://elpa.gnu.org/packages/") ("melpa" . "https://melpa.org/packages/") ("stable" . "https://stable.melpa.org/packages/"))) (unless (package-installed-p 'use-package) (package-refresh-contents) (package-install 'use-package)) ;; ---------------------------------------------------------------------------- ;; Define some simple helper functions for loading user-defined configuration ;; files. Load all configuration files for third-party packages and language ;; support. (defconst user-init-dir "~/.emacs.d/") (defun load-user-file (file) "Load FILE in the current user's configuration directory. File names which are prefixed with an underscore and/or which do not have the extension '.el' will be ignored." (interactive "f") (setq file-name (file-name-nondirectory file)) (when (and (string-suffix-p ".el" file-name) (not (string-prefix-p "_" file-name))) (load-file (expand-file-name file user-init-dir)))) (defun load-user-dir (dir) "Recursively load all files in directory DIR. DIR should be relative to the user's configuration directory." (interactive "f") (setq config-dir (file-name-concat user-init-dir dir)) (dolist (file (directory-files-recursively config-dir "")) (load-user-file file))) (load-user-dir "pkg") (load-user-dir "lang") ;; ---------------------------------------------------------------------------- ;; Configure how and where backup files are created. (setq backup-directory-alist '(("." . "~/.emacs.d/backup")) backup-by-copying t ; Don't delink hardlinks version-control t ; Use version numbers on backups delete-old-versions t ; Automatically delete excess backups kept-new-versions 20 ; How many of the newest versions to keep kept-old-versions 5 ; How many of the oldest versions to keep ) ;; ---------------------------------------------------------------------------- ;; Interface settings: ;; - Open new windows to the right, not on the bottom ;; - Don't use double-spaces after periods ;; - Use unicode ellipses ;; - Don't require full yes/no answers, allow y/n instead ;; - Hide the menu bar ;; - Make it easier to move between windows. Windows can be navigated using ;; in combination with the arrow keys (setq split-height-threshold nil split-width-threshold 0 sentence-end-double-space nil truncate-string-ellipsis "…") (fset 'yes-or-no-p 'y-or-n-p) (menu-bar-mode -1) (setq windmove-wrap-around t) (windmove-default-keybindings) ;; ---------------------------------------------------------------------------- ;; Mode line configuration: ;; - Hide the frame identifier ;; - Display the column and line numbers of the cursor ;; - Display the file size (setq mode-line-frame-identification " ") (column-number-mode) (size-indication-mode) ;; ---------------------------------------------------------------------------- ;; Editor configuration: ;; - Scroll line-by-line, rather than jumping around haphazardly ;; - Automatically reload files if modified outside of the editor ;; - Overwrite selected text when typing ;; - Display line numbers ;; - Prettify symbols (eg. lambda -> λ) ;; - Enable mouse support ;; - Display a ruler in the 80th column ;; - Make sure that UTF-8 is *ALWAYS* the default encoding (setq scroll-conservatively 10000 scroll-margin 0 scroll-preserve-screen-position 1) (global-auto-revert-mode) (delete-selection-mode) (global-display-line-numbers-mode) (global-prettify-symbols-mode) (xterm-mouse-mode +1) (setq-default display-fill-column-indicator-column 80) (add-hook 'prog-mode-hook #'display-fill-column-indicator-mode) (add-hook 'text-mode-hook #'display-fill-column-indicator-mode) (set-charset-priority 'unicode) (prefer-coding-system 'utf-8-unix) ;; ---------------------------------------------------------------------------- ;; Whitespace settings: ;; - Tabs are 4 space characters (as the gods intended) ;; - Ensure a newline character is present at the end files when saving ;; - Clean up extraneous whitespace when saving (setq-default indent-tabs-mode nil tab-width 4 require-final-newline t) (add-hook 'before-save-hook 'whitespace-cleanup) ;; ---------------------------------------------------------------------------- ;; Dired-mode configuration: ;; - Show human-readable file sizes in dired mode ;; - On macOS, `ls` does not support the `--dired` option (setq dired-listing-switches "-alh") (when (string= system-type "darwin") (setq dired-use-ls-dired nil)) ;; ---------------------------------------------------------------------------- ;; Diminish some built-in modes that we don't really care about. (add-hook 'eldoc-mode-hook (lambda () (diminish 'eldoc-mode))) (add-hook 'hs-minor-mode-hook (lambda () (diminish 'hs-minor-mode))) ;; ---------------------------------------------------------------------------- ;; Custom key-bindings. ;; Globally un-set "C-z", which suspends Emacs by default. (global-unset-key (kbd "C-z")) ;; Enable code folding in programming modes, and set some more reasonable ;; shortcuts. (add-hook 'prog-mode-hook #'hs-minor-mode) (global-set-key (kbd "C-c C-h") (kbd "C-c @ C-h")) ; Hide a block (global-set-key (kbd "C-c C-s") (kbd "C-c @ C-s")) ; Show a block ;; ---------------------------------------------------------------------------- ;; WARNING: Don't touch anything after this comment! (custom-set-variables ;; custom-set-variables was added by Custom. ;; If you edit it by hand, you could mess it up, so be careful. ;; Your init file should contain only one such instance. ;; If there is more than one, they won't work right. '(git-gutter:added-sign " +") '(git-gutter:deleted-sign " -") '(git-gutter:modified-sign " *") '(package-selected-packages nil)) (custom-set-faces ;; custom-set-faces was added by Custom. ;; If you edit it by hand, you could mess it up, so be careful. ;; Your init file should contain only one such instance. ;; If there is more than one, they won't work right. ) (provide 'init) ;;; init.el ends here