| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
chore: Use gpui-kit (#2929) ## Summary Zed owns the `gpui` crate names on crates.io and publishes them only occasionally. This PR adds `script/bump-gpui.ts` (Bun) to publish a snapshot of any Zed commit to crates.io under our own names, a weekly `Release GPUI` workflow that runs it, and switches the workspace, README and docs to those crates. | Zed crate | Published as | | --- | --- | | `gpui` | `gpui-pre` | | `gpui_platform` | `gpui-pre-platform` | | `gpui_macros` | `gpui-pre-macros` | | `reqwest_client` | `gpui-pre-reqwest-client` | | `gpui_<x>` / other internal crates | `gpui-pre-<x>` | What the script does: - Fetches the requested Zed revision (`--rev`, default `main`) into `target/gpui-pre/zed`, or reuses a checkout passed with `--zed`. - Walks the workspace path dependencies of the four root crates and publishes the whole closure (25 crates today) at one version, `<VERSION>.<N>` (e.g. `0.3.12`): the `VERSION` constant at the top of the script (`0.3`) plus a patch number that continues from the highest one crates.io already has (`0.3.0` first). A run that stopped part-way resumes the same number. A positional argument publishes an explicit version instead. - Keeps each crate's original name as `[lib] name`, so consumers write `gpui = { package = "gpui-pre", version = "0.3.0" }` and `use gpui::*` unchanged; `actions!` and `#[derive(Action)]` keep working. - Drops optional dependencies that come from git without a crates.io version (`proptest`, `async-tar`) together with the features that enable them, then removes optional dependencies nothing can enable any more. This keeps Zed's `util` crate (which needs Zed's git-patched `async-process`) out of the publish set. - Swaps the workspace `reqwest` dependency (Zed's git fork) for the hand-published `gpui-pre-reqwest` through `DEPENDENCY_OVERRIDES`. - Vendors the gpui source files that `gpui_apple`'s build script reads from `../gpui`, since a crate unpacked from crates.io has no such sibling. - Verifies everything with `cargo publish --workspace --dry-run`, then publishes with `cargo publish --workspace`, re-checking crates.io before each attempt and waiting out the new-crate rate limit so a run can be resumed. Workflow: - `.github/workflows/release-gpui.yml` runs the script every other Sunday (even ISO weeks, gated by a small `cadence` job since cron cannot express two weeks) at 18:00 Beijing time (`0 10 * * 0` UTC) and on `workflow_dispatch` with optional `rev` and `version` inputs, on `macos-latest` so `gpui_apple`'s Metal shader build script is verified. It uses the `CARGO_REGISTRY_TOKEN` secret and writes the published crate table to the job summary. Workspace and docs: - `Cargo.toml` now depends on `gpui-pre` 0.3.0 (`gpui`, `gpui_platform`, `gpui_web`, `gpui_macros`, `reqwest_client`, `sum-tree`) and `gpui-pre-reqwest` 0.12.15 instead of the Zed git repository, `zed-sum-tree` and Zed's reqwest fork. The `[profile.dev.package]` overrides follow the new package names. - README (en/zh-CN), the site docs (en/zh-CN), the gpui-component skill, and the crate READMEs show the `gpui-pre` dependency lines. - CONTRIBUTING documents the workflow and version scheme. ## gpui-kit `crates/kit` (published as `gpui-kit`, names already reserved on crates.io) is the one crate applications depend on. It pins the matching `gpui-pre-*` set and re-exports every layer: | Path | Crate | Feature | | --- | --- | --- | | `gpui_kit::gpui` | `gpui` | always | | `gpui_kit::platform` | `gpui_platform` | always | | `gpui_kit::base` | `gpui-base` | always | | `gpui_kit::component` | `gpui-component` | `component` (default) | | `gpui_kit::assets` | `gpui-kit-assets` | `assets` (default) | | `gpui_kit::shell` | `gpui-shell` | `shell` (default) | | `gpui_kit::webview` | `gpui-wry` | `webview` | `gpui_kit::application()` and `gpui_kit::init()` cover startup, and `gpui_kit::prelude::*` also brings the crate names into scope, so `gpui::…` paths and the `actions!` / `#[derive(Action)]` macros (which expand to `gpui::…`) work without a direct `gpui` dependency. The `gpui-component` features (`inspector`, `decimal`, `tree-sitter*`) are forwarded by name. README, the site docs, the skill, the crate READMEs and `hello_world` now show `gpui-kit = "0.6"` alone; the docs no longer link GPUI to gpui.rs. Workspace crates are bumped to 0.6.0. ## Breaking Changes `gpui-component-assets` is renamed `gpui-kit-assets`; the `links` key is unchanged so `gpui-component`'s build script still finds the icon directory. ```diff -gpui-component-assets = "0.5" +gpui-kit-assets = "0.6" ``` ```diff -use gpui_component_assets::Assets; +use gpui_kit_assets::Assets; ``` Applications that listed GPUI themselves can drop those lines: ```diff -gpui = { package = "gpui-pre", version = "0.3.0" } -gpui_platform = { package = "gpui-pre-platform", version = "0.3.0", features = ["font-kit"] } -gpui-component = "0.5" +gpui-kit = "0.6" ``` ## Release gate Before anything is uploaded, `script/bump-gpui.ts` builds and tests this repository against the staged crates (mirrored outside the checkout and injected with `--config patch.crates-io…`; `Cargo.lock` is scratch-updated and restored, and `cargo metadata` proves the patch resolved). CI's `check`, `clippy` and `test` must pass, so a Zed change that no longer fits `gpui-component` fails the release instead of reaching applications through their caret `gpui-pre` requirement on `cargo update`. `--skip-kit-check` bypasses it. The workflow installs the system dependencies for that step. The facade-aware macro rewrite now copies `#[cfg]` gates onto the wrapped bodies (the published 0.3.1 `gpui-pre-macros` breaks release builds without `inspector`; 0.3.2 fixes it) and the `actions!` rewrite is scoped to the `macro_rules!` block. `gpui-shell` is not published for now (its `llrt_*` dependencies are git-only) and is no longer part of `gpui-kit`; `gpui-fps` is. `release.yml` publishes our crates with one ordered `cargo publish -p …`. ## Verification - `./script/bump-gpui.ts --dry-run --zed <local zed checkout>`: all 25 crates package and build; `gpui-pre-reqwest` resolves from crates.io. - With a temporary `[patch.crates-io]` pointing at the staged workspace (not committed), `cargo check --workspace` passes for every crate, story, story-web and example. - A scratch consumer crate depending on the staged crates via `package = "gpui-pre"` passes `cargo check`, including `actions!`, `#[derive(Action)]` and `collections::` by its original lib name. - `gpui-kit`: `cargo check` with default, no, `base`-only, `component`-only and `webview,inspector,tree-sitter-rust` features, its doc tests, `cargo check --workspace`, the CI clippy set plus `gpui-kit` and `hello_world` with `--deny warnings`, and `cargo machete` all pass against the staged `gpui-pre`. - `tsc --strict` with `@types/bun`, `typos`, and a YAML parse of the workflow pass. `gpui-pre` 0.3.0 is not on crates.io yet, so CI cannot resolve dependencies until the `Release GPUI` workflow has run (by hand, or on the next even ISO week Sunday). A requirement of `0.3.0` accepts every later `0.3.x` as well. `Cargo.lock` is left for that first resolution. ## AI assistance The script, workflow, dependency switch and documentation were written with Claude Code and reviewed by hand. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01D2PVGzukYKuXnb3LB5s53T --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> | 19 天前 | |
website: isolate versioned documentation snapshots (#3189) ## Summary - replace version-owned documentation trees before restoring a release snapshot so main-only pages cannot leak into tagged builds - extract and regression-test the snapshot operation, and run that test in docs CI - include website publishing scripts in the historical build fingerprint so affected cached versions rebuild ## Test plan - `script/test-snapshot-website` - `bash -n script/build-website-versions script/snapshot-website script/test-snapshot-website` - `bun run --cwd website test:showcases` (13 passed) - `bun run --cwd website build` - `bun run --cwd website test:seo` (14 passed) - `bun run --cwd website test:versioned-examples` - `git diff --check` | 6 小时前 | |
Update GitHub Sponsors username in FUNDING.yml | 1 个月前 | |
Add dependabot.yml | 1 年前 | |
input: Add atomic inline tokens to Input and Textarea (#3113) Closes #3110 ## Description Add optional atomic inline tokens to Input and Textarea for mentions, commands, file and image references. A token can display “Alice” while the input value and the clipboard contain `@alice`. Users select, delete and undo the whole token; the application maps its ID back to the resource it names. ## Model and API The input stays a plain-text control: the value is the text, and each token is an annotation over a byte range that follows edits — the same model as Draft.js entity ranges and the VS Code chat input's parts over Monaco decorations, rather than a document tree with atom nodes. Base owns the behavior (atomic caret movement, selection and deletion, history with token deltas, mixed text/element layout and wrapping, activation); Component owns the default appearance. ```rust // Insert a reference at the caret or over the selection; `?` reports why it was refused. state.replace_with_token(InlineToken::new("person:alice", "@alice").with_label("Alice"), window, cx)?; // Save and restore a draft with its tokens; `set_value` takes text or content. let draft = state.content(); state.set_value(draft, window, cx); // Build content from storage; every token is validated as it is attached. let draft = InputContent::new("Ask @alice") .with_token(4..10, InlineToken::new("person:alice", "@alice").with_label("Alice"))?; ``` - `InlineToken` carries a resource ID, its text and a display label. The ID names the resource and may occur more than once in one input. - `InputContent` is what `content()` returns and what `set_value` accepts; plain text converts into content without tokens. `InputContent::with_token` returns `Result`, so a content value is always consistent before it reaches the input. - `Input` / `Textarea` (Base and Component) take a `token` slot and `on_token_click`. A click selects the whole token and then runs the listener; dragging or Shift-selecting does not open it. `ActivateToken` opens an exactly selected token from a key binding or assistive technology. - Component renders tokens as `InputToken` by default, with `icon` and `Styled`; a selected token paints its own selected state, and the text selection highlight stops at its edges. The Base token element uses the arrow cursor, and tokens are measured whenever they render, so an element that grows reflows on the next frame. - The JavaScript API mirrors this on `InputState` / `TextareaState` and on the registered components: `content()`, `tokens()`, `set_value(string | InputContent)`, `replace_with_token`, `replace_range_with_token`, `token`, `on_token_click`. Ranges are UTF-16 string offsets, and validation errors carry `error.code`. Tokens remain opt-in. Editor, NumberInput, formatted masks and password fields do not accept token insertion. Copy/paste uses ordinary text; resource lookup, delimiters around an inserted reference and submission remain application decisions. ## Story and docs The Story is a chat composer shared by Input and Textarea: an `InputGroup` with a toolbar that inserts a `/commit-pr` command, an `[Image 1]` attachment, a `$gpui-kit` skill and an `@alice` mention as tokens, a Send action, draft save/restore, read-only and disabled toggles and a readout of the text, references and last action. The JavaScript Story has the same example. English and Chinese documentation cover insertion, appearance, drafts, validation and the JavaScript API for Input, Textarea and InputGroup. ## Public API ### `gpui-base` (`gpui_base::input`) Data: - `InlineToken` — a reference rendered as one editing unit. `new(id, text)`, `with_label(label)`; readers `id()`, `text()`, `label()`. Derives `Clone, Debug, PartialEq, Eq, Hash`. - `InlineTokenSpan` — a token at its current UTF-8 byte range: `range() -> Range<usize>`, `token() -> &InlineToken`. - `InputContent` — text with its tokens, what `content()` returns and `set_value` accepts. `new(text)`, `with_token(range, token) -> Result<Self, InlineTokenError>` (validates boundary, overlap and text match), `text()`, `tokens()`. `From` for every text type `set_value` accepted before (`&str`, `String`, `SharedString`, `Cow<str>`, `Arc<str>`, `Box<str>`, `char`, and their references). - `InlineTokenError` — `#[non_exhaustive]`: `InvalidRange`, `InvalidBoundary`, `InvalidToken`, `OverlappingTokens`, `TextMismatch`, `UnsupportedMode`, `ValidationRejected`, `CompositionActive`. Implements `Error` and `Display`. - `InlineTokenContext` — what a token renderer sees: `token()`, `range()`, `is_selected()`, `is_disabled()`, `is_readonly()`, `line_height()`, `available_width()`. - `InlineTokenClickEvent` — what a click listener receives: `token()`, `range()`, `bounds() -> Bounds<Pixels>`, `click() -> &ClickEvent`. - `ActivateToken` — action that opens an exactly selected token (key bindings, assistive technology). `InputState` / `TextareaState` (`InputBaseState<InputMode | TextareaMode>`): - `replace_with_token(token, window, cx) -> Result<(), InlineTokenError>` — replace the selection, or insert at the caret, with a token. - `replace_range_with_token(range, token, window, cx) -> Result<(), InlineTokenError>` — replace a byte range, expanding overlaps to whole tokens. - `tokens() -> &[InlineTokenSpan]` — the current tokens in document order. - `content() -> InputContent` — the text with its tokens. - Changed: `set_value(value: impl Into<InputContent>, window, cx)` — was `impl Into<SharedString>`; plain text still converts, content also restores tokens. `Input` / `Textarea` elements: - `token(render: impl Fn(&InlineTokenContext, &mut Window, &mut App) -> impl IntoElement)` — the element each token renders as. - `on_token_click(listener: impl Fn(&InlineTokenClickEvent, &mut Window, &mut App))` — runs after a completed, unconsumed click on a token. Hidden (`#[doc(hidden)]`, for styled controls only): `InlineTokenRenderer`, `InlineTokenClickListener`, `InputBaseState::install_token_presentation`. ### `gpui-component` (`gpui_component::input`) - `InputToken` — the element a token renders as by default: `new(&InlineTokenContext)`, `icon(impl Into<Icon>)`, `Styled`. Selected, disabled and readonly states come from the context. - `Input` / `Textarea`: `token(..)` and `on_token_click(..)` as in Base; `InputGroupInput` / `InputGroupTextarea` inherit them. - Re-exports of the Base data types above and `ActivateToken`. ### `gpui-shell` (host integration) - `StateMethodDescriptor` — an opt-in operation on retained state exposed to scripts: `new::<T>(name, signature, call)`, `with_readonly(bool)`, `name()`, `signature()`, `is_readonly()`. - `StateDescriptor::with_methods(Vec<StateMethodDescriptor>)`, `methods()`. - `ComponentElementCallback::build_interactive_data_with(args, window, cx) -> Result<Option<AnyElement>>` — build a frame-owned inline subtree whose child callbacks retire with that frame. - `ComponentCallback::invoke_data_with(args, window, cx) -> Result<()>`. - `InlineTokenCallbacks` — script callbacks adapted to an element's `token` / `on_token_click` builders: `new(&Entity<InputBaseState<M>>, renderer, listener)`, `apply(element, token, on_token_click)`. - `inline_token_context_data`, `inline_token_click_data`, `input_token_state_methods()`, `textarea_token_state_methods()`. ### JavaScript (`gpui-base` / `gpui-component`) - `InputState` / `TextareaState`: `content(): InputContent`, `tokens(): InlineTokenSpan[]`, `replace_with_token(token)`, `replace_range_with_token(range, token)`, `set_selected_range(range)`, `replace(text)`; changed: `set_value(next: string | InputContent)`. Ranges are UTF-16 offsets; validation errors carry `error.code`. - `Input` / `Textarea` / `InputGroupInput` / `InputGroupTextarea`: `token(render)`, `on_token_click(listener)`. - Types: `InputRange`, `InlineToken`, `InlineTokenSpan`, `InputContent`, `InlineTokenContext`, `InlineTokenClickEvent`. ## Breaking Changes None. Existing input APIs and `InputEvent` variants are unchanged; the token APIs are additive. `set_value` now takes `impl Into<InputContent>`, and every text type it accepted before converts into content, so existing calls compile and behave as they did. ## How to Test Validated on macOS on top of the latest `main`: ```sh cargo fmt --all --check cargo clippy --workspace --all-targets -- --deny warnings cargo test -p gpui-base --lib input:: cargo test -p gpui-shell --lib component_callback_value_tests cargo test -p gpui-component-shell --test inline_tokens_host --test input_group_host --test layout_host cargo test -p gpui-component-story --lib token_story GPUI_COMPONENT_SHELL_BIN=target/debug/gpui-component-shell node crates/component-shell/tests/types/run.mjs cargo run ``` The Base tests cover token insertion and rejection, history with token deltas, boundary and word movement, IME composition, mode gates, wrapping and re-measurement, click selection and re-entrant activation. The Story test drives the composer through insertion, partial-selection deletion, undo, save/restore, sending and the read-only/disabled gates for both controls. Host tests cover UTF-16 emoji boundaries, atomic rejection, re-render retention, token activation and custom child callbacks. In the Story gallery, open Input or Textarea and scroll to “Atomic inline tokens”: click a token to select it and read the status line, insert the same reference twice, select part of a token and delete it, undo, and save and restore the draft. Real IME candidate/cancellation behavior on Windows and Linux remains unverified. ## AI Assistance The implementation, tests and documentation were written with Codex assistance; the API review and rework (resource IDs, `set_value(content)`, the presentation seam, click selection, naming and the composer Story) were done with Claude Code and reviewed by hand. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Jason Lee <huacnlee@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> | 4 天前 |
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 19 天前 | ||
| 6 小时前 | ||
| 1 个月前 | ||
| 1 年前 | ||
| 4 天前 |