diff options
| author | Craig Jennings <c@cjennings.net> | 2026-06-23 22:00:14 -0400 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-06-23 22:00:33 -0400 |
| commit | 1587c119ceeba4698974f402eda17482e68202e8 (patch) | |
| tree | 4d87b784de5c45a11b4d85fa9442f91b24dc062b /.claude/rules/elisp.md | |
| parent | b39633d9d482b6510e5626e0c5441ad211508a6e (diff) | |
| download | chime-1587c119ceeba4698974f402eda17482e68202e8.tar.gz chime-1587c119ceeba4698974f402eda17482e68202e8.zip | |
chore: stop tracking local dev tooling
Diffstat (limited to '.claude/rules/elisp.md')
| -rw-r--r-- | .claude/rules/elisp.md | 75 |
1 files changed, 0 insertions, 75 deletions
diff --git a/.claude/rules/elisp.md b/.claude/rules/elisp.md deleted file mode 100644 index ea9bdc2..0000000 --- a/.claude/rules/elisp.md +++ /dev/null @@ -1,75 +0,0 @@ -# Elisp / Emacs Rules - -Applies to: `**/*.el` - -## Style - -- 2-space indent, no tabs -- Hyphen-case for identifiers: `cj/do-thing`, not `cj/doThing` -- Naming prefixes: - - `cj/name` — user-facing functions and commands (bound to keys, called from init) - - `cj/--name` — private helpers (double-dash signals "internal") - - `<module>/name` — module-scoped where appropriate (e.g., `calendar-sync/parse-ics`) -- File header: `;;; foo-config.el --- brief description -*- lexical-binding: t -*-` -- `(provide 'foo-config)` at the bottom of every module -- `lexical-binding: t` is mandatory — no file without it - -## Function Design - -- Keep functions under 15 lines where possible -- One responsibility per function -- Extract helpers instead of nesting deeply — 5+ levels of nesting is a refactor signal -- Prefer named helpers over lambdas for anything nontrivial -- No premature abstraction — three similar lines beats a clever macro - -Small functions are the single strongest defense against paren errors. Deeply nested code is where AI and humans both fail. - -## Requires and Loading - -- Every `(require 'foo)` must correspond to a loadable file on the load-path -- Byte-compile warnings about free variables usually indicate a missing `require` or a typo in a symbol name — read them -- Use `use-package` for external (MELPA/ELPA) packages -- Use plain `(require 'foo-config)` for internal modules -- For optional features, `(when (require 'foo nil t) ...)` degrades gracefully if absent - -## Lexical-Binding Traps - -- `(boundp 'x)` where `x` is a lexical variable always returns nil. Bind with `defvar` at top level if you need `boundp` to work, or use the value directly. -- `setq` on an undeclared free variable is a warning — use `let` for locals or `defvar` for module-level state -- Closures capture by reference. Avoid capturing mutating loop variables in nested defuns. - -## Regex Gotchas - -- `\s` is NOT whitespace in Emacs regex. Use `[ \t]` or `\\s-` (syntax class). -- `^` in `string-match` matches after `\n` OR at position 0 — use `(= (match-beginning 0) start)` for positional checks when that matters. -- `replace-regexp-in-string` interprets backslashes in the replacement. Pass `t t` (FIXEDCASE LITERAL) when the replacement contains literal backslashes. - -## Keybindings - -- `keymap-global-set` for global; `keymap-set KEYMAP ...` for mode-local -- Group module-specific bindings inside the module's file -- Autoload cookies (`;;;###autoload`) don't activate through plain `(require ...)` — use the form directly, not an autoloaded wrapper - -## Module Template - -```elisp -;;; foo-config.el --- Foo feature configuration -*- lexical-binding: t -*- - -;;; Commentary: -;; One-line description. - -;;; Code: - -;; ... code ... - -(provide 'foo-config) -;;; foo-config.el ends here -``` - -Then `(require 'foo-config)` in `init.el` (or a config aggregator). - -## Editing Workflow - -- A PostToolUse hook runs `check-parens` and `byte-compile-file` on every `.el` save -- If it blocks, read the error — don't retry blindly -- Edit cohesively, then verify parens/byte-compile right away. For nontrivial Elisp, land a function as one complete, coherent change rather than dribbling it in over many tiny partial edits — incremental fragments accumulate subtle paren mismatches. Run the paren-balance and byte-compile checks immediately after editing, whatever editing mechanism the environment uses. |
