From 33c7ddb09e0eae0796686c64ffa022a181145cc1 Mon Sep 17 00:00:00 2001 From: Case Duckworth Date: Wed, 4 Jan 2023 23:21:15 -0600 Subject: Restart ... again ... again --- basics.el | 376 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 376 insertions(+) create mode 100644 basics.el (limited to 'basics.el') diff --git a/basics.el b/basics.el new file mode 100644 index 0000000..06f5ece --- /dev/null +++ b/basics.el @@ -0,0 +1,376 @@ +;;; basics.el --- Super basic Emacs settings -*- lexical-binding: t -*- + +;;; Commentary: + +;; These are the settings that I literally cannot live without. Basic +;; settings, built-in packages, that kind of stuff. Everything else +;; goes in init.el. + +;;; Code: + +;;; Directories + +(defmacro defdir (name directory &optional docstring makedir) + "Define a variable and a function NAME expanding to DIRECTORY. +DOCSTRING is applied to the variable; its default is DIRECTORY's +path. If MAKEDIR is non-nil, the directory and its parents will +be created." + (declare (indent 2) (doc-string 3)) + `(progn + (defvar ,name (expand-file-name ,directory) + ,(concat (or docstring (format "%s" directory)) "\n" + "Defined by `defdir'.")) + (defun ,name (file &optional mkdir) + ,(concat "Expand FILE relative to variable `" (symbol-name name) "'.\n" + "If MKDIR is non-nil, parent directories are created.\n" + "Defined by `defdir'.") + (let ((file-name (expand-file-name + (convert-standard-filename file) ,name))) + (when mkdir + (make-directory (file-name-directory file-name) :parents)) + file-name)) + ,(if makedir + `(make-directory ,directory :parents) + `(unless (file-exists-p ,directory) + (warn "Directory `%s' doesn't exist." ,directory))))) + +(defdir etc/ (locate-user-emacs-file "etc/") + "Where various Emacs files are placed." + :makedir) + +(defdir lisp/ (locate-user-emacs-file "lisp/") + "My bespoke elisp files." + :makedir) +(push lisp/ load-path) + +(defdir sync/ "~/Sync/" + "My Syncthing directory." + :makedir) + +(defdir private/ (sync/ "emacs/private/") + "Private files and stuff." + :makedir) +(push private/ load-path) + +(use-package no-littering + :ensure t :demand t + :preface + (setq-default no-littering-etc-directory etc/ + no-littering-var-directory etc/)) + +;;; Settings + +;; Async +(setq-default async-shell-command-buffer 'new-buffer + async-shell-command-display-buffer nil) + +;; Scrolling +(setq-default auto-hscroll-mode t + auto-window-vscroll nil + fast-but-imprecise-scrolling t + hscroll-margin 1 + hscroll-step 1 + scroll-conservatively 25 + scroll-margin 0 + scroll-preserve-screen-position 1 + scroll-step 1) +(scroll-bar-mode -1) +(horizontal-scroll-bar-mode -1) +(pixel-scroll-precision-mode) + +;; Cursor +(setq-default cursor-in-non-selected-windows 'hollow + cursor-type 'bar + blink-cursor-blinks 1 + blink-cursor-interval 0.25 + blink-cursor-delay 0.25) +(blink-cursor-mode) + +;; Mouse +(setq-default mouse-drag-copy-region t + mouse-wheel-progressive-speed nil + mouse-yank-at-point t) + +;; Dialogs +(unless (boundp 'use-short-answers) + (fset 'yes-or-no-p 'y-or-n-p)) + +(setq-default read-answer-short t + use-dialog-box nil + use-file-dialog nil + use-short-answers t) + +;; Minibuffer +(setq-default completion-ignore-case t + read-buffer-completion-ignore-case t + read-file-name-completion-ignore-case t + completions-detailed t + enable-recursive-minibuffers t + file-name-shadow-properties '(invisible t intangible t) + minibuffer-eldef-shorten-default t + minibuffer-prompt-properties '( read-only t + cursor-intangible t + face minibuffer-prompt)) +(file-name-shadow-mode) +(minibuffer-electric-default-mode) + +(require 'savehist) +(setq-default history-length 1024 + history-delete-duplicates t + ;; savehist-file (etc/ "savehist.el") + savehist-save-minibuffer-history t + savehist-autosave-interval 30) +(savehist-mode) + +;; Undo +(setq-default undo-limit (* 10 1024 1024)) + +;; Killing and yanking +(setq-default kill-do-not-save-duplicates t + kill-read-only-ok t + save-interprogram-paste-before-kill t + yank-pop-change-selection t) +(delete-selection-mode) + +;; Notifying the user +(setq-default echo-keystrokes 0.01 + ring-bell-function #'ignore) + +;; Point and mark +(setq-default set-mark-command-repeat-pop t) + +;; The system +(setq-default read-process-output-max (* 10 1024 1024)) + +;; Startup +(setq-default inhibit-startup-screen t + initial-buffer-choice t + initial-scratch-message nil) + +;; (menu-bar-mode -1) +(tool-bar-mode -1) +(tooltip-mode -1) + +;; Text editing +(setq-default fill-column 80 + sentence-end-double-space t + tab-width 8) +(global-so-long-mode) + +(setq-default show-paren-delay 0.01 + show-paren-style 'parenthesis + show-paren-when-point-in-periphery t + show-paren-when-point-inside-paren t) +(show-paren-mode) +(electric-pair-mode) + +;; Encodings +(set-language-environment "UTF-8") +(setq-default buffer-file-coding-system 'utf-8-unix + coding-system-for-read 'utf-8-unix + coding-system-for-write 'utf-8-unix + default-process-coding-system '(utf-8-unix . utf-8-unix) + locale-coding-system 'utf-8-unix) +(set-charset-priority 'unicode) +(prefer-coding-system 'utf-8-unix) +(set-default-coding-systems 'utf-8-unix) +(set-terminal-coding-system 'utf-8-unix) +(set-keyboard-coding-system 'utf-8-unix) +(pcase system-type + ((or 'ms-dos 'windows-nt) + (set-clipboard-coding-system 'utf-16-le) + (set-selection-coding-system 'utf-16-le)) + (_ + (set-selection-coding-system 'utf-8) + (set-clipboard-coding-system 'utf-8))) + +;; Abbrev +(setq-default abbrev-file-name (sync/ "abbrev.el") + save-abbrevs 'silently) + +;; Files +(setq-default auto-revert-verbose nil + global-auto-revert-non-file-buffers t + create-lockfiles nil + find-file-visit-truename t + mode-require-final-newline t + view-read-only t + save-silently t) +(global-auto-revert-mode) + +(setq-default auto-save-default nil + auto-save-interval 1 + auto-save-no-message t + auto-save-timeout 1 + auto-save-visited-interval 1) +(add-to-list 'auto-save-file-name-transforms + `(".*" ,(etc/ "auto-save/" t) t)) +(auto-save-visited-mode) + +(setq-default backup-by-copying t + version-control t + kept-new-versions 8 + kept-old-versions 8 + delete-old-versions t) + +(require 'recentf) +(setq-default ;; recentf-save-file (etc/ "recentf" t) + recentf-max-menu-items 500 + recentf-max-saved-items nil ; Save the whole list + recentf-auto-cleanup 'mode) +(add-to-list 'recentf-exclude etc/) +(add-to-list 'recentf-exclude "-autoloads.el\\'") +(add-hook 'buffer-list-update-hook #'recentf-track-opened-file) +(recentf-mode) + +(require 'saveplace) +(setq-default ;; save-place-file (etc/ "places.el") + save-place-forget-unreadable-files (eq system-type + 'gnu/linux)) +(save-place-mode) + +(require 'uniquify) +(setq uniquify-after-kill-buffer-p t + uniquify-buffer-name-style 'forward + uniquify-ignore-buffers-re "^\\*" + uniquify-separator path-separator) + +(setq-local vc-follow-symlinks t + vc-make-backup-files t) + +;; Native compilation +(setq-default native-comp-async-report-warnings-errors 'silent + native-comp-deferred-compilation t + native-compile-target-directory (etc/ "eln" t)) +(add-to-list 'native-comp-eln-load-path native-compile-target-directory) +(when (fboundp 'startup-redirect-eln-cache) + (startup-redirect-eln-cache native-compile-target-directory)) + +;; Custom file +(setq-default custom-file (sync/ "emacs/custom.el")) +(define-advice package--save-selected-packages (:around (orig &rest args) no-custom) + "Don't save `package-selected-packages' to `custom-file'." + (let ((custom-file null-device)) + (apply orig args))) + +;; Goto Address +(if (fboundp 'global-goto-address-mode) + (global-goto-address-mode) + (add-hook 'after-change-major-mode-hook #'goto-address-mode)) + +;; Winner +(winner-mode) + +;;; Keybindings + +(defun other-window|switch-buffer (arg) + "Call `other-window' or `switch-buffer' depending on windows. +When called with prefix ARG, unconditionally switch buffer." + (interactive "P") + (if (or arg (one-window-p)) + (switch-to-buffer (other-buffer) nil t) + (other-window 1))) + +(defun delete-window|bury-buffer () + "Delete the current window, or bury the current buffer. +If the current window is the only window, bury the buffer." + (interactive) + (condition-case e + (delete-window) + (t (bury-buffer)))) + +(defun +cycle-spacing (&optional n) + ;; `cycle-spacing' is wildly different in 29.1 over 28. + "Negate N argument on `cycle-spacing'. +That is, with a positive N, deletes newlines as well, leaving -N +spaces. If N is negative, it will not delete newlines and leave +N spaces." + (interactive "*p") + (cycle-spacing (- n))) + +(global-set-key [remap eval-expression] #'pp-eval-expression) +(global-set-key (kbd "M-o") #'other-window|switch-buffer) +(global-set-key (kbd "C-x 0") #'delete-window|bury-buffer) +(global-set-key (kbd "M-SPC") #'+cycle-spacing) +(global-set-key (kbd "C-x C-k") #'kill-this-buffer) + +;;; Hooks + +(add-hook 'after-save-hook #'executable-make-buffer-file-executable-if-script-p) +(add-hook 'find-file-not-found-functions + (defun create-missing-directories () + "Automatically create missing directories." + (let ((target-dir (file-name-directory buffer-file-name))) + (unless (file-exists-p target-dir) + (make-directory target-dir :parents))))) +(add-hook 'find-file-hook + (defun vc-remote-off () + "Turn VC off when remote." + (when (file-remote-p (buffer-file-name)) + (setq-local vc-handled-backends nil)))) + +;;; Advice + +(define-advice switch-to-buffer (:after (&rest _) normal-mode) + "Automatically determine the mode for non-file buffers." + (when-let ((_ (and (eq major-mode 'fundamental-mode))) + (buffer-file-name (buffer-name))) + (normal-mode))) + +(define-advice canonically-space-region + (:around (orig &rest args) double-space-sentences) + "Always double-space sentences canonically." + (let ((sentence-end-double-space t)) + (apply orig args))) + +;; With region or ... +(defun advise-region-or-buffer (&rest _) + "`:before' advice to work on the active region or whole buffer. +See also `with-region-or-buffer'." + (interactive (if mark-active + (list (region-beginning) (region-end)) + (list (point-min) (point-max))))) + +(defun advise-region-or-line (&rest _) + "`:before' advice to work on the active region or whole line. +See also `with-region-or-line'." + (interactive (if mark-active + (list (region-beginning) (region-end)) + (list (line-beginning-position) (line-end-position))))) + +(defun advise-region-or-to-eol (&rest _) + "`:before' advice to work on the active region or to end of line. +See also `with-region-or-to-eol'." + (INTERACTIVE (if mark-active + (list (region-beginning) (region-end)) + (list (point) (line-end-position))))) + +(defmacro with-region-or-buffer (&rest funcs) + "Advise FUNCS with `advise-region-or-buffer'." + `(progn + ,@(cl-loop for fn in funcs + collect + `(advice-add ',fn :before #'advise-region-or-buffer)))) + +(defmacro with-region-or-line (&rest funcs) + "Advise FUNCS with `advise-region-or-line'." + `(progn + ,@(cl-loop for fn in funcs + collect + `(advice-add ',fn :before #'advise-region-or-line)))) + +(defmacro with-region-or-to-eol (&rest funcs) + "Advise FUNCS with `advise-region-or-to-eol'." + `(progn + ,@(cl-loop for fn in funcs + collect + `(advice-add ',fn :before #'advise-region-or-to-eol)))) + +(with-region-or-buffer indent-region) + +;;; Packages + +(use-package _acdw + :load-path private/) + +;;; basics.el ends here -- cgit 1.4.1-21-gabe81