Add search and filter to the guest table
/ opens a filter box under the guest table, and the table filters as you type. Terms are separated by spaces, all must match, and case is ignored: - a plain term matches part of the name, the VMID or a tag - is:running and is:stopped match the status - type:lxc/ct and type:vm/qemu match the guest type Enter keeps the filter and goes back to the table. Escape clears it, from the box or from the table. The frame shows "· filter: <text> · N of M". Actions only ever see the visible rows, and the filter survives reloads and context switches. Review fixes: - Typing "[/b]" or "[/]" crashed the app, because the filter text went into the border subtitle, which Textual parses as markup. The subtitle is now plain text, so "[red]" is also shown literally. - Escape on the table now clears a filter that was applied with Enter. - guest_matches tolerates a None status or type. Read-only live check on mainframe: "debian" gives 104, "type:vm" gives 108, "community-script is:running" gives 14 of 19, and "is:stopped" gives 0 of 19. Closes #16 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit was merged in pull request #29.
This commit is contained in:
1 parent
ff6345c80f
commit
d97ad22c78
4 files changed
+481
-7
No files matched your search
@@ -629,3 +629,31 @@ CLI facts (read-only probes):
|
||||
is dropped after a switch) and is cleared when a switch starts. Failures leave the
|
||||
count unknown (nothing shown), no error notify on mount.
|
||||
- Main footer shows `U Updates`.
|
||||
|
||||
---
|
||||
|
||||
# Search and filter in the guest table (issue #16)
|
||||
|
||||
## Decision
|
||||
|
||||
- `/` on the main screen shows `Input#filter` (hidden until then) below the guest table
|
||||
and focuses it. The table filters as you type.
|
||||
- Filter text = space-separated terms, all must match (AND), case-insensitive:
|
||||
- a plain term matches a substring of the name, the VMID or one of the tags
|
||||
(`tags` from `get guests`, `;`-separated);
|
||||
- `is:running` / `is:stopped` match the status;
|
||||
- `type:lxc` / `type:ct` and `type:vm` / `type:qemu` match the guest type.
|
||||
- Enter in the filter keeps the filter and moves focus to the table. Escape in the
|
||||
filter clears it, hides the input and moves focus to the table.
|
||||
- The frame's bottom border gets "· filter: <text> · N of M" while a filter is active,
|
||||
after the context name and before the backup/package counts.
|
||||
- Actions (s/S/x/r/t/Enter) act on the selected *visible* row only; the table only ever
|
||||
contains the matching guests. A reload (g, after actions, context switch) keeps the
|
||||
filter applied. A context switch keeps the filter text.
|
||||
- Placeholder of the input shows the syntax: `name, vmid, tag · is:running · type:lxc`.
|
||||
- No match: empty table, and the frame says "0 of M"; action keys do nothing.
|
||||
|
||||
### Code
|
||||
|
||||
- Pure function `guest_matches(guest: dict, query: str) -> bool` in `app.py` (or
|
||||
`cli.py`-free module-level helper) so it can be tested without the UI.
|
||||
Reference in new issue
Block a user