From 5a7234cd054ac71bd5116a549371bfced5a4fb0e Mon Sep 17 00:00:00 2001 From: David Thompson Date: Sat, 12 Aug 2023 09:59:47 -0400 Subject: Update rise home config. --- dotfiles/.emacs.d/init.el | 498 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 498 insertions(+) create mode 100644 dotfiles/.emacs.d/init.el (limited to 'dotfiles/.emacs.d/init.el') diff --git a/dotfiles/.emacs.d/init.el b/dotfiles/.emacs.d/init.el new file mode 100644 index 0000000..627ae21 --- /dev/null +++ b/dotfiles/.emacs.d/init.el @@ -0,0 +1,498 @@ +;; -*- lexical-binding: t -*- + +;; Super handy macro for loading packages but not stopping the init +;; process if they aren't found. +(require 'use-package) + +;; This convenient package removes many lines of custom config I used +;; to have here. +(use-package better-defaults) + +(set-fringe-mode 10) +(setq inhibit-startup-message t) ; no splash screen +(setq visible-bell t) + +;; Maximize frames +(add-to-list 'default-frame-alist '(fullscreen . maximized)) + +;; Stop customize from writing to my init file. +(setq custom-file "~/.emacs.d/custom.el") + + +;;; +;;; Look and Feel +;;; + +;; Use Inconsolata font. +(add-to-list 'default-frame-alist '(font . "Inconsolata-14")) + +(use-package doom-themes + :config + (load-theme 'doom-vibrant t) + ;; Enable flashing mode-line on errors + (doom-themes-visual-bell-config) + ;; Enable custom neotree theme (all-the-icons must be installed!) + (doom-themes-neotree-config) + ;; Corrects (and improves) org-mode's native fontification. + (doom-themes-org-config)) + +(use-package doom-modeline + :init (doom-modeline-mode 1) + :custom ((doom-modeline-irc t) + (doom-modeline-irc-buffers t))) + +(column-number-mode t) +(which-function-mode t) +(add-hook 'prog-mode-hook (lambda () (display-line-numbers-mode t))) + +(use-package which-key + :init (which-key-mode) + :diminish which-key-mode + :custom (which-key-idle-delay 0.3)) + + +;;; +;;; Guix +;;; + +(use-package guix + :config + (add-hook 'scheme-mode-hook 'guix-devel-mode) + :custom + ;; Load modules from the guix obtained via 'guix pull'. + (guix-load-path '("~/.guix/current/share/guile/site/3.0")) + (guix-load-compiled-path '("~/.guix/current/lib/guile/3.0/site-ccache"))) + +;; This config based on: https://amodernist.com/texts/emacs-guix.html +(use-package buffer-env + :config + (add-hook 'hack-local-variables-hook #'buffer-env-update) + (add-hook 'comint-mode-hook #'hack-dir-local-variables-non-file-buffer) + :custom + (buffer-env-script-name '("guix.scm" "manifest.scm"))) + + +;;; +;;; Dired +;;; + +;; Don't create buffer litter when moving through directories with +;; dired. +(setq dired-kill-when-opening-new-dired-buffer t) + +;; Revert dired buffer after a copy, rename, etc. +(setq dired-do-revert-buffer t) + + +;;; +;;; TRAMP +;;; + +(use-package tramp-sh + ;; Include the current path for the system to TRAMP's remote path. + ;; This is necessary for GuixSD, where the usual /usr/bin, + ;; /usr/local/bin, etc. do not exist. + :config (push 'tramp-own-remote-path tramp-remote-path)) + + +;;; +;;; Battery +;;; + +(use-package battery + :init + ;; Display battery level in modeline only if a battery is present, + ;; otherwise display-battery-mode will throw an error. + (when (and (boundp 'battery-status-function) + (not (null battery-status-function)) + (not (string-match-p + "N/A" + (battery-format + "%B" + (funcall battery-status-function))))) + (display-battery-mode t))) + + +;;; +;;; Bookmarks +;;; + +(setq bookmark-save-flag 1) + + +;;; +;;; Searching +;;; + +;; Highlight the current "error" (or rgrep search result, etc. it's a +;; bad name.) +(setq next-error-message-highlight t) + + +;;; +;;; Minibuffer and completion +;;; + +(use-package smex) + +;; Present more information when looking at completions via the +;; describe-* family of commands. +(setq completions-detailed t) + +;; Prompt for y/n instead of yes/no. +(setq user-short-answers t) + + +;;; +;;; Buffers +;;; + +;; Kill buffers that haven't been modified in awhile. +(use-package midnight) + +;; Save point position between sessions +(use-package saveplace + :custom ((save-place t) + (save-place-file (expand-file-name ".places" user-emacs-directory)))) + +(defun cleanup-buffer-safe () + "Perform a bunch of safe operations on the whitespace content of a buffer. +Does not indent buffer, because it is used for a before-save-hook, and that +might be bad." + (interactive) + (delete-trailing-whitespace) + (set-buffer-file-coding-system 'utf-8)) + +;; Various superfluous white-space. Just say no. +(add-hook 'before-save-hook 'cleanup-buffer-safe) + +(use-package ibuffer + :init (add-hook 'ibuffer-mode-hook + (lambda () + (ibuffer-switch-to-saved-filter-groups "default"))) + :custom ((ibuffer-saved-filter-groups + '(("default" + ("Dired" (mode . dired-mode)) + ("Org" (mode . org-mode)) + ("ERC" (mode . erc-mode)) + ("Magit" (or (mode . magit-status-mode) + (mode . magit-diff-mode) + (mode . magit-process-mode))) + ("Shell" (mode . shell-mode)) + ("Guix" (name . "Guix")) + ("Emacs Lisp" (mode . emacs-lisp-mode)) + ("Scheme" (or (mode . scheme-mode) + (name . "Geiser") + (mode . geiser-repl-mode) + (mode . geiser-messages-mode))) + ("Ruby" (mode . ruby-mode)) + ("JavaScript" (mode . js2-mode))))) + (ibuffer-show-empty-filter-groups nil))) + +(setq view-read-only t) + +;; Attempt to make buffers with long lines not slow Emacs to a crawl. +(global-so-long-mode) + + +;;; +;;; Tabs and Newlines +;;; + +(setq-default indent-tabs-mode nil) +(setq indent-tabs-mode nil) +(setq tab-width 2) +(setq require-final-newline t) +(setq electric-indent-mode t) + + +;;; +;;; Version Control +;;; + +(use-package magit + :bind (("C-c g" . magit-status)) + :init + ;; Make magit-status project shortcut available immediately. + ;; Without this, it only becomes available after running + ;; magit-status once manually. + (use-package magit-extras) + :config + (use-package magit-blame) + :custom + ;; I don't like magit's default local tracking branch naming + ;; strategy. + ((magit-default-tracking-name-function 'magit-default-tracking-name-branch-only) + (magit-last-seen-setup-instructions "1.4.0") + (magit-completing-read-function #'magit-ido-completing-read))) + +;; Follow symlinks automatically instead of asking each time. +(setq vc-follow-symlinks t) + + +;;; +;;; Compilation +;;; + +(use-package ansi-color + ;; Process ANSI color codes in compilation buffers. + :config (add-hook 'compilation-filter-hook #'ansi-color-compilation-filter)) + + +;;; +;;; Ediff +;;; + +;; Don't break out a separate frame for ediff. +(setq ediff-window-setup-function 'ediff-setup-windows-plain) +(setq ediff-split-window-function 'split-window-horizontally) + + +;;; +;;; C +;;; + +(setq c-default-style "k&r") +(setq-default c-basic-offset 2) +(setq-default c-basic-indent 2) + + +;;; +;;; Javascript +;;; + +(setq js-indent-level 2) + +(use-package js2-mode + :init (add-to-list 'auto-mode-alist '("\\.js$" . js2-mode)) + :custom ((js2-basic-offset 2))) + + +;;; +;;; Web +;;; + +(use-package web-mode + :init + (add-to-list 'auto-mode-alist '("\\.html$" . web-mode)) + (add-to-list 'auto-mode-alist '("\\.tpl$" . web-mode)) + (add-to-list 'auto-mode-alist '("\\.erb$" . web-mode)) + (add-hook 'web-mode-hook + (lambda () + (setq web-mode-markup-indent-offset 2)))) + + +;;; +;;; Lisp +;;; + +(use-package rainbow-delimiters + :hook (prog-mode . rainbow-delimiters-mode)) + +(use-package scheme) + +(use-package paredit + :config + (add-hook 'emacs-lisp-mode-hook #'paredit-mode) + (add-hook 'lisp-mode-hook #'paredit-mode) + (add-hook 'lisp-data-mode-hook #'paredit-mode) + (add-hook 'lisp-interaction-mode-hook #'paredit-mode) + (add-hook 'scheme-mode-hook #'paredit-mode)) + +(use-package geiser + :config + (use-package geiser-guile + :config + (define-key project-prefix-map "l" #'geiser-guile) + (add-to-list 'project-switch-commands '(geiser-guile "Guile REPL") t)) + ;; Flycheck-guile only works if Geiser is around. + (use-package flycheck-guile + :config + (add-hook 'scheme-mode-hook #'flycheck-mode)) + + :custom ((geiser-active-implementations '(guile)) + ;; One REPL per project, please! + (geiser-repl-per-project-p t))) + +;; Hacked to properly indent keywords. Thanks to mark_weaver. +(defun scheme-indent-function (indent-point state) + "Scheme mode function for the value of the variable `lisp-indent-function'. +This behaves like the function `lisp-indent-function', except that: + +i) it checks for a non-nil value of the property `scheme-indent-function' +\(or the deprecated `scheme-indent-hook'), rather than `lisp-indent-function'. + +ii) if that property specifies a function, it is called with three +arguments (not two), the third argument being the default (i.e., current) +indentation." + (let ((normal-indent (current-column))) + (goto-char (1+ (elt state 1))) + (parse-partial-sexp (point) calculate-lisp-indent-last-sexp 0 t) + (if (and (elt state 2) + (not (looking-at "\\sw\\|\\s_"))) + ;; car of form doesn't seem to be a symbol + (progn + (if (not (> (save-excursion (forward-line 1) (point)) + calculate-lisp-indent-last-sexp)) + (progn (goto-char calculate-lisp-indent-last-sexp) + (beginning-of-line) + (parse-partial-sexp (point) + calculate-lisp-indent-last-sexp 0 t))) + ;; Indent under the list or under the first sexp on the same + ;; line as calculate-lisp-indent-last-sexp. Note that first + ;; thing on that line has to be complete sexp since we are + ;; inside the innermost containing sexp. + (backward-prefix-chars) + (current-column)) + (let ((function (buffer-substring (point) + (progn (forward-sexp 1) (point)))) + method) + (setq method (or (get (intern-soft function) 'scheme-indent-function) + (get (intern-soft function) 'scheme-indent-hook))) + (cond ((or (eq method 'defun) + (and (null method) + (> (length function) 3) + (string-match "\\`def" function))) + (lisp-indent-defform state indent-point)) + ;; This next cond clause is the only change -mhw + ((and (null method) + (> (length function) 1) + ; The '#' in '#:' seems to get lost, not sure why + (string-match "\\`:" function)) + (let ((lisp-body-indent 1)) + (lisp-indent-defform state indent-point))) + ((integerp method) + (lisp-indent-specform method state + indent-point normal-indent)) + (method + (funcall method state indent-point normal-indent))))))) + + +;;; +;;; Ruby +;;; + +;; Rake files are ruby, too, as are gemspecs, rackup files, etc. +(add-to-list 'auto-mode-alist '("\\.rake$" . ruby-mode)) +(add-to-list 'auto-mode-alist '("\\.gemspec$" . ruby-mode)) +(add-to-list 'auto-mode-alist '("\\.ru$" . ruby-mode)) +(add-to-list 'auto-mode-alist '("Rakefile$" . ruby-mode)) +(add-to-list 'auto-mode-alist '("Gemfile$" . ruby-mode)) + + +;;; +;;; SQL +;;; + +;; Don't wrap lines so that table listings with a lot of columns +;; remain readable. +(add-hook 'sql-interactive-mode-hook + (lambda () (setq truncate-lines t))) + + +;;; +;;; Org +;;; + +(use-package ox-beamer) +(use-package cl-lib) + +(defun org-sort-by-priority-and-todo () + "Sort org entries first by priority, and then by TODO status." + (interactive) + (push-mark) + (push-mark (point-max) nil t) + (let ((p (point))) + (goto-char (point-min)) + (org-sort-entries nil ?p) + (org-sort-entries nil ?o) + (goto-char p)) + (pop-mark)) + +(add-hook 'org-mode-hook + (lambda () + (local-set-key (kbd "C-c o") 'org-sort-by-priority-and-todo))) + + +;;; +;;; GPG +;;; + +(setq epg-gpg-program "gpg") +(setq epa-pinentry-mode 'loopback) + + +;;; +;;; IRC +;;; + +(use-package erc + :init + (require 'erc-join) + (erc-autojoin-mode t) + (erc-track-mode t) + :custom ((erc-interpret-mirc-color t) + (erc-kill-buffer-on-part t) + (erc-kill-queries-on-quit t) + (erc-kill-server-buffer-on-quit t) + (erc-server-coding-system '(utf-8 . utf-8)) + (erc-autojoin-channels-alist + '(("libera.chat" + "#gnuassembly" "#guile" "#guile-steel" "#guix" "#lispgames" + "#chickadee" "#spritely"))) + ;; Don't open channel buffers in place of the current + ;; buffer because that drives me fucking crazy. + (erc-join-buffer 'bury) + (erc-track-exclude-types '("JOIN" "NICK" "PART" "QUIT" "MODE" + "324" "329" "332" "333" "353" "477")) + (erc-save-buffer-on-part t))) + +(use-package erc-log + :custom ((erc-log-channels-directory "~/.erc/logs/"))) + +(if (not (file-exists-p erc-log-channels-directory)) + (mkdir erc-log-channels-directory t)) + +(use-package erc-notify) +(use-package erc-autoaway) +(use-package erc-services) +(use-package gnutls) + +;; Start and stop erc +(defun start-irc () + "Connect to IRC." + (interactive) + (erc-tls :server "irc.libera.chat" + :port 6697 + :nick "dthompson" + :password (read-passwd "Password: "))) + +(defun stop-irc () + "Disconnects from all irc servers" + (interactive) + (dolist (buffer (delq nil + (mapcar + (lambda (x) + (and (erc-server-buffer-p x) x)) + (buffer-list)))) + (message "Server buffer: %s" (buffer-name buffer)) + (with-current-buffer buffer + (erc-quit-server "Later")))) + +(global-set-key (kbd "C-c i") 'start-irc) + + +;;; +;;; Keybindings +;;; + +(global-set-key (kbd "RET") 'newline-and-indent) +(global-set-key (kbd "C-c C-f") 'ff-find-other-file) +(global-set-key (kbd "M-%") 'query-replace-regexp) +;; No more minimizing Emacs by accident. +(global-unset-key (kbd "C-z")) +;; No more closing Emacs by accident. +(global-unset-key (kbd "C-x C-c")) +;; Enable some disabled-by-default functions. +(put 'upcase-region 'disabled nil) +(put 'downcase-region 'disabled nil) -- cgit v1.2.3