aboutsummaryrefslogtreecommitdiffstats
path: root/sl0p/zj-pane-finder/README.md
blob: da7ebf3f31b967e4547947b2ba9f8bc37d93eae6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# zj-pane-finder

A floating fuzzy finder for every pane in the session. Lists panes across all
tabs, filters as you type, previews the highlighted one, and jumps to it.

It lists every pane in the session, including ones you cannot see: members of a
stack hidden behind the visible one, and panes in other tabs. Selecting a hidden
stack member swaps it into view; selecting a pane in another tab switches to that
tab first. Both come free from the host's `FocusPaneWithId`, which resolves the
owning tab through suppressed panes and hands hidden stack members to the fork's
stack-list logic.

Suppressed **plugin** panes are the exception — `zellij:link` and friends are
deliberately invisible infrastructure, and focusing one shows an empty pane.

Filtering matches pane **metadata** (tab, title, command, cwd) and, failing
that, the **visible contents** of each pane — so you can find a pane by
something you can see in it rather than only by what it is called. Content
matches are marked `≡` in the list, and the preview scrolls to the matching
line with the matched characters highlighted.

## Why it lives here

It path-depends on this checkout's `zellij-tile`, so the plugin API and its
protobuf assets always match the binary built beside it. Keeping the two in one
repo means they cannot drift.

It is deliberately **its own workspace root** rather than a member of zellij's:
a non-root member has its `[profile]` ignored, and `opt-level = "z"` + `lto` +
`strip` are what keep the wasm small — which matters because the keybinding
loads it with `skip_plugin_cache`, recompiling on every launch. Staying
independent also means carrying this crate touches no upstream-tracked file.

## Sizing

On a roomy terminal it opens as a centred float with a frame. Below
`COMPACT_BELOW_COLS` x `COMPACT_BELOW_ROWS` (100x30) it takes the **whole
viewport and drops its frame** instead.

The float's margins cost 16% of the columns and 28% of the rows, plus a border,
plus this fork's pane gap — on an 80x24 terminal that leaves roughly 63x14 to
work with rather than 80x24. Rows are the scarce resource in a list, so most of
the results were going to decoration.

It re-evaluates on `TabUpdate`, so resizing the terminal switches modes live.
Only applied when the decision actually flips, so moving or resizing the pane by
hand is left alone.

## Build and install

```bash
./install.sh
```

Builds for `wasm32-wasip1`, copies to `~/.config/zellij/plugins/`, and
hot-reloads it in every running session — zellij caches a plugin's compiled
module in the server's memory for the life of the session, so overwriting the
`.wasm` alone is not enough.

Note it does **not** build into `./target`: this checkout's `.cargo/config.toml`
sets a shared `build.target-dir`, so `install.sh` asks `cargo metadata` where
the artifact actually landed.

## Binding it

Something used this often wants a single chord rather than a mode dance. In a
config with `default_mode "locked"`, put it in a block shared by the modes you
actually sit in:

```kdl
shared_among "normal" "locked" {
    bind "Ctrl ;" {
        LaunchOrFocusPlugin "file:~/.config/zellij/plugins/pane-finder.wasm" {
            floating true
            move_to_focused_tab true
            skip_plugin_cache true
        };
        SwitchToMode "Locked"
    }
}
```

`Ctrl ;` is deliberately obscure: `;` has no control-code meaning, readline does
not bind it, and vim binds only bare `;` (repeat `f`/`t`), never `Ctrl ;`. Plain
`;` keeps typing normally.

It does need the **kitty keyboard protocol** to be distinguishable from a plain
`;` — zellij enables it and kitty speaks it, but on a terminal without it the
binding simply never fires. `Ctrl \`, `Ctrl ]` and `Ctrl _` are real control
codes and work anywhere, but they collide with SIGQUIT, vim's tag jump and
readline's undo respectively.

## Keys

`type` filter · `Up`/`Down`, `Ctrl-p`/`Ctrl-n`, `Tab` move · `Enter` jump
`Ctrl-w` clear word · `Ctrl-u` clear · `Esc`/`Ctrl-c` close