diff options
| author | user <user@clank> | 2026-08-11 22:39:21 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-08-11 22:39:21 +0200 |
| commit | 42430f313cede1fe48fdf5e84eefd1f619264996 (patch) | |
| tree | 9063742587c419e2045f1fad6db62adc5d9587b6 | |
| parent | sl0p: bring zj-pane-finder into the repo (diff) | |
| download | sl0ppij-42430f313cede1fe48fdf5e84eefd1f619264996.tar.gz sl0ppij-42430f313cede1fe48fdf5e84eefd1f619264996.tar.xz sl0ppij-42430f313cede1fe48fdf5e84eefd1f619264996.zip | |
sl0p(pane-finder): take the whole viewport on small terminals
The finder always opened as a centred float with a frame. That costs its
margins (16% of columns, 28% of rows), a border, and on this fork the pane gap
as well -- on an 80x24 terminal leaving about 63x14 of the 80x24 available.
Rows are the scarce resource in a list, so most of the results were going to
decoration.
Below 100x30 it now takes the whole viewport and asks to be borderless, which
also drops the gap since this fork skips gap/padding for frameless panes. Above
that the centred float is kept, because it reads better when the space is
there.
The viewport is only knowable from TabInfo, so this re-evaluates on TabUpdate,
which is also how a terminal resize reaches a plugin -- switching modes live in
both directions. Re-applied only when the decision flips, so it does not fight
someone moving or resizing the pane by hand.
| -rw-r--r-- | sl0p/zj-pane-finder/README.md | 15 | ||||
| -rw-r--r-- | sl0p/zj-pane-finder/src/main.rs | 74 |
2 files changed, 80 insertions, 9 deletions
diff --git a/sl0p/zj-pane-finder/README.md b/sl0p/zj-pane-finder/README.md index ea198b15..501428d7 100644 --- a/sl0p/zj-pane-finder/README.md +++ b/sl0p/zj-pane-finder/README.md @@ -21,6 +21,21 @@ a non-root member has its `[profile]` ignored, and `opt-level = "z"` + `lto` + 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 diff --git a/sl0p/zj-pane-finder/src/main.rs b/sl0p/zj-pane-finder/src/main.rs index 78eb8114..807a2356 100644 --- a/sl0p/zj-pane-finder/src/main.rs +++ b/sl0p/zj-pane-finder/src/main.rs @@ -110,6 +110,9 @@ struct State { /// cwd per terminal pane id, fetched once per pane and kept fresh via CwdChanged cwds: HashMap<u32, String>, home: Option<String>, + /// whether we last sized ourselves compact; only re-applied when it flips, + /// so we do not fight the user moving or resizing us + applied_compact: Option<bool>, /// viewport lines per pane id, used to search pane CONTENTS. Only populated /// while a search is active: pulling every pane's contents is far too much /// work to do while someone is merely browsing the list. @@ -128,6 +131,15 @@ struct BodyHit { /// minimum total width before we bother splitting off a preview column const MIN_COLS_FOR_PREVIEW: usize = 58; +/// Below either of these we take the whole viewport and drop our frame. +/// +/// A centred float looks better, but it costs its margins (16% of the columns, +/// 28% of the rows) plus a border, and on this fork also the pane gap -- which +/// on an 80x24 terminal leaves about 63x14 to work with instead of 80x24. Rows +/// are the scarce resource in a list, so that is most of the results gone to +/// decoration. +const COMPACT_BELOW_COLS: usize = 100; +const COMPACT_BELOW_ROWS: usize = 30; const PREVIEW_REFRESH_SECS: f64 = 1.0; /// shown in the pane frame instead of the plugin's wasm URL const PANE_TITLE: &str = "pane finder"; @@ -184,6 +196,9 @@ impl ZellijPlugin for State { }, Event::TabUpdate(tabs) => { self.tabs = tabs; + // the viewport is only known from here, so this is also where a + // terminal resize reaches us + self.apply_self_geometry(); self.recompute(); true }, @@ -634,20 +649,61 @@ impl State { /// is the plugin's wasm URL and the default floating geometry is too narrow to /// fit the list plus a preview column. Both need ChangeApplicationState, so /// this runs once permissions are granted rather than at load time. - fn configure_self(&self) { + fn configure_self(&mut self) { let Some(plugin_id) = self.own_plugin_id else { return; }; rename_plugin_pane(plugin_id, PANE_TITLE); - if let Some(coords) = FloatingPaneCoordinates::new( - Some("8%".to_owned()), - Some("12%".to_owned()), - Some("84%".to_owned()), - Some("72%".to_owned()), - None, - None, - ) { + self.apply_self_geometry(); + } + + /// Usable size of the tab we are floating over. + fn viewport(&self) -> Option<(usize, usize)> { + let tab = self.tabs.iter().find(|tab| tab.active)?; + Some((tab.viewport_columns, tab.viewport_rows)) + } + + /// Size ourselves to the terminal: a centred float when there is room to + /// spare, the whole viewport with no frame when there is not. + /// + /// Re-applied only when the decision actually flips, so resizing the + /// terminal adapts but moving or resizing this pane by hand is left alone. + fn apply_self_geometry(&mut self) { + let Some(plugin_id) = self.own_plugin_id else { + return; + }; + let Some((cols, rows)) = self.viewport() else { + return; + }; + let compact = cols < COMPACT_BELOW_COLS || rows < COMPACT_BELOW_ROWS; + if self.applied_compact == Some(compact) { + return; + } + let coords = if compact { + // borderless as well: a frame around something covering the whole + // viewport is pure overhead, and this fork drops the pane gap for + // frameless panes too + FloatingPaneCoordinates::new( + Some("0".to_owned()), + Some("0".to_owned()), + Some("100%".to_owned()), + Some("100%".to_owned()), + None, + Some(true), + ) + } else { + FloatingPaneCoordinates::new( + Some("8%".to_owned()), + Some("12%".to_owned()), + Some("84%".to_owned()), + Some("72%".to_owned()), + None, + Some(false), + ) + }; + if let Some(coords) = coords { change_floating_panes_coordinates(vec![(PaneId::Plugin(plugin_id), coords)]); + self.applied_compact = Some(compact); } } |
