Current section
Files
Jump to
Current section
Files
docs/filtering.md
# Filter captured values
Obtain one [snapshot](observations.md), then select its observed panes:
```elixir
alias LibTmux.{Selection, Snapshot}
editors =
snapshot
|> Snapshot.panes()
|> Selection.where(active: true, current_command: [in: ["nvim", "vim"]])
Enum.map(editors, & &1.id)
```
Selections retain their immutable graph and order. Enumerable delegates to
the materialized list, including suspension and early halt. `size/1` uses
the cached count; ordinary `Enum.member?/2` compares elements. Use
`Selection.member_id?/2` for native ID membership. Enumeration performs no I/O.
`Selection.filter/2` accepts only unary functions and uses Enum truthiness.
Predicate exceptions propagate. `where/2` accepts validated data: keywords
are shorthand for maps, with duplicate keys rejected at every nesting level.
Both validate before scanning, including when no items remain.
`one/2` returns `{:ok, item}` or a structured `:no_match` / `:multiple_matches`
error. `one_or_nil/2` permits zero matches. Their bang variants raise the
same error; both stop at the second match. `exists?/2` stops at its first
match. `count/2` counts matching items; `size/1` returns the cached total.
## Predicate grammar
A bare scalar means equality. Explicit `%{equals: value}` is equivalent.
The [generated schema](schema.md) lists each field's type and operators.
Numbers compare numerically, strings compare case-sensitively without
normalization, and nullable numeric ordering against known nil is false.
`not` negates equality; `not_in` negates membership, including known nil.
Portable regex is not supported. Native predicates may use `Regex` directly.
Fields in one object conjoin. Boolean `and` and `or` accept lists of
criteria; `not` accepts one criteria object. Empty `and` is true and empty
`or` is false. Normalization never combines separate relation quantifiers:
```elixir
Selection.where(Snapshot.sessions(snapshot), %{
panes: %{some: %{active: true, current_command: "nvim"}}
})
```
That predicate requires one pane to satisfy both conditions. Two separate
`some` clauses can match different panes. `every` and `none` are true for
a known-empty relation; `some` is false. `count` counts that relation's
identities: physical windows/panes deduplicate, window links retain memberships.
To-one `is: criteria` is false for known absence and `is_not` negates it.
`is: nil` means absent; `is_not: nil` means present. Session `active_window`
is derived from a complete link domain and loaded active flags. Zero active
links means known absence; multiple active links raise `:ambiguous_relation`.
An unresolved active target remains unloaded. Coverage checks run before
evaluation, including fields behind a Boolean branch that cannot match.
## External filters
`Filter.new/3` returns a validated portable value, and `new!/3` raises its
structured error. Applying that value retains its constructor validation;
explicit new limits validate the normalized tree without generating extra
criteria objects. Prepared predicates may contain
sets and closures; portable filters contain data only.
`Filter.from_json/3` uses built-in JSON and rejects duplicate keys before
map conversion, trailing data and unknown names. `from_wire/3` accepts an
already decoded map; that map cannot reveal discarded duplicate keys.
Neither decoder creates atoms from external keys. Encode through
`Filter.to_wire/1`, then `JSON.encode!/1`.
```json
{"version":1,"entity":"pane","where":{"active":true,"currentCommand":{"in":["nvim","vim"]}}}
```
Default ceilings are 65,536 bytes, depth 16, 1024 value nodes, 256 array
elements and 8192 bytes per string. Wire depth starts at root zero and
counts every member/element; the ceiling is inclusive. Positive integer
options `max_bytes`, `max_depth`, `max_nodes`, `max_list` and
`max_string_bytes` can narrow or widen the constructor budget. JSON object
members have a fixed ceiling of 256. Native input depth counts criteria
objects and also bounds the normalized tree. A normalized conjunction does
not add relation/Boolean nesting; disjunctions, negations and relation
children do. Wire budgets additionally cover the full versioned envelope.
Errors carry the affected path, including Boolean and membership indexes;
early parser-limit errors can identify the root before a path is available.
Selections and filters operate on captured values. Server query planning
and pushdown remain under implementation.