| Commit message (Collapse) | Author | Age |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Completes the two pieces deferred from the first workspace-hints pass.
`zellij run --purpose X` / `zellij action new-pane --purpose X` tag a pane at
spawn time, which is what an agent wants for panes it creates itself; the OSC
wrapper still works for programs that declare their own role. Not supported with
--in-place, which replaces another pane rather than being a pane of its own: clap
rejects the combination rather than accepting a flag that would do nothing.
`tab name="work" purpose="agent-work"` gives a whole tab a role, reported by
`list-tabs --json`. It rides the tab's ROOT layout node, reusing the pane field
because a tab's root is the tab container and never itself a pane -- asserted by a
test for the tightest case (a tab holding exactly one pane), since a leak there
would silently mislabel a pane.
The interesting part is why the flag first shipped broken. There are TWO protobuf
boundaries -- the plugin API and the client->server IPC contract -- and a CLI flag
must cross the second one. Defaulting the field in the conversion (what "no
protoc" usually forces) compiles cleanly and then silently drops the value in
transit, so --purpose parsed, printed a pane id, and did nothing. Fixed by adding
the field to both contracts by hand, in the .proto AND the committed generated
prost, kept in lockstep so a future regeneration reproduces it: protoc is only
needed to regenerate, not to build. Both boundaries now have a round-trip test,
and the IPC one was confirmed to fail when the wire read is removed.
Sanitising moved to Grid::set_authoritative_purpose, the single choke point every
out-of-band source passes through, after the CLI path was observed delivering
`bad purpose; rm -rf /` intact into list-panes --json.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Implements the zellij half of sl0p/workspace-hints-proposal.md: a pane can carry
an opaque agent-facing hint for what it is FOR, so a project can ship a layout
that an agent is able to navigate instead of guessing.
zellij never interprets a purpose. The consuming agent owns the entire vocabulary,
which is what keeps this to one string threaded along the existing status_bar path
rather than a policy engine, and lets the vocabulary change without a rebuild.
Two ways in, because declared panes and agent-created panes are different:
layout: pane name="server" purpose="dev-server"
in-band: printf '\033]5577;1;purpose;agent:build\033\\'
The second exists because tagging at spawn time would mean threading a field
through 28 SpawnTerminal call sites, and a new action variant is impossible while
protobuf enums cannot be regenerated. Wrapping the command costs one printf.
A declared purpose outranks an in-band one and cannot be overridden or cleared by
it. OSC arrives from whatever the pane happens to be showing, so otherwise a
`cat hostile.txt` in the human's editor pane could relabel it as the agent's
scratch pane and invite an agent to run commands where the human is working. A
layout is written by a human in a file they can read; in-band data only fills a
blank.
Exposed on PaneListEntry (`list-panes --json`) rather than PaneInfo, which crosses
the plugin protobuf API we cannot regenerate; resolved in the screen thread where
panes live rather than via route.rs's per-pane PTY round-trips. Values are
sanitised to a bounded [A-Za-z0-9_.:/-] token at both entry points, because a
purpose is never rendered -- it is matched against and pasted into consumers'
shell and JSON pipelines.
Verified end to end rather than by inspection: purposes from a layout appear in
list-panes --json against the right pane ids, an agent-spawned pane tags itself,
a declared purpose survives an in-band override attempt, all of it comes back
after kill + resurrect, an unknown pane property is still a parse error, and a
layout with no purpose leaves dump-layout unchanged.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
`status_bar_button_style "indexed"` renders `1:Approve 2:Reject` instead of
`[Approve] [Reject]`, so the bar doubles as a key legend for a harness that binds
alt+1..9 to the same actions.
A config option rather than a protocol field: whether the numbers mean anything
depends on what the USER has bound, not on what the program knows. It needs no
wire change and so no version bump, and the click report still carries the id --
never the index -- so a program is unaffected by which style is in force.
The style is threaded into layout_status_bar, the one function the renderer draws
from and the hit-test resolves against. That is what makes this safe: changing a
button's rendered width necessarily changes its clickable span too, verified by a
test asserting span width equals the drawn width and that every drawn column
resolves back, for both styles.
Also fixes the web client's Style construction to read the option from config
rather than defaulting it -- my first pass claimed that code had no pane_frames
config available, which was wrong; it uses it two lines further down.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Second slice of the status/action frame. A program declares buttons, and a click
is reported back to it:
printf '\033]5577;1;buttons;approve:Approve;reject:Reject\033\\'
-> click -> program's stdin receives OSC 5577 ; 1 ; click ; approve ST
The report is a FIXED format carrying only the id, never bytes the payload chose,
and ids are restricted to [A-Za-z0-9_-]. The sequence that creates a button is
in-band and untrusted -- `cat` of a hostile file emits it as readily as a
cooperating program -- so a click that could send arbitrary bytes would let
viewing a file inject into the stdin of whatever is running, a shell included.
Labels are '%'-escaped since the wire format is ';'-separated, and both the
button count and id length are capped because the list lives as long as the pane.
Positions come from one layout_status_bar function that the renderer draws from
and the hit-test resolves against. Computing that geometry twice is how the
stacked-pane picker once selected the wrong pane; a test asserts every drawn
column resolves back to the button drawn there, across 100 widths.
Two things the drive caught that unit tests could not:
- The first delivery path pushed onto grid.pending_messages_to_pty, which is
only drained when the PANE produces output -- so a click on an idle program sat
in the queue forever. The write now happens at the tab level, which owns the
senders.
- The hit-test derived the frame row from the pane's raw geometry, but this fork
draws the frame inset by gap_offset, so with `gap 1` every click missed by one
row. It now derives from the CONTENT rect, which is by definition the inside of
the drawn frame and therefore the same columns the renderer lays out.
Buttons serialise with the session like the status text, so a resurrected pane
comes back with its buttons intact.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The status bar survived detach/reattach (it lives on Grid) but not a
serialise/restore cycle, so a resurrected pane came back blank.
It now travels the whole per-pane serialisation pipeline, mirroring the fork's
existing default_fg/default_bg: pane -> PaneLayoutMetadata ->
PaneLayoutManifest -> TiledPaneLayout -> a status_bar property in the serialised
KDL, then back through the normal layout parser and applied by LayoutApplier
when the pane is recreated.
The sanitiser moved from grid.rs into zellij-utils so both entry points share
one definition. That matters: a layout file on disk is no more trustworthy than
the escape sequence that wrote it -- it may have been hand-edited, or copied from
somewhere else -- so restored text is stripped and length-capped on the way in
just like the OSC payload was.
Verified end to end rather than by unit test alone: set the bar, waited for a
serialisation pass, confirmed status_bar="..." in session-layout.kdl, killed the
session until list-sessions reported EXITED, then attached and watched it come
back from disk. The earlier attempt only proved detach/reattach because Quit had
left the session alive.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Upstream's action focuses an already-running plugin, so a chord bound to it can
only ever open one -- there is no way to dismiss with the same key.
This cannot be fixed in a plugin. Keybindings are resolved into actions in
route.rs before a key reaches a pane, so the launching chord never arrives at
the plugin. intercept_key_presses does not help either: the intercept lives in
screen.rs and only sees keys that already became Action::Write, i.e. keys
destined for a pane. Confirmed empirically -- an intercepting build received
Ctrl-u but never Ctrl-;.
Closes only when the plugin is the focused pane in the client's ACTIVE tab, so
the chord cannot close whatever pane the user happens to be on. A plugin that
exists but is hidden behind a floating-layer toggle, or is focused in a
different tab, is revealed or brought over as before.
Defaults to false, so every existing binding is unaffected. Config-only, with no
protobuf representation: defaulted at both boundaries and dropped when an action
crosses the plugin API, so no prost regeneration is needed.
The 24 snapshot lines are the new field appearing in serialised keybind dumps.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A `children` placeholder inserts every pane it receives as a flat sibling.
That single hardcoded policy is why a layout can only express "N equal
columns", "N equal rows" or "one stack" without hand-writing a variant per
pane count -- the max_panes=5 / max_panes=8 / max_panes=12 ladders in a swap
layout file exist purely to work around it.
`pane arrangement="grid" { children; }` builds a tree for N panes instead.
Two to start: grid (ceil(sqrt(n)) columns, rows filled left to right) and
master-stack (one 60%-wide master, the rest beside it).
Generates a TiledPaneLayout rather than geometry, so everything downstream
works unchanged: split_space, the minimum-size feasibility check,
LayoutApplier, swap-layout damage tracking, and the responsive collapse. It
composes with that last one for free -- a grid is simply infeasible on a
narrow terminal, so it is skipped and the collapse takes over.
The arrangement builds ONE self-contained subtree rather than splicing a
variable number of nodes in among the placeholder's siblings, so it stays well
defined next to the pre-existing "children node with sibling nodes" TODO
rather than leaning on it.
Like default_fg/default_bg, the field has no protobuf representation, so it is
defaulted at both plugin-API boundaries and does not survive a round trip.
This is why it is a field rather than a LayoutConstraint variant: a new enum
variant would have no representation when converting TO protobuf, and the
committed prost assets cannot be regenerated here (no protoc).
The 48 snapshot updates are the new field appearing in TiledPaneLayout debug
dumps (324 lines, all `children_arrangement: None`). No snapshot content was
removed. The `expression:` metadata churn in those files is pre-existing drift
that regeneration swept up: the stored snapshots recorded the expression
before normalize_layout_debug was introduced.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
`ui { pane_frames { hide_default_pane_names true } }`, default false.
A pane now shows no title at all until something actually names it: the user
renaming it (including by double-clicking the title row) or the running
program setting a title. Upstream always shows an auto-generated 'Pane #N'.
Implemented by tracking whether pane_title is still the constructor's
placeholder, NOT by matching the string: a program that legitimately titles
itself 'Pane #3' must not be mistaken for an unnamed pane. set_title clears
the flag, since something then chose that title.
current_title reads the option at render time rather than baking an empty
title in at construction, so it hot-reloads and turning the option back off
restores the placeholder on existing panes.
Display precedence is unchanged and now explicit in the code:
user-given name > title set by the running program > placeholder
render_terminal_title already fell back to an empty string rather than the
placeholder, so the terminal WINDOW title is unaffected.
Empty titles were already handled by the frame renderer
(render_title_left_side returns None for an empty title), including the
sl0p centred/right alignment path.
Baselines held: zellij-server 1436/30, zellij-utils 436/5.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
`ui { pane_frames { inactive_grayscale 0-100 } }`, default 0 (off).
Real colour transformation, not the SGR 'faint' attribute zellij already uses
for frames: faint is terminal-dependent, several terminals only apply it to
the 16 ANSI colours, and it does not remove colour. Each cell's colour is
resolved to RGB and blended toward its own Rec.709 luminance, so an unfocused
pane keeps its brightness but drains of colour.
Colour resolution covers the cases that actually occur: RgbCode directly,
ColorIndex via eightbit_to_rgb, and NamedColor by mapping to its 0-15 index.
Cells with NO explicit colour are deliberately left alone - they render in the
terminal default, which is already unsaturated, and rewriting them would mean
emitting an explicit colour for nearly every cell for no visible gain.
Two non-obvious pieces were needed to make it actually work:
- The output buffer only emits CHANGED cells, so an idle pane would keep its
old colours indefinitely after losing focus. Pane::refresh_for_focus_change
forces a full repaint, called from ActivePanes::insert (the single place
focus changes). It is a no-op when the feature is off, so it costs nothing
by default.
- Terminal panes render through the SHARED multi-client path. Focus is per
client, so once unfocused panes are desaturated two clients may need
different output for the same pane. Both tiled and floating panes now fall
back to per-client rendering when grayscale is enabled - the reason this is
opt-in.
Known limitation: sixel/kitty image chunks are not colour-transformed and stay
in colour.
Hot-reloads like the other sl0p options. Tests cover the transform: full
strength yields a true neutral grey, partial sits between original and grey,
indexed and named colours resolve rather than being skipped, luminance is
perceptual (green brighter than blue) not a flat average, already-grey is
unchanged, and non-colour codes are untouched.
Baselines held: zellij-server 1436/30, zellij-utils 436/5.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
`padding` now accepts:
padding 1 -> all four sides
padding 1 2 -> up/down = 1, left/right = 2
padding 1 2 3 4 -> up=1 down=2 left=3 right=4
NOTE the 4-value order is UP DOWN LEFT RIGHT as requested, deliberately NOT
CSS's clockwise top-right-bottom-left. Documented on PanePadding and at the
parser, since the similarity to CSS invites the wrong assumption.
3 or 5 values are rejected with a message naming the accepted forms, rather
than being silently reinterpreted. Negative values clamp to 0.
ASPECT: only the 1-value form is aspect-corrected (left/right multiplied by
gap_aspect) so `padding 1` looks square on a non-square cell grid. The 2- and
4-value forms are literal: specifying axes separately means the caller is
already controlling horizontal size, and silently doubling it would surprise.
Style now carries a PanePadding {top,bottom,left,right} instead of an x/y
pair, which also collapses the reconfigure plumbing back to a single field
rather than growing another parameter per side.
to_kdl always emits the explicit 4-value form: emitting the 1-value form
would re-apply gap_aspect on the next read and silently double the padding
on every config round-trip.
Baselines held: zellij-utils 435/5, zellij-server 1421/30.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Two changes to how the gap is defined.
1. UNIFORM GAP. Previously every pane inset every side by `gap`, so two
neighbours each gave up a cell and the space between them was 2*gap while
the screen edge got only gap. Now a pane insets RIGHT and BOTTOM always,
and LEFT/TOP only where that edge is the viewport boundary. Two neighbours
contribute exactly one gap between them, and the outer screen edges get
the same gap. `gap 1` now means 1 everywhere.
The per-side offset is computed in tiled_panes, which is the layer that
knows the viewport, and pushed to panes via Pane::set_gap_offset before the
content-offset sweep. Floating panes keep a zero gap: they are positioned
explicitly by the user, so an inter-pane gap does not apply to them (they
still get padding).
2. ASPECT CORRECTION. Terminal cells are roughly twice as tall as they are
wide, so an equal number of rows and columns does not look like an equal
distance. `gap` and `padding` are now expressed in ROWS, and columns are
multiplied by `gap_aspect` (default 2, minimum 1). Style carries the
resolved pane_gap_x/y and pane_padding_x/y.
FrameConfig::Default is now hand-written rather than derived: gap_aspect must
default to 2 to match the KDL parser, otherwise a parsed config disagrees with
a default-constructed one and it surfaces as config round-trip diffs (this
broke can_define_ui_configuration_in_configfile and both
bare_config_from_default_assets_to_string tests).
Tests assert the actual invariants: stacked and side-by-side neighbours get
exactly one gap between them, screen edges get the same gap as between panes,
and inset_by refuses to collapse a pane too small to survive it.
Baselines held: zellij-server 1421/30, zellij-utils 433/5.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Adds `ui { pane_frames { gap N; padding N } }`, both defaulting to 0 so
stock configs are unaffected.
gap - cells each pane gives up on every side, leaving real empty
terminal between neighbouring panes (WM-style outer gaps).
Two adjacent panes therefore show 2*gap between them.
padding - cells between a pane's frame and its content; breathing room
inside the pane without moving the frame.
Design: the pane KEEPS its allocated PaneGeom. Only two things move:
1. the drawn frame, via Viewport::inset(gap), reusing the existing
frame_geom_override mechanism already used for stacked panes;
2. the content, via Offset::expanded_by(gap + padding) inside
set_content_offset.
Because the allocation is untouched, the kasuari resize solver and mouse
hit-testing need no changes at all, and a click landing in a gap still
resolves to the owning pane. Content position, size and cursor are all
derived from content_offset, so widening it in one place keeps every
consumer consistent.
Viewport::inset refuses to shrink a pane below a frame's minimum viable
extent (two borders + one content cell) rather than emitting a degenerate
or zero-sized frame. Negative KDL values clamp to 0 instead of wrapping.
Tests cover: inset identity/shrink/recentre, the containment invariant
(an inset frame never escapes its allocation), small-pane refusal, and
the key safety property that content inset by gap+border+padding lands
strictly inside the frame drawn at inset(gap).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Adds `ui { pane_frames { title_alignment "left"|"center"|"right" } }`.
Full-frame panes previously hardcoded the title flush left, while frameless
panes (pane_frame_style "titles") already centered it via
compose_bracketed_title. This brings full frames up to parity and makes the
position configurable.
Implementation notes:
- The value rides on `Style`, which is already threaded to FrameParams, so no
new plumbing through Tab/PaneContentsAndUi was needed.
- It is deliberately NOT round-tripped over the plugin protobuf boundary:
plugins have no use for frame title alignment and adding a proto field
would force regenerating the committed prost assets in assets/prost/.
- Left keeps the original code path untouched, so default configs render
exactly as before.
- The geometry loop clamps the title start against the right-side indicators
and breaks on `>=` rather than `==`, so a mis-clamped segment cannot spin.
Tests: alignment ordering, frame width preservation across widths, and
narrow-pane safety (cols 1..24 must not panic or corrupt width).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* fix: theme query and updated pixel dimensions
* add no-ui-fullscreen key/action/capability
* protocol core
* integration test harness
* fix integration tests
* fix flaky tests
* nested ui (dimming) and directional focus initial implementation
* integration tests for nested ui dimming and directional focus
* initial full screen nesteed implementation
* fix: keep hidden floating panes hidden across nested no-ui fullscreen
* fix integration tests
* no ui fullscreen integration tests
* hardening behavior/tests
* fix(nested): re-derive descend/dim on host tab switch and new-tab so clicking dimmed chrome ascends
* initial modal implementation
* initial ui improvements
* fix integration tests
* improve nested selection ui
* nested session modal refactoring and tests
* improve integration test speed somewhat
* some ui adjustments
* simplify full/auto nested session handling
* hints in compact-bar
* guest stdin leak fix
* allow floating panes to be fullscreen
* make nested session handling configurable
* protocol reannounce
* refactor: naming confusion
* improve ux somewhat
* rustfmt
* merge fixes
* improve integration test rate limiting (fix ci)
* add pr
|
| |
|
|
|
|
|
|
|
|
|
| |
* feat: allow opening panes and tabs from the cli without focusing them
* rustfmt
* fix flake
* rustfmt
* add pr
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* initial implementation
* improve single line title design
* hint text plugin infra
* add proto regen task
* display alt text in status bar
* don't display text with full frames
* style alt hover text
* fix + style control own pane hover
* make multiplayer indications responsive
* update snapshots
* plugin api
* single pane as tab
* better scroll styling
* fix tests
* tab-bar plus hover
* plugin surface tests
* integration tests
* adjust all integration tests
* reduce hover noise
* add pane id to in place
* more integration tests
* style: rustfmt
* update plugin assets
* update assets and snapshots
* add pr
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* feat(panes): focus last pane (#4142)
* add tests
* add client id parameter to `add_floating_pane`
* add action for floating panes
* add tests for floating panes
* add keybinds to configs
* rebase fixes
* simplify focus logic when adding stacked pane
* formatting fix
* formatting fix 2
* fix: make sure expanding pane always focuses it for all clients in stack
* add pr
* fix rebase
---------
Co-authored-by: Aram Drevekenin <aram@poor.dev>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* phase 2+3
* initial mobile plugin (phases 4 + 5 + 6)
* some bugfixes
* implement stage 7
* mobile interface improvements
* improve mobile pane/tab picker
* more ui improvements and fixes
* various mobile fixes
* some mobile fixes
* mobile keyboard triggering fix
* some cleanups
* initial plugin keyboard implementation
* improve keyboard hit zones
* improve keyboard
* pinch resize
* pinching fixes
* implement scrolling + panning
* initial keyboard resizing
* fix: mobile first render issues
* keyboard responsiveness
* fix some issues with the keyboard
* implement fit
* fix mobile scrolling
* add tilde cell to compact
* improve mobile keyboard
* fix starting mobile terminal font to natural keyboard size
* fix mobile resize blank screen flash
* shadow focus for mobile
* more keyboard fixes
* improve mobile status bar
* fix: render plugins to mobile clients
* allow opening new panes/tabs from the mobile plugin
* allow configuring
* fix dot slash
* improve mobile native soft keyboard interaction
* switch to native keyboard - initial implementation
* dirty hacks, but phone keyboard works now
* adjust keyboard help strip
* fix cursor in mobile
* fix keyboard and help line
* rename keyboard to modifier bar
* allow starting new session
* make clicking session name bring us to new session menu
* allow switching to desktop from the mobile ui
* mobile welcome screen initial implementation
* mobile welcome screen fixes
* various welcome screen fixes
* more mobile fixes
* moar mobile fixes
* mobile ui redesign
* fix: swallowed backspace bug
* switch session screen improvement
* touch up some interfaces
* refactor: move mobile state to own struct
* refactor: move fit resizing to the server
* remove dead flash code
* some cleanups
* refactor: clear fit on close
* refactor: improve fit api
* refactor: pane sync functions
* refactor: mouse
* refactor: break into modules
* some cleanups for the sessions screen
* fix scrolling and other stuff
* refactor: sessions screen
* refactor: panes screen
* refactor: new session screen
* refactor: menu screen
* refactor: render
* cleanups
* refactor: plugin structure
* remove unused welcome screen path
* Rename api
* refactor input.js
* cleanup useless comments
* fit/mobile refactoring
* take out the garbage
* remove more comments
* remove mobile flash on startup/attach
* fix: various mobile startup issues
* fix space bugs
* cleanup
* rustfmt
* fix windows build
* adjust modifier bar ui
* add pr
|
| |
|
|
|
|
|
| |
* fix: session-manager delete
* rustfmt
* add pr
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
stale color queries (#5105)
* initial phase 1 implementation
* various fies
* some fixes
* fix fragmented stdin cases
* some fixes
* renaming
* guard against old clients
* implement csi 2031
* allow toggling theme with actions
* rustfmt
* fix: finalize trailing characters in ansi parser as well
* add pr
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* initial implementation
* fix mouse cpu spam
* prevent excess metadata write and prune sessions on startup
* consolidate CommandChanged and PaneCommandChanged
* tests
* rustfmt
* add pr
|
| |
|
|
|
|
|
|
|
| |
* allow sending a stringified layout with --layout-string
* add --tab-id to all the things
* fix windows tests
* add pr
|
| |
|
|
|
|
|
|
|
| |
* add zellij action focus-pane-id
* zellij action are-floating-panes-visible
* fix e2e tests
* add pr
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* remove pane render report
* only collect pane contents if pane should render
* add logs
* conditional keybinding serialization
* remove logs
* rustfmt
* fix tests
* tests
* rustfmt
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* Add Windows path support to strider plugin
Strider is a WASM plugin where std::path::PathBuf uses Unix semantics,
so Windows backslash paths break parent(), join(), strip_prefix(), etc.
Fix by normalizing all incoming paths to forward slashes at plugin
boundaries and converting back to native backslashes for display. A new
platform.rs module detects the host OS at runtime from the initial_cwd
format and centralizes all platform-aware logic.
Also fix scan_host_folder on the server side: canonicalize
plugin_host_folder so the starts_with security check works on Windows,
where canonicalize() adds the \?\ prefix.
* Add virtual root view for drive and WSL navigation in strider
On Windows, navigating up from a drive root (e.g. C:\) now shows a
"Computer" view listing all available drives and WSL distributions.
Drives are enumerated via GetLogicalDriveStringsW and WSL distros
via `wsl -l -q` (since read_dir on \wsl.localhost fails with OS
error 64/67). Drive letters appear before WSL entries, which are
displayed as "Ubuntu-24.04 (WSL)" etc. On non-Windows platforms,
behavior is unchanged.
* Rename ListHostEntries to ListWindowsVolumes and gate behind FullHdAccess
The old name was misleading — on Unix it just returned `/`, which isn't
"listing host entries." Rename to ListWindowsVolumes to make the
Windows-specific intent explicit, gate behind FullHdAccess permission,
and replace the Unix implementation with a log::error since the command
is not meaningful on non-Windows platforms.
* Replace direct array indexing with .get() in strider platform detection
Use safe accessors and matches! macro instead of direct byte indexing
for bounds-checked access patterns.
---------
Co-authored-by: divens <divens.dev@gmail.com>
|
| |
|
|
|
|
|
|
|
| |
* release notes
* fix some link issues
* rustfmt
* fix click wording
|
| |
|
|
|
| |
* cleanup compilation warnings
* consolidate EditScrollbackRaw into EditScrollback
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* add missing pane-id and tab-id arguments to all cli actions
* rustfmt
* dump-screen --ansi
* edit-scrollback --ansi
* add --ansi to subscribe
* add tests for ansi additions
* add ansi render report to plugins
* rustfmt
* fix e2e tests
* add pr
|
| |
|
|
|
|
|
|
|
|
|
| |
* add missing pane-id and tab-id arguments to all cli actions
* rustfmt
* fix tests
* update e2e snapshots
* add pr
|
| |
|
|
|
| |
* highlight priority levels
* add pr
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* feat(cli): add --pane-id option to dump-screen action
Adds the ability to dump a specific terminal pane's content by passing
`--pane-id <ID>` to the `dump-screen` CLI action. When omitted, the
existing behavior of dumping the focused pane is preserved.
This enables coding agents running inside Zellij to inspect the content
of other panes programmatically, without needing complex workarounds.
Prior art: https://github.com/theslyprofessor/zellij-pane-tracker, whose
design complexity is due to current limitations that this PR addresses.
* address review
* improve man page entry
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* initial implementation
* adjust ui
* preserve selection
* width responsiveness
* behavior fixes
* fix: do not count suppressed panes
* ui improvements
* multi-screen config and prompt hint
* tests + refactoring
* improve performance
* add pr
|
| |
|
|
|
| |
* add cli paste action
* add pr
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
of viewport (#4802)
* initial implementation
* implement hover
* add styles and foreground/background emphases, fix upsert hover collisions
* initial implementation of link plugin
* suppress highlighting + clicks on unfocused and mouse mode panes
* also make italic
* fix env var and ~ expansions
* fix regex issues and add defensive validations
* fix tests and add plugin assets
* add tests
* refactor all the things
* add pr
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* feat: add per-pane default foreground/background color support
Add per-pane default foreground and background colors, configurable
through four surfaces:
- OSC 10/11 escape sequences (set/query) and OSC 110/111 (reset)
- CLI action: zellij action set-pane-color --pane-id <id> --fg/--bg
- Layout config: default_fg/default_bg properties on pane nodes
- Plugin API: set_pane_color() SDK function and PaneInfo read-side
Colors are applied at render time as a fallback when cells have no
explicit foreground/background, without mutating stored grid data.
Closes #4712
* refactor: address review feedback for pane color support
- Extract adjust_styles_for_custom_bg_fg in output/mod.rs
- Move color parsing (xparse_color) from tab into Grid
- Move color serialization (ansi_code_to_color_string) into Grid
- Pane trait now uses Option<String> for color getters/setters
- Add colors to session serialization (dump-layout)
- Add default_fg/default_bg to protobuf IPC schema to fix
layout-in-session color loss
- Update example layout with tab-bar and status-bar
* fix stack overflow and ordering
* rustfmt
* update e2e snapshots
---------
Co-authored-by: Karl Bunch <karl@karlbunch.com>
Co-authored-by: Aram Drevekenin <aram@poor.dev>
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
* initial implementation
* rustfmt
* allow disabling with config
* add missing kdl
* add pr
* fix tests
|
| |
|
|
|
|
|
| |
* atomic show/hide floating panes (cli, plugin API, keybinding)
* rustfmt
* add pr
|
| |
|
|
|
|
|
| |
* allow close_replaced_pane from keybind and cli
* rustfmt
* add pr
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* scrollback with ansi support
* add command to kdl parser
* removed an unused esc (actually could cause some visualization issue)
* correctly reset style after new lines
* remove redundant reset
* preserve styled spaces
* more readable code
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* initial pipe interface
* initial open_x_pane_in_new_tab plugin api implementation
* fix: send CommandPaneExited for command panes opened as initial_terminals in new tabs from plugins
* open panes in place of specific pane id plugin commands - initial implementation
* sequence and plugin api ux
* focus self when starting
* combine ui and pipe paths
* highlight selected pane
* initial sequence removal of editing capabilities
* fix: translate plugin paths in api
* properly trim commands when loaded from pipe or pasted text
* minor ux fixes
* get ctrl c to work properly
* behavior fixes
* more ui fixes
* fix tests
* close tab and end sequence properly
* default to AND
* zellij sequence alias
* add alias
* consolidate paths
* rustfmt
* fix ui padding
* add pr
* fix: reset scrolling when resetting terminal state
|
| |
|
|
|
|
|
|
|
| |
permission) (#4700)
* allow plugins to read environment variables
* rustfmt
* add pr
|
| |
|
|
|
|
|
| |
* propagate plugin alias config changes to plugins
* rustfmt
* add pr
|
| |
|
|
|
|
|
|
|
| |
* add equivalent tab_id commands to tab_position commands (cli and plugins)
* add list-tabs and current-tab-info cli commands
* rustfmt
* add pr
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
* initial implementation
* fix tests
* implement zellij action send-keys
* rustfmt
* add test
* fix tests and add pr
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* return created tab_id from relevant plugin API methods
* add to cli
* return Option<PaneId> in plugin API methods that create panes
* return created pane_id in cli for relevant actions
* allow plugins to query for pane_info based on pane_id
* allow plugins to query for TabInfo by its id
* allow plugins to query pane command/cwd synchronously
* zellij action list-panes
* style and formatting
* fix e2e tests
* add pr
|
| |
|
|
|
|
|
|
|
|
|
| |
* refactor: clear distinction between tab_id and tab_position
* add tab_id to TabInfo
* add test
* rustfmt
* add pr
|
| |
|
|
|
|
|
|
|
|
|
| |
* initial implementation
* session manager ui and plugin api
* remove event
* cleanups and formatting
* add pr
|
| |
|
|
|
|
|
|
|
| |
* allow opening tiled pane as borderless
* rustfmt
* add pr
* fix e2e tests
|