#+TITLE: check-parens
#+FILETAGS: :tool:lisp:org:

Standalone parentheseis checker for Lisp source blocks in Org files.

Scans all ~#+begin_src lisp … #+end_src~ blocks in an Org file, uses
SBCL's reader to validate each block. 100% accurate — no false positives
from string literals or character literals (e.g. ~#\)~).

== Limitations

Each ~#+begin_src lisp~ block is checked independently. Some literate
files intentionally split a single form (e.g. a ~defpackage~ with many
symbols) across multiple blocks with prose between them. In such cases
no individual block is self-contained and check-parens will report
false positives.

To verify these files, tangle and compile the resulting .lisp instead:
  check-tangle <file.org>

== Usage

#+begin_src shell
  check-parens <file.org> [<file.org> ...]
  check-parens -v <file.org>
#+end_src

Exit 0 if all blocks are balanced and terminated, 1 otherwise.

== Output

  ~file.org: OK~ — all blocks balanced
  ~file.org: Block at line 27: +2 (missing 2 closes) — near …~
  ~file.org: Block at line 103: unterminated — no matching #+end_src~

The ~-v~ flag prints the full block content for each issue.

== Integration

Pre-commit hook:

#+begin_src shell
  cat > .git/hooks/pre-commit <<'HOOK'
  #!/bin/sh
  for f in $(git diff --cached --name-only --diff-filter=ACM | grep '\.org$'); do
    projects/check-parens/check-parens "$f" || exit 1
  done
  HOOK
  chmod +x .git/hooks/pre-commit
#+end_src

== Dependencies

Python 3 + SBCL (for the reader-based validation).
SBCL must be at `/usr/bin/sbcl` (the default path).
