The previous commit added the option to convert the storage to
the cluster format. That saves memory as rows are moved to scrollback,
but makes scrolling back more expensive due to that conversion.
This commit adds a fast(ish) path for the common case of simply
appending text to a new line before it gets scrolled: the default
format for lines in the screen is now the cluster format and,
provided that the cursor moves from left to right as text is
emitted, can simply append to the cluster storage in-place
and avoids a conversion when the line is moved to scrollback.
This improves the throughput of `time cat enwiki8.wiki` so
that the runtime is typically around 11-12s (compared to 9-10s
before introducing cluster storage). However, this is often
a deal of variance in the measured time and I believe that
that is due to the renderer triggering conversions back to
the vec storage and introducing slowdowns from the render side.
That's what I'll investigate next.
The fixup callback can now by async, which makes it possible to use
other async functions in the callback.
There is an additional parameter to wezterm.exec_domain that allows
setting the label that is shown in the launcher menu.
It accepts either a string value or an async callback function
that can be used to compute the label dynamically.
This commit allows for the SplitPane internal action to use the
pane id of an existing pane as the source of the pane to be added
in the new split target, rather than spawning a new command.
This can be used to move a pane from one tab to another, and is
analagous to tmux's `join-pane` command.
refs: https://github.com/wez/wezterm/discussions/2043
refs: https://github.com/wez/wezterm/issues/1253
This, along with the plumbing included here, allows specifying
the destination of the split (now you can specify top/left, whereas
previously it was limited to right/bottom), as well as the size
of the split, and also whether the split targets the node at the
top level of the tab rather than the active pane--that is referred
to as full-width in tmux terminology.
https://github.com/wez/wezterm/issues/578
The logic that figures out whether/how to map remote windows
to the potential local window needs to account for the workspaces
on any given local/remote pair.
In particular, if we are called with a primary window id that
has say "default" as its workspace, we mustn't decide to place
remote tabs from a window whose workspace is not "default"
into that local window, or else we can end up in a weird
state where we have 3 workspaces on the remote, but have
accidentally folded one of them into the `default` workspace
and thus end up thinking that we have one workspace with two
windows and one other workspace, instead of the intended
3 windows each with a distinct workspace.
refs: https://github.com/wez/wezterm/issues/1978
We need to notice when all of the streams associated with a channel are
closed and remove the channel from the set that we're polling in the
main loop, to avoid continually polling the closed descriptors.
Additionally, if the Session has been dropped, we know that we cannot
be asked to create any new channels, so if there are no more channels
then we can and should exit that dispatch loop and allow the resources
to be cleaned up.
refs: https://github.com/wez/wezterm/issues/1993#issuecomment-1130539934
The launcher menu code to perform attaching has been generalized
into a key assignment action and reimplemented in terms of that
action.
A detach action has been added to disconnect and detach.
refs: https://github.com/wez/wezterm/issues/1874
This commit allows the currently active window to:
* Spawn a new tab in the active window (rather than spawning
a new window) to host the connection status
* Auto-close that connection UI tab (rather than the whole window)
when the window is no longer needed
* Pass the current window through to use as the primary window when
assigning remote window/tabs.
The net effect of this is that there are fewer transient windows,
and that it is easier to connect a set of domains to the active
workspace.
refs: https://github.com/wez/wezterm/issues/1874
Use some heuristics to verify the data that is about to be parsed;
this can help to detect eg: data being output to stdout prior
to us sending any encoded data to the remote mux.
In addition, add a timeout to help avoid waiting forever in
the case that we didn't detect a problem.
refs: https://github.com/wez/wezterm/issues/1860
The heart of the issue here was due to the window-reuse logic that
tries to reuse a GUI window that is no longer associated with a mux
window.
Each GUI window subscribes to the mux for mux events, but it filters
according to is understanding of the mux_window_id that it is associated
with.
The GUI frontend maintains an mapping of GUI and mux window so that it
knows when to reuse a GUI window and when to close it.
When connecting to a remote mux, wezterm spawns a temporary connection
progress window. Once connected, workspace reconiliation is triggered
and decides that this window can be used for something else.
As part of workspace reconciliation, this mapping can be adjusted and
the frontend will notify a GUI window that its mux window has changed.
However, that updated mux window was not visible to the mux notification
subscription so the effect was that a variety of notifications were
effectively ignored, including updates from a remote mux when the output
was changed.
To make matters worse, the workspace reconciliation could "double-tap"
window creation and create excess windows only to later realize they
weren't needed and close them out again.
This commit addresses both of these concerns.
refs: #1841
refs: #1814
After killing the remote pane, we no longer trigger the renderable
poll stuff that would detect that the pane was dead.
Let's speculatively set it to dead so that we don't get stuck with
stray tabs/panes.
https://github.com/wez/wezterm/issues/1752
There were a a couple of issues:
* `ImageData::hash` would re-hash the image on every call, and this was
called for every cell that comprised an image on the mux server side
* `SerializedLine` needed to understand how to remove the `Arc<ImageData>`
image attachments so that we didn't serialize a complete copy of the
image per cell that comprised the image.
A new RPC was introduced to attempt to fetch `ImageData` given its
content hash and pane, row and cell index as a hint to locate it.
A client side LRU of content hash to `ImageData` is used to avoid
issuing repeat calls to that new RPC.
refs: #1237
Pretty much the same test plan as b4c4c85683
but start wezterm:
./target/debug/wezterm -n --config 'ssh_domains={{name="s",remote_address="localhost"}}' connect s
This reliably propagates focus=true events, but if the client switches
focus away from a mux pane to a local pane, then the focus=false event
may not be propagated to the remote mux.
refs: #1608
wezterm cli spawn, and wezterm cli split-pane can use this information
to pick a default for the pane id when invoked from outside of wezterm.
refs: https://github.com/wez/wezterm/issues/1531
This was used by the mux client when the session is tardy.
I've heard feedback that the greying out is distracting and not
especially useful, so I don't think this is any great loss.
This commit does two related things, from opposite ends of the spectrum:
* Sets the sticky bit on pid files and unix sockets to avoid tmpwatch
deleting them in cleanup scenarios
* Falls back to looking at the changed time if the filesystem doesn't
support reporting creation time when wezterm does its own liveness
and cleanup checks for unix domain sockets in the runtime dir
* Allow any wezterm instance to perform that cleanup
refs: #1601
Introduce a new config knob called 'local_echo_threshold_ms' to let
users configure when the local echo prediction should kick in. The
default value is 100ms to retain the current behavior.
This action causes the active workspace for the gui to change.
If the name is omitted a random name will be generated.
If the workspace doesn't exist, it will be be created.
The optional spawn parameter can be used to launch a specific
program into the new workspace; if omitted, the default prog
will be used.
The gui only supports a single active workspace. Switching workspaces
will repurpose existing gui windows and re-assign them to windows
in the new workspace, adjusting their size to fit those windows,
spawning new windows or closing unused windows as required.
The gui now exits when there are no panes in the active workspace,
rather than no panes at all.
refs: #1531
Tidies up some code duplication within the mux protocol handler.
Move some of the logic into Mux, remove legacy Spawn Pdu to reduce
more duplication.
I want to dedup some of the similar logic that exists in the gui
spawn implementation as well in a follow up.
This is not exposed through any UX; the mux api allows setting
the workspace and propagating information about windows whose
workspace has changed.
Windows start with a blank workspace name.
This is just plumbing; nothing uses it yet.
refs: #1531
Define a way to compute a client ID and pass that through to the
mux server when verifying version compatibility.
Once associated, the session handler will keep some metadata
updated in the mux.
A new cli subcommand exposes the info:
```
; ./target/debug/wezterm cli list-clients
USER HOST PID CONNECTED IDLE WORKSPACE
wez mba.localdomain 52979 30.009225s 1.009225s
```
refs: #1531
This is a similar race condition to one we had before with the
multiplexer, where the connection UI made us think that we didn't
need to start a new process.
Additionally, the attach method would unconditionally create a
new client without checking whether we already had one.
In the case that the published symlink is stale, our default
client connection logic was to retry connecting with backoff
to give a newly spawned server a chance to startup.
In the context of a newly launched gui process checking to see
if an existing gui process can serve the same request, we don't
need to give it any grace: it will either answer immediately
or be deemed not useful.
This commit limits us to a single connection attempt in the case
where we're not automatically starting the server, which in turn
constrains the overhead to something in the order of microseconds
rather than nearly 0.5 seconds.
While we're in here, I noticed that if we thought we had a socket
to try and that failed, we'd always try to publish a new symlink.
However, if we failed due to mismatched version info, we shouldn't
publish over the top of the already running instance.
refs: #1529
user vars were stubbed out. This commit adds storage for them
in the mux client and adds a new notification that publishes each
var as it is changed. That differential stream is applied to the
storage in the mux client when it is received.
```lua
local wezterm = require 'wezterm'
wezterm.on("update-right-status", function(window, pane)
local woot = pane:get_user_vars().woot
window:set_right_status(tostring(woot))
end);
return {
unix_domains = {
{name="unix"},
},
}
```
then running:
* `wezterm connect unix`
* in that session: `printf "\033]1337;SetUserVar=%s=%s\007" woot `echo -n nice | base64``
causes `nice` to show in the status area.
refs: #1528
If an ssh domain is set to use_multiplexer=false, it is now
possible to `wezterm connect` to it.
Previously, it was only possible to connect to domains that
used the mux client.
refs: https://github.com/wez/wezterm/issues/1456
The client machinery would try to spawn an async attempt at
detaching the unixdomain from the mux on shutdown, but since
we're in the middle of tearing down the scoped executor,
we could sometimes panic.
The client we have in this situation isn't actually associated
with a domain, so we don't need to detach in that situation.
Formalize that by making it an Option, and address the
fanout.
When spawned with no WEZTERM_UNIX_SOCKET environment set,
we now prefer to resolve the gui instance, falling back to
the mux if it doesn't look like the gui is running.
`wezterm cli --prefer-mux` will use the original behavior of
trying to resolve the path from the unix domain in the config.
Nothing generates them right now, and the mux client has no
way to represent them on the wire.
I'm considering constraining them to just win32 for now.
refs: https://github.com/wez/wezterm/issues/1509
Previously, we would implicitly set it to the special SEQ_ZERO
value, but since that value always flags the row as changed,
it causes some over-invalidation issues downstream in wezterm.
This commit makes that parameter required, so that the code that
is creating a new Line always passes down the seqno from that event.
refs: #1472
Finally getting around to fixing this usability wart: this commit
changes the behavior of Window closing so that you can close a window
containing multiplexer panes without prompting and without killing
off those panes.
This is achieved through some plumbing:
* The mux can now advise Domains about an impending window closure,
giving them the opportunity to "do things" in readiness.
* The mux client domain informs the container ClientPane instances
to ignore the next Pane::kill call, which would otherwise inform
the mux server to kill the remote pane
* Pane:can_close_without_prompting now requires a CloseReason.
* ClientPane's can_close_without_prompting impl allows Window closing
without prompting on the assumption that the ignore-next-kill hack
above is working
refs: #848
refs: #917
refs: #1224
The mux client just returns a dummy reader, and some overlays
have panicking stubs: just allow for them to return None
instead of potentially spawning a useless thread.
In some cases, the `wezterm cli proxy` subcommand had terminated
with error, but the client was still happily waiting for more data
to read.
This commit spawns a thread to detect the process termination and
then drop the child struct when it completes; that in turn causes
the stdio descriptors to close and then things tick over.
refs: #1358
This is a fairly far-reaching commit. The idea is:
* Introduce a unicode_version config that specifies the default level
of unicode conformance for each newly created Terminal (each Pane)
* The unicode_version is passed down to the `grapheme_column_width`
function which interprets the width based on the version
* `Cell` records the width so that later calculations don't need to
know the unicode version
In a subsequent diff, I will introduce an escape sequence that allows
setting/pushing/popping the unicode version so that it can be overridden
via eg: a shell alias prior to launching an application that uses a
different version of unicode from the default.
This approach allows output from multiple applications with differing
understanding of unicode to coexist on the same screen a little more
sanely.
Note that the default `unicode_version` is set to 9, which means that
emoji presentation selectors are now by-default ignored. This was
selected to better match the level of support in widely deployed
applications.
I expect to raise that default version in the future.
Also worth noting: there are a number of callers of
`unicode_column_width` in things like overlays and lua helper functions
that pass `None` for the unicode version: these will assume the latest
known-to-wezterm/termwiz version of unicode to be desired. If those
overlays do things with emoji presentation selectors, then there may be
some alignment artifacts. That can be tackled in a follow up commit.
refs: #1231
refs: #997
The issue here is that when spawning a new tab in the mux client,
we didn't record the local/remote tab id mapping.
Subsequently, when processing the overall list of tabs, we'd realize
that the mapping was missing and allocate a new local tab to act
as the holder for the existing remote tab and end up with a strange
aliased view of the tab in a second tab!
This commit establishes that mapping at the time that we spawn
the new pane.
refs: https://github.com/wez/wezterm/issues/1222
Terminal now maintains a sequence number that increments
for each Action that is applied to it.
Changes to lines are tagged with the current sequence number.
This makes it a bit easier to reason about when an individual
line has changed relative to some point in "time"; the consumer
of the terminal can sample the current sequence number and then
can later determine which lines have changed since that point
in time.
refs: https://github.com/wez/wezterm/issues/867
Possibly related to:
https://github.com/wez/wezterm/issues/783
However, this is more obviously required when scrolling back either
via mouse wheel or a key assignment: the download completes but
we need to then force an invalidation for it to be applied in
the gui.
This looks like a honest typo from when panes were introduced!
We were passing the tab id rather than the pane id when specifying
the target of a split.
likely fix for this issue:
refs: https://github.com/wez/wezterm/issues/781
in the same vein as d657721163
this commit introduces more assertive signalling from the remote
mux when a pane is closed so that the client can update.
This tidies up how we pass the ssh config to the connection ui
logic, by moving the ssh_config setup to the two callers.
A couple of notable adjustments:
* SshDomain::username is now optional; it will default to the
values computed by the ssh config file loader
* no_agent_auth value wasn't hooked up to anything, but now it is
refs: https://github.com/wez/wezterm/issues/730
There are a few notable changes as a result:
* A number of `.ssh/config` options are now respected; host matching
and aliasing and identity file are the main things
* The authentication prompt is inline in the window, rather than
popping up a separate authentication window
Refs: https://github.com/wez/wezterm/issues/457
The wincng based build doesn't recognize newer keys which makes it
impossible to connect to a reasonably up to date Fedora installation.
This commit points to my branch of ssh2-rs that has some changes to
build ssh2 against the vendored openssl that is already part of
the dependency graph for wezterm.
refs: https://github.com/wez/wezterm/issues/507
I've been meaning to do this for a while; this commit moves
the escape sequence parsing into the thread that reads the
pty output which achieves two goals:
* Large escape sequences (eg: image protocols) that span multiple
4k buffers can be processed without ping-ponging between the
reader thread and the main gui thread
* That parsing can happen in the reader thread, keeping the gui
thread more responsive.
These changes free up the CPU during intensive operations such
as timg video playback.
This is a slight layering violation, in that this processing
really belongs to local pane (or any pane that embeds Terminal),
rather than generically at the Mux layer, but it's not any
worse a violation than `advance_bytes` already was.
refs: https://github.com/wez/wezterm/issues/537
This appears to have been broken since the introduction of mouse
assignments :-/
This commit adds Pane::is_alt_screen_active so that the gui layer
can tell whether the alt screen is active, and allow passing down
the event.
refs: #429