aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoruser <user@clank>2026-08-12 13:36:50 +0200
committeruser <user@clank>2026-08-12 19:34:19 +0200
commit8dfaba95dc7963e48a111d95903fb027f9a98f69 (patch)
treee31cf4449e853a8442abf8471fa124cc424e21de
parentsl0p: add close_if_focused to LaunchOrFocusPlugin (diff)
downloadsl0ppi-8dfaba95dc7963e48a111d95903fb027f9a98f69.tar.gz
sl0ppi-8dfaba95dc7963e48a111d95903fb027f9a98f69.tar.xz
sl0ppi-8dfaba95dc7963e48a111d95903fb027f9a98f69.zip
sl0p(pane-finder): find panes hidden in a stack, not just the visible one
In a collapsed (mobile) layout every stack member except the visible one is suppressed, and the finder skipped suppressed panes outright -- so it could only ever find the one pane already on screen, which defeats the point of having it there. Suppressed terminals are now listed and marked "(hidden)". Suppressed plugins still are not: zellij:link and friends are deliberately invisible infrastructure, and focusing one shows an empty pane. Unfiltering everything listed it, which is how that distinction surfaced. Needed no server work. Screen::focus_pane_with_id already locates the owning tab via has_pane_with_pid, which includes suppressed panes, and calls go_to_tab; and Tab::focus_pane_with_id tries focus_hidden_stack_list_member first. So selecting a hidden stack member swaps it into view and selecting a pane in another tab switches tab, both already handled by the host.
-rw-r--r--sl0ppij/sl0p/zj-pane-finder/README.md10
-rw-r--r--sl0ppij/sl0p/zj-pane-finder/src/main.rs20
2 files changed, 28 insertions, 2 deletions
diff --git a/sl0ppij/sl0p/zj-pane-finder/README.md b/sl0ppij/sl0p/zj-pane-finder/README.md
index 83ed136..da7ebf3 100644
--- a/sl0ppij/sl0p/zj-pane-finder/README.md
+++ b/sl0ppij/sl0p/zj-pane-finder/README.md
@@ -3,6 +3,16 @@
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
diff --git a/sl0ppij/sl0p/zj-pane-finder/src/main.rs b/sl0ppij/sl0p/zj-pane-finder/src/main.rs
index 807a235..5f33331 100644
--- a/sl0ppij/sl0p/zj-pane-finder/src/main.rs
+++ b/sl0ppij/sl0p/zj-pane-finder/src/main.rs
@@ -36,6 +36,7 @@ struct PaneEntry {
tab_name: String,
title: String,
is_floating: bool,
+ is_hidden: bool,
is_focused_in_tab: bool,
exited: bool,
command: Option<String>,
@@ -296,6 +297,10 @@ impl ZellijPlugin for State {
if entry.is_floating {
line.push_str(" (floating)");
}
+ if entry.is_hidden {
+ // stacked behind another pane, or otherwise not on screen
+ line.push_str(" (hidden)");
+ }
if entry.exited {
line.push_str(" (exited)");
}
@@ -362,12 +367,22 @@ impl State {
.map(|t| t.name.clone())
.unwrap_or_else(|| format!("tab {}", tab_position + 1));
for pane in panes {
- // never list ourselves, and skip suppressed (invisible) panes
+ // never list ourselves
if pane.is_plugin && Some(pane.id) == self.own_plugin_id {
continue;
}
// unselectable panes are UI furniture (status-bar, tab-bar, …)
- if pane.is_suppressed || !pane.is_selectable {
+ if !pane.is_selectable {
+ continue;
+ }
+ // A suppressed PLUGIN is infrastructure -- zellij:link and
+ // friends are deliberately invisible, and focusing one shows an
+ // empty pane. Suppressed terminals are the opposite: in a
+ // collapsed/stacked layout every stack member except the visible
+ // one is suppressed, so skipping those left the finder able to
+ // find only the pane already on screen. Focusing one swaps it
+ // into view, switching tab if needed, via the host.
+ if pane.is_suppressed && pane.is_plugin {
continue;
}
entries.push(PaneEntry {
@@ -377,6 +392,7 @@ impl State {
tab_name: tab_name.clone(),
title: pane.title.clone(),
is_floating: pane.is_floating,
+ is_hidden: pane.is_suppressed,
is_focused_in_tab: pane.is_focused,
exited: pane.exited,
command: pane.terminal_command.clone(),