;;; init.el --- basic initial declarations ;;; Commentary: ;; _ _ _ _ ;; (_) _ __ (_)| |_ ___ | | ;; | || '_ \ | || __| / _ \| | ;; | || | | || || |_ _| __/| | ;; |_||_| |_||_| \__|(_)\___||_| ;; ;; '((above text graphic generated with command `figlet -k "init.el"')) ;;; Code: (setq gc-cons-threshold (* 8 5000 5000)) (setq load-prefer-newer t) ; why ever use stale code, ever? ;; Load the files that I put my settings in... (defvar mir-directory (directory-file-name (concat user-emacs-directory (convert-standard-filename "lisp/")))) (add-to-list 'load-path mir-directory t) (require 'mir-defuns) ;; minify yes/no prompts (if (>= (string-to-number emacs-version) 28) (defvar use-short-answers t) (defalias 'yes-or-no-p 'y-or-n-p)) ;; do the things (add-hook 'server-after-make-frame-hook #'mir/graphical-setup) (if (display-graphic-p) (add-hook 'elpaca-after-init-hook #'mir/graphical-setup)) ;; Control backups/swapfiles (defvar backup-directory (expand-file-name "emacs-backups" (or (getenv "XDG_CACHE_HOME") (expand-file-name ".cache" "~")))) (if (not (file-exists-p backup-directory)) (make-directory backup-directory t)) (setq backup-directory-alist `(("." . ,backup-directory))) ;; auto-save-mode doesn't create the path automatically! (defvar auto-save-directory (expand-file-name "tmp/auto-saves/" backup-directory)) (make-directory auto-save-directory t) (setq auto-save-list-file-prefix (expand-file-name "sessions/" auto-save-directory) auto-save-file-name-transforms `((".*" ,auto-save-directory t))) (setq create-lockfiles nil) ;; remove auto-generated bits (setq custom-file (expand-file-name "custom.el" backup-directory)) (if (not (file-exists-p custom-file)) (make-empty-file custom-file t)) (load custom-file) ;; Suppress advice warnings on startup ;; https://andrewjamesjohnson.com/suppressing-ad-handle-definition-warnings-in-emacs/ (setq ad-redefinition-action 'accept) ;; we be moving packages here to see what's slow elsewhere (use-package emacs :custom ;; (scroll-margin 2) (scroll-conservatively 100) ;; (scroll-up-aggressively 0.01) ;; (scroll-down-aggressively 0.01) (auto-window-vscroll nil) :init (global-visual-line-mode t) (set-language-environment "UTF-8") (global-prettify-symbols-mode 1) (auto-insert-mode)) (use-package epg :after tramp :custom ;; these are ripped from `custom-file' which was auto-generated (auth-sources '("~/.authinfo.gpg")) (epg-pinentry-mode 'loopback)) ;; save minibuffer history, see Vertico below (use-package savehist :init (savehist-mode) :custom (savehist-file (expand-file-name "minibuffer-history" backup-directory))) ;; save place in all files (use-package saveplace :init (save-place-mode t) :custom (save-place-file (expand-file-name "file-position-save" backup-directory))) (use-package image-mode :hook (image-mode . turn-off-line-numbers) (image-mode . (lambda () (blink-cursor-mode -1)))) ;; Visualize whitespace. In a very chill and invisible way. (use-package whitespace :diminish (whitespace-mode ;; org-indent-mode ;; org-vw-mode auto-fill-mode) :custom (whitespace-style '(face lines-tail)) (whitespace-line-column 80) (fill-column 80) :hook (prog-mode . whitespace-mode) ;; (org-mode . auto-fill-mode) ) ;; ...and finally, sync files with disk changes (use-package autorevert :diminish auto-revert-mode :config (global-auto-revert-mode)) (use-package xwidget :if (featurep 'xwidget) :commands xwidget-webkit-browse-url :config (defun mir/webkit-isearch () (interactive) (xwidget-webkit-search (setq isearch-string (read-from-minibuffer "Find in page: ")) (car xwidget-list) 'insensitive nil t)) (defun mir/webkit-isearch-next () (interactive) (xwidget-webkit-search isearch-string (car xwidget-list) 'insensitive nil t)) (defun mir/webkit-isearch-prev () (interactive) (xwidget-webkit-search isearch-string (car xwidget-list) 'insensitive t t)) ;; (posframe-show ) ;; need posframe package :bind ( ("/" . 'mir/webkit-isearch) ("n" . 'mir/webkit-isearch-next) ("N" . 'mir/webkit-isearch-prev) )) ;; built in spell checker, for losers (use-package flyspell :diminish :custom (flyspell-auto-correct-word t) :hook (org-mode . flyspell-mode)) ;; unique buffer names (use-package uniquify :custom (uniquify-buffer-name-style 'forward)) ;; cache file cleanup (use-package kkc :custom (kkc-init-file-name (expand-file-name "kkcrc" backup-directory))) ;; https://laurencewarne.github.io/emacs/programming/2022/12/26/exploring-proced.html (use-package proced :commands proced :custom (proced-auto-update-flag t) (proced-goal-attribute nil) (proced-show-remote-processes t) (proced-enable-color-flag t) (proced-format 'custom) :config (add-to-list 'proced-format-alist '(custom user pid ppid sess tree pcpu pmem rss start time state (args comm)))) (use-package gnus :hook (gnus-summary-mode . hl-line-mode) (gnus-summary-prepare . gnus-summary-sort-by-most-recent-date) ) (use-package tramp :defer 2 :custom (tramp-persistency-file-name (expand-file-name "tramp-history" backup-directory)) :config (defun find-current-file-sudo (&rest throwaway) ;; (interactive) (if buffer-file-name (unless (or (file-writable-p buffer-file-name) (file-directory-p buffer-file-name)) (find-alternate-file (format "/sudo::%s" buffer-file-name))))) (advice-add #'find-file :after #'find-current-file-sudo)) ;; eshell. Pretty good actually. (use-package eshell :after tramp ;; :commands (eshell/emacs eshell/man) ;; :init ;; (defun eshell-banner-initialize () ;; "Run Neofetch in eshell." ;; (eshell/ls nil)) :custom (eshell-scroll-to-bottom-on-input t) (eshell-hist-ignoredups t) (eshell-history-file-name (expand-file-name "zsh/histfile" "~/.local/share/")) (eshell-history-size nil) (eshell-banner-message "") (eshell-expand-input-functions '(eshell-expand-history-references)) :config (add-to-list 'tramp-remote-path "/bedrock/bin" 'append) (add-to-list 'eshell-modules-list 'eshell-rebind) (add-to-list 'eshell-modules-list 'eshell-hist) (add-to-list 'eshell-modules-list 'eshell-tramp) (add-hook 'kill-emacs-hook (lambda () (if (fboundp #'eshell-save-some-history) (eshell-save-some-history)))) (defun eshell-evil-insert-line (count &optional vcount) (interactive "p") (eshell-bol) (evil-insert count vcount)) (defun mir/edit-file-or-lib (name) "Edit library called NAME if it exists, otherwise edit FILE. If the current window occupies the whole frame, split it." (let* ((old-buffer (current-buffer)) (old-default-dir default-directory) ; needed to preserve environment find-fun lib-fun ; scope these so we can bind them later (openfun (lambda (arg) "Implicit function for opening a file or library." (let ((arg-file-name (expand-file-name arg)) (arg-lib-name (locate-library arg))) (if (file-exists-p arg-file-name) (funcall find-fun arg-file-name) (if arg-lib-name (funcall lib-fun arg) (funcall find-fun arg-file-name))))))) (if (one-window-p) (setq find-fun #'find-file-other-window lib-fun #'find-library-other-window) (setq find-fun #'find-file lib-fun #'find-library)) (let ((result (funcall openfun name))) (with-current-buffer old-buffer (setq default-directory old-default-dir)) result))) (defun eshell/emacs (&rest args) "run external Emacs." (eshell-eval-using-options ; this is somewhat broken but works okay "emacs" args '( (nil "batch" nil batch "Non-interactive") (nil "chdir" t change-dir "change to directory DIR") ("nw" nil nil no-window "open in terminal mode, no window") ("fs" "fullscreen" nil full-screen "Open in full screen") :external "emacs" :usage "[FILE] etc placeholder text...") (mapcar #'mir/edit-file-or-lib (eshell-stringify-list (flatten-tree (reverse args)))))) (defun mir/eshell-setup-keys () (evil-collection-define-key 'normal 'eshell-mode-map (kbd "I") 'eshell-evil-insert-line (kbd "RET") 'hkey-either)) (advice-add 'evil-collection-eshell-setup-keys :after 'mir/eshell-setup-keys)) ;; straight.el: the better package manager? ;; minified bootstrap (split lines if you want) (or not) ;; (defvar bootstrap-version) (let ((bootstrap-file (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory)) (bootstrap-version 5)) (unless (file-exists-p bootstrap-file) (with-current-buffer (url-retrieve-synchronously "https://raw.githubusercontent.com/radian-software/straight.el/develop/install.el" 'silent 'inhibit-cookies) (goto-char (point-max)) (eval-print-last-sexp))) (load bootstrap-file nil 'nomessage)) (straight-use-package 'use-package) (setq straight-use-package-by-default t) ;; actually, use elpaca instead ;; (require 'elpaca-bootstrap) (setq elpaca-bootstrap-file (expand-file-name "elpaca-bootstrap.el" user-emacs-directory)) (unless (file-exists-p elpaca-bootstrap-file) (with-current-buffer (pop-to-buffer (url-retrieve-synchronously "https://raw.githubusercontent.com/progfolio/elpaca/master/README.md")) (re-search-forward (rx "### Installer\n")) (let ((start (1+ (re-search-forward "```emacs-lisp"))) (end (- (re-search-forward "\n```") 3))) (write-region start end elpaca-bootstrap-file)))) (load-file elpaca-bootstrap-file) (elpaca elpaca-use-package (elpaca-use-package-mode) (setq elpaca-use-package-by-default t)) ;; (message "%s" elpaca--queues) (elpaca-process-queues) (require 'mir-packages) ;; Absolute line numbers. Relative ones are an annoyance to set up, sadly. ;; (global-display-line-numbers-mode) ;; (defvar display-line-numbers-width-start t) ;; Don't barf out emacs errors as they are encountered (setq debug-on-error nil) ;; lower gc threshold again (setq gc-cons-threshold (* 2 100 1000)) ;; (add-function :before #'after-focus-change-function #'garbage-collect) ;;; init.el ends here