Compare commits

..

No commits in common. "c20eda48a82a564368b9e5775b44c14d41e96c4a" and "d30ae9a78b91b23cf98cd840bb579af07400bcda" have entirely different histories.

15 changed files with 145 additions and 234 deletions

View file

@ -6,7 +6,7 @@
A literate programming file for bootstraping my Emacs Configuration.
#+begin_src emacs-lisp :exports none
;;; bootstrap.el --- file for bootstraping my Emacs Configuration -*- lexical-binding: t; -*-
;;; bootstrap.el --- file for bootstraping my Emacs Configuration
;;
;; ██████████
;; ░░███░░░░░█
@ -51,7 +51,7 @@ Limit garbage collection before startup and then go back to the default value (8
(add-hook 'emacs-startup-hook
(lambda ()
(setq gc-cons-threshold (* 200 1024 1024))))
(setq gc-cons-threshold (* 100 1024 1024))))
#+END_SRC
** OS Path and Native Compilation
@ -167,7 +167,7 @@ Much of my more complicated code comes from my website essays and other projects
#+end_src
* Emacs Server Control
I actually run two instances of Emacs on some systems, where one instance has all my work-related projects, perspectives, and packages installed (like the Language Server Protocol, LSP), and my personal instance has other packages running (like the Internet Relay Chat, IRC, and Mail). I need a function that can make that distinction, and based on that, it will set =server-start= appropriately, so that =emacsclient= can call into the correct one.
I actually run two instances of Emacs on some systems, where one instance has all my work-related projects, perspectives, and packages installed (like LSP), and my personal instance has other packages running (like IRC and Mail). I need a function that can make that distinction, and based on that, it will set =server-start= appropriately, so that =emacsclient= can call into the correct one.
#+begin_src emacs-lisp
(defun ha-emacs-for-work? ()
"Return non-nil when the Emacs instance is for work.
@ -210,6 +210,7 @@ The following /defines/ the rest of my org-mode literate files, that I load late
"ha-org-literate.org"
"ha-org-clipboard.org"
"ha-capturing-notes.org"
"ha-code-notes.org"
"ha-agendas.org"
"ha-data.org"
"ha-passwords.org"
@ -229,7 +230,6 @@ The following /defines/ the rest of my org-mode literate files, that I load late
"ha-org-publishing.org"
"ha-email.org"
"ha-aux-apps.org"))
"ha-code-notes.org"
"ha-dashboard.org"))
"List of org files that complete the hamacs project.")
#+end_src
@ -241,7 +241,7 @@ The list of /hamacs/ org-formatted files stored in =ha-hamacs-files= is selectiv
(if (not all)
ha-hamacs-files
(thread-last (rx (not ".") (+? any) ".org" string-end)
(thread-last (rx ".org" string-end)
(directory-files hamacs-source-dir nil)
(append ha-hamacs-files)
(--filter (not (string-match (rx "README") it)))

View file

@ -158,8 +158,14 @@ And point Emacs to it:
(setq agent-shell-anthropic-claude-acp-command
(if (file-exists-p "/opt/homebrew")
(file-expand-wildcards "/opt/homebrew/bin/claude-agent-acp")
'("/usr/local/bin/claude-agent-acp"))))
(list (file-expand-wildcards "/opt/homebrew/bin/claude-agent-acp"))
'("/usr/local/bin/claude-agent-acp")))
(when (file-exists-p "~/.zshenv-work")
(setq agent-shell-anthropic-claude-environment (agent-shell-make-environment-variables
:load-env "~/.zshenv-work"))))
;; /opt/homebrew/Cellar/node/26.0.0/bin/claude-agent-acp
#+END_SRC
*** Cursor
@ -221,6 +227,36 @@ And let’s make that the default now:
:config
(setq agent-shell-preferred-agent-config (agent-shell-google-make-gemini-config)))
#+END_SRC
** AI Code Interface
While the =agent-shell= offers a /vibe-codey/ interface to Chatbots, the [[https://github.com/tninja/ai-code-interface.el][ai-code-interface]] offers a more /programmatic/ interface.
#+BEGIN_SRC emacs-lisp
(use-package ai-code
:straight (:host github :repo "tninja/ai-code-interface.el")
:config
;; use codex as backend, other options are 'claude-code, 'gemini,
;; 'github-copilot-cli, 'opencode, 'grok, 'cursor, 'kiro,
;; 'codebuddy, 'aider, 'eca, 'agent-shell, 'claude-code-ide,
;; 'claude-code-el
(ai-code-set-backend 'gemini)
;; Enable global keybinding for the main menu
(global-set-key (kbd "C-c a") #'ai-code-menu)
;; Optional: Enable @ file completion in comments and AI sessions
(ai-code-prompt-filepath-completion-mode 1)
;; Optional: Ask AI to run test after code changes, for a tighter build-test loop
;; (setq ai-code-auto-test-type 'ask-me)
;; Optional: In AI session buffers, SPC in Evil normal state triggers the prompt-enter UI
;; (with-eval-after-load 'evil (ai-code-backends-infra-evil-setup))
;; Optional: Set up Magit integration for AI commands in Magit popups
(with-eval-after-load 'magit
(ai-code-magit-setup-transients)))
#+END_SRC
* Git and Magit
Can not live without [[https://magit.vc/][Magit]], a Git porcelain for Emacs. I stole the bulk of this work from Doom Emacs.
#+begin_src emacs-lisp

View file

@ -63,22 +63,6 @@ This allows me to /wax poetic/ with a parallel, but separate org file. Of course
If this isn’t good for you, check out [[https://github.com/agoodman42/montag][Montag]]. Same project, different approach using a single directory for all notes with [[https://www.orgroam.com/][org-roam]].
Let’s create a pattern for what a notes file is, and how to recognize them:
#+BEGIN_SRC emacs-lisp
(defconst ha-code-notes-rx (rx (optional "/")
"." (one-or-more (not "/")) "-notes.org" string-end))
(defun ha-code-notes-file (file &optional parent)
"Return a FILE's 'code notes' filename.
Prepend the PARENT if given."
(cond
((and parent (string-match-p (rx "/" string-end) parent))
(format "%s.%s-notes.org" parent file))
(parent (format "%s/.%s-notes.org" parent file))
(t (format ".%s-notes.org" file))))
#+END_SRC
Another feature when looking at the notes in the org buffer, is to hit the same key to return to the source code file referencing the notes.
# TODO Create custom settings to override default behavior.
@ -125,8 +109,7 @@ This was far gnarlier than I originally thought, since IMenu only wants to /inte
(file qualified-name offset)"
(let* ((here (point))
(entry (ignore-errors
(thread-last (imenu--make-index-alist t)
(entry (thread-last (imenu--make-index-alist t)
;; Flatten hierarchy labels with dot separators:
(ha-code-notes-location--flatten-index)
;; Filter to only entries that occur after point:
@ -136,7 +119,7 @@ This was far gnarlier than I originally thought, since IMenu only wants to /inte
;; doesn't guarantee the order):
(seq-sort-by #'cdr #'>)
;; And the first entry on the list is our goal:
car))))
car)))
(unless entry
(error "No enclosing definition found for point"))
(list (buffer-file-name)
@ -148,8 +131,8 @@ The needed /trick/ is to flatten this IMenu hierarchy using this recursive beaut
#+BEGIN_SRC emacs-lisp
(defun ha-code-notes-location--flatten-index (alist &optional prefix)
"Flatten imenu ALIST into a list of (NAME . POSITION).
Where the name matches what which-function/imenu expect.
"Flatten imenu ALIST into a list of (QUALIFIED-NAME . POSITION).
Where the qualified-name matches what which-function/imenu expect.
For instance:
@ -159,87 +142,28 @@ The needed /trick/ is to flatten this IMenu hierarchy using this recursive beaut
((\"foo_class.method_one\" ...) (\"foo_class.method_two\" ...)...)
Called recursively, where PREFIX could be a class name, or other higher
abstraction when the nesting represents a real outline (Org, Markdown).
Entries tagged with `imenu-kind' or `breadcrumb-kind' property (as Eglot
nests a function's local variables for Python) are already a flat
namespace of functions/variables/constants, so their own names are kept
bare and not qualified by an enclosing function's name."
This is called recursively, so PREFIX could be a class name, or
other higher abstraction."
;; Like `mapconcat' but lets us concat into something other than a string.
;; Note that `mapcan' uses `nconc' which _mutates_ the `alist'.
;; This is fine as a parameter that we then return:
(mapcan
(lambda (entry)
(unless (or (null entry) (atom entry))
(let* ((raw-name (car entry))
(kind (and (stringp raw-name)
(or (get-text-property 0 'imenu-kind raw-name)
(get-text-property 0 'breadcrumb-kind raw-name))))
(name (if (stringp raw-name)
(replace-regexp-in-string
;; Some imenu backends (e.g. python.el) annotate names with their
;; category, e.g. "Pair (class)" or "sum (def)". Strip that so
;; names match what `which-function'/`add-log-current-defun'
;; produce, and what gets stored as XREF_NAME in notes files.
(let* ((name (replace-regexp-in-string
(rx space "(" (one-or-more alpha) ")" string-end)
"" (substring-no-properties raw-name))
(format "%s" raw-name)))
"" (car entry)))
(value (cdr entry))
(qualified (if (and prefix (not kind)) (format "%s.%s" prefix name) name)))
(cond
;; Case 1: Nested submenu (list of alist entries). Eglot
;; never gives the container itself a position among its
;; children, as Org does; it stashes it in the
;; `imenu-region' text property instead, so recover it
;; here. Children only inherit QUALIFIED as their prefix
;; when this entry has no `imenu-kind' of its own -- i.e.
;; when the nesting is a real outline, not Eglot's flat
;; function/variable/constant tagging.
((and (listp value) (consp (car value)))
(append
(let ((region (and (stringp raw-name)
(get-text-property 0 'imenu-region raw-name))))
(when region (list (cons qualified (car region)))))
(ha-code-notes-location--flatten-index value (unless kind qualified))))
;; Case 2: Direct marker or integer position
((integer-or-marker-p value)
(list (cons qualified (if (markerp value) (marker-position value) value))))
;; Case 3: Overlay or element containing a position in car/cdr
((overlayp value)
(list (cons qualified (overlay-start value))))
((and (consp value) (integer-or-marker-p (car value)))
(list (cons qualified (if (markerp (car value))
(marker-position (car value))
(car value)))))
;; Fallback: ignore non-positional Imenu metadata entries
(t nil)))))
(qualified (if prefix (format "%s.%s" prefix name) name)))
(if (listp value)
(ha-code-notes-location--flatten-index value qualified)
(list (cons qualified (if (markerp value) (marker-position value) value))))))
alist))
#+END_SRC
This flatten feature has been a pain in my side. An org-mode formatted file works well, for instance, running the following on this document:
#+BEGIN_SRC emacs-lisp :tangle no :results replace value raw :export both :wrap example
(ha-code-notes-location--flatten-index (imenu--make-index-alist t))
#+END_SRC
#+RESULTS:
#+begin_example
((*Rescan* . -99) (Introduction . 946) (Helper Functions.Relative Code Locations . 3719) (Helper Functions.Org Properties . 13220) (Helper Functions . 3592) (Write a Note.Return to Source Code . 22408) (Write a Note.Fringe Indicators for Notes . 24001) (Write a Note . 17005) (Technical Artifacts . 27464))
#+end_example
But running the same expression on a Python file (via Eglot) nests the local variables and parameters of each function as children in the index, each tagged with an =imenu-kind= text property on its name, e.g. a function like this:
#+begin_example
(#("parse_args" 0 10 (imenu-region (1245 . 1627) imenu-kind "Function" breadcrumb-region (1245 . 1627) breadcrumb-kind "Function"))
(#("argv" 0 4 (imenu-region (1260 . 1289) imenu-kind "Variable" ...)) . 1260)
(#("parser" 0 6 (imenu-region (1365 . 1371) imenu-kind "Variable" ...)) . 1365))
#+end_example
Naively flattening this treats =argv= and =parser= as if they were nested methods, producing useless entries like ~parse_args.argv~. Worse, the function itself never had its own position among its children (unlike Org, which gives a parent headline a self-pointing entry), so there was no way to jump straight to ~parse_args~ at all.
The fix: the presence of an =imenu-kind=/=breadcrumb-kind= property means the nesting is Eglot's flat function/variable/constant tagging, not a real outline -- so a child's name is never qualified by its parent's. When recursing into a nested submenu, the container's own position is recovered from its =imenu-region= text property, and the name is stripped of text properties. That turns the above into clean, bare entries for every name -- function, variable, and constant alike:
#+begin_example
((parse_args . 1245) (argv . 1260) (parser . 1365) (registry_credentials . 1630) ...)
#+end_example
Once inside a source file, we can jump to one of these /relative locations/:
#+BEGIN_SRC emacs-lisp
@ -252,19 +176,10 @@ Once inside a source file, we can jump to one of these /relative locations/:
(when (and file (not (equal file (buffer-file-name))))
(find-file-other-window file))
(condition-case t
(ha-code-notes--location-goto name offset)
(message "Definition `%s' no longer found in %s" name file))
(ignore-errors
))
(defun ha-code-notes--location-goto (name &optional offset)
"Use `imenu' interface to goto NAME location.
If OFFSET given, move that many lines below."
(let* ((index (ha-code-notes-location--flatten-index (imenu--make-index-alist t)))
(entry (assoc name index)))
(when entry
(if (not entry)
(message "Definition `%s' no longer found in %s" name file)
(goto-char (cdr entry))
(when offset
(forward-line offset)))))
@ -382,7 +297,8 @@ This function defines what the notes filename should look like, loads it in a si
;; Keep in mind the `orig-parent' has a final slash, so the
;; initial . here marks it as hidden:
(note-file (ha-code-notes-file orig-base orig-parent))
(note-file (format "%s.%s-notes.org"
orig-parent orig-base))
(header (which-function))
(offset (ha-code-notes-defun-rel-line)))
@ -406,7 +322,7 @@ Use the builtin autoinsert feature to inject a basic template at the beginning o
(use-package autoinsert
:config
(define-auto-insert
(cons ha-code-notes-rx "Org Notes Template")
(cons (rx "/." (one-or-more (not "/")) "-notes.org" string-end) "Org Notes Template")
'("Short description: "
"#+TITLE: "
(s-titleized-words (s-replace-regexp (rx (any "-" "_")) " "
@ -519,7 +435,10 @@ And give us keybinding that will either go to the notes (if we are in some code)
"Open the notes buffer, or return to the code."
(interactive)
(when (buffer-file-name)
(if (string-match ha-code-notes-rx (buffer-file-name))
(if (string-match (rx "/." ; A hidden file
(one-or-more (not "/"))
"-notes.org" string-end)
(buffer-file-name))
(ha-code-notes-return)
(ha-code-notes))))
@ -561,19 +480,14 @@ A code file with an associated notes file is easy to forget about. Let's mark, i
pair back to an absolute line via `ha-code-notes-location-goto', since the function
may have moved since the note was taken."
(mapc #'delete-overlay ha-code-notes--fringe-overlays)
(setq ha-code-notes--fringe-overlays nil)
(let* ((orig-file (buffer-file-name))
(note-file (and orig-file
(ha-code-notes-file
(format "%s.%s-notes.org"
(file-name-directory orig-file)
(file-name-base orig-file))))
notes)
;; Only run if this is an actual file AND its notes file exists:
(when (and orig-file
note-file
(file-exists-p note-file)
(not (string-match-p ha-code-notes-rx orig-file)))
(when (and note-file (file-exists-p note-file))
(with-temp-buffer
(insert-file-contents note-file)
(org-mode)
@ -602,7 +516,7 @@ New notes and edited notes should refresh the markers too, so we hook into savin
#+BEGIN_SRC emacs-lisp
(defun ha-code-notes--fringe-notes-refresh-all ()
"Refresh fringe note markers in every buffer after saving a notes file."
(when (string-match ha-code-notes-rx (buffer-file-name))
(when (string-match (rx "-notes.org" string-end) (buffer-file-name))
(dolist (buf (buffer-list))
(with-current-buffer buf
(when buffer-file-name

View file

@ -535,18 +535,17 @@ The nerd font package takes a popular font like "Iosevka" and jams a bunch of th
** Symbols and Emojis
Display these two symbols as one character, as using [[Ligatures]] often stretches wider, and the following are nice to be collapsed into a single glyph:
Display these two symbols as one character, as using [[Ligatures]] often stretches wider, and the following are nice to be collapsed:
#+begin_src emacs-lisp
(add-hook 'text-mode-hook (lambda ()
(dolist (pair '(("!?" . "‽")
("ae" . "æ")
("..." . "…") ; ??
("??" . "⁇")
("<<" . "«")
(">>" . "»")
(":-)" . "🙂")
(":-D" . "😃")
(";-)" . "😉")
("..." . "…")))
;; ("<<" . "«")
;; (">>" . "»")
("AE" . "Æ")))
(push pair prettify-symbols-alist))))
#+end_src

View file

@ -366,7 +366,7 @@ This expands on my global [[file:ha-config.org::*Bookmarks][Bookmarks]]:
#+begin_src emacs-lisp
(use-package bookmark-in-project
:bind
:bindd
(("C-x r m" . bookmark-in-project-toggle)
("C-x r M" . ha-bookmark-set))
:config

View file

@ -2,7 +2,7 @@
#+author: Howard Abrams
#+date: 2024-07-07
#+filetags: emacs hamacs
#+lastmod: [2026-09-22 Tue]
#+lastmod: [2026-08-05 Wed]
A literate programming file for literate programming in Emacs Org Files.
@ -19,15 +19,16 @@ A literate programming file for literate programming in Emacs Org Files.
;;
;; While obvious, GNU Emacs does not include this file or project.
;;
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
;; ~/src/hamacs/ha-org-literate.org
;; Using `find-file-at-point', and tangle the file to recreate this.
;;
;;; Commentary:
;;
;; This file contains a collection of functions to easy some of the
;; sharp edges when doing literate programming in Org files.
;;
;; *NB:* Do not edit this file. Instead, edit the original
;; literate file at:
;; ~/src/hamacs/ha-org-literate.org
;; And tangle the file to recreate this one.
;;
;;; Code:
#+end_src
* Introduction
@ -936,9 +937,13 @@ Let's =provide= a name so we can =require= this file:
#+DESCRIPTION: literate programming in Emacs Org Files.
#+PROPERTY: header-args:sh :tangle no
#+PROPERTY: header-args:emacs-lisp :tangle yes
#+PROPERTY: header-args:emacs-lisp :tangle yes :comments link
#+PROPERTY: header-args :results none :eval no-export :comments no mkdirp yes
#+OPTIONS: num:nil toc:t todo:nil tasks:nil tags:nil date:nil
#+OPTIONS: skip:nil author:nil email:nil creator:nil timestamp:nil
#+INFOJS_OPT: view:nil toc:nil ltoc:t mouse:underline buttons:0 path:http://orgmode.org/org-info.js
# Local Variables:
# jinx-local-words: "parseable"
# End:

View file

@ -3,7 +3,7 @@
#+date: 2020-09-18
#+tags: emacs org
#+startup: inlineimages
#+lastmod: [2026-10-09 Fri]
#+lastmod: [2026-08-10 Mon]
A literate programming file for configuring org-mode and those files.
@ -940,7 +940,7 @@ Since the /definitions/ do not work, so let's use the [[https://github.com/abo-a
#+begin_src emacs-lisp
(use-package define-word
:config
(ha-leader
(ha-leader :keymaps 'text-mode-map
"s d" '(:ignore t :which-key "dictionary")
"s d d" '("define this word" . define-word-at-point)
"s d a" '("define any word" . define-word)))
@ -1183,8 +1183,7 @@ I create a configuration file in my home directory:
"stop-words": false,
"terminology": { "severity": "warning" },
"unexpanded-acronym": { "severity": "warning" },
"write-good": false,
"unexpanded-acronym": false
"write-good": false
}
}
#+end_src

View file

@ -1498,6 +1498,16 @@ Integration with the [[https://github.com/bash-lsp/bash-language-server][Bash LS
#+begin_src sh
brew install bash-language-server
#+end_src
*** Fish Shell
I think the [[https://fishshell.com/][fish shell]] is an interesting experiment (and I appreciate the basics that come with [[https://github.com/emacsmirror/fish-mode][fish-mode]]).
#+begin_src emacs-lisp
(use-package fish-mode
:mode (rx ".fish" eol)
:config
(ha-auto-insert-file (rx ".fish") "fish-mode.sh")
:hook
(fish-mode . (lambda () (add-hook 'before-save-hook 'fish_indent-before-save))))
#+end_src
* Technical Artifacts :noexport:
Provide a name to =require= this code.
#+begin_src emacs-lisp :exports none

View file

@ -124,7 +124,7 @@ I'm not giving up on Eshell, but I am playing around with [[https://github.com/a
VTerm has an issue (at least for me) with ~M-Backspace~ not deleting the previous word, and yeah, I want to make sure that both keystrokes do the same thing.
#+begin_src emacs-lisp :tangle no
#+begin_src emacs-lisp
(use-package vterm
:config
(setq vterm-shell "zsh"
@ -162,7 +162,7 @@ An odd use case I have: working in a Terminal session in one buffer window, and
Now, I can type: ~s-G~ (with the shift), select the line with Avy, and type ~N~ to have it copy/paste into the buffer:
#+BEGIN_SRC emacs-lisp :tangle no
#+BEGIN_SRC emacs-lisp
(use-package vterm
:config
(defun ha-vterm-avy-paste-line ()
@ -180,7 +180,7 @@ Now, I can type: ~s-G~ (with the shift), select the line with Avy, and type ~N~
** Eat
While not as fast as [[https://github.com/akermu/emacs-libvterm][vterm]], the [[https://codeberg.org/akib/emacs-eat][Emulate a Terminal]] project (eat) is fast enough, and doesn’t require a dedicate library that requires re-compilation. While offering [[https://elpa.nongnu.org/nongnu-devel/doc/eat.html][online documentation]], I’m glad for an [[info:eat#Top][Info version]].
#+BEGIN_SRC emacs-lisp
#+BEGIN_SRC emacs-lisp :tangle no
(use-package eat
:straight (:host codeberg :repo "akib/emacs-eat"
:files ("*.el" ("term" "term/*.el") "*.texi"
@ -192,25 +192,6 @@ While not as fast as [[https://github.com/akermu/emacs-libvterm][vterm]], the [[
:bind (:map eat-semi-char-mode-map
("C-c C-t" . ha-eat-narrow-to-shell-prompt-dwim))
:config
;; Red:
(set-face-attribute 'eat-term-color-1 nil :foreground "#b78077")
(set-face-attribute 'eat-term-color-9 nil :foreground "#d45d4c")
;; Green:
(set-face-attribute 'eat-term-color-2 nil :foreground "#879a39")
(set-face-attribute 'eat-term-color-10 nil :foreground "#66800b")
;; Yellow:
(set-face-attribute 'eat-term-color-2 nil :foreground "#d0a215")
(set-face-attribute 'eat-term-color-10 nil :foreground "#ad8301")
;; Blue
(set-face-attribute 'eat-term-color-2 nil :foreground "#4385be")
(set-face-attribute 'eat-term-color-10 nil :foreground "#205ea6")
;; Magenta:
(set-face-attribute 'eat-term-color-2 nil :foreground "#ce5d97")
(set-face-attribute 'eat-term-color-10 nil :foreground "#a02f6f")
;; Cyan
(set-face-attribute 'eat-term-color-2 nil :foreground "#3aa99f")
(set-face-attribute 'eat-term-color-10 nil :foreground "#24837b")
(defun ha-eat-narrow-to-shell-prompt-dwim ()
(interactive)
(if (buffer-narrowed-p) (widen) (eat-narrow-to-shell-prompt)))
@ -233,6 +214,8 @@ What about Evil mode?
TODO: Like =eshell=, the Bash in an EAT terminal has a command =_eat_msg= that takes a handler, and a /message/. Then set up an alist of =eat-message-handler-alist= to decide what to do with it.
TODO: Need to /subtlize/ the =eat-term-color-bright-green= and other settings as it is way too garish.
Make sure you add the following for Bash:
#+BEGIN_SRC bash :tangle no

View file

@ -438,20 +438,6 @@ Let’s make a /theme/:
`(term-color-bright-yellow ((t (:foreground ,yellow))))
`(term-color-bright-cyan ((t (:foreground ,slate))))
`(ansi-color-red ((t (:foreground ,red2-lt :background nil))))
`(ansi-color-green ((t (:foreground ,green-lt :background nil))))
`(ansi-color-blue ((t (:foreground ,blue-lt :background nil))))
`(ansi-color-magenta ((t (:foreground ,purple-lt :background nil))))
`(ansi-color-yellow ((t (:foreground ,yellow-lt :background nil))))
`(ansi-color-cyan ((t (:foreground ,slate :background nil))))
`(ansi-color-bright-red ((t (:foreground ,red2 :background nil))))
`(ansi-color-bright-green ((t (:foreground ,green :background nil))))
`(ansi-color-bright-blue ((t (:foreground ,blue :background nil))))
`(ansi-color-bright-magenta ((t (:foreground ,purple :background nil))))
`(ansi-color-bright-yellow ((t (:foreground ,yellow :background nil))))
`(ansi-color-bright-cyan ((t (:foreground ,slate :background nil))))
`(ansi-color-bright-black ((t (:foreground ,gray-50 :background nil))))
`(sh-heredoc ((t (:foreground ,almond))))
`(sh-quoted-exec ((t (:foreground ,orange2-lt))))

View file

@ -2,7 +2,7 @@
#+author: Howard X. Abrams
#+date: 2025-11-24
#+filetags: emacs hamacs
#+lastmod: [2026-10-09 Fri]
#+lastmod: [2026-09-11 Fri]
A literate programming file for configuring Hammerspoon.
@ -76,7 +76,7 @@ To create specific key bindings for starting applications, I can:
end)
hs.hotkey.bind({"alt", "ctrl", "shift"}, "F", function()
hs.application.launchOrFocus("Vivaldi")
hs.application.launchOrFocus("Firefox")
end)
hs.hotkey.bind({"alt", "ctrl", "shift"}, "C", function()

View file

@ -115,8 +115,6 @@ cat > "$HAMACS_DEST/init.el" <<EOF
(add-to-list 'package-archives
'("elpa-dev" . "https://elpa.gnu.org/devel/"))
(setq package-enable-at-startup nil)
;; Configure straight https://github.com/raxod502/straight.el#getting-started
(defvar bootstrap-version)

View file

@ -5,4 +5,3 @@
#+END_SRC
`yas-selected-text`
#+BEGIN_SRC `(ha-org-block-language-and)`

View file

@ -8,6 +8,9 @@
* Work Issues
$0
* Onboarding Work
See [[file:Onboarding-Work.org][Onboard-Work]] for all details.
* Distractions and Support
Anything that doesn't fit the above goes here.

View file

@ -224,12 +224,6 @@ Using the =colorize= plugin (see [[Plugins][plugins section below]]), we customi
export ZSH_COLORIZE_STYLE="coffee"
#+END_SRC
While we are at it, let’s make it easier to read the =ls= output:
#+BEGIN_SRC zsh
export LS_COLORS="rs=0:di=01;34:ln=01;36:mh=00:pi=33:so=01;35:do=01;35:bd=33;01:cd=33;01:or=31;01:mi=00:su=37:sg=30:ca=00:tw=30:ow=34:st=37:ex=01;32:*.7z=01;31:*.ace=01;31:*.alz=01;31:*.apk=01;31:*.arc=01;31:*.arj=01;31:*.bz=01;31:*.bz2=01;31:*.cab=01;31:*.cpio=01;31:*.crate=01;31:*.deb=01;31:*.drpm=01;31:*.dwm=01;31:*.dz=01;31:*.ear=01;31:*.egg=01;31:*.esd=01;31:*.gz=01;31:*.jar=01;31:*.lha=01;31:*.lrz=01;31:*.lz=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.lzo=01;31:*.pyz=01;31:*.rar=01;31:*.rpm=01;31:*.rz=01;31:*.sar=01;31:*.swm=01;31:*.t7z=01;31:*.tar=01;31:*.taz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tgz=01;31:*.tlz=01;31:*.txz=01;31:*.tz=01;31:*.tzo=01;31:*.tzst=01;31:*.udeb=01;31:*.war=01;31:*.whl=01;31:*.wim=01;31:*.xz=01;31:*.z=01;31:*.zip=01;31:*.zoo=01;31:*.zst=01;31:*.avif=01;35:*.jpg=01;35:*.jpeg=01;35:*.jxl=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:*~=00;90:*#=00;90:*.bak=00;90:*.crdownload=00;90:*.dpkg-dist=00;90:*.dpkg-new=00;90:*.dpkg-old=00;90:*.dpkg-tmp=00;90:*.old=00;90:*.orig=00;90:*.part=00;90:*.rej=00;90:*.rpmnew=00;90:*.rpmorig=00;90:*.rpmsave=00;90:*.swp=00;90:*.tmp=00;90:*.ucf-dist=00;90:*.ucf-new=00;90:*.ucf-old=00;90:"
#+END_SRC
** Language Support
Anything special for particular languages.
@ -492,15 +486,8 @@ The =EDITOR= variable that some programs use to edit files from the command line
With these variables defined, we can create simple aliases:
#+BEGIN_SRC zsh
if [[ -n "$INSIDE_EMACS" ]]
then
# If we are already in Emacs, no need to stall the terminal:
e() { emacsclient --eval "(find-file-other-window \"$1\")" }
te() { emacsclient --eval "(find-file \"$1\")" }
else
alias e="$EDITOR"
alias te="$EDITOR"
fi
alias ee="emacsclient --create-frame"
alias eee="emacsclient --create-frame --no-wait"
#+END_SRC
@ -509,7 +496,7 @@ With these variables defined, we can create simple aliases:
To work with [[https://github.com/akermu/emacs-libvterm][VTerm in Emacs]], we need to create this function:
#+BEGIN_SRC zsh :tangle no
#+BEGIN_SRC zsh
vterm_printf() {
if [ -n "$TMUX" ] \
&& { [ "${TERM%%-*}" = "tmux" ] \
@ -528,7 +515,7 @@ To work with [[https://github.com/akermu/emacs-libvterm][VTerm in Emacs]], we ne
This allows us to execute Emacs commands:
#+BEGIN_SRC zsh :tangle no
#+BEGIN_SRC zsh
vterm_cmd() {
local vterm_elisp
vterm_elisp=""
@ -542,7 +529,7 @@ This allows us to execute Emacs commands:
For instance:
#+BEGIN_SRC zsh :tangle no
#+BEGIN_SRC zsh
if [[ "$INSIDE_EMACS" = 'vterm' ]]
then
alias clear='vterm_printf "51;Evterm-clear-scrollback";tput clear'
@ -553,14 +540,6 @@ For instance:
fi
#+END_SRC
** Eat a Terminal
To work with [[:ha-remoting.org::*Eat][Eat]], we need to load up its integration library:
#+BEGIN_SRC zsh :tangle no
[ -n "$EAT_SHELL_INTEGRATION_DIR" ] && source "$EAT_SHELL_INTEGRATION_DIR/zsh"
#+END_SRC
The problem with the Eat integration is it prepends a =0= that doesn’t seem to signify anything useful.
* Aliases
Assuming we’ve installed [[https://github.com/lsd-rs/lsd][lsd]], let’s make an alias for it: