From 27beb69ff81e9b60ac1a2a29459f14c5bbd88fb7 Mon Sep 17 00:00:00 2001 From: Kartios Date: Mon, 31 Aug 2026 16:15:32 -0700 Subject: [PATCH] Build interactive native workspace vertical slice --- Cargo.lock | 180 +- Cargo.toml | 1 + README.md | 10 +- crates/lumbridge-pty/Cargo.toml | 18 + crates/lumbridge-pty/src/lib.rs | 716 ++ docs/ARCHITECTURE.md | 19 +- docs/TESTING.md | 13 + docs/UI_OPTIONS.md | 7 + docs/UI_SPIKE_SCORECARD.md | 52 +- docs/UX_VERTICAL_SLICE.md | 107 + scripts/open-metal-lumbridge.sh | 58 + spikes/floem-shell/src/main.rs | 512 +- spikes/gpui-accessibility-probe/Cargo.lock | 7119 +++++++++++++++++ spikes/gpui-accessibility-probe/Cargo.toml | 14 + spikes/gpui-accessibility-probe/README.md | 83 + .../rust-toolchain.toml | 4 + spikes/gpui-accessibility-probe/src/main.rs | 486 ++ spikes/gpui-shell/src/main.rs | 713 +- spikes/ui-shell-model/src/lib.rs | 623 +- 19 files changed, 10535 insertions(+), 200 deletions(-) create mode 100644 crates/lumbridge-pty/Cargo.toml create mode 100644 crates/lumbridge-pty/src/lib.rs create mode 100644 docs/UX_VERTICAL_SLICE.md create mode 100755 scripts/open-metal-lumbridge.sh create mode 100644 spikes/gpui-accessibility-probe/Cargo.lock create mode 100644 spikes/gpui-accessibility-probe/Cargo.toml create mode 100644 spikes/gpui-accessibility-probe/README.md create mode 100644 spikes/gpui-accessibility-probe/rust-toolchain.toml create mode 100644 spikes/gpui-accessibility-probe/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 1952be9..3a45450 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,6 +21,12 @@ dependencies = [ "libc", ] +[[package]] +name = "anyhow" +version = "1.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" + [[package]] name = "arrayvec" version = "0.7.8" @@ -99,6 +105,12 @@ dependencies = [ "serde", ] +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.13.1" @@ -154,7 +166,7 @@ dependencies = [ "serde_json", "sha2 0.11.0", "subtle", - "thiserror", + "thiserror 2.0.20", "url", "uuid", "zeroize", @@ -169,7 +181,7 @@ dependencies = [ "nostr", "serde", "serde_json", - "thiserror", + "thiserror 2.0.20", "uuid", ] @@ -198,6 +210,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + [[package]] name = "chacha20" version = "0.9.1" @@ -357,6 +375,12 @@ dependencies = [ "syn 3.0.4", ] +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + [[package]] name = "fallible-iterator" version = "0.3.0" @@ -369,6 +393,17 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" +[[package]] +name = "filedescriptor" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e40758ed24c9b2eeb76c35fb0aebc66c626084edd827e07e1552279814c6682d" +dependencies = [ + "libc", + "thiserror 1.0.69", + "winapi", +] + [[package]] name = "find-msvc-tools" version = "0.1.11" @@ -661,6 +696,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.189" @@ -703,7 +744,7 @@ version = "0.0.1" dependencies = [ "buzz-sdk", "nostr", - "thiserror", + "thiserror 2.0.20", "uuid", ] @@ -711,6 +752,15 @@ dependencies = [ name = "lumbridge-core" version = "0.0.1" +[[package]] +name = "lumbridge-pty" +version = "0.0.1" +dependencies = [ + "nix", + "portable-pty", + "thiserror 2.0.20", +] + [[package]] name = "lumbridge-storage" version = "0.0.1" @@ -725,6 +775,18 @@ version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" +[[package]] +name = "nix" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" +dependencies = [ + "bitflags 2.13.1", + "cfg-if", + "cfg_aliases", + "libc", +] + [[package]] name = "nostr" version = "0.44.8" @@ -820,6 +882,27 @@ dependencies = [ "universal-hash", ] +[[package]] +name = "portable-pty" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4a596a2b3d2752d94f51fac2d4a96737b8705dddd311a32b9af47211f08671e" +dependencies = [ + "anyhow", + "bitflags 1.3.2", + "downcast-rs", + "filedescriptor", + "lazy_static", + "libc", + "log", + "nix", + "serial2", + "shared_library", + "shell-words", + "winapi", + "winreg", +] + [[package]] name = "potential_utf" version = "0.1.6" @@ -915,7 +998,7 @@ version = "0.40.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23f2a97da3e3873c73cb2a2e71b35c40ff95e0b1eefa8d72d8499a6928c3b5b3" dependencies = [ - "bitflags", + "bitflags 2.13.1", "fallible-iterator", "fallible-streaming-iterator", "libsqlite3-sys", @@ -1012,6 +1095,17 @@ dependencies = [ "zmij", ] +[[package]] +name = "serial2" +version = "0.2.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b16809bc35793b19ce4e0c53924bc0dce3937f15487997cfdaed936004180730" +dependencies = [ + "cfg-if", + "libc", + "windows-sys", +] + [[package]] name = "sha2" version = "0.10.9" @@ -1034,6 +1128,22 @@ dependencies = [ "digest 0.11.3", ] +[[package]] +name = "shared_library" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a9e7e0f2bfae24d8a5b5a66c5b257a83c7412304311512a0c054cd5e619da11" +dependencies = [ + "lazy_static", + "libc", +] + +[[package]] +name = "shell-words" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc6fe69c597f9c37bfeeeeeb33da3530379845f10be461a66d16d03eca2ded77" + [[package]] name = "shlex" version = "2.0.1" @@ -1097,13 +1207,33 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + [[package]] name = "thiserror" version = "2.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" dependencies = [ - "thiserror-impl", + "thiserror-impl 2.0.20", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", ] [[package]] @@ -1277,6 +1407,28 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-core" version = "0.62.2" @@ -1336,6 +1488,24 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] + [[package]] name = "writeable" version = "0.6.4" diff --git a/Cargo.toml b/Cargo.toml index 870bca6..0474323 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ members = [ "apps/lumbridge", "crates/lumbridge-buzz", "crates/lumbridge-core", + "crates/lumbridge-pty", "crates/lumbridge-storage", ] exclude = ["spikes"] diff --git a/README.md b/README.md index b388e74..20df6b7 100644 --- a/README.md +++ b/README.md @@ -16,10 +16,12 @@ as installable binaries; building from source will remain supported. ## Status -This repository is in architecture and product-definition phase. The current -binary is deliberately only a scaffold. We are validating the terminal engine, -UI stack, process/session model, ACP integration, packaging, and usage-data -contracts before committing to a large implementation. +This repository is in architecture and vertical-slice phase. The installable +binary is still a scaffold, while the isolated native UI spikes now exercise an +interactive six-surface workspace and the root workspace contains the first +bounded local PTY boundary. We are still validating terminal emulation, the +session runtime, ACP integration, packaging, and usage-data contracts before a +large implementation. ## Product shape diff --git a/crates/lumbridge-pty/Cargo.toml b/crates/lumbridge-pty/Cargo.toml new file mode 100644 index 0000000..b2b3c7a --- /dev/null +++ b/crates/lumbridge-pty/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "lumbridge-pty" +description = "Portable local PTY process boundary for Lumbridge" +version.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true +repository.workspace = true + +[dependencies] +portable-pty = "0.9.0" +thiserror = "2.0" + +[target.'cfg(unix)'.dependencies] +nix = { version = "0.28", features = ["process", "signal"] } + +[lints] +workspace = true diff --git a/crates/lumbridge-pty/src/lib.rs b/crates/lumbridge-pty/src/lib.rs new file mode 100644 index 0000000..49055fb --- /dev/null +++ b/crates/lumbridge-pty/src/lib.rs @@ -0,0 +1,716 @@ +//! Portable local PTY process ownership for the Lumbridge runtime. +//! +//! This crate moves unparsed bytes between a child process and its PTY. Terminal +//! emulation, scrollback, persistence, remote sessions, and secret injection are +//! intentionally separate concerns. + +#![forbid(unsafe_code)] + +use portable_pty::{Child, CommandBuilder, MasterPty, PtySize, native_pty_system}; +use std::ffi::OsString; +use std::io::{self, Read, Write}; +use std::num::NonZeroUsize; +use std::path::PathBuf; +use std::sync::mpsc::{self, Receiver, RecvTimeoutError, SyncSender}; +use std::thread::{self, JoinHandle}; +use std::time::{Duration, Instant}; +use thiserror::Error; + +const OUTPUT_CHUNK_BYTES: usize = 8 * 1024; +const DEFAULT_OUTPUT_QUEUE_CHUNKS: usize = 64; +const TERMINATION_GRACE: Duration = Duration::from_millis(250); +const TERMINATION_POLL: Duration = Duration::from_millis(10); + +/// A validated terminal cell and pixel size. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct TerminalSize { + rows: u16, + columns: u16, + pixel_width: u16, + pixel_height: u16, +} + +impl TerminalSize { + /// Creates a cell-only size. Rows and columns must both be non-zero. + /// + /// # Errors + /// + /// Returns [`PtyError::InvalidSize`] when either cell dimension is zero. + pub fn new(rows: u16, columns: u16) -> Result { + Self::with_pixels(rows, columns, 0, 0) + } + + /// Creates a size that also reports the viewport's pixel dimensions. + /// + /// # Errors + /// + /// Returns [`PtyError::InvalidSize`] when either cell dimension is zero. + pub fn with_pixels( + rows: u16, + columns: u16, + pixel_width: u16, + pixel_height: u16, + ) -> Result { + if rows == 0 || columns == 0 { + return Err(PtyError::InvalidSize); + } + + Ok(Self { + rows, + columns, + pixel_width, + pixel_height, + }) + } + + #[must_use] + pub const fn rows(self) -> u16 { + self.rows + } + + #[must_use] + pub const fn columns(self) -> u16 { + self.columns + } +} + +impl Default for TerminalSize { + fn default() -> Self { + Self { + rows: 24, + columns: 80, + pixel_width: 0, + pixel_height: 0, + } + } +} + +impl From for PtySize { + fn from(size: TerminalSize) -> Self { + Self { + rows: size.rows, + cols: size.columns, + pixel_width: size.pixel_width, + pixel_height: size.pixel_height, + } + } +} + +/// Credential-free process launch configuration. +/// +/// The configuration deliberately has no arbitrary environment-variable API. +/// A child receives only a small fixed allowlist from the Lumbridge process, +/// plus terminal capability variables. Future secret injection belongs behind +/// the runtime's secret-store boundary and must not be represented here. +pub struct CommandConfig { + program: OsString, + arguments: Vec, + working_directory: Option, +} + +impl CommandConfig { + /// Creates a launch configuration for a non-empty executable name or path. + /// + /// # Errors + /// + /// Returns [`PtyError::EmptyProgram`] for an empty executable name. + pub fn new(program: impl Into) -> Result { + let program = program.into(); + if program.is_empty() { + return Err(PtyError::EmptyProgram); + } + + Ok(Self { + program, + arguments: Vec::new(), + working_directory: None, + }) + } + + #[must_use] + pub fn arg(mut self, argument: impl Into) -> Self { + self.arguments.push(argument.into()); + self + } + + #[must_use] + pub fn args(mut self, arguments: I) -> Self + where + I: IntoIterator, + S: Into, + { + self.arguments.extend(arguments.into_iter().map(Into::into)); + self + } + + #[must_use] + pub fn working_directory(mut self, path: impl Into) -> Self { + self.working_directory = Some(path.into()); + self + } + + fn into_builder(self) -> CommandBuilder { + let mut command = CommandBuilder::new(self.program); + command.args(self.arguments); + command.env_clear(); + + for name in inherited_environment_allowlist() { + if let Some(value) = std::env::var_os(name) { + command.env(name, value); + } + } + + command.env("TERM", "xterm-256color"); + command.env("COLORTERM", "truecolor"); + if let Some(directory) = self.working_directory { + command.cwd(directory); + } + command + } +} + +fn inherited_environment_allowlist() -> &'static [&'static str] { + &[ + "HOME", + "LANG", + "LC_ALL", + "LC_CTYPE", + "LOGNAME", + "PATH", + "SHELL", + "TMPDIR", + "USER", + "XDG_CONFIG_HOME", + "XDG_DATA_HOME", + "XDG_RUNTIME_DIR", + ] +} + +/// Spawn-time settings for a local PTY. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct PtyOptions { + pub size: TerminalSize, + /// Capacity in fixed-size output chunks. The reader blocks when full, + /// propagating backpressure to the kernel PTY rather than growing memory. + pub output_queue_chunks: NonZeroUsize, +} + +impl PtyOptions { + #[must_use] + pub const fn new(size: TerminalSize) -> Self { + let output_queue_chunks = match NonZeroUsize::new(DEFAULT_OUTPUT_QUEUE_CHUNKS) { + Some(capacity) => capacity, + None => NonZeroUsize::MIN, + }; + Self { + size, + output_queue_chunks, + } + } + + #[must_use] + pub const fn with_output_queue_chunks(mut self, capacity: NonZeroUsize) -> Self { + self.output_queue_chunks = capacity; + self + } +} + +impl Default for PtyOptions { + fn default() -> Self { + Self::new(TerminalSize::default()) + } +} + +/// A single item delivered by the bounded PTY output queue. +#[derive(Debug, Eq, PartialEq)] +pub enum OutputEvent { + /// Unparsed bytes read from the PTY. A chunk is never larger than 8 KiB. + Data(Vec), + /// The PTY slave closed normally. + Eof, + /// The reader stopped because the operating-system read failed. + ReadFailed(PtyReadError), +} + +/// A redacted, cloneable description of a PTY reader failure. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct PtyReadError { + pub kind: io::ErrorKind, + pub message: String, +} + +/// A completed child-process status. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct ExitStatus { + pub code: u32, + pub signal: Option, +} + +impl ExitStatus { + #[must_use] + pub const fn success(&self) -> bool { + self.code == 0 && self.signal.is_none() + } +} + +impl From for ExitStatus { + fn from(status: portable_pty::ExitStatus) -> Self { + Self { + code: status.exit_code(), + signal: status.signal().map(ToOwned::to_owned), + } + } +} + +#[derive(Debug, Error)] +pub enum PtyError { + #[error("PTY program cannot be empty")] + EmptyProgram, + #[error("PTY rows and columns must both be non-zero")] + InvalidSize, + #[error("failed to open the local PTY: {0}")] + Open(String), + #[error("failed to clone the local PTY reader: {0}")] + CloneReader(String), + #[error("failed to take the local PTY writer: {0}")] + TakeWriter(String), + #[error("failed to spawn the local PTY child: {0}")] + Spawn(String), + #[error("the PTY session is closed")] + Closed, + #[error("PTY I/O failed")] + Io(#[source] io::Error), + #[error("PTY child did not exit within {0:?}")] + ExitTimeout(Duration), + #[error("PTY output was not available before the timeout")] + OutputTimeout, + #[error("PTY output reader disconnected without an EOF event")] + OutputDisconnected, +} + +/// Owns one local PTY, its child process, and its bounded output queue. +/// +/// A session is intentionally single-owner. The future runtime actor performs +/// input ordering and forwards output events to terminal emulation. +pub struct PtySession { + master: Option>, + writer: Option>, + child: Box, + process_id: Option, + output: Option>, + reader_thread: Option>, + exit_status: Option, +} + +impl PtySession { + /// Opens a native PTY and spawns the configured child inside it. + /// + /// # Errors + /// + /// Returns an error when the PTY, reader, writer, child, or reader thread + /// cannot be created. + pub fn spawn(config: CommandConfig, options: PtyOptions) -> Result { + let pty_system = native_pty_system(); + let pair = pty_system + .openpty(options.size.into()) + .map_err(|error| PtyError::Open(error.to_string()))?; + let reader = pair + .master + .try_clone_reader() + .map_err(|error| PtyError::CloneReader(error.to_string()))?; + let writer = pair + .master + .take_writer() + .map_err(|error| PtyError::TakeWriter(error.to_string()))?; + let (sender, output) = mpsc::sync_channel(options.output_queue_chunks.get()); + let reader_thread = thread::Builder::new() + .name("lumbridge-pty-reader".to_owned()) + .spawn(move || read_output(reader, &sender)) + .map_err(PtyError::Io)?; + let child = pair + .slave + .spawn_command(config.into_builder()) + .map_err(|error| PtyError::Spawn(error.to_string()))?; + let process_id = child.process_id(); + drop(pair.slave); + + Ok(Self { + master: Some(pair.master), + writer: Some(writer), + child, + process_id, + output: Some(output), + reader_thread: Some(reader_thread), + exit_status: None, + }) + } + + #[must_use] + pub const fn process_id(&self) -> Option { + self.process_id + } + + /// Writes ordered raw input bytes to the PTY and flushes the writer. + /// + /// # Errors + /// + /// Returns [`PtyError::Closed`] after input has closed, or [`PtyError::Io`] + /// when the operating-system write fails. + pub fn write_all(&mut self, bytes: &[u8]) -> Result<(), PtyError> { + let writer = self.writer.as_mut().ok_or(PtyError::Closed)?; + writer.write_all(bytes).map_err(PtyError::Io)?; + writer.flush().map_err(PtyError::Io) + } + + /// Applies a validated terminal size to the PTY. + /// + /// # Errors + /// + /// Returns [`PtyError::Closed`] after session cleanup, or [`PtyError::Io`] + /// when the platform resize operation fails. + pub fn resize(&self, size: TerminalSize) -> Result<(), PtyError> { + self.master + .as_ref() + .ok_or(PtyError::Closed)? + .resize(size.into()) + .map_err(|error| PtyError::Io(io::Error::other(error.to_string()))) + } + + /// Receives the next bounded output event before `timeout` elapses. + /// + /// # Errors + /// + /// Returns a closed, timeout, or unexpected-disconnection error when no + /// event can be delivered. + pub fn recv_output_timeout(&self, timeout: Duration) -> Result { + let output = self.output.as_ref().ok_or(PtyError::Closed)?; + match output.recv_timeout(timeout) { + Ok(event) => Ok(event), + Err(RecvTimeoutError::Timeout) => Err(PtyError::OutputTimeout), + Err(RecvTimeoutError::Disconnected) => Err(PtyError::OutputDisconnected), + } + } + + /// Polls the child without blocking and caches a completed status. + /// + /// # Errors + /// + /// Returns [`PtyError::Io`] when the platform child poll fails. + pub fn try_wait(&mut self) -> Result, PtyError> { + if let Some(status) = &self.exit_status { + return Ok(Some(status.clone())); + } + + let status: Option = + self.child.try_wait().map_err(PtyError::Io)?.map(Into::into); + if let Some(status) = &status { + self.exit_status = Some(status.clone()); + } + Ok(status) + } + + /// Blocks until the session leader exits and caches its status. + /// + /// Callers should continue consuming output from another runtime task when + /// a child may produce more than the bounded queue can hold. + /// + /// # Errors + /// + /// Returns [`PtyError::Io`] when the platform wait fails. + pub fn wait(&mut self) -> Result { + if let Some(status) = &self.exit_status { + return Ok(status.clone()); + } + + let status = ExitStatus::from(self.child.wait().map_err(PtyError::Io)?); + self.exit_status = Some(status.clone()); + Ok(status) + } + + /// Polls until the child exits or the supplied timeout expires. + /// + /// # Errors + /// + /// Returns [`PtyError::ExitTimeout`] on expiry or [`PtyError::Io`] when a + /// platform child poll fails. + pub fn wait_timeout(&mut self, timeout: Duration) -> Result { + let deadline = Instant::now() + timeout; + loop { + if let Some(status) = self.try_wait()? { + return Ok(status); + } + if Instant::now() >= deadline { + return Err(PtyError::ExitTimeout(timeout)); + } + thread::sleep(TERMINATION_POLL.min(deadline.saturating_duration_since(Instant::now()))); + } + } + + /// Terminates the PTY's process tree and waits for the session leader. + /// + /// Unix children run in the session/process group created by + /// `portable-pty`; the whole group is signalled so a shell's foreground + /// process cannot be orphaned. Other platforms use the portable child + /// killer. + /// + /// # Errors + /// + /// Returns [`PtyError::Io`] when signalling or waiting for the child fails. + pub fn terminate(&mut self) -> Result { + self.close_input(); + terminate_process_tree(self.process_id, self.child.as_mut())?; + self.wait() + } + + /// Closes the input half without terminating the child. + pub fn close_input(&mut self) { + self.writer.take(); + } + + fn disconnect_output(&mut self) { + self.output.take(); + } + + fn join_finished_reader(&mut self) { + if self + .reader_thread + .as_ref() + .is_some_and(JoinHandle::is_finished) + && let Some(reader_thread) = self.reader_thread.take() + { + let _ = reader_thread.join(); + } + } +} + +impl Drop for PtySession { + fn drop(&mut self) { + // Disconnect first so a reader blocked by queue backpressure can exit. + self.disconnect_output(); + self.close_input(); + if terminate_process_tree(self.process_id, self.child.as_mut()).is_ok() { + let _ = self.child.wait(); + } else { + // Destructors must not hang indefinitely when platform signalling + // itself failed. The child handle is still dropped below. + let _ = self.child.try_wait(); + } + self.master.take(); + self.join_finished_reader(); + } +} + +fn read_output(mut reader: Box, sender: &SyncSender) { + let mut buffer = vec![0_u8; OUTPUT_CHUNK_BYTES]; + loop { + match reader.read(&mut buffer) { + Ok(0) => { + let _ = sender.send(OutputEvent::Eof); + return; + } + Ok(length) => { + if sender + .send(OutputEvent::Data(buffer[..length].to_vec())) + .is_err() + { + return; + } + } + Err(error) if error.kind() == io::ErrorKind::Interrupted => {} + Err(error) => { + let _ = sender.send(OutputEvent::ReadFailed(PtyReadError { + kind: error.kind(), + message: error.to_string(), + })); + return; + } + } + } +} + +#[cfg(unix)] +fn terminate_process_tree( + process_id: Option, + child: &mut (dyn Child + Send + Sync), +) -> Result<(), PtyError> { + use nix::errno::Errno; + use nix::sys::signal::{Signal, killpg}; + use nix::unistd::Pid; + + let Some(process_id) = process_id.and_then(|id| i32::try_from(id).ok()) else { + child.kill().map_err(PtyError::Io)?; + return Ok(()); + }; + let group = Pid::from_raw(process_id); + + if let Err(error) = killpg(group, Signal::SIGHUP) + && error != Errno::ESRCH + { + return Err(PtyError::Io(io::Error::from_raw_os_error(error as i32))); + } + + let deadline = Instant::now() + TERMINATION_GRACE; + while Instant::now() < deadline { + if child.try_wait().map_err(PtyError::Io)?.is_some() { + break; + } + thread::sleep(TERMINATION_POLL); + } + + // Always address the group. The leader may have exited while a foreground + // descendant that ignored SIGHUP remains attached to the terminal. + if let Err(error) = killpg(group, Signal::SIGKILL) + && error != Errno::ESRCH + { + return Err(PtyError::Io(io::Error::from_raw_os_error(error as i32))); + } + Ok(()) +} + +#[cfg(not(unix))] +fn terminate_process_tree( + _process_id: Option, + child: &mut (dyn Child + Send + Sync), +) -> Result<(), PtyError> { + child.kill().map_err(PtyError::Io) +} + +#[cfg(test)] +mod tests { + use super::{ + CommandConfig, ExitStatus, OutputEvent, PtyError, PtyOptions, PtySession, TerminalSize, + }; + use std::num::NonZeroUsize; + use std::time::{Duration, Instant}; + + const TEST_TIMEOUT: Duration = Duration::from_secs(3); + + fn shell(script: &str) -> CommandConfig { + CommandConfig::new("/bin/sh") + .expect("/bin/sh is a valid program") + .args(["-c", script]) + } + + fn collect_until_eof(session: &PtySession) -> Vec { + let deadline = Instant::now() + TEST_TIMEOUT; + let mut output = Vec::new(); + loop { + let remaining = deadline.saturating_duration_since(Instant::now()); + assert!(!remaining.is_zero(), "timed out collecting PTY output"); + match session.recv_output_timeout(remaining) { + Ok(OutputEvent::Data(bytes)) => { + assert!(bytes.len() <= super::OUTPUT_CHUNK_BYTES); + output.extend(bytes); + } + Ok(OutputEvent::Eof) => return output, + Ok(OutputEvent::ReadFailed(error)) => panic!("PTY read failed: {error:?}"), + Err(error) => panic!("PTY output failed: {error}"), + } + } + } + + #[test] + fn captures_raw_output_and_nonzero_exit() { + let mut session = PtySession::spawn( + shell("printf 'lumbridge-ready\\n'; exit 7"), + PtyOptions::default(), + ) + .expect("spawn synthetic shell"); + + let output = collect_until_eof(&session); + let status = session.wait_timeout(TEST_TIMEOUT).expect("shell exits"); + + assert!(String::from_utf8_lossy(&output).contains("lumbridge-ready")); + assert_eq!( + status, + ExitStatus { + code: 7, + signal: None + } + ); + } + + #[test] + fn writes_input_and_reports_resize_to_child() { + let initial = TerminalSize::new(24, 80).expect("valid initial size"); + let resized = TerminalSize::new(41, 101).expect("valid resized size"); + let mut session = PtySession::spawn( + shell("IFS= read -r line; stty size; printf 'got:%s\\n' \"$line\""), + PtyOptions::new(initial), + ) + .expect("spawn synthetic shell"); + + session.resize(resized).expect("resize PTY"); + session + .write_all(b"hello-lumbridge\n") + .expect("write PTY input"); + + let output = String::from_utf8_lossy(&collect_until_eof(&session)).replace('\r', ""); + let status = session.wait_timeout(TEST_TIMEOUT).expect("shell exits"); + assert!(output.contains("41 101"), "unexpected output: {output:?}"); + assert!( + output.contains("got:hello-lumbridge"), + "unexpected output: {output:?}" + ); + assert!(status.success()); + } + + #[test] + fn bounded_queue_preserves_large_output_when_consumed() { + let options = PtyOptions::default() + .with_output_queue_chunks(NonZeroUsize::new(1).expect("non-zero capacity")); + let mut session = PtySession::spawn( + shell("i=0; while [ $i -lt 2048 ]; do printf '0123456789abcdef'; i=$((i+1)); done"), + options, + ) + .expect("spawn synthetic producer"); + + let output = collect_until_eof(&session); + let status = session.wait_timeout(TEST_TIMEOUT).expect("producer exits"); + assert_eq!(output.len(), 32 * 1024); + assert!(status.success()); + } + + #[test] + fn terminate_stops_a_hung_child_with_a_timeout_bound() { + let mut session = + PtySession::spawn(shell("trap '' HUP; exec sleep 30"), PtyOptions::default()) + .expect("spawn synthetic sleeper"); + + let started = Instant::now(); + let status = session.terminate().expect("terminate process tree"); + assert!(!status.success()); + assert!(started.elapsed() < TEST_TIMEOUT); + } + + #[test] + fn rejects_invalid_dimensions_and_empty_program() { + assert!(matches!( + TerminalSize::new(0, 80), + Err(PtyError::InvalidSize) + )); + assert!(matches!( + CommandConfig::new(""), + Err(PtyError::EmptyProgram) + )); + } + + #[test] + fn child_environment_is_minimal_and_excludes_provider_credentials() { + let command = shell("exit 0").into_builder(); + + assert_eq!( + command.get_env("TERM"), + Some(std::ffi::OsStr::new("xterm-256color")) + ); + for forbidden in [ + "ANTHROPIC_API_KEY", + "CEREBRAS_API_KEY", + "GEMINI_API_KEY", + "GROQ_API_KEY", + "OPENAI_API_KEY", + ] { + assert_eq!(command.get_env(forbidden), None, "inherited {forbidden}"); + } + } +} diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 11e6518..36112bd 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -41,13 +41,17 @@ messages should be real from the beginning. - `lumbridge`: installable application entry point. The scaffold currently contains `lumbridge-core`, `lumbridge-storage`, -`lumbridge-buzz`, and the entry point. Larger runtime crates are added after -their architecture spikes pass. +`lumbridge-buzz`, `lumbridge-pty`, and the entry point. Larger runtime crates are +added after their architecture spikes pass. ## Terminal path The runtime owns PTYs, child process groups, resize signals, input ordering, and -raw output. The terminal engine turns output into immutable render snapshots and +raw output. The first `lumbridge-pty` boundary now uses `portable-pty` behind a +single-owner session, a fixed credential-free child environment, validated +sizes, an 8 KiB bounded output queue, resize/input/wait operations, and Unix +process-group cleanup. It deliberately does not emulate a terminal or persist +scrollback. The terminal engine turns output into immutable render snapshots and bounded deltas for the UI. Scrollback is chunked and persisted separately from the live screen to prevent large agent transcripts from blocking input. @@ -59,15 +63,18 @@ and simultaneous automation plus human input. ## UI decision gate -Do not lock the project to a webview or to Zed's private implementation details -before a measured spike. Compare: +Do not lock the project to a webview or to Zed's application implementation +details. The measured spike compares: 1. GPUI for a Zed-like native model and excellent text-heavy interaction. 2. Floem for an independent native Rust model with existing editor primitives. The winner must render six busy panes smoothly, keep input latency low, support IME/accessibility, package on macOS and both Linux targets, and avoid a license -or upstream-stability trap. +or upstream-stability trap. Current Zed GPUI is the provisional winner because +its AccessKit semantics compile while the pinned Floem revision has no semantic +accessibility integration. This remains behind a narrow adapter until platform +assistive-technology, IME, packaging, licensing, and release measurements pass. ## Local-first and remote session path diff --git a/docs/TESTING.md b/docs/TESTING.md index b1af2bb..bbbc70a 100644 --- a/docs/TESTING.md +++ b/docs/TESTING.md @@ -101,6 +101,19 @@ cargo xtest 2025. `scripts/watch.sh` uses Bacon and retains a cargo-watch fallback for people who already have the final cargo-watch release installed. +## Implemented vertical-slice coverage + +- The framework-neutral six-surface model has deterministic tests for focus, + direct selection, needs-input transitions, command-palette lifecycle, + identical GPUI/Floem action replay, bounded output, and workload counters. +- `lumbridge-pty` runs synthetic `/bin/sh` tests for raw output, non-zero exits, + input, resize, one-chunk backpressure, hung-process termination, invalid + dimensions, and exclusion of provider credentials from the child environment. +- The current-GPUI probe compile-checks real AccessKit element wiring and real + platform input-handler installation. Unit tests cover its semantic tree and + UTF-16/UTF-8 composed-text mutations. OS screen readers, IME candidate windows, + and macOS behavior remain platform tests. + ## CI matrix as the project grows Every change runs format, Clippy, unit, contract, integration, and doctests on diff --git a/docs/UI_OPTIONS.md b/docs/UI_OPTIONS.md index d24d479..e22463e 100644 --- a/docs/UI_OPTIONS.md +++ b/docs/UI_OPTIONS.md @@ -10,6 +10,13 @@ This decision stays open until the finalists run the same workload. Choosing on repository popularity or a polished demo would hide the risks that matter for a terminal-heavy, accessibility-aware, cross-platform IDE. +The current vertical-slice result is GPUI-first, not GPUI-final: current Zed +GPUI compile-proves the required AccessKit and IME handler paths, while the +pinned Floem revision fails the semantic-accessibility hard gate. The app-facing +UI boundary must stay narrow until platform AT/IME, packaging, license closure, +and release measurements finish. See `UI_SPIKE_SCORECARD.md` for evidence and +remaining gates. + ## Finalists ### GPUI diff --git a/docs/UI_SPIKE_SCORECARD.md b/docs/UI_SPIKE_SCORECARD.md index 4e8a418..4e1cb4c 100644 --- a/docs/UI_SPIKE_SCORECARD.md +++ b/docs/UI_SPIKE_SCORECARD.md @@ -10,8 +10,8 @@ from macOS and Linux and the hard gates pass. | Builds on Ubuntu | yes | conditional | pass | | Builds on Omarchy/Arch | yes | pending | pending | | Dependency/license closure permits Apache-2.0 distribution | yes | pending | pending | -| Keyboard navigation + AccessKit tree | yes | pending | pending | -| IME and composed Unicode input | yes | pending | pending | +| Keyboard navigation + AccessKit tree | yes | keyboard pass; current-GPUI semantics compile; platform AT pending | fail: no AccessKit integration at pinned revision | +| IME and composed Unicode input | yes | framework API exists; end-to-end pending | editor API exists; end-to-end pending | | Isolated system browser child | yes | pending | pending | | Cold startup, p50/p95 | record | pending | pending | | Idle RSS / six-stream RSS | record | pending | pending | @@ -43,4 +43,50 @@ performance numbers. GPUI's Ubuntu row remains conditional because the host has the runtime `libxkbcommon-x11.so.0` but lacks the unversioned development linker name normally supplied by `libxkbcommon-x11-dev`. Floem current main also requires its `editor` feature for the style/label modules used by this shell; -that feature is now explicit in the spike. Neither finding decides the UI stack. +that feature is now explicit in the spike. Neither build result by itself +decides the UI stack. + +## Accessibility gate and provisional direction + +The published `gpui 0.2.2` used by the visual shell has focus and keyboard +actions but does not expose the current AccessKit element API. An isolated probe +therefore pins GPUI directly to Zed commit +`ce48461eaadd16c65c31f835511ab96bd3b6e746` with its matching Rust 1.97.1 +toolchain. The real element wiring compiles with stable accessibility IDs, +workspace/pane/terminal roles, selected state, focus tracking, and a needs-input +description. The same probe installs real `EntityInputHandler` and +`ElementInputHandler` implementations and tests marked-text commit, a composed +accent, and a multi-codepoint emoji without splitting UTF-8. Three deterministic +tests pass. AT-SPI/OS IME on Linux and VoiceOver/IME on macOS remain end-to-end +gates. + +The pinned Floem revision has keyboard focus and editor IME plumbing but no +AccessKit dependency or semantic tree. That fails Lumbridge's accessibility +gate without a maintained framework fork or adapter. The provisional direction +is therefore **GPUI-first using current Zed GPUI behind a narrow Lumbridge UI +adapter**. The published GPUI shell remains the lightweight interaction and +visual benchmark until the dependency/toolchain migration is accepted. + +This is not the final cross-platform release decision. Current-GPUI validation +on amd-server required a 624 MiB Rust 1.97.1 toolchain, a 691-package lockfile, +and 4.4 GiB of debug artifacts across check, test, Clippy, and build. Packaging, +license closure, IME, platform assistive technology, browser parenting, macOS, +and Omarchy still have to pass. + +The comparable Floem shell passes build, test, strict Clippy, live rendering, +streaming, mouse selection, and numeric pane selection on metal. Its command +palette opens through the visible clickable affordance and uses Floem's native +`TextInput`, but Ctrl/Cmd+K did not reach the handler in the X11 automation +probe. That unresolved focus/event-routing behavior is another current strike +against adopting Floem; it is recorded rather than hidden behind the clickable +fallback. + +## Measurement semantics + +Both renderers consume the same deterministic six-surface action stream. Each +tick invalidates six surfaces, appends one bounded line to each of the three +terminal fixtures, and records stable event/revision counters. The GPUI footer +currently reports dispatch-to-element-build p50/p95 over a bounded 256-sample +window. It is deliberately not called key-to-present or frame-present latency: +neither candidate exposes a reliable public cross-platform post-present +callback. True present latency requires an external platform probe. diff --git a/docs/UX_VERTICAL_SLICE.md b/docs/UX_VERTICAL_SLICE.md new file mode 100644 index 0000000..6143ab9 --- /dev/null +++ b/docs/UX_VERTICAL_SLICE.md @@ -0,0 +1,107 @@ +# Decisive native workspace vertical slice + +## Outcome + +The slice must let an engineer notice one waiting agent, move focus to it from +the keyboard, inspect the request, and choose a safe next action without losing +the state of five other busy surfaces. It is a product interaction test and a +framework decision gate, not a decorative dashboard. + +## Current-run audit + +The 2026-08-31 GPUI baseline succeeds at calm density: the six surfaces are easy +to scan, typography is consistent, and local/remote targets remain visible. It +fails the task flow in four important ways: + +1. all panes have equal visual priority, so `NEEDS INPUT` is too easy to miss; +2. no pane exposes visible keyboard focus or selection; +3. the command palette affordance has no interaction behind it; +4. status and usage text in the footer is too quiet to explain provenance or + confidence at a glance. + +Screenshots for the audit are stored outside Git under +`~/shots/2026-08/lumbridge-ui-audit/`. Accessibility and IME correctness cannot +be established from screenshots and remain explicit runtime gates. + +## Preserved design language + +- Near-black blue surfaces with one cool-blue action accent. +- Thin borders and compact spacing; no elevated card shadows. +- Text carries most hierarchy. Color is supplementary and never the only state + signal. +- Monospace content inside terminal surfaces; system UI typography elsewhere. +- Dense information, but only the focused or waiting surface becomes prominent. + +## Orca reference, translated for Lumbridge + +The visual reference is the MIT-licensed Orca repository at researched commit +`02a7742406a5a84fb372d6255d5a4367421990bd`. Its screenshots are product +research, not source assets for Lumbridge. We adapt these interaction patterns: + +- a worktree/task-first sidebar whose rows show state without becoming large + cards; +- a quiet top tab strip for mixed terminal, Markdown, browser, and review + surfaces; +- one primary work surface with optional splits, instead of forcing every + surface into an equal dashboard tile; +- narrow contextual tools, such as files, review, or Buzz, that can collapse + when the terminal needs the space; +- usage and agent state at the edge of the workspace rather than in modal + account pages. + +Lumbridge deliberately differs where its product model differs: remote runtime +ownership is always visible, `needs input` receives a dedicated attention path, +usage includes provenance and uncertainty, and Buzz is a signed collaboration +surface rather than a hosted Lumbridge control plane. + +## Visual hierarchy + +1. The top bar names the current workspace, repository/branch, and command + palette shortcut. +2. The sidebar starts with a compact `ATTENTION` group, followed by workspaces + and remote hosts. It does not become a notification feed. +3. The active pane receives a two-pixel accent edge plus a quiet tinted header. +4. A waiting pane uses an amber semantic label and remains visible when another + pane is selected. The label always includes words such as `NEEDS INPUT`. +5. Pane headers expose title, execution target, harness state, and unread count + in a stable order. +6. The footer groups connection state, selected-harness identity, usage-window + provenance, and burn forecast into readable regions. + +## Keyboard task flow + +- Arrow keys or `h/j/k/l`: move focus through the 2×3 pane grid. +- `1` through `6`: focus a pane directly. +- `Cmd+K` on macOS or `Ctrl+K` on Linux: open the command palette. +- Typing while the palette is open changes its query; arrows change the result; + `Enter` runs it; `Escape` closes it and restores pane focus. +- `Enter` on a waiting agent opens its request detail. Approval remains a + separate explicit action and is never triggered by focusing the pane. +- `Escape` closes transient UI before it changes workspace state. + +Every command is represented by the shared interaction model so GPUI and Floem +receive the same state transitions and tests. + +## Decisive workload + +- One deterministic tick invalidates all six surfaces and appends bounded output + to the three terminal panes. Framework adapters consume the same event trace. +- One pane enters and leaves `needs input` through a deterministic event. +- Markdown, browser-boundary, and review panes update counters without using a + web application shell. +- The model records actions, revisions, six-surface updates, and bounded terminal + line counts. Framework adapters label each measured timing stage explicitly; + element-build timing is never presented as display-present timing. +- A later PTY adapter replaces one synthetic stream without changing the UI + contract. Synthetic streams stay available for repeatable performance tests. + +## Hard gates + +- Every focus movement and palette command is unit tested without a window. +- Focus and `needs input` remain distinguishable in monochrome screenshots. +- The current-GPUI input probe preserves composed Unicode and multi-codepoint + graphemes. Real candidate-window placement still requires Linux/macOS testing. +- The accessibility tree names each pane, selected state, execution target, and + waiting state. +- Six streams remain responsive while the palette is open. +- Closing the UI never implies that a runtime-owned session has stopped. diff --git a/scripts/open-metal-lumbridge.sh b/scripts/open-metal-lumbridge.sh new file mode 100755 index 0000000..a311682 --- /dev/null +++ b/scripts/open-metal-lumbridge.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash +set -euo pipefail + +repo_path=${LUMBRIDGE_REPO:-/home/metal/Desktop/Lumbridge Code/lumbridge} +window_title='Lumbridge · GPUI workspace' +bacon_title='Lumbridge · Bacon' +manifest_path="$repo_path/spikes/gpui-shell/Cargo.toml" +binary_path="$repo_path/spikes/gpui-shell/target/debug/lumbridge-spike-gpui" + +if [[ ! -d "$repo_path/.git" ]]; then + echo "Lumbridge repository not found at $repo_path" >&2 + exit 1 +fi + +export DISPLAY=${DISPLAY:-:0} +export XAUTHORITY=${XAUTHORITY:-/run/user/1000/gdm/Xauthority} +export XDG_RUNTIME_DIR=${XDG_RUNTIME_DIR:-/run/user/1000} +export DBUS_SESSION_BUS_ADDRESS=${DBUS_SESSION_BUS_ADDRESS:-unix:path=/run/user/1000/bus} + +for command_name in cargo wmctrl; do + if ! command -v "$command_name" >/dev/null 2>&1; then + echo "required command not found: $command_name" >&2 + exit 1 + fi +done + +if [[ ! -x "$binary_path" ]]; then + cargo build --locked --manifest-path "$manifest_path" +fi + +existing_id=$(wmctrl -l | awk -v title="$window_title" 'index($0, title) { print $1; exit }') +if [[ -z "$existing_id" ]]; then + "$binary_path" >"$XDG_RUNTIME_DIR/lumbridge-gpui.log" 2>&1 & + for _attempt in $(seq 1 80); do + existing_id=$(wmctrl -l | awk -v title="$window_title" 'index($0, title) { print $1; exit }') + [[ -n "$existing_id" ]] && break + sleep 0.1 + done +fi + +if [[ -z "$existing_id" ]]; then + echo "Lumbridge window did not become visible; see $XDG_RUNTIME_DIR/lumbridge-gpui.log" >&2 + exit 1 +fi + +# Gigabyte G34WQC is 3440x1440 at X=0. Lumbridge owns its left half; Bacon +# remains visible beside it on the right half of the same monitor. +bacon_id=$(wmctrl -l | awk -v title="$bacon_title" 'index($0, title) { print $1; exit }') +if [[ -n "$bacon_id" ]]; then + wmctrl -i -r "$bacon_id" -b remove,maximized_vert,maximized_horz + wmctrl -i -r "$bacon_id" -e 0,1720,0,1720,1400 +fi + +wmctrl -i -r "$existing_id" -b remove,maximized_vert,maximized_horz +wmctrl -i -r "$existing_id" -e 0,0,0,1720,1400 +wmctrl -i -a "$existing_id" + +echo "Lumbridge is visible in window $existing_id on the left half of the Gigabyte display." diff --git a/spikes/floem-shell/src/main.rs b/spikes/floem-shell/src/main.rs index 57da62d..7274b25 100644 --- a/spikes/floem-shell/src/main.rs +++ b/spikes/floem-shell/src/main.rs @@ -1,151 +1,481 @@ -use floem::{Application, kurbo::Size, peniko::Color, prelude::*, window::WindowConfig}; +use std::time::Duration; + +use floem::{ + Application, + action::exec_after, + event::EventPropagation, + kurbo::Size, + peniko::Color, + prelude::*, + reactive::{Effect, RwSignal, SignalGet, SignalTrack, SignalUpdate, SignalWith}, + style::Position, + window::WindowConfig, +}; use lumbridge_spike_model::{ - FOOTER_CENTER, FOOTER_LEFT, FOOTER_RIGHT, PANES, PaneFixture, WORKSPACES, + FOOTER_CENTER, FOOTER_RIGHT, FocusDirection, PaneId, PaneState, ShellAction, ShellModel, + SurfaceKind, WORKSPACES, }; -const BG: Color = Color::from_rgb8(12, 14, 19); -const PANEL: Color = Color::from_rgb8(18, 23, 34); -const PANEL_ALT: Color = Color::from_rgb8(23, 29, 41); -const BORDER: Color = Color::from_rgb8(41, 50, 68); -const TEXT: Color = Color::from_rgb8(217, 226, 242); -const MUTED: Color = Color::from_rgb8(127, 139, 163); -const ACCENT: Color = Color::from_rgb8(119, 189, 251); +const BG: Color = Color::from_rgb8(9, 12, 18); +const PANEL: Color = Color::from_rgb8(16, 22, 32); +const PANEL_ALT: Color = Color::from_rgb8(21, 29, 41); +const PANEL_ACTIVE: Color = Color::from_rgb8(24, 35, 52); +const BORDER: Color = Color::from_rgb8(38, 50, 70); +const BORDER_QUIET: Color = Color::from_rgb8(28, 38, 54); +const TEXT: Color = Color::from_rgb8(219, 229, 244); +const MUTED: Color = Color::from_rgb8(130, 144, 168); +const ACCENT: Color = Color::from_rgb8(104, 181, 248); +const ATTENTION: Color = Color::from_rgb8(241, 185, 106); +const SUCCESS: Color = Color::from_rgb8(112, 214, 168); +const OS_MOD: Modifiers = if cfg!(target_os = "macos") { + Modifiers::META +} else { + Modifiers::CONTROL +}; -fn pane_card(pane: PaneFixture) -> impl IntoView { - let header = Stack::horizontal(( - Label::new(pane.title).style(|s| s.flex_grow(1.0).color(TEXT)), - Label::new(pane.badge).style(|s| s.font_size(11.0).color(ACCENT)), - )) - .style(|s| { - s.items_center() - .height(34.0) - .padding_horiz(10.0) - .background(PANEL_ALT) - .border_bottom(1.0) - .border_color(BORDER) +fn dispatch(model: RwSignal, action: ShellAction) { + model.update(|model| { + model.dispatch(action); }); +} - let lines = - Stack::vertical(pane.lines.map(|line| { - Label::new(line).style(|s| s.font_size(12.0).color(TEXT).margin_bottom(5.0)) - })); - - Stack::vertical(( - header, - Label::new(pane.target).style(|s| s.font_size(11.0).color(MUTED).padding(10.0)), - lines.style(|s| s.padding_horiz(10.0).padding_bottom(10.0)), - )) +fn pane_card(id: PaneId, model: RwSignal) -> impl IntoView { + dyn_container( + move || model.with(|model| (model.pane(id).clone(), model.selected_pane() == id)), + move |(pane, selected)| render_pane_card(pane, selected, model), + ) .style(|s| { s.flex_basis(0) .flex_grow(1.0) .min_width(0.0) .min_height(0.0) .margin(4.0) - .background(PANEL) - .border(1.0) - .border_color(BORDER) - .border_radius(6.0) }) } -fn app_view() -> impl IntoView { - let sidebar_items = Stack::vertical(WORKSPACES.map(|name| { - Label::new(name).style(move |s| { - s.width_full() - .padding_vert(8.0) - .padding_horiz(12.0) - .margin_bottom(3.0) - .color(if name == "Lumbridge Code" { - TEXT - } else { - MUTED - }) - .apply_if(name == "Lumbridge Code", |s| { - s.background(PANEL_ALT).border_radius(6.0) - }) +fn render_pane_card(pane: PaneState, selected: bool, model: RwSignal) -> impl IntoView { + let id = pane.id(); + let needs_input = pane.needs_input(); + let state_color = if needs_input { + ATTENTION + } else if matches!(pane.kind(), SurfaceKind::Terminal) { + SUCCESS + } else { + ACCENT + }; + let state_label = if matches!(pane.kind(), SurfaceKind::Terminal) { + pane.status().label() + } else { + pane.fixture().badge + }; + let start = pane.lines().len().saturating_sub(12); + let lines = Stack::from_iter(pane.lines()[start..].iter().cloned().map(|line| { + Label::new(line).style(|s| { + s.font_size(12.0) + .color(TEXT) + .margin_bottom(4.0) + .min_width(0.0) }) - })); + })) + .style(|s| s.flex_col().padding_horiz(10.0).padding_bottom(10.0)); - let sidebar = Stack::vertical(( - Label::new("WORKSPACES").style(|s| s.font_size(11.0).color(MUTED).padding(12.0)), - sidebar_items.style(|s| s.padding_horiz(8.0)), - Label::new("HOSTS").style(|s| { - s.font_size(11.0) - .color(MUTED) - .padding(12.0) - .margin_top(12.0) - }), - Label::new("● metal · connected").style(|s| s.color(ACCENT).padding_horiz(14.0)), - Label::new("● amd-server · connected") - .style(|s| s.color(MUTED).padding_horiz(14.0).margin_top(8.0)), - Label::new("○ spark-1 · sleeping") - .style(|s| s.color(MUTED).padding_horiz(14.0).margin_top(8.0)), + let header = Stack::horizontal(( + Stack::horizontal(( + Label::new(format!("{}", id.index() + 1)) + .style(|s| s.font_size(11.0).color(MUTED).margin_right(8.0)), + Label::new(pane.fixture().title) + .style(|s| s.flex_grow(1.0).font_size(13.0).color(TEXT)), + )) + .style(|s| s.items_center().min_width(0.0).flex_grow(1.0)), + Label::new(state_label).style(move |s| s.font_size(10.0).color(state_color)), + )) + .style(move |s| { + s.items_center() + .height(36.0) + .padding_horiz(10.0) + .background(if selected { PANEL_ACTIVE } else { PANEL_ALT }) + .border_bottom(1.0) + .border_color(BORDER_QUIET) + }); + + let target = Stack::horizontal(( + Label::new(pane.fixture().target).style(|s| s.flex_grow(1.0).color(MUTED)), + Label::new(if selected { "FOCUSED" } else { "" }) + .style(|s| s.font_size(10.0).color(ACCENT)), )) .style(|s| { - s.width(220.0) + s.items_center() + .padding_horiz(10.0) + .padding_vert(8.0) + .font_size(11.0) + }); + + Stack::vertical((header, target, lines)) + .style(move |s| { + s.width_full() + .height_full() + .min_width(0.0) + .min_height(0.0) + .background(if selected { PANEL_ACTIVE } else { PANEL }) + .border(if selected { 2.0 } else { 1.0 }) + .border_color(if selected || needs_input { + state_color + } else { + BORDER + }) + .border_radius(5.0) + .keyboard_navigable() + }) + .on_event_stop(listener::Click, move |_, _| { + dispatch(model, ShellAction::SelectPane(id)); + }) +} + +fn sidebar() -> impl IntoView { + let worktrees = Stack::from_iter(WORKSPACES.into_iter().enumerate().map(|(index, name)| { + Stack::vertical(( + Label::new(name), + Label::new(if index == 0 { "main · metal" } else { "" }) + .style(|s| s.font_size(10.0).color(MUTED).margin_top(2.0)), + )) + .style(move |s| { + s.width_full() + .padding_vert(7.0) + .padding_horiz(10.0) + .margin_bottom(3.0) + .color(if index == 0 { TEXT } else { MUTED }) + .apply_if(index == 0, |s| s.background(PANEL_ALT).border_radius(5.0)) + }) + })) + .style(|s| s.flex_col().padding_horiz(8.0)); + + Stack::vertical(( + Label::new("ATTENTION · 1").style(|s| s.font_size(10.0).color(ATTENTION).padding(12.0)), + Stack::vertical(( + Label::new("Claude Code · UI").style(|s| s.color(TEXT)), + Label::new("Waiting for a split decision") + .style(|s| s.font_size(10.0).color(MUTED).margin_top(3.0)), + )) + .style(|s| { + s.margin_horiz(8.0) + .margin_bottom(12.0) + .padding(10.0) + .background(PANEL_ACTIVE) + .border(1.0) + .border_color(ATTENTION) + .border_radius(5.0) + }), + Label::new("WORKTREES").style(|s| s.font_size(10.0).color(MUTED).padding(12.0)), + worktrees, + Label::new("RUNTIMES").style(|s| { + s.font_size(10.0) + .color(MUTED) + .padding_horiz(12.0) + .padding_vert(9.0) + .margin_top(8.0) + }), + Label::new("● metal · connected").style(|s| s.color(SUCCESS).padding_horiz(12.0)), + Label::new("● amd-server · connected") + .style(|s| s.color(MUTED).padding_horiz(12.0).margin_top(7.0)), + Label::new("○ spark-1 · sleeping") + .style(|s| s.color(MUTED).padding_horiz(12.0).margin_top(7.0)), + Empty::new().style(|s| s.flex_grow(1.0)), + Stack::vertical(( + Label::new("Buzz · lumbridgecode"), + Label::new("connected · signed identity").style(|s| s.color(SUCCESS).margin_top(3.0)), + )) + .style(|s| { + s.margin(10.0) + .padding(10.0) + .font_size(10.0) + .color(MUTED) + .background(PANEL_ALT) + .border_radius(5.0) + }), + )) + .style(|s| { + s.width(248.0) .height_full() .flex_shrink(0.0) .background(PANEL) .border_right(1.0) - .border_color(BORDER) + .border_color(BORDER_QUIET) + }) +} + +fn tabs() -> impl IntoView { + Stack::horizontal(( + Label::new("Agent workspace").style(|s| { + s.height_full() + .items_center() + .padding_horiz(12.0) + .border_bottom(2.0) + .border_color(ACCENT) + .color(TEXT) + }), + Label::new("Architecture.md").style(|s| s.padding_horiz(12.0).color(MUTED)), + Label::new("Review").style(|s| s.padding_horiz(12.0).color(MUTED)), + Empty::new().style(|s| s.flex_grow(1.0)), + Label::new("6 surfaces · 3 remote · 1 waiting") + .style(|s| s.font_size(10.0).padding_horiz(12.0).color(MUTED)), + )) + .style(|s| { + s.height(38.0) + .items_center() + .font_size(12.0) + .background(PANEL) + .border_bottom(1.0) + .border_color(BORDER_QUIET) + }) +} + +fn command_palette(query: RwSignal) -> impl IntoView { + let input = TextInput::new(query) + .placeholder("Type a command…") + .style(|s| { + s.width_full() + .height(44.0) + .padding_horiz(12.0) + .color(TEXT) + .background(PANEL_ALT) + .border(0.0) + }); + let input_id = input.id(); + exec_after(Duration::from_millis(1), move |_| input_id.request_focus()); + + let card = Stack::vertical(( + input, + Stack::vertical(( + Stack::vertical(( + Label::new("Focus next pane").style(|s| s.color(TEXT)), + Label::new("Workspace · navigation") + .style(|s| s.font_size(10.0).color(MUTED).margin_top(3.0)), + )) + .style(|s| s.padding(10.0).background(PANEL_ACTIVE).border_radius(5.0)), + Label::new("Open attention request").style(|s| s.padding(10.0).color(MUTED)), + Label::new("Share selected pane to Buzz…").style(|s| s.padding(10.0).color(MUTED)), + )) + .style(|s| { + s.padding(8.0) + .border_top(1.0) + .border_bottom(1.0) + .border_color(BORDER) + }), + Stack::horizontal(( + Label::new("Enter to run").style(|s| s.flex_grow(1.0)), + Label::new("Esc to close"), + )) + .style(|s| { + s.padding_horiz(12.0) + .padding_vert(8.0) + .font_size(10.0) + .color(MUTED) + }), + )) + .style(|s| { + s.width(620.0) + .margin_top(92.0) + .background(PANEL_ALT) + .border(1.0) + .border_color(ACCENT) + .border_radius(8.0) + }); + + Container::new(card).style(|s| { + s.position(Position::Absolute) + .inset(0.0) + .items_start() + .justify_center() + .background(Color::from_rgba8(5, 7, 11, 220)) + .z_index(50) + }) +} + +fn handle_key( + model: RwSignal, + query: RwSignal, + KeyboardEvent { + code, + key, + modifiers, + .. + }: &KeyboardEvent, +) -> EventPropagation { + if *code == Code::KeyK && modifiers.contains(OS_MOD) { + query.set(String::new()); + dispatch(model, ShellAction::OpenCommandPalette); + return EventPropagation::Stop; + } + + if model.with(|model| model.command_palette().is_open()) { + if *key == Key::Named(NamedKey::Escape) { + query.set(String::new()); + dispatch(model, ShellAction::CloseCommandPalette); + return EventPropagation::Stop; + } + return EventPropagation::Continue; + } + + let action = match key { + Key::Named(NamedKey::ArrowLeft) => Some(ShellAction::MoveFocus(FocusDirection::Left)), + Key::Named(NamedKey::ArrowRight) => Some(ShellAction::MoveFocus(FocusDirection::Right)), + Key::Named(NamedKey::ArrowUp) => Some(ShellAction::MoveFocus(FocusDirection::Up)), + Key::Named(NamedKey::ArrowDown) => Some(ShellAction::MoveFocus(FocusDirection::Down)), + Key::Character(character) if modifiers.is_empty() => match character.as_str() { + "h" => Some(ShellAction::MoveFocus(FocusDirection::Left)), + "l" => Some(ShellAction::MoveFocus(FocusDirection::Right)), + "k" => Some(ShellAction::MoveFocus(FocusDirection::Up)), + "j" => Some(ShellAction::MoveFocus(FocusDirection::Down)), + "1" => Some(ShellAction::SelectPane(PaneId::CodexRuntime)), + "2" => Some(ShellAction::SelectPane(PaneId::ClaudeUi)), + "3" => Some(ShellAction::SelectPane(PaneId::PiDocs)), + "4" => Some(ShellAction::SelectPane(PaneId::Architecture)), + "5" => Some(ShellAction::SelectPane(PaneId::AcpPreview)), + "6" => Some(ShellAction::SelectPane(PaneId::RuntimeReview)), + _ => None, + }, + _ => None, + }; + + if let Some(action) = action { + dispatch(model, action); + EventPropagation::Stop + } else { + EventPropagation::Continue + } +} + +fn app_view() -> impl IntoView { + let model = RwSignal::new(ShellModel::default()); + let query = RwSignal::new(String::new()); + let timer_pulse = RwSignal::new(()); + + Effect::new(move |_| { + timer_pulse.track(); + exec_after(Duration::from_millis(650), move |_| { + dispatch(model, ShellAction::SyntheticStreamTick); + timer_pulse.set(()); + }); + }); + + Effect::new(move |_| { + let query = query.get(); + model.update(|model| { + if model.command_palette().is_open() && model.command_palette().query() != query { + model.dispatch(ShellAction::SetCommandPaletteQuery(query)); + } + }); }); let top_row = Stack::horizontal(( - pane_card(PANES[0]), - pane_card(PANES[1]), - pane_card(PANES[2]), + pane_card(PaneId::CodexRuntime, model), + pane_card(PaneId::ClaudeUi, model), + pane_card(PaneId::PiDocs, model), )) .style(|s| s.flex_basis(0).flex_grow(1.0).min_height(0.0).width_full()); let bottom_row = Stack::horizontal(( - pane_card(PANES[3]), - pane_card(PANES[4]), - pane_card(PANES[5]), + pane_card(PaneId::Architecture, model), + pane_card(PaneId::AcpPreview, model), + pane_card(PaneId::RuntimeReview, model), )) .style(|s| s.flex_basis(0).flex_grow(1.0).min_height(0.0).width_full()); - let panes = Stack::vertical((top_row, bottom_row)).style(|s| { + let grid = Stack::vertical((top_row, bottom_row)).style(|s| { s.flex_basis(0) .flex_grow(1.0) .min_width(0.0) - .height_full() + .min_height(0.0) .padding(4.0) }); let header = Stack::horizontal(( - Label::new("Lumbridge").style(|s| s.font_size(18.0).color(TEXT).flex_grow(1.0)), - Label::new("UI spike · Floem").style(|s| s.color(MUTED).flex_grow(1.0)), - Label::new("⌘K Command Palette").style(|s| s.color(ACCENT)), + Label::new("Lumbridge").style(|s| s.font_size(18.0).color(TEXT)), + Label::new("Lumbridge Code / main") + .style(|s| s.color(MUTED).margin_left(12.0).flex_grow(1.0)), + Label::new("metal · runtime online") + .style(|s| s.font_size(10.0).color(SUCCESS).margin_right(18.0)), + Label::new("Ctrl/⌘ K · Commands") + .style(|s| s.color(ACCENT).keyboard_navigable()) + .on_event_stop(listener::Click, move |_, _| { + query.set(String::new()); + dispatch(model, ShellAction::OpenCommandPalette); + }), )) .style(|s| { - s.height(46.0) + s.height(48.0) .padding_horiz(14.0) .items_center() .background(PANEL_ALT) .border_bottom(1.0) - .border_color(BORDER) + .border_color(BORDER_QUIET) }); - let body = Stack::horizontal((sidebar, panes)) - .style(|s| s.flex_basis(0).flex_grow(1.0).min_height(0.0)); + let body = Stack::horizontal(( + sidebar(), + Stack::vertical((tabs(), grid)).style(|s| { + s.flex_basis(0) + .flex_grow(1.0) + .min_width(0.0) + .min_height(0.0) + }), + )) + .style(|s| s.flex_basis(0).flex_grow(1.0).min_height(0.0)); let footer = Stack::horizontal(( - Label::new(FOOTER_LEFT).style(|s| s.flex_grow(1.0)), + Label::derived(move || { + model.with(|model| { + let counters = model.counters(); + format!( + "rev {} · {} focus moves · {} surface updates · {} lines", + model.revision(), + counters.focus_moves, + counters.surface_updates, + counters.terminal_lines_appended + ) + }) + }) + .style(|s| s.flex_grow(1.0)), Label::new(FOOTER_CENTER).style(|s| s.flex_grow(1.0)), Label::new(FOOTER_RIGHT), )) .style(|s| { - s.height(30.0) + s.height(32.0) .padding_horiz(10.0) .items_center() - .font_size(11.0) + .font_size(10.0) .color(MUTED) .background(PANEL_ALT) .border_top(1.0) - .border_color(BORDER) + .border_color(BORDER_QUIET) }); - Stack::vertical((header, body, footer)) - .style(|s| s.width_full().height_full().background(BG)) - .window_title(|| "Lumbridge · Floem spike".to_owned()) + let palette = dyn_container( + move || model.with(|model| model.command_palette().is_open()), + move |open| { + if open { + command_palette(query).into_any() + } else { + Empty::new().into_any() + } + }, + ); + + let root = Stack::vertical((header, body, footer, palette)) + .style(|s| { + s.position(Position::Relative) + .width_full() + .height_full() + .background(BG) + .color(TEXT) + .keyboard_navigable() + }) + .on_event(listener::KeyDown, move |_, event| { + handle_key(model, query, event) + }) + .window_title(|| "Lumbridge · Floem workspace".to_owned()); + + let root_id = root.id(); + exec_after(Duration::from_millis(1), move |_| root_id.request_focus()); + root } fn main() { @@ -154,9 +484,9 @@ fn main() { |_| app_view(), Some( WindowConfig::default() - .size(Size::new(1280.0, 800.0)) + .size(Size::new(1500.0, 960.0)) .min_size(Size::new(900.0, 600.0)) - .title("Lumbridge · Floem spike"), + .title("Lumbridge · Floem workspace"), ), ) .run(); diff --git a/spikes/gpui-accessibility-probe/Cargo.lock b/spikes/gpui-accessibility-probe/Cargo.lock new file mode 100644 index 0000000..af03c06 --- /dev/null +++ b/spikes/gpui-accessibility-probe/Cargo.lock @@ -0,0 +1,7119 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "accesskit" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3b7f7f85a7e5f68090000ed7622545829afd484d210358702ae4cb97dd0c320" +dependencies = [ + "enumn", + "uuid", +] + +[[package]] +name = "accesskit_atspi_common" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e8c61bee90b42a772d39d06a740207dc71a4e780004ace1db8d99fb1baaa954" +dependencies = [ + "accesskit", + "accesskit_consumer 0.36.0", + "atspi-common", + "phf", + "serde", + "zvariant", +] + +[[package]] +name = "accesskit_consumer" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25e0d7e25d06f4dc21d1774d67146e9e80d6789216cbd4d1e88185b0095dba60" +dependencies = [ + "accesskit", + "hashbrown 0.16.1", +] + +[[package]] +name = "accesskit_consumer" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950720ce064757a1b629caad3a408e8d2c63bb01f29b8a3ff8daa331053ffeb" +dependencies = [ + "accesskit", + "hashbrown 0.16.1", +] + +[[package]] +name = "accesskit_consumer" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d10a236f96f87d70732e44520046785431ef01d5bcd6b041317bfadd2f88245" +dependencies = [ + "accesskit", + "hashbrown 0.16.1", +] + +[[package]] +name = "accesskit_macos" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce02dc63b43f0c9296af9ac946312a2dc8814427d7a64d2d600971dac55b6076" +dependencies = [ + "accesskit", + "accesskit_consumer 0.38.0", + "hashbrown 0.16.1", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "accesskit_unix" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b016ca8db0ea0ea2ceff29a9d6240391492d960716aa471967c00e8cc8cb197c" +dependencies = [ + "accesskit", + "accesskit_atspi_common", + "async-channel", + "async-executor", + "async-task", + "atspi", + "futures-lite", + "futures-util", + "serde", + "zbus", +] + +[[package]] +name = "accesskit_windows" +version = "0.33.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36e93ac7bf50b964f1cbb75f741629a4e950571baa1ef1274457ab5a80d9bcc2" +dependencies = [ + "accesskit", + "accesskit_consumer 0.37.0", + "hashbrown 0.16.1", + "static_assertions", + "windows 0.62.2", + "windows-core 0.62.2", +] + +[[package]] +name = "addr2line" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", + "zeroize", +] + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "const-random", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" +dependencies = [ + "memchr", +] + +[[package]] +name = "aligned" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee4508988c62edf04abd8d92897fca0c2995d907ce1dfeaf369dac3716a40685" +dependencies = [ + "as-slice", +] + +[[package]] +name = "aligned-vec" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" +dependencies = [ + "equator", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "android_system_properties" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" + +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" + +[[package]] +name = "arg_enum_proc_macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" + +[[package]] +name = "as-raw-xcb-connection" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" + +[[package]] +name = "as-slice" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "ash" +version = "0.38.0+1.3.281" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" +dependencies = [ + "libloading", +] + +[[package]] +name = "ashpd" +version = "0.13.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb8421aaa9644a5faf26735f258b669b15f063313ef8f8e2bdb28912a1a6f111" +dependencies = [ + "enumflags2", + "futures-channel", + "futures-util", + "getrandom 0.4.3", + "serde", + "serde_repr", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "zbus", +] + +[[package]] +name = "async-broadcast" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" +dependencies = [ + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-channel" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-compression" +version = "0.4.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3976abdc8fe7d1133d43d304afd42abdf5bc3e1319d263d223bde07b5efc4be8" +dependencies = [ + "compression-codecs", + "compression-core", + "futures-io", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "pin-project-lite", + "slab", +] + +[[package]] +name = "async-fs" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8034a681df4aed8b8edbd7fbe472401ecf009251c8b40556b304567052e294c5" +dependencies = [ + "async-lock", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" +dependencies = [ + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-lock" +version = "3.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-net" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b948000fad4873c1c9339d60f2623323a0cfd3816e5181033c6a5cb68b2accf7" +dependencies = [ + "async-io", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-process" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" +dependencies = [ + "async-channel", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "async-signal" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52b5aaafa020cf5053a01f2a60e8ff5dccf550f0f77ec54a4e47285ac2bab485" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix", + "signal-hook-registry", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "async-trait" +version = "0.1.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.4", +] + +[[package]] +name = "atomic" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "atspi" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c77886257be21c9cd89a4ae7e64860c6f0eefca799bb79127913052bd0eefb3d" +dependencies = [ + "atspi-common", + "atspi-proxies", +] + +[[package]] +name = "atspi-common" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20c5617155740c98003016429ad13fe43ce7a77b007479350a9f8bf95a29f63d" +dependencies = [ + "enumflags2", + "serde", + "static_assertions", + "zbus", + "zbus-lockstep", + "zbus-lockstep-macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "atspi-proxies" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2230e48787ed3eb4088996eab66a32ca20c0b67bbd4fd6cdfe79f04f1f04c9fc" +dependencies = [ + "atspi-common", + "serde", + "zbus", +] + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "av-scenechange" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f321d77c20e19b92c39e7471cf986812cbb46659d2af674adc4331ef3f18394" +dependencies = [ + "aligned", + "anyhow", + "arg_enum_proc_macro", + "arrayvec", + "log", + "num-rational", + "num-traits", + "pastey", + "rayon", + "thiserror 2.0.20", + "v_frame", + "y4m", +] + +[[package]] +name = "av1-grain" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cfddb07216410377231960af4fcab838eaa12e013417781b78bd95ee22077f8" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom 8.0.0", + "num-rational", + "v_frame", +] + +[[package]] +name = "avif-serialize" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7178fe5f7d460b13895ebb9dcb28a3a6216d2df2574a0806cb51b555d297f38" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "backtrace" +version = "0.3.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide 0.8.9", + "object", + "rustc-demangle", + "windows-link 0.2.1", +] + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bindgen" +version = "0.71.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" +dependencies = [ + "bitflags 2.13.1", + "cexpr", + "clang-sys", + "itertools 0.13.0", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash 2.1.3", + "shlex 1.3.0", + "syn 2.0.119", +] + +[[package]] +name = "bit-set" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34ddef2995421ab6a5c779542c81ee77c115206f4ad9d5a8e05f4ff49716a3dd" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71798fca2c1fe1086445a7258a4bc81e6e49dcd24c8d0dd9a1e57395b603f51" + +[[package]] +name = "bit_field" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" + +[[package]] +name = "bitstream-io" +version = "4.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eff00be299a18769011411c9def0d827e8f2d7bf0c3dbf53633147a8867fd1f" +dependencies = [ + "no_std_io2", +] + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-padding" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +dependencies = [ + "objc2 0.5.2", +] + +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2 0.6.4", +] + +[[package]] +name = "blocking" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a70e4329df6cb94385eed412ec92375c3cdd8a6e502493d1229b6414e4036dfa" +dependencies = [ + "async-channel", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + +[[package]] +name = "borsh" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "553c5d846a6ba5150c65e3b1b8ec073bcf1abc20f9b7220de384a4443ea4e20a" +dependencies = [ + "bytes", + "cfg_aliases", +] + +[[package]] +name = "built" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c0e531d93d39c34eef561e929e8a7f86d77a5af08aac4f6d6e39976c51858e9" + +[[package]] +name = "bumpalo" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + +[[package]] +name = "bytemuck" +version = "1.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0e56a716f1e132ff6bf4bdac1c944a3fcdc1cae65f70a4a2a1ac3b401d2d1f" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.4", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + +[[package]] +name = "bytes" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" + +[[package]] +name = "bzip2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3a53fac24f34a81bc9954b5d6cfce0c21e18ec6959f44f56e8e90e4bb7c346c" +dependencies = [ + "libbz2-rs-sys", +] + +[[package]] +name = "calloop" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dbf9978365bac10f54d1d4b04f7ce4427e51f71d61f2fe15e3fed5166474df7" +dependencies = [ + "bitflags 2.13.1", + "polling", + "rustix", + "slab", + "tracing", +] + +[[package]] +name = "calloop-wayland-source" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138efcf0940a02ebf0cc8d1eff41a1682a46b431630f4c52450d6265876021fa" +dependencies = [ + "calloop", + "rustix", + "wayland-backend", + "wayland-client", +] + +[[package]] +name = "cbc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" +dependencies = [ + "cipher", +] + +[[package]] +name = "cbindgen" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadd868a2ce9ca38de7eeafdcec9c7065ef89b42b32f0839278d55f35c54d1ff" +dependencies = [ + "heck 0.4.1", + "indexmap", + "log", + "proc-macro2", + "quote", + "serde", + "serde_json", + "syn 2.0.119", + "tempfile", + "toml 0.8.23", +] + +[[package]] +name = "cc" +version = "1.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ad534f4357a5264cce5019c989cf66a4f0dc4e0d1b1d15f8aacec0ff7360273" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex 2.0.1", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom 7.1.3", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" + +[[package]] +name = "cgl" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ced0551234e87afee12411d535648dd89d2e7f34c78b753395567aff3d447ff" +dependencies = [ + "libc", +] + +[[package]] +name = "chrono" +version = "0.4.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-traits", + "serde", + "wasm-bindgen", + "windows-link 0.2.1", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", + "zeroize", +] + +[[package]] +name = "clang-sys" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "157a8ba7b480713b56f4c09fd13fc3e0a22a5dfab8097ba61cbc5feef950788a" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "cocoa" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6140449f97a6e97f9511815c5632d84c8aacf8ac271ad77c559218161a1373c" +dependencies = [ + "bitflags 1.3.2", + "block", + "cocoa-foundation 0.1.2", + "core-foundation 0.9.4", + "core-graphics 0.23.2", + "foreign-types", + "libc", + "objc", +] + +[[package]] +name = "cocoa" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f79398230a6e2c08f5c9760610eb6924b52aa9e7950a619602baba59dcbbdbb2" +dependencies = [ + "bitflags 2.13.1", + "block", + "cocoa-foundation 0.2.1", + "core-foundation 0.10.1", + "core-graphics 0.24.0", + "foreign-types", + "libc", + "objc", +] + +[[package]] +name = "cocoa-foundation" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" +dependencies = [ + "bitflags 1.3.2", + "block", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", + "libc", + "objc", +] + +[[package]] +name = "cocoa-foundation" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81411967c50ee9a1fc11365f8c585f863a22a9697c89239c452292c40ba79b0d" +dependencies = [ + "bitflags 2.13.1", + "block", + "core-foundation 0.10.1", + "core-graphics-types 0.2.0", + "objc", +] + +[[package]] +name = "codespan-reporting" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681" +dependencies = [ + "serde", + "termcolor", + "unicode-width", +] + +[[package]] +name = "collections" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed.git?rev=ce48461eaadd16c65c31f835511ab96bd3b6e746#ce48461eaadd16c65c31f835511ab96bd3b6e746" +dependencies = [ + "gpui_util", + "indexmap", + "rustc-hash 2.1.3", +] + +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "compression-codecs" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce2548391e9c1929c21bf6aa2680af86fe4c1b33e6cea9ac1cfeec0bd11218cf" +dependencies = [ + "bzip2", + "compression-core", + "flate2", + "memchr", +] + +[[package]] +name = "compression-core" +version = "0.4.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc14f565cf027a105f7a44ccf9e5b424348421a1d8952a8fc9d499d313107789" + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom 0.2.17", + "once_cell", + "tiny-keccak", +] + +[[package]] +name = "convert_case" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "core-graphics" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" +dependencies = [ + "bitflags 1.3.2", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" +dependencies = [ + "bitflags 2.13.1", + "core-foundation 0.10.1", + "core-graphics-types 0.2.0", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-helmer-fork" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32eb7c354ae9f6d437a6039099ce7ecd049337a8109b23d73e48e8ffba8e9cd5" +dependencies = [ + "bitflags 2.13.1", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +dependencies = [ + "bitflags 1.3.2", + "core-foundation 0.9.4", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" +dependencies = [ + "bitflags 2.13.1", + "core-foundation 0.10.1", + "libc", +] + +[[package]] +name = "core-graphics2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4416167a69126e617f8d0a214af0e3c1dbdeffcb100ddf72dcd1a1ac9893c146" +dependencies = [ + "bitflags 2.13.1", + "block", + "cfg-if", + "core-foundation 0.10.1", + "libc", +] + +[[package]] +name = "core-text" +version = "21.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a593227b66cbd4007b2a050dfdd9e1d1318311409c8d600dc82ba1b15ca9c130" +dependencies = [ + "core-foundation 0.10.1", + "core-graphics 0.24.0", + "foreign-types", + "libc", +] + +[[package]] +name = "core-video" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139679cc63eb9504bdbe37e37874b0247136177655f0008588781e90863afa62" +dependencies = [ + "block", + "core-foundation 0.10.1", + "core-graphics2", + "io-surface", + "libc", + "metal", +] + +[[package]] +name = "core_maths" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77745e017f5edba1a9c1d854f6f3a52dac8a12dd5af5d2f54aecf61e43d80d30" +dependencies = [ + "libm", +] + +[[package]] +name = "cosmic-text" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be17b688510d934ce13f48a2beba700e11583e281e0fda99c22bb256a14eda73" +dependencies = [ + "bitflags 2.13.1", + "fontdb", + "harfrust", + "linebender_resource_handle", + "log", + "rangemap", + "rustc-hash 2.1.3", + "self_cell", + "skrifa 0.40.0", + "smol_str", + "swash", + "sys-locale", + "unicode-bidi", + "unicode-linebreak", + "unicode-script", + "unicode-segmentation", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8498c871161e1742aaa9d52551b2d6ebdd4c3d45a3be423e3728f33b955be550" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "803d13fb3b09d88be9f4dbc29062c66b19bf7170867ceb746d2a8689bf6c7a26" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "ctor" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "914a755b7c2d4af2bdcff7ce1739e2db9a1b81a9b07123d8015786ae03c0980d" +dependencies = [ + "link-section", + "linktime-proc-macro", +] + +[[package]] +name = "data-url" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be1e0bca6c3637f992fc1cc7cbc52a78c1ef6db076dbf1059c4323d6a2048376" + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" + +[[package]] +name = "derive_more" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.119", + "unicode-xid", +] + +[[package]] +name = "derive_refineable" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed.git?rev=ce48461eaadd16c65c31f835511ab96bd3b6e746#ce48461eaadd16c65c31f835511ab96bd3b6e746" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "dirs" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.61.2", +] + +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "dispatch2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "libc", + "objc2 0.6.4", +] + +[[package]] +name = "displaydoc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.4", +] + +[[package]] +name = "dlib" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab8ecd87370524b461f8557c119c405552c396ed91fc0a8eec68679eab26f94a" +dependencies = [ + "libloading", +] + +[[package]] +name = "document-features" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +dependencies = [ + "litrs", +] + +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "dwrote" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b35532432acc8b19ceed096e35dfa088d3ea037fe4f3c085f1f97f33b4d02" +dependencies = [ + "lazy_static", + "libc", + "winapi", + "wio", +] + +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + +[[package]] +name = "either" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34" + +[[package]] +name = "embed-resource" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbfdaacccebec3b28e4866b8973543c7647797db5ada1bdab552e48fe665fbbd" +dependencies = [ + "cc", + "memchr", + "rustc_version", + "toml 1.1.4+spec-1.1.0", + "vswhom", + "winreg", +] + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "endi" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" + +[[package]] +name = "enumflags2" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "enumn" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "equator" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "erased-serde" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2add8a07dd6a8d93ff627029c51de145e12686fbc36ecb298ac22e74cf02dec" +dependencies = [ + "serde", + "serde_core", + "typeid", +] + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "etagere" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc89bf99e5dc15954a60f707c1e09d7540e5cd9af85fa75caa0b510bc08c5342" +dependencies = [ + "euclid", + "svg_fmt", +] + +[[package]] +name = "euclid" +version = "0.22.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a05365e3b1c6d1650318537c7460c6923f1abdd272ad6842baa2b509957a06" +dependencies = [ + "num-traits", +] + +[[package]] +name = "event-listener" +version = "5.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a23add41df1562121a9393cb065eab5146a1242410f23a644851e90cfd669d2" +dependencies = [ + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] + +[[package]] +name = "exr" +version = "1.74.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711fe42c9964295e01ee3fba3f9fe0e1d24b98886950d68efe81b1c76e21adf3" +dependencies = [ + "bit_field", + "half", + "lebe", + "miniz_oxide 0.8.9", + "num-complex", + "pulp", + "rayon-core", + "smallvec", + "zune-inflate", +] + +[[package]] +name = "fastrand" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" +dependencies = [ + "getrandom 0.4.3", +] + +[[package]] +name = "fax" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf1079563223d5d59d83c85886a56e586cfd5c1a26292e971a0fa266531ac5a" + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "filedescriptor" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e40758ed24c9b2eeb76c35fb0aebc66c626084edd827e07e1552279814c6682d" +dependencies = [ + "libc", + "thiserror 1.0.69", + "winapi", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d45db016d36b838f563236e9193d0ee6ce38f3f68b6c94e914b4929c96bbb890" + +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + +[[package]] +name = "flate2" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e634e2e0ebac1ee034020da1ca582e17ffe4e0f5e985823721e168928136dcb" +dependencies = [ + "crc32fast", + "miniz_oxide 0.9.1", + "zlib-rs", +] + +[[package]] +name = "float-cmp" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" + +[[package]] +name = "float-ord" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce81f49ae8a0482e4c55ea62ebbd7e5a686af544c00b9d090bba3ff9be97b3d" + +[[package]] +name = "float_next_after" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bf7cc16383c4b8d58b9905a8509f02926ce3058053c056376248d958c9df1e8" + +[[package]] +name = "flume" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e139bc46ca777eb5efaf62df0ab8cc5fd400866427e56c68b22e414e53bd3be" +dependencies = [ + "fastrand", + "futures-core", + "futures-sink", + "spin 0.9.9", +] + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "font-types" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b38ad915f6dadd993ced50848a8291a543bd41ca62bc10740d5e64e2ab4cfd7" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "font-types" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e64eb721ca85a34323425f4041adc5d82704d3782d5f8f03793bc012419dce23" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "fontconfig-parser" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbc773e24e02d4ddd8395fd30dc147524273a83e54e0f312d986ea30de5f5646" +dependencies = [ + "roxmltree 0.20.0", +] + +[[package]] +name = "fontdb" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "457e789b3d1202543297a350643cf459f836cade38934e7a4cf6a39e7cde2905" +dependencies = [ + "fontconfig-parser", + "log", + "memmap2", + "slotmap", + "tinyvec", + "ttf-parser", +] + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea5190182e6915eb873ddbc16e23b711b6eb1f9c00a0d0a3a91b5f6228475225" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.4", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "freetype-sys" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7edc5b9669349acfda99533e9e0bcf26a51862ab43b08ee7745c55d28eb134" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + +[[package]] +name = "futures" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a31d2a3fbaaeb2af2368bbdd904aa8e812d3c04a1ee10d3171f52d556e5d0a3" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-concurrency" +version = "7.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175cd8cca9e1d45b87f18ffa75088f2099e3c4fe5e2f83e42de112560bea8ea6" +dependencies = [ + "fixedbitset", + "futures-core", + "futures-lite", + "pin-project", + "smallvec", +] + +[[package]] +name = "futures-core" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" + +[[package]] +name = "futures-executor" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "031b47cf1a3c6cc8bc2fc76cd437f521619387907d469316e7c0bc278f1f5432" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed" + +[[package]] +name = "futures-lite" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "futures-macro" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.4", +] + +[[package]] +name = "futures-sink" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1944426bf7d03f1d14f708785e4b33efd750b36d48a157b836b3efc15ede8e1d" + +[[package]] +name = "futures-task" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" + +[[package]] +name = "futures-util" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "gethostname" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" +dependencies = [ + "rustix", + "windows-link 0.2.1", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi 5.3.0", + "wasip2", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi 6.0.0", + "wasm-bindgen", +] + +[[package]] +name = "gif" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee8cfcc411d9adbbaba82fb72661cc1bcca13e8bba98b364e62b2dba8f960159" +dependencies = [ + "color_quant", + "weezl", +] + +[[package]] +name = "gimli" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" + +[[package]] +name = "gl_generator" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" +dependencies = [ + "khronos_api", + "log", + "xml-rs", +] + +[[package]] +name = "glob" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b" + +[[package]] +name = "glow" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29038e1c483364cc6bb3cf78feee1816002e127c331a1eec55a4d202b9e1adb5" +dependencies = [ + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "glutin_wgl_sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c4ee00b289aba7a9e5306d57c2d05499b2e5dc427f84ac708bd2c090212cf3e" +dependencies = [ + "gl_generator", +] + +[[package]] +name = "gpu-allocator" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51255ea7cfaadb6c5f1528d43e92a82acb2b96c43365989a28b2d44ee38f8795" +dependencies = [ + "ash", + "hashbrown 0.16.1", + "log", + "presser", + "thiserror 2.0.20", + "windows 0.62.2", +] + +[[package]] +name = "gpu-descriptor" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca" +dependencies = [ + "bitflags 2.13.1", + "gpu-descriptor-types", + "hashbrown 0.15.5", +] + +[[package]] +name = "gpu-descriptor-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" +dependencies = [ + "bitflags 2.13.1", +] + +[[package]] +name = "gpui" +version = "0.2.2" +source = "git+https://github.com/zed-industries/zed.git?rev=ce48461eaadd16c65c31f835511ab96bd3b6e746#ce48461eaadd16c65c31f835511ab96bd3b6e746" +dependencies = [ + "accesskit", + "anyhow", + "async-channel", + "async-task", + "bindgen", + "bitflags 2.13.1", + "chrono", + "collections", + "core-video", + "ctor", + "derive_more", + "embed-resource", + "etagere", + "futures", + "futures-concurrency", + "getrandom 0.3.4", + "gpui_macros", + "gpui_shared_string", + "gpui_util", + "heapless", + "http_client", + "image", + "inventory", + "itertools 0.14.0", + "log", + "lyon", + "num_cpus", + "parking", + "parking_lot", + "pin-project", + "pollster 0.4.0", + "postage", + "profiling", + "rand 0.9.5", + "raw-window-handle", + "refineable", + "regex", + "resvg", + "scheduler", + "schemars", + "seahash", + "serde", + "serde_json", + "slotmap", + "smallvec", + "spin 0.10.1", + "strum", + "sum_tree", + "taffy", + "thiserror 2.0.20", + "tracing", + "ttf-parser", + "url", + "usvg", + "util_macros", + "uuid", + "waker-fn", + "web-time", + "windows 0.61.3", + "zed-scap", + "ztracing", +] + +[[package]] +name = "gpui_apple" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed.git?rev=ce48461eaadd16c65c31f835511ab96bd3b6e746#ce48461eaadd16c65c31f835511ab96bd3b6e746" +dependencies = [ + "anyhow", + "block", + "cbindgen", + "cocoa 0.26.0", + "collections", + "core-foundation 0.10.1", + "core-video", + "derive_more", + "etagere", + "foreign-types", + "gpui", + "image", + "log", + "metal", + "objc", + "parking_lot", +] + +[[package]] +name = "gpui_linux" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed.git?rev=ce48461eaadd16c65c31f835511ab96bd3b6e746#ce48461eaadd16c65c31f835511ab96bd3b6e746" +dependencies = [ + "accesskit", + "accesskit_unix", + "anyhow", + "as-raw-xcb-connection", + "ashpd", + "bitflags 2.13.1", + "bytemuck", + "calloop", + "calloop-wayland-source", + "collections", + "filedescriptor", + "futures", + "gpui", + "gpui_util", + "gpui_wgpu", + "http_client", + "libc", + "log", + "notify-rust", + "oo7", + "open", + "parking_lot", + "raw-window-handle", + "smallvec", + "smol", + "strum", + "url", + "uuid", + "wayland-backend", + "wayland-client", + "wayland-cursor", + "wayland-protocols", + "wayland-protocols-plasma", + "wayland-protocols-wlr", + "x11-clipboard", + "x11rb", + "xkbcommon", + "zed-scap", + "zed-xim", +] + +[[package]] +name = "gpui_macos" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed.git?rev=ce48461eaadd16c65c31f835511ab96bd3b6e746#ce48461eaadd16c65c31f835511ab96bd3b6e746" +dependencies = [ + "accesskit", + "accesskit_macos", + "anyhow", + "async-task", + "block", + "block2 0.6.2", + "cocoa 0.26.0", + "collections", + "core-foundation 0.10.1", + "core-foundation-sys", + "core-graphics 0.24.0", + "core-text", + "ctor", + "dispatch2", + "foreign-types", + "futures", + "gpui", + "gpui_apple", + "gpui_util", + "image", + "itertools 0.14.0", + "libc", + "log", + "mach2", + "media", + "metal", + "objc", + "objc2 0.6.4", + "objc2-app-kit 0.3.2", + "objc2-foundation 0.3.2", + "objc2-user-notifications", + "parking_lot", + "pathfinder_geometry", + "raw-window-handle", + "semver", + "smallvec", + "strum", + "uuid", + "zed-font-kit", +] + +[[package]] +name = "gpui_macros" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed.git?rev=ce48461eaadd16c65c31f835511ab96bd3b6e746#ce48461eaadd16c65c31f835511ab96bd3b6e746" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "gpui_platform" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed.git?rev=ce48461eaadd16c65c31f835511ab96bd3b6e746#ce48461eaadd16c65c31f835511ab96bd3b6e746" +dependencies = [ + "console_error_panic_hook", + "gpui", + "gpui_linux", + "gpui_macos", + "gpui_web", + "gpui_windows", +] + +[[package]] +name = "gpui_shared_string" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed.git?rev=ce48461eaadd16c65c31f835511ab96bd3b6e746#ce48461eaadd16c65c31f835511ab96bd3b6e746" +dependencies = [ + "schemars", + "serde", + "smol_str", +] + +[[package]] +name = "gpui_util" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed.git?rev=ce48461eaadd16c65c31f835511ab96bd3b6e746#ce48461eaadd16c65c31f835511ab96bd3b6e746" +dependencies = [ + "anyhow", + "log", + "which", +] + +[[package]] +name = "gpui_web" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed.git?rev=ce48461eaadd16c65c31f835511ab96bd3b6e746#ce48461eaadd16c65c31f835511ab96bd3b6e746" +dependencies = [ + "anyhow", + "console_error_panic_hook", + "futures", + "gpui", + "gpui_wgpu", + "http_client", + "js-sys", + "log", + "parking_lot", + "raw-window-handle", + "scheduler", + "uuid", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm_thread", + "web-sys", + "web-time", +] + +[[package]] +name = "gpui_wgpu" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed.git?rev=ce48461eaadd16c65c31f835511ab96bd3b6e746#ce48461eaadd16c65c31f835511ab96bd3b6e746" +dependencies = [ + "anyhow", + "bytemuck", + "collections", + "cosmic-text", + "etagere", + "gpui", + "gpui_util", + "itertools 0.14.0", + "log", + "parking_lot", + "profiling", + "raw-window-handle", + "smallvec", + "swash", + "unicode-bidi", + "unicode-segmentation", + "web-sys", + "wgpu", + "zed-font-kit", +] + +[[package]] +name = "gpui_windows" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed.git?rev=ce48461eaadd16c65c31f835511ab96bd3b6e746#ce48461eaadd16c65c31f835511ab96bd3b6e746" +dependencies = [ + "accesskit", + "accesskit_windows", + "anyhow", + "collections", + "dunce", + "etagere", + "futures", + "gpui", + "gpui_util", + "image", + "itertools 0.14.0", + "log", + "parking_lot", + "rand 0.9.5", + "raw-window-handle", + "smallvec", + "uuid", + "windows 0.61.3", + "windows-core 0.61.2", + "windows-numerics 0.2.0", + "windows-registry", +] + +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "num-traits", + "zerocopy", +] + +[[package]] +name = "harfrust" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9da2e5ae821f6e96664977bf974d6d6a2d6682f9ccee23e62ec1d134246845f9" +dependencies = [ + "bitflags 2.13.1", + "bytemuck", + "core_maths", + "read-fonts 0.37.0", + "smallvec", +] + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "heapless" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25ba4bd83f9415b58b4ed8dc5714c76e626a105be4646c02630ad730ad3b5aa4" +dependencies = [ + "hash32", + "stable_deref_trait", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17592d60ebacc7d5e169f4663c5f84f9161cc90328abcfe8456f41e4dfcb284" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hexf-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" + +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "http" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "918d3568bebf352712bc2ef3d46a8bcf1a75b373be6539de198e9105cbbf9ce0" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2a8f2913ee65f60facd6a5905613afaa448497a0230cc41ce022d93290bc2c" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http_client" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed.git?rev=ce48461eaadd16c65c31f835511ab96bd3b6e746#ce48461eaadd16c65c31f835511ab96bd3b6e746" +dependencies = [ + "anyhow", + "async-compression", + "bytes", + "derive_more", + "futures", + "http", + "http-body", + "log", + "parking_lot", + "serde", + "serde_json", + "serde_urlencoded", + "url", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core 0.62.2", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa68d21081c4a05d5a901a1c62add574c77048b6a1c67be3b50ce0b60d4ca513" +dependencies = [ + "displaydoc", + "potential_utf", + "utf8_iter", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d56e28588da92eee5c3201a6eff33fabdd49b62269c8938d4ff050ce4d900deb" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f9cf5f235641ed274641dd81c3f28d870e276763d0797aeeab72317b1c646f" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1563da1ed3e0b3bf3d74c9b85917ac9c56464d2f57242270c09c9e752f8021a0" + +[[package]] +name = "icu_properties" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e7ca276ad3145661a65914e6daf131ca5120cd3dcee8f8f3214b8875184a148" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e590f038c1464a96894fd6d10127e90a8be4509f56ff7ecef851b15cee0b7caa" + +[[package]] +name = "icu_provider" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d27bbb9d3abbefac45d55f647c9de1d44aafcd1186eb91879afef17c396c3e73" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "image" +version = "0.25.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" +dependencies = [ + "bytemuck", + "byteorder-lite", + "color_quant", + "exr", + "gif", + "image-webp", + "moxcms", + "num-traits", + "png 0.18.1", + "qoi", + "ravif", + "rayon", + "tiff", + "zune-core", + "zune-jpeg", +] + +[[package]] +name = "image-webp" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3" +dependencies = [ + "byteorder-lite", + "quick-error", +] + +[[package]] +name = "imagesize" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09e54e57b4c48b40f7aec75635392b12b3421fa26fe8b4332e63138ed278459c" + +[[package]] +name = "imgref" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e44b0a4eaa4c82f441d50a963f2d5f05a787240aeee097597033e72accfd22f" + +[[package]] +name = "indexmap" +version = "2.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07aa2048142242915a31d35844fb311e0e53fcca590c3a0a40dcf1b841fa09eb" +dependencies = [ + "equivalent", + "hashbrown 0.17.1", + "serde", + "serde_core", +] + +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "block-padding", + "generic-array", +] + +[[package]] +name = "interpolate_name" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "inventory" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4f0c30c76f2f4ccee3fe55a2435f691ca00c0e4bd87abe4f4a851b1d4dac39b" +dependencies = [ + "rustversion", +] + +[[package]] +name = "io-surface" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "554b8c5d64ec09a3a520fe58e4d48a73e00ff32899cdcbe32a4877afd4968b8e" +dependencies = [ + "cgl", + "core-foundation 0.10.1", + "core-foundation-sys", + "leaky-cow", +] + +[[package]] +name = "is-docker" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3" +dependencies = [ + "once_cell", +] + +[[package]] +name = "is-wsl" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5" +dependencies = [ + "is-docker", + "once_cell", +] + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "jni-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +dependencies = [ + "jni-sys 0.4.1", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.119", +] + +[[package]] +name = "jobserver" +version = "0.1.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3" +dependencies = [ + "getrandom 0.4.3", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a" +dependencies = [ + "cfg-if", + "futures-util", + "wasm-bindgen", +] + +[[package]] +name = "khronos-egl" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" +dependencies = [ + "libc", + "libloading", + "pkg-config", +] + +[[package]] +name = "khronos_api" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" + +[[package]] +name = "kurbo" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b60dfc32f652b926df6192e55525b16d186c69d47876c3ead4da5cc9f8450e2" +dependencies = [ + "arrayvec", + "euclid", + "polycool", + "smallvec", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "leak" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd100e01f1154f2908dfa7d02219aeab25d0b9c7fa955164192e3245255a0c73" + +[[package]] +name = "leaky-cow" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40a8225d44241fd324a8af2806ba635fc7c8a7e9a7de4d5cf3ef54e71f5926fc" +dependencies = [ + "leak", +] + +[[package]] +name = "lebe" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" + +[[package]] +name = "libbz2-rs-sys" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34b357333733e8260735ba5894eb928c02ecc69c78715f01a8019e7fa7f2db4c" + +[[package]] +name = "libc" +version = "0.2.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" + +[[package]] +name = "libfuzzer-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9fd2f41a1cba099f79a0b6b6c35656cf7c03351a7bae8ff0f28f25270f929d2" +dependencies = [ + "arbitrary", + "cc", +] + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link 0.2.1", +] + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "libredox" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7955dfc218a8afb29dfeffd540e3a6e96baeb94fe7138228dd7cc6937fbbf96" +dependencies = [ + "libc", +] + +[[package]] +name = "linebender_resource_handle" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4a5ff6bcca6c4867b1c4fd4ef63e4db7436ef363e0ad7531d1558856bae64f4" + +[[package]] +name = "link-section" +version = "0.19.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39c29a617ce3df32c08497bdc1ab6e2376e0b17948ac166a2fbe5977c5954cd9" + +[[package]] +name = "linktime-proc-macro" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e57c38c1e860fd37c604281cdfb1dd2216977fd76a50f85ba2f388ef3219616" + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "litemap" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d9d19d1d6efa0109d2f65ff4c85cddd50bd572e5a00127ab10987290bcefae" + +[[package]] +name = "litrs" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" +dependencies = [ + "serde_core", + "value-bag", +] + +[[package]] +name = "loop9" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" +dependencies = [ + "imgref", +] + +[[package]] +name = "lumbridge-spike-gpui-accessibility" +version = "0.0.1" +dependencies = [ + "gpui", + "gpui_platform", +] + +[[package]] +name = "lyon" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0578bdecb7d6d88987b8b2b1e3a4e2f81df9d0ece1078623324a567904e7b7" +dependencies = [ + "lyon_algorithms", + "lyon_tessellation", +] + +[[package]] +name = "lyon_algorithms" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdfa8785f95e57914ddb35e3b59994aeba6f5e79e9cfd03da1c269f010f36009" +dependencies = [ + "lyon_path", + "num-traits", +] + +[[package]] +name = "lyon_geom" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4336502e29e32af93cf2dad2214ed6003c17ceb5bd499df77b1de663b9042b92" +dependencies = [ + "arrayvec", + "euclid", + "num-traits", +] + +[[package]] +name = "lyon_path" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c463f9c428b7fc5ec885dcd39ce4aa61e29111d0e33483f6f98c74e89d8621e" +dependencies = [ + "lyon_geom", + "num-traits", +] + +[[package]] +name = "lyon_tessellation" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dabea159dc6eea9171a541b458134b70ca95e3162d068132b2b3b9bc01aad06e" +dependencies = [ + "float_next_after", + "lyon_path", + "num-traits", +] + +[[package]] +name = "mac-notification-sys" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd604973958ddcc11b561193c0fb96ba146506ef2f231ef2e7c35fd2cbc9beca" +dependencies = [ + "cc", + "log", + "objc2 0.6.4", + "objc2-foundation 0.3.2", + "time", + "uuid", +] + +[[package]] +name = "mach2" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a1b95cd5421ec55b445b5ae102f5ea0e768de1f82bd3001e11f426c269c3aea" +dependencies = [ + "libc", +] + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "maybe-rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", + "rayon", +] + +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + +[[package]] +name = "media" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed.git?rev=ce48461eaadd16c65c31f835511ab96bd3b6e746#ce48461eaadd16c65c31f835511ab96bd3b6e746" +dependencies = [ + "anyhow", + "bindgen", + "core-foundation 0.10.1", + "core-video", + "foreign-types", + "metal", + "objc", +] + +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "memmap2" +version = "0.9.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1219ed1b7f229ee7104d281dd01d6802fe28bb6e95d292942c4daacdeb798c0" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "metal" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7047791b5bc903b8cd963014b355f71dc9864a9a0b727057676c1dcae5cbc15" +dependencies = [ + "bitflags 2.13.1", + "block", + "core-graphics-types 0.2.0", + "foreign-types", + "log", + "objc", + "paste", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "miniz_oxide" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63fbc4a50860e98e7b2aa7804ded1db5cbc3aff9193adaff57a6931bf7c4b4c" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "moxcms" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" +dependencies = [ + "num-traits", + "pxfm", +] + +[[package]] +name = "naga" +version = "29.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2bf919621e7975acb27d881bae2fb993e0d45c8e0446e85e6272971e00dc8df" +dependencies = [ + "arrayvec", + "bit-set", + "bitflags 2.13.1", + "cfg-if", + "cfg_aliases", + "codespan-reporting", + "half", + "hashbrown 0.16.1", + "hexf-parse", + "indexmap", + "libm", + "log", + "num-traits", + "once_cell", + "rustc-hash 1.1.0", + "spirv", + "thiserror 2.0.20", + "unicode-ident", +] + +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys 0.3.1", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "no_std_io2" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418abd1b6d34fbf6cae440dc874771b0525a604428704c76e48b29a5e67b8003" +dependencies = [ + "memchr", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + +[[package]] +name = "notify-rust" +version = "4.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5b4c1b4f2aa9f25f63a7a49d3dd0ed567b3670da15330a66b29434be899b891" +dependencies = [ + "futures-lite", + "log", + "mac-notification-sys", + "serde", + "tauri-winrt-notification", + "zbus", +] + +[[package]] +name = "ntapi" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3b335231dfd352ffb0f8017f3b6027a4917f7df785ea2143d8af2adc66980ae" +dependencies = [ + "winapi", +] + +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c89e69e7e0f03bea5ef08013795c25018e101932225a656383bd384495ecc367" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-bigint-dig" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7f9a86e097b0d187ad0e65667c2f58b9254671e86e7dbb78036b16692eae099" +dependencies = [ + "libm", + "num-integer", + "num-iter", + "num-traits", + "once_cell", + "rand 0.9.5", + "serde", + "smallvec", + "zeroize", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "bytemuck", + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "num-integer" +version = "0.1.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ce2d95d4b3734dc35aa2f45e1aa22cd416814592a4f9d9205e11affd5b8e10b" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92800bd69a1eac91786bcfe9da64a897eb72911b8dc3095decbd07429e8048b" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_cpus" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", + "objc_exception", +] + +[[package]] +name = "objc-foundation" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" +dependencies = [ + "block", + "objc", + "objc_id", +] + +[[package]] +name = "objc-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" + +[[package]] +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys", + "objc2-encode", +] + +[[package]] +name = "objc2" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.13.1", + "block2 0.5.1", + "libc", + "objc2 0.5.2", + "objc2-core-data", + "objc2-core-image", + "objc2-foundation 0.2.2", + "objc2-quartz-core 0.2.2", +] + +[[package]] +name = "objc2-app-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.13.1", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags 2.13.1", + "dispatch2", + "objc2 0.6.4", +] + +[[package]] +name = "objc2-core-image" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal 0.2.2", +] + +[[package]] +name = "objc2-core-location" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca347214e24bc973fc025fd0d36ebb179ff30536ed1f80252706db19ee452009" +dependencies = [ + "objc2 0.6.4", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.13.1", + "block2 0.5.1", + "libc", + "objc2 0.5.2", +] + +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "libc", + "objc2 0.6.4", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.13.1", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-metal" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0125f776a10d00af4152d74616409f0d4a2053a6f57fa5b7d6aa2854ac04794" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "objc2 0.6.4", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.13.1", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal 0.2.2", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" +dependencies = [ + "bitflags 2.13.1", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "objc2-metal 0.3.2", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9df9128cbbfef73cda168416ccf7f837b62737d748333bfe9ab71c245d76613e" +dependencies = [ + "bitflags 2.13.1", + "block2 0.6.2", + "objc2 0.6.4", + "objc2-core-location", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc_exception" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" +dependencies = [ + "cc", +] + +[[package]] +name = "objc_id" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" +dependencies = [ + "objc", +] + +[[package]] +name = "object" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "oo7" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78f2bfed90f1618b4b48dcad9307f25e14ae894e2949642c87c351601d62cebd" +dependencies = [ + "aes", + "ashpd", + "async-fs", + "async-io", + "async-lock", + "blocking", + "cbc", + "cipher", + "digest", + "endi", + "futures-lite", + "futures-util", + "getrandom 0.4.3", + "hkdf", + "hmac", + "md-5", + "num", + "num-bigint-dig", + "pbkdf2", + "serde", + "serde_bytes", + "sha2", + "subtle", + "zbus", + "zbus_macros", + "zeroize", + "zvariant", +] + +[[package]] +name = "open" +version = "5.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade3be4664bc1ef537ce133015f04c176b737815c2ba9fd60edf212d6e90dd55" +dependencies = [ + "is-wsl", + "libc", +] + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "ordered-float" +version = "5.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c7c9e0d9b23589f26070720bac724174bfec1083e82f7854cdd0267518343c0" +dependencies = [ + "num-traits", +] + +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link 0.2.1", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pastey" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec" + +[[package]] +name = "pathfinder_geometry" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b7e7b4ea703700ce73ebf128e1450eb69c3a8329199ffbfb9b2a0418e5ad3" +dependencies = [ + "log", + "pathfinder_simd", +] + +[[package]] +name = "pathfinder_simd" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4500030c302e4af1d423f36f3b958d1aecb6c04184356ed5a833bf6b60435777" +dependencies = [ + "rustc_version", +] + +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest", + "hmac", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "perf" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed.git?rev=ce48461eaadd16c65c31f835511ab96bd3b6e746#ce48461eaadd16c65c31f835511ab96bd3b6e746" +dependencies = [ + "collections", + "serde", + "serde_json", +] + +[[package]] +name = "phf" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" +dependencies = [ + "phf_macros", + "phf_shared", + "serde", +] + +[[package]] +name = "phf_generator" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" +dependencies = [ + "fastrand", + "phf_shared", +] + +[[package]] +name = "phf_macros" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "phf_shared" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pico-args" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" + +[[package]] +name = "pin-project" +version = "1.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "piper" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + +[[package]] +name = "pkg-config" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548" + +[[package]] +name = "png" +version = "0.17.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide 0.8.9", +] + +[[package]] +name = "png" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" +dependencies = [ + "bitflags 2.13.1", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide 0.8.9", +] + +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix", + "windows-sys 0.61.2", +] + +[[package]] +name = "pollster" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5da3b0203fd7ee5720aa0b5e790b591aa5d3f41c3ed2c34a3a393382198af2f7" + +[[package]] +name = "pollster" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3" + +[[package]] +name = "polycool" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50596ddc09eb5ad5f75cacd40209568e66df71baf86e1499a0e99c4cff12a5a6" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "portable-atomic" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85" + +[[package]] +name = "portable-atomic-util" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "postage" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af3fb618632874fb76937c2361a7f22afd393c982a2165595407edc75b06d3c1" +dependencies = [ + "atomic", + "crossbeam-queue", + "futures", + "log", + "parking_lot", + "pin-project", + "pollster 0.2.5", + "static_assertions", + "thiserror 1.0.69", +] + +[[package]] +name = "potential_utf" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d83eb9bc6d8e5cf568e7a1101d60ee05e81ed50ea106026f3d18deeb046d7661" +dependencies = [ + "zerovec", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "presser" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.119", +] + +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit 0.25.13+spec-1.1.0", +] + +[[package]] +name = "proc-macro2" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "profiling" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d595e54a326bc53c1c197b32d295e14b169e3cfeaa8dc82b529f947fba6bcf5" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4488a4a36b9a4ba6b9334a32a39971f77c1436ec82c38707bce707699cc3bbcb" +dependencies = [ + "quote", + "syn 2.0.119", +] + +[[package]] +name = "pulp" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "046aa45b989642ec2e4717c8e72d677b13edd831a4d3b6cf37d9a3e54912496a" +dependencies = [ + "bytemuck", + "cfg-if", + "libm", + "num-complex", + "paste", + "pulp-wasm-simd-flag", + "raw-cpuid", + "reborrow", + "version_check", +] + +[[package]] +name = "pulp-wasm-simd-flag" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d8f70e07b9c3962945a74e59ca1c511bba65b6419468acc217c457d93f3c740" + +[[package]] +name = "pxfm" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d55d956fa96f5ec02be2e13af0e20391a5aa83d6a074e3ad368959d0fab299ea" + +[[package]] +name = "qoi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + +[[package]] +name = "quick-xml" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e660451e55124f798a69a5af3f49ccfbefbd41910eefd25caf2393e1f3473ec1" +dependencies = [ + "memchr", +] + +[[package]] +name = "quote" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "rand" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e058c7de0b26af77780c769414d6257830bb240f3c38477dbc2c16e5f54d6d4c" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.17", +] + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "range-alloc" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca45419789ae5a7899559e9512e58ca889e41f04f1f2445e9f4b290ceccd1d08" + +[[package]] +name = "rangemap" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a611d15b50743feb4c76b7d03edcb0e64f399c26961e4efe6975bc398be6aa3d" + +[[package]] +name = "rav1e" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b6dd56e85d9483277cde964fd1bdb0428de4fec5ebba7540995639a21cb32b" +dependencies = [ + "aligned-vec", + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av-scenechange", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools 0.14.0", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "paste", + "profiling", + "rand 0.9.5", + "rand_chacha 0.9.0", + "simd_helpers", + "thiserror 2.0.20", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e52310197d971b0f5be7fe6b57530dcd27beb35c1b013f29d66c1ad73fbbcc45" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rayon", + "rgb", +] + +[[package]] +name = "raw-cpuid" +version = "11.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" +dependencies = [ + "bitflags 2.13.1", +] + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[package]] +name = "raw-window-metal" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40d213455a5f1dc59214213c7330e074ddf8114c9a42411eb890c767357ce135" +dependencies = [ + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "objc2-quartz-core 0.3.2", +] + +[[package]] +name = "rayon" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "read-fonts" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b634fabf032fab15307ffd272149b622260f55974d9fad689292a5d33df02e5" +dependencies = [ + "bytemuck", + "core_maths", + "font-types 0.11.3", +] + +[[package]] +name = "read-fonts" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "046a7d674daf459825b32f5062056d6882db0d2f5a479fbd76ccfc870ac18709" +dependencies = [ + "bytemuck", + "font-types 0.12.4", + "once_cell", +] + +[[package]] +name = "reborrow" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03251193000f4bd3b042892be858ee50e8b3719f2b08e5833ac4353724632430" + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.13.1", +] + +[[package]] +name = "redox_users" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" +dependencies = [ + "getrandom 0.2.17", + "libredox", + "thiserror 2.0.20", +] + +[[package]] +name = "ref-cast" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e440fb4e4b4147295338efb76001ab9e4efc0e5839df2c47fc5ac2381d365c3" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecd8964f8453721699a1ed72037b0db49ce2f5a5138486ee89bed6f67cdf3a" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.4", +] + +[[package]] +name = "refineable" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed.git?rev=ce48461eaadd16c65c31f835511ab96bd3b6e746#ce48461eaadd16c65c31f835511ab96bd3b6e746" +dependencies = [ + "derive_refineable", +] + +[[package]] +name = "regex" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + +[[package]] +name = "renderdoc-sys" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" + +[[package]] +name = "resvg" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b563218631706d614e23059436526d005b50ab5f2d506b55a17eb65c5eb83419" +dependencies = [ + "gif", + "image-webp", + "log", + "pico-args", + "rgb", + "svgtypes", + "tiny-skia", + "usvg", + "zune-jpeg", +] + +[[package]] +name = "rgb" +version = "0.8.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "roxmltree" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" + +[[package]] +name = "roxmltree" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1964b10c76125c36f8afe190065a4bf9a87bf324842c05701330bba9f1cacbb" +dependencies = [ + "memchr", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b74b56ffa8bb2830709a538c2cbcae9aa062db0d2a42563bfb09bdaae44020eb" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hash" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags 2.13.1", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustversion" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" + +[[package]] +name = "rustybuzz" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd3c7c96f8a08ee34eff8857b11b49b07d71d1c3f4e88f8a88d4c9e9f90b1702" +dependencies = [ + "bitflags 2.13.1", + "bytemuck", + "core_maths", + "log", + "smallvec", + "ttf-parser", + "unicode-bidi-mirroring", + "unicode-ccc", + "unicode-properties", + "unicode-script", +] + +[[package]] +name = "ryu" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scheduler" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed.git?rev=ce48461eaadd16c65c31f835511ab96bd3b6e746#ce48461eaadd16c65c31f835511ab96bd3b6e746" +dependencies = [ + "async-task", + "backtrace", + "chrono", + "flume", + "futures", + "parking_lot", + "rand 0.9.5", + "wasm_thread", + "web-time", +] + +[[package]] +name = "schemars" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "687274d293b6cdc6e73e0fee520bf2049650090d7164f87672d212a3c530cf4a" +dependencies = [ + "dyn-clone", + "indexmap", + "ref-cast", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98c67716b46af2f0b8cf752abc930f6f9aecfbf671ecfb531db8a31dbe4e2ba" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 3.0.4", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "screencapturekit" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5eeeb57ac94960cfe5ff4c402be6585ae4c8d29a2cf41b276048c2e849d64e" +dependencies = [ + "screencapturekit-sys", +] + +[[package]] +name = "screencapturekit-sys" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22411b57f7d49e7fe08025198813ee6fd65e1ee5eff4ebc7880c12c82bde4c60" +dependencies = [ + "block", + "dispatch", + "objc", + "objc-foundation", + "objc_id", + "once_cell", +] + +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + +[[package]] +name = "self_cell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab42ca02749e120097e328d91d415325bdf43b1c72c4c8badf37375fe40a813" + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "serde" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_bytes" +version = "0.11.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.4", +] + +[[package]] +name = "serde_derive_internals" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f852137cce035d6a4df67ccce505ff6b3e9fd3a10e3e52b24dc71e650bb1a9bd" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.4", +] + +[[package]] +name = "serde_fmt" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e497af288b3b95d067a23a4f749f2861121ffcb2f6d8379310dcda040c345ed" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_json" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +dependencies = [ + "indexmap", + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_repr" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d3b1629de253c70a0508c3899572da79ca359fdab27c7920ff00406df418906" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.4", +] + +[[package]] +name = "serde_spanned" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_spanned" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha1_smol" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + +[[package]] +name = "simd-adler32" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea" + +[[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] + +[[package]] +name = "simplecss" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a9c6883ca9c3c7c90e888de77b7a5c849c779d25d74a1269b0218b14e8b136c" +dependencies = [ + "log", +] + +[[package]] +name = "siphasher" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" + +[[package]] +name = "skrifa" +version = "0.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fbdfe3d2475fbd7ddd1f3e5cf8288a30eb3e5f95832829570cd88115a7434ac" +dependencies = [ + "bytemuck", + "read-fonts 0.37.0", +] + +[[package]] +name = "skrifa" +version = "0.44.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819ab7d62b1d3e72d9d9dea5650bac30424f9111364bb94928dbf5ecad1baa68" +dependencies = [ + "bytemuck", + "read-fonts 0.41.0", +] + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "slotmap" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" +dependencies = [ + "version_check", +] + +[[package]] +name = "smallvec" +version = "1.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" + +[[package]] +name = "smol" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33bd3e260892199c3ccfc487c88b2da2265080acb316cd920da72fdfd7c599f" +dependencies = [ + "async-channel", + "async-executor", + "async-fs", + "async-io", + "async-lock", + "async-net", + "async-process", + "blocking", + "futures-lite", +] + +[[package]] +name = "smol_str" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aaa7368fcf4852a4c2dd92df0cace6a71f2091ca0a23391ce7f3a31833f1523" +dependencies = [ + "borsh", + "serde_core", +] + +[[package]] +name = "spin" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3763264f6b73151db08c50ff20d7d8a0b8796e021cdea7ceedad07b80155fa0e" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spin" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "023a211cb3138dbc438680b32560ad89f699977624c9f8dbb95a47d5b4c07dd3" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spirv" +version = "0.4.0+sdk-1.4.341.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9571ea910ebd84c86af4b3ed27f9dbdc6ad06f17c5f96146b2b671e2976744f" +dependencies = [ + "bitflags 2.13.1", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strict-num" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" +dependencies = [ + "float-cmp", +] + +[[package]] +name = "strum" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "sum_tree" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed.git?rev=ce48461eaadd16c65c31f835511ab96bd3b6e746#ce48461eaadd16c65c31f835511ab96bd3b6e746" +dependencies = [ + "heapless", + "log", + "rayon", + "tracing", + "ztracing", +] + +[[package]] +name = "sval" +version = "2.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b81b254da21fe1fcc4e3a74fe39b46e25e3a863078f8b71c954d47f84889dbc6" + +[[package]] +name = "sval_buffer" +version = "2.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50be352d2822ffafb59e3e2ddac9d5ee60f2eeadbb7b5a2a951b9f3651e87a6f" +dependencies = [ + "sval", + "sval_ref", + "zerocopy", +] + +[[package]] +name = "sval_dynamic" +version = "2.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048ca293b998d9a45659159f94a64063791e74cdc670164943dbb434405573d" +dependencies = [ + "sval", +] + +[[package]] +name = "sval_fmt" +version = "2.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6b5888e40f80568733217f27b7317b845f463400ced36c424b1a804730e53b2" +dependencies = [ + "itoa", + "ryu", + "sval", +] + +[[package]] +name = "sval_json" +version = "2.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17664d6bb6b74947afaab9d7c991caa9bf5638d4dee16fcbef637f440796049" +dependencies = [ + "itoa", + "ryu", + "sval", +] + +[[package]] +name = "sval_nested" +version = "2.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07c059969ca5ca163ea7fef6c9661758973d17691aba92abdcf5c428f4ec122c" +dependencies = [ + "sval", + "sval_buffer", + "sval_ref", +] + +[[package]] +name = "sval_ref" +version = "2.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d6b29ff568c85c87561807f51d2adfff4b6016c6363133f7cd1652a12548f3" +dependencies = [ + "sval", +] + +[[package]] +name = "sval_serde" +version = "2.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f33ec9edc42b12764d5c90ca0a1d84189c6bde81ed27507f1e661c6e4e05853" +dependencies = [ + "serde_core", + "sval", + "sval_nested", +] + +[[package]] +name = "svg_fmt" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0193cc4331cfd2f3d2011ef287590868599a2f33c3e69bc22c1a3d3acf9e02fb" + +[[package]] +name = "svgtypes" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "695b5790b3131dafa99b3bbfd25a216edb3d216dad9ca208d4657bfb8f2abc3d" +dependencies = [ + "kurbo", + "siphasher", +] + +[[package]] +name = "swash" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c2499c2d826531388872b2268718aed907a39bd785ab0dcfe57fab26283f92e" +dependencies = [ + "skrifa 0.44.0", + "yazi", + "zeno", +] + +[[package]] +name = "syn" +version = "2.0.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6275cddf4610d1775e6d1fe9469b2e77d0f39fd98fb7450901b821e0c53649f" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "sys-locale" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eab9a99a024a169fe8a903cf9d4a3b3601109bcc13bd9e3c6fff259138626c4" +dependencies = [ + "libc", +] + +[[package]] +name = "sysinfo" +version = "0.31.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "355dbe4f8799b304b05e1b0f05fc59b2a18d36645cf169607da45bde2f69a1be" +dependencies = [ + "core-foundation-sys", + "libc", + "memchr", + "ntapi", + "rayon", + "windows 0.57.0", +] + +[[package]] +name = "taffy" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c034e05f6ee85a12daa63863c2245797715075c70649947aa0da54f3f2ab1d0f" +dependencies = [ + "arrayvec", + "serde", + "slotmap", + "smallvec", +] + +[[package]] +name = "tao-core-video-sys" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271450eb289cb4d8d0720c6ce70c72c8c858c93dd61fc625881616752e6b98f6" +dependencies = [ + "cfg-if", + "core-foundation-sys", + "libc", + "objc", +] + +[[package]] +name = "tauri-winrt-notification" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed071c670382e85fc2f48ae706492d8c338f4f89bf72520d32f8abfe880aade" +dependencies = [ + "thiserror 2.0.20", + "windows 0.61.3", + "windows-version", +] + +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom 0.4.3", + "once_cell", + "rustix", + "windows-sys 0.61.2", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" +dependencies = [ + "thiserror-impl 2.0.20", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.4", +] + +[[package]] +name = "thread_local" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad99c4c6d32803332c548b1af0540b357b3f5fc0be8f6c6bfe8b2e6ae784070" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "tiff" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63feaf3343d35b6ca4d50483f94843803b0f51634937cc2ec519fc32232bc52" +dependencies = [ + "fax", + "flate2", + "half", + "quick-error", + "weezl", + "zune-jpeg", +] + +[[package]] +name = "time" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb87b95ec50ddfa440816d227a17b2ccbdda963a316a727fda0fc4334f7d134" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "serde_core", + "time-core", +] + +[[package]] +name = "time-core" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tiny-skia" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" +dependencies = [ + "arrayref", + "arrayvec", + "bytemuck", + "cfg-if", + "log", + "png 0.17.16", + "tiny-skia-path", +] + +[[package]] +name = "tiny-skia-path" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" +dependencies = [ + "arrayref", + "bytemuck", + "strict-num", +] + +[[package]] +name = "tinystr" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e27c91459209c2986af3dcf603a5a74a4368754ce37414f59acc971167f643" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "toml" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" +dependencies = [ + "serde", + "serde_spanned 0.6.9", + "toml_datetime 0.6.11", + "toml_edit 0.22.27", +] + +[[package]] +name = "toml" +version = "1.1.4+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3aace63f4bbcdfc2c965b059de67119c89c4017a70d633be6c104910f67056f5" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned 1.1.1", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "toml_writer", + "winnow 1.0.4", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap", + "serde", + "serde_spanned 0.6.9", + "toml_datetime 0.6.11", + "toml_write", + "winnow 0.7.15", +] + +[[package]] +name = "toml_edit" +version = "0.25.13+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6975367e4d2ef766d86af01ffad14b622fecc8d4357a998fbc4deb6e9bacaf9b" +dependencies = [ + "indexmap", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "winnow 1.0.4", +] + +[[package]] +name = "toml_parser" +version = "1.1.3+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" +dependencies = [ + "winnow 1.0.4", +] + +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + +[[package]] +name = "toml_writer" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2" + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" +dependencies = [ + "nu-ansi-term", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "ttf-parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" +dependencies = [ + "core_maths", +] + +[[package]] +name = "typeid" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" + +[[package]] +name = "typenum" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + +[[package]] +name = "uds_windows" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e" +dependencies = [ + "memoffset", + "tempfile", + "windows-sys 0.61.2", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" + +[[package]] +name = "unicode-bidi-mirroring" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfa6e8c60bb66d49db113e0125ee8711b7647b5579dc7f5f19c42357ed039fe" + +[[package]] +name = "unicode-ccc" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce61d488bcdc9bc8b5d1772c404828b17fc481c0a582b5581e95fb233aef503e" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-linebreak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" + +[[package]] +name = "unicode-properties" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" + +[[package]] +name = "unicode-script" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "383ad40bb927465ec0ce7720e033cb4ca06912855fc35db31b5755d0de75b1ee" + +[[package]] +name = "unicode-segmentation" +version = "1.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" + +[[package]] +name = "unicode-vo" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d386ff53b415b7fe27b50bb44679e2cc4660272694b7b6f3326d8480823a94" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "url" +version = "2.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "usvg" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e419dff010bb12512b0ae9e3d2f318dfbdf0167fde7eb05465134d4e8756076f" +dependencies = [ + "base64", + "data-url", + "flate2", + "fontdb", + "imagesize", + "kurbo", + "log", + "pico-args", + "roxmltree 0.21.1", + "rustybuzz", + "simplecss", + "siphasher", + "strict-num", + "svgtypes", + "tiny-skia-path", + "unicode-bidi", + "unicode-script", + "unicode-vo", + "xmlwriter", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "util_macros" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed.git?rev=ce48461eaadd16c65c31f835511ab96bd3b6e746#ce48461eaadd16c65c31f835511ab96bd3b6e746" +dependencies = [ + "perf", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "uuid" +version = "1.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5772d71c9be8a8a6ac2117d949c5b224c1b72241bb611d9a3012edcf8af7812" +dependencies = [ + "getrandom 0.4.3", + "js-sys", + "serde_core", + "sha1_smol", + "wasm-bindgen", +] + +[[package]] +name = "v_frame" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2" +dependencies = [ + "aligned-vec", + "num-traits", + "wasm-bindgen", +] + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "value-bag" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "068e763e8279de7ab94b6afebded2cb701678af094feb1c12ccb061b4783c1be" +dependencies = [ + "value-bag-serde1", + "value-bag-sval2", +] + +[[package]] +name = "value-bag-serde1" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27780e3aec98b13ac796bc0d5770205ee6e976d1ccb33a52da70b73ff0ff880d" +dependencies = [ + "erased-serde", + "serde_core", + "serde_fmt", +] + +[[package]] +name = "value-bag-sval2" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c093d229c7ead9974b640e61170976e0eff3dac447cf6792c645f0b7f28b3de" +dependencies = [ + "sval", + "sval_buffer", + "sval_dynamic", + "sval_fmt", + "sval_json", + "sval_ref", + "sval_serde", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "vswhom" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be979b7f07507105799e854203b470ff7c78a1639e330a58f183b5fea574608b" +dependencies = [ + "libc", + "vswhom-sys", +] + +[[package]] +name = "vswhom-sys" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb067e4cbd1ff067d1df46c9194b5de0e98efd2810bbc95c5d5e5f25a3231150" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "waker-fn" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.4+wasi-0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.127" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b7777d5cc23d0e91404e53ce2d5e8ec7acae3026b16233dba62cd3246457950" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.127" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.127" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.119", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.127" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm_thread" +version = "0.3.3" +source = "git+https://github.com/zed-industries/wasm_thread?rev=0cf96c7708dfb97ccf3da50347e25edcf75d6937#0cf96c7708dfb97ccf3da50347e25edcf75d6937" +dependencies = [ + "futures", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wayland-backend" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38a91b4eaddff87b1cd1074985e3713da4af2c49742d1b356b2c01670a67a078" +dependencies = [ + "cc", + "downcast-rs", + "rustix", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c36a0f861ad76d0901f2800b46321410d9f73f2ea88aac0650d86c32688073" +dependencies = [ + "bitflags 2.13.1", + "rustix", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-cursor" +version = "0.31.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a52d18780be9b1314328a3de5f930b73d2200112e3849ca6cb11822793fb34d" +dependencies = [ + "rustix", + "wayland-client", + "xcursor", +] + +[[package]] +name = "wayland-protocols" +version = "0.32.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d0c813de3daa2ed6520af85a3bd49b0e722a3078506899aa9686fea58dc4b6" +dependencies = [ + "bitflags 2.13.1", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-plasma" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b6d8cf1eb2c1c31ed1f5643c88a6e53538129d4af80030c8cabd1f9fa884d91" +dependencies = [ + "bitflags 2.13.1", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-wlr" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb04e52f7836d7c7976c78ca0250d61e33873c34156a2a1fc9474828ec268234" +dependencies = [ + "bitflags 2.13.1", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "338e30461b3a2b67d70eb30a6d89f8e0c93a833e07d2ae89085cd070c4a00ac0" +dependencies = [ + "proc-macro2", + "quick-xml", + "quote", +] + +[[package]] +name = "wayland-sys" +version = "0.31.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8eab23fefc9e41f8e841df4a9c707e8a8c4ed26e944ef69297184de2785e3be" +dependencies = [ + "dlib", + "log", + "once_cell", + "pkg-config", +] + +[[package]] +name = "web-sys" +version = "0.3.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c435338968042f4f59a557f690a253676d47ce13ceb55d70100e7facf6620a30" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "weezl" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" + +[[package]] +name = "wgpu" +version = "29.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76e8840e1ba2881d4cbb18d2147627a56af426ff064c0401eb0c8410c6325d07" +dependencies = [ + "arrayvec", + "bitflags 2.13.1", + "bytemuck", + "cfg-if", + "cfg_aliases", + "document-features", + "hashbrown 0.16.1", + "js-sys", + "log", + "naga", + "parking_lot", + "portable-atomic", + "profiling", + "raw-window-handle", + "smallvec", + "static_assertions", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "wgpu-core", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-core" +version = "29.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f519832254e56965a9940c4af57dcb75f702b6f6fa4a0b172f685395843a4d7" +dependencies = [ + "arrayvec", + "bit-set", + "bit-vec", + "bitflags 2.13.1", + "bytemuck", + "cfg_aliases", + "document-features", + "hashbrown 0.16.1", + "indexmap", + "log", + "naga", + "once_cell", + "parking_lot", + "portable-atomic", + "profiling", + "raw-window-handle", + "rustc-hash 1.1.0", + "smallvec", + "thiserror 2.0.20", + "wgpu-core-deps-apple", + "wgpu-core-deps-emscripten", + "wgpu-core-deps-wasm", + "wgpu-core-deps-windows-linux-android", + "wgpu-hal", + "wgpu-naga-bridge", + "wgpu-types", +] + +[[package]] +name = "wgpu-core-deps-apple" +version = "29.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5e39e26c4c0e07589e67d18546cf79ff45383659fc72fca4dd293358a0347f3" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-core-deps-emscripten" +version = "29.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01e09be551dc939498bdd5f6b2c66e55ab275dad25825267a08605a80fc9f0af" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-core-deps-wasm" +version = "29.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1fb1798be2a912497d4c224f72d39bb0cb34af50e8bcc29865bc339c943059" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-core-deps-windows-linux-android" +version = "29.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e592c1bbef6ad047647ae6e666ebd8cee7a32bb4544d9700ec96cbf73230257" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-hal" +version = "29.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97ace1c17727311c22a46e4e3faf56ea6de81af99dcc839bdfb54857b94d448d" +dependencies = [ + "android_system_properties", + "arrayvec", + "ash", + "bit-set", + "bitflags 2.13.1", + "block2 0.6.2", + "bytemuck", + "cfg-if", + "cfg_aliases", + "glow", + "glutin_wgl_sys", + "gpu-allocator", + "gpu-descriptor", + "hashbrown 0.16.1", + "js-sys", + "khronos-egl", + "libc", + "libloading", + "log", + "naga", + "ndk-sys", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "objc2-metal 0.3.2", + "objc2-quartz-core 0.3.2", + "once_cell", + "ordered-float", + "parking_lot", + "portable-atomic", + "portable-atomic-util", + "profiling", + "range-alloc", + "raw-window-handle", + "raw-window-metal", + "renderdoc-sys", + "smallvec", + "thiserror 2.0.20", + "wasm-bindgen", + "wayland-sys", + "web-sys", + "wgpu-naga-bridge", + "wgpu-types", + "windows 0.62.2", + "windows-core 0.62.2", + "windows-result 0.4.1", +] + +[[package]] +name = "wgpu-naga-bridge" +version = "29.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95226013f547544b223281cd16a4fb549aa9dcb562adbda0faae4c73ffbbc161" +dependencies = [ + "naga", + "wgpu-types", +] + +[[package]] +name = "wgpu-types" +version = "29.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84bf84cd9ca8ca45e2b223a3868f1adf9bfc0c66aeac212e76ee7e40fdadf8f5" +dependencies = [ + "bitflags 2.13.1", + "bytemuck", + "js-sys", + "log", + "raw-window-handle", + "web-sys", +] + +[[package]] +name = "which" +version = "8.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bae2f2b2b816647a1cab1acc91f5bd20812d53cb344382635ec2181940c8034f" +dependencies = [ + "libc", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" +dependencies = [ + "windows-core 0.57.0", + "windows-targets", +] + +[[package]] +name = "windows" +version = "0.61.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +dependencies = [ + "windows-collections 0.2.0", + "windows-core 0.61.2", + "windows-future 0.2.1", + "windows-link 0.1.3", + "windows-numerics 0.2.0", +] + +[[package]] +name = "windows" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" +dependencies = [ + "windows-collections 0.3.2", + "windows-core 0.62.2", + "windows-future 0.3.2", + "windows-numerics 0.3.1", +] + +[[package]] +name = "windows-capture" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a4df73e95feddb9ec1a7e9c2ca6323b8c97d5eeeff78d28f1eccdf19c882b24" +dependencies = [ + "parking_lot", + "rayon", + "thiserror 2.0.20", + "windows 0.61.3", + "windows-future 0.2.1", +] + +[[package]] +name = "windows-collections" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" +dependencies = [ + "windows-core 0.61.2", +] + +[[package]] +name = "windows-collections" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" +dependencies = [ + "windows-core 0.62.2", +] + +[[package]] +name = "windows-core" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" +dependencies = [ + "windows-implement 0.57.0", + "windows-interface 0.57.0", + "windows-result 0.1.2", + "windows-targets", +] + +[[package]] +name = "windows-core" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement 0.60.2", + "windows-interface 0.59.3", + "windows-link 0.1.3", + "windows-result 0.3.4", + "windows-strings 0.4.2", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement 0.60.2", + "windows-interface 0.59.3", + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", + "windows-threading 0.1.0", +] + +[[package]] +name = "windows-future" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" +dependencies = [ + "windows-core 0.62.2", + "windows-link 0.2.1", + "windows-threading 0.2.1", +] + +[[package]] +name = "windows-implement" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "windows-interface" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-numerics" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", +] + +[[package]] +name = "windows-numerics" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" +dependencies = [ + "windows-core 0.62.2", + "windows-link 0.2.1", +] + +[[package]] +name = "windows-registry" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" +dependencies = [ + "windows-link 0.1.3", + "windows-result 0.3.4", + "windows-strings 0.4.2", +] + +[[package]] +name = "windows-result" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows-threading" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-threading" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-version" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4060a1da109b9d0326b7262c8e12c84df67cc0dbc9e33cf49e01ccc2eb63631" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.55.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb5a765337c50e9ec252c2069be9bf91c7df47afb103b642ba3a53bf8101be97" +dependencies = [ + "cfg-if", + "windows-sys 0.59.0", +] + +[[package]] +name = "wio" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d129932f4644ac2396cb456385cbf9e63b5b30c6e8dc4820bdca4eb082037a5" +dependencies = [ + "winapi", +] + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "writeable" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc" + +[[package]] +name = "x11" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "502da5464ccd04011667b11c435cb992822c2c0dbde1770c988480d312a0db2e" +dependencies = [ + "libc", + "pkg-config", +] + +[[package]] +name = "x11-clipboard" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "662d74b3d77e396b8e5beb00b9cad6a9eccf40b2ef68cc858784b14c41d535a3" +dependencies = [ + "libc", + "x11rb", +] + +[[package]] +name = "x11rb" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414" +dependencies = [ + "as-raw-xcb-connection", + "gethostname", + "libc", + "rustix", + "x11rb-protocol", + "xcursor", +] + +[[package]] +name = "x11rb-protocol" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" + +[[package]] +name = "xcb" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6c2ad15e0e922856ee89afe862b8992334bbe7953adad56cd1199358cb30566" +dependencies = [ + "bitflags 2.13.1", + "libc", + "quick-xml", + "x11", +] + +[[package]] +name = "xcursor" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "163b33ed8786455e2fa5d72f554057ce3f3182425434f756cd39c99839d88e23" + +[[package]] +name = "xim-ctext" +version = "0.3.0" +source = "git+https://github.com/zed-industries/xim-rs.git?rev=16f35a2c881b815a2b6cdfd6687988e84f8447d8#16f35a2c881b815a2b6cdfd6687988e84f8447d8" +dependencies = [ + "encoding_rs", +] + +[[package]] +name = "xim-parser" +version = "0.2.1" +source = "git+https://github.com/zed-industries/xim-rs.git?rev=16f35a2c881b815a2b6cdfd6687988e84f8447d8#16f35a2c881b815a2b6cdfd6687988e84f8447d8" +dependencies = [ + "bitflags 2.13.1", +] + +[[package]] +name = "xkbcommon" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d66ca9352cbd4eecbbc40871d8a11b4ac8107cfc528a6e14d7c19c69d0e1ac9" +dependencies = [ + "as-raw-xcb-connection", + "libc", + "memmap2", + "xkeysym", +] + +[[package]] +name = "xkeysym" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" + +[[package]] +name = "xml-rs" +version = "0.8.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e450f9b2ed1dff33c94c12589a87338689467b9c4f5d8a5710bd09a847d2c8a7" + +[[package]] +name = "xmlwriter" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9" + +[[package]] +name = "y4m" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5a4b21e1a62b67a2970e6831bc091d7b87e119e7f9791aef9702e3bef04448" + +[[package]] +name = "yazi" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01738255b5a16e78bbb83e7fbba0a1e7dd506905cfc53f4622d89015a03fbb5" + +[[package]] +name = "yeslogic-fontconfig-sys" +version = "6.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d8b8abf912b9a29ff112e1671c97c33636903d13a69712037190e6805af4f76" +dependencies = [ + "dlib", + "once_cell", + "pkg-config", +] + +[[package]] +name = "yoke" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", + "synstructure", +] + +[[package]] +name = "zbus" +version = "5.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5db4be7c075cb421e4b7ee645541604239bd243ba7c357511f4ff3a74b555907" +dependencies = [ + "async-broadcast", + "async-executor", + "async-io", + "async-lock", + "async-process", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "enumflags2", + "event-listener", + "futures-core", + "futures-lite", + "hex", + "libc", + "ordered-stream", + "rustix", + "serde", + "serde_repr", + "tracing", + "uds_windows", + "uuid", + "windows-sys 0.61.2", + "winnow 1.0.4", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus-lockstep" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6998de05217a084b7578728a9443d04ea4cd80f2a0839b8d78770b76ccd45863" +dependencies = [ + "zbus_xml", + "zvariant", +] + +[[package]] +name = "zbus-lockstep-macros" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10da05367f3a7b7553c8cdf8fa91aee6b64afebe32b51c95177957efc47ca3a0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", + "zbus-lockstep", + "zbus_xml", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "5.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2990635d09ade6df1868f72f8cac69a876a90981e8bd3c40b1be413f8dc88f40" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 3.0.4", + "zbus_names", + "zvariant", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "4.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8bf88b4a3ff53e883001e0e0115b297a9d53c31b9c1edd2bfdd853e3428624e" +dependencies = [ + "serde", + "winnow 1.0.4", + "zvariant", +] + +[[package]] +name = "zbus_xml" +version = "5.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1586c021a01ca0a9216dcd874e546382e156a5cbab5fab6cb5f10087e22682a" +dependencies = [ + "serde", + "winnow 1.0.4", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zcheapstr" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1afec51604565183aeb5c54c20aeab286120d4e4460f7f76e3e8bb8c0d99473" +dependencies = [ + "serde", +] + +[[package]] +name = "zed-font-kit" +version = "0.14.1-zed" +source = "git+https://github.com/zed-industries/font-kit?rev=94b0f28166665e8fd2f53ff6d268a14955c82269#94b0f28166665e8fd2f53ff6d268a14955c82269" +dependencies = [ + "bitflags 2.13.1", + "byteorder", + "core-foundation 0.10.1", + "core-graphics 0.24.0", + "core-text", + "dirs", + "dwrote", + "float-ord", + "freetype-sys", + "lazy_static", + "libc", + "log", + "pathfinder_geometry", + "pathfinder_simd", + "walkdir", + "winapi", + "yeslogic-fontconfig-sys", +] + +[[package]] +name = "zed-scap" +version = "0.0.8-zed" +source = "git+https://github.com/zed-industries/scap?rev=4afea48c3b002197176fb19cd0f9b180dd36eaac#4afea48c3b002197176fb19cd0f9b180dd36eaac" +dependencies = [ + "anyhow", + "cocoa 0.25.0", + "core-graphics-helmer-fork", + "log", + "objc", + "rand 0.8.8", + "screencapturekit", + "screencapturekit-sys", + "sysinfo", + "tao-core-video-sys", + "windows 0.61.3", + "windows-capture", + "x11", + "xcb", +] + +[[package]] +name = "zed-xim" +version = "0.4.0-zed" +source = "git+https://github.com/zed-industries/xim-rs.git?rev=16f35a2c881b815a2b6cdfd6687988e84f8447d8#16f35a2c881b815a2b6cdfd6687988e84f8447d8" +dependencies = [ + "ahash", + "hashbrown 0.14.5", + "log", + "x11rb", + "xim-ctext", + "xim-parser", +] + +[[package]] +name = "zeno" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6df3dc4292935e51816d896edcd52aa30bc297907c26167fec31e2b0c6a32524" + +[[package]] +name = "zerocopy" +version = "0.8.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "556764e583adb45a9f8d413c2a147fa7e8d821e48e12b14fd560b607998b75eb" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2ab42fc20575779bd240faa45f94a74256f755c0fa9e89f0ede20d91d0cdfc1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "zerofrom" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "zerotrie" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea269c3bd32f0a32c321907a2ae912ba6f4649bb0fc764a15627e99a7095a3f" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0464e17806c1d976d5cba29399c7f08e516e279e2ba493f63123b5fca67dd8" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34df6fc39dbd26ddc9c10e6a2984476e13acce22e64e4487636ef494369225da" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.4", +] + +[[package]] +name = "zlib-rs" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34b31d188d9d685a4f9c7b46d6e36631b07058d2cfe190267adce54dc230bf12" + +[[package]] +name = "zlog" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed.git?rev=ce48461eaadd16c65c31f835511ab96bd3b6e746#ce48461eaadd16c65c31f835511ab96bd3b6e746" +dependencies = [ + "anyhow", + "chrono", + "collections", + "log", +] + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" + +[[package]] +name = "ztracing" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed.git?rev=ce48461eaadd16c65c31f835511ab96bd3b6e746#ce48461eaadd16c65c31f835511ab96bd3b6e746" +dependencies = [ + "tracing", + "tracing-subscriber", + "zlog", + "ztracing_macro", +] + +[[package]] +name = "ztracing_macro" +version = "0.1.0" +source = "git+https://github.com/zed-industries/zed.git?rev=ce48461eaadd16c65c31f835511ab96bd3b6e746#ce48461eaadd16c65c31f835511ab96bd3b6e746" + +[[package]] +name = "zune-core" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d56377fd46368984a170bc5aac5567e52ca5da874caa60bea39fcbca78fb658b" + +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "zune-jpeg" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296" +dependencies = [ + "zune-core", +] + +[[package]] +name = "zvariant" +version = "5.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1d34c27cc6cdd1f458427519dd6b8612f7b7e3f7b9a0b2355d041dda9869147" +dependencies = [ + "endi", + "enumflags2", + "serde", + "serde_bytes", + "winnow 1.0.4", + "zcheapstr", + "zvariant_derive", + "zvariant_utils", +] + +[[package]] +name = "zvariant_derive" +version = "5.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "864155e69b4352db0c7f374917bf45d1e0c8d17659c8b3dbf9795f3673f8c497" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 3.0.4", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad0294361a320b694a328460dc73add56c306150f5cb6bfafc44446120008a3" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "syn 3.0.4", + "winnow 1.0.4", +] diff --git a/spikes/gpui-accessibility-probe/Cargo.toml b/spikes/gpui-accessibility-probe/Cargo.toml new file mode 100644 index 0000000..9d82bb2 --- /dev/null +++ b/spikes/gpui-accessibility-probe/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "lumbridge-spike-gpui-accessibility" +description = "Isolated proof of current GPUI accessibility and IME input for Lumbridge" +version = "0.0.1" +edition = "2024" +rust-version = "1.97.1" +license = "Apache-2.0" +publish = false + +[dependencies] +gpui = { git = "https://github.com/zed-industries/zed.git", rev = "ce48461eaadd16c65c31f835511ab96bd3b6e746", default-features = false, features = ["wayland", "x11"] } +gpui_platform = { git = "https://github.com/zed-industries/zed.git", rev = "ce48461eaadd16c65c31f835511ab96bd3b6e746", default-features = false, features = ["font-kit", "wayland", "x11"] } + +[workspace] diff --git a/spikes/gpui-accessibility-probe/README.md b/spikes/gpui-accessibility-probe/README.md new file mode 100644 index 0000000..d1e4610 --- /dev/null +++ b/spikes/gpui-accessibility-probe/README.md @@ -0,0 +1,83 @@ +# GPUI accessibility and input probe + +This independent workspace answers one narrow question: can the GPUI version +currently used by Zed expose the minimum semantic tree Lumbridge needs for a +workspace and terminal pane, while accepting real platform IME input? + +## Reproducibility + +- Upstream: `https://github.com/zed-industries/zed` +- Commit: `ce48461eaadd16c65c31f835511ab96bd3b6e746` +- GPUI license at this commit: Apache-2.0 +- Rust: 1.97.1, matching the upstream `rust-toolchain.toml` + +Both `gpui` and `gpui_platform` are pinned to the full commit. This directory is +an independent Cargo workspace, so its toolchain and dependency graph do not +change Lumbridge's root MSRV or release graph. + +## Semantics under test + +The rendered tree contains: + +- an application named `Lumbridge accessibility probe`; +- a stable, externally identifiable `Region` named `Lumbridge workspace`; +- a stable, focusable `Pane` named `Local terminal pane`; +- `selected = true` on the pane; +- real GPUI keyboard focus tracked on the pane; +- the description `Needs input: choose whether to run the proposed command`; +- a `Terminal` child named `Terminal output` for the pane's content. + +Current GPUI exposes these through its AccessKit integration using `role`, +`accessibility_id`, `aria_label`, `aria_description`, `aria_selected`, +`focusable`, and `track_focus`. The deterministic unit test checks the exact +AccessKit role and properties. The binary compile-checks GPUI's element wiring; +a platform screen reader remains necessary for end-to-end AT-SPI/VoiceOver +validation. + +## Input and IME proof + +The focused pane also installs a real `ElementInputHandler` +during element paint. `ImeTextReceiver` implements GPUI's +`EntityInputHandler`, including text queries, UTF-16 selection, marked-text +composition, replacement, unmarking, selection updates, editable length, and +IME candidate bounds. This is the code path GPUI's platform adapters call for +composed operating-system text input. + +The backing buffer stores UTF-8 only at valid scalar boundaries and translates +the platform's UTF-16 ranges before mutation. Deterministic tests cover: + +- replacing a selected decomposed `e` plus combining acute accent with `é`; +- a marked decomposed-accent IME composition and commit; +- inserting, selecting, and replacing the multi-codepoint grapheme `👩🏽‍💻`; +- collapsed selection placement after every replacement. + +These tests prove range conversion and composed-text preservation without +splitting UTF-8. An actual keyboard IME on X11/Wayland and macOS remains an +end-to-end platform test, not a unit-test claim. + +## Commands + +```bash +cargo check --locked +cargo test --locked +cargo clippy --locked --all-targets -- -D warnings +``` + +The first command installs the pinned Rust toolchain if rustup does not already +have it and downloads Zed's GPUI dependency closure. + +On Ubuntu hosts that have only the runtime libraries, checks work with +`RUST_FONTCONFIG_DLOPEN=1`. Linking a test or binary additionally needs the +unversioned linker names normally installed by `libxcb1-dev`, +`libxkbcommon-dev`, and `libxkbcommon-x11-dev`. The amd-server validation used +temporary symlinks under the ignored `target/native-libs` directory and set +`LIBRARY_PATH` to that directory; no system packages or root files changed. + +## Observed local cost + +On amd-server, the first successful check required roughly 90 seconds after +installing/fetching, with some Cargo-cache contention from concurrent work. The +lockfile contains 691 packages. After check, test, Clippy, and a debug build, +the isolated target directory was 4.4 GiB and the debug binary was 535 MiB. The +minimal Rust 1.97.1 toolchain occupies 624 MiB. These are development costs, not +optimized release measurements. diff --git a/spikes/gpui-accessibility-probe/rust-toolchain.toml b/spikes/gpui-accessibility-probe/rust-toolchain.toml new file mode 100644 index 0000000..3caff2a --- /dev/null +++ b/spikes/gpui-accessibility-probe/rust-toolchain.toml @@ -0,0 +1,4 @@ +[toolchain] +channel = "1.97.1" +profile = "minimal" +components = ["clippy", "rustfmt"] diff --git a/spikes/gpui-accessibility-probe/src/main.rs b/spikes/gpui-accessibility-probe/src/main.rs new file mode 100644 index 0000000..580d83b --- /dev/null +++ b/spikes/gpui-accessibility-probe/src/main.rs @@ -0,0 +1,486 @@ +use std::ops::Range; + +use gpui::{ + App, Bounds, ClipboardItem, Context, Element, ElementId, ElementInputHandler, Entity, + EntityInputHandler, FocusHandle, GlobalElementId, LayoutId, Pixels, Point, Role, Style, + UTF16Selection, Window, WindowBounds, WindowOptions, div, prelude::*, px, relative, rgb, size, + text, +}; +use gpui_platform::application; + +const WORKSPACE_LABEL: &str = "Lumbridge workspace"; +const PANE_LABEL: &str = "Local terminal pane"; +const PANE_DESCRIPTION: &str = "Needs input: choose whether to run the proposed command"; +const PANE_ACCESSIBILITY_ID: &str = "lumbridge.pane.local-terminal"; + +struct AccessibilityProbe { + pane_focus: FocusHandle, + input: Entity, +} + +impl AccessibilityProbe { + fn new(window: &mut Window, cx: &mut Context) -> Self { + let pane_focus = cx.focus_handle().tab_stop(true); + window.focus(&pane_focus, cx); + Self { + pane_focus, + input: cx.new(|_| ImeTextReceiver::default()), + } + } +} + +#[derive(Clone, Copy)] +enum BoundaryBias { + Floor, + Ceil, +} + +#[derive(Debug, Default, PartialEq, Eq)] +struct TextBuffer { + text: String, + selection: Range, + marked: Option>, +} + +impl TextBuffer { + fn utf16_to_utf8(text: &str, offset: usize, bias: BoundaryBias) -> usize { + let mut utf16_offset = 0; + + for (utf8_offset, character) in text.char_indices() { + if utf16_offset == offset { + return utf8_offset; + } + + let next_utf16 = utf16_offset + character.len_utf16(); + if offset < next_utf16 { + return match bias { + BoundaryBias::Floor => utf8_offset, + BoundaryBias::Ceil => utf8_offset + character.len_utf8(), + }; + } + utf16_offset = next_utf16; + } + + text.len() + } + + fn utf8_to_utf16(text: &str, offset: usize) -> usize { + text[..offset].encode_utf16().count() + } + + fn range_from_utf16(text: &str, range: &Range) -> Range { + if range.is_empty() { + let offset = Self::utf16_to_utf8(text, range.start, BoundaryBias::Floor); + return offset..offset; + } + + Self::utf16_to_utf8(text, range.start, BoundaryBias::Floor) + ..Self::utf16_to_utf8(text, range.end, BoundaryBias::Ceil) + } + + fn range_to_utf16(&self, range: &Range) -> Range { + Self::utf8_to_utf16(&self.text, range.start)..Self::utf8_to_utf16(&self.text, range.end) + } + + fn selection_utf16(&self) -> Range { + self.range_to_utf16(&self.selection) + } + + fn marked_utf16(&self) -> Option> { + self.marked.as_ref().map(|range| self.range_to_utf16(range)) + } + + fn set_selection_utf16(&mut self, range: Range) { + self.selection = Self::range_from_utf16(&self.text, &range); + } + + fn replacement_range(&self, range_utf16: Option<&Range>) -> Range { + range_utf16 + .map(|range| Self::range_from_utf16(&self.text, range)) + .or_else(|| self.marked.clone()) + .unwrap_or_else(|| self.selection.clone()) + } + + fn replace_text_in_range(&mut self, range_utf16: Option>, new_text: &str) { + let range = self.replacement_range(range_utf16.as_ref()); + let caret = range.start + new_text.len(); + self.text.replace_range(range, new_text); + self.selection = caret..caret; + self.marked = None; + } + + fn replace_and_mark_text_in_range( + &mut self, + range_utf16: Option>, + new_text: &str, + new_selection_utf16: Option>, + ) { + let range = self.replacement_range(range_utf16.as_ref()); + let insertion_start = range.start; + self.text.replace_range(range, new_text); + + let inserted = insertion_start..insertion_start + new_text.len(); + self.marked = (!new_text.is_empty()).then(|| inserted.clone()); + self.selection = new_selection_utf16 + .map(|selection| Self::range_from_utf16(new_text, &selection)) + .map(|selection| insertion_start + selection.start..insertion_start + selection.end) + .unwrap_or(inserted.end..inserted.end); + } +} + +#[derive(Debug, Default)] +struct ImeTextReceiver { + buffer: TextBuffer, +} + +impl EntityInputHandler for ImeTextReceiver { + fn text_for_range( + &mut self, + range_utf16: Range, + adjusted_range: &mut Option>, + _window: &mut Window, + _cx: &mut Context, + ) -> Option { + let range = TextBuffer::range_from_utf16(&self.buffer.text, &range_utf16); + adjusted_range.replace(self.buffer.range_to_utf16(&range)); + Some(self.buffer.text[range].to_owned()) + } + + fn selected_text_range( + &mut self, + _ignore_disabled_input: bool, + _window: &mut Window, + _cx: &mut Context, + ) -> Option { + Some(UTF16Selection { + range: self.buffer.selection_utf16(), + reversed: false, + }) + } + + fn marked_text_range( + &self, + _window: &mut Window, + _cx: &mut Context, + ) -> Option> { + self.buffer.marked_utf16() + } + + fn unmark_text(&mut self, _window: &mut Window, cx: &mut Context) { + self.buffer.marked = None; + cx.notify(); + } + + fn paste(&mut self, item: ClipboardItem, window: &mut Window, cx: &mut Context) { + if let Some(text) = item.text() { + self.replace_text_in_range(None, &text, window, cx); + } + } + + fn replace_text_in_range( + &mut self, + range_utf16: Option>, + text: &str, + _window: &mut Window, + cx: &mut Context, + ) { + self.buffer.replace_text_in_range(range_utf16, text); + cx.notify(); + } + + fn replace_and_mark_text_in_range( + &mut self, + range_utf16: Option>, + new_text: &str, + new_selected_range_utf16: Option>, + _window: &mut Window, + cx: &mut Context, + ) { + self.buffer + .replace_and_mark_text_in_range(range_utf16, new_text, new_selected_range_utf16); + cx.notify(); + } + + fn bounds_for_range( + &mut self, + _range_utf16: Range, + element_bounds: Bounds, + _window: &mut Window, + _cx: &mut Context, + ) -> Option> { + Some(element_bounds) + } + + fn character_index_for_point( + &mut self, + _point: Point, + _window: &mut Window, + _cx: &mut Context, + ) -> Option { + Some(self.buffer.selection_utf16().end) + } + + fn set_selected_text_range( + &mut self, + range_utf16: Range, + _window: &mut Window, + cx: &mut Context, + ) { + self.buffer.set_selection_utf16(range_utf16); + cx.notify(); + } + + fn text_length_utf16( + &mut self, + _window: &mut Window, + _cx: &mut Context, + ) -> Option { + Some(self.buffer.text.encode_utf16().count()) + } +} + +struct InputCaptureElement { + input: Entity, + focus: FocusHandle, +} + +impl IntoElement for InputCaptureElement { + type Element = Self; + + fn into_element(self) -> Self::Element { + self + } +} + +impl Element for InputCaptureElement { + type RequestLayoutState = (); + type PrepaintState = (); + + fn id(&self) -> Option { + None + } + + fn source_location(&self) -> Option<&'static core::panic::Location<'static>> { + None + } + + fn request_layout( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&gpui::InspectorElementId>, + window: &mut Window, + cx: &mut App, + ) -> (LayoutId, Self::RequestLayoutState) { + let mut style = Style::default(); + style.size.width = relative(1.).into(); + style.size.height = px(32.).into(); + (window.request_layout(style, [], cx), ()) + } + + fn prepaint( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&gpui::InspectorElementId>, + _bounds: Bounds, + _request_layout: &mut Self::RequestLayoutState, + _window: &mut Window, + _cx: &mut App, + ) -> Self::PrepaintState { + } + + fn paint( + &mut self, + _id: Option<&GlobalElementId>, + _inspector_id: Option<&gpui::InspectorElementId>, + bounds: Bounds, + _request_layout: &mut Self::RequestLayoutState, + _prepaint: &mut Self::PrepaintState, + window: &mut Window, + cx: &mut App, + ) { + window.handle_input( + &self.focus, + ElementInputHandler::new(bounds, self.input.clone()), + cx, + ); + } +} + +impl Render for AccessibilityProbe { + fn render(&mut self, _window: &mut Window, cx: &mut Context) -> impl IntoElement { + let input_text = self.input.read(cx).buffer.text.clone(); + + div() + .id("lumbridge-application") + .role(Role::Application) + .aria_label("Lumbridge accessibility probe") + .size_full() + .p_4() + .bg(rgb(0x0c0e13)) + .text_color(rgb(0xd9e2f2)) + .child( + div() + .id("workspace") + .accessibility_id("lumbridge.workspace.primary") + .role(Role::Region) + .aria_label(WORKSPACE_LABEL) + .size_full() + .p_3() + .border_1() + .border_color(rgb(0x293244)) + .rounded_md() + .child( + div() + .id("pane-local-terminal") + .accessibility_id(PANE_ACCESSIBILITY_ID) + .role(Role::Pane) + .aria_label(PANE_LABEL) + .aria_description(PANE_DESCRIPTION) + .aria_selected(true) + .focusable() + .track_focus(&self.pane_focus) + .size_full() + .p_3() + .bg(rgb(0x121722)) + .rounded_md() + .child( + div() + .id("terminal-content") + .role(Role::Terminal) + .aria_label("Terminal output") + .flex() + .flex_col() + .gap_2() + .child(text!("codex is waiting for approval")) + .child( + div() + .id("ime-input-status") + .role(Role::Status) + .aria_label("Composed input") + .child(if input_text.is_empty() { + "Type composed Unicode here…".to_owned() + } else { + input_text + }), + ) + .child(InputCaptureElement { + input: self.input.clone(), + focus: self.pane_focus.clone(), + }), + ), + ), + ) + } +} + +fn main() { + application().run(|cx: &mut App| { + let bounds = Bounds::centered(None, size(px(760.0), px(420.0)), cx); + cx.open_window( + WindowOptions { + window_bounds: Some(WindowBounds::Windowed(bounds)), + titlebar: Some(gpui::TitlebarOptions { + title: Some("Lumbridge · GPUI accessibility probe".into()), + ..Default::default() + }), + ..Default::default() + }, + |window, cx| cx.new(|cx| AccessibilityProbe::new(window, cx)), + ) + .expect("GPUI accessibility probe window should open"); + + cx.activate(true); + }); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn workspace_and_focused_pane_map_to_an_accesskit_tree() { + use gpui::accesskit::{Node, NodeId, Tree, TreeId, TreeUpdate}; + + let workspace_id = NodeId(1); + let pane_id = NodeId(2); + + let mut workspace = Node::new(Role::Region); + workspace.set_label(WORKSPACE_LABEL.to_owned()); + workspace.set_children(vec![pane_id]); + + let mut pane = Node::new(Role::Pane); + pane.set_author_id(PANE_ACCESSIBILITY_ID.to_owned()); + pane.set_label(PANE_LABEL.to_owned()); + pane.set_description(PANE_DESCRIPTION.to_owned()); + pane.set_selected(true); + + let update = TreeUpdate { + nodes: vec![(workspace_id, workspace), (pane_id, pane)], + tree: Some(Tree::new(workspace_id)), + tree_id: TreeId::ROOT, + focus: pane_id, + }; + let pane = &update.nodes[1].1; + + assert_eq!( + update.tree.as_ref().map(|tree| tree.root), + Some(workspace_id) + ); + assert_eq!(update.focus, pane_id); + assert_eq!(update.nodes[0].1.role(), Role::Region); + assert_eq!(update.nodes[0].1.label(), Some(WORKSPACE_LABEL)); + assert_eq!(pane.role(), Role::Pane); + assert_eq!(pane.author_id(), Some(PANE_ACCESSIBILITY_ID)); + assert_eq!(pane.label(), Some(PANE_LABEL)); + assert_eq!(pane.description(), Some(PANE_DESCRIPTION)); + assert_eq!(pane.is_selected(), Some(true)); + } + + #[test] + fn replace_selected_composed_accent_without_splitting_utf8() { + let mut buffer = TextBuffer { + text: "Cafe\u{301}".to_owned(), + selection: 0..0, + marked: None, + }; + buffer.set_selection_utf16(3..5); + + buffer.replace_text_in_range(None, "é"); + + assert_eq!(buffer.text, "Café"); + assert_eq!(buffer.selection_utf16(), 4..4); + assert!(buffer.text.is_char_boundary(buffer.selection.start)); + } + + #[test] + fn composed_ime_and_multi_codepoint_grapheme_preserve_selection() { + let grapheme = "👩🏽‍💻"; + let grapheme_utf16_len = grapheme.encode_utf16().count(); + let mut buffer = TextBuffer::default(); + + buffer.replace_and_mark_text_in_range(Some(0..0), "e\u{301}", Some(2..2)); + assert_eq!(buffer.text, "e\u{301}"); + assert_eq!(buffer.marked_utf16(), Some(0..2)); + assert_eq!(buffer.selection_utf16(), 2..2); + + buffer.replace_text_in_range(None, "é"); + assert_eq!(buffer.text, "é"); + assert_eq!(buffer.marked_utf16(), None); + assert_eq!(buffer.selection_utf16(), 1..1); + + buffer.set_selection_utf16(0..1); + buffer.replace_text_in_range(None, grapheme); + + assert_eq!(buffer.text, grapheme); + assert_eq!( + buffer.selection_utf16(), + grapheme_utf16_len..grapheme_utf16_len + ); + assert!(buffer.text.is_char_boundary(buffer.selection.start)); + + buffer.set_selection_utf16(0..grapheme_utf16_len); + buffer.replace_text_in_range(None, "done"); + assert_eq!(buffer.text, "done"); + assert_eq!(buffer.selection_utf16(), 4..4); + } +} diff --git a/spikes/gpui-shell/src/main.rs b/spikes/gpui-shell/src/main.rs index f05f413..0d4ed7d 100644 --- a/spikes/gpui-shell/src/main.rs +++ b/spikes/gpui-shell/src/main.rs @@ -1,85 +1,445 @@ +use std::collections::VecDeque; +use std::time::{Duration, Instant}; + use gpui::{ - App, Application, Bounds, Context, Window, WindowBounds, WindowOptions, div, prelude::*, px, - rgb, size, + App, Application, Bounds, Context, FocusHandle, KeyBinding, KeyDownEvent, Window, WindowBounds, + WindowOptions, actions, div, prelude::*, px, rgb, size, }; use lumbridge_spike_model::{ - FOOTER_CENTER, FOOTER_LEFT, FOOTER_RIGHT, PANES, PaneFixture, WORKSPACES, + ActionOutcome, FOOTER_RIGHT, FocusDirection, PaneId, PaneState, ShellAction, ShellModel, + SurfaceKind, WORKSPACES, }; -const BG: u32 = 0x0c0e13; -const PANEL: u32 = 0x121722; -const PANEL_ALT: u32 = 0x171d29; -const BORDER: u32 = 0x293244; -const TEXT: u32 = 0xd9e2f2; -const MUTED: u32 = 0x7f8ba3; -const ACCENT: u32 = 0x77bdfb; +const BG: u32 = 0x090c12; +const PANEL: u32 = 0x101620; +const PANEL_ALT: u32 = 0x151d29; +const PANEL_ACTIVE: u32 = 0x182334; +const BORDER: u32 = 0x263246; +const BORDER_QUIET: u32 = 0x1c2636; +const TEXT: u32 = 0xdbe5f4; +const MUTED: u32 = 0x8290a8; +const ACCENT: u32 = 0x68b5f8; +const ATTENTION: u32 = 0xf1b96a; +const SUCCESS: u32 = 0x70d6a8; +const TIMING_SAMPLE_LIMIT: usize = 256; -struct LumbridgeShell; +actions!( + lumbridge, + [ + FocusLeft, + FocusRight, + FocusUp, + FocusDown, + OpenPalette, + ClosePalette, + SelectPane1, + SelectPane2, + SelectPane3, + SelectPane4, + SelectPane5, + SelectPane6, + ] +); -fn pane_card(pane: &PaneFixture) -> impl IntoElement { - div() - .flex() - .flex_col() - .min_w_0() - .min_h_0() - .overflow_hidden() - .bg(rgb(PANEL)) - .border_1() - .border_color(rgb(BORDER)) - .rounded_md() - .child( - div() - .flex() - .items_center() - .justify_between() - .px_3() - .h(px(34.0)) - .bg(rgb(PANEL_ALT)) - .border_b_1() - .border_color(rgb(BORDER)) - .text_sm() - .text_color(rgb(TEXT)) - .child(pane.title) - .child(div().text_xs().text_color(rgb(ACCENT)).child(pane.badge)), - ) - .child( - div() - .px_3() - .py_2() - .text_xs() - .text_color(rgb(MUTED)) - .child(pane.target), - ) - .child( - div() - .flex() - .flex_col() - .gap_1() - .px_3() - .pb_3() - .text_sm() - .text_color(rgb(TEXT)) - .children(pane.lines.into_iter()), +struct LumbridgeShell { + model: ShellModel, + timing: RenderTiming, + root_focus: FocusHandle, + pane_focus: [FocusHandle; 6], +} + +#[derive(Default)] +struct RenderTiming { + pending_dispatch: Option, + dispatch_to_element_micros: VecDeque, +} + +impl RenderTiming { + fn mark_dispatch(&mut self) { + self.pending_dispatch = Some(Instant::now()); + } + + fn observe_element_build(&mut self) { + let Some(started) = self.pending_dispatch.take() else { + return; + }; + if self.dispatch_to_element_micros.len() == TIMING_SAMPLE_LIMIT { + self.dispatch_to_element_micros.pop_front(); + } + self.dispatch_to_element_micros + .push_back(started.elapsed().as_micros()); + } + + fn summary(&self) -> String { + if self.dispatch_to_element_micros.is_empty() { + return "dispatch→element collecting…".to_owned(); + } + let mut samples = self + .dispatch_to_element_micros + .iter() + .copied() + .collect::>(); + samples.sort_unstable(); + let percentile = |percent: usize| { + let index = ((samples.len() - 1) * percent) / 100; + samples[index] + }; + format!( + "dispatch→element p50 {}µs · p95 {}µs · n{}", + percentile(50), + percentile(95), + samples.len() ) + } +} + +impl LumbridgeShell { + fn new(window: &mut Window, cx: &mut Context) -> Self { + let pane_focus = std::array::from_fn(|index| { + cx.focus_handle() + .tab_index(index as isize + 1) + .tab_stop(true) + }); + let root_focus = cx.focus_handle(); + window.focus(&pane_focus[0]); + + cx.spawn(async move |this, cx| { + loop { + cx.background_executor() + .timer(Duration::from_millis(650)) + .await; + if this + .update(cx, |shell, cx| { + shell.dispatch(ShellAction::SyntheticStreamTick); + cx.notify(); + }) + .is_err() + { + break; + } + } + }) + .detach(); + + Self { + model: ShellModel::default(), + timing: RenderTiming::default(), + root_focus, + pane_focus, + } + } + + fn dispatch(&mut self, action: ShellAction) -> ActionOutcome { + self.timing.mark_dispatch(); + self.model.dispatch(action) + } + + fn select_pane(&mut self, pane: PaneId, window: &mut Window, cx: &mut Context) { + self.dispatch(ShellAction::SelectPane(pane)); + window.focus(&self.pane_focus[pane.index()]); + cx.notify(); + } + + fn move_focus( + &mut self, + direction: FocusDirection, + window: &mut Window, + cx: &mut Context, + ) { + let outcome = self.dispatch(ShellAction::MoveFocus(direction)); + window.focus(&self.pane_focus[outcome.selected_pane.index()]); + cx.notify(); + } + + fn focus_left(&mut self, _: &FocusLeft, window: &mut Window, cx: &mut Context) { + self.move_focus(FocusDirection::Left, window, cx); + } + + fn focus_right(&mut self, _: &FocusRight, window: &mut Window, cx: &mut Context) { + self.move_focus(FocusDirection::Right, window, cx); + } + + fn focus_up(&mut self, _: &FocusUp, window: &mut Window, cx: &mut Context) { + self.move_focus(FocusDirection::Up, window, cx); + } + + fn focus_down(&mut self, _: &FocusDown, window: &mut Window, cx: &mut Context) { + self.move_focus(FocusDirection::Down, window, cx); + } + + fn open_palette(&mut self, _: &OpenPalette, _: &mut Window, cx: &mut Context) { + self.dispatch(ShellAction::OpenCommandPalette); + cx.notify(); + } + + fn close_palette(&mut self, _: &ClosePalette, _: &mut Window, cx: &mut Context) { + self.dispatch(ShellAction::CloseCommandPalette); + cx.notify(); + } + + fn on_key_down(&mut self, event: &KeyDownEvent, _window: &mut Window, cx: &mut Context) { + if !self.model.command_palette().is_open() { + return; + } + + let mut query = self.model.command_palette().query().to_owned(); + match event.keystroke.key.as_str() { + "backspace" => { + query.pop(); + } + "enter" => { + self.dispatch(ShellAction::CloseCommandPalette); + cx.notify(); + return; + } + _ => { + if let Some(character) = event.keystroke.key_char.as_deref() + && !event.keystroke.modifiers.control + && !event.keystroke.modifiers.platform + { + query.push_str(character); + } else { + return; + } + } + } + self.dispatch(ShellAction::SetCommandPaletteQuery(query)); + cx.notify(); + } + + fn pane_card( + pane: &PaneState, + selected: bool, + focus: FocusHandle, + cx: &mut Context, + ) -> gpui::AnyElement { + let id = pane.id(); + let needs_input = pane.needs_input(); + let label = match pane.kind() { + SurfaceKind::Terminal => pane.status().label(), + _ => pane.fixture().badge, + }; + let state_color = if needs_input { + ATTENTION + } else if matches!(pane.kind(), SurfaceKind::Terminal) { + SUCCESS + } else { + ACCENT + }; + let line_start = pane.lines().len().saturating_sub(12); + + div() + .id(("pane", id.index())) + .track_focus(&focus) + .tab_index(id.index() as isize + 1) + .flex() + .flex_col() + .min_w_0() + .min_h_0() + .overflow_hidden() + .bg(rgb(if selected { PANEL_ACTIVE } else { PANEL })) + .border_1() + .border_color(rgb(if selected || needs_input { + state_color + } else { + BORDER + })) + .rounded(px(5.0)) + .when(selected, |view| view.border_2()) + .on_click(cx.listener(move |shell, _, window, cx| { + shell.select_pane(id, window, cx); + })) + .child( + div() + .flex() + .items_center() + .justify_between() + .px_3() + .h(px(36.0)) + .flex_none() + .bg(rgb(if selected { PANEL_ACTIVE } else { PANEL_ALT })) + .border_b_1() + .border_color(rgb(BORDER_QUIET)) + .text_sm() + .text_color(rgb(TEXT)) + .child( + div() + .flex() + .items_center() + .gap_2() + .child( + div() + .text_xs() + .text_color(rgb(MUTED)) + .child(format!("{}", id.index() + 1)), + ) + .child(pane.fixture().title), + ) + .child(div().text_xs().text_color(rgb(state_color)).child(label)), + ) + .child( + div() + .flex() + .items_center() + .justify_between() + .px_3() + .py_2() + .text_xs() + .text_color(rgb(MUTED)) + .child(pane.fixture().target) + .when(selected, |view| view.child("FOCUSED")), + ) + .child( + div() + .flex() + .flex_col() + .gap_1() + .px_3() + .pb_3() + .text_sm() + .text_color(rgb(TEXT)) + .children(pane.lines()[line_start..].iter().cloned()), + ) + .into_any_element() + } + + fn command_palette(&self) -> impl IntoElement { + let query = self.model.command_palette().query(); + let prompt = if query.is_empty() { + "Type a command…".to_owned() + } else { + query.to_owned() + }; + + div() + .absolute() + .inset_0() + .flex() + .justify_center() + .items_start() + .pt(px(92.0)) + .bg(gpui::black().opacity(0.72)) + .child( + div() + .w(px(620.0)) + .overflow_hidden() + .bg(rgb(PANEL_ALT)) + .border_1() + .border_color(rgb(ACCENT)) + .rounded(px(8.0)) + .child( + div() + .px_4() + .py_3() + .border_b_1() + .border_color(rgb(BORDER)) + .text_color(rgb(if query.is_empty() { MUTED } else { TEXT })) + .child(prompt), + ) + .child( + div() + .flex() + .flex_col() + .p_2() + .text_sm() + .child( + div() + .px_3() + .py_2() + .rounded(px(5.0)) + .bg(rgb(PANEL_ACTIVE)) + .child("Focus next pane") + .child( + div() + .mt_1() + .text_xs() + .text_color(rgb(MUTED)) + .child("Workspace · navigation"), + ), + ) + .child( + div() + .px_3() + .py_2() + .text_color(rgb(MUTED)) + .child("Open attention request"), + ) + .child( + div() + .px_3() + .py_2() + .text_color(rgb(MUTED)) + .child("Share selected pane to Buzz…"), + ), + ) + .child( + div() + .flex() + .justify_between() + .px_4() + .py_2() + .border_t_1() + .border_color(rgb(BORDER)) + .text_xs() + .text_color(rgb(MUTED)) + .child("Enter to run") + .child("Esc to close"), + ), + ) + } } impl Render for LumbridgeShell { - fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + fn render(&mut self, _window: &mut Window, cx: &mut Context) -> impl IntoElement { + let attention = self.model.pane(PaneId::ClaudeUi); let sidebar = div() .flex() .flex_col() - .w(px(220.0)) + .w(px(248.0)) .flex_none() .bg(rgb(PANEL)) .border_r_1() - .border_color(rgb(BORDER)) + .border_color(rgb(BORDER_QUIET)) .child( div() .px_4() - .py_3() - .text_sm() + .pt_4() + .pb_2() + .text_xs() + .text_color(rgb(ATTENTION)) + .child("ATTENTION · 1"), + ) + .child( + div() + .mx_2() + .mb_3() + .px_3() + .py_2() + .rounded(px(5.0)) + .bg(rgb(PANEL_ACTIVE)) + .border_1() + .border_color(rgb(ATTENTION)) + .child( + div() + .text_sm() + .text_color(rgb(TEXT)) + .child(attention.fixture().title), + ) + .child( + div() + .mt_1() + .text_xs() + .text_color(rgb(MUTED)) + .child("Waiting for a split decision"), + ), + ) + .child( + div() + .px_4() + .py_2() + .text_xs() .text_color(rgb(MUTED)) - .child("WORKSPACES"), + .child("WORKTREES"), ) .children(WORKSPACES.into_iter().enumerate().map(|(index, name)| { div() @@ -87,30 +447,130 @@ impl Render for LumbridgeShell { .mb_1() .px_3() .py_2() - .rounded_md() + .rounded(px(5.0)) .when(index == 0, |view| { view.bg(rgb(PANEL_ALT)).text_color(rgb(TEXT)) }) .when(index != 0, |view| view.text_color(rgb(MUTED))) .child(name) + .when(index == 0, |view| { + view.child( + div() + .mt_1() + .text_xs() + .text_color(rgb(MUTED)) + .child("main · metal"), + ) + }) })) .child( div() - .mt_4() + .mt_3() .px_4() + .py_2() .text_xs() .text_color(rgb(MUTED)) - .child("HOSTS") + .child("RUNTIMES"), + ) + .child( + div() + .px_4() + .py_1() + .text_sm() + .text_color(rgb(SUCCESS)) + .child("metal · connected"), + ) + .child( + div() + .px_4() + .py_1() + .text_sm() + .text_color(rgb(MUTED)) + .child("amd-server · connected"), + ) + .child( + div() + .px_4() + .py_1() + .text_sm() + .text_color(rgb(MUTED)) + .child("spark-1 · sleeping"), + ) + .child(div().flex_1()) + .child( + div() + .m_3() + .p_3() + .rounded(px(5.0)) + .bg(rgb(PANEL_ALT)) + .text_xs() + .text_color(rgb(MUTED)) + .child("Buzz · lumbridgecode") .child( div() - .mt_2() - .text_color(rgb(ACCENT)) - .child("● metal · connected"), - ) - .child(div().mt_2().child("● amd-server · connected")) - .child(div().mt_2().child("○ spark-1 · sleeping")), + .mt_1() + .text_color(rgb(SUCCESS)) + .child("connected · signed identity"), + ), ); + let tabs = div() + .flex() + .items_center() + .h(px(38.0)) + .flex_none() + .px_2() + .gap_1() + .bg(rgb(PANEL)) + .border_b_1() + .border_color(rgb(BORDER_QUIET)) + .child( + div() + .h_full() + .flex() + .items_center() + .px_3() + .border_b_2() + .border_color(rgb(ACCENT)) + .text_sm() + .child("Agent workspace"), + ) + .child( + div() + .px_3() + .text_sm() + .text_color(rgb(MUTED)) + .child("Architecture.md"), + ) + .child( + div() + .px_3() + .text_sm() + .text_color(rgb(MUTED)) + .child("Review"), + ) + .child(div().flex_1()) + .child( + div() + .px_3() + .text_xs() + .text_color(rgb(MUTED)) + .child("6 surfaces · 3 remote · 1 waiting"), + ); + + let pane_cards = self + .model + .panes() + .iter() + .map(|pane| { + Self::pane_card( + pane, + self.model.selected_pane() == pane.id(), + self.pane_focus[pane.id().index()].clone(), + cx, + ) + }) + .collect::>(); let grid = div() .grid() .grid_cols(3) @@ -118,9 +578,48 @@ impl Render for LumbridgeShell { .gap_2() .p_2() .size_full() - .children(PANES.iter().map(pane_card)); + .children(pane_cards); - div() + let counters = self.model.counters(); + let footer_left = format!( + "rev {} · {} focus moves · {} surface updates · {} lines", + self.model.revision(), + counters.focus_moves, + counters.surface_updates, + counters.terminal_lines_appended + ); + let timing = self.timing.summary(); + + let root = div() + .id("lumbridge-shell") + .relative() + .track_focus(&self.root_focus) + .key_context("LumbridgeShell") + .on_action(cx.listener(Self::focus_left)) + .on_action(cx.listener(Self::focus_right)) + .on_action(cx.listener(Self::focus_up)) + .on_action(cx.listener(Self::focus_down)) + .on_action(cx.listener(Self::open_palette)) + .on_action(cx.listener(Self::close_palette)) + .on_action(cx.listener(|shell, _: &SelectPane1, window, cx| { + shell.select_pane(PaneId::CodexRuntime, window, cx); + })) + .on_action(cx.listener(|shell, _: &SelectPane2, window, cx| { + shell.select_pane(PaneId::ClaudeUi, window, cx); + })) + .on_action(cx.listener(|shell, _: &SelectPane3, window, cx| { + shell.select_pane(PaneId::PiDocs, window, cx); + })) + .on_action(cx.listener(|shell, _: &SelectPane4, window, cx| { + shell.select_pane(PaneId::Architecture, window, cx); + })) + .on_action(cx.listener(|shell, _: &SelectPane5, window, cx| { + shell.select_pane(PaneId::AcpPreview, window, cx); + })) + .on_action(cx.listener(|shell, _: &SelectPane6, window, cx| { + shell.select_pane(PaneId::RuntimeReview, window, cx); + })) + .on_key_down(cx.listener(Self::on_key_down)) .flex() .flex_col() .size_full() @@ -130,63 +629,105 @@ impl Render for LumbridgeShell { div() .flex() .items_center() - .justify_between() - .h(px(46.0)) + .h(px(48.0)) .flex_none() .px_4() .bg(rgb(PANEL_ALT)) .border_b_1() - .border_color(rgb(BORDER)) + .border_color(rgb(BORDER_QUIET)) .child(div().text_lg().child("Lumbridge")) .child( div() + .ml_3() .text_sm() .text_color(rgb(MUTED)) - .child("UI spike · GPUI"), + .child("Lumbridge Code / main"), + ) + .child(div().flex_1()) + .child( + div() + .mr_4() + .text_xs() + .text_color(rgb(SUCCESS)) + .child("metal · runtime online"), ) .child( div() .text_sm() .text_color(rgb(ACCENT)) - .child("⌘K Command Palette"), + .child("Ctrl/⌘ K · Commands"), ), ) - .child(div().flex().flex_1().min_h_0().child(sidebar).child(grid)) + .child( + div().flex().flex_1().min_h_0().child(sidebar).child( + div() + .flex() + .flex_col() + .flex_1() + .min_w_0() + .child(tabs) + .child(grid), + ), + ) .child( div() .flex() .items_center() .justify_between() - .h(px(30.0)) + .h(px(32.0)) .flex_none() .px_3() .bg(rgb(PANEL_ALT)) .border_t_1() - .border_color(rgb(BORDER)) + .border_color(rgb(BORDER_QUIET)) .text_xs() .text_color(rgb(MUTED)) - .child(FOOTER_LEFT) - .child(FOOTER_CENTER) + .child(footer_left) + .child(timing) .child(FOOTER_RIGHT), ) + .when(self.model.command_palette().is_open(), |view| { + view.child(self.command_palette()) + }); + self.timing.observe_element_build(); + root } } fn main() { Application::new().run(|cx: &mut App| { - let bounds = Bounds::centered(None, size(px(1280.0), px(800.0)), cx); + cx.bind_keys([ + KeyBinding::new("left", FocusLeft, Some("LumbridgeShell")), + KeyBinding::new("right", FocusRight, Some("LumbridgeShell")), + KeyBinding::new("up", FocusUp, Some("LumbridgeShell")), + KeyBinding::new("down", FocusDown, Some("LumbridgeShell")), + KeyBinding::new("h", FocusLeft, Some("LumbridgeShell")), + KeyBinding::new("l", FocusRight, Some("LumbridgeShell")), + KeyBinding::new("k", FocusUp, Some("LumbridgeShell")), + KeyBinding::new("j", FocusDown, Some("LumbridgeShell")), + KeyBinding::new("secondary-k", OpenPalette, Some("LumbridgeShell")), + KeyBinding::new("escape", ClosePalette, Some("LumbridgeShell")), + KeyBinding::new("1", SelectPane1, Some("LumbridgeShell")), + KeyBinding::new("2", SelectPane2, Some("LumbridgeShell")), + KeyBinding::new("3", SelectPane3, Some("LumbridgeShell")), + KeyBinding::new("4", SelectPane4, Some("LumbridgeShell")), + KeyBinding::new("5", SelectPane5, Some("LumbridgeShell")), + KeyBinding::new("6", SelectPane6, Some("LumbridgeShell")), + ]); + + let bounds = Bounds::centered(None, size(px(1500.0), px(960.0)), cx); cx.open_window( WindowOptions { window_bounds: Some(WindowBounds::Windowed(bounds)), titlebar: Some(gpui::TitlebarOptions { - title: Some("Lumbridge · GPUI spike".into()), + title: Some("Lumbridge · GPUI workspace".into()), ..Default::default() }), ..Default::default() }, - |_, cx| cx.new(|_| LumbridgeShell), + |window, cx| cx.new(|cx| LumbridgeShell::new(window, cx)), ) - .expect("GPUI spike window should open"); + .expect("GPUI workspace window should open"); cx.activate(true); }); } diff --git a/spikes/ui-shell-model/src/lib.rs b/spikes/ui-shell-model/src/lib.rs index df0708c..c2ed869 100644 --- a/spikes/ui-shell-model/src/lib.rs +++ b/spikes/ui-shell-model/src/lib.rs @@ -1,3 +1,70 @@ +//! Deterministic state and fixtures shared by the GPUI and Floem spikes. +//! +//! UI candidates translate framework input into [`ShellAction`] and render the +//! resulting [`ShellModel`]. This makes their interaction traces comparable. + +use std::fmt; + +pub const GRID_ROWS: usize = 2; +pub const GRID_COLUMNS: usize = 3; +pub const DEFAULT_TERMINAL_LINE_LIMIT: usize = 64; + +/// Stable identity used in traces and accessibility identifiers. +#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[repr(u8)] +pub enum PaneId { + CodexRuntime = 0, + ClaudeUi = 1, + PiDocs = 2, + Architecture = 3, + AcpPreview = 4, + RuntimeReview = 5, +} + +impl PaneId { + pub const ALL: [Self; GRID_ROWS * GRID_COLUMNS] = [ + Self::CodexRuntime, + Self::ClaudeUi, + Self::PiDocs, + Self::Architecture, + Self::AcpPreview, + Self::RuntimeReview, + ]; + + #[must_use] + pub const fn index(self) -> usize { + self as usize + } + + #[must_use] + pub const fn stable_name(self) -> &'static str { + match self { + Self::CodexRuntime => "codex-runtime", + Self::ClaudeUi => "claude-ui", + Self::PiDocs => "pi-docs", + Self::Architecture => "architecture", + Self::AcpPreview => "acp-preview", + Self::RuntimeReview => "runtime-review", + } + } + + #[must_use] + pub const fn row(self) -> usize { + self.index() / GRID_COLUMNS + } + + #[must_use] + pub const fn column(self) -> usize { + self.index() % GRID_COLUMNS + } +} + +impl fmt::Display for PaneId { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str(self.stable_name()) + } +} + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum SurfaceKind { Terminal, @@ -6,21 +73,45 @@ pub enum SurfaceKind { Review, } +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum PaneStatus { + Working, + NeedsInput, + Streaming, + Ready, +} + +impl PaneStatus { + #[must_use] + pub const fn label(self) -> &'static str { + match self { + Self::Working => "WORKING", + Self::NeedsInput => "NEEDS INPUT", + Self::Streaming => "STREAMING", + Self::Ready => "READY", + } + } +} + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct PaneFixture { + pub id: PaneId, pub title: &'static str, pub badge: &'static str, pub target: &'static str, pub kind: SurfaceKind, + pub status: PaneStatus, pub lines: [&'static str; 4], } pub const PANES: [PaneFixture; 6] = [ PaneFixture { + id: PaneId::CodexRuntime, title: "Codex · runtime", badge: "WORKING", target: "metal · Tailscale SSH", kind: SurfaceKind::Terminal, + status: PaneStatus::Working, lines: [ "$ cargo nextest run -p lumbridge-runtime", "PASS remote::reconnect_replays_output", @@ -29,10 +120,12 @@ pub const PANES: [PaneFixture; 6] = [ ], }, PaneFixture { + id: PaneId::ClaudeUi, title: "Claude Code · UI", badge: "NEEDS INPUT", target: "MacBook Air · local", kind: SurfaceKind::Terminal, + status: PaneStatus::NeedsInput, lines: [ "$ bacon clippy", "finished in 0.42s", @@ -41,10 +134,12 @@ pub const PANES: [PaneFixture; 6] = [ ], }, PaneFixture { + id: PaneId::PiDocs, title: "Pi · docs", badge: "STREAMING", target: "amd-server · OpenSSH", kind: SurfaceKind::Terminal, + status: PaneStatus::Streaming, lines: [ "$ cargo watch --why", "ACP session resumed at event 1842", @@ -53,10 +148,12 @@ pub const PANES: [PaneFixture; 6] = [ ], }, PaneFixture { + id: PaneId::Architecture, title: "Architecture.md", badge: "MARKDOWN", target: "lumbridge-code · worktree", kind: SurfaceKind::Markdown, + status: PaneStatus::Ready, lines: [ "## Remote session path", "The destination runtime owns the PTY.", @@ -65,10 +162,12 @@ pub const PANES: [PaneFixture; 6] = [ ], }, PaneFixture { + id: PaneId::AcpPreview, title: "Preview · ACP docs", badge: "BROWSER", target: "isolated system web engine", kind: SurfaceKind::Browser, + status: PaneStatus::Ready, lines: [ "https://agentclientprotocol.com", "Content process: sandboxed", @@ -77,10 +176,12 @@ pub const PANES: [PaneFixture; 6] = [ ], }, PaneFixture { + id: PaneId::RuntimeReview, title: "Changes · lumbridge-runtime", badge: "REVIEW", target: "metal · worktree remote-runtime", kind: SurfaceKind::Review, + status: PaneStatus::Ready, lines: [ "+ 184 remote transport", "+ 96 SQLite migrations", @@ -97,26 +198,538 @@ pub const WORKSPACES: [&str; 5] = [ "ACP adapters", "Usage telemetry", ]; - pub const FOOTER_LEFT: &str = "6 panes · 3 remote · 1 needs input"; pub const FOOTER_CENTER: &str = "Codex · ChatGPT subscription · 62% window remaining"; pub const FOOTER_RIGHT: &str = "burn 8.4%/hr · resets in 2h 14m"; +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct PaneState { + fixture: PaneFixture, + status: PaneStatus, + status_before_input: Option, + lines: Vec, + synthetic_line_sequence: u64, +} + +impl PaneState { + #[must_use] + pub const fn id(&self) -> PaneId { + self.fixture.id + } + #[must_use] + pub const fn fixture(&self) -> &PaneFixture { + &self.fixture + } + #[must_use] + pub const fn kind(&self) -> SurfaceKind { + self.fixture.kind + } + #[must_use] + pub const fn status(&self) -> PaneStatus { + self.status + } + #[must_use] + pub const fn needs_input(&self) -> bool { + matches!(self.status, PaneStatus::NeedsInput) + } + #[must_use] + pub fn lines(&self) -> &[String] { + &self.lines + } + #[must_use] + pub const fn synthetic_line_sequence(&self) -> u64 { + self.synthetic_line_sequence + } +} + +#[derive(Clone, Debug, Default, Eq, PartialEq)] +pub struct CommandPaletteState { + open: bool, + query: String, +} + +impl CommandPaletteState { + #[must_use] + pub const fn is_open(&self) -> bool { + self.open + } + #[must_use] + pub fn query(&self) -> &str { + &self.query + } +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum FocusDirection { + Left, + Right, + Up, + Down, +} + +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum ShellAction { + MoveFocus(FocusDirection), + SelectPane(PaneId), + SetNeedsInput { pane: PaneId, needs_input: bool }, + OpenCommandPalette, + CloseCommandPalette, + SetCommandPaletteQuery(String), + SyntheticStreamTick, +} + +/// Counters prove both candidates replayed the same workload. Framework +/// adapters may use the event sequence and revision for explicitly labelled +/// timing stages; these counters do not imply pixels reached the display. +#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] +pub struct MeasurementCounters { + pub events_dispatched: u64, + pub state_changes: u64, + pub focus_moves: u64, + pub blocked_focus_moves: u64, + pub direct_selections: u64, + pub needs_input_changes: u64, + pub palette_changes: u64, + pub synthetic_ticks: u64, + /// Total surfaces invalidated by the deterministic six-surface workload. + pub surface_updates: u64, + pub terminal_lines_appended: u64, +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct ActionOutcome { + pub event_sequence: u64, + pub revision: u64, + pub changed: bool, + pub selected_pane: PaneId, + pub terminal_lines_appended: usize, +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct InvalidTerminalLineLimit; + +impl fmt::Display for InvalidTerminalLineLimit { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("terminal line limit must be greater than zero") + } +} +impl std::error::Error for InvalidTerminalLineLimit {} + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct ShellModel { + panes: [PaneState; GRID_ROWS * GRID_COLUMNS], + selected_pane: PaneId, + command_palette: CommandPaletteState, + terminal_line_limit: usize, + synthetic_tick: u64, + revision: u64, + counters: MeasurementCounters, +} + +impl Default for ShellModel { + fn default() -> Self { + Self::with_terminal_line_limit(DEFAULT_TERMINAL_LINE_LIMIT) + .expect("the default terminal line limit is non-zero") + } +} + +impl ShellModel { + pub fn with_terminal_line_limit(limit: usize) -> Result { + if limit == 0 { + return Err(InvalidTerminalLineLimit); + } + let panes = PANES.map(|fixture| { + let mut lines = fixture.lines.map(String::from).to_vec(); + if fixture.kind == SurfaceKind::Terminal && lines.len() > limit { + lines.drain(..lines.len() - limit); + } + PaneState { + fixture, + status: fixture.status, + status_before_input: (fixture.status == PaneStatus::NeedsInput) + .then_some(PaneStatus::Working), + lines, + synthetic_line_sequence: 0, + } + }); + Ok(Self { + panes, + selected_pane: PaneId::CodexRuntime, + command_palette: CommandPaletteState::default(), + terminal_line_limit: limit, + synthetic_tick: 0, + revision: 0, + counters: MeasurementCounters::default(), + }) + } + + #[must_use] + pub fn panes(&self) -> &[PaneState; GRID_ROWS * GRID_COLUMNS] { + &self.panes + } + #[must_use] + pub fn pane(&self, id: PaneId) -> &PaneState { + &self.panes[id.index()] + } + #[must_use] + pub const fn selected_pane(&self) -> PaneId { + self.selected_pane + } + #[must_use] + pub const fn command_palette(&self) -> &CommandPaletteState { + &self.command_palette + } + #[must_use] + pub const fn terminal_line_limit(&self) -> usize { + self.terminal_line_limit + } + #[must_use] + pub const fn synthetic_tick(&self) -> u64 { + self.synthetic_tick + } + #[must_use] + pub const fn revision(&self) -> u64 { + self.revision + } + #[must_use] + pub const fn counters(&self) -> MeasurementCounters { + self.counters + } + + pub fn dispatch(&mut self, action: ShellAction) -> ActionOutcome { + self.counters.events_dispatched += 1; + let mut changed = false; + let mut appended = 0; + match action { + ShellAction::MoveFocus(direction) => { + if let Some(next) = focus_neighbor(self.selected_pane, direction) { + self.selected_pane = next; + self.counters.focus_moves += 1; + changed = true; + } else { + self.counters.blocked_focus_moves += 1; + } + } + ShellAction::SelectPane(pane) => { + if self.selected_pane != pane { + self.selected_pane = pane; + self.counters.direct_selections += 1; + changed = true; + } + } + ShellAction::SetNeedsInput { pane, needs_input } => { + let pane = &mut self.panes[pane.index()]; + if needs_input && !pane.needs_input() { + pane.status_before_input = Some(pane.status); + pane.status = PaneStatus::NeedsInput; + self.counters.needs_input_changes += 1; + changed = true; + } else if !needs_input && pane.needs_input() { + pane.status = pane.status_before_input.take().unwrap_or(PaneStatus::Ready); + self.counters.needs_input_changes += 1; + changed = true; + } + } + ShellAction::OpenCommandPalette => { + if !self.command_palette.open { + self.command_palette.open = true; + self.command_palette.query.clear(); + self.counters.palette_changes += 1; + changed = true; + } + } + ShellAction::CloseCommandPalette => { + if self.command_palette.open { + self.command_palette.open = false; + self.command_palette.query.clear(); + self.counters.palette_changes += 1; + changed = true; + } + } + ShellAction::SetCommandPaletteQuery(query) => { + if self.command_palette.open && self.command_palette.query != query { + self.command_palette.query = query; + self.counters.palette_changes += 1; + changed = true; + } + } + ShellAction::SyntheticStreamTick => { + self.synthetic_tick += 1; + self.counters.synthetic_ticks += 1; + for pane in &mut self.panes { + pane.synthetic_line_sequence += 1; + if pane.kind() != SurfaceKind::Terminal { + continue; + } + pane.lines.push(format!( + "[tick {:06}] {} · synthetic line {:06}", + self.synthetic_tick, + pane.id(), + pane.synthetic_line_sequence + )); + if pane.lines.len() > self.terminal_line_limit { + pane.lines.remove(0); + } + appended += 1; + } + self.counters.surface_updates += self.panes.len() as u64; + self.counters.terminal_lines_appended += appended as u64; + changed = true; + } + } + if changed { + self.revision += 1; + self.counters.state_changes += 1; + } + ActionOutcome { + event_sequence: self.counters.events_dispatched, + revision: self.revision, + changed, + selected_pane: self.selected_pane, + terminal_lines_appended: appended, + } + } +} + +#[must_use] +pub const fn focus_neighbor(pane: PaneId, direction: FocusDirection) -> Option { + let row = pane.row(); + let column = pane.column(); + let next = match direction { + FocusDirection::Left if column > 0 => Some(pane.index() - 1), + FocusDirection::Right if column + 1 < GRID_COLUMNS => Some(pane.index() + 1), + FocusDirection::Up if row > 0 => Some(pane.index() - GRID_COLUMNS), + FocusDirection::Down if row + 1 < GRID_ROWS => Some(pane.index() + GRID_COLUMNS), + _ => None, + }; + match next { + Some(index) => Some(PaneId::ALL[index]), + None => None, + } +} + #[cfg(test)] mod tests { - use super::{PANES, SurfaceKind}; + use super::{ + FocusDirection, GRID_COLUMNS, GRID_ROWS, PANES, PaneId, PaneStatus, ShellAction, + ShellModel, SurfaceKind, focus_neighbor, + }; #[test] - fn comparison_fixture_has_six_mixed_surfaces() { - assert_eq!(PANES.len(), 6); + fn fixture_has_stable_ids_and_mixed_surfaces() { + assert_eq!(PANES.len(), GRID_ROWS * GRID_COLUMNS); + assert_eq!(PANES.map(|pane| pane.id), PaneId::ALL); + assert_eq!(PaneId::CodexRuntime.stable_name(), "codex-runtime"); + assert_eq!(PaneId::RuntimeReview.to_string(), "runtime-review"); assert!(PANES.iter().any(|pane| pane.kind == SurfaceKind::Markdown)); assert!(PANES.iter().any(|pane| pane.kind == SurfaceKind::Browser)); assert_eq!( PANES .iter() - .filter(|pane| pane.kind == SurfaceKind::Terminal) + .filter(|p| p.kind == SurfaceKind::Terminal) .count(), 3 ); } + + #[test] + fn initial_state_has_one_explicit_needs_input_pane() { + let model = ShellModel::default(); + assert_eq!(model.selected_pane(), PaneId::CodexRuntime); + assert_eq!(model.revision(), 0); + assert!(!model.command_palette().is_open()); + assert_eq!( + model + .panes() + .iter() + .filter(|pane| pane.needs_input()) + .map(|pane| pane.id()) + .collect::>(), + vec![PaneId::ClaudeUi] + ); + } + + #[test] + fn neighbors_match_two_by_three_grid_without_wrapping() { + assert_eq!( + focus_neighbor(PaneId::CodexRuntime, FocusDirection::Right), + Some(PaneId::ClaudeUi) + ); + assert_eq!( + focus_neighbor(PaneId::ClaudeUi, FocusDirection::Down), + Some(PaneId::AcpPreview) + ); + assert_eq!( + focus_neighbor(PaneId::RuntimeReview, FocusDirection::Up), + Some(PaneId::PiDocs) + ); + assert_eq!( + focus_neighbor(PaneId::Architecture, FocusDirection::Left), + None + ); + assert_eq!(focus_neighbor(PaneId::PiDocs, FocusDirection::Right), None); + assert_eq!( + focus_neighbor(PaneId::CodexRuntime, FocusDirection::Up), + None + ); + } + + #[test] + fn focus_updates_selection_revision_and_blocked_counter() { + let mut model = ShellModel::default(); + let blocked = model.dispatch(ShellAction::MoveFocus(FocusDirection::Left)); + assert!(!blocked.changed); + assert_eq!((blocked.event_sequence, blocked.revision), (1, 0)); + let moved = model.dispatch(ShellAction::MoveFocus(FocusDirection::Right)); + assert!(moved.changed); + assert_eq!(moved.selected_pane, PaneId::ClaudeUi); + assert_eq!(moved.revision, 1); + model.dispatch(ShellAction::MoveFocus(FocusDirection::Down)); + assert_eq!(model.selected_pane(), PaneId::AcpPreview); + assert_eq!(model.counters().focus_moves, 2); + assert_eq!(model.counters().blocked_focus_moves, 1); + } + + #[test] + fn direct_selection_is_idempotent_and_counted_separately() { + let mut model = ShellModel::default(); + assert!( + !model + .dispatch(ShellAction::SelectPane(PaneId::CodexRuntime)) + .changed + ); + assert!( + model + .dispatch(ShellAction::SelectPane(PaneId::RuntimeReview)) + .changed + ); + assert_eq!(model.selected_pane(), PaneId::RuntimeReview); + assert_eq!(model.counters().direct_selections, 1); + assert_eq!(model.counters().events_dispatched, 2); + assert_eq!(model.counters().state_changes, 1); + } + + #[test] + fn needs_input_restores_previous_status() { + let mut model = ShellModel::default(); + model.dispatch(ShellAction::SetNeedsInput { + pane: PaneId::PiDocs, + needs_input: true, + }); + assert_eq!(model.pane(PaneId::PiDocs).status(), PaneStatus::NeedsInput); + assert!( + !model + .dispatch(ShellAction::SetNeedsInput { + pane: PaneId::PiDocs, + needs_input: true, + }) + .changed + ); + model.dispatch(ShellAction::SetNeedsInput { + pane: PaneId::PiDocs, + needs_input: false, + }); + assert_eq!(model.pane(PaneId::PiDocs).status(), PaneStatus::Streaming); + model.dispatch(ShellAction::SetNeedsInput { + pane: PaneId::ClaudeUi, + needs_input: false, + }); + assert_eq!(model.pane(PaneId::ClaudeUi).status(), PaneStatus::Working); + assert_eq!(model.counters().needs_input_changes, 3); + } + + #[test] + fn command_palette_has_explicit_lifecycle() { + let mut model = ShellModel::default(); + assert!( + !model + .dispatch(ShellAction::SetCommandPaletteQuery("pane".into())) + .changed + ); + model.dispatch(ShellAction::OpenCommandPalette); + model.dispatch(ShellAction::SetCommandPaletteQuery("pane: next".into())); + assert!(model.command_palette().is_open()); + assert_eq!(model.command_palette().query(), "pane: next"); + model.dispatch(ShellAction::CloseCommandPalette); + assert!(!model.command_palette().is_open()); + assert_eq!(model.command_palette().query(), ""); + assert_eq!(model.counters().palette_changes, 3); + } + + #[test] + fn ticks_append_predictable_lines_to_terminals_only() { + let mut model = ShellModel::default(); + let markdown = model.pane(PaneId::Architecture).lines().to_vec(); + let outcome = model.dispatch(ShellAction::SyntheticStreamTick); + assert_eq!(outcome.terminal_lines_appended, 3); + assert_eq!(model.synthetic_tick(), 1); + assert_eq!( + model.pane(PaneId::CodexRuntime).lines().last().unwrap(), + "[tick 000001] codex-runtime · synthetic line 000001" + ); + assert_eq!(model.pane(PaneId::Architecture).lines(), markdown); + assert!( + model + .panes() + .iter() + .all(|pane| pane.synthetic_line_sequence() == 1) + ); + assert_eq!(model.counters().synthetic_ticks, 1); + assert_eq!(model.counters().surface_updates, 6); + assert_eq!(model.counters().terminal_lines_appended, 3); + } + + #[test] + fn terminal_scrollback_is_bounded_below_fixture_size() { + let mut model = ShellModel::with_terminal_line_limit(2).unwrap(); + assert_eq!(model.pane(PaneId::CodexRuntime).lines().len(), 2); + for _ in 0..10 { + model.dispatch(ShellAction::SyntheticStreamTick); + } + for pane in model + .panes() + .iter() + .filter(|pane| pane.kind() == SurfaceKind::Terminal) + { + assert_eq!(pane.lines().len(), 2); + assert_eq!(pane.synthetic_line_sequence(), 10); + assert!(pane.lines()[0].starts_with("[tick 000009]")); + assert!(pane.lines()[1].starts_with("[tick 000010]")); + } + assert!(ShellModel::with_terminal_line_limit(0).is_err()); + } + + #[test] + fn identical_action_replays_produce_identical_models_and_counters() { + let actions = [ + ShellAction::MoveFocus(FocusDirection::Right), + ShellAction::MoveFocus(FocusDirection::Down), + ShellAction::OpenCommandPalette, + ShellAction::SetCommandPaletteQuery("workspace".into()), + ShellAction::CloseCommandPalette, + ShellAction::SetNeedsInput { + pane: PaneId::CodexRuntime, + needs_input: true, + }, + ShellAction::SyntheticStreamTick, + ShellAction::SyntheticStreamTick, + ]; + let mut gpui = ShellModel::default(); + let mut floem = ShellModel::default(); + let gpui_outcomes = actions + .iter() + .cloned() + .map(|action| gpui.dispatch(action)) + .collect::>(); + let floem_outcomes = actions + .iter() + .cloned() + .map(|action| floem.dispatch(action)) + .collect::>(); + assert_eq!(gpui_outcomes, floem_outcomes); + assert_eq!(gpui, floem); + assert_eq!(gpui.counters().events_dispatched, actions.len() as u64); + assert_eq!(gpui.counters().surface_updates, 12); + assert_eq!(gpui.counters().terminal_lines_appended, 6); + } }