| 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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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 mouse_hover_effects governs two unrelated things: the frame highlight
on hover, and the "Ctrl <MouseScroll> or <drag borders> to resize" hint. Its own
comment in default.kdl admits as much. So silencing a beginner reminder you have
outgrown also costs you a highlight that stays useful indefinitely.
mouse_hover_help_text (default true) gates only the hint. One line in
execute_send_to_terminal; the highlight is set in execute_update_hover and is
untouched.
Config-file only, deliberately. The option has no protobuf slot, so it does not
cross the client/server IPC contract -- the roundtrip test asserts exactly that,
with the fixture set to None and a comment explaining why. It still works from
the config file because the server parses the file itself and Options::merge
keeps the file value when the client sends None; a CLI flag would be silently
ignored.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The boxed entries read as clutter: every entry bracketed in vertical bars, and
the active one marked by a "> " that sits outside its own cell.
`stack_list_style "minimal"` drops both. The active entry is shown by
inverting it instead, which needs no glyph and no column, and the padding is
moved inside the styled run so the inverted block covers the whole cell rather
than leaving unstyled gaps at its edges. Four fewer columns of decoration per
entry, so more fit per row in grid mode.
Uses ribbon_selected rather than text_selected. Themes give ribbon_selected
real contrast because it marks the selected item elsewhere in zellij's UI --
gruber yellow here, white-on-blue in the TempleOS theme -- whereas
text_selected's background is 40,40,40 against a 24,24,24 terminal and read as
essentially no highlight when tried.
Decoration width comes from the style itself, so Tab's column arithmetic and
the renderer cannot disagree about how wide an entry is. Default stays boxed,
so nothing changes for anyone who does not ask.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
`stack_list_layout "grid"` packs picker entries several per row, which turns
stack_list_max_rows from a count into a space budget: eight panes in a wide
terminal now fit on one row instead of spending three and hiding five.
The entry renderer already drew each entry as a single chunk at its own x/y,
sized by its geom and centring its own label, so a grid needed no rendering
changes at all -- only the loop assigning every entry the same x and the full
width. Column count is derived from the widest label rather than configured, so
it adapts to the titles; one column is the floor and reproduces the previous
full-width rows byte for byte.
The row -> member mapping now has a column axis, and it had already caused one
wrong-pane bug when two consumers disagreed. So the layout is computed once,
by one function, into explicit cells; the renderer, the reserved-row budget and
the mouse hit-test all read those same cells rather than each doing their own
arithmetic. Windowing is by row, so a grid scrolls a whole row at a time and
degrades to the old per-member window when there is one column.
Cells are separated by a two-column gap: without it the focused entry's "> "
marker sits flush against the previous cell and reads as belonging to it.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A stack reserves one row per member plus a padding row, so a deep stack spends
most of the screen listing itself. `stack_list_max_rows` caps that; the list
windows around the focused member and reports the rest as "+N more".
The indicator goes in the padding row the list already reserves, so it costs
no extra row and never displaces a real entry. Entries keep their real rank
rather than renumbering from 1, otherwise the numbering stops meaning anything
once the window has scrolled. The window slides on ordinary focus movement,
which is also why this needs no new keybinding -- Action is a protobuf enum
and the prost assets cannot be regenerated here (no protoc).
A fixed cap rather than hover-to-expand on purpose: reserved_top_rows feeds
pane geometry, so growing the list on hover would resize the pane's PTY and
reflow whatever is running in it on every mouse move. A real expand/collapse
has to be an overlay that reserves nothing, which is a much larger change to
the render path.
reserved_top_rows and the renderer both go through stack_list_window(); if
they disagreed the list would draw into rows the geometry never reserved, i.e.
over the pane beneath it.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Splitting a window into thirds is great until the window is 70 columns wide
and each pane gets 23. `responsive_min_cols` collapses the tab into the swap
layout named by `responsive_layout` when it gets narrower than that, and
restores the previously active layout when it grows back.
Selects a swap layout BY NAME rather than adding a size-aware
LayoutConstraint: that type crosses both the plugin protobuf API and the
client/server contract, and the committed prost assets cannot be regenerated
here (no protoc).
Restoring uses a 10-column hysteresis band. Without a dead band, dragging a
window edge that lands exactly on the threshold flips the layout on every
motion event, and every flip resizes every PTY in the tab.
"Did the user rearrange panes by hand" is judged from the damaged flag as
sampled BEFORE each resize, not the live one: resize_whole_tab's own
auto-layout pass sets that flag itself and clears it again only if it found a
layout that fits, so on a terminal too narrow for any of them it latches true
although nothing was rearranged. And once collapsed, restore stays reachable
regardless of the flag, so damage occurring while collapsed cannot strand the
tab in the narrow layout.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
aa51848d replaced "SCROLL: 42/1000" with a compact "^42" glyph and stopped
showing any indicator when the pane is not actually scrolled up, but did not
refresh the insta snapshots that encode the old upstream frame rendering.
That left 30 failing tests in zellij-server from the very first sl0p commit
onward, which in turn masked 5 more in zellij-utils (cargo stops at the first
failing test binary, so zellij-utils never ran).
Bisected to aa51848d; the upstream fork point 0e6e4404 is green.
zellij-server (44 snapshots): frame titles lose the "SCROLL: 0/N" segment when
not scrolled, and render "^N" where they previously rendered "SCROLL: N/M".
Verified every diff is scroll-only, and that the genuinely-scrolled cases
(2/13, 3/33, 6/33) still render as ^2, ^3 and ^6 rather than disappearing.
zellij-utils (5 snapshots): serialized Config gained the sl0p FrameConfig
fields (title_alignment, gap, padding, gap_aspect, inactive_grayscale,
hide_default_pane_names), all at their existing defaults. Additions only.
Several tests assert multiple snapshots and insta aborts at the first
mismatch, so this took four regenerate/verify passes to fully converge.
zellij-server: 1471 passed, 0 failed.
zellij-utils: 441 passed, 0 failed.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* initial implementation - kinda working
* tests and fixes
* fix bounds
* tests and compatibility fixes
* fix: cursor scroll, clears, deletes, key tolerance, and host id range
* fix: keep images alive across resize, relayout and history scroll
* anchor to lines, not pixels
* fix image/text alignments
* config to allow disabling
* fix pinned pane issue
* never let host graphics replies reach the keyboard parser
* fix nested session
* properly handle fullscreening a pane
* rustfmt
* cleanup of ignored test
* add pr
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
* chore(deps): upgrade base64 0.22, colored 3.1, crossterm 0.29, dialoguer 0.11, directories 6.0, highway 1.2, prost 0.12.6, strip-ansi-escapes 0.2.1, suggest 0.5.1
* chore(deps): upgrade miette 7.6, nix 0.30, notify 8.2, notify-debouncer-full 0.5
* vte 0.15
* clap 4.6
* workspaceify plugin deps
* don't send empty fs watch events
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
table (#5324)
* build(deps): bump sysinfo to 0.37 for scan-free partial process refresh
Bump it to pull in sysinfo 0.37's change "Linux: greatly improve partial
processes retrieval", so that refreshing a specific set of pids
(ProcessesToUpdate::Some) no longer walks the entire /proc tree.
This makes the existing get_cwd/get_cwds polling O(panes) instead of
O(host processes) and unblocks doing the same for foreground-command discovery.
* perf: discover foreground pane commands w/o scanning all processes
Foreground command discovery was reading information about every process
on the host, on each pane/tab creation and on every periodic poll. On hosts
with many processes (eg, 50k) this stalled pane creation for tens of seconds
and overran the action-completion timeout.
Replace that O(host processes) lookup with an O(panes) lookup. Instead
of looking up the parent pid of every process to find the child, get
the foreground process-group leader's pid from a call to tcgetpgrp on
the pane's controlling terminal. When the leader is the shell itself
(idle prompt or a command sharing the shell's group without job control)
the pane is omitted and the caller falls back to the shell command,
matching prior behavior; with job control on it now reports the true
foreground job instead of possibly a background one.
This changes the paths for Linux, macOS, and BSD. It leaves Windows unchanged.
* refactor(os_input): extract apply_post_command_hook helper
The command -> run_command_hook -> trim/split pipeline was duplicated between
the #[cfg(not(unix))] get_all_cmds_by_ppid and the unix get_foreground_cmds.
Extract a single apply_post_command_hook helper and call it from both sites,
routing the hook-failure fallback through the project's non_fatal() logging
idiom (CONTRIBUTING.md "Logging errors") instead of log::error!.
* review: simplify tcgetpgrp locking, trim comments, drop changelog entries
- Remove the lock-drop dance and its TOCTOU caveat from tcgetpgrp,
to make it mirror tcdrain
- Prune AI comments
- Remove CHANGELOG entries
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* initial implementation
* improve ui
* fix: stacked resize interaction
* title list boundaries fix
* fix BEL
* mouse parity
* float/embed + bulk-op features
* fix in-place bug
* improve ui
* config live reload
* improve ui
* fix issues, add exit status
* fix for serialization
* fix tests
* integration tests
* comments
* refactor: duplicate title logic
* refactor: consolidate logic
* fix: flaky tests
* add a stacked swap layout
* rustfmt
* fix e2e
* 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>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* initial implementation
* refactoring and cleanups
* port basic e2e tests
* fix tab rotation
* migrate client and mouse tests
* migrate the rest of the tests
* remove old e2e tests
* rustfmt
* add e2e note
* fix stale test
* fix: cross platform locking/cleanup
* fix: change mode race discovered by tests
* rustfmt
* fix: attach/detach race in tests
* fix plugin test assertion
* add pr
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* 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: clear bell when focusing with mouse
* add pr
|
| |
|
|
|
|
|
| |
* fix: deadlock with blocking panes
* rustfmt
* add pr
|
| |
|
|
|
|
|
| |
* feat: allow independent tab resizing
* rustfmt
* add pr
|
| |
|
|
|
|
|
| |
* fix: block pty byte processing while waiting for host terminal reply
* 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
|
| |
|
|
|
|
|
|
| |
(#5014)
PR #4967 added VT modifier encoding for non-Char keys but the guard
condition also matched Char keys, re-encoding Ctrl+C from [0x03] to
CSI u sequence \x1b[3;5u which shells don't understand. Skip the
encoding block for Char keys since they already handle modifiers.
|
| |
|
|
|
|
|
| |
* fix: race condition when starting panes
* rustfmt
* add pr
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* fix: respect --name flag when creating and renaming panes
Three issues fixed:
1. Pane creation: --name was silently discarded for default shell panes
because use_terminal_title was true. Now user-provided names take
priority. Also pass initial_pane_title as pane_name to TerminalPane
constructor (was hardcoded to empty string).
2. CLI rename without --pane-id: was routed through PaneNameInput which
appends to existing name. Now uses a dedicated RenameActivePane action
that fully replaces the name, working for any name length including
single characters.
3. Interactive rename: entering rename mode preserves the existing name
for editing (append/backspace). Esc reverts to the name before rename
mode was entered.
Adds 28 tests covering rename semantics, interactive editing, undo,
OSC title interaction, and a wire-level IPC round-trip test.
* refactor: route active-pane rename via Option<PaneId>
Replace the dedicated Action::RenameActivePane variant with an
Option<PaneId> on the existing Action::RenamePaneByPaneId. route.rs
dispatches None to the server-internal ScreenInstruction::RenameActivePane
and Some(id) to the existing RenamePaneWithPaneId path.
Drops all proto/conversion boilerplate for the removed variant: plugin
API additions, IPC tag 137, and both directions of the wire conversion.
---------
Co-authored-by: divens <divens.dev@gmail.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* fix: position host cursor for CJK IME even when app hides cursor
When apps like Claude Code (ink/React library) hide the cursor during
rendering, Zellij's render_cursor() was not sending a CUP sequence to
the host terminal. This caused IME composition candidates to appear at
the wrong position, breaking CJK input in these apps.
Change cursor_coordinates() to return the cursor position unconditionally
(as long as it is within bounds) along with a bool indicating visibility.
render_cursor() now positions the host cursor even when the app has hidden
it, so the IME subsystem can read the correct cursor position.
* add test
* rustfmt
---------
Co-authored-by: Aram Drevekenin <aram@poor.dev>
|
| |
|
|
|
|
|
|
|
| |
* 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 all blocking flags to action new-pane
* security updates
|
| |
|
|
|
| |
* 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
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
(#4818)
* fix: handle short writes in write_to_tty_stdin to prevent paste truncation
On macOS the kernel PTY buffer is only 4-16 KiB, so a single write()
call for a large paste returns a short write count rather than blocking
until all bytes are accepted. The current code returns this partial
count without retrying, silently dropping the remaining bytes.
This wraps the write in a retry loop that handles:
- Short writes (advances the buffer offset and retries)
- EINTR (retries immediately)
- EAGAIN (sleeps 1ms then retries)
Without this fix, pasting ~1 KiB+ of text into a terminal pane loses
everything beyond the first kernel-buffer-full.
Includes a test that exercises the fix using a real PTY pair with
O_NONBLOCK set on the master fd to force short writes.
* fix: cap EAGAIN retries at 50 to prevent infinite busy-wait
Per reviewer feedback, add a retry counter that caps consecutive EAGAIN
retries at 50 and logs an error if the limit is reached. The counter
resets on any successful write progress, so it only triggers when the
PTY is genuinely stuck.
* fix: use poll(POLLOUT) instead of sleep-retry loop for EAGAIN handling
Replace the 50-retry sleep(1ms) busy-wait with poll(POLLOUT, 5s timeout).
This properly waits for fd writability without CPU spinning and returns
an error on timeout instead of silently returning Ok(partial) — which
the caller (pty_writer_main) would ignore, causing silent data loss.
Tests:
- write_to_tty_stdin_delivers_all_bytes: remove flaky reader delay,
use concurrent reader, move master close after reader join to avoid
macOS kernel buffer flush race
- write_all_to_fd_errors_on_stuck_pty: new test verifying timeout
returns Err on stuck PTY (uses 100ms timeout for speed)
* fix: re-queue partial PTY writes instead of blocking PtyWriter thread
Replace the poll(POLLOUT) blocking loop with a non-blocking re-queue
approach as suggested in review. On partial write or EAGAIN:
- write_to_tty_stdin now drains as much as the kernel accepts in one
pass and returns the count (may be 0 on EAGAIN)
- PtyWriter re-queues unwritten bytes back onto its own channel,
letting other terminals' writes proceed between retries
- Retry count tracks consecutive zero-progress attempts (reset on
any forward progress), drops bytes after 50 retries with log::error
- yield_now() before re-queue on zero progress to avoid tight spin
- Guard against write() returning Ok(0) on non-empty buffer
- Wire up PtyWriter's self-sender (was None, now Some(&to_pty_writer))
* fix: per-terminal write buffering to handle short writes and EAGAIN
Replace re-queue approach with per-terminal pending write buffers
(HashMap<u32, VecDeque<PendingWrite>>). Uses recv_timeout(10ms) when
pending data exists, blocking recv when idle. 10MB per-terminal cap
drops buffer on overflow. Terminal errors clear the queue.
Adds Bus::recv_timeout via crossbeam Select::select_timeout.
Removes tcdrain from write path.
* use safe accessor methods and saturating substitutions
* add tests for ptywriter
* rustfmt
* fix tests by not assuming kernel buffer sizes
* rustfmt
* add pr
---------
Co-authored-by: Aram Drevekenin <aram@poor.dev>
|
| |
|
|
|
|
|
|
|
| |
* implement focus follows mouse
* mouse click through
* rustfmt
* 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 subscribe implementation
* tests for subscribe
* update cli help
* rustfmt
* 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>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* feat: add Windows signal and process implementations
- AsyncSignalListener: polls crossterm size at 100ms, tokio ctrl_c/break/close
- BlockingSignalIterator: SetConsoleCtrlHandler + AtomicBool, polls size at 50ms
- signal_process: GenerateConsoleCtrlEvent for Interrupt, TerminateProcess for Kill
- Add windows-sys workspace dependency
* feat: add Windows IPC support with named pipes and marker files
- ipc_connect/ipc_bind/ipc_bind_async helpers with cfg gates for named pipes
- Dual-pipe architecture on Windows: main pipe + reply pipe per connection to
prevent IPC deadlock (half-duplex named pipe limitation)
- is_ipc_socket returns is_file() on non-Unix for marker file discovery
- ipc_bind creates empty marker file after binding named pipe on Windows
- assert_socket split: cfg(unix) probes with ConnStatus, cfg(not(unix)) returns
true to avoid deadlocking the server accept loop
- Replace tokio UnixListener/UnixStream with interprocess tokio Listener/Stream
in web server IPC for cross-platform support
- Add interprocess tokio feature to workspace deps
* feat: add Windows client support for input, server spawn, and stack size
- Two-mode Windows input: crossterm event reader for native console,
termwiz byte parser for terminal emulators (VT input mode)
- cast_crossterm_key: convert crossterm KeyEvent to KeyWithModifier
- ENABLE_VIRTUAL_TERMINAL_INPUT on Windows stdin for raw VT byte reading
- Skip ANSI terminal query on Windows to unblock startup
- spawn_server: CREATE_NO_WINDOW | CREATE_NEW_PROCESS_GROUP on Windows
- 8MB stack trampoline in main() for Windows (default 1MB overflows)
- 8MB stack for server worker threads (WASM compilation needs it)
- Enable crossterm events and bracketed-paste features
* test: make tests cross-platform for Windows
- Socket tests: cross-platform IpcGuard/IpcName helpers with GenericNamespaced
on Windows vs GenericFilePath/TempDir on Unix
- Layout tests: normalize_layout_debug() replaces backslash separators in Debug
output on Windows; gate env_var_expansion test with cfg(unix)
- Setup tests: use PathBuf::join + display() instead of hardcoded / separators
- Server OS tests: cross-platform command helpers (long_running_cmd, echo_cmd,
stdin_reader_cmd) with CREATE_NO_WINDOW on Windows
- zellij_exports: replace GenericFilePath with ipc_connect() helper
* ci: add Windows build and test jobs with debug logging
- Add build-windows job: cargo check --no-default-features on windows-latest
- Add test-windows job: cargo test --no-default-features for utils/server/client
- Enable manual workflow_dispatch trigger
- Add debug log::info! calls in server startup, plugin loading, PTY spawning,
and screen layout application for troubleshooting
* feat: implement Windows stubs for shell, command hooks, and process listing
Replace unimplemented!() stubs with working Windows implementations:
- get_default_shell: reads $COMSPEC, falls back to cmd.exe
- run_command_hook: uses cmd /C with RESURRECT_COMMAND env var
- get_all_cmds_by_ppid: uses sysinfo to enumerate processes by parent PID
* feat: implement Windows daemonize_web_server with detached process spawning
Replace the `unimplemented!()` stub with a proper background process
spawner that mirrors the existing `spawn_server` pattern: launch a
foreground `zellij web --start` child with CREATE_NO_WINDOW |
CREATE_NEW_PROCESS_GROUP, poll the TCP port to confirm it's listening,
then exit the parent process.
* feat: implement native ConPTY backend for Windows PTY
Replace all WindowsPtyBackend stubs with a full ConPTY implementation:
- CreatePseudoConsole with overlapped named pipes for IOCP-based async
I/O (zero extra threads on the read path per pane)
- CreateProcessW with PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE and proper
UTF-16 command line quoting / environment block construction
- ConPtyAsyncReader with lazy promotion from OwnedHandle to tokio
NamedPipeServer (reactor not available at spawn time)
- Per-terminal exit monitoring thread using WaitForSingleObject
- ResizePseudoConsole for terminal resize, WriteFile for stdin,
TerminateProcess / GenerateConsoleCtrlEvent for signals
Note: for PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE, the HPCON value must be
passed directly as lpValue (not a pointer to it), matching the C
convention where HPCON is void*. In Rust (windows-sys) HPCON is isize,
requiring an explicit cast. See microsoft/terminal#6705.
* chore: remove debug logging from ConPTY backend
* fix: resolve Windows plugin directory and WASI mount errors
Two Windows-specific fixes for the plugin system:
1. Replace colons with underscores in URL-derived plugin directory names
(e.g. "zellij:tab-bar" -> "zellij_tab-bar"). Colons are illegal in
Windows path components, causing OS error 123 on plugin dir creation.
2. Use FILE_FLAG_BACKUP_SEMANTICS when opening directories for WASI
pre-opened mounts. Windows requires this flag to open directory
handles, otherwise File::open() returns OS error 5 (access denied).
Both fixes are behind #[cfg(windows)] — Unix behavior is unchanged.
* fix: enable mouse support on Windows native console path
Mouse events were silently dropped in the crossterm event loop, and
enable_mouse() wrote VT escape sequences that don't set the required
ENABLE_MOUSE_INPUT console mode flag. Add from_crossterm_mouse()
converter, InputInstruction::MouseEvent variant, and use crossterm's
EnableMouseCapture/DisableMouseCapture on Windows.
* fix: Windows get_default_shell() now checks $SHELL before $COMSPEC
* fix: resolve bare command names via PATH and PATHEXT on Windows
CreateProcessW doesn't reliably resolve bare command names (e.g.
"pwsh") through PATH the way Unix execvp does. Additionally, the
existing command_exists() check didn't consider Windows PATHEXT
extensions (.exe, .cmd, .bat, etc.).
Add find_executable() and resolve_command() which search PATH with
PATHEXT support on Windows, and use the resolved absolute path when
spawning via CreateProcessW.
* chore: run cargo fmt --all
* fix: canonicalize expected paths in setup tests for Windows \\?\ prefix
* fix: Windows CI test failures in spawn_and_read_output and snapshot test
Use cmd /K instead of /C in spawn test so ConPTY has time to flush
output before the pipe closes. Normalize backslashes in snapshot test
to handle Windows path separators.
* fix: strip redundant Shift and AltGr modifiers from Windows key events
On the Windows native console path, crossterm reports physical modifier
flags alongside the already-translated character. For example on French
AZERTY, Shift+ù produces Char('%') with SHIFT, and AltGr+_ produces
Char('\') with CTRL+ALT. These extra modifiers cause keybinding
mismatches and prevent modified characters from being typed in plugin
text inputs.
Strip Shift for all Char events and Ctrl+Alt (AltGr) when the character
is printable, matching Unix terminal behavior where only the resulting
character is reported. Also fix raw byte synthesis for AltGr characters
to emit plain UTF-8 instead of ESC-prefixed sequences.
* fix: detect and clean up stale Windows sessions via PID-based liveness check
Write server PID to marker files instead of creating empty files.
assert_socket() on Windows now reads the PID and checks process liveness
via OpenProcess, cleaning up stale marker files for dead sessions.
* fix: connect reply pipe on Windows for kill-session and delete-session
On Windows the server blocks on reply_listener.accept() after accepting
the main pipe connection. Without a reply pipe connection, the route
thread is never spawned and the KillSession message is never processed.
* fix: wait for server Exit response in kill/delete session on Windows
The previous fire-and-forget approach was unreliable: the client would
disconnect before the server's route thread had time to read and process
the KillSession message. Now we wait for the Exit response on the reply
pipe, ensuring the server has fully processed the kill before we return.
* fix: resolve Windows console mode race between VT input and mouse setup
Two threads race over SetConsoleMode on the stdin console handle:
- stdin_handler calls enable_vt_input() (read-modify-write)
- input_handler calls enable_mouse() via crossterm's EnableMouseCapture
(full SetConsoleMode overwrite to 0x0098)
Depending on ordering, crossterm could clobber ENABLE_VIRTUAL_TERMINAL_INPUT
(breaking the VT byte reader), or enable_vt_input could preserve
ENABLE_QUICK_EDIT_MODE (intercepting mouse events at the console level).
Fix enable_vt_input() to explicitly set the exact console mode needed
(0x0298) instead of read-modify-write, clearing QUICK_EDIT_MODE and other
line-editing flags.
Fix enable_mouse()/disable_mouse() on the VT path (TERM is set) to use
ANSI escape sequences instead of crossterm's Console API, avoiding the
competing SetConsoleMode call entirely. Enable ENABLE_VIRTUAL_TERMINAL_PROCESSING
on stdout first so ConPTY forwards the DEC private mode sequences to the
terminal emulator.
* fix: session-manager plugin kill session on Windows dual-pipe IPC
The plugin's kill_sessions() only connected the main pipe and sent
KillSession, but on Windows the server blocks on reply_listener.accept()
before spawning the route thread. Without connecting the reply pipe the
message was never processed.
Add the same dual-pipe handling as the CLI kill_session(): connect the
reply pipe first, send the message, then wait for the Exit response.
* fix(windows): replace resize polling with event forwarding from stdin thread
Forward crossterm Event::Resize from the stdin thread to the signal
handler thread via an mpsc channel, replacing the 50ms polling loop.
This makes terminal resizing much more responsive during mouse-driven
resizes and eliminates wasteful polling when idle.
When the VT reader path is active (terminal emulators with TERM set),
the sender is dropped, causing the signal handler to automatically
fall back to size-polling — preserving existing behavior for that path.
Unix is unaffected: handle_signals receives None for the receiver and
BlockingSignalIterator continues using signal_hook as before.
* fix(windows): enable ANSI terminal queries on the VT reader path
The startup ANSI query mechanism (pixel dimensions, colors, sync output)
was blanket-skipped on Windows. The actual limitation is specific to the
native console path, where crossterm's event::read() uses
ReadConsoleInput (INPUT_RECORDs) and never reaches the byte-reader loop
that parses ANSI responses.
On the VT reader path (terminal emulators like Alacritty with TERM set),
fill_buf() reads raw VT bytes via ReadFile — same as Unix — so ANSI
query responses work normally. Move the use_vt_reader decision earlier
and use it to gate the query, enabling it for the VT reader path while
still skipping it on native console.
* fix: handle early TerminalResize before client is fully registered
On Windows, enable_mouse()'s SetConsoleMode call can generate a
WINDOW_BUFFER_SIZE_EVENT that arrives as a resize before the server
finishes processing the initial client connection. At that point
set_client_data() hasn't been called yet, so set_client_size() silently
no-ops on the None entry and min_client_terminal_size() returns None.
Instead of panicking, skip the resize when the minimum size can't be
determined — the server will query the terminal size once setup
completes.
* fix: remove unnecessary custom stack size
Early versions of zelilj windows port crashed with stack overflow.
Increasing stack size allowed proper startup and moving further with the
porting effort. Current implementation no longer suffers from stack
issues, so we can revert back to default stack size.
* fix(windows): re-enable Ctrl+C handling inherited by ConPTY children
The server is spawned with CREATE_NEW_PROCESS_GROUP, which disables
Ctrl+C for the process. Children inherit this disabled state, so
ConPTY child processes (shells, ping, etc.) silently ignore
CTRL_C_EVENT signals generated by the pseudo-console.
Call SetConsoleCtrlHandler(NULL, FALSE) early in start_server() to
clear the inherited ignore flag before any ConPTY children are created.
* refactor(windows): move inline cfg(windows) blocks to platform files
Break out inline #[cfg(windows)] blocks from shared client code into
the existing _unix.rs / _windows.rs platform files, per upstream
feedback.
- Split spawn_server into two #[cfg]-gated function definitions
- Extract setup_ipc, enable_mouse_support, disable_mouse_support into
os_input_output_unix.rs and os_input_output_windows.rs
- Unify BlockingSignalIterator::new() signature across platforms
- Extract native console stdin loop into stdin_handler_windows.rs
* fix: remove sporadic info log statements
* ci(windows): add Windows x64 release builds and upgrade CI
- Add Windows x64 target to release.yml for both normal and no-web
release matrices, with NASM, static CRT, .zip packaging, and
PowerShell checksum steps
- Upgrade build-windows in rust.yml from cargo check to cargo xtask
build, add wasm32-wasip1 target and NASM
- Add build_release() function and platform-aware e2e_build() to
xtask/src/ci.rs
- Add BuildRelease command definition to xtask/src/flags.rs
* refactor(client): make resize channel unconditional across platforms
Create the resize mpsc channel on all platforms instead of gating it
behind #[cfg(windows)], avoiding conditionally-existing variables that
are hard to follow. On Unix the sender is immediately dropped and the
receiver is passed as None-equivalent to handle_signals.
* refactor(windows): restructure signal iterator with if/else for channel vs poll
Consolidate the quit check at the top of a single loop and use if/else
for channel mode (native console) vs poll mode (VT reader). On channel
disconnect, set resize_receiver to None and continue into the else
branch instead of falling through.
* docs(server): clarify comment about early resize before client init
Explain why min_client_terminal_size() can return None even after
set_client_size(): new_client() inserts None, and set_client_size()
is a no-op on None entries since it uses as_mut().map().
* feat(web): add --server-startup-timeout flag for web server
Make the hardcoded 10-second TCP-poll timeout in the non-Unix
daemonize_web_server configurable via a CLI flag, defaulting to 10s.
* fix(windows): use unique pipe names for ConPTY output on re-spawn
When a held pane re-runs a command or drops to shell, do_spawn tried
to create a named pipe with the same name as the previous spawn. The
old ConPtyAsyncReader still held the read handle, so CreateNamedPipeW
failed (FILE_FLAG_FIRST_PIPE_INSTANCE, max instances = 1) and the
error was silently swallowed, leaving the pane blank.
Add a monotonic AtomicU64 counter to the pipe name so each spawn gets
a globally unique pipe, regardless of whether the previous one has
been cleaned up yet.
* ci(windows): enable static CRT for regular Windows release build
The no-web Windows build already had RUSTFLAGS="-C target-feature=+crt-static"
but the regular build was missing it, resulting in a dynamic CRT dependency.
* docs(web): clarify --server-startup-timeout is Windows-only
---------
Co-authored-by: divens <divens.dev@gmail.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
* initial implementation
* rustfmt
* allow disabling with config
* add missing kdl
* add pr
* fix tests
|
| |
|
|
|
| |
* fix: properly offset viewport when refreshing
* update snapshots
|
| |
|
|
|
|
|
| |
* allow close_replaced_pane from keybind and cli
* rustfmt
* add pr
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
for cross-platform support (#4740)
* refactor: upgrade interprocess to v2+ with cross-platform IPC support
Replace interprocess 1.2.1 with 2.2+ which provides cross-platform
local socket support (Unix domain sockets on Unix, named pipes on
Windows). Migrate all call sites from the flat v1 API to the v2
enum-dispatch API, and replace nix::unistd::dup fd-duplication with
interprocess::TryClone::try_clone().
* refactor: abstract FD duplication in IPC behind IpcStream trait
Decouple IPC structs from the concrete transport by introducing an
IpcStream trait that abstracts read/write/clone. Internal fields change
from BufWriter<LocalSocketStream> to BufWriter<Box<dyn IpcStream>>,
while the public new() constructors still accept LocalSocketStream so
no callers need updating.
* refactor: abstract session discovery behind is_ipc_socket() helper
Replace all 6 direct uses of std::os::unix::fs::FileTypeExt::is_socket()
with a cross-platform is_ipc_socket() helper in consts.rs. On Unix it
delegates to FileTypeExt::is_socket(); on non-Unix it returns false as a
placeholder for platform-specific session discovery added later.
---------
Co-authored-by: divens <divens.dev@gmail.com>
|