mirror of
https://github.com/l0ng-ai/tty7.git
synced 2026-09-22 08:02:24 +00:00
* feat(remote): keep a remote workspace whole across reopens and restarts Reopening a remote workspace — or coming back to one whose `tty7-server` had been replaced — landed on a screen of `tty7 — disconnected` panes with their coding-agent conversations gone. Several independent holes added up to that; this closes them together, and picks up the surrounding work the same session produced. **Telling a restarted server from a blinked link.** `ControlHelloOk` now carries an `instance` minted once per server *process*. Nothing else in the handshake changes across a restart — `build` and both dialect numbers survive it — so a reconnect had no way to know its `pane_id`s were dead. It does now: a different instance rebuilds the window from its layout (same tabs and splits, fresh shells in the saved cwds) instead of re-attaching to a process that is gone. An absent instance means *unknown* and is never read as a restart. **An attach can now fail.** `Attach` has no synchronous reply, so the client returned `Ok` unconditionally and the daemon's `Error` frame was read much later by the reader thread, which has no arm for it — the pane then landed in the *link is down* state instead of falling back to a fresh shell. The client now reads far enough into the reply to classify it on the kind byte (the snapshot behind it can be megabytes) and hands those bytes to the reader thread, so a successful attach loses none of its replay. Local and remote attaches get different waits: the local one is on the UI thread. **The agent session survives to be resumed.** `TerminalView` raises `AgentSessionChanged` when the pane's agent reports a new native session id, so the layout on file catches up instead of waiting for the user to happen to open a tab. A pane that is still connecting now carries its agent through `PendingSpawn` — a save landing in that window used to write `agent: null` over the record — and `land_pane` sends `--resume` when the attach turned out to need a fresh shell. **Ending sessions says so on file.** "End Sessions" kills the panes and then drops their ids from the record, pushing the cleared layout to the machine that owns it (design §10: the remote's copy wins, so a local-only clear would be undone by the next open — the open this exists for). **The new-tab dropdown lists the window's machine.** `Host::shells` and a `Shells` control request (dialect v2) make the "+" menu a property of the machine the window is bound to. A remote window filled from this computer's `/etc/shells` offered `/bin/zsh` on a box whose zsh is elsewhere, and every pick failed to spawn. **An install reports its bytes.** The download and the SFTP upload each report progress, relayed to the client over the routed connection as a `RoutePrompt::InstallProgress`, and painted as a bar under the machine's row in the switcher. ~8 MB across two hops behind the word "connecting…" was indistinguishable from a hang. **The installer compares dialects, not version strings.** `tty7-server --protocol` prints what a binary speaks without starting it, so a connect adopts an already-running server it can talk to rather than prompting about a build difference and uploading 8 MB the machine did not need. **Switcher.** A machine's `⋯` menu holds "New Workspace" (it was a row under every machine, pushing the list a quarter of a card down) and a new "Disconnect", which drops the connection and leaves the windows open and read-only. The suspension lasts exactly as long as that machine has a window on it. Also drops three design/contract docs for the now-shipped remote-workspace work. * fix(session): stop one workspace's panes from being restored into another A restart put a copy of one workspace's seven tabs — cwds, layout and recorded agent sessions — in front of another workspace's own tabs, and auto-resumed every one of those agents a second time: six `claude --resume <id>` pairs running in parallel against the same conversations, one set per window. The record-level corruption that seeded it is still unattributed, but every mechanism that let it propagate, amplify, or go unnoticed is closable, and this closes them. **Panes now know their owner.** `Spawn` can carry the workspace the pane is created for; the daemon stores it immutably and reports it in `List`'s `PaneInfo.owner`. Restore refuses to re-attach a pane another workspace owns (`pane_attachable`) — before this, a saved id landing on somebody else's live pane attached silently, which is how one window could pick up another's shells. The field rides a new `SPAWN_OWNED` frame with a struct payload (the legacy spawn payloads are positional tuples an old daemon cannot grow), gated on a new `pane-owner` feature string: a client only sends it to a daemon that advertises it, so the legacy kinds stay byte-for-byte what old daemons expect. A pane with no recorded owner stays attachable by anyone — that is the pre-field behavior, not a new risk. **Saved pane ids are bound to the daemon process that issued them.** `DaemonVersion` now carries an `instance` minted once per process (the local twin of the control hello's), the GUI caches it at the `ensure_running` handshake, and each local workspace records it as `daemon_instance` beside its layout. Claiming a workspace whose ids came from a different instance blanks them first: daemon pane ids restart from 1, so after a reboot every saved id points at whatever unrelated shell holds the number now, and the aliveness check cannot tell a survivor from a squatter. A blank on either side means "cannot tell" and never trips it. Unlike the duplicate-claim case below, this path keeps the agent resume — the pane is genuinely gone with its daemon, and the fresh shell resuming the conversation is the feature. **A duplicate claim loses its agent resume along with its pane id.** `dedupe_pane_ids` kept the loser's layout *and* its `agent_session_id`, so the blanked leaves took restore's spawn-fresh path and auto-typed `claude --resume` for conversations the winning workspace's panes were still running — the doubling above. The winner keeps the panes and the resume; the loser keeps only cwds. **Cross-workspace saves are caught at the write.** Every terminal view remembers the workspace whose window created it, and `save_session` logs an error naming both ids if a window ever records a pane created for a different workspace — the tripwire for the still-unattributed seed corruption, so a recurrence is caught in the act instead of reconstructed from `session.json` archaeology days later. Wire compatibility both ways: `PaneInfo.owner`, `DaemonVersion.instance` and `Workspace.daemon_instance` are `#[serde(default)]` struct fields (old peers' JSON decodes, new fields are ignored by old readers), and `SPAWN_OWNED` is feature-gated as above. `daemon_instance` is client-owned in the design-§10 storage split — it names the local daemon, and the field-census test pins the classification. * fix(session): resume the agent when a local pane dies mid-restore `session_to_pane` decided whether to send a coding agent's `--resume` from `restore.is_none()` — i.e. from whether the pane looked alive when the restore started. But `alive_panes_on` runs one `List` at the top of the restore, while the attaches happen per leaf afterwards. A pane that exited in between failed its attach, fell back to a fresh shell inside `spawn_shell_terminal_in`, and then landed in the `restore.is_some()` arm: an empty shell with its conversation dropped. `ShellParts.restored` already answers this exactly, and the remote path already reads it in `land_pane`. Carry it onto `TerminalView` so the synchronous local path can read it too, and branch on that instead of re-deriving the answer from a set that may be stale by the time it is used. No behaviour change on the paths that were already correct: a view that was never restoring anything reports `restored: false`, which is the same answer `restore.is_none()` gave them. * fix(remote): check the server instance against the record, not just memory A remote workspace's pane ids were only guarded against server restarts by `RemoteLinks::instances`, an in-memory map. On the first connect after the client starts, every machine is a first sighting, so `server_restarted` answers false — and a `tty7-server` that was replaced while the client was closed sails straight through. Its pane ids restart from 1, so the saved ones now name unrelated shells, and the reconnect attaches to them: the exact id-reuse failure the local side already guards against. `Workspace::daemon_instance` was local-only for the stated reason that a remote server's identity is tracked live per connection. That tracking is correct but not sufficient — it cannot survive the client restart that makes the question worth asking. So the field now means the same thing on both sides: which process minted the pane ids in this record. `WorkspaceStore::serving_instance` picks the local daemon or the far machine's server depending on the workspace, and `finish_attempt` compares it per workspace before deciding to re-attach or rebuild. It stays client-owned: it records what *this* client last saw, so two clients on one remote workspace each keep their own and neither may overwrite the other's. An unreachable machine still records nothing, which is what keeps a good stamp from being erased with `None` — that would disarm the next check. Also in these three files: the §N references to the deleted design docs, cleaned up as part of the sweep in the following commit. * docs: drop the references to the deleted design documents The three documents this branch removed were cited ~280 times: `design §10`, `contract §8`, `§17` and friends in comments, five references by file path in code and manifests, five in CI workflows and one in the release skill. Every one of them now points at nothing. Rewritten rather than merely stripped, because most were not decoration: "design §10 makes the remote's `workspaces.json` the authority" becomes a statement in its own right, and the several that carried a Chinese phrase from the document as their justification say the same thing in English instead. Where the reference was purely parenthetical it is simply gone. Not touched: `PRD §7.1`, `brief §8` and the like, which name documents this branch did not remove and were already external before it, and the `RFC 4648 §10` test-vector citation, which is a real specification. The `host boundary` CI job loses `(§10.6)` from its name. It is not one of the required checks, so branch protection is unaffected. --------- Co-authored-by: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com>
319 lines
16 KiB
TOML
319 lines
16 KiB
TOML
[package]
|
|
name = "tty7"
|
|
version.workspace = true
|
|
edition = "2024"
|
|
description = "A terminal workbench: shells, persistent sessions, SSH, coding agents — GPU-rendered on Zed's gpui, pure Rust"
|
|
repository = "https://github.com/l0ng-ai/tty7"
|
|
license = "Apache-2.0"
|
|
readme = "README.md"
|
|
publish = false
|
|
default-run = "tty7"
|
|
|
|
[[bin]]
|
|
name = "tty7"
|
|
path = "src/main.rs"
|
|
|
|
[dependencies]
|
|
# The framework-free half of tty7: wire protocol, session daemon, PTY, the
|
|
# native SSH engine, and the domain model the headless `tty7-server` shares with
|
|
# this GUI. Everything that does *not* need gpui lives there.
|
|
# `gssapi` is off in tty7-core's defaults (a static musl `tty7-server` cannot
|
|
# link the system krb5 it binds); the GUI, which builds against a real desktop
|
|
# toolchain, turns it on so managed SSH connections keep offering
|
|
# `gssapi-with-mic` exactly as before.
|
|
#
|
|
# `remote-install` is off there for the same shape of reason: it pulls an HTTPS
|
|
# client used only to *download* a `tty7-server` onto a remote machine
|
|
# (decision D5). The server binary is the thing being downloaded, so it can
|
|
# never take that path; the GUI, which is the client that pushes it, can.
|
|
tty7-core = { path = "crates/tty7-core", features = ["gssapi", "remote-install"] }
|
|
|
|
gpui = { workspace = true }
|
|
gpui_platform = { workspace = true }
|
|
gpui-component = { workspace = true }
|
|
gpui-component-assets = { workspace = true }
|
|
|
|
anyhow.workspace = true
|
|
log.workspace = true
|
|
# Smart double-click selection patterns (URL/email/path). Already in the tree
|
|
# transitively, so pinning it here adds no new native code.
|
|
regex = "1"
|
|
# SIMD byte search for `MarkScanner`'s Text-state fast path (`terminal::marks`),
|
|
# which scans every output batch the client receives — the same skip-ahead the
|
|
# tokenizers in `tty7-core` already use. Already in the tree via `tty7-core`,
|
|
# so this pins no new code.
|
|
memchr = "2"
|
|
smol.workspace = true
|
|
smallvec.workspace = true
|
|
serde = { workspace = true }
|
|
serde_json.workspace = true
|
|
|
|
# SSH profile ids in the connection manager UI (`ui::ssh_connect`,
|
|
# `ui::settings`, the command palette). The profiles themselves — and the
|
|
# secret-free `CredentialRef` they carry — live in `tty7-core`, which `Config`
|
|
# needs to parse `config.json` without gpui.
|
|
uuid = { version = "1", features = ["v4", "serde"] }
|
|
|
|
# The credential vault's storage half (`core::keychain`). `keyring` 4.x's default
|
|
# `v1` feature auto-selects the platform store (macOS Keychain / Windows
|
|
# Credential Manager / Linux Secret Service), so no per-platform guards are
|
|
# needed.
|
|
#
|
|
# It sits here rather than in `tty7-core` on purpose: every caller is in `ui::`
|
|
# (`ssh_prompt`, `ssh_connect`, `settings`, `app`), and leaving it downstairs made
|
|
# the headless `tty7-server` — a static binary pushed onto machines that have no
|
|
# keychain at all — link `zbus`/`secret-service` and thirty-odd crates behind them
|
|
# for code it can never reach. Only the secret-free naming half (`CredentialRef`,
|
|
# the account scheme) stays in core, where `config.json` parsing needs it.
|
|
keyring = "4"
|
|
|
|
# Theme files. tty7 themes are authored as YAML (`~/.config/tty7/themes/*.yaml`,
|
|
# our own schema); `plist` parses imported iTerm2 `.itermcolors` schemes (XML
|
|
# plist) so the large iTerm color-scheme ecosystem drops straight in. serde_yaml
|
|
# is already in the tree transitively, so it pins no new code; plist is pure Rust.
|
|
serde_yaml = "0.9"
|
|
plist = "1"
|
|
|
|
# Clipboard-image paste (`terminal::view`). When the clipboard holds a screenshot
|
|
# and a coding-agent TUI (Claude Code &co.) is in the pane, off macOS we stage the
|
|
# image to a temp file and paste its path — agents attach an image path the same way
|
|
# they do a drag-drop. Windows screenshots arrive as BMP (`CF_DIB`), which agent
|
|
# vision won't accept, so we transcode to PNG. `image` is already in the tree via
|
|
# gpui's own clipboard code, so pinning it here adds no new native code.
|
|
image = "0.25"
|
|
|
|
# HTTP client for the startup update check (`core::update`): one GET to the
|
|
# GitHub releases API to see if a newer version has shipped. `reqwest_client`
|
|
# wraps Zed's `zed-reqwest` fork behind gpui's `http_client` trait (re-exported
|
|
# as `gpui::http_client`) and manages its own tokio runtime. That reqwest+rustls
|
|
# stack is *already* compiled into the tree via `gpui-component-assets`, so this
|
|
# pins no new native code — it only exposes what we're already building. Pinned
|
|
# to gpui's rev so the shared `http_client`/`zed-reqwest` versions stay aligned.
|
|
reqwest_client = { git = "https://github.com/zed-industries/zed", rev = "1d217ee39d381ac101b7cf49d3d22451ac1093fe" }
|
|
|
|
# Our fork of Zed's alacritty_terminal fork. Used by the *client*
|
|
# (`terminal::remote`) for the VT parser + grid (`Term`/`ansi::Processor`) that
|
|
# renders the mirror. The daemon's PTY itself is driven by `portable-pty` below.
|
|
#
|
|
# The `tty7` branch is Zed's `fcf32fe` (the rev Zed pins) plus two commits, both
|
|
# still missing from alacritty master as of 852e971:
|
|
#
|
|
# 1. `push_keyboard_mode` capped its stack by removing from `title_stack` instead
|
|
# of `keyboard_mode_stack` — a copy-paste slip from `push_title` that compiles
|
|
# because both are `Vec`s. With `kitty_keyboard` on (see
|
|
# `terminal_config_from_user`) every overflowing push silently drops a saved
|
|
# title, and once the title stack is empty `Vec::remove(0)` panics — 4097
|
|
# unpopped `CSI > 1 u` pushes, about 20KB of output, kill the reader thread and
|
|
# freeze the pane.
|
|
# 2. `input` reserves columns per `char`, so an emoji written as base + U+FE0F
|
|
# (`❤️`, `🗂️`, `⚠️` — any base whose East Asian Width is Neutral) gets one
|
|
# column instead of two and shifts the rest of the line left by one. The fork
|
|
# re-scores the sequence with `UnicodeWidthStr` and widens the cell (issue
|
|
# #203).
|
|
#
|
|
# Each patch has a guard test in `src/terminal/remote.rs`; drop this fork once
|
|
# both land upstream.
|
|
alacritty_terminal = { git = "https://github.com/l0ng-ai/alacritty", rev = "b79e70484b13308ce766a763531ac25a8302c012" }
|
|
|
|
# Desktop notifications driven by OSC 9 / OSC 777 escape sequences. Cross-platform;
|
|
# the macOS backend uses the deprecated NSUserNotification (weak — a completion
|
|
# toast is fine, revisit mac-notification-sys if it proves unusable).
|
|
notify-rust = "4"
|
|
|
|
# Filesystem watcher for live config reload: watches `config.json` and reloads
|
|
# `Config` + re-applies the theme without a restart. The code panel (file tree /
|
|
# editor, `ui::code`) reuses it to refresh the tree and detect external edits.
|
|
notify = "8"
|
|
|
|
# System tray / menu bar status item (`ui::tray`). Rasterizes the bundled SVG
|
|
# logo into the tray bitmap at runtime — gpui's own SVG path only yields a
|
|
# tinted alpha mask, not raw RGBA. The gpui and gpui-component forks both pin
|
|
# the same 0.47, so the whole tree shares a single resvg/usvg/tiny-skia stack;
|
|
# default features off drops the text/font machinery our icon SVGs don't use.
|
|
resvg = { version = "0.47", default-features = false }
|
|
|
|
# The tray icon itself, macOS + Windows: tauri's `tray-icon` (NSStatusItem /
|
|
# Shell_NotifyIcon via objc2 / windows-sys, both already in the tree). Linux is
|
|
# deliberately NOT on this crate — its Linux backend needs GTK + libappindicator,
|
|
# which tty7's AppImage doesn't bundle and the x11/wayland gpui backends don't
|
|
# pull. Linux instead uses `ksni` below.
|
|
[target.'cfg(any(target_os = "macos", target_os = "windows"))'.dependencies]
|
|
tray-icon = "0.24"
|
|
|
|
# The pty-size ioctl in `terminal::generator` is the only libc user left in the
|
|
# GUI (the daemon's own libc calls went to tty7-core), and it is Unix-only — so
|
|
# the dep is Unix-only too.
|
|
[target.'cfg(unix)'.dependencies]
|
|
libc = "0.2"
|
|
|
|
# Embeds `assets/favicon.ico` into the `.exe` so Windows shows the tty7 logo in
|
|
# the taskbar / window / Explorer (macOS gets its icon from the `.app` bundle via
|
|
# bundle.sh instead). Only needed at build time on Windows — see build.rs.
|
|
[target.'cfg(windows)'.build-dependencies]
|
|
winresource = "0.1"
|
|
|
|
# gpui only *reads* the macOS window appearance; it never sets it. We force the
|
|
# app appearance to match the active theme (see `ui::theme::sync_native_appearance`)
|
|
# so the native traffic-light buttons render in the right light/dark style.
|
|
[target.'cfg(target_os = "macos")'.dependencies]
|
|
# CFStringTokenizer FFI for dictionary-based CJK word segmentation on
|
|
# double-click (`terminal::smart_select`). Already in the tree transitively,
|
|
# and it makes jieba unnecessary here — see the non-macos section below.
|
|
core-foundation = "0.10"
|
|
objc2 = "0.6"
|
|
objc2-app-kit = { version = "0.3", features = ["NSApplication", "NSResponder", "NSAppearance", "NSGraphics", "NSImage"] }
|
|
# NSData feeds the runtime Dock icon for bare (non-bundled) binaries — see
|
|
# `set_dock_icon_for_bare_binary` in main.rs.
|
|
objc2-foundation = { version = "0.3", features = ["NSData"] }
|
|
|
|
# Dictionary-based Chinese word segmentation for double-click selection
|
|
# (`terminal::smart_select`), as a *fallback* where the OS has no tokenizer of
|
|
# its own. macOS is excluded on purpose: CFStringTokenizer segments Chinese
|
|
# about as well (and Japanese/Korean far better) at zero cost, while jieba's
|
|
# table costs ~55 MB resident once built and ~2 MB of binary for the embedded
|
|
# dictionary. Keeping the dep off macOS means that dictionary isn't even
|
|
# linked into the build that can't use it.
|
|
[target.'cfg(not(target_os = "macos"))'.dependencies]
|
|
jieba-rs = "0.10"
|
|
|
|
# x11/wayland are the Linux windowing backends; only pull them on Linux. The
|
|
# Windows backend (`gpui_windows`) and macOS backend are selected by gpui_platform
|
|
# itself via `cfg`, so no feature is needed for them.
|
|
[target.'cfg(target_os = "linux")'.dependencies]
|
|
gpui_platform = { workspace = true, features = ["x11", "wayland"] }
|
|
# Linux tray (`ui::tray`): pure-Rust StatusNotifierItem over DBus (zbus — already
|
|
# in the tree). `blocking` + `async-io` gives a synchronous handle without
|
|
# requiring the app to own a tokio runtime; ksni runs its own service thread. On
|
|
# desktops without an SNI host (bare GNOME without the AppIndicator extension)
|
|
# spawning fails and the tray is silently absent — the app is unaffected.
|
|
ksni = { version = "0.3.6", default-features = false, features = ["blocking", "async-io"] }
|
|
|
|
# gpui's `test-support` unlocks `#[gpui::test]` + `TestAppContext`, the headless
|
|
# App/Window harness the view/event tests run on. Dev-only: the feature merges
|
|
# into test builds and never reaches a release binary.
|
|
[dev-dependencies]
|
|
gpui = { workspace = true, features = ["test-support"] }
|
|
|
|
[lints]
|
|
workspace = true
|
|
|
|
# ---- Standalone workspace mirroring gpui-component's pins so the git/source
|
|
# ---- caches are shared and versions stay aligned. ----
|
|
[workspace]
|
|
members = ["crates/*"]
|
|
# The root `tty7` package is a member implicitly; naming all three here is what
|
|
# makes a bare `cargo build` / `cargo test` at the root cover the whole
|
|
# workspace, which is how CI invokes them.
|
|
default-members = [".", "crates/tty7-core", "crates/tty7-server"]
|
|
|
|
[workspace.package]
|
|
edition = "2024"
|
|
# The single version for all three crates — `tty7`, `tty7-core`, `tty7-server`
|
|
# all inherit it with `version.workspace = true`. They ship together and a
|
|
# client talking to a server of a different build has to be able to say so, so
|
|
# they must never drift apart. This is the line a release bump edits (and the
|
|
# one nightly's `awk '/^version = /'` stamps: it is the first such line in the
|
|
# file, since the package entries above are all `version.workspace = true`).
|
|
version = "26.7.6"
|
|
|
|
[workspace.dependencies]
|
|
# Our fork's `tty7` branch carries the local customizations tty7 relies on:
|
|
# `PopupMenu::with_size`, the 1px hairline menu separator, and the custom-button
|
|
# label color the chrome tiles need. The exact commit is still pinned by
|
|
# Cargo.lock. For co-developing the UI crate, point these back at a sibling
|
|
# checkout: `path = "../gpui-component/crates/{ui,assets}"` — but never commit
|
|
# that, since a path dependency can't resolve on CI.
|
|
#
|
|
# `tree-sitter-languages` compiles the grammars the code editor highlights with.
|
|
gpui-component = { git = "https://github.com/l0ng-ai/gpui-component", branch = "tty7", version = "0.5.2", features = [
|
|
"tree-sitter-languages",
|
|
] }
|
|
gpui-component-assets = { git = "https://github.com/l0ng-ai/gpui-component", branch = "tty7", version = "0.5.1" }
|
|
|
|
gpui = { git = "https://github.com/zed-industries/zed", rev = "1d217ee39d381ac101b7cf49d3d22451ac1093fe" }
|
|
# Base features are cross-platform (`font-kit`, `runtime_shaders` only map to the
|
|
# macOS backend; they're no-ops elsewhere). The Linux-only `x11`/`wayland`
|
|
# backends are added by the `cfg(target_os = "linux")` dependency entry in the
|
|
# package manifest, so they never reach the Windows/macOS builds.
|
|
gpui_platform = { git = "https://github.com/zed-industries/zed", rev = "1d217ee39d381ac101b7cf49d3d22451ac1093fe", features = ["font-kit", "runtime_shaders"] }
|
|
|
|
anyhow = "1"
|
|
log = "0.4"
|
|
serde = { version = "1.0.219", features = ["derive"] }
|
|
serde_json = "1"
|
|
smallvec = "1"
|
|
smol = "2"
|
|
|
|
[patch.crates-io]
|
|
# Temporary until upstream russh releases gssapi-with-mic client auth support
|
|
# (https://github.com/Eugeny/russh/pull/737) — remove this patch and take the
|
|
# crates.io release once it lands. Pinned to an exact rev (never a branch):
|
|
# russh is the SSH protocol layer handling user credentials, and a moving
|
|
# branch on a third-party fork could change what `cargo update` builds.
|
|
russh = { git = "https://github.com/ayamir/russh", rev = "0d1d073350ed823069252075cbf3db9672d5b490" }
|
|
|
|
[workspace.lints.clippy]
|
|
dbg_macro = "deny"
|
|
todo = "deny"
|
|
type_complexity = "allow"
|
|
|
|
[profile.dev]
|
|
codegen-units = 16
|
|
debug = "limited"
|
|
split-debuginfo = "unpacked"
|
|
|
|
[profile.dev.package]
|
|
resvg = { opt-level = 3 }
|
|
rustybuzz = { opt-level = 3 }
|
|
taffy = { opt-level = 3 }
|
|
ttf-parser = { opt-level = 3 }
|
|
smol = { opt-level = 3 }
|
|
gpui = { opt-level = 3 }
|
|
gpui_platform = { opt-level = 3 }
|
|
gpui_macros = { opt-level = 3 }
|
|
# The VT parser + grid run on every PTY byte; at opt-level 0 a `cat bigfile`
|
|
# crawls under `cargo dev`.
|
|
alacritty_terminal = { opt-level = 3 }
|
|
|
|
# The render/parse hot path crosses the tty7 ↔ alacritty_terminal ↔ gpui crate
|
|
# boundaries, so cross-crate inlining (thin LTO, like Zed ships) buys real
|
|
# throughput there; single codegen unit for the same reason.
|
|
[profile.release]
|
|
lto = "thin"
|
|
codegen-units = 1
|
|
|
|
# ---- gpui fork ------------------------------------------------------------
|
|
# Our `tty7` branch (cut from the pinned upstream rev, three commits on top) carries:
|
|
#
|
|
# 1. `prefers_ime_for_printable_keys` takes the keystroke, so an input handler can
|
|
# answer per key instead of per view. tty7 needs it for Option-as-Meta — macOS
|
|
# routes ⌥-chords to the IME whenever a CJK input source is active, and without
|
|
# the keystroke there is no way to decline just those chords (see
|
|
# `terminal::input::prefers_ime_for_printable_keys`, issue #177).
|
|
#
|
|
# 2. gpui's Windows backend rasterizes a font-fallback run with the face
|
|
# DirectWrite actually shaped it with, instead of re-deriving one from the
|
|
# face's family/weight/style. The round trip mapped DirectWrite's italic to
|
|
# oblique, so italic CJK — which every pane reaches through the fallback chain,
|
|
# Hack having no CJK — drew a *different* face's outlines at the shaped glyph
|
|
# indices. Every character rendered as an unrelated character, one for one,
|
|
# which reads as mojibake rather than as a font bug.
|
|
#
|
|
# 3. resvg/usvg bumped 0.45 → 0.47 so gpui's SVG stack unifies with the resvg
|
|
# tty7 pins directly above (follow-up to the #227 dependabot bump).
|
|
#
|
|
# Patching by source rather than editing the `gpui`/`gpui_platform` pins above is
|
|
# deliberate: `gpui-component` declares its own `gpui` from the upstream URL, and
|
|
# a plain pin swap would put two incompatible copies of gpui in the tree. `[patch]`
|
|
# rewrites the source for every dependent at once, so the fork's sibling crates
|
|
# (`gpui_macos`, `gpui_web`, …) come along through their in-repo path deps.
|
|
#
|
|
# When bumping the upstream rev: rebase the fork's `tty7` branch onto the new rev,
|
|
# push, then update the `rev` pins above — the branch here follows automatically.
|
|
[patch."https://github.com/zed-industries/zed"]
|
|
gpui = { git = "https://github.com/l0ng-ai/zed", branch = "tty7" }
|
|
gpui_platform = { git = "https://github.com/l0ng-ai/zed", branch = "tty7" }
|
|
gpui_macros = { git = "https://github.com/l0ng-ai/zed", branch = "tty7" }
|
|
gpui_web = { git = "https://github.com/l0ng-ai/zed", branch = "tty7" }
|
|
reqwest_client = { git = "https://github.com/l0ng-ai/zed", branch = "tty7" }
|