From fd0da00ba501f37efea1cbfb89414cde847c48c3 Mon Sep 17 00:00:00 2001 From: Duncan Wilkie Date: Wed, 7 Jun 2023 13:30:34 -0500 Subject: Drastic config changes and a temporary file totally unrelated. --- config.org | 1604 ++++++++++++++++++++++++++++++++++------------------------- system-auth | 28 ++ 2 files changed, 941 insertions(+), 691 deletions(-) create mode 100644 system-auth diff --git a/config.org b/config.org index 46d33d7..23f0539 100644 --- a/config.org +++ b/config.org @@ -1,14 +1,100 @@ -#+title DNW's GNU Emacs Configuration -#+PROPERTY: header-args:emacs-lisp :tangle ./init.el +#+Title DNW's GNU Emacs Configuration +#+PROPERTY: header-args :tangle ./init.el + +Top-level TODOs: + - Describe how I use things, and what the alternatives are and why I dislike them, more than what things do. They can read the code. + - Learn how to use compilation and debugging modes + - Get really good auth-sources etc. support + - Emacsclient + - Read through the Emacs source tree/info pages for all the features I'm missing + - nerd-icons-completion + - Links to Emacs documentation explaining the things I talk about, and all the keybindings accessible. + +* Why Emacs? + +#+begin_verse +... +Reason is clouding, +Hearts are hardening, +And the result is murder. +This age is grave bound, +Likewise its aging successors. +Aging, all the while, descending +Developing an even more insatiable thirst for chaos. +Life among hyenas and asps under vultures +That pick at the corpses of the fallen. +And man will continue to suffer unto itself +Until some stand to rally the fray by firm example. +Chaos must succumb to order +Lest these days be numbered. +I cannot contribute to disarray. +I simply cannot relate. +Let this be my act of defiance. +Let this by my refusal to fit in. +Let this by my writ of misanthropy... + + --- /Scornful of The Motives And Virtue of Others/, Shai Hulud, 2003 + +#+end_verse + +The joke goes "Emacs is a wonderful operating system lacking only a decent text editor." The joke has a kernel of truth: Emacs is first and foremost, from a design perspective, a Lisp environment, which merely happens to have extensive faculties for interacting with text. This is precisely why Emacs is the /best/ text editor. For a system which edits text must not only be good at that now, for whatever definition of "text" occupies its designers, but also later, for whatever evolutions in the definition of "text" occur. It must be able to handle the slings and arrows of the evolution of text's structure, and be able to be modified to handle any well-specified action on any form of text that any sufficiently driven user would like to implement. The ease with which it handles that task is precisely the extent to which it will survive. + +Emacs and vi have long histories, each back to 1976. As editors based on them in some way have seen extensive use through all of the evolution of text and its structure (not even to mention the evolution of computers!) in the intervening 47 years, they over all newer editors can evidence the claim that their systems are capable. However, these systems are very different and, I hope to argue, actually seem /dual/. + +The vi perspective (in line with the UNIX perspective) is that text in the filesystem is the substance on which programs operate; it is what they produce and consume, and that by composing individual programs that perform simple text manipulations one may arive at powerful systems from simple parts. Programs are configured through filesystem text, either with a declarative config file or by modifying and recompilng their source. Programs are accessed through filesystem text, by typing their name into a shell (which can only take text input, and can only output other text and side-effects). Even hardware devices are accessed through filesystem text, by reading and writing under the =/proc= and =/dev= trees. This is a worthy perspective, and certainly an elegant one. Getting good at shell-fu gives great h@x0r feelings. The reason this paradigm has been capable of surviving a near half-century is that the editor itself does relatively little: it's the responsibility of the tools around the editor to extend the functionality of the editor itself. + +By contrast, I think the Emacs perspective is that text is merely the substance of which programs and the data they operate on can be /composed/, but is not what they /are/. Therefore, we need not control our computers through particular text incantations in a shell (though we may), nor must all programs interface through the intermediary of a text terminal or terminal emulator (though, again, they may). The text editor exists more generally to describe and control computer behavior, which, yes, often takes the form of reading, writing, and executing text, but which also can take the form of simple keystrokes bound to functionality, pictures and animations presented to the user, or interactive graphical displays. vi people have recognized this to an extent, mercilessly abusing terminal control codes to get colors and interactive animations in the tty, polluting their textual paradise with programs graphical in all but name. Emacs, by contrast, has no such philosophical restrictions, so it may be principled about drawing, via C codes actually /designed/ for the purpose, from the ground up. Emacs, rather than a text editor, should be regarded as a replacement of the /shell/, the vi man's door to his system. + +Emacs is configured in Lisp. The language represents a fixed point in the relationship between programs' identity and programs' composition---homoiconicity, there being no distinction in form between a Lisp's representation of the data it operates on and the code doing the operation, enables ordinary Lisp code to reason about other Lisp code with the same primitives used for reasoning about anything else---no weird templating, interpolation, parsing, or quoting. Just =macroexpand=. It's a dead-simple language, with about 5 pieces of syntax (lists, procedure calls, quotes, and quasiquotes). Other versions can be implemented with about 10 primitives (see the wizard book). It's extremely expressive---most modern CAS (for a fact: Maple, Wolfram/Mathematica, and SageMATH) drew on theoretical advances made by the MACSYMA system, written at MIT in Maclisp for the PDP-6 starting in 1968. Sage is actually said to have some of the original 1968 Lisp code, albeit ported to CommonLisp, surviving in its core routines. Configuration in a general-purpose language like this enables the editor's functionality to change as its users' preferences, requirements, systems, and operating systems do. The actual, runtime state of configuration variables can be inspected and changed on the fly. + +From a user perspective, the fact that all keystrokes in Emacs are user-configurably bound to Lisp functions (or Lisp wrappers of C functions) is a large part of what enables its power. One may attach any functionality to any key combination in any way, at runtime, in any way you desire. And so it has been since Stallman's FOSS port to GNU in 1984. Without this, I doubt I'd be writing this today. This contrasts again with the structure of vi: the improvements to Emacs are internal, not external. Programs written in Emacs Lisp, distributed and installed just as other programs, are used as substitutes for command-line alternatives, written in bash or C. To be clear, no generality or speed need be lost: Emacs can interact with the C ABI and command-line programs just as vi-based editors can. Instead, that generality and speed becomes a balance against ease of development and use, a balance most seem to have struck against developing code externally first. Which, probably, would mean that more code would have been developed for vi, had its users the same option (neovim's Lua configuration confirms this further). + +Emacs is additionally self-documenting. In the Common Lisp tradition, every package, module, variable, function, and macro can be adorned with a docstring. These docstrings can be used to dynamically produce documentation pages for variables and keybinds, as you forget them in real-time. Emacs' use of prefix keys (e.g. =C-x=, after which the keystroke =b= will mean the Lisp function =switch-to-buffer= rather than insertion of a characters) enables packages that, through runtime querying of the current keymap, will tell you all the available next-step bindings and their functions in a key sequence if you wait longer than a time out. If you forget what a key does, or want to use a key combination in a script, =C-h k= will let you type it in and will present the documentation page of the function to which the key combination is bound. Similarly, under =C-h= are many other facilities to bring up documentation pages, which, after some configuration with an external package, will present the command, its arguments, its docstring, any manual/info entries about it, links to the documentation of other functions in close relation to it, any key bindings in any mode map that are defined to it, it's definition (whether C or Emacs Lisp), other source references to it (C or Emacs Lisp), trace calls of it, and more. I wrote my first Emacs major mode in a weekend, knowing zero Emacs Lisp beyond what I had copied verbatim from David Wilson's /Emacs from Scratch/ videos, and was distributing it among my research group the following Monday. It's difficult to overstate its power. + +Hopefully, this is a convincing case for "/the/ extensible, customizable, self-documenting, real-time display editor." An illustrative, mature personal configuration follows. + +* How to Use This Configuration + +If you're completely new to Emacs, drop everything and type =C-h t= (=h= with == held down, and then =t= after releasing). This will explain the basic buffer navigation and editing commands and some terminology. After finishing that (you can go back at any time by typing the same thing), type =C-h C-h= (=h= with == held down, done twice) to see all of the other places you can get help. The manual, accessed via =C-h r=, is quite helpful (if you press =u= for "up" a bunch, you can get to the top-level info directory, and read info manuals for other things on your system within Emacs!). + +Place this org file under =~/.emacs.d/=. Once Emacs is up-and-running with this configuration, simply saving this file after making changes to the config snippets will result in those changes being written out to an =init.el= file in this directory, which will be loaded by Emacs at startup. However, this init file must be working in order for the setting enabling tangle-on-save to be set. The first time, you can type =M-x org-babel-tangle= (bound to =C-c C-v t=) to produce it, and it should (hopefully) work painlessly after restarting. + +This is intended to be read in tandem with other sources of documentation; particularly, the manual above and the built-in help facilities. To learn how to navigate the manual, press =C-h m= in the manual, and test the commands (=C-h r= at any time should return to the Emacs manual, and when in doubt, spam =C-g= a few times before rerunning). To see exactly what something in the configuration snippets is doing, press =C-h o= with the point near the thing in question and it should be the first completion candidate (otherwise just type it in like a plebian 😎). + +* Configuration Philosophy + +There are a few principles this configuration follows. + +- Packages that exploit built-in features usually integrate better and are more powerful and extensible than those which don't. +- However, this shouldn't induce too strong an aversion to external code---packages with substantially improved feature sets and ergonomics can offset the above. +- Modules should load lazily to reduce startup time and memory overhead (e.g. don't load a major mode until a file to which it applies is opened), and tear down when no longer needed. +- User interfaces should be mostly invisible until called-upon---the user can rely on explicit documentation and help features to learn what's available when. +- Minimize keystrokes, prevent injury. +- Mice are literally spawn of Satan: keyboard-driven workflows are preferred at all costs (hence why this is an Emacs configuration). The time taken moving keyboard-to-mouse adds up. +- Modal editing requires keeping track of which mode you're in, and doesn't seem to meaningfully reduce either keystrokes or dependence upon modifier keys, and as such is needless complexity. The keystroke =A= should always insert the character "A", unless specifically instruced otherwise via prefixing. In a sense, these prefixes are a type of "modal editing"---and accordingly, by exploiting them in depth, the key combinations are more semantic/mnemonic and far more numerous (by default, there are 10000+ key combinations). +- In-Emacs user-interfaces are preferred to external programs, in the interest of maximizing configurability, integration, and extensibility (with the same caveat as the second bullet, /mutadis mutandis/). +- Colors, symbols, and embedded pictures enable more compact representation and faster communication of information than text alone (hence GUI Emacs). +- Avoid the "customize" interface, because actual use of it clutters up the init file/process. Changes to variables should be performed first temporarily through =M-:= and then permanently via =setq= in this org file, and tangled out to the actual =init.el=. +- Starting with more feature-complete packages, while I might not need all of their functionality immediately, prevents needing to rewrite an existing config for what would be a single =setq= otherwise. Especially true if it's already built-in---there's little downside. + +There are also some rules according to which this text is composed. + +- Group configuration elements by their highest-level end-user purpose +- Describe first the /why/ of the config snippet. Then describe the /what/ with comments in the actual snippet, and follow the snippet with some /how/ (useful keybindings, extra necessary system configuration etc). +- Link to first-party repositories and documentation as much as possible. +- Describe useful built-in Emacs tools that might need no configuration, so the reader knows what's out there. +- For similar reasons, describe the other packages not included in the configuration, but are worthy of evaluation, detailing the reasoning for what is chosen based on the list above. * Startup Performance -Increase RAM footprint on startup to reduce load time. Display load time as well. +The configuration will load faster if we let the interpreter's RAM footprint blow up on startup. #+begin_src emacs-lisp + ;; Increase garbage-collection threshold (setq gc-cons-threshold (* 50 1000 1000)) + ;; Tell us how fast we're going, for benchmarking (defun dnw/display-startup-time () (message "Emacs loaded in %s with %d garbage collections." (format "%2f seconds" @@ -18,77 +104,112 @@ Increase RAM footprint on startup to reduce load time. Display load time as well (add-hook 'emacs-startup-hook #'dnw/display-startup-time) - ;;(server-start) - #+end_src +* Package Management -* General Keybinds +The default Emacs system, from 24 to 28, has only the =require= interface, which is imperative and somewhat difficult to optimize load-time with. The =use-package= macro provides a more ergonomic, declarative way to control loading and configuration of packages, and will be in Emacs 29 (a few weeks away at time of writing). Additionally, installs are only available from the official GNU ELPA archive by default. Most third-party packages are hosted on the MELPA. Currently, some alternative package managers/loaders/configurers are: =straight=, =quelpa-use-package=, =elpaca=, =el-get=, =elpaso=, =cask=. I will not claim to be familiar with any of these, but the selection criteria few sections above ought to apply, /mutatis mutandis/, to package managers. -** Text Editing +#+begin_src emacs-lisp -Indent region; set TAB to complete in right circumstance + ;; Get the good stuff from MELPA + (require 'package) + (setq package-archives '(("melpa" . "https://melpa.org/packages/") + ("elpa" . "https://elpa.gnu.org/packages/"))) -#+begin_src emacs-lisp + ;; Sync the repos + (package-initialize) + (unless package-archive-contents + (package-refresh-contents)) - (global-set-key (kbd "C->") 'indent-rigidly-right-to-tab-stop) - (global-set-key (kbd "C-<") 'indent-rigidly-left-to-tab-stop) + ;; When compiling config (for load time's sake), install and load use-package, if not done already. + (eval-when-compile + (unless (package-installed-p 'use-package) + (package-install use-package)) + (require 'use-package)) - (setq tab-always-indent 'complete) - (setq align-to-tab-stop nil) + ;; Ensure that every package declared is installed correctly. + (setq use-package-always-ensure t) + + ;; Allows us to make sure external binaries are available to support a particular package. + (use-package use-package-ensure-system-package) #+end_src -* Basic Configuration UI +* UI Glow-Up + +By default, Emacs is ugly as sin. ** Better Font -Noto Emoji is the fallback here. +Something like GNU Unifont is the default; I don't think I have a good eye for fonts generally, but Iosevka seems leaps and bounds better. Google's Noto fonts have great unicode coverage, and nice-looking emojis. #+begin_src emacs-lisp - ;; default-frame-alist works with --daemon + ;; Check for the desired fonts. + (if (not (find-font (font-spec :name "Iosevka"))) + (message "Must have Iosevka font installed and available to Emacs.")) + + (if (not (find-font (font-spec :name "Liberation Sans"))) + (message "Must have Iosevka font installed and available to Emacs.")) + (if (not (find-font (font-spec :name "Noto Sans"))) + (message "Must have Google's Noto Emoji font installed and available to Emacs.")) + + (if (not (find-font (font-spec :name "Noto Color Emoji"))) + (message "Must have Google's Noto Color font installed and available to Emacs.")) + + ;; Set the default font to be monospaced (add-to-list 'default-frame-alist '(font . "Iosevka-10")) + ;; Set fallback for Unicode characters (defun dnw/unicode-fonts () (setf use-default-font-for-symbols nil) + (set-face-font 'variable-pitch (font-spec :name "Liberation Sans")) + (set-face-font 'fixed-pitch (font-spec :name "Iosevka")) (set-fontset-font t 'unicode "Noto Emoji" nil 'append) (set-fontset-font t 'emoji "Noto Color Emoji")) + ;; Configuring the fallbacks has some timing intricacies with the daemon (if (daemonp) (add-hook 'server-after-make-frame-hook #'dnw/unicode-fonts) (dnw/unicode-fonts)) #+end_src -** Hide Ugly GUI Elements +** Hide Ugly UI Elements #+begin_src emacs-lisp - (setq inhibit-startup-message t) - + ;; Everything that reeks of desktop environments must go. We know what we're doing. (menu-bar-mode -1) (tool-bar-mode -1) (scroll-bar-mode -1) (tooltip-mode -1) (set-fringe-mode 10) + ;; Make a 1337 h@ckerman5 splash screen TODO + (setq inhibit-startup-message t) + #+end_src ** Line Numbers -Display cursor position on the modeline, and line numbers left of the buffer. Except where it's stupid. +The desktop environment clutter may now be replaced with tasteful, contentual, context-dependent navigation information. #+begin_src emacs-lisp + ;; Show column number on the modeline. (column-number-mode) + + ;; Display line numbers in the left margin, as a general rule, (global-display-line-numbers-mode t) - ;; Disable in e.g. shell + ;; but disable them where they just add clutter, e.g. shell. (dolist (mode '(org-mode-hook term-mode-hook + vterm-mode-hook eshell-mode-hook Info-mode-hook ement-room-mode-hook @@ -98,84 +219,266 @@ Display cursor position on the modeline, and line numbers left of the buffer. Ex #+end_src -** Transparency +** DOOM Features + +DOOM Emacs' modeline simply looks better to me than the default or Spacemacs'. If the minor-mode list ever gets too cluttered, install the =diminish= package to mitigate. The DOOM themes, additionally, appear to play nicer with buffers created by external packages (I presume because these are in DOOM's distribution by default). #+begin_src emacs-lisp - (set-frame-parameter (selected-frame) 'alpha '(100 100)) + ;; Get the modeline. + (use-package doom-modeline + :ensure t + :init (doom-modeline-mode 1)) + + ;; It installs an Emacs package for its icon fonts, but the symbols need to be installed. + (if (not (find-font (font-spec :name "Symbols Nerd Font Mono"))) + (nerd-icons-install-fonts)) - (add-to-list 'default-frame-alist '(alpha 100 100)) + ;; Get the themes, and load the favorite. + (use-package doom-themes + :init (load-theme 'doom-tomorrow-night t)) #+end_src -* Package Management +To test out alternative themes, do =M-x load-theme=. Beware that sometimes artefacts of old themes persist and make new ones look bad; =M-x disable-theme= prevents this to an extent. -Declare which archives to use, syncing them on start. Always-ensure downloads needed packages not on the system. +** Ligatures and Fancy Characters #+begin_src emacs-lisp - (require 'package) - (setq package-archives '(("melpa" . "https://melpa.org/packages/") - ("elpa" . "https://elpa.gnu.org/packages/"))) + ;; Fancifies TeX-style quotation marks + (electric-quote-mode t) - (package-initialize) - (unless package-archive-contents - (package-refresh-contents)) + ;; Replace e.g. lambda -> λ in Emacs Lisp mode, + ;; or \alpha -> α in TeX-mode + (global-prettify-symbols-mode t) - (eval-when-compile - (require 'use-package)) + ;; Enables fonts' ligature support---Iosevka has some good ones. + (use-package ligature + :config + (global-ligature-mode t) + (ligature-set-ligatures + '(prog-mode org-mode) + '("-<<" "-<" "-<-" "<--" "<---" "<<-" "<-" "->" "->>" "-->" "--->" "->-" ">-" ">>-" + "=<<" "=<" "=<=" "<==" "<===" "<<=" "<=" "=>" "=>>" "==>" "===>" "=>=" ">=" ">>=" + "<->" "<-->" "<--->" "<---->" "<=>" "<==>" "<===>" "<====>" "::" ":::" "__" + "<~~" "" "/>" "~~>" "==" "!=" "/=" "~=" "<>" "===" "!==" "!===" "=/=" "=!=" + "<:" ":=" "*=" "*+" "<*" "<*>" "*>" "<|" "<|>" "|>" "<." "<.>" ".>" "+*" "=*" "=:" ":>" + "(*" "*)" "/*" "*/" "[|" "|]" "{|" "|}" "++" "+++" "\\/" "/\\" "|-" "-|" "