aboutsummaryrefslogtreecommitdiff
path: root/shoshimacs.org
diff options
context:
space:
mode:
Diffstat (limited to 'shoshimacs.org')
-rw-r--r--shoshimacs.org823
1 files changed, 823 insertions, 0 deletions
diff --git a/shoshimacs.org b/shoshimacs.org
new file mode 100644
index 0000000..b597e19
--- /dev/null
+++ b/shoshimacs.org
@@ -0,0 +1,823 @@
+#+AUTHOR: Grant Shoshin Shangreaux
+#+EMAIL: shoshin@cicadas.surf
+#+DESCRIPTION: Html version of an Emacs literate org configuration
+#+STARTUP: overview
+#+PROPERTY: header-args:emacs-lisp :lexical t
+#+OPTIONS: broken-links:mark
+
+* A New Start
+
+To welcome in Emacs 28 I intend to re-aquaint myself with the application
+and its ecosystem. I've been perusing the packages available through the
+default ELPA and non-gnu ELPA repos and trying to put together the various
+things that I've grown accustomed to.
+
+However, with a beginner's mind, I've been trying to avoid going down the
+same old idiosyncratic paths. Courting a bit of discomfort in order to learn
+what newcomers might experience coming to Emacs in this current version.
+
+** Overview
+
+This document is a journal, manual, and a program at once. I'm no expert at
+writing a document like this. If you happen to be reading it, the journal
+nature may be confusing. Over time, the journal will be incorporated into the
+bits that are a manual, solidified knowledge gained through the experience.
+
+The program bits will be tangled into [[file:shoshin-config.el]]. As a program, it
+requires a certain structure from top to bottom. Here, the snippets may be
+scattered around. I'll attempt to have a system to keep them organized, but
+this is all an experiment.
+
+The following code block is the "table of contents" that determines what
+is tangled into the resulting elisp file:
+
+#+begin_src emacs-lisp :tangle yes :noweb no-export
+ ;;; shoshimacs.el --- Beginner's Mind Config -*- lexical-binding:t -*-
+
+ <<preamble>>
+
+ <<defvars>>
+
+ ;;; Package Management
+ <<package-management>>
+
+ ;;; Major Keybinding
+ <<keybinding>>
+
+ ;;; Completion
+ <<completion>>
+
+ ;;; Editing
+ <<editing>>
+
+ ;;; Programming
+ <<programming>>
+
+ ;;; Projects
+ <<projects>>
+
+ ;;; External Services
+ <<external-services>>
+
+ ;;; User Interface
+ <<user-interface>>
+#+end_src
+
+** Preamble
+:PROPERTIES:
+:header-args:emacs-lisp+: :noweb-ref preamble :noweb-sep "\n\n" :results silent
+:END:
+
+This section covers initialization that works best before anything else is
+configured. For example, it is much easier to manage the "custom variables"
+if they are not automatically tacked onto your initialization file. You can
+set and load a separate file to keep it clean:
+
+#+begin_src emacs-lisp
+ (let ((my-custom-file (expand-file-name
+ "shoshimacs-custom.el" user-emacs-directory)))
+ (unless (file-exists-p my-custom-file)
+ (make-empty-file my-custom-file))
+ (setq custom-file my-custom-file)
+ (load custom-file))
+#+end_src
+
+* Package Management
+:PROPERTIES:
+:header-args:emacs-lisp+: :noweb-ref package-management :noweb-sep "\n\n" :results silent
+:END:
+
+I've been using [[https://github.com/radian-software/straight.el#start-of-content][straight.el]]
+as my package manager since 2019 when I moved away from Spacemacs as my
+main configuration for day-to-day work. While I definitely recommend it
+as a flexible yet minimal package manager, it is certainly more useful
+to experienced Emacs users.
+
+This configuration will stick to packages available through the built-in
+~package.el~ system. As of Emacs 28, this is everything in the ELPA and
+non-gnu ELPA package repositories.
+
+** ELPA and Non-GNU ELPA
+
+ELPA packages have their copyright assigned to the FSF, which is a requirement
+for any code to be included into Emacs itself. ELPA packages are thus the
+most likely to be merged into Emacs as a new feature. Some, like EMMS, are
+likely to continue as "add-on" optional features only some users may choose.
+
+Non-gnu ELPA is relatively new, and does not require copyright assignment
+to the FSF. Packages are added to both repositories through the emacs-devel
+mailing list and the maintainers there. It intends to extend the packages
+available to the base Emacs installation while providing a bridge to inclusion
+in ELPA or Emacs proper at some time in the future.
+
+*** Add non-gnu ELPA to Emacs < 28
+
+Emacs 28 is the first version to include non-gnu ELPA by default. Some
+distributions may not yet have it as an available package.
+
+#+name: add-nongnu-elpa
+#+begin_src emacs-lisp
+ (when (< emacs-major-version 28)
+ (add-to-list 'package-archives '("nongnu" . "https://elpa.nongnu.org/nongnu/")))
+#+end_src
+
+** Installing Packages
+
+~package.el~ provides the [[help:package-install][package-install]] command which can be used interactively
+or from Lisp code like this configuration. If a package is already installed,
+it won't try to install it again. When you install a package this way, Emacs will
+add its name to [[help:package-selected-packages][package-selected-packages]].
+
+You can also use ~list-packages~ to browse, install and upgrade packages as
+well.
+
+I'll initialize the package functionality and refresh the contents to look for
+updates, and ensure any additional archives are fetched. this may have a startup
+impact, but i'm not concerned about that.
+
+#+begin_src emacs-lisp
+ (package-initialize)
+ (package-refresh-contents)
+#+end_src
+
+** Packages not in the default repos
+
+Any elisp package that is in Emacs's [[help:load-path][load-path]] can be ~require~'d and used.
+~(add-to-list 'load-path (expand-file-name "some-package/" user-emacs-directory))~
+is an example of putting the directory ~some-package/~ into the load path.
+
+*** COMMENT xah-fly-keys
+
+muscle memory has bound me to xah-fly-keys, and so i've decided to just
+manually install it by cloning the repo and adding it to the
+
+#+begin_src shell :var dir=(expand-file-name "xah-fly-keys" user-emacs-directory) :tangle no
+ git clone https://github.com/xahlee/xah-fly-keys $dir
+#+end_src
+
+#+begin_src emacs-lisp
+ (add-to-list 'load-path (expand-file-name "xah-fly-keys/" user-emacs-directory))
+ (require 'xah-fly-keys)
+ (xah-fly-keys-set-layout "qwerty")
+ (xah-fly-keys t)
+#+end_src
+
+however, it is now in non-gnu elpa! so i don't need this anymore.
+
+** Emacs 28 native compilation
+
+[[info:elisp#Native Compilation][elisp#Native Compilation]]
+
+This is a new feature in Emacs 28 that will compile all of the Elisp as native
+machine code, rather than byte-code, which can result in major performance boosts.
+Compilation will happen in the background and is logged to the
+=*Async-native-compile-log*= buffer if you are curious. Mostly you shouldn't
+have to worry about it, though you may see some compilation warnings at times.
+
+#+begin_src emacs-lisp
+ (when (and (functionp #'native-comp-available-p) (native-comp-available-p))
+ (setq native-comp-always-compile t
+ package-native-compile t))
+#+end_src
+
+* Keybinding
+:PROPERTIES:
+:header-args:emacs-lisp+: :noweb-ref keybinding :noweb-sep "\n\n" :results silent
+:END:
+
+Keybindings are the key to playing Emacs like an instrument. no matter
+what you choose, keep in mind that you can always bind keys to your
+most commonly used commands to make things convienient.
+
+I highly recommend creating a personal key map bound to a "leader key".
+You initiate it with the leader, and then bind following key sequences
+to commands you use. creating your own will make it easier to remember
+and keep organized.
+
+** xah-fly-keys
+
+This is what I adopted to combat RSI. my muscle memory is tied into it
+tightly right now. you may have other opinions about keybindings
+
+#+begin_src emacs-lisp
+ ;; these need to be set before requiring the package
+ (setq xah-fly-use-control-key nil
+ xah-fly-use-meta-key nil)
+ (package-install 'xah-fly-keys)
+ (require 'xah-fly-keys)
+ (xah-fly-keys-set-layout "qwerty")
+ (xah-fly-keys t)
+#+end_src
+
+i'm setting it up early in the config so that its keymaps are available
+to modify / integrate with other packages.
+
+*** adding some custom commands to xah maps
+**** SPC 1 delete-other-windows
+
+i want this often, feels as if i'm constantly wanting that other window
+to go away.
+
+#+begin_src emacs-lisp
+ (define-key 'xah-fly-leader-key-map (kbd "1") #'delete-other-windows)
+#+end_src
+
+** with-map-defkey
+
+#+begin_src emacs-lisp
+ (defmacro with-map-defkey (keymap leader &rest pairs)
+ "Define a new KEYMAP with prefix key LEADER, and list of bindings in it."
+ (declare (indent 2))
+ `(progn
+ (defvar ,keymap (make-sparse-keymap))
+ (define-prefix-command (quote ,keymap))
+ (global-set-key (kbd ,leader) ,keymap)
+ (mapc (lambda (pair)
+ (define-key ,keymap
+ (kbd (if (numberp (car pair)) (number-to-string (car pair))
+ (symbol-name (car pair))))
+ (cadr pair)))
+ (quote ,(seq-partition pairs 2)))))
+
+ (defvar *my-config* "~/projects/shoshimacs/shoshin-config.org"
+ "Path to my main configuration file.")
+
+ (defun my-configuration ()
+ (interactive)
+ (find-file *my-config*))
+
+ (defun my-reload-config ()
+ "Tangles and reloads a literate config with `org-babel-load-file'"
+ (interactive)
+ (org-babel-load-file *my-config*))
+
+ (with-map-defkey my-key-map "M-m"
+ 1 delete-other-windows
+ a apropos
+ b consult-buffer
+ c my-configuration
+ d embark-act
+ e eshell
+ f find-file
+ g magit
+ h info
+ i consult-imenu
+ j describe-function
+ k describe-variable
+ n tab-next
+ s consult-ripgrep
+ t consult-theme
+ w which-key-mode
+ <f1> my-reload-config)
+#+end_src
+
+** COMMENT bind-map
+
+there is a package available in nongnu elpa that offers a macro that
+sort of generalizes the leader key idea. it also hooks into the evil package
+a bit to allow definition of bindings over different "states" that your
+editor might be in, like command or insert mode in xah-fly-keys. its fairly
+geared toward evil in that way, so i'm not sure how it will interact, but let us
+find out. the other option would be to make a simple macro of our own to hook
+into leader key maps.
+
+#+begin_src emacs-lisp
+ (package-install 'bind-map)
+
+ (bind-map my-keymap
+ :keys ("M-m"))
+
+ (bind-map my-org-map
+ :keys ("M-m m")
+ :major-modes (org-mode)
+ :bindings ("," #'org-insert-structure-template))
+
+ (bind-map my-elisp-map
+ :keys ("M-m m")
+ :major-modes (emacs-lisp-mode
+ lisp-interaction-mode)
+ :bindings ("e" #'edebug-instrument-function))
+
+ (bind-map my-ruby-map
+ :keys ("M-m m")
+ :major-modes (ruby-mode)
+ :bindings ("d" #'ruby-beginning-of-defun))
+
+ (bind-map-set-keys my-keymap
+ "b" #'consult-buffer
+ "c" #'my-config
+ "g" #'magit
+ "j" #'consult-grep
+ "k" #'consult-imenu
+ "n" #'tab-next
+ "t" #'consult-theme)
+#+end_src
+
+* Completion
+:PROPERTIES:
+:header-args:emacs-lisp: :noweb-ref completion :noweb-sep "\n\n" :results silent
+:END:
+
+Completion is a huge part of my experience using Emacs. I have been on
+an evolving journey of from the basic type of terminal tab completion
+to spaceship level UI implemented as almost a sub-application in Emacs.
+
+This configuration is aiming at using a new crop of completion enhancements
+that tie into Emacs's native completion API. This is a more modular approach
+that allows a sort of composition of extensions to completion behavior and
+its appearance in the user interface.
+
+** Two kinds of completion
+
+I want to point out that there are two distinct but similar features
+both grouped under the concept of "completion". The first is *Minibuffer*
+completion. Any time you use the minibuffer to enter commands or arguments,
+there is a completion system available to help you enter text there.
+The second is *Buffer* completion, offering candidates for text you are
+typing in any buffer. Code completion provided by a language server
+is one example. In vanilla Emacs, you get [[info:emacs#Symbol Completion][Symbol Completion]]
+for free, since Emacs itself is a running Lisp process with knowledge of
+all the defined symbols in the system.
+
+I've been confused by this in the past, because the features are so similar.
+However, completing text in an arbitrary buffer really depends on context,
+and it is much more complex than completing commands and arguments that are
+appropriate to a specific situation.
+
+** Emacs completion styles
+
+Emacs has a quite sophisticated way of selecting candidates for completion.
+You can read about them here: [[info:emacs#Completion Styles][emacs#Completion Styles]]
+
+I've grown used to the =flex= style of completion where typing
+=pr/s/sho.o= at the find file prompt expands to
+=projects/shoshimacs/shoshin-config.org=. There are other alternatives
+and you can even write your own. The ~completion-styles~ is a list of
+all the styles you'd like to use. It starts at the front, and if no matches
+are found, moves to the next style of completion. In this config, I just
+added =flex= to the front of the default completion styles.
+
+#+begin_src emacs-lisp
+ (setq completion-styles '(flex basic partial-completion emacs22)
+ completion-cycle-threshold 3
+ tab-always-indent 'complete)
+#+end_src
+
+~completion-cycle-threshold~ defines when you want to just cycle through
+alternatives on each <TAB> (or whatever key you use) rather than presenting
+options. Setting it to 3 means if my options are "FOO, FOP, FOR" or less,
+hitting complete will change FOO->FOP, FOP->FOR, FOR->FOO.
+
+~tab-always-indent~ changes the behavior of the TAB key:
+
+#+begin_quote
+ If ‘complete’, TAB first tries to indent the current line, and if the line
+ was already indented, then try to complete the thing at point.
+#+end_quote
+
+** [[info:consult#Top][consult]] - Consulting [[info:elisp#Minibuffer Completion][completing-read]]
+
+consult offers enhanced completion similar to ivy and helm, but with the
+built in completing read functionality of the minibuffer.
+
+#+begin_src emacs-lisp
+ (package-install 'consult)
+#+end_src
+
+main entry point would be ~consult-buffer~. however, there are many consult
+commands that can enhance any completing read function.
+
+*** "Virtual Buffers"
+
+it introduces this concept of "Virtual Buffers", but i'm not certain what
+it means. consult "supports ... narrowing to the virtual buffer types".
+
+perhaps a Virtual Buffer is a "grouping" of actual Emacs buffers or "things"
+that can be materialized in a buffer. For example, I can ~consult-buffer~
+and press ~m SPC~ to narrow the "buffer list" to any bookmarks.
+
+*** consult keybindings
+
+#+begin_src emacs-lisp
+ (global-set-key (kbd "C-x b") #'consult-buffer)
+ (define-key xah-fly-leader-key-map (kbd "f") #'consult-buffer)
+ (define-key xah-fly-command-map (kbd "n") #'consult-line)
+#+end_src
+
+*** consult-themes
+
+i had a bit of a mess with it at first, because i'd implemented my own
+solution to a quirk of theme loading. enabling themes is additive,
+and can cause unexpected results. so i added [[info:elisp#Advising Functions][advice]]
+to ~load-theme~ to automatically disable the old one before enabling
+the new.
+
+it seems like ~consult-theme~ does this as well. additionally, as
+it will preview the theme as you are narrowing the selection. i did not
+expect this behavior and it got all kinds of wonky. the manual has a
+nice example of delaying the theme-switch-preview since it is slow.
+this way you can scroll / narrow your list of themes without the colors
+changing with every keypress.
+
+#+begin_src emacs-lisp
+ (with-eval-after-load 'consult
+ (consult-customize consult-theme :preview-key '(:debounce 0.5 any))
+ (setq consult-themes my-chosen-themes))
+#+end_src
+
+*** TODO consult-project-buffer
+
+how do project buffers get filtered? i'm seeing buffers assigned to a project
+that in my mind, shouldn't be.
+
+looks like it interfaces with ~project-switch-to-buffer~ which has its own
+logic about which project a buffer belongs to. some of the mistakes i was seeing
+earlier were simply due to starting a repl in a particular directory.
+
+it appears that "special" buffers may get assigned to a particular project as
+well. for example the EWW buffer is part of a project, but it is unclear as
+to why. appears likely to have to do with the behavior of the ~default-directory~
+variable which is buffer-local.
+
+i may want to figure out ways to mark "special" buffers as having a non-project
+default-directory set so they don't show up, or just filter them out if it
+becomes annoying. i'm accustomed to ~perspectives~ provided by a MELPA package
+that hooked into ~projectile~'s project definitions. it would keep a list of
+perspective-local buffers where the perspective was tied to a project.
+
+** embark
+
+#+begin_src emacs-lisp
+ (package-install 'embark)
+ (package-install 'embark-consult)
+ (global-set-key (kbd "C-;") #'embark-act)
+ (setq prefix-help-command #'embark-prefix-help-command)
+#+end_src
+
+** marginalia
+
+#+begin_src emacs-lisp
+ (package-install 'marginalia)
+ (marginalia-mode)
+#+end_src
+
+** vertico
+
+#+begin_src emacs-lisp
+ (package-install 'vertico)
+ (setq minibuffer-prompt-properties
+ '(read-only t cursor-intangible t face minibuffer-prompt))
+ (add-hook 'minibuffer-setup-hook #'cursor-intangible-mode)
+ (setq read-extended-command-predicate
+ #'command-completion-default-include-p)
+ (setq enable-recursive-minibuffers t)
+ (vertico-mode)
+#+end_src
+
+*** vertico-directory
+
+i'd like to emulate the behavior in ~find-file~ that i'm used to from Ivy.
+basically, when i press DEL it should act normally until i hit a directory
+boundary, then it should jump up a dir with the following press.
+
+this is implemented with the ~vertico-directory~ extension.
+
+#+begin_src emacs-lisp
+ (require 'vertico-directory)
+ (define-key vertico-map (kbd "RET") #'vertico-directory-enter)
+ (define-key vertico-map (kbd "DEL") #'vertico-directory-delete-char)
+ (define-key vertico-map (kbd "M-DEL") #'vertico-directory-delete-word)
+ (define-key vertico-map (kbd "M-j") #'vertico-quick-insert)
+#+end_src
+
+** corfu
+
+#+begin_src emacs-lisp
+ (package-install 'corfu)
+ (setq corfu-auto t
+ corfu-cycle t
+ corfu-quit-no-match t)
+ (global-corfu-mode t)
+#+end_src
+
+*** corfu-terminal enables in terminal interface
+
+#+begin_src emacs-lisp
+ (package-install 'corfu-terminal)
+ (unless (display-graphic-p)
+ (corfu-terminal-mode +1))
+#+end_src
+** which-key
+
+which-key is an excellent package that helps provide guide posts for command
+discoverability. many key commands in Emacs are in sequences. for example,
+~org-babel-tangle~ is ~C-c C-v t~. as a user, the commands you use often
+become muscle memory, or you map them to something more convienient. but
+sometimes you know there is some command to do what you want but you don't
+quite remember what the sequence is. or perhaps you're in a new major-mode
+and you know there must be several handy commands under ~C-c~. ~which-key~
+pops up a buffer with a listing of all the possible continuations from where
+you are in a key sequence. for that reason, it can be useful at times even
+for experienced users.
+
+this config installs which-key, but does not activate it automatically.
+some advice from Daniel Mendler (consult author) suggested that limiting the
+amount Emacs pops things up automatically is a better user experience.
+which-key is just a toggle away when needed, and there is also [[*embark][embark]]
+which has a command to show prefix key continuations.
+
+#+begin_src emacs-lisp
+ (package-install 'which-key)
+ (which-key-mode)
+#+end_src
+
+* Editing
+:PROPERTIES:
+:header-args:emacs-lisp: :noweb-ref editing :noweb-sep "\n\n" :results silent
+:END:
+** [[info:emacs#Matching][electric pair mode]]
+I've been using smartparens -> (bookmark-jump "smartparens package") in my
+main config. electric pair mode does some of what smartparens does out of
+the box. what i'm missing is the generalized ~sp-hybrid-slurp~ or
+whatever it was called. but using the built in is good for now. further
+config might get what i want with vanilla built ins.
+
+#+begin_src emacs-lisp
+ (electric-pair-mode)
+#+end_src
+
+** markdown mode
+#+begin_src emacs-lisp
+ (package-install 'markdown-mode)
+#+end_src
+
+** org mode
+*** jump to top level parent heading
+
+a friend was wanting this functionality, so i dug around in the org functions
+to find one i could build a command out of:
+
+#+begin_src emacs-lisp
+ (defun my-org-top-level-heading ()
+ (interactive)
+ (let ((moo 1))
+ (while moo (setq moo (org-up-heading-safe)))))
+#+end_src
+
+~org-up-heading-safe~ is designed not to throw an error and returns the level
+of the headline found (as it goes up) or nil if no higher level is found.
+this just uses a dumb while loop to call it until it returns nil, which should
+get us where we are looking to go 😃
+
+*** exporting
+#+begin_src
+ (require 'ox-md)
+#+end_src
+**** htmilze
+
+this seems to be required to fontify source blocks
+
+#+begin_src emacs-lisp
+ (package-install 'htmlize)
+#+end_src
+
+** recentf-mode
+
+this tracks recently operated on files (by default) and enables quick selection
+from them in various Emacs menus. [[*\[\[info:consult#Top\]\[consult\]\] - Consulting \[\[info:elisp#Minibuffer Completion\]\[completing-read\]\]][consult]] hooks into it as well.
+
+#+begin_src emacs-lisp
+ (recentf-mode)
+#+end_src
+
+** tabs and spaces
+
+#+begin_src emacs-lisp
+ (setq indent-tabs-mode nil)
+#+end_src
+
+* Programming
+:PROPERTIES:
+:header-args:emacs-lisp: :noweb-ref programming :noweb-sep "\n\n" :results silent
+:END:
+** Languages
+*** Common Lisp
+#+begin_src emacs-lisp
+ (package-install 'sly)
+#+end_src
+
+*** Javascript
+
+#+begin_src emacs-lisp
+ (package-install 'json-mode)
+#+end_src
+
+*** Ruby
+**** inf-ruby
+
+inf-ruby provides an interface to the various REPLs available in the Ruby-verse
+its currently provided by non-gnu ELPA:
+
+#+begin_src emacs-lisp
+ (package-install 'inf-ruby)
+#+end_src
+
+** Dev Docs
+#+begin_src emacs-lisp
+ (package-install 'devdocs)
+#+end_src
+* Projects
+:PROPERTIES:
+:header-args:emacs-lisp: :noweb-ref projects :noweb-sep "\n\n" :results silent
+:END:
+
+** project.el
+
+~project.el~ is the built in project management tool. previously, I've used
+~projectile~, which is great, but some of the more recent tools (like eglot)
+use the built in ~project.el~ api for their features.
+
+I've got the ~project-prefix-map~ on the key =p= in [[*with-map-defkey][my-key-map]].
+
+** version control
+*** magit
+
+its the best! 🪄
+
+#+begin_src emacs-lisp
+ (package-install 'magit)
+#+end_src
+* External Services
+:PROPERTIES:
+:header-args:emacs-lisp: :noweb-ref external-services :noweb-sep "\n\n" :results silent
+:END:
+
+Packages that enable communication via HTTP or connect with external APIs or other
+resources outside of Emacs and/or the local machine.
+
+** plz - http library
+
+this is an http library that intends to solve some of the "pain points" of url.el.
+i ran into some of them trying to download and install the Victor Mono font used
+by my configuration. the downside of ~plz~ is that it is dependent on ~curl~, rather
+than being pure elisp. however, this is a non-issue for me, especially since my
+use case had devolved into using ~make-process~ to call ~wget~ and then implement
+a "callback" with a process sentinel. kinda neat, but maybe too much.
+
+#+begin_src emacs-lisp
+ (package-install 'plz)
+#+end_src
+
+the sourcehut package in this config also depends on ~plz~
+
+** sourcehut
+there's a new package in GNU ELPA for some basic interaction with the sr.ht http api.
+i'm interested to try it out since i still pay for the account, plus the forge is
+free software and could be self-hosted if it comes to it.
+
+it also depends on ~plz~ which is another new package providing a nicer API for
+HTTP requests.
+
+#+begin_src emacs-lisp
+ (package-install 'srht)
+ (setq srht-username "shoshin")
+#+end_src
+
+an API token is stored in my ~.authinfo~ file.
+
+* UI
+:PROPERTIES:
+:header-args:emacs-lisp: :noweb-ref user-interface :noweb-sep "\n\n" :results silent
+:END:
+** basic Emacs UI tweaks
+
+#+begin_src emacs-lisp
+ (when (display-graphic-p)
+ (scroll-bar-mode -1)
+ (fringe-mode '(8 . 0)))
+
+ (tab-bar-mode t)
+ (display-battery-mode t)
+#+end_src
+
+** darkroom - distraction free writing
+
+the notes suggest using ~darkroom-tentative-mode~ which auto switches
+depending on the window layout currently in use.
+
+#+begin_src emacs-lisp
+ (package-install 'darkroom)
+#+end_src
+
+** Fonts
+For code, I've grown fond of Victor Mono.
+
+#+begin_src emacs-lisp
+ (set-frame-font "Victor Mono")
+#+end_src
+
+*** COMMENT Attempt to install the font via Emacs, url.el and ~make-process~
+
+in the end, this "works" but isn't very useful. the font cache needs to be updated
+before Emacs runs for the font to register anyway. This will instead be implemented
+as a shell script that can be run as a pre-req before initializing emacs.
+
+however, i did learn a bit about [[info:elisp#Sentinels][Sentinels]] they are kinda neat.
+
+#+begin_src emacs-lisp
+ ;; this actually doesn't work right, because the process unzipping starts
+ ;; before the file is completely written i think.
+ (url-retrieve "https://rubjo.github.io/victor-mono/VictorMonoAll.zip"
+ #'victor-mono-download-callback)
+
+ (make-process :name "getting victor mono"
+ :buffer "*Download Victor Mono*"
+ :command '("wget" "--output-document=/home/shoshin/.fonts/VictorMonoAll.zip"
+ "https://rubjo.github.io/victor-mono/VictorMonoAll.zip")
+ :sentinel #'victor-mono-download-callback)
+
+ (defun victor-mono-download-callback (process event)
+ (if (string-equal "finished\n" event)
+ (let ((default-directory "~/.fonts/VictorMono"))
+ (unless (file-directory-p default-directory)
+ (make-directory default-directory))
+ (make-process :name "unzipping victor mono"
+ :buffer "*Unzip Victor Mono*"
+ :command `("unzip" ,(expand-file-name "~/.fonts/VictorMonoAll.zip"))
+ :sentinel #'victor-mono-sentinel))))
+
+ (defun victor-mono-sentinel (process event)
+ (print event)
+ (if (string-equal "finished\n" event)
+ (progn (message "works!")
+ (make-process :name "run fc-cache" :command '("fc-cache")))))
+#+end_src
+** Highlights
+*** [[help:global-hl-line-mode][global-hl-mode]]
+i enjoy having the current line highighted as a visual cue.
+
+#+begin_src emacs-lisp
+ (global-hl-line-mode t)
+#+end_src
+
+can be toggled with <leader> l 2
+
+*** COMMENT lin-global-mode
+Make `hl-line-mode' more suitable for selection UIs
+
+add other hooks to ~lin-mode-hooks~
+
+#+begin_src emacs-lisp
+ (setq my-lin-mode-hooks
+ '())
+#+end_src
+
+#+begin_src emacs-lisp
+ (package-install 'lin)
+ (require 'lin)
+ (setq lin-face 'lin-blue)
+ (mapc (lambda (e) (cl-pushnew e lin-mode-hooks)) my-lin-mode-hooks)
+ (lin-global-mode)
+#+end_src
+** Themes
+*** theme packages / installation
+
+to keep it concise, i'll define a special variable to hold the theme packages
+i'd like to install anytime this config is loaded on a system where they are
+not there. then i can ~mapc~ #'package-install over the list of themes.
+
+#+begin_src emacs-lisp :noweb-ref defvars
+ (defvar my-themes-to-install
+ '(cyberpunk-theme dracula-theme nano-theme)
+ "List of themes to install when loading shoshimacs config.")
+#+end_src
+
+#+begin_src emacs-lisp
+ (load-theme (seq-random-elt my-chosen-themes))
+#+end_src
+
+*** chosen theme list and random loading on init
+
+i generally haven't used built-in themes much, but there's a few i like,
+and the ones i specifically install i'd like to keep in a list of "chosen"
+ones. i can load one at random if i please, and perhaps provide it as
+candidates to ~consult-themes~.
+
+#+begin_src emacs-lisp :noweb-ref defvars
+ (defvar my-chosen-themes
+ '(cyberpunk dichromacy dracula leuven modus-operandi modus-vivendi
+ nano-dark nano-light tango tango-dark)
+ "List of themes I prefer for narrowing and random selection.")
+#+end_src
+
+#+begin_src emacs-lisp
+ (mapc #'package-install my-themes-to-install)
+#+end_src
+
+** windresize
+
+#+begin_src emacs-lisp
+ (package-install 'windresize)
+#+end_src
+
+