;;; core.el -*- lexical-binding: t; -*- ;;; ;;; Author: Jakob L. Kreuze ;;; URL: https://git.sr.ht/~jakob/.emacs.d/ ;;; ;;; Configuration for the "core" behavior of GNU Emacs. Generally, anything ;;; which does not involve a third-party package. ;;; ;; Having Emacs open to `*scratch*' feels as though it's inviting me to punch ;; out some Lisp forms and evaluate them. I like to pretend that my computers ;; are Lisp machines. ;; TODO: Replace with dashboard.el? (setq inhibit-startup-message t inhibit-startup-buffer-menu t initial-scratch-message nil initial-buffer-choice nil) ;; A recurring theme in this configuration file is changing where Emacs packages ;; drop their various state files. 'no-littering.el' is a package that handles ;; this by creating 'var/' and 'etc/' directories in the Emacs directory, but ;; it's implemented in a way that pollutes the global namespace with variables ;; for packages that I don't use, and would require a significant amount of ;; configuration on my part anyway, so I've decided to do this manually, setting ;; relevant variables to subdirectories of XDG_CACHE_HOME and XDG_DATA_HOME. ;; Save backup files to one directory instead of making a mess of the filesystem. (setq backup-directory-alist `(("." . "~/.cache/emacs"))) ;; `auto-save', in addition to the actual files it saves, maintains another file ;; listing the files it's currently taking care of. (setq auto-save-list-file-prefix "~/.cache/emacs/auto-save-list/.saves-") ;; Disable the creation of locking symlinks in the current directory. This is a ;; very opinionated choice, and probably isn't a good idea for most. (setq create-lockfiles nil) ;; I don't use 'custom.el' to set variables, but a few of the packages I use do. ;; This snippet ensures that a massacre is not made of my init.el. (setq custom-file "~/.emacs.d/custom.el") (when (file-exists-p custom-file) (load custom-file)) ;; I don't really care about persisting minibuffer history between sessions. ;; Even if I disable `savehist-mode', it still writes to disk, so the least I ;; can do is move the history file to somewhere that isn't .emacs.d. (savehist-mode -1) (setq savehist-file "~/.cache/emacs/history") (use-package tramp :straight nil :init (setq tramp-backup-directory-alist backup-directory-alist) (setq-default tramp-persistency-file-name "~/.cache/emacs/tramp") ;; Apply recommendations from the following for speeding up Tramp. ;; ;; :init (setq remote-file-name-inhibit-cache nil) (setq vc-ignore-dir-regexp (format "%s\\|%s" vc-ignore-dir-regexp tramp-file-name-regexp)) (setq tramp-verbose 1) ;; Never ask me if I want to save credentials to .authinfo :init (setq auth-source-save-behavior nil)) (use-package nsm :straight nil :init (setq nsm-settings-file "~/.cache/emacs/network-security.data")) ;; Use a consistent confirmation dialog of "y or n". (fset 'yes-or-no-p 'y-or-n-p) ;; Automatically revert buffers and dired listings when something on disk ;; changes. (use-package autorevert :config (global-auto-revert-mode 1) (setq global-auto-revert-non-file-buffers t auto-revert-verbose nil)) ;; "Command attempted to use minibuffer while in minibuffer" gets old fast. (setq enable-recursive-minibuffers t) ;; Select help windows when I pop them so that I can kill them with . (setq help-window-select t) ;; Most *NIX tools work best when files are terminated with a newline. (setq require-final-newline t) ;; Sentences should be separated by a single space. Treat two sentences as such ;; when filling. (setq sentence-end-double-space nil) ;; I use the tab key, but I generally prefer space characters to tabstops and ;; like a four-character width for indentation. (setq-default indent-tabs-mode nil tab-width 4) ;; Modern conventions state that 80 characters is the standard width. (setq-default fill-column 80) ;; When killing, add whatever's in the system clipboard if it isn't there ;; already, so I can get it back with . (setq save-interprogram-paste-before-kill t) ;; Enable the default-disabled functions that I use. (put 'downcase-region 'disabled nil) (put 'upcase-region 'disabled nil) ;; Enable useful visual queues. (column-number-mode t) ;; Unbind and so that I'm not accidentally calling =suspend-frame=. (global-unset-key (kbd "C-z")) (global-unset-key (kbd "C-x C-z")) ;; Replace `kill-word', `backward-kill-word', and `kill-visual-line' with ;; equivalents that do not copy the region into the kill ring. (defun delete-word (arg) "Delete characters forward until encountering the end of a word. With argument ARG, do this that many times." (interactive "p") (delete-region (point) (progn (forward-word arg) (point)))) (defun backward-delete-word (arg) "Delete characters backward until encountering the beginning of a word. With argument ARG, do this that many times." (interactive "p") (delete-word (- arg))) (defun delete-visual-line (&optional arg) "Delete the rest of the visual line. With prefix argument ARG, delete that many visual lines from point. If ARG is negative, delete visual lines backward. If ARG is zero, delete the text before point on the current visual line." (interactive "P") ;; Like in `kill-line', it's better to move point to the other end ;; of the kill before killing. (let ((opoint (point)) (delete-whole-line (and kill-whole-line (bolp)))) (if arg (vertical-motion (prefix-numeric-value arg)) (end-of-visual-line 1) (if (= (point) opoint) (vertical-motion 1) ;; Skip any trailing whitespace at the end of the visual line. ;; We used to do this only if `show-trailing-whitespace' is ;; nil, but that's wrong; the correct thing would be to check ;; whether the trailing whitespace is highlighted. But, it's ;; OK to just do this unconditionally. (skip-chars-forward " \t"))) (delete-region opoint (if (and delete-whole-line (= (following-char) ?\n)) (1+ (point)) (point))))) (bind-key "M-d" #'delete-word) (bind-key "M-DEL" #'backward-delete-word) (bind-key "C-k" #'delete-visual-line) ;; I use and for movement, mostly, so having and ;; bound to the same functions is a little redundant. What I prefer is to bind ;; them to functions for scolling by one line at a time instead. Sometimes ;; useful when perusing IRC logs. (defgroup baby-scroll () "Minor mode for subtle scrolling commands." :group 'convenience) (define-minor-mode baby-scroll-mode "Toggle `baby-scroll-mode'. Minor mode which remaps and to less extreme scrolling functions." :global t :lighter "Baby Scroll" :group 'baby-scroll :keymap '(([next] . scroll-up-line) ([prior] . scroll-down-line)) nil) (baby-scroll-mode) ;; Don't do jerky jumps when the cursor reaches the end of the window. Instead, ;; just scroll by one line. (setq scroll-conservatively most-positive-fixnum)