<feed xmlns='http://www.w3.org/2005/Atom'>
<title>sl0ppij.git/zellij-server/src/thread_bus.rs, branch main</title>
<subtitle>a sl0p.foo repository</subtitle>
<id>https://git.sl0p.foo/sl0ppij.git/atom/zellij-server/src/thread_bus.rs?h=main</id>
<link rel='self' href='https://git.sl0p.foo/sl0ppij.git/atom/zellij-server/src/thread_bus.rs?h=main'/>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/sl0ppij.git/'/>
<updated>2026-03-12T09:12:22Z</updated>
<entry>
<title>fix: handle short writes in write_to_tty_stdin to prevent paste truncation (#4818)</title>
<updated>2026-03-12T09:12:22Z</updated>
<author>
<name>Edgars Nemše</name>
<email>edgars.nemse@gmail.com</email>
</author>
<published>2026-03-12T09:12:22Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/sl0ppij.git/commit/?id=3ef1675bbf126db11137b17bfe94c7cab7282c07'/>
<id>urn:sha1:3ef1675bbf126db11137b17bfe94c7cab7282c07</id>
<content type='text'>
* 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(&amp;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&lt;u32, VecDeque&lt;PendingWrite&gt;&gt;). 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 &lt;aram@poor.dev&gt;</content>
</entry>
<entry>
<title>Feature: allow overriding a layout for a currently running tab (change layout at runtime) (#4566)</title>
<updated>2025-12-23T12:41:56Z</updated>
<author>
<name>Aram Drevekenin</name>
<email>aram@poor.dev</email>
</author>
<published>2025-12-23T12:41:56Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/sl0ppij.git/commit/?id=3fe48a972c55537502128779116d38d8f8aedb7e'/>
<id>urn:sha1:3fe48a972c55537502128779116d38d8f8aedb7e</id>
<content type='text'>
* add tests for LayoutApplier

* initial untested implementation of override functions

* add override-layout cli action with stub in screen

* filter run instructions to ignore

* implement override-layout roundtrip through plugin and pty threads

* initial full-cycle working override implementation

* fix some bugs (eg. actually start new terminals)

* fix some bugs with focus after override

* fix floating pane matching bug in layout applier

* formatting

* use first tab, error on more than 1 tab

* fix some floating_panes ordering and shell issues

* get new tab name to work

* respect swap layouts

* allow specifying tab properties on main layout node if we just have one tab

* add tests for new override methods

* start work on retaining panes, hard-coded things, kind of working but broken in many places

* fixed most tiled pane override bugs

* reset viewport before reapplying

* revert constraint system changes

* retain-existing-terminal-panes flag

* add retain terminal panes tests

* add retain plugin panes flag

* add keybind

* add retain plugin panes tests

* add override-layout e2e test

* refactor: layout_applier

* style: rustfmt

* some cleanups

* fix cli flags

* no crashy

* formatting and artifacts

* moar cleanups

* fix: respect expanded in stack when overriding

* docs(changelog): add PR</content>
</entry>
<entry>
<title>feat(ui): swap layouts and stacked panes (#2167)</title>
<updated>2023-02-17T11:05:50Z</updated>
<author>
<name>Aram Drevekenin</name>
<email>aram@poor.dev</email>
</author>
<published>2023-02-17T11:05:50Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/sl0ppij.git/commit/?id=f1ff272b0b65f6d328fef24531ada67ea585ce85'/>
<id>urn:sha1:f1ff272b0b65f6d328fef24531ada67ea585ce85</id>
<content type='text'>
* relayout working with hard coded layout

* work

* refactor(layout): PaneLayout =&gt; TiledPaneLayout

* tests passing

* tests passing

* tests passing

* stacked panes and passing tests

* tests for stacked panes

* refactor(panes): stacked panes

* fix: focusing into stacked panes from the left/right

* fix(layouts): handle stacked layouts in the middle of the screen

* fix(pane-stack): focus correctly when coming to stack from above/below

* fix(stacked-panes): resize stack

* fix(stacked-panes): focus with mouse

* fix(stacked-panes): focus next pane

* fix(layout-applier): sane focus order

* fix(stacked-panes): better titles for one-liners

* fix(stacked-panes): handle moving pane location in stack

* fix(relayout): properly calculate display area

* fix(relayout): properly calculate rounding errors

* fix(stacked-panes): properly handle closing a pane near a stack

* fix(swap-layouts): adjust swap layout sort order

* feat(swap-layouts): ui + ux

* fix(swap-layouts): include base layout

* refactor(layout): remove unused method

* fix(swap-layouts): respect pane contents and focus

* work

* fix(swap-layouts): load swap layouts from external file

* fix(swap-layouts): properly truncate layout children

* fix(stacked-panes): allow stacked panes to become fullscreen

* fix(swap-layouts): work with multiple tabs

* fix(swap-layouts): embed/eject panes properly with auto-layout

* fix(stacked-panes): close last pane in stack

* fix(stacked-panes): move focus for all clients in stack

* fix(floating-panes): set layout damaged when moving panes

* fix(relayout): move out of unfitting layout when resizing whole tab

* fix(ui): background color for swap layout indicator

* fix(keybinds): add switch next layout in tmux

* fix(ui): swap layout indication in compact layout

* fix(compact): correct swap constraint

* fix(tests): tmux swap config shortcut

* fix(resizes): cache resizes so as not to confuse panes (eg. vim) with multiple resizes that it debounces weirdly

* feat(cli): dump swap layouts

* fix(ui): stacked panes without pane frames

* fix(ux): move pane forward/backwards also with floating panes

* refactor(lint): remove unused stuff

* refactor(tab): move swap layouts to separate file

* style(fmt): rustfmt

* style(fmt): rustfmt

* refactor(panes): various cleanups

* chore(deps): upgrade termwiz to get alt left-bracket

* fix(assets): merge conflicts of binary files

* style(fmt): rustfmt

* style(clippy): no thank you!

* chore(repo): remove garbage file</content>
</entry>
<entry>
<title>fix(panes): show visual error when unable to split panes vertically/horizontally (#2025)</title>
<updated>2022-12-14T21:26:48Z</updated>
<author>
<name>Aram Drevekenin</name>
<email>aram@poor.dev</email>
</author>
<published>2022-12-14T21:26:48Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/sl0ppij.git/commit/?id=c3115a428ed5c990cc5ead5629dabb624ae90453'/>
<id>urn:sha1:c3115a428ed5c990cc5ead5629dabb624ae90453</id>
<content type='text'>
* fix(panes): show visual error when failing to split pane vertically/horizontally

* fix: lockfile</content>
</entry>
<entry>
<title>refactor(plugins): fix plugin loading data flow (#1995)</title>
<updated>2022-12-06T14:34:43Z</updated>
<author>
<name>Aram Drevekenin</name>
<email>aram@poor.dev</email>
</author>
<published>2022-12-06T14:34:43Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/sl0ppij.git/commit/?id=b7adfcc581d40952ec5d1f5a853669322e895bd7'/>
<id>urn:sha1:b7adfcc581d40952ec5d1f5a853669322e895bd7</id>
<content type='text'>
</content>
</entry>
<entry>
<title>refactor(plugins): change the data flow (#1934)</title>
<updated>2022-11-15T11:21:36Z</updated>
<author>
<name>Aram Drevekenin</name>
<email>aram@poor.dev</email>
</author>
<published>2022-11-15T11:21:36Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/sl0ppij.git/commit/?id=3d2a6d6a5aa47cace356fe39184f2ac018898552'/>
<id>urn:sha1:3d2a6d6a5aa47cace356fe39184f2ac018898552</id>
<content type='text'>
* refactor(plugins): do not block render loop

* refactor(plugins): cleanup

* style(fmt): rustfmt

* fix(plugins): various rendering pipeline fixes</content>
</entry>
<entry>
<title>zellij-server: improve thread_bus error handling (#1775)</title>
<updated>2022-10-07T09:04:08Z</updated>
<author>
<name>Bohdan Ivashko</name>
<email>20084245+arriven@users.noreply.github.com</email>
</author>
<published>2022-10-07T09:04:08Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/sl0ppij.git/commit/?id=39f33a9a9a47bd7e22bff4c1ec3a0a1456ca30e8'/>
<id>urn:sha1:39f33a9a9a47bd7e22bff4c1ec3a0a1456ca30e8</id>
<content type='text'>
* zellij-server: improve thread_bus error handling

* zellij-server/thread_bus: get rid of option.unwrap

* zellij-utils/errors.rs: generic error in to_anyhow</content>
</entry>
<entry>
<title>feat(config): switch to kdl (#1759)</title>
<updated>2022-10-05T05:44:00Z</updated>
<author>
<name>Aram Drevekenin</name>
<email>aram@poor.dev</email>
</author>
<published>2022-10-05T05:44:00Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/sl0ppij.git/commit/?id=79bf6ab868cbdab1f9a3827c9b70198f54548b44'/>
<id>urn:sha1:79bf6ab868cbdab1f9a3827c9b70198f54548b44</id>
<content type='text'>
* chore(config): default kdl keybindings config

* tests

* work

* refactor(config): move stuff around

* work

* tab merge layout

* work

* work

* layouts working

* work

* layout tests

* work

* work

* feat(parsing): kdl layouts without config

* refactor(kdl): move stuff around

* work

* tests(layout): add cases and fix bugs

* work

* fix(kdl): various bugs

* chore(layouts): move all layouts to kdl

* feat(kdl): shared keybidns

* fix(layout): do not count fixed panes toward percentile

* fix(keybinds): missing keybinds and actions

* fix(config): adjust default tips

* refactor(config): move stuff around

* fix(tests): make e2e tests pass

* fix(kdl): add verbose parsing errors

* fix(kdl): focused tab

* fix(layout): corret default_tab_template behavior

* style(code): fix compile warnings

* feat(cli): send actions through the cli

* fix(cli): exit only when action is done

* fix(cli): open embedded pane from floating pane

* fix(cli): send actions to other sessions

* feat(cli): command alias

* feat(converter): convert old config

* feat(converter): convert old layout and theme files

* feat(kdl): pretty errors

* feat(client): convert old YAML files on startup

* fix: various bugs and styling issues

* fix: e2e tests

* fix(screen): propagate errors after merge

* style(clippy): lower clippy level

* fix(tests): own session_name variable

* style(fmt): rustfmt

* fix(cli): various action fixes

* style(fmt): rustfmt

* fix(themes): loading of theme files

* style(fmt): rustfmt

* fix(tests): theme fixtures

* fix(layouts): better errors on unknown nodes

* fix(kdl): clarify valid node terminator error

* fix(e2e): adjust close tab test

* fix(e2e): adjust close tab test again

* style(code): cleanup some comments</content>
</entry>
<entry>
<title>fix(terminal): SGR/UTF8 mouse reporting in terminal panes (#1664)</title>
<updated>2022-08-17T07:28:51Z</updated>
<author>
<name>Aram Drevekenin</name>
<email>aram@poor.dev</email>
</author>
<published>2022-08-17T07:28:51Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/sl0ppij.git/commit/?id=f4ad946497264dbe8339f50b2e9ef0cf90a2024c'/>
<id>urn:sha1:f4ad946497264dbe8339f50b2e9ef0cf90a2024c</id>
<content type='text'>
* work

* work

* fix: selection mishandling

* style(fmt): rustfmt

* style(comments): remove outdated

* style(clippy): make clippy happy

* fix(mouse): off by one sgr/utf8 reporting

* style(fmt): rustfmt

* fix(mouse): correctly report drag event code

* fix(input): support mouse middle click

* style(fmt): rustfmt</content>
</entry>
<entry>
<title>fix(pty): paste freeze with large amounts of text (#1383)</title>
<updated>2022-05-16T19:14:57Z</updated>
<author>
<name>Thomas Linford</name>
<email>tlinford@users.noreply.github.com</email>
</author>
<published>2022-05-16T19:14:57Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/sl0ppij.git/commit/?id=e8f955906293fcfe84d73a8af4a3c7f458708d06'/>
<id>urn:sha1:e8f955906293fcfe84d73a8af4a3c7f458708d06</id>
<content type='text'>
add pty writer thread to avoid screen thread blocking on unistd::write</content>
</entry>
</feed>
