speclj.line-filter
*chosen-characteristics*
dynamic
*chosen-descriptions*
dynamic
active?
(active?)
True once *chosen-characteristics* has been bound (even to an empty set).
Callers bind this explicitly when `*line-targets*` is non-empty.
filtered-file?
(filtered-file? component)
True when this component's :file is named by some entry in *line-targets*.
Untargeted files run through normal focus/tag logic; only files with an
active line-target get narrowed.
pass-line-filter?
(pass-line-filter? component)
Only call this for components in `filtered-file?` files; untargeted files
should be gated by the normal focus/tag logic instead. Characteristics
pass iff they're in *chosen-characteristics*; Descriptions pass iff they
sit on the ancestor chain of a chosen characteristic.
resolve-targets
(resolve-targets descriptions line-targets)
Walks the description tree once and resolves each [user-path line-num]
target into a set of chosen Characteristic instances plus a list of
unmatched target strings (targets whose file isn't loaded).
Returns {:chosen #{characteristics...} :unmatched ["path:line" ...]}split-line-spec
(split-line-spec s)
Splits "path:line" → [path line-int]. Returns [s nil] when s has no
numeric :N suffix. Preserves Windows drive letters like "C:\\foo.clj"
by requiring the matched path to be longer than one char and to not end
with a colon (which would mean a bare drive letter or "foo::N").
with-chosen
(with-chosen descriptions body-fn)
If `*line-targets*` is non-empty, resolves them against `descriptions`,
records any unmatched targets into `*run-unmatched*` (when bound), and
invokes body-fn with `*chosen-characteristics*` and
`*chosen-descriptions*` bound. Otherwise just invokes body-fn.