switch project fix
This commit is contained in:
207
AGENTS.md
Normal file
207
AGENTS.md
Normal file
@@ -0,0 +1,207 @@
|
||||
# AGENTS.md — org-roam-project
|
||||
|
||||
Guidance for AI coding agents working in this repository.
|
||||
|
||||
## Project overview
|
||||
|
||||
`org-roam-project` is an Emacs Lisp package that extends
|
||||
[org-roam](https://www.orgroam.com/) with per-project databases using
|
||||
Emacs' built-in `project.el`. Each project gets its own isolated notes
|
||||
directory and SQLite database. The global zettelkasten is never touched.
|
||||
|
||||
**Language:** Emacs Lisp
|
||||
**Dependencies:** Emacs >= 28.1, org-roam >= 2.2.0
|
||||
**License:** GPL-3.0-or-later
|
||||
|
||||
### Repository layout
|
||||
|
||||
```
|
||||
org-roam-project.el Main package source (~355 lines)
|
||||
org-roam-project-test.el ERT test suite (~430 lines)
|
||||
Makefile Build and test runner
|
||||
flake.nix / shell.nix Nix dev environment
|
||||
```
|
||||
|
||||
## Build commands
|
||||
|
||||
```sh
|
||||
make all # Byte-compile + run tests
|
||||
make compile # Byte-compile org-roam-project.el
|
||||
make test # Run the full ERT test suite in batch mode
|
||||
make clean # Remove .elc files
|
||||
```
|
||||
|
||||
### Running a single test
|
||||
|
||||
```sh
|
||||
emacs --batch \
|
||||
-l ert \
|
||||
-l org-roam \
|
||||
--eval "(add-to-list 'load-path \".\")" \
|
||||
-l org-roam-project \
|
||||
-l org-roam-project-test \
|
||||
--eval "(ert-run-tests-batch-and-exit '\"orp-test-NAME\")"
|
||||
```
|
||||
|
||||
Replace `orp-test-NAME` with the test name (e.g. `orp-test-default-notes-subdir`).
|
||||
The string is an ERT selector regexp matching test names.
|
||||
|
||||
### Dev environment
|
||||
|
||||
The project uses Nix flakes. Run `nix develop` (or let `direnv` activate
|
||||
via `.envrc`) to get an Emacs with org-roam and all dev tools on `$PATH`.
|
||||
|
||||
## Code style guidelines
|
||||
|
||||
### Lexical binding
|
||||
|
||||
Every `.el` file MUST have `lexical-binding: t` in the first line:
|
||||
|
||||
```elisp
|
||||
;;; file.el --- Description -*- lexical-binding: t; -*-
|
||||
```
|
||||
|
||||
### File structure
|
||||
|
||||
Follow this order in every source file:
|
||||
|
||||
1. First line with description and `lexical-binding: t`
|
||||
2. Copyright / Author / Version / Package-Requires / Keywords / URL
|
||||
3. License boilerplate (GPL-3.0-or-later)
|
||||
4. `;;; Commentary:` section
|
||||
5. `;;; Code:` marker
|
||||
6. `(require ...)` forms
|
||||
7. `;;; Section` headers (three semicolons) grouping related code
|
||||
8. `(provide 'feature)` at the end
|
||||
9. `;;; file.el ends here` footer
|
||||
|
||||
### Namespace prefix
|
||||
|
||||
All symbols use the `org-roam-project` prefix:
|
||||
|
||||
- **Public:** `org-roam-project-<name>` (single dash)
|
||||
- **Private:** `org-roam-project--<name>` (double dash)
|
||||
- **Test public:** `orp-test-<name>`
|
||||
- **Test private:** `orp-test--<name>`
|
||||
|
||||
Never introduce unprefixed top-level symbols.
|
||||
|
||||
### Requires / imports
|
||||
|
||||
- Place all `(require ...)` forms at the top of `;;; Code:`.
|
||||
- Only hard runtime dependencies. No `eval-when-compile` unless truly
|
||||
needed for macros.
|
||||
- **Do not use `cl-lib` in production code.** Use only built-in Emacs
|
||||
Lisp primitives (`let`, `let*`, `when`, `unless`, `cond`, `cons`,
|
||||
`car`, `cdr`, `alist-get`, `dolist`, etc.). `cl-lib` is acceptable
|
||||
in the test file only.
|
||||
|
||||
### Formatting
|
||||
|
||||
- **Line length:** ~80 columns. String literals may slightly exceed this.
|
||||
- **Indentation:** Standard Emacs Lisp indentation (2-space aligned
|
||||
`let` bindings, standard `defun`/`defmacro`/`cond` indentation).
|
||||
- **Parentheses:** Closing parens always on the same line as the last
|
||||
form — never on their own line.
|
||||
- **Blank lines:** One blank line between top-level forms. Section
|
||||
headers (`;;;`) get blank lines before and after.
|
||||
- **Function references:** Always use sharp-quote: `#'function-name`.
|
||||
- **`let` vs `let*`:** Use `let*` only when bindings depend on earlier
|
||||
bindings in the same form. Use plain `let` otherwise.
|
||||
|
||||
### Docstrings
|
||||
|
||||
Every public and private function, macro, and variable must have a
|
||||
docstring.
|
||||
|
||||
- First line: complete imperative sentence ("Return the context…").
|
||||
- Arguments referenced in UPPER CASE: `"DIR defaults to…"`.
|
||||
- Cross-reference other symbols with backtick-quote: `` `org-roam-project-init' ``.
|
||||
- Document return values and nil-return conditions explicitly.
|
||||
|
||||
### Inline comments
|
||||
|
||||
- Use `;;` (two semicolons) on a line by itself above the code.
|
||||
- Section headers use `;;;` (three semicolons).
|
||||
- Avoid end-of-line comments in production code (acceptable in tests
|
||||
for brief annotations).
|
||||
|
||||
### Defcustom conventions
|
||||
|
||||
```elisp
|
||||
(defcustom org-roam-project-XXXX default-value
|
||||
"Docstring."
|
||||
:type 'TYPE
|
||||
:group 'org-roam-project)
|
||||
```
|
||||
|
||||
- Always specify `:type` and `:group`.
|
||||
- If the variable is usable in `.dir-locals.el`, add a
|
||||
`safe-local-variable` declaration with an `;;;###autoload` cookie:
|
||||
|
||||
```elisp
|
||||
;;;###autoload
|
||||
(put 'org-roam-project-XXXX 'safe-local-variable #'stringp)
|
||||
```
|
||||
|
||||
### Autoloads
|
||||
|
||||
Place `;;;###autoload` on:
|
||||
- All interactive commands
|
||||
- The minor mode definition (`define-minor-mode`)
|
||||
- `safe-local-variable` `put` forms
|
||||
|
||||
Never autoload internal (`--`) functions.
|
||||
|
||||
### Error handling
|
||||
|
||||
Two-tier pattern:
|
||||
|
||||
1. **Internal functions** return `nil` on failure — never signal errors.
|
||||
Let callers decide behavior.
|
||||
2. **Interactive commands** call `org-roam-project--require-context`
|
||||
which signals `user-error` (not `error`) with actionable messages.
|
||||
|
||||
Always use `user-error` for user-facing errors, never bare `error`.
|
||||
|
||||
### Macros
|
||||
|
||||
- Always declare `(declare (indent 0) (debug t))` as the first form.
|
||||
- Accept `&rest body`, splice with `,@body`.
|
||||
- Use `unwind-protect` for cleanup in test macros.
|
||||
|
||||
### Dynamic scoping pattern
|
||||
|
||||
The core architectural pattern: temporarily rebind `org-roam-directory`
|
||||
and `org-roam-db-location` via `let` — never mutate them with `setq`.
|
||||
|
||||
```elisp
|
||||
(let ((org-roam-directory (car ctx))
|
||||
(org-roam-db-location (cdr ctx)))
|
||||
(org-roam-node-find))
|
||||
```
|
||||
|
||||
## Testing conventions
|
||||
|
||||
- **Framework:** ERT (Emacs Regression Testing), built-in.
|
||||
- **Test file:** `org-roam-project-test.el`
|
||||
- **Test names:** `orp-test-<descriptive-name>` (no double dash).
|
||||
- **Helpers/macros:** `orp-test--<name>` (double dash).
|
||||
- Tests create real temporary Git repos via `git init` so `project.el`
|
||||
recognizes them. Always clean up with `orp-test--cleanup`.
|
||||
- Use `orp-test--with-project` or `orp-test--with-initialized-project`
|
||||
macros to set up and tear down test fixtures.
|
||||
- Test `user-error` conditions with `(should-error ... :type 'user-error)`.
|
||||
- Tests use real org-roam (not mocked) to catch compatibility issues.
|
||||
- `cl-lib` functions (`cl-remove-if`, `cl-find`, `cl-count`, etc.) are
|
||||
allowed in tests.
|
||||
|
||||
## Section headers in test file
|
||||
|
||||
Tests are numbered in groups with decorative Unicode headers:
|
||||
|
||||
```elisp
|
||||
;;; ─── 1. Customisation defaults ───────────────
|
||||
```
|
||||
|
||||
Maintain this grouping style when adding new test sections.
|
||||
Reference in New Issue
Block a user