Compare commits

..

2 Commits

Author SHA1 Message Date
Nate Butler
58a7a277df wip 2024-10-21 10:20:26 -04:00
Nate Butler
5e9f084f12 Start on quick commit UI PoC 2024-10-21 09:33:15 -04:00
1178 changed files with 58558 additions and 111681 deletions

View File

@@ -13,12 +13,6 @@ rustflags = ["-C", "link-arg=-fuse-ld=mold"]
linker = "clang" linker = "clang"
rustflags = ["-C", "link-arg=-fuse-ld=mold"] rustflags = ["-C", "link-arg=-fuse-ld=mold"]
[target.aarch64-apple-darwin]
rustflags = ["-C", "link-args=-Objc -all_load"]
[target.x86_64-apple-darwin]
rustflags = ["-C", "link-args=-Objc -all_load"]
# This cfg will reduce the size of `windows::core::Error` from 16 bytes to 4 bytes # This cfg will reduce the size of `windows::core::Error` from 16 bytes to 4 bytes
[target.'cfg(target_os = "windows")'] [target.'cfg(target_os = "windows")']
rustflags = ["--cfg", "windows_slim_errors"] rustflags = ["--cfg", "windows_slim_errors"]

View File

@@ -3,6 +3,15 @@ export default {
const url = new URL(request.url); const url = new URL(request.url);
url.hostname = "docs-anw.pages.dev"; url.hostname = "docs-anw.pages.dev";
// These pages were removed, but may still be served due to Cloudflare's
// [asset retention](https://developers.cloudflare.com/pages/configuration/serving-pages/#asset-retention).
if (
url.pathname === "/docs/assistant/context-servers" ||
url.pathname === "/docs/assistant/model-context-protocol"
) {
return await fetch("https://zed.dev/404");
}
let res = await fetch(url, request); let res = await fetch(url, request);
if (res.status === 404) { if (res.status === 404) {

View File

@@ -15,13 +15,6 @@ body:
description: A clear and concise description of what you want to happen. description: A clear and concise description of what you want to happen.
validations: validations:
required: true required: true
- type: textarea
id: environment
attributes:
label: Environment
description: Run the `copy system specs into clipboard` command palette action and paste the output in the field below. If you are unable to run the command, please include your Zed version and release channel, operating system and version, RAM amount, and architecture.
validations:
required: true
- type: textarea - type: textarea
attributes: attributes:
label: | label: |

View File

@@ -2,7 +2,7 @@ name: Bug Report
description: | description: |
Use this template for **non-crash-related** bug reports. Use this template for **non-crash-related** bug reports.
Tip: open this issue template from within Zed with the `file bug report` command palette action. Tip: open this issue template from within Zed with the `file bug report` command palette action.
labels: ["admin read", "triage", "bug"] labels: ["admin read", "triage", "defect"]
body: body:
- type: checkboxes - type: checkboxes
attributes: attributes:
@@ -21,7 +21,7 @@ body:
id: environment id: environment
attributes: attributes:
label: Environment label: Environment
description: Run the `copy system specs into clipboard` command palette action and paste the output in the field below. If you are unable to run the command, please include your Zed version and release channel, operating system and version, RAM amount, and architecture. description: Run the `copy system specs into clipboard` command palette action and paste the output in the field below.
validations: validations:
required: true required: true
- type: textarea - type: textarea
@@ -38,12 +38,9 @@ body:
Linux: `~/.local/share/zed/logs/Zed.log` or $XDG_DATA_HOME Linux: `~/.local/share/zed/logs/Zed.log` or $XDG_DATA_HOME
If you only need the most recent lines, you can run the `zed: open log` command palette action to see the last 1000. If you only need the most recent lines, you can run the `zed: open log` command palette action to see the last 1000.
value: | value: |
<details><summary>Zed.log</summary> <details><summary>Zed.log</summary><pre>
<!-- Click below this line and paste or drag-and-drop your log--> <!-- Click below this line and paste or drag-and-drop your log-->
```
``` <!-- Click above this line and paste or drag-and-drop your log--></pre></details>
<!-- Click above this line and paste or drag-and-drop your log--></details>
validations: validations:
required: false required: false

View File

@@ -1,7 +1,7 @@
name: Crash Report name: Crash Report
description: | description: |
Use this template for crash reports. Use this template for crash reports.
labels: ["admin read", "triage", "bug", "panic / crash"] labels: ["admin read", "triage", "defect", "panic / crash"]
body: body:
- type: checkboxes - type: checkboxes
attributes: attributes:
@@ -20,7 +20,7 @@ body:
id: environment id: environment
attributes: attributes:
label: Environment label: Environment
description: Run the `copy system specs into clipboard` command palette action and paste the output in the field below. If you are unable to run the command, please include your Zed version and release channel, operating system and version, RAM amount, and architecture. description: Run the `copy system specs into clipboard` command palette action and paste the output in the field below.
validations: validations:
required: true required: true
- type: textarea - type: textarea
@@ -31,12 +31,9 @@ body:
Linux: `~/.local/share/zed/logs/Zed.log` or $XDG_DATA_HOME Linux: `~/.local/share/zed/logs/Zed.log` or $XDG_DATA_HOME
If you only need the most recent lines, you can run the `zed: open log` command palette action to see the last 1000. If you only need the most recent lines, you can run the `zed: open log` command palette action to see the last 1000.
value: | value: |
<details><summary>Zed.log</summary> <details><summary>Zed.log</summary><pre>
<!-- Click below this line and paste or drag-and-drop your log--> <!-- Click below this line and paste or drag-and-drop your log-->
```
``` <!-- Click above this line and paste or drag-and-drop your log--></pre></details>
<!-- Click above this line and paste or drag-and-drop your log--></details>
validations: validations:
required: false required: false

View File

@@ -10,7 +10,7 @@ runs:
cargo install cargo-nextest cargo install cargo-nextest
- name: Install Node - name: Install Node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4 uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4
with: with:
node-version: "18" node-version: "18"

View File

@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with: with:
fetch-depth: 0 fetch-depth: 0

View File

@@ -18,7 +18,7 @@ jobs:
- buildjet-16vcpu-ubuntu-2204 - buildjet-16vcpu-ubuntu-2204
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with: with:
ref: ${{ github.event.inputs.branch }} ref: ${{ github.event.inputs.branch }}
ssh-key: ${{ secrets.ZED_BOT_DEPLOY_KEY }} ssh-key: ${{ secrets.ZED_BOT_DEPLOY_KEY }}
@@ -43,8 +43,6 @@ jobs:
esac esac
which cargo-set-version > /dev/null || cargo install cargo-edit which cargo-set-version > /dev/null || cargo install cargo-edit
output=$(cargo set-version -p zed --bump patch 2>&1 | sed 's/.* //') output=$(cargo set-version -p zed --bump patch 2>&1 | sed 's/.* //')
export GIT_COMMITTER_NAME="Zed Bot"
export GIT_COMMITTER_EMAIL="hi@zed.dev"
git commit -am "Bump to $output for @$GITHUB_ACTOR" --author "Zed Bot <hi@zed.dev>" git commit -am "Bump to $output for @$GITHUB_ACTOR" --author "Zed Bot <hi@zed.dev>"
git tag v${output}${tag_suffix} git tag v${output}${tag_suffix}
git push origin HEAD v${output}${tag_suffix} git push origin HEAD v${output}${tag_suffix}

View File

@@ -13,7 +13,7 @@ on:
branches: branches:
- "**" - "**"
paths-ignore: paths-ignore:
- "docs/**/*" - "docs/**"
- ".github/workflows/community_*" - ".github/workflows/community_*"
concurrency: concurrency:
@@ -25,7 +25,6 @@ env:
CARGO_TERM_COLOR: always CARGO_TERM_COLOR: always
CARGO_INCREMENTAL: 0 CARGO_INCREMENTAL: 0
RUST_BACKTRACE: 1 RUST_BACKTRACE: 1
RUSTFLAGS: "-D warnings"
jobs: jobs:
migration_checks: migration_checks:
@@ -37,7 +36,7 @@ jobs:
- test - test
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with: with:
clean: false clean: false
fetch-depth: 0 # fetch full history fetch-depth: 0 # fetch full history
@@ -79,26 +78,25 @@ jobs:
- buildjet-8vcpu-ubuntu-2204 - buildjet-8vcpu-ubuntu-2204
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
- name: Run style checks - name: Run style checks
uses: ./.github/actions/check_style uses: ./.github/actions/check_style
- name: Check for typos - name: Check for typos
uses: crate-ci/typos@8e6a4285bcbde632c5d79900a7779746e8b7ea3f # v1.24.6 uses: crate-ci/typos@v1.24.6
with: with:
config: ./typos.toml config: ./typos.toml
macos_tests: macos_tests:
timeout-minutes: 60 timeout-minutes: 60
name: (macOS) Run Clippy and tests name: (macOS) Run Clippy and tests
if: github.repository_owner == 'zed-industries'
runs-on: runs-on:
- self-hosted - self-hosted
- test - test
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with: with:
clean: false clean: false
@@ -113,30 +111,21 @@ jobs:
script/check-licenses script/check-licenses
script/generate-licenses /tmp/zed_licenses_output script/generate-licenses /tmp/zed_licenses_output
- name: Check for new vulnerable dependencies
if: github.event_name == 'pull_request'
uses: actions/dependency-review-action@3b139cfc5fae8b618d3eae3675e383bb1769c019 # v4
with:
license-check: false
- name: Run tests - name: Run tests
uses: ./.github/actions/run_tests uses: ./.github/actions/run_tests
- name: Build collab - name: Build collab
run: cargo build -p collab run: RUSTFLAGS="-D warnings" cargo build -p collab
- name: Build other binaries and features - name: Build other binaries and features
run: | run: |
cargo build --workspace --bins --all-features RUSTFLAGS="-D warnings" cargo build --workspace --bins --all-features
cargo check -p gpui --features "macos-blade" cargo check -p gpui --features "macos-blade"
cargo check -p workspace RUSTFLAGS="-D warnings" cargo build -p remote_server
cargo build -p remote_server
script/check-rust-livekit-macos
linux_tests: linux_tests:
timeout-minutes: 60 timeout-minutes: 60
name: (Linux) Run Clippy and tests name: (Linux) Run Clippy and tests
if: github.repository_owner == 'zed-industries'
runs-on: runs-on:
- buildjet-16vcpu-ubuntu-2204 - buildjet-16vcpu-ubuntu-2204
steps: steps:
@@ -144,7 +133,7 @@ jobs:
run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with: with:
clean: false clean: false
@@ -163,15 +152,12 @@ jobs:
- name: Run tests - name: Run tests
uses: ./.github/actions/run_tests uses: ./.github/actions/run_tests
- name: Build other binaries and features - name: Build Zed
run: | run: RUSTFLAGS="-D warnings" cargo build -p zed
cargo build -p zed
cargo check -p workspace
build_remote_server: build_remote_server:
timeout-minutes: 60 timeout-minutes: 60
name: (Linux) Build Remote Server name: (Linux) Build Remote Server
if: github.repository_owner == 'zed-industries'
runs-on: runs-on:
- buildjet-16vcpu-ubuntu-2204 - buildjet-16vcpu-ubuntu-2204
steps: steps:
@@ -179,7 +165,7 @@ jobs:
run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with: with:
clean: false clean: false
@@ -193,20 +179,16 @@ jobs:
run: ./script/remote-server && ./script/install-mold 2.34.0 run: ./script/remote-server && ./script/install-mold 2.34.0
- name: Build Remote Server - name: Build Remote Server
run: cargo build -p remote_server run: RUSTFLAGS="-D warnings" cargo build -p remote_server
# todo(windows): Actually run the tests # todo(windows): Actually run the tests
windows_tests: windows_tests:
timeout-minutes: 60 timeout-minutes: 60
name: (Windows) Run Clippy and tests name: (Windows) Run Clippy and tests
if: github.repository_owner == 'zed-industries'
runs-on: hosted-windows-1 runs-on: hosted-windows-1
steps: steps:
# more info here:- https://github.com/rust-lang/cargo/issues/13020
- name: Enable longer pathnames for git
run: git config --system core.longpaths true
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with: with:
clean: false clean: false
@@ -221,7 +203,7 @@ jobs:
run: cargo xtask clippy run: cargo xtask clippy
- name: Build Zed - name: Build Zed
run: cargo build run: $env:RUSTFLAGS="-D warnings"; cargo build
bundle-mac: bundle-mac:
timeout-minutes: 60 timeout-minutes: 60
@@ -242,12 +224,12 @@ jobs:
DIGITALOCEAN_SPACES_SECRET_KEY: ${{ secrets.DIGITALOCEAN_SPACES_SECRET_KEY }} DIGITALOCEAN_SPACES_SECRET_KEY: ${{ secrets.DIGITALOCEAN_SPACES_SECRET_KEY }}
steps: steps:
- name: Install Node - name: Install Node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4 uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4
with: with:
node-version: "18" node-version: "18"
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with: with:
# We need to fetch more than one commit so that `script/draft-release-notes` # We need to fetch more than one commit so that `script/draft-release-notes`
# is able to diff between the current and previous tag. # is able to diff between the current and previous tag.
@@ -255,7 +237,6 @@ jobs:
# 25 was chosen arbitrarily. # 25 was chosen arbitrarily.
fetch-depth: 25 fetch-depth: 25
clean: false clean: false
ref: ${{ github.ref }}
- name: Limit target directory size - name: Limit target directory size
run: script/clear-target-dir-if-larger-than 100 run: script/clear-target-dir-if-larger-than 100
@@ -271,10 +252,7 @@ jobs:
run: | run: |
mkdir -p target/ mkdir -p target/
# Ignore any errors that occur while drafting release notes to not fail the build. # Ignore any errors that occur while drafting release notes to not fail the build.
script/draft-release-notes "$RELEASE_VERSION" "$RELEASE_CHANNEL" > target/release-notes.md || true script/draft-release-notes "$version" "$channel" > target/release-notes.md || true
script/create-draft-release target/release-notes.md
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Generate license file - name: Generate license file
run: script/generate-licenses run: script/generate-licenses
@@ -282,12 +260,18 @@ jobs:
- name: Create macOS app bundle - name: Create macOS app bundle
run: script/bundle-mac run: script/bundle-mac
- name: Rename binaries - name: Rename single-architecture binaries
if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }} if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
run: | run: |
mv target/aarch64-apple-darwin/release/Zed.dmg target/aarch64-apple-darwin/release/Zed-aarch64.dmg mv target/aarch64-apple-darwin/release/Zed.dmg target/aarch64-apple-darwin/release/Zed-aarch64.dmg
mv target/x86_64-apple-darwin/release/Zed.dmg target/x86_64-apple-darwin/release/Zed-x86_64.dmg mv target/x86_64-apple-darwin/release/Zed.dmg target/x86_64-apple-darwin/release/Zed-x86_64.dmg
- name: Upload app bundle (universal) to workflow run if main branch or specific label
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4
if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
with:
name: Zed_${{ github.event.pull_request.head.sha || github.sha }}.dmg
path: target/release/Zed.dmg
- name: Upload app bundle (aarch64) to workflow run if main branch or specific label - name: Upload app bundle (aarch64) to workflow run if main branch or specific label
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4 uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4
if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }} if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
@@ -313,6 +297,8 @@ jobs:
target/zed-remote-server-macos-aarch64.gz target/zed-remote-server-macos-aarch64.gz
target/aarch64-apple-darwin/release/Zed-aarch64.dmg target/aarch64-apple-darwin/release/Zed-aarch64.dmg
target/x86_64-apple-darwin/release/Zed-x86_64.dmg target/x86_64-apple-darwin/release/Zed-x86_64.dmg
target/release/Zed.dmg
body_path: target/release-notes.md
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -328,7 +314,7 @@ jobs:
ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON: ${{ secrets.ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON }} ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON: ${{ secrets.ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON }}
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with: with:
clean: false clean: false
@@ -359,6 +345,7 @@ jobs:
files: | files: |
target/zed-remote-server-linux-x86_64.gz target/zed-remote-server-linux-x86_64.gz
target/release/zed-linux-x86_64.tar.gz target/release/zed-linux-x86_64.tar.gz
body: ""
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -374,7 +361,7 @@ jobs:
ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON: ${{ secrets.ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON }} ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON: ${{ secrets.ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON }}
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with: with:
clean: false clean: false
@@ -399,24 +386,13 @@ jobs:
- name: Upload app bundle to release - name: Upload app bundle to release
uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1 uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
if: ${{ env.RELEASE_CHANNEL == 'preview' || env.RELEASE_CHANNEL == 'stable' }}
with: with:
draft: true draft: true
prerelease: ${{ env.RELEASE_CHANNEL == 'preview' }} prerelease: ${{ env.RELEASE_CHANNEL == 'preview' }}
files: | files: |
target/zed-remote-server-linux-aarch64.gz target/zed-remote-server-linux-aarch64.gz
target/release/zed-linux-aarch64.tar.gz target/release/zed-linux-aarch64.tar.gz
env: body: ""
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
auto-release-preview:
name: Auto release preview
if: ${{ startsWith(github.ref, 'refs/tags/v') && endsWith(github.ref, '-pre') && !endsWith(github.ref, '.0-pre') }}
needs: [bundle-mac, bundle-linux, bundle-linux-aarch64]
runs-on:
- self-hosted
- bundle
steps:
- name: gh release
run: gh release edit $GITHUB_REF_NAME --draft=false
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -6,7 +6,6 @@ on:
jobs: jobs:
stale: stale:
if: github.repository_owner == 'zed-industries'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9 - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9
@@ -15,17 +14,17 @@ jobs:
stale-issue-message: > stale-issue-message: >
Hi there! 👋 Hi there! 👋
We're working to clean up our issue tracker by closing older issues that might not be relevant anymore. If you are able to reproduce this issue in the latest version of Zed, please let us know by commenting on this issue, and we will keep it open. If you can't reproduce it, feel free to close the issue yourself. Otherwise, we'll close it in 7 days. We're working to clean up our issue tracker by closing older issues that might not be relevant anymore. Are you able to reproduce this issue in the latest version of Zed? If so, please let us know by commenting on this issue and we will keep it open; otherwise, we'll close it in 7 days. Feel free to open a new issue if you're seeing this message after the issue has been closed.
Thanks for your help! Thanks for your help!
close-issue-message: "This issue was closed due to inactivity. If you're still experiencing this problem, please open a new issue with a link to this issue." close-issue-message: "This issue was closed due to inactivity. If you're still experiencing this problem, please open a new issue with a link to this issue."
# We will increase `days-before-stale` to 365 on or after Jan 24th, # We will increase `days-before-stale` to 365 on or after Jan 24th,
# 2024. This date marks one year since migrating issues from # 2024. This date marks one year since migrating issues from
# 'community' to 'zed' repository. The migration added activity to all # 'community' to 'zed' repository. The migration added activity to all
# issues, preventing 365 days from working until then. # issues, preventing 365 days from working until then.
days-before-stale: 180 days-before-stale: 180
days-before-close: 7 days-before-close: 7
any-of-issue-labels: "bug,panic / crash" any-of-issue-labels: "defect,panic / crash"
operations-per-run: 1000 operations-per-run: 1000
ascending: true ascending: true
enable-statistics: true enable-statistics: true

View File

@@ -10,9 +10,9 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.repository_owner == 'zed-industries' if: github.repository_owner == 'zed-industries'
steps: steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
- name: Set up uv - name: Set up uv
uses: astral-sh/setup-uv@caf0cab7a618c569241d31dcd442f54681755d39 # v3 uses: astral-sh/setup-uv@f3bcaebff5eace81a1c062af9f9011aae482ca9d # v3
with: with:
version: "latest" version: "latest"
enable-cache: true enable-cache: true

View File

@@ -10,9 +10,9 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.repository_owner == 'zed-industries' if: github.repository_owner == 'zed-industries'
steps: steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
- name: Set up uv - name: Set up uv
uses: astral-sh/setup-uv@caf0cab7a618c569241d31dcd442f54681755d39 # v3 uses: astral-sh/setup-uv@f3bcaebff5eace81a1c062af9f9011aae482ca9d # v3
with: with:
version: "latest" version: "latest"
enable-cache: true enable-cache: true

View File

@@ -14,14 +14,14 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
with: with:
version: 9 version: 9
- name: Setup Node - name: Setup Node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4 uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4
with: with:
node-version: "20" node-version: "20"
cache: "pnpm" cache: "pnpm"

View File

@@ -13,7 +13,7 @@ jobs:
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with: with:
clean: false clean: false
@@ -37,28 +37,28 @@ jobs:
mdbook build ./docs --dest-dir=../target/deploy/docs/ mdbook build ./docs --dest-dir=../target/deploy/docs/
- name: Deploy Docs - name: Deploy Docs
uses: cloudflare/wrangler-action@6d58852c35a27e6034745c5d0bc373d739014f7f # v3 uses: cloudflare/wrangler-action@9681c2997648301493e78cacbfb790a9f19c833f # v3
with: with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy target/deploy --project-name=docs command: pages deploy target/deploy --project-name=docs
- name: Deploy Install - name: Deploy Install
uses: cloudflare/wrangler-action@6d58852c35a27e6034745c5d0bc373d739014f7f # v3 uses: cloudflare/wrangler-action@9681c2997648301493e78cacbfb790a9f19c833f # v3
with: with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: r2 object put -f script/install.sh zed-open-source-website-assets/install.sh command: r2 object put -f script/install.sh zed-open-source-website-assets/install.sh
- name: Deploy Docs Workers - name: Deploy Docs Workers
uses: cloudflare/wrangler-action@6d58852c35a27e6034745c5d0bc373d739014f7f # v3 uses: cloudflare/wrangler-action@9681c2997648301493e78cacbfb790a9f19c833f # v3
with: with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: deploy .cloudflare/docs-proxy/src/worker.js command: deploy .cloudflare/docs-proxy/src/worker.js
- name: Deploy Install Workers - name: Deploy Install Workers
uses: cloudflare/wrangler-action@6d58852c35a27e6034745c5d0bc373d739014f7f # v3 uses: cloudflare/wrangler-action@9681c2997648301493e78cacbfb790a9f19c833f # v3
with: with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}

View File

@@ -17,7 +17,7 @@ jobs:
- test - test
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with: with:
clean: false clean: false
fetch-depth: 0 fetch-depth: 0
@@ -36,7 +36,7 @@ jobs:
needs: style needs: style
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with: with:
clean: false clean: false
fetch-depth: 0 fetch-depth: 0
@@ -71,7 +71,7 @@ jobs:
run: doctl registry login run: doctl registry login
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with: with:
clean: false clean: false
@@ -97,7 +97,7 @@ jobs:
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with: with:
clean: false clean: false

View File

@@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
with: with:
@@ -31,7 +31,7 @@ jobs:
} }
- name: Check for Typos with Typos-CLI - name: Check for Typos with Typos-CLI
uses: crate-ci/typos@8e6a4285bcbde632c5d79900a7779746e8b7ea3f # v1.24.6 uses: crate-ci/typos@v1.24.6
with: with:
config: ./typos.toml config: ./typos.toml
files: ./docs/ files: ./docs/

View File

@@ -16,7 +16,7 @@ jobs:
- ubuntu-latest - ubuntu-latest
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with: with:
clean: false clean: false

View File

@@ -22,12 +22,12 @@ jobs:
- buildjet-16vcpu-ubuntu-2204 - buildjet-16vcpu-ubuntu-2204
steps: steps:
- name: Install Node - name: Install Node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4 uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4
with: with:
node-version: "18" node-version: "18"
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with: with:
clean: false clean: false

View File

@@ -23,7 +23,7 @@ jobs:
- test - test
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with: with:
clean: false clean: false
fetch-depth: 0 fetch-depth: 0
@@ -44,7 +44,7 @@ jobs:
needs: style needs: style
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with: with:
clean: false clean: false
@@ -70,12 +70,12 @@ jobs:
ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON: ${{ secrets.ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON }} ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON: ${{ secrets.ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON }}
steps: steps:
- name: Install Node - name: Install Node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4 uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4
with: with:
node-version: "18" node-version: "18"
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with: with:
clean: false clean: false
@@ -109,7 +109,7 @@ jobs:
ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON: ${{ secrets.ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON }} ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON: ${{ secrets.ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON }}
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with: with:
clean: false clean: false
@@ -149,7 +149,7 @@ jobs:
ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON: ${{ secrets.ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON }} ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON: ${{ secrets.ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON }}
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with: with:
clean: false clean: false
@@ -182,7 +182,7 @@ jobs:
- bundle-linux-arm - bundle-linux-arm
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with: with:
fetch-depth: 0 fetch-depth: 0

View File

@@ -1,21 +0,0 @@
name: Script
on:
pull_request:
paths:
- "script/**"
push:
branches:
- main
jobs:
shellcheck:
name: "ShellCheck Scripts"
if: github.repository_owner == 'zed-industries'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: Shellcheck ./scripts
run: |
./script/shellcheck-scripts error

1
.gitignore vendored
View File

@@ -1,5 +1,4 @@
/.direnv /.direnv
.envrc
.idea .idea
**/target **/target
**/cargo-target **/cargo-target

View File

@@ -22,14 +22,10 @@ Antonio Scandurra <me@as-cii.com> <antonio@zed.dev>
Bennet Bo Fenner <bennet@zed.dev> Bennet Bo Fenner <bennet@zed.dev>
Bennet Bo Fenner <bennet@zed.dev> <53836821+bennetbo@users.noreply.github.com> Bennet Bo Fenner <bennet@zed.dev> <53836821+bennetbo@users.noreply.github.com>
Bennet Bo Fenner <bennet@zed.dev> <bennetbo@gmx.de> Bennet Bo Fenner <bennet@zed.dev> <bennetbo@gmx.de>
Boris Cherny <boris@anthropic.com>
Boris Cherny <boris@anthropic.com> <boris@performancejs.com>
Chris Hayes <chris+git@hayes.software>
Christian Bergschneider <christian.bergschneider@gmx.de> Christian Bergschneider <christian.bergschneider@gmx.de>
Christian Bergschneider <christian.bergschneider@gmx.de> <magiclake@gmx.de> Christian Bergschneider <christian.bergschneider@gmx.de> <magiclake@gmx.de>
Conrad Irwin <conrad@zed.dev> Conrad Irwin <conrad@zed.dev>
Conrad Irwin <conrad@zed.dev> <conrad.irwin@gmail.com> Conrad Irwin <conrad@zed.dev> <conrad.irwin@gmail.com>
Dairon Medina <dairon.medina@gmail.com>
Danilo Leal <danilo@zed.dev> Danilo Leal <danilo@zed.dev>
Danilo Leal <danilo@zed.dev> <67129314+danilo-leal@users.noreply.github.com> Danilo Leal <danilo@zed.dev> <67129314+danilo-leal@users.noreply.github.com>
Evren Sen <nervenes@icloud.com> Evren Sen <nervenes@icloud.com>
@@ -39,7 +35,6 @@ Fernando Tagawa <tagawafernando@gmail.com>
Fernando Tagawa <tagawafernando@gmail.com> <fernando.tagawa.gamail.com@gmail.com> Fernando Tagawa <tagawafernando@gmail.com> <fernando.tagawa.gamail.com@gmail.com>
Greg Morenz <greg-morenz@droid.cafe> Greg Morenz <greg-morenz@droid.cafe>
Greg Morenz <greg-morenz@droid.cafe> <morenzg@gmail.com> Greg Morenz <greg-morenz@droid.cafe> <morenzg@gmail.com>
Ihnat Aŭtuška <autushka.ihnat@gmail.com>
Ivan Žužak <izuzak@gmail.com> Ivan Žužak <izuzak@gmail.com>
Ivan Žužak <izuzak@gmail.com> <ivan.zuzak@github.com> Ivan Žužak <izuzak@gmail.com> <ivan.zuzak@github.com>
Joseph T. Lyons <JosephTLyons@gmail.com> Joseph T. Lyons <JosephTLyons@gmail.com>
@@ -65,14 +60,9 @@ Max Brunsfeld <maxbrunsfeld@gmail.com>
Max Brunsfeld <maxbrunsfeld@gmail.com> <max@zed.dev> Max Brunsfeld <maxbrunsfeld@gmail.com> <max@zed.dev>
Max Linke <maxlinke88@gmail.com> Max Linke <maxlinke88@gmail.com>
Max Linke <maxlinke88@gmail.com> <kain88-de@users.noreply.github.com> Max Linke <maxlinke88@gmail.com> <kain88-de@users.noreply.github.com>
Michael Sloan <michael@zed.dev>
Michael Sloan <michael@zed.dev> <mgsloan@gmail.com>
Michael Sloan <michael@zed.dev> <mgsloan@google.com>
Mikayla Maki <mikayla@zed.dev> Mikayla Maki <mikayla@zed.dev>
Mikayla Maki <mikayla@zed.dev> <mikayla.c.maki@gmail.com> Mikayla Maki <mikayla@zed.dev> <mikayla.c.maki@gmail.com>
Mikayla Maki <mikayla@zed.dev> <mikayla.c.maki@icloud.com> Mikayla Maki <mikayla@zed.dev> <mikayla.c.maki@icloud.com>
Muhammad Talal Anwar <mail@talal.io>
Muhammad Talal Anwar <mail@talal.io> <talalanwar@outlook.com>
Nate Butler <iamnbutler@gmail.com> Nate Butler <iamnbutler@gmail.com>
Nate Butler <iamnbutler@gmail.com> <nate@zed.dev> Nate Butler <iamnbutler@gmail.com> <nate@zed.dev>
Nathan Sobo <nathan@zed.dev> Nathan Sobo <nathan@zed.dev>
@@ -96,11 +86,7 @@ Robert Clover <git@clo4.net>
Robert Clover <git@clo4.net> <robert@clover.gdn> Robert Clover <git@clo4.net> <robert@clover.gdn>
Roy Williams <roy.williams.iii@gmail.com> Roy Williams <roy.williams.iii@gmail.com>
Roy Williams <roy.williams.iii@gmail.com> <roy@anthropic.com> Roy Williams <roy.williams.iii@gmail.com> <roy@anthropic.com>
Sebastijan Kelnerič <sebastijan.kelneric@sebba.dev>
Sebastijan Kelnerič <sebastijan.kelneric@sebba.dev> <sebastijan.kelneric@vichava.com>
Sergey Onufrienko <sergey@onufrienko.com> Sergey Onufrienko <sergey@onufrienko.com>
Shish <webmaster@shishnet.org>
Shish <webmaster@shishnet.org> <shish@shishnet.org>
Thorben Kröger <dev@thorben.net> Thorben Kröger <dev@thorben.net>
Thorben Kröger <dev@thorben.net> <thorben.kroeger@hexagon.com> Thorben Kröger <dev@thorben.net> <thorben.kroeger@hexagon.com>
Thorsten Ball <thorsten@zed.dev> Thorsten Ball <thorsten@zed.dev>

View File

@@ -1,3 +1,3 @@
# Code of Conduct # Code of Conduct
The Code of Conduct for this repository can be found online at [zed.dev/code-of-conduct](https://zed.dev/code-of-conduct). The Code of Conduct for this repository can be found online at [zed.dev/docs/code-of-conduct](https://zed.dev/docs/code-of-conduct).

View File

@@ -2,7 +2,7 @@
Thanks for your interest in contributing to Zed, the collaborative platform that is also a code editor! Thanks for your interest in contributing to Zed, the collaborative platform that is also a code editor!
All activity in Zed forums is subject to our [Code of Conduct](https://zed.dev/code-of-conduct). Additionally, contributors must sign our [Contributor License Agreement](https://zed.dev/cla) before their contributions can be merged. All activity in Zed forums is subject to our [Code of Conduct](https://zed.dev/docs/code-of-conduct). Additionally, contributors must sign our [Contributor License Agreement](https://zed.dev/cla) before their contributions can be merged.
## Contribution ideas ## Contribution ideas

4222
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -5,13 +5,10 @@ members = [
"crates/anthropic", "crates/anthropic",
"crates/assets", "crates/assets",
"crates/assistant", "crates/assistant",
"crates/assistant2",
"crates/assistant_slash_command", "crates/assistant_slash_command",
"crates/assistant_tool", "crates/assistant_tool",
"crates/assistant_tools",
"crates/audio", "crates/audio",
"crates/auto_update", "crates/auto_update",
"crates/auto_update_ui",
"crates/breadcrumbs", "crates/breadcrumbs",
"crates/call", "crates/call",
"crates/channel", "crates/channel",
@@ -23,10 +20,10 @@ members = [
"crates/collections", "crates/collections",
"crates/command_palette", "crates/command_palette",
"crates/command_palette_hooks", "crates/command_palette_hooks",
"crates/context_server", "crates/context_servers",
"crates/context_server_settings",
"crates/copilot", "crates/copilot",
"crates/db", "crates/db",
"crates/dev_server_projects",
"crates/diagnostics", "crates/diagnostics",
"crates/docs_preprocessor", "crates/docs_preprocessor",
"crates/editor", "crates/editor",
@@ -34,7 +31,6 @@ members = [
"crates/extension", "crates/extension",
"crates/extension_api", "crates/extension_api",
"crates/extension_cli", "crates/extension_cli",
"crates/extension_host",
"crates/extensions_ui", "crates/extensions_ui",
"crates/feature_flags", "crates/feature_flags",
"crates/feedback", "crates/feedback",
@@ -49,25 +45,21 @@ members = [
"crates/google_ai", "crates/google_ai",
"crates/gpui", "crates/gpui",
"crates/gpui_macros", "crates/gpui_macros",
"crates/headless",
"crates/html_to_markdown", "crates/html_to_markdown",
"crates/http_client", "crates/http_client",
"crates/image_viewer", "crates/image_viewer",
"crates/indexed_docs", "crates/indexed_docs",
"crates/inline_completion",
"crates/inline_completion_button", "crates/inline_completion_button",
"crates/install_cli", "crates/install_cli",
"crates/journal", "crates/journal",
"crates/language", "crates/language",
"crates/language_extension",
"crates/language_model", "crates/language_model",
"crates/language_model_selector",
"crates/language_models",
"crates/language_selector", "crates/language_selector",
"crates/language_tools", "crates/language_tools",
"crates/languages", "crates/languages",
"crates/livekit_client", "crates/live_kit_client",
"crates/livekit_client_macos", "crates/live_kit_server",
"crates/livekit_server",
"crates/lsp", "crates/lsp",
"crates/markdown", "crates/markdown",
"crates/markdown_preview", "crates/markdown_preview",
@@ -87,6 +79,7 @@ members = [
"crates/project_panel", "crates/project_panel",
"crates/project_symbols", "crates/project_symbols",
"crates/proto", "crates/proto",
"crates/quick_action_bar",
"crates/recent_projects", "crates/recent_projects",
"crates/refineable", "crates/refineable",
"crates/refineable/derive_refineable", "crates/refineable/derive_refineable",
@@ -122,12 +115,10 @@ members = [
"crates/terminal_view", "crates/terminal_view",
"crates/text", "crates/text",
"crates/theme", "crates/theme",
"crates/theme_extension",
"crates/theme_importer", "crates/theme_importer",
"crates/theme_selector", "crates/theme_selector",
"crates/time_format", "crates/time_format",
"crates/title_bar", "crates/title_bar",
"crates/toolchain_selector",
"crates/ui", "crates/ui",
"crates/ui_input", "crates/ui_input",
"crates/ui_macros", "crates/ui_macros",
@@ -135,7 +126,6 @@ members = [
"crates/util", "crates/util",
"crates/vcs_menu", "crates/vcs_menu",
"crates/vim", "crates/vim",
"crates/vim_mode_setting",
"crates/welcome", "crates/welcome",
"crates/workspace", "crates/workspace",
"crates/worktree", "crates/worktree",
@@ -149,6 +139,7 @@ members = [
"extensions/astro", "extensions/astro",
"extensions/clojure", "extensions/clojure",
"extensions/csharp", "extensions/csharp",
"extensions/dart",
"extensions/deno", "extensions/deno",
"extensions/elixir", "extensions/elixir",
"extensions/elm", "extensions/elm",
@@ -158,6 +149,7 @@ members = [
"extensions/haskell", "extensions/haskell",
"extensions/html", "extensions/html",
"extensions/lua", "extensions/lua",
"extensions/ocaml",
"extensions/php", "extensions/php",
"extensions/perplexity", "extensions/perplexity",
"extensions/prisma", "extensions/prisma",
@@ -191,13 +183,10 @@ ai = { path = "crates/ai" }
anthropic = { path = "crates/anthropic" } anthropic = { path = "crates/anthropic" }
assets = { path = "crates/assets" } assets = { path = "crates/assets" }
assistant = { path = "crates/assistant" } assistant = { path = "crates/assistant" }
assistant2 = { path = "crates/assistant2" }
assistant_slash_command = { path = "crates/assistant_slash_command" } assistant_slash_command = { path = "crates/assistant_slash_command" }
assistant_tool = { path = "crates/assistant_tool" } assistant_tool = { path = "crates/assistant_tool" }
assistant_tools = { path = "crates/assistant_tools" }
audio = { path = "crates/audio" } audio = { path = "crates/audio" }
auto_update = { path = "crates/auto_update" } auto_update = { path = "crates/auto_update" }
auto_update_ui = { path = "crates/auto_update_ui" }
breadcrumbs = { path = "crates/breadcrumbs" } breadcrumbs = { path = "crates/breadcrumbs" }
call = { path = "crates/call" } call = { path = "crates/call" }
channel = { path = "crates/channel" } channel = { path = "crates/channel" }
@@ -209,14 +198,13 @@ collab_ui = { path = "crates/collab_ui" }
collections = { path = "crates/collections" } collections = { path = "crates/collections" }
command_palette = { path = "crates/command_palette" } command_palette = { path = "crates/command_palette" }
command_palette_hooks = { path = "crates/command_palette_hooks" } command_palette_hooks = { path = "crates/command_palette_hooks" }
context_server = { path = "crates/context_server" } context_servers = { path = "crates/context_servers" }
context_server_settings = { path = "crates/context_server_settings" }
copilot = { path = "crates/copilot" } copilot = { path = "crates/copilot" }
db = { path = "crates/db" } db = { path = "crates/db" }
dev_server_projects = { path = "crates/dev_server_projects" }
diagnostics = { path = "crates/diagnostics" } diagnostics = { path = "crates/diagnostics" }
editor = { path = "crates/editor" } editor = { path = "crates/editor" }
extension = { path = "crates/extension" } extension = { path = "crates/extension" }
extension_host = { path = "crates/extension_host" }
extensions_ui = { path = "crates/extensions_ui" } extensions_ui = { path = "crates/extensions_ui" }
feature_flags = { path = "crates/feature_flags" } feature_flags = { path = "crates/feature_flags" }
feedback = { path = "crates/feedback" } feedback = { path = "crates/feedback" }
@@ -229,29 +217,23 @@ git = { path = "crates/git" }
git_hosting_providers = { path = "crates/git_hosting_providers" } git_hosting_providers = { path = "crates/git_hosting_providers" }
go_to_line = { path = "crates/go_to_line" } go_to_line = { path = "crates/go_to_line" }
google_ai = { path = "crates/google_ai" } google_ai = { path = "crates/google_ai" }
gpui = { path = "crates/gpui", default-features = false, features = [ gpui = { path = "crates/gpui", default-features = false, features = ["http_client"]}
"http_client",
] }
gpui_macros = { path = "crates/gpui_macros" } gpui_macros = { path = "crates/gpui_macros" }
headless = { path = "crates/headless" }
html_to_markdown = { path = "crates/html_to_markdown" } html_to_markdown = { path = "crates/html_to_markdown" }
http_client = { path = "crates/http_client" } http_client = { path = "crates/http_client" }
image_viewer = { path = "crates/image_viewer" } image_viewer = { path = "crates/image_viewer" }
indexed_docs = { path = "crates/indexed_docs" } indexed_docs = { path = "crates/indexed_docs" }
inline_completion = { path = "crates/inline_completion" }
inline_completion_button = { path = "crates/inline_completion_button" } inline_completion_button = { path = "crates/inline_completion_button" }
install_cli = { path = "crates/install_cli" } install_cli = { path = "crates/install_cli" }
journal = { path = "crates/journal" } journal = { path = "crates/journal" }
language = { path = "crates/language" } language = { path = "crates/language" }
language_extension = { path = "crates/language_extension" }
language_model = { path = "crates/language_model" } language_model = { path = "crates/language_model" }
language_model_selector = { path = "crates/language_model_selector" }
language_models = { path = "crates/language_models" }
language_selector = { path = "crates/language_selector" } language_selector = { path = "crates/language_selector" }
language_tools = { path = "crates/language_tools" } language_tools = { path = "crates/language_tools" }
languages = { path = "crates/languages" } languages = { path = "crates/languages" }
livekit_client = { path = "crates/livekit_client" } live_kit_client = { path = "crates/live_kit_client" }
livekit_client_macos = { path = "crates/livekit_client_macos" } live_kit_server = { path = "crates/live_kit_server" }
livekit_server = { path = "crates/livekit_server" }
lsp = { path = "crates/lsp" } lsp = { path = "crates/lsp" }
markdown = { path = "crates/markdown" } markdown = { path = "crates/markdown" }
markdown_preview = { path = "crates/markdown_preview" } markdown_preview = { path = "crates/markdown_preview" }
@@ -273,6 +255,7 @@ project = { path = "crates/project" }
project_panel = { path = "crates/project_panel" } project_panel = { path = "crates/project_panel" }
project_symbols = { path = "crates/project_symbols" } project_symbols = { path = "crates/project_symbols" }
proto = { path = "crates/proto" } proto = { path = "crates/proto" }
quick_action_bar = { path = "crates/quick_action_bar" }
recent_projects = { path = "crates/recent_projects" } recent_projects = { path = "crates/recent_projects" }
refineable = { path = "crates/refineable" } refineable = { path = "crates/refineable" }
release_channel = { path = "crates/release_channel" } release_channel = { path = "crates/release_channel" }
@@ -307,19 +290,16 @@ terminal = { path = "crates/terminal" }
terminal_view = { path = "crates/terminal_view" } terminal_view = { path = "crates/terminal_view" }
text = { path = "crates/text" } text = { path = "crates/text" }
theme = { path = "crates/theme" } theme = { path = "crates/theme" }
theme_extension = { path = "crates/theme_extension" }
theme_importer = { path = "crates/theme_importer" } theme_importer = { path = "crates/theme_importer" }
theme_selector = { path = "crates/theme_selector" } theme_selector = { path = "crates/theme_selector" }
time_format = { path = "crates/time_format" } time_format = { path = "crates/time_format" }
title_bar = { path = "crates/title_bar" } title_bar = { path = "crates/title_bar" }
toolchain_selector = { path = "crates/toolchain_selector" }
ui = { path = "crates/ui" } ui = { path = "crates/ui" }
ui_input = { path = "crates/ui_input" } ui_input = { path = "crates/ui_input" }
ui_macros = { path = "crates/ui_macros" } ui_macros = { path = "crates/ui_macros" }
util = { path = "crates/util" } util = { path = "crates/util" }
vcs_menu = { path = "crates/vcs_menu" } vcs_menu = { path = "crates/vcs_menu" }
vim = { path = "crates/vim" } vim = { path = "crates/vim" }
vim_mode_setting = { path = "crates/vim_mode_setting" }
welcome = { path = "crates/welcome" } welcome = { path = "crates/welcome" }
workspace = { path = "crates/workspace" } workspace = { path = "crates/workspace" }
worktree = { path = "crates/worktree" } worktree = { path = "crates/worktree" }
@@ -335,7 +315,7 @@ alacritty_terminal = { git = "https://github.com/alacritty/alacritty", rev = "91
any_vec = "0.14" any_vec = "0.14"
anyhow = "1.0.86" anyhow = "1.0.86"
arrayvec = { version = "0.7.4", features = ["serde"] } arrayvec = { version = "0.7.4", features = ["serde"] }
ashpd = { version = "0.10", default-features = false, features = ["async-std"]} ashpd = "0.9.1"
async-compat = "0.2.1" async-compat = "0.2.1"
async-compression = { version = "0.4", features = ["gzip", "futures-io"] } async-compression = { version = "0.4", features = ["gzip", "futures-io"] }
async-dispatcher = "0.1" async-dispatcher = "0.1"
@@ -344,7 +324,7 @@ async-pipe = { git = "https://github.com/zed-industries/async-pipe-rs", rev = "8
async-recursion = "1.0.0" async-recursion = "1.0.0"
async-tar = "0.5.0" async-tar = "0.5.0"
async-trait = "0.1" async-trait = "0.1"
async-tungstenite = "0.28" async-tungstenite = "0.24"
async-watch = "0.3.1" async-watch = "0.3.1"
async_zip = { version = "0.0.17", features = ["deflate", "deflate64"] } async_zip = { version = "0.0.17", features = ["deflate", "deflate64"] }
base64 = "0.22" base64 = "0.22"
@@ -354,13 +334,12 @@ blade-macros = { git = "https://github.com/kvark/blade", rev = "e142a3a5e678eb6a
blade-util = { git = "https://github.com/kvark/blade", rev = "e142a3a5e678eb6a13e642ad8401b1f3aa38e969" } blade-util = { git = "https://github.com/kvark/blade", rev = "e142a3a5e678eb6a13e642ad8401b1f3aa38e969" }
blake3 = "1.5.3" blake3 = "1.5.3"
bytes = "1.0" bytes = "1.0"
cargo_metadata = "0.19" cargo_metadata = "0.18"
cargo_toml = "0.20" cargo_toml = "0.20"
chrono = { version = "0.4", features = ["serde"] } chrono = { version = "0.4", features = ["serde"] }
clap = { version = "4.4", features = ["derive"] } clap = { version = "4.4", features = ["derive"] }
clickhouse = "0.11.6" clickhouse = "0.11.6"
cocoa = "0.26" cocoa = "0.26"
cocoa-foundation = "0.2.0"
convert_case = "0.6.0" convert_case = "0.6.0"
core-foundation = "0.9.3" core-foundation = "0.9.3"
core-foundation-sys = "0.8.6" core-foundation-sys = "0.8.6"
@@ -372,7 +351,6 @@ ec4rs = "1.1"
emojis = "0.6.1" emojis = "0.6.1"
env_logger = "0.11" env_logger = "0.11"
exec = "0.3.1" exec = "0.3.1"
fancy-regex = "0.14.0"
fork = "0.2.0" fork = "0.2.0"
futures = "0.3" futures = "0.3"
futures-batch = "0.6.1" futures-batch = "0.6.1"
@@ -384,23 +362,17 @@ heed = { version = "0.20.1", features = ["read-txn-no-tls"] }
hex = "0.4.3" hex = "0.4.3"
html5ever = "0.27.0" html5ever = "0.27.0"
hyper = "0.14" hyper = "0.14"
http = "1.1"
ignore = "0.4.22" ignore = "0.4.22"
image = "0.25.1" image = "0.25.1"
indexmap = { version = "1.6.2", features = ["serde"] } indexmap = { version = "1.6.2", features = ["serde"] }
indoc = "2" indoc = "2"
itertools = "0.13.0" itertools = "0.13.0"
jsonwebtoken = "9.3" jsonwebtoken = "9.3"
jupyter-protocol = { version = "0.5.0" }
jupyter-websocket-client = { version = "0.8.0" }
libc = "0.2" libc = "0.2"
libsqlite3-sys = { version = "0.30.1", features = ["bundled"] }
linkify = "0.10.0" linkify = "0.10.0"
livekit = { git = "https://github.com/zed-industries/rust-sdks", rev="799f10133d93ba2a88642cd480d01ec4da53408c", features = ["dispatcher", "services-dispatcher", "rustls-tls-native-roots"], default-features = false }
log = { version = "0.4.16", features = ["kv_unstable_serde", "serde"] } log = { version = "0.4.16", features = ["kv_unstable_serde", "serde"] }
markup5ever_rcdom = "0.3.0" markup5ever_rcdom = "0.3.0"
nanoid = "0.4" nanoid = "0.4"
nbformat = { version = "0.9.0" }
nix = "0.29" nix = "0.29"
num-format = "0.4.4" num-format = "0.4.4"
once_cell = "1.19.0" once_cell = "1.19.0"
@@ -408,21 +380,14 @@ ordered-float = "2.1.1"
palette = { version = "0.7.5", default-features = false, features = ["std"] } palette = { version = "0.7.5", default-features = false, features = ["std"] }
parking_lot = "0.12.1" parking_lot = "0.12.1"
pathdiff = "0.2" pathdiff = "0.2"
pet = { git = "https://github.com/microsoft/python-environment-tools.git", rev = "ffcbf3f28c46633abd5448a52b1f396c322e0d6c" }
pet-fs = { git = "https://github.com/microsoft/python-environment-tools.git", rev = "ffcbf3f28c46633abd5448a52b1f396c322e0d6c" }
pet-conda = { git = "https://github.com/microsoft/python-environment-tools.git", rev = "ffcbf3f28c46633abd5448a52b1f396c322e0d6c" }
pet-core = { git = "https://github.com/microsoft/python-environment-tools.git", rev = "ffcbf3f28c46633abd5448a52b1f396c322e0d6c" }
pet-poetry = { git = "https://github.com/microsoft/python-environment-tools.git", rev = "ffcbf3f28c46633abd5448a52b1f396c322e0d6c" }
pet-reporter = { git = "https://github.com/microsoft/python-environment-tools.git", rev = "ffcbf3f28c46633abd5448a52b1f396c322e0d6c" }
postage = { version = "0.5", features = ["futures-traits"] } postage = { version = "0.5", features = ["futures-traits"] }
pretty_assertions = { version = "1.3.0", features = ["unstable"] } pretty_assertions = "1.3.0"
profiling = "1" profiling = "1"
prost = "0.9" prost = "0.9"
prost-build = "0.9" prost-build = "0.9"
prost-types = "0.9" prost-types = "0.9"
pulldown-cmark = { version = "0.12.0", default-features = false } pulldown-cmark = { version = "0.12.0", default-features = false }
rand = "0.8.5" rand = "0.8.5"
rayon = "1.8"
regex = "1.5" regex = "1.5"
repair_json = "0.1.0" repair_json = "0.1.0"
reqwest = { git = "https://github.com/zed-industries/reqwest.git", rev = "fd110f6998da16bbca97b6dddda9be7827c50e29", default-features = false, features = [ reqwest = { git = "https://github.com/zed-industries/reqwest.git", rev = "fd110f6998da16bbca97b6dddda9be7827c50e29", default-features = false, features = [
@@ -434,12 +399,12 @@ reqwest = { git = "https://github.com/zed-industries/reqwest.git", rev = "fd110f
"stream", "stream",
] } ] }
rsa = "0.9.6" rsa = "0.9.6"
runtimelib = { version = "0.24.0", default-features = false, features = [ runtimelib = { version = "0.15", default-features = false, features = [
"async-dispatcher-runtime", "async-dispatcher-runtime",
] } ] }
rustc-demangle = "0.1.23" rustc-demangle = "0.1.23"
rust-embed = { version = "8.4", features = ["include-exclude"] } rust-embed = { version = "8.4", features = ["include-exclude"] }
rustls = "0.21.12" rustls = "0.20.3"
rustls-native-certs = "0.8.0" rustls-native-certs = "0.8.0"
schemars = { version = "0.8", features = ["impl_json_schema"] } schemars = { version = "0.8", features = ["impl_json_schema"] }
semver = "1.0" semver = "1.0"
@@ -494,7 +459,7 @@ tree-sitter-diff = "0.1.0"
tree-sitter-html = "0.20" tree-sitter-html = "0.20"
tree-sitter-jsdoc = "0.23" tree-sitter-jsdoc = "0.23"
tree-sitter-json = "0.23" tree-sitter-json = "0.23"
tree-sitter-md = { git = "https://github.com/tree-sitter-grammars/tree-sitter-markdown", rev = "9a23c1a96c0513d8fc6520972beedd419a973539" } tree-sitter-md = { git = "https://github.com/zed-industries/tree-sitter-markdown", rev = "4cfa6aad6b75052a5077c80fd934757d9267d81b" }
tree-sitter-python = "0.23" tree-sitter-python = "0.23"
tree-sitter-regex = "0.23" tree-sitter-regex = "0.23"
tree-sitter-ruby = "0.23" tree-sitter-ruby = "0.23"
@@ -504,9 +469,8 @@ tree-sitter-yaml = { git = "https://github.com/zed-industries/tree-sitter-yaml",
unicase = "2.6" unicase = "2.6"
unindent = "0.1.7" unindent = "0.1.7"
unicode-segmentation = "1.10" unicode-segmentation = "1.10"
unicode-script = "0.5.7"
url = "2.2" url = "2.2"
uuid = { version = "1.1.2", features = ["v4", "v5", "v7", "serde"] } uuid = { version = "1.1.2", features = ["v4", "v5", "serde"] }
wasmparser = "0.215" wasmparser = "0.215"
wasm-encoder = "0.215" wasm-encoder = "0.215"
wasmtime = { version = "24", default-features = false, features = [ wasmtime = { version = "24", default-features = false, features = [
@@ -575,10 +539,6 @@ features = [
"Win32_UI_WindowsAndMessaging", "Win32_UI_WindowsAndMessaging",
] ]
# TODO livekit https://github.com/RustAudio/cpal/pull/891
[patch.crates-io]
cpal = { git = "https://github.com/zed-industries/cpal", rev = "fd8bc2fd39f1f5fdee5a0690656caff9a26d9d50" }
[profile.dev] [profile.dev]
split-debuginfo = "unpacked" split-debuginfo = "unpacked"
debug = "limited" debug = "limited"
@@ -592,46 +552,6 @@ rustybuzz = { opt-level = 3 }
ttf-parser = { opt-level = 3 } ttf-parser = { opt-level = 3 }
wasmtime-cranelift = { opt-level = 3 } wasmtime-cranelift = { opt-level = 3 }
wasmtime = { opt-level = 3 } wasmtime = { opt-level = 3 }
# Build single-source-file crates with cg=1 as it helps make `cargo build` of a whole workspace a bit faster
activity_indicator = { codegen-units = 1 }
assets = { codegen-units = 1 }
breadcrumbs = { codegen-units = 1 }
collections = { codegen-units = 1 }
command_palette = { codegen-units = 1 }
command_palette_hooks = { codegen-units = 1 }
evals = { codegen-units = 1 }
extension_cli = { codegen-units = 1 }
feature_flags = { codegen-units = 1 }
file_icons = { codegen-units = 1 }
fsevent = { codegen-units = 1 }
image_viewer = { codegen-units = 1 }
inline_completion_button = { codegen-units = 1 }
install_cli = { codegen-units = 1 }
journal = { codegen-units = 1 }
menu = { codegen-units = 1 }
notifications = { codegen-units = 1 }
ollama = { codegen-units = 1 }
outline = { codegen-units = 1 }
paths = { codegen-units = 1 }
prettier = { codegen-units = 1 }
project_symbols = { codegen-units = 1 }
refineable = { codegen-units = 1 }
release_channel = { codegen-units = 1 }
reqwest_client = { codegen-units = 1 }
rich_text = { codegen-units = 1 }
semantic_version = { codegen-units = 1 }
session = { codegen-units = 1 }
snippet = { codegen-units = 1 }
snippets_ui = { codegen-units = 1 }
sqlez_macros = { codegen-units = 1 }
story = { codegen-units = 1 }
supermaven_api = { codegen-units = 1 }
telemetry_events = { codegen-units = 1 }
theme_selector = { codegen-units = 1 }
time_format = { codegen-units = 1 }
ui_input = { codegen-units = 1 }
vcs_menu = { codegen-units = 1 }
zed_actions = { codegen-units = 1 }
[profile.release] [profile.release]
debug = "limited" debug = "limited"
@@ -681,7 +601,6 @@ new_ret_no_self = { level = "allow" }
# We have a few `next` functions that differ in lifetimes # We have a few `next` functions that differ in lifetimes
# compared to Iterator::next. Yet, clippy complains about those. # compared to Iterator::next. Yet, clippy complains about those.
should_implement_trait = { level = "allow" } should_implement_trait = { level = "allow" }
let_underscore_future = "allow"
[workspace.metadata.cargo-machete] [workspace.metadata.cargo-machete]
ignored = ["bindgen", "cbindgen", "prost_build", "serde"] ignored = ["bindgen", "cbindgen", "prost_build", "serde"]

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-blocks"><rect width="7" height="7" x="14" y="3" rx="1"/><path d="M10 21V8a1 1 0 0 0-1-1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-5a1 1 0 0 0-1-1H3"/></svg>

Before

Width:  |  Height:  |  Size: 368 B

View File

@@ -1,5 +1 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-text-cursor"><path d="M17 22h-1a4 4 0 0 1-4-4V6a4 4 0 0 1 4-4h1"/><path d="M7 22h1a4 4 0 0 0 4-4v-1"/><path d="M7 2h1a4 4 0 0 1 4 4v1"/></svg>
<path d="M17 20H16C14.9391 20 13.9217 19.6629 13.1716 19.0627C12.4214 18.4626 12 17.6487 12 16.8V7.2C12 6.35131 12.4214 5.53737 13.1716 4.93726C13.9217 4.33714 14.9391 4 16 4H17" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M7 20H8C9.06087 20 10.0783 19.5786 10.8284 18.8284C11.5786 18.0783 12 17.0609 12 16V15" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M7 4H8C9.06087 4 10.0783 4.42143 10.8284 5.17157C11.5786 5.92172 12 6.93913 12 8V9" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 715 B

After

Width:  |  Height:  |  Size: 345 B

View File

@@ -1,8 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3.5 6.66666V8.66666" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M9.20721 10.8551C7.67694 10.8551 6.33401 11.0424 5.52243 11.1878C5.15088 11.2543 4.808 10.9114 4.87454 10.5399C5.01987 9.72825 5.20721 8.38532 5.20721 6.85505C5.20721 5.69375 5.09932 4.64034 4.98377 3.84516C4.9431 3.56522 5.40267 3.3722 5.5684 3.60145C6.30333 4.61809 7.44022 6.08806 8.70721 7.35505C9.9742 8.62204 11.4442 9.75893 12.4608 10.4939C12.69 10.6596 12.497 11.1192 12.2171 11.0785C11.4219 10.963 10.3685 10.8551 9.20721 10.8551Z" fill="black" stroke="black" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M5.5 5V11" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M7.11129 10.6816L5.28324 8.85355C5.08798 8.65829 4.7714 8.65829 4.57613 8.85355L3.35355 10.0761C3.15829 10.2714 3.15829 10.588 3.35355 10.7832L5.1816 12.6113C5.37686 12.8066 5.69345 12.8066 5.88871 12.6113L7.11129 11.3887C7.30655 11.1934 7.30655 10.8769 7.11129 10.6816Z" fill="black"/>
<path d="M7.5 3V13" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M9.5 5.33334V10" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M11.5 4V12" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M13.5 6.66666V8.66666" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 751 B

After

Width:  |  Height:  |  Size: 946 B

View File

@@ -1,5 +0,0 @@
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.5 3L8.5 10" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M5 6.5H12" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M5 13H12" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 415 B

View File

@@ -34,7 +34,6 @@
"dat": "storage", "dat": "storage",
"db": "storage", "db": "storage",
"dbf": "storage", "dbf": "storage",
"diff": "diff",
"dll": "storage", "dll": "storage",
"doc": "document", "doc": "document",
"docx": "document", "docx": "document",
@@ -59,7 +58,6 @@
"gitignore": "vcs", "gitignore": "vcs",
"gitkeep": "vcs", "gitkeep": "vcs",
"gitmodules": "vcs", "gitmodules": "vcs",
"gleam": "gleam",
"go": "go", "go": "go",
"gql": "graphql", "gql": "graphql",
"graphql": "graphql", "graphql": "graphql",
@@ -67,7 +65,6 @@
"h": "c", "h": "c",
"handlebars": "code", "handlebars": "code",
"hbs": "template", "hbs": "template",
"hcl": "hcl",
"heex": "elixir", "heex": "elixir",
"heic": "image", "heic": "image",
"heif": "image", "heif": "image",
@@ -85,7 +82,6 @@
"j2k": "image", "j2k": "image",
"java": "java", "java": "java",
"jfif": "image", "jfif": "image",
"jl": "julia",
"jp2": "image", "jp2": "image",
"jpeg": "image", "jpeg": "image",
"jpg": "image", "jpg": "image",
@@ -113,7 +109,6 @@
"mkv": "video", "mkv": "video",
"ml": "ocaml", "ml": "ocaml",
"mli": "ocaml", "mli": "ocaml",
"mod": "go",
"mov": "video", "mov": "video",
"mp3": "audio", "mp3": "audio",
"mp4": "video", "mp4": "video",
@@ -121,7 +116,6 @@
"myd": "storage", "myd": "storage",
"myi": "storage", "myi": "storage",
"nim": "nim", "nim": "nim",
"nix": "nix",
"nu": "terminal", "nu": "terminal",
"odp": "document", "odp": "document",
"ods": "document", "ods": "document",
@@ -129,7 +123,6 @@
"ogg": "audio", "ogg": "audio",
"opus": "audio", "opus": "audio",
"otf": "font", "otf": "font",
"pcss": "css",
"pdb": "storage", "pdb": "storage",
"pdf": "document", "pdf": "document",
"php": "php", "php": "php",
@@ -150,15 +143,12 @@
"rb": "ruby", "rb": "ruby",
"rebar.config": "erlang", "rebar.config": "erlang",
"rkt": "code", "rkt": "code",
"roc": "roc",
"rs": "rust", "rs": "rust",
"rtf": "document", "rtf": "document",
"sass": "sass",
"sav": "storage", "sav": "storage",
"sc": "scala", "sc": "scala",
"scala": "scala", "scala": "scala",
"scm": "code", "scm": "code",
"scss": "sass",
"sdf": "storage", "sdf": "storage",
"sh": "terminal", "sh": "terminal",
"sql": "storage", "sql": "storage",
@@ -176,9 +166,6 @@
"tsx": "react", "tsx": "react",
"ttf": "font", "ttf": "font",
"txt": "document", "txt": "document",
"v": "v",
"vsh": "v",
"vv": "v",
"vue": "vue", "vue": "vue",
"wav": "audio", "wav": "audio",
"webm": "video", "webm": "video",
@@ -187,7 +174,6 @@
"wmv": "video", "wmv": "video",
"woff": "font", "woff": "font",
"woff2": "font", "woff2": "font",
"work": "go",
"wv": "audio", "wv": "audio",
"xls": "document", "xls": "document",
"xlsx": "document", "xlsx": "document",
@@ -196,7 +182,6 @@
"yaml": "settings", "yaml": "settings",
"yml": "settings", "yml": "settings",
"yrl": "erlang", "yrl": "erlang",
"zig": "zig",
"zlogin": "terminal", "zlogin": "terminal",
"zsh": "terminal", "zsh": "terminal",
"zsh_aliases": "terminal", "zsh_aliases": "terminal",
@@ -242,9 +227,6 @@
"default": { "default": {
"icon": "icons/file_icons/file.svg" "icon": "icons/file_icons/file.svg"
}, },
"diff": {
"icon": "icons/file_icons/diff.svg"
},
"docker": { "docker": {
"icon": "icons/file_icons/docker.svg" "icon": "icons/file_icons/docker.svg"
}, },
@@ -275,9 +257,6 @@
"fsharp": { "fsharp": {
"icon": "icons/file_icons/fsharp.svg" "icon": "icons/file_icons/fsharp.svg"
}, },
"gleam": {
"icon": "icons/file_icons/gleam.svg"
},
"go": { "go": {
"icon": "icons/file_icons/go.svg" "icon": "icons/file_icons/go.svg"
}, },
@@ -287,9 +266,6 @@
"haskell": { "haskell": {
"icon": "icons/file_icons/haskell.svg" "icon": "icons/file_icons/haskell.svg"
}, },
"hcl": {
"icon": "icons/file_icons/hcl.svg"
},
"heroku": { "heroku": {
"icon": "icons/file_icons/heroku.svg" "icon": "icons/file_icons/heroku.svg"
}, },
@@ -302,9 +278,6 @@
"javascript": { "javascript": {
"icon": "icons/file_icons/javascript.svg" "icon": "icons/file_icons/javascript.svg"
}, },
"julia": {
"icon": "icons/file_icons/julia.svg"
},
"kotlin": { "kotlin": {
"icon": "icons/file_icons/kotlin.svg" "icon": "icons/file_icons/kotlin.svg"
}, },
@@ -320,9 +293,6 @@
"nim": { "nim": {
"icon": "icons/file_icons/nim.svg" "icon": "icons/file_icons/nim.svg"
}, },
"nix": {
"icon": "icons/file_icons/nix.svg"
},
"ocaml": { "ocaml": {
"icon": "icons/file_icons/ocaml.svg" "icon": "icons/file_icons/ocaml.svg"
}, },
@@ -347,18 +317,12 @@
"react": { "react": {
"icon": "icons/file_icons/react.svg" "icon": "icons/file_icons/react.svg"
}, },
"roc": {
"icon": "icons/file_icons/roc.svg"
},
"ruby": { "ruby": {
"icon": "icons/file_icons/ruby.svg" "icon": "icons/file_icons/ruby.svg"
}, },
"rust": { "rust": {
"icon": "icons/file_icons/rust.svg" "icon": "icons/file_icons/rust.svg"
}, },
"sass": {
"icon": "icons/file_icons/sass.svg"
},
"scala": { "scala": {
"icon": "icons/file_icons/scala.svg" "icon": "icons/file_icons/scala.svg"
}, },
@@ -389,9 +353,6 @@
"typescript": { "typescript": {
"icon": "icons/file_icons/typescript.svg" "icon": "icons/file_icons/typescript.svg"
}, },
"v": {
"icon": "icons/file_icons/v.svg"
},
"vcs": { "vcs": {
"icon": "icons/file_icons/git.svg" "icon": "icons/file_icons/git.svg"
}, },
@@ -400,9 +361,6 @@
}, },
"vue": { "vue": {
"icon": "icons/file_icons/vue.svg" "icon": "icons/file_icons/vue.svg"
},
"zig": {
"icon": "icons/file_icons/zig.svg"
} }
} }
} }

View File

@@ -1,7 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7.3848 9.30444C7.3848 9.30444 7.53254 10.2646 8.53248 10.0882C9.53242 9.91193 9.36378 8.95549 9.36378 8.95549" stroke="black" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M5.54155 5.54157C6.12355 4.90104 6.01688 2.62541 7.22875 2.3985C8.44063 2.17158 9.19097 4.33148 9.91982 4.6814C10.6487 5.03133 12.8517 4.3028 13.4381 5.38734C14.0244 6.47188 12.1395 7.95973 12.026 8.64088C11.9126 9.32203 13.3614 11.2416 12.4675 12.1701C11.5736 13.0986 9.73005 11.7545 8.90486 11.8834C8.07966 12.0123 6.79244 13.9095 5.67367 13.3502C4.55491 12.7909 5.16702 10.5455 4.82437 9.87612C4.48171 9.20673 2.34028 8.54978 2.4525 7.35049C2.56471 6.15121 4.95956 6.1821 5.54155 5.54157Z" stroke="#FF7676" stroke-opacity="0.52" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M5.54155 5.54157C6.12355 4.90104 6.01688 2.62541 7.22875 2.3985C8.44063 2.17158 9.19097 4.33148 9.91982 4.6814C10.6487 5.03133 12.8517 4.3028 13.4381 5.38734C14.0244 6.47188 12.1395 7.95973 12.026 8.64088C11.9126 9.32203 13.3614 11.2416 12.4675 12.1701C11.5736 13.0986 9.73005 11.7545 8.90486 11.8834C8.07966 12.0123 6.79244 13.9095 5.67367 13.3502C4.55491 12.7909 5.16702 10.5455 4.82437 9.87612C4.48171 9.20673 2.34028 8.54978 2.4525 7.35049C2.56471 6.15121 4.95956 6.1821 5.54155 5.54157Z" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="6.25098" cy="7.75" r="0.75" fill="black"/>
<circle cx="10.1035" cy="7.25" r="0.75" fill="black"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.11466 3.11809C7.21859 3.37393 7.09545 3.66558 6.83961 3.76952L4.31181 4.79643C4.1233 4.87302 4 5.05619 4 5.25967V11.5C4 11.7761 3.77614 12 3.5 12H2.5C2.22386 12 2 11.7761 2 11.5V4.41827C2 3.90959 2.30825 3.45164 2.77953 3.26018L6.08686 1.91658C6.34269 1.81265 6.63434 1.93579 6.73828 2.19163L7.11466 3.11809ZM10.5 1.99999C10.7761 1.99999 11 2.22384 11 2.49999V10.5C11 10.7761 10.7761 11 10.5 11H9.5C9.22386 11 9 10.7761 9 10.5V9.49999C9 9.22384 8.77614 8.99999 8.5 8.99999H7.5C7.22386 8.99999 7 9.22384 7 9.49999V13.5C7 13.7761 6.77614 14 6.5 14H5.5C5.22386 14 5 13.7761 5 13.5V5.53124C5 5.25509 5.22386 5.03124 5.5 5.03124H6.5C6.77614 5.03124 7 5.25509 7 5.53124V6.49999C7 6.77613 7.22386 6.99999 7.5 6.99999H8.5C8.77614 6.99999 9 6.77613 9 6.49999V2.49999C9 2.22384 9.22386 1.99999 9.5 1.99999H10.5ZM13.5 4.03124C13.7761 4.03124 14 4.2551 14 4.53124L14 11.5847C14 12.0859 13.7006 12.5386 13.2394 12.7349L9.99399 14.1159C9.7399 14.224 9.44626 14.1057 9.33813 13.8516L8.94658 12.9315C8.83845 12.6774 8.95678 12.3837 9.21087 12.2756L11.6958 11.2182C11.8802 11.1397 12 10.9586 12 10.7581L12 4.53124C12 4.2551 12.2238 4.03124 12.5 4.03124L13.5 4.03124Z" fill="black"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -1,5 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="8" cy="5" r="2.75" fill="black"/>
<circle cx="4.75" cy="11" r="2.75" fill="black" fill-opacity="0.5"/>
<circle cx="11.25" cy="11" r="2.75" fill="black" fill-opacity="0.75"/>
</svg>

Before

Width:  |  Height:  |  Size: 289 B

View File

@@ -1,8 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6.00005 4.76556L4.76569 2.74996M6.00005 4.76556L3.75 4.76563M6.00005 4.76556L7.25006 4.7656" stroke="black" stroke-width="1.5" stroke-linecap="round"/>
<path d="M10.0232 11.2311L11.2675 13.2406M10.0232 11.2311L12.2732 11.2199M10.0232 11.2311L8.7732 11.2373" stroke="black" stroke-opacity="0.5" stroke-width="1.5" stroke-linecap="round"/>
<path d="M9.99025 4.91551L10.9985 2.77781M9.99025 4.91551L8.75599 3.03419M9.99025 4.91551L10.6759 5.9607" stroke="black" stroke-opacity="0.5" stroke-width="1.5" stroke-linecap="round"/>
<path d="M6.0323 11.1009L5.03465 13.2436M6.0323 11.1009L7.27585 12.9761M6.0323 11.1009L5.34151 10.0592" stroke="black" stroke-width="1.5" stroke-linecap="round"/>
<path d="M11.883 8.19023L14.2466 8.19287M11.883 8.19023L13.0602 6.27268M11.883 8.19023L11.229 9.25547" stroke="black" stroke-width="1.5" stroke-linecap="round"/>
<path d="M4.12354 7.8356L1.76002 7.84465M4.12354 7.8356L2.95585 9.75894M4.12354 7.8356L4.7723 6.76713" stroke="black" stroke-opacity="0.5" stroke-width="1.5" stroke-linecap="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -1,7 +0,0 @@
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.51497 2.02702L1.92042 1.95067C1.69543 1.94589 1.57917 2.21756 1.73796 2.37702L6.24865 6.9068C6.42388 7.08277 6.72071 6.92326 6.67067 6.68002L5.75454 2.22659C5.73103 2.11231 5.63161 2.02949 5.51497 2.02702Z" fill="black" fill-opacity="0.5"/>
<path d="M8.05816 7.38492L12.1366 8.02844C12.3704 8.06532 12.5198 7.78697 12.3599 7.61255L7.30439 2.09814C7.13336 1.91159 6.82522 2.06811 6.87499 2.31624L7.852 7.18714C7.87257 7.28971 7.95483 7.36862 8.05816 7.38492Z" fill="black"/>
<path d="M9.0952 10.9797L11.3824 9.35081C11.564 9.22151 11.4983 8.93722 11.2785 8.90058L8.496 8.43683C8.31974 8.40746 8.17047 8.56712 8.21162 8.74101L8.70689 10.8337C8.74777 11.0064 8.95062 11.0827 9.0952 10.9797Z" fill="black" fill-opacity="0.5"/>
<path d="M5.10282 13.9632L7.59108 12.4532C7.68331 12.3972 7.72923 12.2884 7.70498 12.1832L6.75736 8.07484C6.699 7.8218 6.34133 7.81448 6.27266 8.06491L4.73201 13.6834C4.67223 13.9014 4.90954 14.0805 5.10282 13.9632Z" fill="black"/>
<path d="M11.3183 4.89351L13.1588 7.03149L15.535 6.14302C15.7099 6.07761 15.754 5.85043 15.6161 5.72438L13.7222 3.99219L11.4546 4.48614C11.2695 4.52645 11.1947 4.74995 11.3183 4.89351Z" fill="black"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.92096 7.00668C7.87408 7.83549 10.0987 7.48203 10.9376 7.06254C12.8751 6.09381 13.9407 4.39379 12.6407 2.90629C11.0157 1.04692 6.24221 2.49998 4.89844 3.40625C3.55467 4.31252 2.67972 5.53126 2.89071 7.1719C3.1017 8.81254 4.68758 9.7422 6.03128 10.3203C5.38786 10.5616 3.8517 11.0388 3.3125 11.7188C2.71341 12.4742 3.04343 14 4.51577 14C7.15639 14 7.59539 11.1486 7.14847 10.4375C7.88773 10.1295 8.49597 9.96169 9.40138 9.77081C9.63831 9.72087 9.65457 9.46395 9.41295 9.44827C8.80252 9.40864 7.30567 9.8489 6.92096 9.97657C5.78909 9.35157 4.51016 7.93818 4.59378 6.87501C4.68676 5.6928 5.27676 5.07603 6.84508 4.21876C8.01705 3.57813 10.258 3.10695 11.25 3.62501C12.6563 4.35936 10.7875 5.75599 9.92969 6.32031C9.28179 6.74656 8.21971 6.77513 7.22979 6.61435C6.99371 6.576 6.74048 6.84974 6.92096 7.00668ZM5.6719 12.4643C6.35508 11.9894 6.45471 11.1076 6.29955 10.8844C5.76663 11.0874 4.36593 11.9102 4.75111 12.4643C4.90628 12.6875 5.31358 12.7134 5.6719 12.4643Z" fill="black"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -1,4 +0,0 @@
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path opacity="0.5" d="M10.0469 12.8661L13.3884 3.31889C13.4386 3.1754 13.3167 3.03055 13.1667 3.05554L10.7292 3.46179C10.5875 3.48542 10.4693 3.58324 10.4197 3.71807L7.24789 12.3271C7.12763 12.6536 7.36919 13 7.71706 13H9.8581C9.94309 13 10.0188 12.9463 10.0469 12.8661Z" fill="black"/>
<path d="M6.90625 12.7321L3.61161 3.31889C3.56139 3.1754 3.6833 3.03055 3.83326 3.05554L6.27076 3.46179C6.4125 3.48542 6.53067 3.58324 6.58034 3.71807L9.90084 12.7309C9.94895 12.8614 9.85232 13 9.71317 13H7.28379C7.11381 13 6.9624 12.8926 6.90625 12.7321Z" fill="black"/>
</svg>

Before

Width:  |  Height:  |  Size: 663 B

View File

@@ -1,5 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14.25 12H11C10.794 12 10.6764 11.7648 10.8 11.6L11.925 10.1C11.9722 10.037 12.0463 10 12.125 10H12.75C12.8881 10 13 9.88807 13 9.75V6.25C13 6.11193 12.8881 6 12.75 6H12.4045C12.2187 6 12.0978 5.80442 12.1809 5.6382L12.9309 4.1382C12.9732 4.0535 13.0598 4 13.1545 4H14.25C14.3881 4 14.5 4.11193 14.5 4.25V11.75C14.5 11.8881 14.3881 12 14.25 12Z" fill="black"/>
<path d="M1.75 4H5C5.20601 4 5.32361 4.23519 5.2 4.4L4.075 5.9C4.02779 5.96295 3.95369 6 3.875 6H3.25C3.11193 6 3 6.11193 3 6.25V9.75C3 9.88807 3.11193 10 3.25 10H3.59549C3.78134 10 3.90221 10.1956 3.8191 10.3618L3.0691 11.8618C3.02675 11.9465 2.94018 12 2.84549 12H1.75C1.61193 12 1.5 11.8881 1.5 11.75V4.25C1.5 4.11193 1.61193 4 1.75 4Z" fill="black"/>
<path d="M7.55748 6H5.95006C5.74177 6 5.62482 5.76022 5.75306 5.59609L6.92493 4.09609C6.97231 4.03544 7.04498 4 7.12194 4H9.93075C9.97607 4 10.0205 3.98769 10.0594 3.96437L11.6408 3.0155C11.8641 2.88154 12.1179 3.13555 11.9837 3.3587L8.22612 9.6083C8.12629 9.77433 8.24508 9.98591 8.43881 9.98712L10.0039 9.9969C10.2092 9.99818 10.3255 10.2327 10.2023 10.3969L9.075 11.9C9.02779 11.963 8.95369 12 8.875 12H6.55383C6.51835 12 6.48328 12.0076 6.45094 12.0222L4.32473 12.9824C4.10122 13.0833 3.88113 12.8356 4.00771 12.6255L7.77161 6.37903C7.87201 6.2124 7.75202 6 7.55748 6Z" fill="black"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-file-search"><path d="M14 2v4a2 2 0 0 0 2 2h4"/><path d="M4.268 21a2 2 0 0 0 1.727 1H18a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v3"/><path d="m9 18-1.5-1.5"/><circle cx="5" cy="14" r="3"/></svg>

Before

Width:  |  Height:  |  Size: 393 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-globe"><circle cx="12" cy="12" r="10"/><path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"/><path d="M2 12h20"/></svg>

Before

Width:  |  Height:  |  Size: 327 B

View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.4662 14.9152C13.5801 15.0291 13.7648 15.0291 13.8787 14.9152L14.9145 13.8793C15.0284 13.7654 15.0284 13.5807 14.9145 13.4667L12.9483 11.5004L14.9145 9.53392C15.0285 9.42004 15.0285 9.23533 14.9145 9.12137L13.8787 8.08547C13.7648 7.97154 13.5801 7.97154 13.4662 8.08547L11.5 10.0519L9.53376 8.08545C9.41988 7.97152 9.23517 7.97152 9.12124 8.08545L8.08543 9.12136C7.97152 9.23533 7.97152 9.42004 8.08543 9.53392L10.0517 11.5004L8.08545 13.4667C7.97155 13.5807 7.97155 13.7654 8.08545 13.8793L9.12126 14.9152C9.23517 15.0292 9.41988 15.0292 9.53376 14.9152L11.5 12.9489L13.4662 14.9152Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 756 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-keyboard"><path d="M10 8h.01"/><path d="M12 12h.01"/><path d="M14 8h.01"/><path d="M16 12h.01"/><path d="M18 8h.01"/><path d="M6 8h.01"/><path d="M7 16h10"/><path d="M8 12h.01"/><rect width="20" height="16" x="2" y="4" rx="2"/></svg>

Before

Width:  |  Height:  |  Size: 436 B

View File

@@ -1,3 +0,0 @@
<svg width="11" height="11" viewBox="0 0 11 11" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="2.1" y="2.1" width="6.8" height="6.8" rx="3.4" stroke="black" stroke-width="1.8"/>
</svg>

Before

Width:  |  Height:  |  Size: 195 B

View File

@@ -1,3 +0,0 @@
<svg width="11" height="11" viewBox="0 0 11 11" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="3" y="3" width="5" height="5" rx="2.5" fill="black"/>
</svg>

Before

Width:  |  Height:  |  Size: 166 B

View File

@@ -1,10 +0,0 @@
<svg width="11" height="11" viewBox="0 0 11 11" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_2080_948)">
<path d="M1.52492 8.72287L1.04243 9.55H2H9H9.95757L9.47508 8.72287L5.97508 2.72287L5.5 1.90845L5.02492 2.72287L1.52492 8.72287Z" stroke="black" stroke-width="1.1"/>
</g>
<defs>
<clipPath id="clip0_2080_948">
<rect width="11" height="11" fill="white"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 412 B

View File

@@ -1,3 +0,0 @@
<svg width="11" height="11" viewBox="0 0 11 11" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2 9H9L5.5 3L2 9Z" fill="black"/>
</svg>

Before

Width:  |  Height:  |  Size: 146 B

View File

@@ -1,10 +0,0 @@
<svg width="11" height="11" viewBox="0 0 11 11" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_2050_903)">
<path d="M1.83327 2.89393L1.19687 3.53033L1.83327 4.16672L3.16654 5.5L1.83327 6.83327L1.19687 7.46967L1.83327 8.10606L2.89393 9.16672L3.53033 9.80312L4.16672 9.16672L5.5 7.83345L6.83327 9.16672L7.46967 9.80312L8.10606 9.16672L9.16672 8.10606L9.80312 7.46967L9.16672 6.83327L7.83345 5.5L9.16672 4.16672L9.80312 3.53033L9.16672 2.89393L8.10606 1.83327L7.46967 1.19687L6.83327 1.83327L5.5 3.16654L4.16672 1.83327L3.53033 1.19687L2.89393 1.83327L1.83327 2.89393Z" stroke="black" stroke-width="1.8"/>
</g>
<defs>
<clipPath id="clip0_2050_903">
<rect width="11" height="11" fill="white"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 743 B

View File

@@ -1,3 +0,0 @@
<svg width="11" height="11" viewBox="0 0 11 11" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3 3L5.5 5.5M8 8L5.5 5.5M5.5 5.5L3 8M5.5 5.5L8 3" stroke="black" stroke-width="1.5"/>
</svg>

Before

Width:  |  Height:  |  Size: 198 B

View File

@@ -1,7 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.33333 8H3" stroke="#FBF1C7" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M11.6667 4H3" stroke="#FBF1C7" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M11.6667 12H3" stroke="#FBF1C7" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M13.6667 6.66663L11 9.33329" stroke="#FBF1C7" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M11 6.66663L13.6667 9.33329" stroke="#FBF1C7" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 579 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-phone-incoming"><polyline points="16 2 16 8 22 8"/><line x1="22" x2="16" y1="2" y2="8"/><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>

Before

Width:  |  Height:  |  Size: 594 B

View File

@@ -1,5 +0,0 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7 21V12M7 12H3M7 12H11" stroke="black" stroke-width="2" stroke-linecap="round"/>
<path d="M21 19L16 19L16 14" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M7.99987 5.07027L7.49915 4.20467L7.99987 5.07027ZM6.04652 5.25026C5.63245 5.61573 5.59305 6.24766 5.95851 6.66173C6.32398 7.0758 6.95592 7.1152 7.36999 6.74974L6.04652 5.25026ZM11.9999 5C15.8659 5 18.9999 8.13401 18.9999 12H20.9999C20.9999 7.02944 16.9705 3 11.9999 3V5ZM18.9999 12C18.9999 14.2101 17.9768 16.1806 16.3744 17.4651L17.6254 19.0256C19.6809 17.3779 20.9999 14.8426 20.9999 12H18.9999ZM8.5006 5.93588C9.5292 5.34086 10.7232 5 11.9999 5V3C10.3623 3 8.82395 3.4383 7.49915 4.20467L8.5006 5.93588ZM7.36999 6.74974C7.71803 6.44255 8.09667 6.16954 8.5006 5.93588L7.49915 4.20467C6.9797 4.50515 6.49329 4.85593 6.04652 5.25026L7.36999 6.74974Z" fill="black"/>
</svg>

Before

Width:  |  Height:  |  Size: 979 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-swatch-book"><path d="M11 17a4 4 0 0 1-8 0V5a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2Z"/><path d="M16.7 13H19a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2H7"/><path d="M 7 17h.01"/><path d="m11 8 2.3-2.3a2.4 2.4 0 0 1 3.404.004L18.6 7.6a2.4 2.4 0 0 1 .026 3.434L9.9 19.8"/></svg>

Before

Width:  |  Height:  |  Size: 456 B

View File

@@ -1,3 +0,0 @@
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.5 3L3 12H14L8.5 3Z" fill="black"/>
</svg>

Before

Width:  |  Height:  |  Size: 150 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-wand"><path d="M15 4V2"/><path d="M15 16v-2"/><path d="M8 9h2"/><path d="M20 9h2"/><path d="M17.8 11.8 19 13"/><path d="M15 9h.01"/><path d="M17.8 6.2 19 5"/><path d="m3 21 9-9"/><path d="M12.2 6.2 11 5"/></svg>

Before

Width:  |  Height:  |  Size: 414 B

View File

@@ -1,3 +0,0 @@
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5 4.5L12 11.5M12 4.5L5 11.5" stroke="black" stroke-width="2" stroke-linecap="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 199 B

View File

@@ -56,8 +56,7 @@
"shift-tab": "editor::TabPrev", "shift-tab": "editor::TabPrev",
"ctrl-k": "editor::CutToEndOfLine", "ctrl-k": "editor::CutToEndOfLine",
// "ctrl-t": "editor::Transpose", // "ctrl-t": "editor::Transpose",
"ctrl-k ctrl-q": "editor::Rewrap", "alt-q": "editor::Rewrap",
"ctrl-k q": "editor::Rewrap",
"ctrl-backspace": "editor::DeleteToPreviousWordStart", "ctrl-backspace": "editor::DeleteToPreviousWordStart",
"ctrl-delete": "editor::DeleteToNextWordEnd", "ctrl-delete": "editor::DeleteToNextWordEnd",
"shift-delete": "editor::Cut", "shift-delete": "editor::Cut",
@@ -108,9 +107,7 @@
"ctrl-'": "editor::ToggleHunkDiff", "ctrl-'": "editor::ToggleHunkDiff",
"ctrl-\"": "editor::ExpandAllHunkDiffs", "ctrl-\"": "editor::ExpandAllHunkDiffs",
"ctrl-i": "editor::ShowSignatureHelp", "ctrl-i": "editor::ShowSignatureHelp",
"alt-g b": "editor::ToggleGitBlame", "alt-g b": "editor::ToggleGitBlame"
"menu": "editor::OpenContextMenu",
"shift-f10": "editor::OpenContextMenu"
} }
}, },
{ {
@@ -129,8 +126,7 @@
"shift-enter": "editor::Newline", "shift-enter": "editor::Newline",
"ctrl-enter": "editor::NewlineAbove", "ctrl-enter": "editor::NewlineAbove",
"ctrl-shift-enter": "editor::NewlineBelow", "ctrl-shift-enter": "editor::NewlineBelow",
"ctrl-k ctrl-z": "editor::ToggleSoftWrap", "alt-z": "editor::ToggleSoftWrap",
"ctrl-k z": "editor::ToggleSoftWrap",
"ctrl-f": "buffer_search::Deploy", "ctrl-f": "buffer_search::Deploy",
"ctrl-h": ["buffer_search::Deploy", { "replace_enabled": true }], "ctrl-h": ["buffer_search::Deploy", { "replace_enabled": true }],
// "cmd-e": ["buffer_search::Deploy", { "focus": false }], // "cmd-e": ["buffer_search::Deploy", { "focus": false }],
@@ -144,7 +140,7 @@
"bindings": { "bindings": {
"alt-]": "editor::NextInlineCompletion", "alt-]": "editor::NextInlineCompletion",
"alt-[": "editor::PreviousInlineCompletion", "alt-[": "editor::PreviousInlineCompletion",
"alt-right": "editor::AcceptPartialInlineCompletion" "ctrl-right": "editor::AcceptPartialInlineCompletion"
} }
}, },
{ {
@@ -173,7 +169,7 @@
"ctrl-k c": "assistant::CopyCode", "ctrl-k c": "assistant::CopyCode",
"ctrl-g": "search::SelectNextMatch", "ctrl-g": "search::SelectNextMatch",
"ctrl-shift-g": "search::SelectPrevMatch", "ctrl-shift-g": "search::SelectPrevMatch",
"ctrl-shift-m": "assistant::ToggleModelSelector", "alt-m": "assistant::ToggleModelSelector",
"ctrl-k h": "assistant::DeployHistory", "ctrl-k h": "assistant::DeployHistory",
"ctrl-k l": "assistant::DeployPromptLibrary", "ctrl-k l": "assistant::DeployPromptLibrary",
"ctrl-n": "assistant::NewContext" "ctrl-n": "assistant::NewContext"
@@ -253,14 +249,12 @@
"ctrl-pagedown": "pane::ActivateNextItem", "ctrl-pagedown": "pane::ActivateNextItem",
"ctrl-shift-pageup": "pane::SwapItemLeft", "ctrl-shift-pageup": "pane::SwapItemLeft",
"ctrl-shift-pagedown": "pane::SwapItemRight", "ctrl-shift-pagedown": "pane::SwapItemRight",
"back": "pane::GoBack",
"forward": "pane::GoForward",
"ctrl-w": "pane::CloseActiveItem", "ctrl-w": "pane::CloseActiveItem",
"ctrl-f4": "pane::CloseActiveItem", "ctrl-f4": "pane::CloseActiveItem",
"alt-ctrl-t": ["pane::CloseInactiveItems", { "close_pinned": false }], "alt-ctrl-t": "pane::CloseInactiveItems",
"alt-ctrl-shift-w": "workspace::CloseInactiveTabsAndPanes", "alt-ctrl-shift-w": "workspace::CloseInactiveTabsAndPanes",
"ctrl-k u": ["pane::CloseCleanItems", { "close_pinned": false }], "ctrl-k u": "pane::CloseCleanItems",
"ctrl-k w": ["pane::CloseAllItems", { "close_pinned": false }], "ctrl-k w": "pane::CloseAllItems",
"ctrl-shift-f": "project_search::ToggleFocus", "ctrl-shift-f": "project_search::ToggleFocus",
"ctrl-alt-g": "search::SelectNextMatch", "ctrl-alt-g": "search::SelectNextMatch",
"ctrl-alt-shift-g": "search::SelectPrevMatch", "ctrl-alt-shift-g": "search::SelectPrevMatch",
@@ -319,19 +313,11 @@
"ctrl-k ctrl-l": "editor::ToggleFold", "ctrl-k ctrl-l": "editor::ToggleFold",
"ctrl-k ctrl-[": "editor::FoldRecursive", "ctrl-k ctrl-[": "editor::FoldRecursive",
"ctrl-k ctrl-]": "editor::UnfoldRecursive", "ctrl-k ctrl-]": "editor::UnfoldRecursive",
"ctrl-k ctrl-1": ["editor::FoldAtLevel", { "level": 1 }],
"ctrl-k ctrl-2": ["editor::FoldAtLevel", { "level": 2 }],
"ctrl-k ctrl-3": ["editor::FoldAtLevel", { "level": 3 }],
"ctrl-k ctrl-4": ["editor::FoldAtLevel", { "level": 4 }],
"ctrl-k ctrl-5": ["editor::FoldAtLevel", { "level": 5 }],
"ctrl-k ctrl-6": ["editor::FoldAtLevel", { "level": 6 }],
"ctrl-k ctrl-7": ["editor::FoldAtLevel", { "level": 7 }],
"ctrl-k ctrl-8": ["editor::FoldAtLevel", { "level": 8 }],
"ctrl-k ctrl-9": ["editor::FoldAtLevel", { "level": 9 }],
"ctrl-k ctrl-0": "editor::FoldAll", "ctrl-k ctrl-0": "editor::FoldAll",
"ctrl-k ctrl-j": "editor::UnfoldAll", "ctrl-k ctrl-j": "editor::UnfoldAll",
"ctrl-space": "editor::ShowCompletions", "ctrl-space": "editor::ShowCompletions",
"ctrl-.": "editor::ToggleCodeActions", "ctrl-.": "editor::ToggleCodeActions",
"alt-ctrl-r": "editor::RevealInFileManager",
"ctrl-k r": "editor::RevealInFileManager", "ctrl-k r": "editor::RevealInFileManager",
"ctrl-k p": "editor::CopyPath", "ctrl-k p": "editor::CopyPath",
"ctrl-\\": "pane::SplitRight", "ctrl-\\": "pane::SplitRight",
@@ -407,7 +393,7 @@
"ctrl-shift-p": "command_palette::Toggle", "ctrl-shift-p": "command_palette::Toggle",
"f1": "command_palette::Toggle", "f1": "command_palette::Toggle",
"ctrl-shift-m": "diagnostics::Deploy", "ctrl-shift-m": "diagnostics::Deploy",
"ctrl-shift-e": "pane::RevealInProjectPanel", "ctrl-shift-e": "project_panel::ToggleFocus",
"ctrl-shift-b": "outline_panel::ToggleFocus", "ctrl-shift-b": "outline_panel::ToggleFocus",
"ctrl-?": "assistant::ToggleFocus", "ctrl-?": "assistant::ToggleFocus",
"ctrl-alt-s": "workspace::SaveAll", "ctrl-alt-s": "workspace::SaveAll",
@@ -422,8 +408,6 @@
"ctrl-k shift-up": ["workspace::SwapPaneInDirection", "Up"], "ctrl-k shift-up": ["workspace::SwapPaneInDirection", "Up"],
"ctrl-k shift-down": ["workspace::SwapPaneInDirection", "Down"], "ctrl-k shift-down": ["workspace::SwapPaneInDirection", "Down"],
"ctrl-shift-x": "zed::Extensions", "ctrl-shift-x": "zed::Extensions",
"ctrl-shift-r": "task::Rerun",
"ctrl-alt-r": "task::Rerun",
"alt-t": "task::Rerun", "alt-t": "task::Rerun",
"alt-shift-t": "task::Spawn" "alt-shift-t": "task::Spawn"
} }
@@ -521,13 +505,6 @@
"ctrl-enter": "assistant::InlineAssist" "ctrl-enter": "assistant::InlineAssist"
} }
}, },
{
"context": "ProposedChangesEditor",
"bindings": {
"ctrl-shift-y": "editor::ApplyDiffHunk",
"ctrl-alt-a": "editor::ApplyAllDiffHunks"
}
},
{ {
"context": "Editor && jupyter && !ContextEditor", "context": "Editor && jupyter && !ContextEditor",
"bindings": { "bindings": {
@@ -539,7 +516,6 @@
"context": "ContextEditor > Editor", "context": "ContextEditor > Editor",
"bindings": { "bindings": {
"ctrl-enter": "assistant::Assist", "ctrl-enter": "assistant::Assist",
"ctrl-shift-enter": "assistant::Edit",
"ctrl-s": "workspace::Save", "ctrl-s": "workspace::Save",
"ctrl->": "assistant::QuoteSelection", "ctrl->": "assistant::QuoteSelection",
"ctrl-<": "assistant::InsertIntoEditor", "ctrl-<": "assistant::InsertIntoEditor",
@@ -571,11 +547,9 @@
"ctrl-alt-c": "outline_panel::CopyPath", "ctrl-alt-c": "outline_panel::CopyPath",
"alt-ctrl-shift-c": "outline_panel::CopyRelativePath", "alt-ctrl-shift-c": "outline_panel::CopyRelativePath",
"alt-ctrl-r": "outline_panel::RevealInFileManager", "alt-ctrl-r": "outline_panel::RevealInFileManager",
"space": "outline_panel::Open", "space": ["outline_panel::Open", { "change_selection": false }],
"shift-down": "menu::SelectNext", "shift-down": "menu::SelectNext",
"shift-up": "menu::SelectPrev", "shift-up": "menu::SelectPrev"
"alt-enter": "editor::OpenExcerpts",
"ctrl-k enter": "editor::OpenExcerptsSplit"
} }
}, },
{ {
@@ -596,8 +570,7 @@
"ctrl-delete": ["project_panel::Delete", { "skip_prompt": false }], "ctrl-delete": ["project_panel::Delete", { "skip_prompt": false }],
"alt-ctrl-r": "project_panel::RevealInFileManager", "alt-ctrl-r": "project_panel::RevealInFileManager",
"ctrl-shift-enter": "project_panel::OpenWithSystem", "ctrl-shift-enter": "project_panel::OpenWithSystem",
"ctrl-shift-e": "project_panel::ToggleFocus", "alt-shift-f": "project_panel::NewSearchInDirectory",
"ctrl-shift-f": "project_panel::NewSearchInDirectory",
"shift-down": "menu::SelectNext", "shift-down": "menu::SelectNext",
"shift-up": "menu::SelectPrev", "shift-up": "menu::SelectPrev",
"escape": "menu::Cancel" "escape": "menu::Cancel"
@@ -654,28 +627,7 @@
}, },
{ {
"context": "FileFinder", "context": "FileFinder",
"bindings": { "bindings": { "ctrl-shift-p": "file_finder::SelectPrev" }
"ctrl": "file_finder::ToggleMenu"
}
},
{
"context": "FileFinder && !menu_open",
"bindings": {
"ctrl-shift-p": "file_finder::SelectPrev",
"ctrl-j": "pane::SplitDown",
"ctrl-k": "pane::SplitUp",
"ctrl-h": "pane::SplitLeft",
"ctrl-l": "pane::SplitRight"
}
},
{
"context": "FileFinder && menu_open",
"bindings": {
"j": "pane::SplitDown",
"k": "pane::SplitUp",
"h": "pane::SplitLeft",
"l": "pane::SplitRight"
}
}, },
{ {
"context": "TabSwitcher", "context": "TabSwitcher",

View File

@@ -1,7 +1,6 @@
[ [
// Standard macOS bindings // Standard macOS bindings
{ {
"use_key_equivalents": true,
"bindings": { "bindings": {
"up": "menu::SelectPrev", "up": "menu::SelectPrev",
"shift-tab": "menu::SelectPrev", "shift-tab": "menu::SelectPrev",
@@ -41,7 +40,6 @@
}, },
{ {
"context": "Editor", "context": "Editor",
"use_key_equivalents": true,
"bindings": { "bindings": {
"escape": "editor::Cancel", "escape": "editor::Cancel",
"backspace": "editor::Backspace", "backspace": "editor::Backspace",
@@ -51,16 +49,16 @@
"ctrl-d": "editor::Delete", "ctrl-d": "editor::Delete",
"tab": "editor::Tab", "tab": "editor::Tab",
"shift-tab": "editor::TabPrev", "shift-tab": "editor::TabPrev",
"ctrl-k": "editor::CutToEndOfLine",
"ctrl-t": "editor::Transpose", "ctrl-t": "editor::Transpose",
"ctrl-k": "editor::KillRingCut", "alt-q": "editor::Rewrap",
"ctrl-y": "editor::KillRingYank",
"cmd-k q": "editor::Rewrap",
"cmd-k cmd-q": "editor::Rewrap",
"cmd-backspace": "editor::DeleteToBeginningOfLine", "cmd-backspace": "editor::DeleteToBeginningOfLine",
"cmd-delete": "editor::DeleteToEndOfLine", "cmd-delete": "editor::DeleteToEndOfLine",
"alt-backspace": "editor::DeleteToPreviousWordStart", "alt-backspace": "editor::DeleteToPreviousWordStart",
"ctrl-w": "editor::DeleteToPreviousWordStart", "ctrl-w": "editor::DeleteToPreviousWordStart",
"alt-delete": "editor::DeleteToNextWordEnd", "alt-delete": "editor::DeleteToNextWordEnd",
"alt-h": "editor::DeleteToPreviousWordStart",
"alt-d": "editor::DeleteToNextWordEnd",
"cmd-x": "editor::Cut", "cmd-x": "editor::Cut",
"cmd-c": "editor::Copy", "cmd-c": "editor::Copy",
"cmd-v": "editor::Paste", "cmd-v": "editor::Paste",
@@ -88,7 +86,9 @@
"ctrl-f": "editor::MoveRight", "ctrl-f": "editor::MoveRight",
"ctrl-l": "editor::ScrollCursorCenter", "ctrl-l": "editor::ScrollCursorCenter",
"alt-left": "editor::MoveToPreviousWordStart", "alt-left": "editor::MoveToPreviousWordStart",
"alt-b": "editor::MoveToPreviousWordStart",
"alt-right": "editor::MoveToNextWordEnd", "alt-right": "editor::MoveToNextWordEnd",
"alt-f": "editor::MoveToNextWordEnd",
"cmd-left": "editor::MoveToBeginningOfLine", "cmd-left": "editor::MoveToBeginningOfLine",
"ctrl-a": "editor::MoveToBeginningOfLine", "ctrl-a": "editor::MoveToBeginningOfLine",
"cmd-right": "editor::MoveToEndOfLine", "cmd-right": "editor::MoveToEndOfLine",
@@ -104,7 +104,9 @@
"shift-right": "editor::SelectRight", "shift-right": "editor::SelectRight",
"ctrl-shift-f": "editor::SelectRight", "ctrl-shift-f": "editor::SelectRight",
"alt-shift-left": "editor::SelectToPreviousWordStart", // cursorWordLeftSelect "alt-shift-left": "editor::SelectToPreviousWordStart", // cursorWordLeftSelect
"alt-shift-b": "editor::SelectToPreviousWordStart",
"alt-shift-right": "editor::SelectToNextWordEnd", // cursorWordRightSelect "alt-shift-right": "editor::SelectToNextWordEnd", // cursorWordRightSelect
"alt-shift-f": "editor::SelectToNextWordEnd",
"ctrl-shift-up": "editor::SelectToStartOfParagraph", "ctrl-shift-up": "editor::SelectToStartOfParagraph",
"ctrl-shift-down": "editor::SelectToEndOfParagraph", "ctrl-shift-down": "editor::SelectToEndOfParagraph",
"cmd-shift-up": "editor::SelectToBeginning", "cmd-shift-up": "editor::SelectToBeginning",
@@ -119,7 +121,7 @@
"shift-end": ["editor::SelectToEndOfLine", { "stop_at_soft_wraps": true }], "shift-end": ["editor::SelectToEndOfLine", { "stop_at_soft_wraps": true }],
"ctrl-shift-e": ["editor::SelectToEndOfLine", { "stop_at_soft_wraps": true }], "ctrl-shift-e": ["editor::SelectToEndOfLine", { "stop_at_soft_wraps": true }],
"ctrl-v": ["editor::MovePageDown", { "center_cursor": true }], "ctrl-v": ["editor::MovePageDown", { "center_cursor": true }],
"ctrl-shift-v": ["editor::MovePageUp", { "center_cursor": true }], "alt-v": ["editor::MovePageUp", { "center_cursor": true }],
"ctrl-cmd-space": "editor::ShowCharacterPalette", "ctrl-cmd-space": "editor::ShowCharacterPalette",
"cmd-;": "editor::ToggleLineNumbers", "cmd-;": "editor::ToggleLineNumbers",
"cmd-alt-z": "editor::RevertSelectedHunks", "cmd-alt-z": "editor::RevertSelectedHunks",
@@ -133,13 +135,12 @@
}, },
{ {
"context": "Editor && mode == full", "context": "Editor && mode == full",
"use_key_equivalents": true,
"bindings": { "bindings": {
"enter": "editor::Newline", "enter": "editor::Newline",
"shift-enter": "editor::Newline", "shift-enter": "editor::Newline",
"cmd-enter": "editor::NewlineBelow", "cmd-enter": "editor::NewlineBelow",
"cmd-shift-enter": "editor::NewlineAbove", "cmd-shift-enter": "editor::NewlineAbove",
"cmd-k z": "editor::ToggleSoftWrap", "alt-z": "editor::ToggleSoftWrap",
"cmd-f": "buffer_search::Deploy", "cmd-f": "buffer_search::Deploy",
"cmd-alt-f": ["buffer_search::Deploy", { "replace_enabled": true }], "cmd-alt-f": ["buffer_search::Deploy", { "replace_enabled": true }],
"cmd-alt-l": ["buffer_search::Deploy", { "selection_search_enabled": true }], "cmd-alt-l": ["buffer_search::Deploy", { "selection_search_enabled": true }],
@@ -151,23 +152,20 @@
}, },
{ {
"context": "Editor && mode == full && inline_completion", "context": "Editor && mode == full && inline_completion",
"use_key_equivalents": true,
"bindings": { "bindings": {
"alt-tab": "editor::NextInlineCompletion", "alt-]": "editor::NextInlineCompletion",
"alt-shift-tab": "editor::PreviousInlineCompletion", "alt-[": "editor::PreviousInlineCompletion",
"ctrl-right": "editor::AcceptPartialInlineCompletion" "cmd-right": "editor::AcceptPartialInlineCompletion"
} }
}, },
{ {
"context": "Editor && !inline_completion", "context": "Editor && !inline_completion",
"use_key_equivalents": true,
"bindings": { "bindings": {
"alt-tab": "editor::ShowInlineCompletion" "alt-\\": "editor::ShowInlineCompletion"
} }
}, },
{ {
"context": "Editor && mode == auto_height", "context": "Editor && mode == auto_height",
"use_key_equivalents": true,
"bindings": { "bindings": {
"ctrl-enter": "editor::Newline", "ctrl-enter": "editor::Newline",
"shift-enter": "editor::Newline", "shift-enter": "editor::Newline",
@@ -176,14 +174,12 @@
}, },
{ {
"context": "Markdown", "context": "Markdown",
"use_key_equivalents": true,
"bindings": { "bindings": {
"cmd-c": "markdown::Copy" "cmd-c": "markdown::Copy"
} }
}, },
{ {
"context": "Editor && jupyter && !ContextEditor", "context": "Editor && jupyter && !ContextEditor",
"use_key_equivalents": true,
"bindings": { "bindings": {
"ctrl-shift-enter": "repl::Run", "ctrl-shift-enter": "repl::Run",
"ctrl-alt-enter": "repl::RunInPlace" "ctrl-alt-enter": "repl::RunInPlace"
@@ -191,12 +187,11 @@
}, },
{ {
"context": "AssistantPanel", "context": "AssistantPanel",
"use_key_equivalents": true,
"bindings": { "bindings": {
"cmd-k c": "assistant::CopyCode", "cmd-k c": "assistant::CopyCode",
"cmd-g": "search::SelectNextMatch", "cmd-g": "search::SelectNextMatch",
"cmd-shift-g": "search::SelectPrevMatch", "cmd-shift-g": "search::SelectPrevMatch",
"cmd-shift-m": "assistant::ToggleModelSelector", "alt-m": "assistant::ToggleModelSelector",
"cmd-k h": "assistant::DeployHistory", "cmd-k h": "assistant::DeployHistory",
"cmd-k l": "assistant::DeployPromptLibrary", "cmd-k l": "assistant::DeployPromptLibrary",
"cmd-n": "assistant::NewContext" "cmd-n": "assistant::NewContext"
@@ -204,10 +199,8 @@
}, },
{ {
"context": "ContextEditor > Editor", "context": "ContextEditor > Editor",
"use_key_equivalents": true,
"bindings": { "bindings": {
"cmd-enter": "assistant::Assist", "cmd-enter": "assistant::Assist",
"cmd-shift-enter": "assistant::Edit",
"cmd-s": "workspace::Save", "cmd-s": "workspace::Save",
"cmd->": "assistant::QuoteSelection", "cmd->": "assistant::QuoteSelection",
"cmd-<": "assistant::InsertIntoEditor", "cmd-<": "assistant::InsertIntoEditor",
@@ -217,24 +210,8 @@
"alt-enter": "editor::Newline" "alt-enter": "editor::Newline"
} }
}, },
{
"context": "AssistantPanel2",
"use_key_equivalents": true,
"bindings": {
"cmd-n": "assistant2::NewThread",
"cmd-shift-h": "assistant2::OpenHistory"
}
},
{
"context": "MessageEditor > Editor",
"use_key_equivalents": true,
"bindings": {
"cmd-enter": "assistant2::Chat"
}
},
{ {
"context": "PromptLibrary", "context": "PromptLibrary",
"use_key_equivalents": true,
"bindings": { "bindings": {
"cmd-n": "prompt_library::NewPrompt", "cmd-n": "prompt_library::NewPrompt",
"cmd-shift-s": "prompt_library::ToggleDefaultPrompt", "cmd-shift-s": "prompt_library::ToggleDefaultPrompt",
@@ -243,7 +220,6 @@
}, },
{ {
"context": "BufferSearchBar", "context": "BufferSearchBar",
"use_key_equivalents": true,
"bindings": { "bindings": {
"escape": "buffer_search::Dismiss", "escape": "buffer_search::Dismiss",
"tab": "buffer_search::FocusEditor", "tab": "buffer_search::FocusEditor",
@@ -257,7 +233,6 @@
}, },
{ {
"context": "BufferSearchBar && in_replace > Editor", "context": "BufferSearchBar && in_replace > Editor",
"use_key_equivalents": true,
"bindings": { "bindings": {
"enter": "search::ReplaceNext", "enter": "search::ReplaceNext",
"cmd-enter": "search::ReplaceAll" "cmd-enter": "search::ReplaceAll"
@@ -265,7 +240,6 @@
}, },
{ {
"context": "BufferSearchBar && !in_replace > Editor", "context": "BufferSearchBar && !in_replace > Editor",
"use_key_equivalents": true,
"bindings": { "bindings": {
"up": "search::PreviousHistoryQuery", "up": "search::PreviousHistoryQuery",
"down": "search::NextHistoryQuery" "down": "search::NextHistoryQuery"
@@ -273,7 +247,6 @@
}, },
{ {
"context": "ProjectSearchBar", "context": "ProjectSearchBar",
"use_key_equivalents": true,
"bindings": { "bindings": {
"escape": "project_search::ToggleFocus", "escape": "project_search::ToggleFocus",
"cmd-shift-j": "project_search::ToggleFilters", "cmd-shift-j": "project_search::ToggleFilters",
@@ -285,7 +258,6 @@
}, },
{ {
"context": "ProjectSearchBar > Editor", "context": "ProjectSearchBar > Editor",
"use_key_equivalents": true,
"bindings": { "bindings": {
"up": "search::PreviousHistoryQuery", "up": "search::PreviousHistoryQuery",
"down": "search::NextHistoryQuery" "down": "search::NextHistoryQuery"
@@ -293,7 +265,6 @@
}, },
{ {
"context": "ProjectSearchBar && in_replace > Editor", "context": "ProjectSearchBar && in_replace > Editor",
"use_key_equivalents": true,
"bindings": { "bindings": {
"enter": "search::ReplaceNext", "enter": "search::ReplaceNext",
"cmd-enter": "search::ReplaceAll" "cmd-enter": "search::ReplaceAll"
@@ -301,7 +272,6 @@
}, },
{ {
"context": "ProjectSearchView", "context": "ProjectSearchView",
"use_key_equivalents": true,
"bindings": { "bindings": {
"escape": "project_search::ToggleFocus", "escape": "project_search::ToggleFocus",
"cmd-shift-j": "project_search::ToggleFilters", "cmd-shift-j": "project_search::ToggleFilters",
@@ -312,7 +282,6 @@
}, },
{ {
"context": "Pane", "context": "Pane",
"use_key_equivalents": true,
"bindings": { "bindings": {
"cmd-{": "pane::ActivatePrevItem", "cmd-{": "pane::ActivatePrevItem",
"cmd-}": "pane::ActivateNextItem", "cmd-}": "pane::ActivateNextItem",
@@ -321,10 +290,10 @@
"ctrl-shift-pageup": "pane::SwapItemLeft", "ctrl-shift-pageup": "pane::SwapItemLeft",
"ctrl-shift-pagedown": "pane::SwapItemRight", "ctrl-shift-pagedown": "pane::SwapItemRight",
"cmd-w": "pane::CloseActiveItem", "cmd-w": "pane::CloseActiveItem",
"alt-cmd-t": ["pane::CloseInactiveItems", { "close_pinned": false }], "alt-cmd-t": "pane::CloseInactiveItems",
"ctrl-alt-cmd-w": "workspace::CloseInactiveTabsAndPanes", "ctrl-alt-cmd-w": "workspace::CloseInactiveTabsAndPanes",
"cmd-k u": ["pane::CloseCleanItems", { "close_pinned": false }], "cmd-k u": "pane::CloseCleanItems",
"cmd-k cmd-w": ["pane::CloseAllItems", { "close_pinned": false }], "cmd-k cmd-w": "pane::CloseAllItems",
"cmd-f": "project_search::ToggleFocus", "cmd-f": "project_search::ToggleFocus",
"cmd-g": "search::SelectNextMatch", "cmd-g": "search::SelectNextMatch",
"cmd-shift-g": "search::SelectPrevMatch", "cmd-shift-g": "search::SelectPrevMatch",
@@ -341,7 +310,6 @@
// Bindings from VS Code // Bindings from VS Code
{ {
"context": "Editor", "context": "Editor",
"use_key_equivalents": true,
"bindings": { "bindings": {
"cmd-[": "editor::Outdent", "cmd-[": "editor::Outdent",
"cmd-]": "editor::Indent", "cmd-]": "editor::Indent",
@@ -376,25 +344,17 @@
"alt-cmd-f12": "editor::GoToTypeDefinitionSplit", "alt-cmd-f12": "editor::GoToTypeDefinitionSplit",
"alt-shift-f12": "editor::FindAllReferences", "alt-shift-f12": "editor::FindAllReferences",
"ctrl-m": "editor::MoveToEnclosingBracket", "ctrl-m": "editor::MoveToEnclosingBracket",
"cmd-|": "editor::MoveToEnclosingBracket", "cmd-shift-\\": "editor::MoveToEnclosingBracket",
"alt-cmd-[": "editor::Fold", "alt-cmd-[": "editor::Fold",
"alt-cmd-]": "editor::UnfoldLines", "alt-cmd-]": "editor::UnfoldLines",
"cmd-k cmd-l": "editor::ToggleFold", "cmd-k cmd-l": "editor::ToggleFold",
"cmd-k cmd-[": "editor::FoldRecursive", "cmd-k cmd-[": "editor::FoldRecursive",
"cmd-k cmd-]": "editor::UnfoldRecursive", "cmd-k cmd-]": "editor::UnfoldRecursive",
"cmd-k cmd-1": ["editor::FoldAtLevel", { "level": 1 }],
"cmd-k cmd-2": ["editor::FoldAtLevel", { "level": 2 }],
"cmd-k cmd-3": ["editor::FoldAtLevel", { "level": 3 }],
"cmd-k cmd-4": ["editor::FoldAtLevel", { "level": 4 }],
"cmd-k cmd-5": ["editor::FoldAtLevel", { "level": 5 }],
"cmd-k cmd-6": ["editor::FoldAtLevel", { "level": 6 }],
"cmd-k cmd-7": ["editor::FoldAtLevel", { "level": 7 }],
"cmd-k cmd-8": ["editor::FoldAtLevel", { "level": 8 }],
"cmd-k cmd-9": ["editor::FoldAtLevel", { "level": 9 }],
"cmd-k cmd-0": "editor::FoldAll", "cmd-k cmd-0": "editor::FoldAll",
"cmd-k cmd-j": "editor::UnfoldAll", "cmd-k cmd-j": "editor::UnfoldAll",
"ctrl-space": "editor::ShowCompletions", "ctrl-space": "editor::ShowCompletions",
"cmd-.": "editor::ToggleCodeActions", "cmd-.": "editor::ToggleCodeActions",
"alt-cmd-r": "editor::RevealInFileManager",
"cmd-k r": "editor::RevealInFileManager", "cmd-k r": "editor::RevealInFileManager",
"cmd-k p": "editor::CopyPath", "cmd-k p": "editor::CopyPath",
"cmd-\\": "pane::SplitRight", "cmd-\\": "pane::SplitRight",
@@ -405,7 +365,6 @@
}, },
{ {
"context": "Editor && mode == full", "context": "Editor && mode == full",
"use_key_equivalents": true,
"bindings": { "bindings": {
"cmd-shift-o": "outline::Toggle", "cmd-shift-o": "outline::Toggle",
"ctrl-g": "go_to_line::Toggle" "ctrl-g": "go_to_line::Toggle"
@@ -413,7 +372,6 @@
}, },
{ {
"context": "Pane", "context": "Pane",
"use_key_equivalents": true,
"bindings": { "bindings": {
"ctrl-1": ["pane::ActivateItem", 0], "ctrl-1": ["pane::ActivateItem", 0],
"ctrl-2": ["pane::ActivateItem", 1], "ctrl-2": ["pane::ActivateItem", 1],
@@ -433,7 +391,6 @@
}, },
{ {
"context": "Workspace", "context": "Workspace",
"use_key_equivalents": true,
"bindings": { "bindings": {
// Change the default action on `menu::Confirm` by setting the parameter // Change the default action on `menu::Confirm` by setting the parameter
// "alt-cmd-o": ["projects::OpenRecent", {"create_new_window": true }], // "alt-cmd-o": ["projects::OpenRecent", {"create_new_window": true }],
@@ -470,7 +427,7 @@
"ctrl-shift-tab": ["tab_switcher::Toggle", { "select_last": true }], "ctrl-shift-tab": ["tab_switcher::Toggle", { "select_last": true }],
"cmd-shift-p": "command_palette::Toggle", "cmd-shift-p": "command_palette::Toggle",
"cmd-shift-m": "diagnostics::Deploy", "cmd-shift-m": "diagnostics::Deploy",
"cmd-shift-e": "pane::RevealInProjectPanel", "cmd-shift-e": "project_panel::ToggleFocus",
"cmd-shift-b": "outline_panel::ToggleFocus", "cmd-shift-b": "outline_panel::ToggleFocus",
"cmd-?": "assistant::ToggleFocus", "cmd-?": "assistant::ToggleFocus",
"cmd-alt-s": "workspace::SaveAll", "cmd-alt-s": "workspace::SaveAll",
@@ -489,18 +446,14 @@
}, },
{ {
"context": "Workspace && !Terminal", "context": "Workspace && !Terminal",
"use_key_equivalents": true,
"bindings": { "bindings": {
"cmd-shift-r": "task::Spawn", "alt-t": "task::Rerun",
"cmd-alt-r": "task::Rerun",
"alt-t": "task::Spawn",
"alt-shift-t": "task::Spawn" "alt-shift-t": "task::Spawn"
} }
}, },
// Bindings from Sublime Text // Bindings from Sublime Text
{ {
"context": "Editor", "context": "Editor",
"use_key_equivalents": true,
"bindings": { "bindings": {
"ctrl-j": "editor::JoinLines", "ctrl-j": "editor::JoinLines",
"ctrl-alt-backspace": "editor::DeleteToPreviousSubwordStart", "ctrl-alt-backspace": "editor::DeleteToPreviousSubwordStart",
@@ -520,7 +473,6 @@
// Bindings from Atom // Bindings from Atom
{ {
"context": "Pane", "context": "Pane",
"use_key_equivalents": true,
"bindings": { "bindings": {
"cmd-k up": "pane::SplitUp", "cmd-k up": "pane::SplitUp",
"cmd-k down": "pane::SplitDown", "cmd-k down": "pane::SplitDown",
@@ -531,14 +483,12 @@
// Bindings that should be unified with bindings for more general actions // Bindings that should be unified with bindings for more general actions
{ {
"context": "Editor && renaming", "context": "Editor && renaming",
"use_key_equivalents": true,
"bindings": { "bindings": {
"enter": "editor::ConfirmRename" "enter": "editor::ConfirmRename"
} }
}, },
{ {
"context": "Editor && showing_completions", "context": "Editor && showing_completions",
"use_key_equivalents": true,
"bindings": { "bindings": {
"enter": "editor::ConfirmCompletion", "enter": "editor::ConfirmCompletion",
"tab": "editor::ComposeCompletion" "tab": "editor::ComposeCompletion"
@@ -546,21 +496,18 @@
}, },
{ {
"context": "Editor && inline_completion && !showing_completions", "context": "Editor && inline_completion && !showing_completions",
"use_key_equivalents": true,
"bindings": { "bindings": {
"tab": "editor::AcceptInlineCompletion" "tab": "editor::AcceptInlineCompletion"
} }
}, },
{ {
"context": "Editor && showing_code_actions", "context": "Editor && showing_code_actions",
"use_key_equivalents": true,
"bindings": { "bindings": {
"enter": "editor::ConfirmCodeAction" "enter": "editor::ConfirmCodeAction"
} }
}, },
{ {
"context": "Editor && (showing_code_actions || showing_completions)", "context": "Editor && (showing_code_actions || showing_completions)",
"use_key_equivalents": true,
"bindings": { "bindings": {
"up": "editor::ContextMenuPrev", "up": "editor::ContextMenuPrev",
"ctrl-p": "editor::ContextMenuPrev", "ctrl-p": "editor::ContextMenuPrev",
@@ -572,7 +519,6 @@
}, },
// Custom bindings // Custom bindings
{ {
"use_key_equivalents": true,
"bindings": { "bindings": {
"ctrl-alt-cmd-f": "workspace::FollowNextCollaborator", "ctrl-alt-cmd-f": "workspace::FollowNextCollaborator",
// TODO: Move this to a dock open action // TODO: Move this to a dock open action
@@ -583,7 +529,6 @@
}, },
{ {
"context": "Editor && mode == full", "context": "Editor && mode == full",
"use_key_equivalents": true,
"bindings": { "bindings": {
"alt-enter": "editor::OpenExcerpts", "alt-enter": "editor::OpenExcerpts",
"shift-enter": "editor::ExpandExcerpts", "shift-enter": "editor::ExpandExcerpts",
@@ -593,17 +538,8 @@
"ctrl-enter": "assistant::InlineAssist" "ctrl-enter": "assistant::InlineAssist"
} }
}, },
{
"context": "ProposedChangesEditor",
"use_key_equivalents": true,
"bindings": {
"cmd-shift-y": "editor::ApplyDiffHunk",
"cmd-shift-a": "editor::ApplyAllDiffHunks"
}
},
{ {
"context": "PromptEditor", "context": "PromptEditor",
"use_key_equivalents": true,
"bindings": { "bindings": {
"ctrl-[": "assistant::CyclePreviousInlineAssist", "ctrl-[": "assistant::CyclePreviousInlineAssist",
"ctrl-]": "assistant::CycleNextInlineAssist" "ctrl-]": "assistant::CycleNextInlineAssist"
@@ -611,14 +547,12 @@
}, },
{ {
"context": "ProjectSearchBar && !in_replace", "context": "ProjectSearchBar && !in_replace",
"use_key_equivalents": true,
"bindings": { "bindings": {
"cmd-enter": "project_search::SearchInNew" "cmd-enter": "project_search::SearchInNew"
} }
}, },
{ {
"context": "OutlinePanel && not_editing", "context": "OutlinePanel && not_editing",
"use_key_equivalents": true,
"bindings": { "bindings": {
"escape": "menu::Cancel", "escape": "menu::Cancel",
"left": "outline_panel::CollapseSelectedEntry", "left": "outline_panel::CollapseSelectedEntry",
@@ -626,16 +560,13 @@
"cmd-alt-c": "outline_panel::CopyPath", "cmd-alt-c": "outline_panel::CopyPath",
"alt-cmd-shift-c": "outline_panel::CopyRelativePath", "alt-cmd-shift-c": "outline_panel::CopyRelativePath",
"alt-cmd-r": "outline_panel::RevealInFileManager", "alt-cmd-r": "outline_panel::RevealInFileManager",
"space": "outline_panel::Open", "space": ["outline_panel::Open", { "change_selection": false }],
"shift-down": "menu::SelectNext", "shift-down": "menu::SelectNext",
"shift-up": "menu::SelectPrev", "shift-up": "menu::SelectPrev"
"alt-enter": "editor::OpenExcerpts",
"cmd-k enter": "editor::OpenExcerptsSplit"
} }
}, },
{ {
"context": "ProjectPanel", "context": "ProjectPanel",
"use_key_equivalents": true,
"bindings": { "bindings": {
"left": "project_panel::CollapseSelectedEntry", "left": "project_panel::CollapseSelectedEntry",
"right": "project_panel::ExpandSelectedEntry", "right": "project_panel::ExpandSelectedEntry",
@@ -655,9 +586,8 @@
"cmd-delete": ["project_panel::Delete", { "skip_prompt": false }], "cmd-delete": ["project_panel::Delete", { "skip_prompt": false }],
"alt-cmd-r": "project_panel::RevealInFileManager", "alt-cmd-r": "project_panel::RevealInFileManager",
"ctrl-shift-enter": "project_panel::OpenWithSystem", "ctrl-shift-enter": "project_panel::OpenWithSystem",
"cmd-shift-e": "project_panel::ToggleFocus",
"cmd-alt-backspace": ["project_panel::Delete", { "skip_prompt": false }], "cmd-alt-backspace": ["project_panel::Delete", { "skip_prompt": false }],
"cmd-shift-f": "project_panel::NewSearchInDirectory", "alt-shift-f": "project_panel::NewSearchInDirectory",
"shift-down": "menu::SelectNext", "shift-down": "menu::SelectNext",
"shift-up": "menu::SelectPrev", "shift-up": "menu::SelectPrev",
"escape": "menu::Cancel" "escape": "menu::Cancel"
@@ -665,14 +595,12 @@
}, },
{ {
"context": "ProjectPanel && not_editing", "context": "ProjectPanel && not_editing",
"use_key_equivalents": true,
"bindings": { "bindings": {
"space": "project_panel::Open" "space": "project_panel::Open"
} }
}, },
{ {
"context": "CollabPanel && not_editing", "context": "CollabPanel && not_editing",
"use_key_equivalents": true,
"bindings": { "bindings": {
"ctrl-backspace": "collab_panel::Remove", "ctrl-backspace": "collab_panel::Remove",
"space": "menu::Confirm" "space": "menu::Confirm"
@@ -680,21 +608,18 @@
}, },
{ {
"context": "(CollabPanel && editing) > Editor", "context": "(CollabPanel && editing) > Editor",
"use_key_equivalents": true,
"bindings": { "bindings": {
"space": "collab_panel::InsertSpace" "space": "collab_panel::InsertSpace"
} }
}, },
{ {
"context": "ChannelModal", "context": "ChannelModal",
"use_key_equivalents": true,
"bindings": { "bindings": {
"tab": "channel_modal::ToggleMode" "tab": "channel_modal::ToggleMode"
} }
}, },
{ {
"context": "Picker > Editor", "context": "Picker > Editor",
"use_key_equivalents": true,
"bindings": { "bindings": {
"tab": "picker::ConfirmCompletion", "tab": "picker::ConfirmCompletion",
"alt-enter": ["picker::ConfirmInput", { "secondary": false }], "alt-enter": ["picker::ConfirmInput", { "secondary": false }],
@@ -703,42 +628,16 @@
}, },
{ {
"context": "ChannelModal > Picker > Editor", "context": "ChannelModal > Picker > Editor",
"use_key_equivalents": true,
"bindings": { "bindings": {
"tab": "channel_modal::ToggleMode" "tab": "channel_modal::ToggleMode"
} }
}, },
{ {
"context": "FileFinder", "context": "FileFinder",
"use_key_equivalents": true, "bindings": { "cmd-shift-p": "file_finder::SelectPrev" }
"bindings": {
"cmd": "file_finder::ToggleMenu"
}
},
{
"context": "FileFinder && !menu_open",
"use_key_equivalents": true,
"bindings": {
"cmd-shift-p": "file_finder::SelectPrev",
"cmd-j": "pane::SplitDown",
"cmd-k": "pane::SplitUp",
"cmd-h": "pane::SplitLeft",
"cmd-l": "pane::SplitRight"
}
},
{
"context": "FileFinder && menu_open",
"use_key_equivalents": true,
"bindings": {
"j": "pane::SplitDown",
"k": "pane::SplitUp",
"h": "pane::SplitLeft",
"l": "pane::SplitRight"
}
}, },
{ {
"context": "TabSwitcher", "context": "TabSwitcher",
"use_key_equivalents": true,
"bindings": { "bindings": {
"ctrl-up": "menu::SelectPrev", "ctrl-up": "menu::SelectPrev",
"ctrl-down": "menu::SelectNext", "ctrl-down": "menu::SelectNext",
@@ -748,7 +647,6 @@
}, },
{ {
"context": "Terminal", "context": "Terminal",
"use_key_equivalents": true,
"bindings": { "bindings": {
"ctrl-cmd-space": "terminal::ShowCharacterPalette", "ctrl-cmd-space": "terminal::ShowCharacterPalette",
"cmd-c": "terminal::Copy", "cmd-c": "terminal::Copy",
@@ -782,11 +680,7 @@
"cmd-end": "terminal::ScrollToBottom", "cmd-end": "terminal::ScrollToBottom",
"shift-home": "terminal::ScrollToTop", "shift-home": "terminal::ScrollToTop",
"shift-end": "terminal::ScrollToBottom", "shift-end": "terminal::ScrollToBottom",
"ctrl-shift-space": "terminal::ToggleViMode", "ctrl-shift-space": "terminal::ToggleViMode"
"ctrl-k up": "pane::SplitUp",
"ctrl-k down": "pane::SplitDown",
"ctrl-k left": "pane::SplitLeft",
"ctrl-k right": "pane::SplitRight"
} }
} }
] ]

View File

@@ -1,63 +0,0 @@
// documentation: https://zed.dev/docs/key-bindings
//
// To see the default key bindings run `zed: open default keymap`
// from the command palette.
[
{
"context": "Editor",
"bindings": {
"ctrl-g": "editor::Cancel",
"ctrl-shift-g": "go_to_line::Toggle",
//"ctrl-space": "editor::SetMark",
"ctrl-x u": "editor::Undo",
"ctrl-x ctrl-u": "editor::Redo",
"ctrl-f": "editor::MoveRight",
"ctrl-b": "editor::MoveLeft",
"ctrl-n": "editor::MoveDown",
"ctrl-p": "editor::MoveUp",
"ctrl-a": "editor::MoveToBeginningOfLine",
"ctrl-e": "editor::MoveToEndOfLine",
"alt-f": "editor::MoveToNextSubwordEnd",
"alt-b": "editor::MoveToPreviousSubwordStart",
"ctrl-d": "editor::Delete",
"alt-d": "editor::DeleteToNextWordEnd",
"ctrl-k": "editor::CutToEndOfLine",
"ctrl-w": "editor::Cut",
"alt-w": "editor::Copy",
"ctrl-y": "editor::Paste",
"ctrl-_": "editor::Undo",
"ctrl-v": "editor::MovePageDown",
"alt-v": "editor::MovePageUp",
"ctrl-x ]": "editor::MoveToEnd",
"ctrl-x [": "editor::MoveToBeginning",
"ctrl-l": "editor::ScrollCursorCenterTopBottom",
"ctrl-s": "buffer_search::Deploy",
"ctrl-x ctrl-f": "file_finder::Toggle",
"ctrl-shift-r": "editor::Rename"
}
},
{
"context": "Workspace",
"bindings": {
"ctrl-x k": "pane::CloseActiveItem",
"ctrl-x ctrl-c": "workspace::CloseWindow",
"ctrl-x o": "workspace::ActivateNextPane",
"ctrl-x b": "tab_switcher::Toggle",
"ctrl-x 0": "pane::CloseActiveItem",
"ctrl-x 1": "pane::CloseInactiveItems",
"ctrl-x 2": "pane::SplitVertical",
"ctrl-x ctrl-f": "file_finder::Toggle",
"ctrl-x ctrl-s": "workspace::Save",
"ctrl-x ctrl-w": "workspace::SaveAs",
"ctrl-x s": "workspace::SaveAll",
"shift shift": "file_finder::Toggle"
}
},
{
"context": "Pane",
"bindings": {
"ctrl-alt-left": "pane::GoBack",
"ctrl-alt-right": "pane::GoForward"
}
}
]

View File

@@ -1,7 +1,6 @@
[ [
{ {
"bindings": { "bindings": {
"ctrl-alt-s": "zed::OpenSettings",
"ctrl-shift-[": "pane::ActivatePrevItem", "ctrl-shift-[": "pane::ActivatePrevItem",
"ctrl-shift-]": "pane::ActivateNextItem" "ctrl-shift-]": "pane::ActivateNextItem"
} }
@@ -26,8 +25,8 @@
"alt-j": ["editor::SelectNext", { "replace_newest": false }], "alt-j": ["editor::SelectNext", { "replace_newest": false }],
"alt-shift-j": ["editor::SelectPrevious", { "replace_newest": false }], "alt-shift-j": ["editor::SelectPrevious", { "replace_newest": false }],
"ctrl-/": ["editor::ToggleComments", { "advance_downwards": true }], "ctrl-/": ["editor::ToggleComments", { "advance_downwards": true }],
"ctrl-w": "editor::SelectLargerSyntaxNode", "alt-up": "editor::SelectLargerSyntaxNode",
"ctrl-shift-w": "editor::SelectSmallerSyntaxNode", "alt-down": "editor::SelectSmallerSyntaxNode",
"shift-alt-up": "editor::MoveLineUp", "shift-alt-up": "editor::MoveLineUp",
"shift-alt-down": "editor::MoveLineDown", "shift-alt-down": "editor::MoveLineDown",
"ctrl-alt-l": "editor::Format", "ctrl-alt-l": "editor::Format",
@@ -44,7 +43,6 @@
"shift-f2": "editor::GoToPrevDiagnostic", "shift-f2": "editor::GoToPrevDiagnostic",
"ctrl-alt-shift-down": "editor::GoToHunk", "ctrl-alt-shift-down": "editor::GoToHunk",
"ctrl-alt-shift-up": "editor::GoToPrevHunk", "ctrl-alt-shift-up": "editor::GoToPrevHunk",
"ctrl-alt-z": "editor::RevertSelectedHunks",
"ctrl-home": "editor::MoveToBeginning", "ctrl-home": "editor::MoveToBeginning",
"ctrl-end": "editor::MoveToEnd", "ctrl-end": "editor::MoveToEnd",
"ctrl-shift-home": "editor::SelectToBeginning", "ctrl-shift-home": "editor::SelectToBeginning",

View File

@@ -4,7 +4,9 @@
"ctrl-shift-[": "pane::ActivatePrevItem", "ctrl-shift-[": "pane::ActivatePrevItem",
"ctrl-shift-]": "pane::ActivateNextItem", "ctrl-shift-]": "pane::ActivateNextItem",
"ctrl-pageup": "pane::ActivatePrevItem", "ctrl-pageup": "pane::ActivatePrevItem",
"ctrl-pagedown": "pane::ActivateNextItem" "ctrl-pagedown": "pane::ActivateNextItem",
"ctrl-tab": "pane::ActivateNextItem",
"ctrl-shift-tab": "pane::ActivatePrevItem"
} }
}, },
{ {
@@ -16,7 +18,6 @@
"ctrl-shift-l": "editor::SplitSelectionIntoLines", "ctrl-shift-l": "editor::SplitSelectionIntoLines",
"ctrl-shift-a": "editor::SelectLargerSyntaxNode", "ctrl-shift-a": "editor::SelectLargerSyntaxNode",
"ctrl-shift-d": "editor::DuplicateLineDown", "ctrl-shift-d": "editor::DuplicateLineDown",
"alt-f3": "editor::SelectAllMatches", // find_all_under
"f12": "editor::GoToDefinition", "f12": "editor::GoToDefinition",
"ctrl-f12": "editor::GoToDefinitionSplit", "ctrl-f12": "editor::GoToDefinitionSplit",
"shift-f12": "editor::FindAllReferences", "shift-f12": "editor::FindAllReferences",

View File

@@ -1,63 +0,0 @@
// documentation: https://zed.dev/docs/key-bindings
//
// To see the default key bindings run `zed: open default keymap`
// from the command palette.
[
{
"context": "Editor",
"bindings": {
"ctrl-g": "editor::Cancel",
"ctrl-shift-g": "go_to_line::Toggle",
//"ctrl-space": "editor::SetMark",
"ctrl-x u": "editor::Undo",
"ctrl-x ctrl-u": "editor::Redo",
"ctrl-f": "editor::MoveRight",
"ctrl-b": "editor::MoveLeft",
"ctrl-n": "editor::MoveDown",
"ctrl-p": "editor::MoveUp",
"ctrl-a": "editor::MoveToBeginningOfLine",
"ctrl-e": "editor::MoveToEndOfLine",
"alt-f": "editor::MoveToNextSubwordEnd",
"alt-b": "editor::MoveToPreviousSubwordStart",
"ctrl-d": "editor::Delete",
"alt-d": "editor::DeleteToNextWordEnd",
"ctrl-k": "editor::CutToEndOfLine",
"ctrl-w": "editor::Cut",
"alt-w": "editor::Copy",
"ctrl-y": "editor::Paste",
"ctrl-_": "editor::Undo",
"ctrl-v": "editor::MovePageDown",
"alt-v": "editor::MovePageUp",
"ctrl-x ]": "editor::MoveToEnd",
"ctrl-x [": "editor::MoveToBeginning",
"ctrl-l": "editor::ScrollCursorCenterTopBottom",
"ctrl-s": "buffer_search::Deploy",
"ctrl-x ctrl-f": "file_finder::Toggle",
"ctrl-shift-r": "editor::Rename"
}
},
{
"context": "Workspace",
"bindings": {
"ctrl-x k": "pane::CloseActiveItem",
"ctrl-x ctrl-c": "workspace::CloseWindow",
"ctrl-x o": "workspace::ActivateNextPane",
"ctrl-x b": "tab_switcher::Toggle",
"ctrl-x 0": "pane::CloseActiveItem",
"ctrl-x 1": "pane::CloseInactiveItems",
"ctrl-x 2": "pane::SplitVertical",
"ctrl-x ctrl-f": "file_finder::Toggle",
"ctrl-x ctrl-s": "workspace::Save",
"ctrl-x ctrl-w": "workspace::SaveAs",
"ctrl-x s": "workspace::SaveAll",
"shift shift": "file_finder::Toggle"
}
},
{
"context": "Pane",
"bindings": {
"ctrl-alt-left": "pane::GoBack",
"ctrl-alt-right": "pane::GoForward"
}
}
]

View File

@@ -24,8 +24,8 @@
"ctrl-g": ["editor::SelectNext", { "replace_newest": false }], "ctrl-g": ["editor::SelectNext", { "replace_newest": false }],
"ctrl-cmd-g": ["editor::SelectPrevious", { "replace_newest": false }], "ctrl-cmd-g": ["editor::SelectPrevious", { "replace_newest": false }],
"cmd-/": ["editor::ToggleComments", { "advance_downwards": true }], "cmd-/": ["editor::ToggleComments", { "advance_downwards": true }],
"cmd-up": "editor::SelectLargerSyntaxNode", "alt-up": "editor::SelectLargerSyntaxNode",
"cmd-down": "editor::SelectSmallerSyntaxNode", "alt-down": "editor::SelectSmallerSyntaxNode",
"shift-alt-up": "editor::MoveLineUp", "shift-alt-up": "editor::MoveLineUp",
"shift-alt-down": "editor::MoveLineDown", "shift-alt-down": "editor::MoveLineDown",
"cmd-alt-l": "editor::Format", "cmd-alt-l": "editor::Format",
@@ -58,12 +58,6 @@
"alt-enter": "editor::ToggleCodeActions" "alt-enter": "editor::ToggleCodeActions"
} }
}, },
{
"context": "BufferSearchBar > Editor",
"bindings": {
"shift-enter": "search::SelectPrevMatch"
}
},
{ {
"context": "Workspace", "context": "Workspace",
"bindings": { "bindings": {

View File

@@ -4,7 +4,9 @@
"cmd-shift-[": "pane::ActivatePrevItem", "cmd-shift-[": "pane::ActivatePrevItem",
"cmd-shift-]": "pane::ActivateNextItem", "cmd-shift-]": "pane::ActivateNextItem",
"ctrl-pageup": "pane::ActivatePrevItem", "ctrl-pageup": "pane::ActivatePrevItem",
"ctrl-pagedown": "pane::ActivateNextItem" "ctrl-pagedown": "pane::ActivateNextItem",
"ctrl-tab": "pane::ActivateNextItem",
"ctrl-shift-tab": "pane::ActivatePrevItem"
} }
}, },
{ {
@@ -19,7 +21,6 @@
"cmd-shift-l": "editor::SplitSelectionIntoLines", "cmd-shift-l": "editor::SplitSelectionIntoLines",
"cmd-shift-a": "editor::SelectLargerSyntaxNode", "cmd-shift-a": "editor::SelectLargerSyntaxNode",
"cmd-shift-d": "editor::DuplicateLineDown", "cmd-shift-d": "editor::DuplicateLineDown",
"ctrl-cmd-g": "editor::SelectAllMatches", // find_all_under
"shift-f12": "editor::FindAllReferences", "shift-f12": "editor::FindAllReferences",
"alt-cmd-down": "editor::GoToDefinition", "alt-cmd-down": "editor::GoToDefinition",
"ctrl-alt-cmd-down": "editor::GoToDefinitionSplit", "ctrl-alt-cmd-down": "editor::GoToDefinitionSplit",

View File

@@ -32,18 +32,6 @@
"(": "vim::SentenceBackward", "(": "vim::SentenceBackward",
")": "vim::SentenceForward", ")": "vim::SentenceForward",
"|": "vim::GoToColumn", "|": "vim::GoToColumn",
"] ]": "vim::NextSectionStart",
"] [": "vim::NextSectionEnd",
"[ [": "vim::PreviousSectionStart",
"[ ]": "vim::PreviousSectionEnd",
"] m": "vim::NextMethodStart",
"] M": "vim::NextMethodEnd",
"[ m": "vim::PreviousMethodStart",
"[ M": "vim::PreviousMethodEnd",
"[ *": "vim::PreviousComment",
"[ /": "vim::PreviousComment",
"] *": "vim::NextComment",
"] /": "vim::NextComment",
// Word motions // Word motions
"w": "vim::NextWordStart", "w": "vim::NextWordStart",
"e": "vim::NextWordEnd", "e": "vim::NextWordEnd",
@@ -66,10 +54,6 @@
"n": "vim::MoveToNextMatch", "n": "vim::MoveToNextMatch",
"shift-n": "vim::MoveToPrevMatch", "shift-n": "vim::MoveToPrevMatch",
"%": "vim::Matching", "%": "vim::Matching",
"] }": ["vim::UnmatchedForward", { "char": "}" }],
"[ {": ["vim::UnmatchedBackward", { "char": "{" }],
"] )": ["vim::UnmatchedForward", { "char": ")" }],
"[ (": ["vim::UnmatchedBackward", { "char": "(" }],
"f": ["vim::PushOperator", { "FindForward": { "before": false } }], "f": ["vim::PushOperator", { "FindForward": { "before": false } }],
"t": ["vim::PushOperator", { "FindForward": { "before": true } }], "t": ["vim::PushOperator", { "FindForward": { "before": true } }],
"shift-f": ["vim::PushOperator", { "FindBackward": { "after": false } }], "shift-f": ["vim::PushOperator", { "FindBackward": { "after": false } }],
@@ -143,9 +127,6 @@
"shift-h": "vim::WindowTop", "shift-h": "vim::WindowTop",
"shift-m": "vim::WindowMiddle", "shift-m": "vim::WindowMiddle",
"shift-l": "vim::WindowBottom", "shift-l": "vim::WindowBottom",
"q": "vim::ToggleRecord",
"shift-q": "vim::ReplayLastRecording",
"@": ["vim::PushOperator", "ReplayRegister"],
// z commands // z commands
"z enter": ["workspace::SendKeystrokes", "z t ^"], "z enter": ["workspace::SendKeystrokes", "z t ^"],
"z -": ["workspace::SendKeystrokes", "z b ^"], "z -": ["workspace::SendKeystrokes", "z b ^"],
@@ -156,14 +137,14 @@
"z .": ["workspace::SendKeystrokes", "z z ^"], "z .": ["workspace::SendKeystrokes", "z z ^"],
"z b": "editor::ScrollCursorBottom", "z b": "editor::ScrollCursorBottom",
"z a": "editor::ToggleFold", "z a": "editor::ToggleFold",
"z shift-a": "editor::ToggleFoldRecursive", "z A": "editor::ToggleFoldRecursive",
"z c": "editor::Fold", "z c": "editor::Fold",
"z shift-c": "editor::FoldRecursive", "z C": "editor::FoldRecursive",
"z o": "editor::UnfoldLines", "z o": "editor::UnfoldLines",
"z shift-o": "editor::UnfoldRecursive", "z O": "editor::UnfoldRecursive",
"z f": "editor::FoldSelectedRanges", "z f": "editor::FoldSelectedRanges",
"z shift-m": "editor::FoldAll", "z M": "editor::FoldAll",
"z shift-r": "editor::UnfoldAll", "z R": "editor::UnfoldAll",
"shift-z shift-q": ["pane::CloseActiveItem", { "saveIntent": "skip" }], "shift-z shift-q": ["pane::CloseActiveItem", { "saveIntent": "skip" }],
"shift-z shift-z": ["pane::CloseActiveItem", { "saveIntent": "saveAll" }], "shift-z shift-z": ["pane::CloseActiveItem", { "saveIntent": "saveAll" }],
// Count support // Count support
@@ -176,6 +157,51 @@
"7": ["vim::Number", 7], "7": ["vim::Number", 7],
"8": ["vim::Number", 8], "8": ["vim::Number", 8],
"9": ["vim::Number", 9], "9": ["vim::Number", 9],
// window related commands (ctrl-w X)
"ctrl-w": null,
"ctrl-w left": ["workspace::ActivatePaneInDirection", "Left"],
"ctrl-w right": ["workspace::ActivatePaneInDirection", "Right"],
"ctrl-w up": ["workspace::ActivatePaneInDirection", "Up"],
"ctrl-w down": ["workspace::ActivatePaneInDirection", "Down"],
"ctrl-w h": ["workspace::ActivatePaneInDirection", "Left"],
"ctrl-w l": ["workspace::ActivatePaneInDirection", "Right"],
"ctrl-w k": ["workspace::ActivatePaneInDirection", "Up"],
"ctrl-w j": ["workspace::ActivatePaneInDirection", "Down"],
"ctrl-w ctrl-h": ["workspace::ActivatePaneInDirection", "Left"],
"ctrl-w ctrl-l": ["workspace::ActivatePaneInDirection", "Right"],
"ctrl-w ctrl-k": ["workspace::ActivatePaneInDirection", "Up"],
"ctrl-w ctrl-j": ["workspace::ActivatePaneInDirection", "Down"],
"ctrl-w shift-left": ["workspace::SwapPaneInDirection", "Left"],
"ctrl-w shift-right": ["workspace::SwapPaneInDirection", "Right"],
"ctrl-w shift-up": ["workspace::SwapPaneInDirection", "Up"],
"ctrl-w shift-down": ["workspace::SwapPaneInDirection", "Down"],
"ctrl-w shift-h": ["workspace::SwapPaneInDirection", "Left"],
"ctrl-w shift-l": ["workspace::SwapPaneInDirection", "Right"],
"ctrl-w shift-k": ["workspace::SwapPaneInDirection", "Up"],
"ctrl-w shift-j": ["workspace::SwapPaneInDirection", "Down"],
"ctrl-w g t": "pane::ActivateNextItem",
"ctrl-w ctrl-g t": "pane::ActivateNextItem",
"ctrl-w g shift-t": "pane::ActivatePrevItem",
"ctrl-w ctrl-g shift-t": "pane::ActivatePrevItem",
"ctrl-w w": "workspace::ActivateNextPane",
"ctrl-w ctrl-w": "workspace::ActivateNextPane",
"ctrl-w p": "workspace::ActivatePreviousPane",
"ctrl-w ctrl-p": "workspace::ActivatePreviousPane",
"ctrl-w shift-w": "workspace::ActivatePreviousPane",
"ctrl-w ctrl-shift-w": "workspace::ActivatePreviousPane",
"ctrl-w v": "pane::SplitVertical",
"ctrl-w ctrl-v": "pane::SplitVertical",
"ctrl-w s": "pane::SplitHorizontal",
"ctrl-w shift-s": "pane::SplitHorizontal",
"ctrl-w ctrl-s": "pane::SplitHorizontal",
"ctrl-w c": "pane::CloseAllItems",
"ctrl-w ctrl-c": "pane::CloseAllItems",
"ctrl-w q": "pane::CloseAllItems",
"ctrl-w ctrl-q": "pane::CloseAllItems",
"ctrl-w o": "workspace::CloseInactiveTabsAndPanes",
"ctrl-w ctrl-o": "workspace::CloseInactiveTabsAndPanes",
"ctrl-w n": "workspace::NewFileSplitHorizontal",
"ctrl-w ctrl-n": "workspace::NewFileSplitHorizontal",
"ctrl-w d": "editor::GoToDefinitionSplit", "ctrl-w d": "editor::GoToDefinitionSplit",
"ctrl-w g d": "editor::GoToDefinitionSplit", "ctrl-w g d": "editor::GoToDefinitionSplit",
"ctrl-w shift-d": "editor::GoToTypeDefinitionSplit", "ctrl-w shift-d": "editor::GoToTypeDefinitionSplit",
@@ -219,13 +245,15 @@
"shift-s": "vim::SubstituteLine", "shift-s": "vim::SubstituteLine",
">": ["vim::PushOperator", "Indent"], ">": ["vim::PushOperator", "Indent"],
"<": ["vim::PushOperator", "Outdent"], "<": ["vim::PushOperator", "Outdent"],
"=": ["vim::PushOperator", "AutoIndent"],
"g u": ["vim::PushOperator", "Lowercase"], "g u": ["vim::PushOperator", "Lowercase"],
"g shift-u": ["vim::PushOperator", "Uppercase"], "g shift-u": ["vim::PushOperator", "Uppercase"],
"g ~": ["vim::PushOperator", "OppositeCase"], "g ~": ["vim::PushOperator", "OppositeCase"],
"\"": ["vim::PushOperator", "Register"], "\"": ["vim::PushOperator", "Register"],
"g q": ["vim::PushOperator", "Rewrap"], "g q": ["vim::PushOperator", "Rewrap"],
"g w": ["vim::PushOperator", "Rewrap"], "g w": ["vim::PushOperator", "Rewrap"],
"q": "vim::ToggleRecord",
"shift-q": "vim::ReplayLastRecording",
"@": ["vim::PushOperator", "ReplayRegister"],
"ctrl-pagedown": "pane::ActivateNextItem", "ctrl-pagedown": "pane::ActivateNextItem",
"ctrl-pageup": "pane::ActivatePrevItem", "ctrl-pageup": "pane::ActivatePrevItem",
"insert": "vim::InsertBefore", "insert": "vim::InsertBefore",
@@ -251,7 +279,7 @@
"bindings": { "bindings": {
":": "vim::VisualCommand", ":": "vim::VisualCommand",
"u": "vim::ConvertToLowerCase", "u": "vim::ConvertToLowerCase",
"shift-u": "vim::ConvertToUpperCase", "U": "vim::ConvertToUpperCase",
"o": "vim::OtherEnd", "o": "vim::OtherEnd",
"shift-o": "vim::OtherEnd", "shift-o": "vim::OtherEnd",
"d": "vim::VisualDelete", "d": "vim::VisualDelete",
@@ -275,8 +303,8 @@
"g ctrl-x": ["vim::Decrement", { "step": true }], "g ctrl-x": ["vim::Decrement", { "step": true }],
"shift-i": "vim::InsertBefore", "shift-i": "vim::InsertBefore",
"shift-a": "vim::InsertAfter", "shift-a": "vim::InsertAfter",
"g shift-i": "vim::VisualInsertFirstNonWhiteSpace", "g I": "vim::VisualInsertFirstNonWhiteSpace",
"g shift-a": "vim::VisualInsertEndOfLine", "g A": "vim::VisualInsertEndOfLine",
"shift-j": "vim::JoinLines", "shift-j": "vim::JoinLines",
"r": ["vim::PushOperator", "Replace"], "r": ["vim::PushOperator", "Replace"],
"ctrl-c": ["vim::SwitchMode", "Normal"], "ctrl-c": ["vim::SwitchMode", "Normal"],
@@ -284,7 +312,6 @@
"ctrl-[": ["vim::SwitchMode", "Normal"], "ctrl-[": ["vim::SwitchMode", "Normal"],
">": "vim::Indent", ">": "vim::Indent",
"<": "vim::Outdent", "<": "vim::Outdent",
"=": "vim::AutoIndent",
"i": ["vim::PushOperator", { "Object": { "around": false } }], "i": ["vim::PushOperator", { "Object": { "around": false } }],
"a": ["vim::PushOperator", { "Object": { "around": true } }], "a": ["vim::PushOperator", { "Object": { "around": true } }],
"g c": "vim::ToggleComments", "g c": "vim::ToggleComments",
@@ -312,32 +339,10 @@
"ctrl-t": "vim::Indent", "ctrl-t": "vim::Indent",
"ctrl-d": "vim::Outdent", "ctrl-d": "vim::Outdent",
"ctrl-k": ["vim::PushOperator", { "Digraph": {} }], "ctrl-k": ["vim::PushOperator", { "Digraph": {} }],
"ctrl-v": ["vim::PushOperator", { "Literal": {} }],
"ctrl-shift-v": "editor::Paste", // note: this is *very* similar to ctrl-v in vim, but ctrl-shift-v on linux is the typical shortcut for paste when ctrl-v is already in use.
"ctrl-q": ["vim::PushOperator", { "Literal": {} }],
"ctrl-shift-q": ["vim::PushOperator", { "Literal": {} }],
"ctrl-r": ["vim::PushOperator", "Register"], "ctrl-r": ["vim::PushOperator", "Register"],
"insert": "vim::ToggleReplace", "insert": "vim::ToggleReplace"
"ctrl-o": "vim::TemporaryNormal"
} }
}, },
{
"context": "vim_mode == helix_normal",
"bindings": {
"i": "vim::InsertBefore",
"a": "vim::InsertAfter",
"d": "vim::HelixDelete",
"w": "vim::NextWordStart",
"e": "vim::NextWordEnd",
"b": "vim::PreviousWordStart",
"h": "vim::Left",
"j": "vim::Down",
"k": "vim::Up",
"l": "vim::Right"
}
},
{ {
"context": "vim_mode == insert && !(showing_code_actions || showing_completions)", "context": "vim_mode == insert && !(showing_code_actions || showing_completions)",
"bindings": { "bindings": {
@@ -352,10 +357,6 @@
"ctrl-c": "vim::NormalBefore", "ctrl-c": "vim::NormalBefore",
"ctrl-[": "vim::NormalBefore", "ctrl-[": "vim::NormalBefore",
"ctrl-k": ["vim::PushOperator", { "Digraph": {} }], "ctrl-k": ["vim::PushOperator", { "Digraph": {} }],
"ctrl-v": ["vim::PushOperator", { "Literal": {} }],
"ctrl-shift-v": "editor::Paste", // note: this is *very* similar to ctrl-v in vim, but ctrl-shift-v on linux is the typical shortcut for paste when ctrl-v is already in use.
"ctrl-q": ["vim::PushOperator", { "Literal": {} }],
"ctrl-shift-q": ["vim::PushOperator", { "Literal": {} }],
"backspace": "vim::UndoReplace", "backspace": "vim::UndoReplace",
"tab": "vim::Tab", "tab": "vim::Tab",
"enter": "vim::Enter", "enter": "vim::Enter",
@@ -370,9 +371,7 @@
"escape": "vim::ClearOperators", "escape": "vim::ClearOperators",
"ctrl-c": "vim::ClearOperators", "ctrl-c": "vim::ClearOperators",
"ctrl-[": "vim::ClearOperators", "ctrl-[": "vim::ClearOperators",
"ctrl-k": ["vim::PushOperator", { "Digraph": {} }], "ctrl-k": ["vim::PushOperator", { "Digraph": {} }]
"ctrl-v": ["vim::PushOperator", { "Literal": {} }],
"ctrl-q": ["vim::PushOperator", { "Literal": {} }]
} }
}, },
{ {
@@ -380,8 +379,7 @@
"bindings": { "bindings": {
"escape": "vim::ClearOperators", "escape": "vim::ClearOperators",
"ctrl-c": "vim::ClearOperators", "ctrl-c": "vim::ClearOperators",
"ctrl-[": "vim::ClearOperators", "ctrl-[": "vim::ClearOperators"
"g c": "vim::Comment"
} }
}, },
{ {
@@ -401,17 +399,12 @@
"b": "vim::Parentheses", "b": "vim::Parentheses",
"[": "vim::SquareBrackets", "[": "vim::SquareBrackets",
"]": "vim::SquareBrackets", "]": "vim::SquareBrackets",
"r": "vim::SquareBrackets",
"{": "vim::CurlyBrackets", "{": "vim::CurlyBrackets",
"}": "vim::CurlyBrackets", "}": "vim::CurlyBrackets",
"shift-b": "vim::CurlyBrackets", "shift-b": "vim::CurlyBrackets",
"<": "vim::AngleBrackets", "<": "vim::AngleBrackets",
">": "vim::AngleBrackets", ">": "vim::AngleBrackets",
"a": "vim::Argument", "a": "vim::Argument"
"i": "vim::IndentObj",
"shift-i": ["vim::IndentObj", { "includeBelow": true }],
"f": "vim::Method",
"c": "vim::Class"
} }
}, },
{ {
@@ -486,61 +479,12 @@
"<": "vim::CurrentLine" "<": "vim::CurrentLine"
} }
}, },
{
"context": "vim_operator == eq",
"bindings": {
"=": "vim::CurrentLine"
}
},
{ {
"context": "vim_operator == gc", "context": "vim_operator == gc",
"bindings": { "bindings": {
"c": "vim::CurrentLine" "c": "vim::CurrentLine"
} }
}, },
{
"context": "vim_mode == literal",
"bindings": {
"ctrl-@": ["vim::Literal", ["ctrl-@", "\u0000"]],
"ctrl-a": ["vim::Literal", ["ctrl-a", "\u0001"]],
"ctrl-b": ["vim::Literal", ["ctrl-b", "\u0002"]],
"ctrl-c": ["vim::Literal", ["ctrl-c", "\u0003"]],
"ctrl-d": ["vim::Literal", ["ctrl-d", "\u0004"]],
"ctrl-e": ["vim::Literal", ["ctrl-e", "\u0005"]],
"ctrl-f": ["vim::Literal", ["ctrl-f", "\u0006"]],
"ctrl-g": ["vim::Literal", ["ctrl-g", "\u0007"]],
"ctrl-h": ["vim::Literal", ["ctrl-h", "\u0008"]],
"ctrl-i": ["vim::Literal", ["ctrl-i", "\u0009"]],
"ctrl-j": ["vim::Literal", ["ctrl-j", "\u000A"]],
"ctrl-k": ["vim::Literal", ["ctrl-k", "\u000B"]],
"ctrl-l": ["vim::Literal", ["ctrl-l", "\u000C"]],
"ctrl-m": ["vim::Literal", ["ctrl-m", "\u000D"]],
"ctrl-n": ["vim::Literal", ["ctrl-n", "\u000E"]],
"ctrl-o": ["vim::Literal", ["ctrl-o", "\u000F"]],
"ctrl-p": ["vim::Literal", ["ctrl-p", "\u0010"]],
"ctrl-q": ["vim::Literal", ["ctrl-q", "\u0011"]],
"ctrl-r": ["vim::Literal", ["ctrl-r", "\u0012"]],
"ctrl-s": ["vim::Literal", ["ctrl-s", "\u0013"]],
"ctrl-t": ["vim::Literal", ["ctrl-t", "\u0014"]],
"ctrl-u": ["vim::Literal", ["ctrl-u", "\u0015"]],
"ctrl-v": ["vim::Literal", ["ctrl-v", "\u0016"]],
"ctrl-w": ["vim::Literal", ["ctrl-w", "\u0017"]],
"ctrl-x": ["vim::Literal", ["ctrl-x", "\u0018"]],
"ctrl-y": ["vim::Literal", ["ctrl-y", "\u0019"]],
"ctrl-z": ["vim::Literal", ["ctrl-z", "\u001A"]],
"ctrl-[": ["vim::Literal", ["ctrl-[", "\u001B"]],
"ctrl-\\": ["vim::Literal", ["ctrl-\\", "\u001C"]],
"ctrl-]": ["vim::Literal", ["ctrl-]", "\u001D"]],
"ctrl-^": ["vim::Literal", ["ctrl-^", "\u001E"]],
"ctrl-_": ["vim::Literal", ["ctrl-_", "\u001F"]],
"escape": ["vim::Literal", ["escape", "\u001B"]],
"enter": ["vim::Literal", ["enter", "\u000D"]],
"tab": ["vim::Literal", ["tab", "\u0009"]],
// zed extensions:
"backspace": ["vim::Literal", ["backspace", "\u0008"]],
"delete": ["vim::Literal", ["delete", "\u007F"]]
}
},
{ {
"context": "BufferSearchBar && !in_replace", "context": "BufferSearchBar && !in_replace",
"bindings": { "bindings": {
@@ -549,63 +493,7 @@
} }
}, },
{ {
"context": "ProjectPanel || CollabPanel || OutlinePanel || ChatPanel || VimControl || EmptyPane || SharedScreen || MarkdownPreview || KeyContextView", "context": "EmptyPane || SharedScreen",
"bindings": {
// window related commands (ctrl-w X)
"ctrl-w": null,
"ctrl-w left": ["workspace::ActivatePaneInDirection", "Left"],
"ctrl-w right": ["workspace::ActivatePaneInDirection", "Right"],
"ctrl-w up": ["workspace::ActivatePaneInDirection", "Up"],
"ctrl-w down": ["workspace::ActivatePaneInDirection", "Down"],
"ctrl-w h": ["workspace::ActivatePaneInDirection", "Left"],
"ctrl-w l": ["workspace::ActivatePaneInDirection", "Right"],
"ctrl-w k": ["workspace::ActivatePaneInDirection", "Up"],
"ctrl-w j": ["workspace::ActivatePaneInDirection", "Down"],
"ctrl-w ctrl-h": ["workspace::ActivatePaneInDirection", "Left"],
"ctrl-w ctrl-l": ["workspace::ActivatePaneInDirection", "Right"],
"ctrl-w ctrl-k": ["workspace::ActivatePaneInDirection", "Up"],
"ctrl-w ctrl-j": ["workspace::ActivatePaneInDirection", "Down"],
"ctrl-w shift-left": ["workspace::SwapPaneInDirection", "Left"],
"ctrl-w shift-right": ["workspace::SwapPaneInDirection", "Right"],
"ctrl-w shift-up": ["workspace::SwapPaneInDirection", "Up"],
"ctrl-w shift-down": ["workspace::SwapPaneInDirection", "Down"],
"ctrl-w shift-h": ["workspace::SwapPaneInDirection", "Left"],
"ctrl-w shift-l": ["workspace::SwapPaneInDirection", "Right"],
"ctrl-w shift-k": ["workspace::SwapPaneInDirection", "Up"],
"ctrl-w shift-j": ["workspace::SwapPaneInDirection", "Down"],
"ctrl-w >": ["vim::ResizePane", "Widen"],
"ctrl-w <": ["vim::ResizePane", "Narrow"],
"ctrl-w -": ["vim::ResizePane", "Shorten"],
"ctrl-w +": ["vim::ResizePane", "Lengthen"],
"ctrl-w _": "vim::MaximizePane",
"ctrl-w =": "vim::ResetPaneSizes",
"ctrl-w g t": "pane::ActivateNextItem",
"ctrl-w ctrl-g t": "pane::ActivateNextItem",
"ctrl-w g shift-t": "pane::ActivatePrevItem",
"ctrl-w ctrl-g shift-t": "pane::ActivatePrevItem",
"ctrl-w w": "workspace::ActivateNextPane",
"ctrl-w ctrl-w": "workspace::ActivateNextPane",
"ctrl-w p": "workspace::ActivatePreviousPane",
"ctrl-w ctrl-p": "workspace::ActivatePreviousPane",
"ctrl-w shift-w": "workspace::ActivatePreviousPane",
"ctrl-w ctrl-shift-w": "workspace::ActivatePreviousPane",
"ctrl-w v": "pane::SplitVertical",
"ctrl-w ctrl-v": "pane::SplitVertical",
"ctrl-w s": "pane::SplitHorizontal",
"ctrl-w shift-s": "pane::SplitHorizontal",
"ctrl-w ctrl-s": "pane::SplitHorizontal",
"ctrl-w c": "pane::CloseAllItems",
"ctrl-w ctrl-c": "pane::CloseAllItems",
"ctrl-w q": "pane::CloseAllItems",
"ctrl-w ctrl-q": "pane::CloseAllItems",
"ctrl-w o": "workspace::CloseInactiveTabsAndPanes",
"ctrl-w ctrl-o": "workspace::CloseInactiveTabsAndPanes",
"ctrl-w n": "workspace::NewFileSplitHorizontal",
"ctrl-w ctrl-n": "workspace::NewFileSplitHorizontal"
}
},
{
"context": "EmptyPane || SharedScreen || MarkdownPreview || KeyContextView || Welcome",
"bindings": { "bindings": {
":": "command_palette::Toggle", ":": "command_palette::Toggle",
"g /": "pane::DeploySearch" "g /": "pane::DeploySearch"
@@ -633,12 +521,6 @@
"p": "project_panel::Open", "p": "project_panel::Open",
"x": "project_panel::RevealInFileManager", "x": "project_panel::RevealInFileManager",
"s": "project_panel::OpenWithSystem", "s": "project_panel::OpenWithSystem",
"] c": "project_panel::SelectNextGitEntry",
"[ c": "project_panel::SelectPrevGitEntry",
"] d": "project_panel::SelectNextDiagnostic",
"[ d": "project_panel::SelectPrevDiagnostic",
"}": "project_panel::SelectNextDirectory",
"{": "project_panel::SelectPrevDirectory",
"shift-g": "menu::SelectLast", "shift-g": "menu::SelectLast",
"g g": "menu::SelectFirst", "g g": "menu::SelectFirst",
"-": "project_panel::SelectParent", "-": "project_panel::SelectParent",

View File

@@ -88,6 +88,7 @@ origin: (f64, f64),
<edit> <edit>
<path>src/shapes/rectangle.rs</path> <path>src/shapes/rectangle.rs</path>
<description>Update the Rectangle's new function to take an origin parameter</description>
<operation>update</operation> <operation>update</operation>
<old_text> <old_text>
fn new(width: f64, height: f64) -> Self { fn new(width: f64, height: f64) -> Self {
@@ -116,6 +117,7 @@ pub struct Circle {
<edit> <edit>
<path>src/shapes/circle.rs</path> <path>src/shapes/circle.rs</path>
<description>Update the Circle's new function to take an origin parameter</description>
<operation>update</operation> <operation>update</operation>
<old_text> <old_text>
fn new(radius: f64) -> Self { fn new(radius: f64) -> Self {
@@ -132,6 +134,7 @@ fn new(origin: (f64, f64), radius: f64) -> Self {
<edit> <edit>
<path>src/shapes/rectangle.rs</path> <path>src/shapes/rectangle.rs</path>
<description>Add an import for the std::fmt module</description>
<operation>insert_before</operation> <operation>insert_before</operation>
<old_text> <old_text>
struct Rectangle { struct Rectangle {
@@ -144,10 +147,7 @@ use std::fmt;
<edit> <edit>
<path>src/shapes/rectangle.rs</path> <path>src/shapes/rectangle.rs</path>
<description> <description>Add a Display implementation for Rectangle</description>
Add a manual Display implementation for Rectangle.
Currently, this is the same as a derived Display implementation.
</description>
<operation>insert_after</operation> <operation>insert_after</operation>
<old_text> <old_text>
Rectangle { width, height } Rectangle { width, height }
@@ -169,6 +169,7 @@ impl fmt::Display for Rectangle {
<edit> <edit>
<path>src/shapes/circle.rs</path> <path>src/shapes/circle.rs</path>
<description>Add an import for the `std::fmt` module</description>
<operation>insert_before</operation> <operation>insert_before</operation>
<old_text> <old_text>
struct Circle { struct Circle {
@@ -180,6 +181,7 @@ use std::fmt;
<edit> <edit>
<path>src/shapes/circle.rs</path> <path>src/shapes/circle.rs</path>
<description>Add a Display implementation for Circle</description>
<operation>insert_after</operation> <operation>insert_after</operation>
<old_text> <old_text>
Circle { radius } Circle { radius }

View File

@@ -68,17 +68,9 @@
"ui_font_size": 16, "ui_font_size": 16,
// How much to fade out unused code. // How much to fade out unused code.
"unnecessary_code_fade": 0.3, "unnecessary_code_fade": 0.3,
// Active pane styling settings. // The factor to grow the active pane by. Defaults to 1.0
"active_pane_modifiers": { // which gives the same size as all other panes.
// The factor to grow the active pane by. Defaults to 1.0 "active_pane_magnification": 1.0,
// which gives the same size as all other panes.
"magnification": 1.0,
// Inset border size of the active pane, in pixels.
"border_size": 0.0,
// Opacity of the inactive panes. 0 means transparent, 1 means opaque.
// Values are clamped to the [0.0, 1.0] range.
"inactive_opacity": 1.0
},
// The direction that you want to split panes horizontally. Defaults to "up" // The direction that you want to split panes horizontally. Defaults to "up"
"pane_split_direction_horizontal": "up", "pane_split_direction_horizontal": "up",
// The direction that you want to split panes horizontally. Defaults to "left" // The direction that you want to split panes horizontally. Defaults to "left"
@@ -157,10 +149,10 @@
"auto_signature_help": false, "auto_signature_help": false,
/// Whether to show the signature help after completion or a bracket pair inserted. /// Whether to show the signature help after completion or a bracket pair inserted.
/// If `auto_signature_help` is enabled, this setting will be treated as enabled also. /// If `auto_signature_help` is enabled, this setting will be treated as enabled also.
"show_signature_help_after_edits": false, "show_signature_help_after_edits": true,
// Whether to show wrap guides (vertical rulers) in the editor. // Whether to show wrap guides (vertical rulers) in the editor.
// Setting this to true will show a guide at the 'preferred_line_length' value // Setting this to true will show a guide at the 'preferred_line_length' value
// if 'soft_wrap' is set to 'preferred_line_length', and will show any // if softwrap is set to 'preferred_line_length', and will show any
// additional guides as specified by the 'wrap_guides' setting. // additional guides as specified by the 'wrap_guides' setting.
"show_wrap_guides": true, "show_wrap_guides": true,
// Character counts at which to show wrap guides in the editor. // Character counts at which to show wrap guides in the editor.
@@ -182,8 +174,6 @@
// bracket, brace, single or double quote characters. // bracket, brace, single or double quote characters.
// For example, when you select text and type (, Zed will surround the text with (). // For example, when you select text and type (, Zed will surround the text with ().
"use_auto_surround": true, "use_auto_surround": true,
// Whether indentation of pasted content should be adjusted based on the context.
"auto_indent_on_paste": true,
// Controls how the editor handles the autoclosed characters. // Controls how the editor handles the autoclosed characters.
// When set to `false`(default), skipping over and auto-removing of the closing characters // When set to `false`(default), skipping over and auto-removing of the closing characters
// happen only for auto-inserted characters. // happen only for auto-inserted characters.
@@ -193,9 +183,6 @@
// Controls whether inline completions are shown immediately (true) // Controls whether inline completions are shown immediately (true)
// or manually by triggering `editor::ShowInlineCompletion` (false). // or manually by triggering `editor::ShowInlineCompletion` (false).
"show_inline_completions": true, "show_inline_completions": true,
// Controls whether inline completions are shown in a given language scope.
// Example: ["string", "comment"]
"inline_completions_disabled_in": [],
// Whether to show tabs and spaces in the editor. // Whether to show tabs and spaces in the editor.
// This setting can take three values: // This setting can take three values:
// //
@@ -300,8 +287,6 @@
"scroll_beyond_last_line": "one_page", "scroll_beyond_last_line": "one_page",
// The number of lines to keep above/below the cursor when scrolling. // The number of lines to keep above/below the cursor when scrolling.
"vertical_scroll_margin": 3, "vertical_scroll_margin": 3,
// Whether to scroll when clicking near the edge of the visible text area.
"autoscroll_on_clicks": false,
// Scroll sensitivity multiplier. This multiplier is applied // Scroll sensitivity multiplier. This multiplier is applied
// to both the horizontal and vertical delta values while scrolling. // to both the horizontal and vertical delta values while scrolling.
"scroll_sensitivity": 1.0, "scroll_sensitivity": 1.0,
@@ -384,27 +369,6 @@
/// 5. Never show the scrollbar: /// 5. Never show the scrollbar:
/// "never" /// "never"
"show": null "show": null
},
/// Which files containing diagnostic errors/warnings to mark in the project panel.
/// This setting can take the following three values:
///
/// 1. Do not mark any files:
/// "off"
/// 2. Only mark files with errors:
/// "errors"
/// 3. Mark files with errors and warnings:
/// "all"
"show_diagnostics": "all",
// Settings related to indent guides in the project panel.
"indent_guides": {
// When to show indent guides in the project panel.
// This setting can take two values:
//
// 1. Always show indent guides:
// "always"
// 2. Never show indent guides:
// "never"
"show": "always"
} }
}, },
"outline_panel": { "outline_panel": {
@@ -428,35 +392,7 @@
"auto_reveal_entries": true, "auto_reveal_entries": true,
/// Whether to fold directories automatically /// Whether to fold directories automatically
/// when a directory has only one directory inside. /// when a directory has only one directory inside.
"auto_fold_dirs": true, "auto_fold_dirs": true
// Settings related to indent guides in the outline panel.
"indent_guides": {
// When to show indent guides in the outline panel.
// This setting can take two values:
//
// 1. Always show indent guides:
// "always"
// 2. Never show indent guides:
// "never"
"show": "always"
},
/// Scrollbar-related settings
"scrollbar": {
/// When to show the scrollbar in the project panel.
/// This setting can take four values:
///
/// 1. null (default): Inherit editor settings
/// 2. Show the scrollbar if there's important information or
/// follow the system's configured behavior (default):
/// "auto"
/// 3. Match the system's configured behavior:
/// "system"
/// 4. Always show the scrollbar:
/// "always"
/// 5. Never show the scrollbar:
/// "never"
"show": null
}
}, },
"collaboration_panel": { "collaboration_panel": {
// Whether to show the collaboration panel button in the status bar. // Whether to show the collaboration panel button in the status bar.
@@ -500,7 +436,7 @@
"default_width": 640, "default_width": 640,
// Default height when the assistant is docked to the bottom. // Default height when the assistant is docked to the bottom.
"default_height": 320, "default_height": 320,
// The default model to use when creating new chats. // The default model to use when creating new contexts.
"default_model": { "default_model": {
// The provider to use. // The provider to use.
"provider": "zed.dev", "provider": "zed.dev",
@@ -559,26 +495,13 @@
"close_position": "right", "close_position": "right",
// Whether to show the file icon for a tab. // Whether to show the file icon for a tab.
"file_icons": false, "file_icons": false,
// Whether to always show the close button on tabs.
"always_show_close_button": false,
// What to do after closing the current tab. // What to do after closing the current tab.
// //
// 1. Activate the tab that was open previously (default) // 1. Activate the tab that was open previously (default)
// "History" // "History"
// 2. Activate the neighbour tab (prefers the right one, if present) // 2. Activate the neighbour tab (prefers the right one, if present)
// "Neighbour" // "Neighbour"
"activate_on_close": "history", "activate_on_close": "history"
/// Which files containing diagnostic errors/warnings to mark in the tabs.
/// Diagnostics are only shown when file icons are also active.
/// This setting only works when can take the following three values:
///
/// 1. Do not mark any files:
/// "off"
/// 2. Only mark files with errors:
/// "errors"
/// 3. Mark files with errors and warnings:
/// "all"
"show_diagnostics": "off"
}, },
// Settings related to preview tabs. // Settings related to preview tabs.
"preview_tabs": { "preview_tabs": {
@@ -595,23 +518,7 @@
// Settings related to the file finder. // Settings related to the file finder.
"file_finder": { "file_finder": {
// Whether to show file icons in the file finder. // Whether to show file icons in the file finder.
"file_icons": true, "file_icons": true
// Determines how much space the file finder can take up in relation to the available window width.
// There are 5 possible width values:
//
// 1. Small: This value is essentially a fixed width.
// "modal_width": "small"
// 2. Medium:
// "modal_width": "medium"
// 3. Large:
// "modal_width": "large"
// 4. Extra Large:
// "modal_width": "xlarge"
// 5. Fullscreen: This value removes any horizontal padding, as it consumes the whole viewport width.
// "modal_width": "full"
//
// Default: small
"modal_max_width": "small"
}, },
// Whether or not to remove any trailing whitespace from lines of a buffer // Whether or not to remove any trailing whitespace from lines of a buffer
// before saving it. // before saving it.
@@ -680,7 +587,7 @@
}, },
// Add files or globs of files that will be excluded by Zed entirely: // Add files or globs of files that will be excluded by Zed entirely:
// they will be skipped during FS scan(s), file tree and file search // they will be skipped during FS scan(s), file tree and file search
// will lack the corresponding file entries. Overrides `file_scan_inclusions`. // will lack the corresponding file entries.
"file_scan_exclusions": [ "file_scan_exclusions": [
"**/.git", "**/.git",
"**/.svn", "**/.svn",
@@ -691,11 +598,6 @@
"**/.classpath", "**/.classpath",
"**/.settings" "**/.settings"
], ],
// Add files or globs of files that will be included by Zed, even when
// ignored by git. This is useful for files that are not tracked by git,
// but are still important to your project. Note that globs that are
// overly broad can slow down Zed's file scanning. Overridden by `file_scan_exclusions`.
"file_scan_inclusions": [".env*"],
// Git gutter behavior configuration. // Git gutter behavior configuration.
"git": { "git": {
// Control whether the git gutter is shown. May take 2 values: // Control whether the git gutter is shown. May take 2 values:
@@ -711,12 +613,6 @@
// Sets a delay after which the inline blame information is shown. // Sets a delay after which the inline blame information is shown.
// Delay is restarted with every cursor movement. // Delay is restarted with every cursor movement.
// "delay_ms": 600 // "delay_ms": 600
//
// Whether or not do display the git commit summary on the same line.
// "show_commit_summary": false
//
// The minimum column number to show the inline blame information at
// "min_column": 0
} }
}, },
// Configuration for how direnv configuration should be loaded. May take 2 values: // Configuration for how direnv configuration should be loaded. May take 2 values:
@@ -856,12 +752,8 @@
} }
}, },
"toolbar": { "toolbar": {
// Whether to display the terminal title in its toolbar's breadcrumbs. // Whether to display the terminal title in its toolbar.
// Only shown if the terminal title is not empty. "title": true
//
// The shell running in the terminal needs to be configured to emit the title.
// Example: `echo -e "\e]2;New Title\007";`
"breadcrumbs": true
} }
// Set the terminal's font size. If this option is not included, // Set the terminal's font size. If this option is not included,
// the terminal will default to matching the buffer's font size. // the terminal will default to matching the buffer's font size.
@@ -897,14 +789,21 @@
// //
"file_types": { "file_types": {
"Plain Text": ["txt"], "Plain Text": ["txt"],
"JSONC": ["**/.zed/**/*.json", "**/zed/**/*.json", "**/Zed/**/*.json", "**/.vscode/**/*.json"], "JSON": ["flake.lock"],
"Shell Script": [".env.*"] "JSONC": [
"**/.zed/**/*.json",
"**/zed/**/*.json",
"**/Zed/**/*.json",
"tsconfig.json",
"pyrightconfig.json"
],
"TOML": ["uv.lock"]
}, },
/// By default use a recent system version of node, or install our own. /// By default use a recent system version of node, or install our own.
/// You can override this to use a version of node that is not in $PATH with: /// You can override this to use a version of node that is not in $PATH with:
/// { /// {
/// "node": { /// "node": {
/// "path": "/path/to/node" /// "node_path": "/path/to/node"
/// "npm_path": "/path/to/npm" (defaults to node_path/../npm) /// "npm_path": "/path/to/npm" (defaults to node_path/../npm)
/// } /// }
/// } /// }
@@ -1086,11 +985,13 @@
"api_url": "https://generativelanguage.googleapis.com" "api_url": "https://generativelanguage.googleapis.com"
}, },
"ollama": { "ollama": {
"api_url": "http://localhost:11434" "api_url": "http://localhost:11434",
"low_speed_timeout_in_seconds": 60
}, },
"openai": { "openai": {
"version": "1", "version": "1",
"api_url": "https://api.openai.com/v1" "api_url": "https://api.openai.com/v1",
"low_speed_timeout_in_seconds": 600
} }
}, },
// Zed's Prettier integration settings. // Zed's Prettier integration settings.
@@ -1140,7 +1041,6 @@
"use_system_clipboard": "always", "use_system_clipboard": "always",
"use_multiline_find": false, "use_multiline_find": false,
"use_smartcase_find": false, "use_smartcase_find": false,
"highlight_on_yank_duration": 200,
"custom_digraphs": {} "custom_digraphs": {}
}, },
// The server to connect to. If the environment variable // The server to connect to. If the environment variable
@@ -1198,16 +1098,14 @@
// "W": "workspace::Save" // "W": "workspace::Save"
// } // }
"command_aliases": {}, "command_aliases": {},
// Whether to show user picture in titlebar.
"show_user_picture": true,
// ssh_connections is an array of ssh connections. // ssh_connections is an array of ssh connections.
// By default this setting is null, which disables the direct ssh connection support.
// You can configure these from `project: Open Remote` in the command palette. // You can configure these from `project: Open Remote` in the command palette.
// Zed's ssh support will pull configuration from your ~/.ssh too. // Zed's ssh support will pull configuration from your ~/.ssh too.
// Examples: // Examples:
// [ // [
// { // {
// "host": "example-box", // "host": "example-box",
// // "port": 22, "username": "test", "args": ["-i", "/home/user/.ssh/id_rsa"]
// "projects": [ // "projects": [
// { // {
// "paths": ["/home/user/code/zed"] // "paths": ["/home/user/code/zed"]
@@ -1215,7 +1113,16 @@
// ] // ]
// } // }
// ] // ]
"ssh_connections": [], "ssh_connections": null,
// Configures context servers for use in the Assistant. // Configures the Context Server Protocol binaries
"context_servers": {} //
// Examples:
// {
// "id": "server-1",
// "executable": "/path",
// "args": ['arg1", "args2"]
// }
"experimental.context_servers": {
"servers": []
}
} }

View File

@@ -16,7 +16,6 @@
"allow_concurrent_runs": false, "allow_concurrent_runs": false,
// What to do with the terminal pane and tab, after the command was started: // What to do with the terminal pane and tab, after the command was started:
// * `always` — always show the terminal pane, add and focus the corresponding task's tab in it (default) // * `always` — always show the terminal pane, add and focus the corresponding task's tab in it (default)
// * `no_focus` — always show the terminal pane, add/reuse the task's tab there, but don't focus it
// * `never` — avoid changing current terminal pane focus, but still add/reuse the task's tab there // * `never` — avoid changing current terminal pane focus, but still add/reuse the task's tab there
"reveal": "always", "reveal": "always",
// What to do with the terminal pane and tab, after the command had finished: // What to do with the terminal pane and tab, after the command had finished:

View File

@@ -1,5 +1,5 @@
{ {
"$schema": "https://zed.dev/schema/themes/v0.2.0.json", "$schema": "https://zed.dev/schema/themes/v0.1.0.json",
"name": "Andromeda", "name": "Andromeda",
"author": "Zed Industries", "author": "Zed Industries",
"themes": [ "themes": [
@@ -46,7 +46,7 @@
"tab.active_background": "#1e2025ff", "tab.active_background": "#1e2025ff",
"search.match_background": "#11a79366", "search.match_background": "#11a79366",
"panel.background": "#21242bff", "panel.background": "#21242bff",
"panel.focused_border": "#10a793ff", "panel.focused_border": null,
"pane.focused_border": null, "pane.focused_border": null,
"scrollbar.thumb.background": "#f7f7f84c", "scrollbar.thumb.background": "#f7f7f84c",
"scrollbar.thumb.hover_background": "#252931ff", "scrollbar.thumb.hover_background": "#252931ff",

View File

@@ -1,5 +1,5 @@
{ {
"$schema": "https://zed.dev/schema/themes/v0.2.0.json", "$schema": "https://zed.dev/schema/themes/v0.1.0.json",
"name": "Atelier", "name": "Atelier",
"author": "Zed Industries", "author": "Zed Industries",
"themes": [ "themes": [
@@ -46,7 +46,7 @@
"tab.active_background": "#19171cff", "tab.active_background": "#19171cff",
"search.match_background": "#576dda66", "search.match_background": "#576dda66",
"panel.background": "#221f26ff", "panel.background": "#221f26ff",
"panel.focused_border": "#566ddaff", "panel.focused_border": null,
"pane.focused_border": null, "pane.focused_border": null,
"scrollbar.thumb.background": "#efecf44c", "scrollbar.thumb.background": "#efecf44c",
"scrollbar.thumb.hover_background": "#332f38ff", "scrollbar.thumb.hover_background": "#332f38ff",
@@ -431,7 +431,7 @@
"tab.active_background": "#efecf4ff", "tab.active_background": "#efecf4ff",
"search.match_background": "#586dda66", "search.match_background": "#586dda66",
"panel.background": "#e6e3ebff", "panel.background": "#e6e3ebff",
"panel.focused_border": "#586cdaff", "panel.focused_border": null,
"pane.focused_border": null, "pane.focused_border": null,
"scrollbar.thumb.background": "#19171c4c", "scrollbar.thumb.background": "#19171c4c",
"scrollbar.thumb.hover_background": "#cbc8d1ff", "scrollbar.thumb.hover_background": "#cbc8d1ff",

View File

@@ -1,5 +1,5 @@
{ {
"$schema": "https://zed.dev/schema/themes/v0.2.0.json", "$schema": "https://zed.dev/schema/themes/v0.1.0.json",
"name": "Ayu", "name": "Ayu",
"author": "Zed Industries", "author": "Zed Industries",
"themes": [ "themes": [
@@ -46,7 +46,7 @@
"tab.active_background": "#0d1016ff", "tab.active_background": "#0d1016ff",
"search.match_background": "#5ac2fe66", "search.match_background": "#5ac2fe66",
"panel.background": "#1f2127ff", "panel.background": "#1f2127ff",
"panel.focused_border": "#5ac1feff", "panel.focused_border": null,
"pane.focused_border": null, "pane.focused_border": null,
"scrollbar.thumb.background": "#bfbdb64c", "scrollbar.thumb.background": "#bfbdb64c",
"scrollbar.thumb.hover_background": "#2d2f34ff", "scrollbar.thumb.hover_background": "#2d2f34ff",
@@ -416,7 +416,7 @@
"tab.active_background": "#fcfcfcff", "tab.active_background": "#fcfcfcff",
"search.match_background": "#3b9ee566", "search.match_background": "#3b9ee566",
"panel.background": "#ececedff", "panel.background": "#ececedff",
"panel.focused_border": "#3b9ee5ff", "panel.focused_border": null,
"pane.focused_border": null, "pane.focused_border": null,
"scrollbar.thumb.background": "#5c61664c", "scrollbar.thumb.background": "#5c61664c",
"scrollbar.thumb.hover_background": "#dfe0e1ff", "scrollbar.thumb.hover_background": "#dfe0e1ff",

View File

@@ -1,5 +1,5 @@
{ {
"$schema": "https://zed.dev/schema/themes/v0.2.0.json", "$schema": "https://zed.dev/schema/themes/v0.1.0.json",
"name": "Gruvbox", "name": "Gruvbox",
"author": "Zed Industries", "author": "Zed Industries",
"themes": [ "themes": [
@@ -55,7 +55,7 @@
"tab.active_background": "#282828ff", "tab.active_background": "#282828ff",
"search.match_background": "#83a59866", "search.match_background": "#83a59866",
"panel.background": "#3a3735ff", "panel.background": "#3a3735ff",
"panel.focused_border": "#83a598ff", "panel.focused_border": null,
"pane.focused_border": null, "pane.focused_border": null,
"scrollbar.thumb.background": "#fbf1c74c", "scrollbar.thumb.background": "#fbf1c74c",
"scrollbar.thumb.hover_background": "#494340ff", "scrollbar.thumb.hover_background": "#494340ff",
@@ -439,7 +439,7 @@
"tab.active_background": "#1d2021ff", "tab.active_background": "#1d2021ff",
"search.match_background": "#83a59866", "search.match_background": "#83a59866",
"panel.background": "#393634ff", "panel.background": "#393634ff",
"panel.focused_border": "#83a598ff", "panel.focused_border": null,
"pane.focused_border": null, "pane.focused_border": null,
"scrollbar.thumb.background": "#fbf1c74c", "scrollbar.thumb.background": "#fbf1c74c",
"scrollbar.thumb.hover_background": "#494340ff", "scrollbar.thumb.hover_background": "#494340ff",

View File

@@ -1,5 +1,5 @@
{ {
"$schema": "https://zed.dev/schema/themes/v0.2.0.json", "$schema": "https://zed.dev/schema/themes/v0.1.0.json",
"name": "One", "name": "One",
"author": "Zed Industries", "author": "Zed Industries",
"themes": [ "themes": [
@@ -27,15 +27,15 @@
"ghost_element.active": "#454a56ff", "ghost_element.active": "#454a56ff",
"ghost_element.selected": "#454a56ff", "ghost_element.selected": "#454a56ff",
"ghost_element.disabled": "#2e343eff", "ghost_element.disabled": "#2e343eff",
"text": "#dce0e5ff", "text": "#c8ccd4ff",
"text.muted": "#a9afbcff", "text.muted": "#838994ff",
"text.placeholder": "#878a98ff", "text.placeholder": "#696B77ff",
"text.disabled": "#878a98ff", "text.disabled": "#696B77ff",
"text.accent": "#74ade8ff", "text.accent": "#74ade8ff",
"icon": "#dce0e5ff", "icon": "#c8ccd4ff",
"icon.muted": "#a9afbcff", "icon.muted": "#838994ff",
"icon.disabled": "#878a98ff", "icon.disabled": "#696B77ff",
"icon.placeholder": "#a9afbcff", "icon.placeholder": "#838994ff",
"icon.accent": "#74ade8ff", "icon.accent": "#74ade8ff",
"status_bar.background": "#3b414dff", "status_bar.background": "#3b414dff",
"title_bar.background": "#3b414dff", "title_bar.background": "#3b414dff",
@@ -60,19 +60,19 @@
"editor.active_line.background": "#2f343ebf", "editor.active_line.background": "#2f343ebf",
"editor.highlighted_line.background": "#2f343eff", "editor.highlighted_line.background": "#2f343eff",
"editor.line_number": "#c8ccd459", "editor.line_number": "#c8ccd459",
"editor.active_line_number": "#dce0e5ff", "editor.active_line_number": "#c8ccd4ff",
"editor.invisible": "#878a98ff", "editor.invisible": "#696B77ff",
"editor.wrap_guide": "#c8ccd40d", "editor.wrap_guide": "#c8ccd40d",
"editor.active_wrap_guide": "#c8ccd41a", "editor.active_wrap_guide": "#c8ccd41a",
"editor.document_highlight.read_background": "#74ade81a", "editor.document_highlight.read_background": "#74ade81a",
"editor.document_highlight.write_background": "#555a6366", "editor.document_highlight.write_background": "#555a6366",
"terminal.background": "#282c33ff", "terminal.background": "#282c33ff",
"terminal.foreground": "#dce0e5ff", "terminal.foreground": "#c8ccd4ff",
"terminal.bright_foreground": "#dce0e5ff", "terminal.bright_foreground": "#c8ccd4ff",
"terminal.dim_foreground": "#282c33ff", "terminal.dim_foreground": "#282c33ff",
"terminal.ansi.black": "#282c33ff", "terminal.ansi.black": "#282c33ff",
"terminal.ansi.bright_black": "#525561ff", "terminal.ansi.bright_black": "#525561ff",
"terminal.ansi.dim_black": "#dce0e5ff", "terminal.ansi.dim_black": "#c8ccd4ff",
"terminal.ansi.red": "#d07277ff", "terminal.ansi.red": "#d07277ff",
"terminal.ansi.bright_red": "#673a3cff", "terminal.ansi.bright_red": "#673a3cff",
"terminal.ansi.dim_red": "#eab7b9ff", "terminal.ansi.dim_red": "#eab7b9ff",
@@ -91,8 +91,8 @@
"terminal.ansi.cyan": "#6eb4bfff", "terminal.ansi.cyan": "#6eb4bfff",
"terminal.ansi.bright_cyan": "#3a565bff", "terminal.ansi.bright_cyan": "#3a565bff",
"terminal.ansi.dim_cyan": "#b9d9dfff", "terminal.ansi.dim_cyan": "#b9d9dfff",
"terminal.ansi.white": "#dce0e5ff", "terminal.ansi.white": "#c8ccd4ff",
"terminal.ansi.bright_white": "#dce0e5ff", "terminal.ansi.bright_white": "#c8ccd4ff",
"terminal.ansi.dim_white": "#575d65ff", "terminal.ansi.dim_white": "#575d65ff",
"link_text.hover": "#74ade8ff", "link_text.hover": "#74ade8ff",
"conflict": "#dec184ff", "conflict": "#dec184ff",
@@ -107,14 +107,14 @@
"error": "#d07277ff", "error": "#d07277ff",
"error.background": "#d072771a", "error.background": "#d072771a",
"error.border": "#4c2b2cff", "error.border": "#4c2b2cff",
"hidden": "#878a98ff", "hidden": "#696B77ff",
"hidden.background": "#696b771a", "hidden.background": "#696B771a",
"hidden.border": "#414754ff", "hidden.border": "#414754ff",
"hint": "#788ca6ff", "hint": "#5a6f89ff",
"hint.background": "#5a6f891a", "hint.background": "#5a6f891a",
"hint.border": "#293b5bff", "hint.border": "#293b5bff",
"ignored": "#878a98ff", "ignored": "#696B77ff",
"ignored.background": "#696b771a", "ignored.background": "#696B771a",
"ignored.border": "#464b57ff", "ignored.border": "#464b57ff",
"info": "#74ade8ff", "info": "#74ade8ff",
"info.background": "#74ade81a", "info.background": "#74ade81a",
@@ -131,7 +131,7 @@
"success": "#a1c181ff", "success": "#a1c181ff",
"success.background": "#a1c1811a", "success.background": "#a1c1811a",
"success.border": "#38482fff", "success.border": "#38482fff",
"unreachable": "#a9afbcff", "unreachable": "#838994ff",
"unreachable.background": "#8389941a", "unreachable.background": "#8389941a",
"unreachable.border": "#464b57ff", "unreachable.border": "#464b57ff",
"warning": "#dec184ff", "warning": "#dec184ff",
@@ -211,7 +211,7 @@
"font_weight": null "font_weight": null
}, },
"embedded": { "embedded": {
"color": "#dce0e5ff", "color": "#c8ccd4ff",
"font_style": null, "font_style": null,
"font_weight": null "font_weight": null
}, },
@@ -236,7 +236,7 @@
"font_weight": null "font_weight": null
}, },
"hint": { "hint": {
"color": "#788ca6ff", "color": "#5a6f89ff",
"font_style": null, "font_style": null,
"font_weight": 700 "font_weight": 700
}, },
@@ -276,7 +276,7 @@
"font_weight": null "font_weight": null
}, },
"preproc": { "preproc": {
"color": "#dce0e5ff", "color": "#c8ccd4ff",
"font_style": null, "font_style": null,
"font_weight": null "font_weight": null
}, },
@@ -361,7 +361,7 @@
"font_weight": null "font_weight": null
}, },
"variable": { "variable": {
"color": "#dce0e5ff", "color": "#c8ccd4ff",
"font_style": null, "font_style": null,
"font_weight": null "font_weight": null
}, },
@@ -402,15 +402,15 @@
"ghost_element.active": "#cacacaff", "ghost_element.active": "#cacacaff",
"ghost_element.selected": "#cacacaff", "ghost_element.selected": "#cacacaff",
"ghost_element.disabled": "#ebebecff", "ghost_element.disabled": "#ebebecff",
"text": "#242529ff", "text": "#383a41ff",
"text.muted": "#58585aff", "text.muted": "#7e8087ff",
"text.placeholder": "#7e8086ff", "text.placeholder": "#a1a1a3ff",
"text.disabled": "#7e8086ff", "text.disabled": "#a1a1a3ff",
"text.accent": "#5c78e2ff", "text.accent": "#5c78e2ff",
"icon": "#242529ff", "icon": "#383a41ff",
"icon.muted": "#58585aff", "icon.muted": "#7e8087ff",
"icon.disabled": "#7e8086ff", "icon.disabled": "#a1a1a3ff",
"icon.placeholder": "#58585aff", "icon.placeholder": "#7e8087ff",
"icon.accent": "#5c78e2ff", "icon.accent": "#5c78e2ff",
"status_bar.background": "#dcdcddff", "status_bar.background": "#dcdcddff",
"title_bar.background": "#dcdcddff", "title_bar.background": "#dcdcddff",
@@ -428,26 +428,26 @@
"scrollbar.thumb.border": "#dfdfe0ff", "scrollbar.thumb.border": "#dfdfe0ff",
"scrollbar.track.background": "#00000000", "scrollbar.track.background": "#00000000",
"scrollbar.track.border": "#eeeeeeff", "scrollbar.track.border": "#eeeeeeff",
"editor.foreground": "#242529ff", "editor.foreground": "#383a41ff",
"editor.background": "#fafafaff", "editor.background": "#fafafaff",
"editor.gutter.background": "#fafafaff", "editor.gutter.background": "#fafafaff",
"editor.subheader.background": "#ebebecff", "editor.subheader.background": "#ebebecff",
"editor.active_line.background": "#ebebecbf", "editor.active_line.background": "#ebebecbf",
"editor.highlighted_line.background": "#ebebecff", "editor.highlighted_line.background": "#ebebecff",
"editor.line_number": "#383a4159", "editor.line_number": "#383a4159",
"editor.active_line_number": "#242529ff", "editor.active_line_number": "#383a41ff",
"editor.invisible": "#a3a3a4ff", "editor.invisible": "#a3a3a4ff",
"editor.wrap_guide": "#383a410d", "editor.wrap_guide": "#383a410d",
"editor.active_wrap_guide": "#383a411a", "editor.active_wrap_guide": "#383a411a",
"editor.document_highlight.read_background": "#5c78e21a", "editor.document_highlight.read_background": "#5c78e21a",
"editor.document_highlight.write_background": "#a3a3a466", "editor.document_highlight.write_background": "#a3a3a466",
"terminal.background": "#fafafaff", "terminal.background": "#fafafaff",
"terminal.foreground": "#242529ff", "terminal.foreground": "#383a41ff",
"terminal.bright_foreground": "#242529ff", "terminal.bright_foreground": "#383a41ff",
"terminal.dim_foreground": "#fafafaff", "terminal.dim_foreground": "#fafafaff",
"terminal.ansi.black": "#fafafaff", "terminal.ansi.black": "#fafafaff",
"terminal.ansi.bright_black": "#aaaaaaff", "terminal.ansi.bright_black": "#aaaaaaff",
"terminal.ansi.dim_black": "#242529ff", "terminal.ansi.dim_black": "#383a41ff",
"terminal.ansi.red": "#d36151ff", "terminal.ansi.red": "#d36151ff",
"terminal.ansi.bright_red": "#f0b0a4ff", "terminal.ansi.bright_red": "#f0b0a4ff",
"terminal.ansi.dim_red": "#6f312aff", "terminal.ansi.dim_red": "#6f312aff",
@@ -466,11 +466,11 @@
"terminal.ansi.cyan": "#3a82b7ff", "terminal.ansi.cyan": "#3a82b7ff",
"terminal.ansi.bright_cyan": "#a3bedaff", "terminal.ansi.bright_cyan": "#a3bedaff",
"terminal.ansi.dim_cyan": "#254058ff", "terminal.ansi.dim_cyan": "#254058ff",
"terminal.ansi.white": "#242529ff", "terminal.ansi.white": "#383a41ff",
"terminal.ansi.bright_white": "#242529ff", "terminal.ansi.bright_white": "#383a41ff",
"terminal.ansi.dim_white": "#97979aff", "terminal.ansi.dim_white": "#97979aff",
"link_text.hover": "#5c78e2ff", "link_text.hover": "#5c78e2ff",
"conflict": "#a48819ff", "conflict": "#dec184ff",
"conflict.background": "#faf2e6ff", "conflict.background": "#faf2e6ff",
"conflict.border": "#f4e7d1ff", "conflict.border": "#f4e7d1ff",
"created": "#669f59ff", "created": "#669f59ff",
@@ -482,19 +482,19 @@
"error": "#d36151ff", "error": "#d36151ff",
"error.background": "#fbdfd9ff", "error.background": "#fbdfd9ff",
"error.border": "#f6c6bdff", "error.border": "#f6c6bdff",
"hidden": "#7e8086ff", "hidden": "#a1a1a3ff",
"hidden.background": "#dcdcddff", "hidden.background": "#dcdcddff",
"hidden.border": "#d3d3d4ff", "hidden.border": "#d3d3d4ff",
"hint": "#7274a7ff", "hint": "#9294beff",
"hint.background": "#e2e2faff", "hint.background": "#e2e2faff",
"hint.border": "#cbcdf6ff", "hint.border": "#cbcdf6ff",
"ignored": "#7e8086ff", "ignored": "#a1a1a3ff",
"ignored.background": "#dcdcddff", "ignored.background": "#dcdcddff",
"ignored.border": "#c9c9caff", "ignored.border": "#c9c9caff",
"info": "#5c78e2ff", "info": "#5c78e2ff",
"info.background": "#e2e2faff", "info.background": "#e2e2faff",
"info.border": "#cbcdf6ff", "info.border": "#cbcdf6ff",
"modified": "#a48819ff", "modified": "#a47a23ff",
"modified.background": "#faf2e6ff", "modified.background": "#faf2e6ff",
"modified.border": "#f4e7d1ff", "modified.border": "#f4e7d1ff",
"predictive": "#9b9ec6ff", "predictive": "#9b9ec6ff",
@@ -506,10 +506,10 @@
"success": "#669f59ff", "success": "#669f59ff",
"success.background": "#dfeadbff", "success.background": "#dfeadbff",
"success.border": "#c8dcc1ff", "success.border": "#c8dcc1ff",
"unreachable": "#58585aff", "unreachable": "#7e8087ff",
"unreachable.background": "#dcdcddff", "unreachable.background": "#dcdcddff",
"unreachable.border": "#c9c9caff", "unreachable.border": "#c9c9caff",
"warning": "#a48819ff", "warning": "#dec184ff",
"warning.background": "#faf2e6ff", "warning.background": "#faf2e6ff",
"warning.border": "#f4e7d1ff", "warning.border": "#f4e7d1ff",
"players": [ "players": [
@@ -544,7 +544,7 @@
"selection": "#d361513d" "selection": "#d361513d"
}, },
{ {
"cursor": "#a48819ff", "cursor": "#dec184ff",
"background": "#dec184ff", "background": "#dec184ff",
"selection": "#dec1843d" "selection": "#dec1843d"
}, },
@@ -586,7 +586,7 @@
"font_weight": null "font_weight": null
}, },
"embedded": { "embedded": {
"color": "#242529ff", "color": "#383a41ff",
"font_style": null, "font_style": null,
"font_weight": null "font_weight": null
}, },
@@ -611,7 +611,7 @@
"font_weight": null "font_weight": null
}, },
"hint": { "hint": {
"color": "#7274a7ff", "color": "#9294beff",
"font_style": null, "font_style": null,
"font_weight": 700 "font_weight": 700
}, },
@@ -651,12 +651,12 @@
"font_weight": null "font_weight": null
}, },
"preproc": { "preproc": {
"color": "#242529ff", "color": "#383a41ff",
"font_style": null, "font_style": null,
"font_weight": null "font_weight": null
}, },
"primary": { "primary": {
"color": "#242529ff", "color": "#383a41ff",
"font_style": null, "font_style": null,
"font_weight": null "font_weight": null
}, },
@@ -666,7 +666,7 @@
"font_weight": null "font_weight": null
}, },
"punctuation": { "punctuation": {
"color": "#242529ff", "color": "#383a41ff",
"font_style": null, "font_style": null,
"font_weight": null "font_weight": null
}, },
@@ -736,7 +736,7 @@
"font_weight": null "font_weight": null
}, },
"variable": { "variable": {
"color": "#242529ff", "color": "#383a41ff",
"font_style": null, "font_style": null,
"font_weight": null "font_weight": null
}, },

View File

@@ -1,5 +1,5 @@
{ {
"$schema": "https://zed.dev/schema/themes/v0.2.0.json", "$schema": "https://zed.dev/schema/themes/v0.1.0.json",
"name": "Rosé Pine", "name": "Rosé Pine",
"author": "Zed Industries", "author": "Zed Industries",
"themes": [ "themes": [
@@ -46,7 +46,7 @@
"tab.active_background": "#191724ff", "tab.active_background": "#191724ff",
"search.match_background": "#57949f66", "search.match_background": "#57949f66",
"panel.background": "#1c1b2aff", "panel.background": "#1c1b2aff",
"panel.focused_border": "#9bced6ff", "panel.focused_border": null,
"pane.focused_border": null, "pane.focused_border": null,
"scrollbar.thumb.background": "#e0def44c", "scrollbar.thumb.background": "#e0def44c",
"scrollbar.thumb.hover_background": "#232132ff", "scrollbar.thumb.hover_background": "#232132ff",
@@ -426,7 +426,7 @@
"tab.active_background": "#faf4edff", "tab.active_background": "#faf4edff",
"search.match_background": "#9cced766", "search.match_background": "#9cced766",
"panel.background": "#fef9f2ff", "panel.background": "#fef9f2ff",
"panel.focused_border": "#57949fff", "panel.focused_border": null,
"pane.focused_border": null, "pane.focused_border": null,
"scrollbar.thumb.background": "#5752794c", "scrollbar.thumb.background": "#5752794c",
"scrollbar.thumb.hover_background": "#e5e0dfff", "scrollbar.thumb.hover_background": "#e5e0dfff",
@@ -806,7 +806,7 @@
"tab.active_background": "#232136ff", "tab.active_background": "#232136ff",
"search.match_background": "#9cced766", "search.match_background": "#9cced766",
"panel.background": "#28253cff", "panel.background": "#28253cff",
"panel.focused_border": "#9bced6ff", "panel.focused_border": null,
"pane.focused_border": null, "pane.focused_border": null,
"scrollbar.thumb.background": "#e0def44c", "scrollbar.thumb.background": "#e0def44c",
"scrollbar.thumb.hover_background": "#322f48ff", "scrollbar.thumb.hover_background": "#322f48ff",

View File

@@ -1,5 +1,5 @@
{ {
"$schema": "https://zed.dev/schema/themes/v0.2.0.json", "$schema": "https://zed.dev/schema/themes/v0.1.0.json",
"name": "Sandcastle", "name": "Sandcastle",
"author": "Zed Industries", "author": "Zed Industries",
"themes": [ "themes": [
@@ -46,7 +46,7 @@
"tab.active_background": "#282c33ff", "tab.active_background": "#282c33ff",
"search.match_background": "#528b8b66", "search.match_background": "#528b8b66",
"panel.background": "#2b3038ff", "panel.background": "#2b3038ff",
"panel.focused_border": "#518b8bff", "panel.focused_border": null,
"pane.focused_border": null, "pane.focused_border": null,
"scrollbar.thumb.background": "#fdf4c14c", "scrollbar.thumb.background": "#fdf4c14c",
"scrollbar.thumb.hover_background": "#313741ff", "scrollbar.thumb.hover_background": "#313741ff",

View File

@@ -1,5 +1,5 @@
{ {
"$schema": "https://zed.dev/schema/themes/v0.2.0.json", "$schema": "https://zed.dev/schema/themes/v0.1.0.json",
"name": "Solarized", "name": "Solarized",
"author": "Zed Industries", "author": "Zed Industries",
"themes": [ "themes": [
@@ -46,7 +46,7 @@
"tab.active_background": "#002a35ff", "tab.active_background": "#002a35ff",
"search.match_background": "#288bd166", "search.match_background": "#288bd166",
"panel.background": "#04313bff", "panel.background": "#04313bff",
"panel.focused_border": "#278ad1ff", "panel.focused_border": null,
"pane.focused_border": null, "pane.focused_border": null,
"scrollbar.thumb.background": "#fdf6e34c", "scrollbar.thumb.background": "#fdf6e34c",
"scrollbar.thumb.hover_background": "#053541ff", "scrollbar.thumb.hover_background": "#053541ff",
@@ -416,7 +416,7 @@
"tab.active_background": "#fdf6e3ff", "tab.active_background": "#fdf6e3ff",
"search.match_background": "#298bd166", "search.match_background": "#298bd166",
"panel.background": "#f3eddaff", "panel.background": "#f3eddaff",
"panel.focused_border": "#288bd1ff", "panel.focused_border": null,
"pane.focused_border": null, "pane.focused_border": null,
"scrollbar.thumb.background": "#002a354c", "scrollbar.thumb.background": "#002a354c",
"scrollbar.thumb.hover_background": "#dcdacbff", "scrollbar.thumb.hover_background": "#dcdacbff",
@@ -519,8 +519,8 @@
"selection": "#d337813d" "selection": "#d337813d"
}, },
{ {
"cursor": "#cb4b16ff", "cursor": "#cb4b17ff",
"background": "#cb4b16ff", "background": "#cb4b17ff",
"selection": "#cb4b173d" "selection": "#cb4b173d"
}, },
{ {
@@ -596,7 +596,7 @@
"font_weight": 700 "font_weight": 700
}, },
"enum": { "enum": {
"color": "#cb4b16ff", "color": "#cb4b17ff",
"font_style": null, "font_style": null,
"font_weight": null "font_weight": null
}, },
@@ -621,7 +621,7 @@
"font_weight": null "font_weight": null
}, },
"link_text": { "link_text": {
"color": "#cb4b16ff", "color": "#cb4b17ff",
"font_style": "italic", "font_style": "italic",
"font_weight": null "font_weight": null
}, },
@@ -636,7 +636,7 @@
"font_weight": null "font_weight": null
}, },
"operator": { "operator": {
"color": "#cb4b16ff", "color": "#cb4b17ff",
"font_style": null, "font_style": null,
"font_weight": null "font_weight": null
}, },
@@ -686,7 +686,7 @@
"font_weight": null "font_weight": null
}, },
"string": { "string": {
"color": "#cb4b16ff", "color": "#cb4b17ff",
"font_style": null, "font_style": null,
"font_weight": null "font_weight": null
}, },
@@ -696,17 +696,17 @@
"font_weight": null "font_weight": null
}, },
"string.regex": { "string.regex": {
"color": "#cb4b16ff", "color": "#cb4b17ff",
"font_style": null, "font_style": null,
"font_weight": null "font_weight": null
}, },
"string.special": { "string.special": {
"color": "#cb4b16ff", "color": "#cb4b17ff",
"font_style": null, "font_style": null,
"font_weight": null "font_weight": null
}, },
"string.special.symbol": { "string.special.symbol": {
"color": "#cb4b16ff", "color": "#cb4b17ff",
"font_style": null, "font_style": null,
"font_weight": null "font_weight": null
}, },
@@ -716,7 +716,7 @@
"font_weight": null "font_weight": null
}, },
"text.literal": { "text.literal": {
"color": "#cb4b16ff", "color": "#cb4b17ff",
"font_style": null, "font_style": null,
"font_weight": null "font_weight": null
}, },

View File

@@ -1,5 +1,5 @@
{ {
"$schema": "https://zed.dev/schema/themes/v0.2.0.json", "$schema": "https://zed.dev/schema/themes/v0.1.0.json",
"name": "Summercamp", "name": "Summercamp",
"author": "Zed Industries", "author": "Zed Industries",
"themes": [ "themes": [
@@ -46,7 +46,7 @@
"tab.active_background": "#1b1810ff", "tab.active_background": "#1b1810ff",
"search.match_background": "#499bef66", "search.match_background": "#499bef66",
"panel.background": "#231f16ff", "panel.background": "#231f16ff",
"panel.focused_border": "#499befff", "panel.focused_border": null,
"pane.focused_border": null, "pane.focused_border": null,
"scrollbar.thumb.background": "#f8f5de4c", "scrollbar.thumb.background": "#f8f5de4c",
"scrollbar.thumb.hover_background": "#29251bff", "scrollbar.thumb.hover_background": "#29251bff",

View File

@@ -16,15 +16,13 @@ doctest = false
anyhow.workspace = true anyhow.workspace = true
auto_update.workspace = true auto_update.workspace = true
editor.workspace = true editor.workspace = true
extension_host.workspace = true extension.workspace = true
futures.workspace = true futures.workspace = true
gpui.workspace = true gpui.workspace = true
language.workspace = true language.workspace = true
lsp.workspace = true
project.workspace = true project.workspace = true
smallvec.workspace = true smallvec.workspace = true
ui.workspace = true ui.workspace = true
util.workspace = true
workspace.workspace = true workspace.workspace = true
[dev-dependencies] [dev-dependencies]

View File

@@ -1,19 +1,19 @@
use auto_update::{AutoUpdateStatus, AutoUpdater, DismissErrorMessage}; use auto_update::{AutoUpdateStatus, AutoUpdater, DismissErrorMessage};
use editor::Editor; use editor::Editor;
use extension_host::ExtensionStore; use extension::ExtensionStore;
use futures::StreamExt; use futures::StreamExt;
use gpui::{ use gpui::{
actions, percentage, Animation, AnimationExt as _, AppContext, AppContext, CursorStyle, actions, percentage, Animation, AnimationExt as _, AppContext, CursorStyle, EventEmitter,
EventEmitter, InteractiveElement as _, Model, ParentElement as _, Render, SharedString, InteractiveElement as _, Model, ParentElement as _, Render, SharedString,
StatefulInteractiveElement, Styled, Transformation, View, VisualContext as _, StatefulInteractiveElement, Styled, Transformation, View, ViewContext, VisualContext as _,
};
use language::{
LanguageRegistry, LanguageServerBinaryStatus, LanguageServerId, LanguageServerName,
}; };
use language::{LanguageRegistry, LanguageServerBinaryStatus, LanguageServerId};
use lsp::LanguageServerName;
use project::{EnvironmentErrorMessage, LanguageServerProgress, Project, WorktreeId}; use project::{EnvironmentErrorMessage, LanguageServerProgress, Project, WorktreeId};
use smallvec::SmallVec; use smallvec::SmallVec;
use std::{cmp::Reverse, fmt::Write, sync::Arc, time::Duration}; use std::{cmp::Reverse, fmt::Write, sync::Arc, time::Duration};
use ui::{prelude::*, ButtonLike, ContextMenu, PopoverMenu, PopoverMenuHandle, Tooltip}; use ui::{prelude::*, ButtonLike, ContextMenu, PopoverMenu, PopoverMenuHandle};
use util::truncate_and_trailoff;
use workspace::{item::ItemHandle, StatusItemView, Workspace}; use workspace::{item::ItemHandle, StatusItemView, Workspace};
actions!(activity_indicator, [ShowErrorMessage]); actions!(activity_indicator, [ShowErrorMessage]);
@@ -46,38 +46,34 @@ struct PendingWork<'a> {
struct Content { struct Content {
icon: Option<gpui::AnyElement>, icon: Option<gpui::AnyElement>,
message: String, message: String,
on_click: on_click: Option<Arc<dyn Fn(&mut ActivityIndicator, &mut ViewContext<ActivityIndicator>)>>,
Option<Arc<dyn Fn(&mut ActivityIndicator, &Model<ActivityIndicator>, &mut AppContext)>>,
} }
impl ActivityIndicator { impl ActivityIndicator {
pub fn new( pub fn new(
workspace: &mut Workspace, workspace: &mut Workspace,
languages: Arc<LanguageRegistry>, languages: Arc<LanguageRegistry>,
model: &Model<Workspace>, cx: &mut ViewContext<Workspace>,
cx: &mut AppContext, ) -> View<ActivityIndicator> {
) -> Model<ActivityIndicator> {
let project = workspace.project().clone(); let project = workspace.project().clone();
let auto_updater = AutoUpdater::get(cx); let auto_updater = AutoUpdater::get(cx);
let this = cx.new_model(|model: &Model<Self>, cx: &mut AppContext| { let this = cx.new_view(|cx: &mut ViewContext<Self>| {
let mut status_events = languages.language_server_binary_statuses(); let mut status_events = languages.language_server_binary_statuses();
model cx.spawn(|this, mut cx| async move {
.spawn(cx, |this, mut cx| async move { while let Some((name, status)) = status_events.next().await {
while let Some((name, status)) = status_events.next().await { this.update(&mut cx, |this, cx| {
this.update(&mut cx, |this, model, cx| { this.statuses.retain(|s| s.name != name);
this.statuses.retain(|s| s.name != name); this.statuses.push(LspStatus { name, status });
this.statuses.push(LspStatus { name, status }); cx.notify();
model.notify(cx); })?;
})?; }
} anyhow::Ok(())
anyhow::Ok(()) })
}) .detach();
.detach(); cx.observe(&project, |_, _, cx| cx.notify()).detach();
cx.observe(&project, |_, _, cx| model.notify(cx)).detach();
if let Some(auto_updater) = auto_updater.as_ref() { if let Some(auto_updater) = auto_updater.as_ref() {
cx.observe(auto_updater, |_, _, cx| model.notify(cx)) cx.observe(auto_updater, |_, _, cx| cx.notify()).detach();
.detach();
} }
Self { Self {
@@ -90,8 +86,7 @@ impl ActivityIndicator {
cx.subscribe(&this, move |_, _, event, cx| match event { cx.subscribe(&this, move |_, _, event, cx| match event {
Event::ShowError { lsp_name, error } => { Event::ShowError { lsp_name, error } => {
let create_buffer = let create_buffer = project.update(cx, |project, cx| project.create_buffer(cx));
project.update(cx, |project, model, cx| project.create_buffer(model, cx));
let project = project.clone(); let project = project.clone();
let error = error.clone(); let error = error.clone();
let lsp_name = lsp_name.clone(); let lsp_name = lsp_name.clone();
@@ -110,8 +105,8 @@ impl ActivityIndicator {
})?; })?;
workspace.update(&mut cx, |workspace, cx| { workspace.update(&mut cx, |workspace, cx| {
workspace.add_item_to_active_pane( workspace.add_item_to_active_pane(
Box::new(cx.new_model(|model, cx| { Box::new(cx.new_view(|cx| {
Editor::for_buffer(buffer, Some(project.clone()), model, cx) Editor::for_buffer(buffer, Some(project.clone()), cx)
})), })),
None, None,
true, true,
@@ -128,44 +123,29 @@ impl ActivityIndicator {
this this
} }
fn show_error_message( fn show_error_message(&mut self, _: &ShowErrorMessage, cx: &mut ViewContext<Self>) {
&mut self,
_: &ShowErrorMessage,
model: &Model<Self>,
window: &mut Window,
cx: &mut AppContext,
) {
self.statuses.retain(|status| { self.statuses.retain(|status| {
if let LanguageServerBinaryStatus::Failed { error } = &status.status { if let LanguageServerBinaryStatus::Failed { error } = &status.status {
model.emit( cx.emit(Event::ShowError {
cx, lsp_name: status.name.clone(),
Event::ShowError { error: error.clone(),
lsp_name: status.name.clone(), });
error: error.clone(),
},
);
false false
} else { } else {
true true
} }
}); });
model.notify(cx); cx.notify();
} }
fn dismiss_error_message( fn dismiss_error_message(&mut self, _: &DismissErrorMessage, cx: &mut ViewContext<Self>) {
&mut self,
_: &DismissErrorMessage,
model: &Model<Self>,
window: &mut Window,
cx: &mut AppContext,
) {
if let Some(updater) = &self.auto_updater { if let Some(updater) = &self.auto_updater {
updater.update(cx, |updater, model, cx| { updater.update(cx, |updater, cx| {
updater.dismiss_error(model, cx); updater.dismiss_error(cx);
}); });
} }
model.notify(cx); cx.notify();
} }
fn pending_language_server_work<'a>( fn pending_language_server_work<'a>(
@@ -203,7 +183,7 @@ impl ActivityIndicator {
self.project.read(cx).shell_environment_errors(cx) self.project.read(cx).shell_environment_errors(cx)
} }
fn content_to_render(&mut self, model: &Model<Self>, cx: &mut AppContext) -> Option<Content> { fn content_to_render(&mut self, cx: &mut ViewContext<Self>) -> Option<Content> {
// Show if any direnv calls failed // Show if any direnv calls failed
if let Some((&worktree_id, error)) = self.pending_environment_errors(cx).next() { if let Some((&worktree_id, error)) = self.pending_environment_errors(cx).next() {
return Some(Content { return Some(Content {
@@ -214,7 +194,7 @@ impl ActivityIndicator {
), ),
message: error.0.clone(), message: error.0.clone(),
on_click: Some(Arc::new(move |this, cx| { on_click: Some(Arc::new(move |this, cx| {
this.project.update(cx, |project, model, cx| { this.project.update(cx, |project, cx| {
project.remove_environment_error(cx, worktree_id); project.remove_environment_error(cx, worktree_id);
}); });
cx.dispatch_action(Box::new(workspace::OpenLog)); cx.dispatch_action(Box::new(workspace::OpenLog));
@@ -371,10 +351,7 @@ impl ActivityIndicator {
.into_any_element(), .into_any_element(),
), ),
message: format!("Formatting failed: {}. Click to see logs.", failure), message: format!("Formatting failed: {}. Click to see logs.", failure),
on_click: Some(Arc::new(|indicator, cx| { on_click: Some(Arc::new(|_, cx| {
indicator.project.update(cx, |project, model, cx| {
project.reset_last_formatting_failure(cx);
});
cx.dispatch_action(Box::new(workspace::OpenLog)); cx.dispatch_action(Box::new(workspace::OpenLog));
})), })),
}); });
@@ -462,35 +439,23 @@ impl ActivityIndicator {
None None
} }
fn toggle_language_server_work_context_menu( fn toggle_language_server_work_context_menu(&mut self, cx: &mut ViewContext<Self>) {
&mut self, self.context_menu_handle.toggle(cx);
model: &Model<Self>,
cx: &mut AppContext,
) {
self.context_menu_handle.toggle(model, cx);
} }
} }
impl EventEmitter<Event> for ActivityIndicator {} impl EventEmitter<Event> for ActivityIndicator {}
const MAX_MESSAGE_LEN: usize = 50;
impl Render for ActivityIndicator { impl Render for ActivityIndicator {
fn render( fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
&mut self,
model: &Model<Self>,
window: &mut gpui::Window,
cx: &mut AppContext,
) -> impl IntoElement {
let result = h_flex() let result = h_flex()
.id("activity-indicator") .id("activity-indicator")
.on_action(model.listener(Self::show_error_message)) .on_action(cx.listener(Self::show_error_message))
.on_action(model.listener(Self::dismiss_error_message)); .on_action(cx.listener(Self::dismiss_error_message));
let Some(content) = self.content_to_render(model, cx) else { let Some(content) = self.content_to_render(cx) else {
return result; return result;
}; };
let this = model.downgrade(); let this = cx.view().downgrade();
let truncate_content = content.message.len() > MAX_MESSAGE_LEN;
result.gap_2().child( result.gap_2().child(
PopoverMenu::new("activity-indicator-popover") PopoverMenu::new("activity-indicator-popover")
.trigger( .trigger(
@@ -499,25 +464,9 @@ impl Render for ActivityIndicator {
.id("activity-indicator-status") .id("activity-indicator-status")
.gap_2() .gap_2()
.children(content.icon) .children(content.icon)
.map(|button| { .child(Label::new(content.message).size(LabelSize::Small))
if truncate_content {
button
.child(
Label::new(truncate_and_trailoff(
&content.message,
MAX_MESSAGE_LEN,
))
.size(LabelSize::Small),
)
.tooltip(move |window, cx| {
Tooltip::text(&content.message, cx)
})
} else {
button.child(Label::new(content.message).size(LabelSize::Small))
}
})
.when_some(content.on_click, |this, handler| { .when_some(content.on_click, |this, handler| {
this.on_click(model.listener(move |this, _, model, window, cx| { this.on_click(cx.listener(move |this, _, cx| {
handler(this, cx); handler(this, cx);
})) }))
.cursor(CursorStyle::PointingHand) .cursor(CursorStyle::PointingHand)
@@ -525,10 +474,10 @@ impl Render for ActivityIndicator {
), ),
) )
.anchor(gpui::AnchorCorner::BottomLeft) .anchor(gpui::AnchorCorner::BottomLeft)
.menu(move |window, cx| { .menu(move |cx| {
let strong_this = this.upgrade()?; let strong_this = this.upgrade()?;
let mut has_work = false; let mut has_work = false;
let menu = ContextMenu::build(window, cx, |mut menu, model, window, cx| { let menu = ContextMenu::build(cx, |mut menu, cx| {
for work in strong_this.read(cx).pending_language_server_work(cx) { for work in strong_this.read(cx).pending_language_server_work(cx) {
has_work = true; has_work = true;
let this = this.clone(); let this = this.clone();
@@ -553,17 +502,16 @@ impl Render for ActivityIndicator {
.into_any_element() .into_any_element()
}, },
move |cx| { move |cx| {
this.update(cx, |this, model, cx| { this.update(cx, |this, cx| {
this.project.update(cx, |project, model, cx| { this.project.update(cx, |project, cx| {
project.cancel_language_server_work( project.cancel_language_server_work(
language_server_id, language_server_id,
Some(token.clone()), Some(token.clone()),
model,
cx, cx,
); );
}); });
this.context_menu_handle.hide(cx); this.context_menu_handle.hide(cx);
model.notify(cx); cx.notify();
}) })
.ok(); .ok();
}, },
@@ -586,11 +534,5 @@ impl Render for ActivityIndicator {
} }
impl StatusItemView for ActivityIndicator { impl StatusItemView for ActivityIndicator {
fn set_active_pane_item( fn set_active_pane_item(&mut self, _: Option<&dyn ItemHandle>, _: &mut ViewContext<Self>) {}
&mut self,
_: Option<&dyn ItemHandle>,
_: &Model<Self>,
_: &mut AppContext,
) {
}
} }

View File

@@ -1,12 +1,13 @@
mod supported_countries; mod supported_countries;
use std::time::Duration;
use std::{pin::Pin, str::FromStr}; use std::{pin::Pin, str::FromStr};
use anyhow::{anyhow, Context, Result}; use anyhow::{anyhow, Context, Result};
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use futures::{io::BufReader, stream::BoxStream, AsyncBufReadExt, AsyncReadExt, Stream, StreamExt}; use futures::{io::BufReader, stream::BoxStream, AsyncBufReadExt, AsyncReadExt, Stream, StreamExt};
use http_client::http::{HeaderMap, HeaderValue}; use http_client::http::{HeaderMap, HeaderValue};
use http_client::{AsyncBody, HttpClient, Method, Request as HttpRequest}; use http_client::{AsyncBody, HttpClient, HttpRequestExt, Method, Request as HttpRequest};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use strum::{EnumIter, EnumString}; use strum::{EnumIter, EnumString};
use thiserror::Error; use thiserror::Error;
@@ -28,13 +29,13 @@ pub struct AnthropicModelCacheConfiguration {
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, EnumIter)] #[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, EnumIter)]
pub enum Model { pub enum Model {
#[default] #[default]
#[serde(rename = "claude-3-5-sonnet", alias = "claude-3-5-sonnet-latest")] #[serde(rename = "claude-3-5-sonnet", alias = "claude-3-5-sonnet-20240620")]
Claude3_5Sonnet, Claude3_5Sonnet,
#[serde(rename = "claude-3-opus", alias = "claude-3-opus-latest")] #[serde(rename = "claude-3-opus", alias = "claude-3-opus-20240229")]
Claude3Opus, Claude3Opus,
#[serde(rename = "claude-3-sonnet", alias = "claude-3-sonnet-latest")] #[serde(rename = "claude-3-sonnet", alias = "claude-3-sonnet-20240229")]
Claude3Sonnet, Claude3Sonnet,
#[serde(rename = "claude-3-haiku", alias = "claude-3-haiku-latest")] #[serde(rename = "claude-3-haiku", alias = "claude-3-haiku-20240307")]
Claude3Haiku, Claude3Haiku,
#[serde(rename = "custom")] #[serde(rename = "custom")]
Custom { Custom {
@@ -68,10 +69,10 @@ impl Model {
pub fn id(&self) -> &str { pub fn id(&self) -> &str {
match self { match self {
Model::Claude3_5Sonnet => "claude-3-5-sonnet-latest", Model::Claude3_5Sonnet => "claude-3-5-sonnet-20240620",
Model::Claude3Opus => "claude-3-opus-latest", Model::Claude3Opus => "claude-3-opus-20240229",
Model::Claude3Sonnet => "claude-3-sonnet-latest", Model::Claude3Sonnet => "claude-3-sonnet-20240229",
Model::Claude3Haiku => "claude-3-haiku-latest", Model::Claude3Haiku => "claude-3-haiku-20240307",
Self::Custom { name, .. } => name, Self::Custom { name, .. } => name,
} }
} }
@@ -160,7 +161,10 @@ pub async fn complete(
.method(Method::POST) .method(Method::POST)
.uri(uri) .uri(uri)
.header("Anthropic-Version", "2023-06-01") .header("Anthropic-Version", "2023-06-01")
.header("Anthropic-Beta", "prompt-caching-2024-07-31") .header(
"Anthropic-Beta",
"tools-2024-04-04,prompt-caching-2024-07-31,max-tokens-3-5-sonnet-2024-07-15",
)
.header("X-Api-Key", api_key) .header("X-Api-Key", api_key)
.header("Content-Type", "application/json"); .header("Content-Type", "application/json");
@@ -206,8 +210,9 @@ pub async fn stream_completion(
api_url: &str, api_url: &str,
api_key: &str, api_key: &str,
request: Request, request: Request,
low_speed_timeout: Option<Duration>,
) -> Result<BoxStream<'static, Result<Event, AnthropicError>>, AnthropicError> { ) -> Result<BoxStream<'static, Result<Event, AnthropicError>>, AnthropicError> {
stream_completion_with_rate_limit_info(client, api_url, api_key, request) stream_completion_with_rate_limit_info(client, api_url, api_key, request, low_speed_timeout)
.await .await
.map(|output| output.0) .map(|output| output.0)
} }
@@ -259,6 +264,7 @@ pub async fn stream_completion_with_rate_limit_info(
api_url: &str, api_url: &str,
api_key: &str, api_key: &str,
request: Request, request: Request,
low_speed_timeout: Option<Duration>,
) -> Result< ) -> Result<
( (
BoxStream<'static, Result<Event, AnthropicError>>, BoxStream<'static, Result<Event, AnthropicError>>,
@@ -271,7 +277,7 @@ pub async fn stream_completion_with_rate_limit_info(
stream: true, stream: true,
}; };
let uri = format!("{api_url}/v1/messages"); let uri = format!("{api_url}/v1/messages");
let request_builder = HttpRequest::builder() let mut request_builder = HttpRequest::builder()
.method(Method::POST) .method(Method::POST)
.uri(uri) .uri(uri)
.header("Anthropic-Version", "2023-06-01") .header("Anthropic-Version", "2023-06-01")
@@ -281,6 +287,9 @@ pub async fn stream_completion_with_rate_limit_info(
) )
.header("X-Api-Key", api_key) .header("X-Api-Key", api_key)
.header("Content-Type", "application/json"); .header("Content-Type", "application/json");
if let Some(low_speed_timeout) = low_speed_timeout {
request_builder = request_builder.read_timeout(low_speed_timeout);
}
let serialized_request = let serialized_request =
serde_json::to_string(&request).context("failed to serialize request")?; serde_json::to_string(&request).context("failed to serialize request")?;
let request = request_builder let request = request_builder

View File

@@ -33,7 +33,7 @@ client.workspace = true
clock.workspace = true clock.workspace = true
collections.workspace = true collections.workspace = true
command_palette_hooks.workspace = true command_palette_hooks.workspace = true
context_server.workspace = true context_servers.workspace = true
db.workspace = true db.workspace = true
editor.workspace = true editor.workspace = true
feature_flags.workspace = true feature_flags.workspace = true
@@ -50,8 +50,6 @@ indexed_docs.workspace = true
indoc.workspace = true indoc.workspace = true
language.workspace = true language.workspace = true
language_model.workspace = true language_model.workspace = true
language_model_selector.workspace = true
language_models.workspace = true
log.workspace = true log.workspace = true
lsp.workspace = true lsp.workspace = true
markdown.workspace = true markdown.workspace = true

View File

@@ -5,58 +5,60 @@ pub mod assistant_settings;
mod context; mod context;
pub mod context_store; pub mod context_store;
mod inline_assistant; mod inline_assistant;
mod model_selector;
mod patch; mod patch;
mod prompt_library; mod prompt_library;
mod prompts; mod prompts;
mod slash_command; mod slash_command;
pub(crate) mod slash_command_picker; pub(crate) mod slash_command_picker;
pub mod slash_command_settings; pub mod slash_command_settings;
mod slash_command_working_set;
mod streaming_diff; mod streaming_diff;
mod terminal_inline_assistant; mod terminal_inline_assistant;
mod tools;
use crate::slash_command::project_command::ProjectSlashCommandFeatureFlag;
pub use crate::slash_command_working_set::{SlashCommandId, SlashCommandWorkingSet};
pub use assistant_panel::{AssistantPanel, AssistantPanelEvent}; pub use assistant_panel::{AssistantPanel, AssistantPanelEvent};
use assistant_settings::AssistantSettings; use assistant_settings::AssistantSettings;
use assistant_slash_command::SlashCommandRegistry; use assistant_slash_command::SlashCommandRegistry;
use assistant_tool::ToolRegistry;
use client::{proto, Client}; use client::{proto, Client};
use command_palette_hooks::CommandPaletteFilter; use command_palette_hooks::CommandPaletteFilter;
pub use context::*; pub use context::*;
use context_servers::ContextServerRegistry;
pub use context_store::*; pub use context_store::*;
use feature_flags::FeatureFlagAppExt; use feature_flags::FeatureFlagAppExt;
use fs::Fs; use fs::Fs;
use gpui::impl_actions;
use gpui::{actions, AppContext, Global, SharedString, UpdateGlobal}; use gpui::{actions, AppContext, Global, SharedString, UpdateGlobal};
use gpui::{impl_actions, Context as _};
use indexed_docs::IndexedDocsRegistry;
pub(crate) use inline_assistant::*; pub(crate) use inline_assistant::*;
use language_model::{ use language_model::{
LanguageModelId, LanguageModelProviderId, LanguageModelRegistry, LanguageModelResponseMessage, LanguageModelId, LanguageModelProviderId, LanguageModelRegistry, LanguageModelResponseMessage,
}; };
pub(crate) use model_selector::*;
pub use patch::*; pub use patch::*;
pub use prompts::PromptBuilder; pub use prompts::PromptBuilder;
use prompts::PromptLoadingParams; use prompts::PromptLoadingParams;
use semantic_index::{CloudEmbeddingProvider, SemanticDb}; use semantic_index::{CloudEmbeddingProvider, SemanticDb};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use settings::{update_settings_file, Settings, SettingsStore}; use settings::{update_settings_file, Settings, SettingsStore};
use slash_command::search_command::SearchSlashCommandFeatureFlag; use slash_command::workflow_command::WorkflowSlashCommand;
use slash_command::{ use slash_command::{
auto_command, cargo_workspace_command, default_command, delta_command, diagnostics_command, auto_command, cargo_workspace_command, context_server_command, default_command, delta_command,
docs_command, fetch_command, file_command, now_command, project_command, prompt_command, diagnostics_command, docs_command, fetch_command, file_command, now_command, project_command,
search_command, selection_command, symbols_command, tab_command, terminal_command, prompt_command, search_command, symbols_command, tab_command, terminal_command,
workflow_command,
}; };
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::Arc; use std::sync::Arc;
pub(crate) use streaming_diff::*; pub(crate) use streaming_diff::*;
use util::ResultExt; use util::ResultExt;
use crate::slash_command::streaming_example_command;
use crate::slash_command_settings::SlashCommandSettings; use crate::slash_command_settings::SlashCommandSettings;
actions!( actions!(
assistant, assistant,
[ [
Assist, Assist,
Edit,
Split, Split,
CopyCode, CopyCode,
CycleMessageRole, CycleMessageRole,
@@ -212,17 +214,6 @@ pub fn init(
cx.spawn(|mut cx| { cx.spawn(|mut cx| {
let client = client.clone(); let client = client.clone();
async move { async move {
let is_search_slash_command_enabled = cx
.update(|cx| cx.wait_for_flag::<SearchSlashCommandFeatureFlag>())?
.await;
let is_project_slash_command_enabled = cx
.update(|cx| cx.wait_for_flag::<ProjectSlashCommandFeatureFlag>())?
.await;
if !is_search_slash_command_enabled && !is_project_slash_command_enabled {
return Ok(());
}
let embedding_provider = CloudEmbeddingProvider::new(client.clone()); let embedding_provider = CloudEmbeddingProvider::new(client.clone());
let semantic_index = SemanticDb::new( let semantic_index = SemanticDb::new(
paths::embeddings_dir().join("semantic-index-db.0.mdb"), paths::embeddings_dir().join("semantic-index-db.0.mdb"),
@@ -242,7 +233,7 @@ pub fn init(
assistant_slash_command::init(cx); assistant_slash_command::init(cx);
assistant_tool::init(cx); assistant_tool::init(cx);
assistant_panel::init(cx); assistant_panel::init(cx);
context_server::init(cx); context_servers::init(cx);
let prompt_builder = prompts::PromptBuilder::new(Some(PromptLoadingParams { let prompt_builder = prompts::PromptBuilder::new(Some(PromptLoadingParams {
fs: fs.clone(), fs: fs.clone(),
@@ -255,6 +246,7 @@ pub fn init(
.map(Arc::new) .map(Arc::new)
.unwrap_or_else(|| Arc::new(prompts::PromptBuilder::new(None).unwrap())); .unwrap_or_else(|| Arc::new(prompts::PromptBuilder::new(None).unwrap()));
register_slash_commands(Some(prompt_builder.clone()), cx); register_slash_commands(Some(prompt_builder.clone()), cx);
register_tools(cx);
inline_assistant::init( inline_assistant::init(
fs.clone(), fs.clone(),
prompt_builder.clone(), prompt_builder.clone(),
@@ -267,7 +259,7 @@ pub fn init(
client.telemetry().clone(), client.telemetry().clone(),
cx, cx,
); );
indexed_docs::init(cx); IndexedDocsRegistry::init_global(cx);
CommandPaletteFilter::update_global(cx, |filter, _cx| { CommandPaletteFilter::update_global(cx, |filter, _cx| {
filter.hide_namespace(Assistant::NAMESPACE); filter.hide_namespace(Assistant::NAMESPACE);
@@ -285,9 +277,69 @@ pub fn init(
}) })
.detach(); .detach();
register_context_server_handlers(cx);
prompt_builder prompt_builder
} }
fn register_context_server_handlers(cx: &mut AppContext) {
cx.subscribe(
&context_servers::manager::ContextServerManager::global(cx),
|manager, event, cx| match event {
context_servers::manager::Event::ServerStarted { server_id } => {
cx.update_model(
&manager,
|manager: &mut context_servers::manager::ContextServerManager, cx| {
let slash_command_registry = SlashCommandRegistry::global(cx);
let context_server_registry = ContextServerRegistry::global(cx);
if let Some(server) = manager.get_server(server_id) {
cx.spawn(|_, _| async move {
let Some(protocol) = server.client.read().clone() else {
return;
};
if let Some(prompts) = protocol.list_prompts().await.log_err() {
for prompt in prompts
.into_iter()
.filter(context_server_command::acceptable_prompt)
{
log::info!(
"registering context server command: {:?}",
prompt.name
);
context_server_registry.register_command(
server.id.clone(),
prompt.name.as_str(),
);
slash_command_registry.register_command(
context_server_command::ContextServerSlashCommand::new(
&server, prompt,
),
true,
);
}
}
})
.detach();
}
},
);
}
context_servers::manager::Event::ServerStopped { server_id } => {
let slash_command_registry = SlashCommandRegistry::global(cx);
let context_server_registry = ContextServerRegistry::global(cx);
if let Some(commands) = context_server_registry.get_commands(server_id) {
for command_name in commands {
slash_command_registry.unregister_command_by_name(&command_name);
context_server_registry.unregister_command(&server_id, &command_name);
}
}
}
},
)
.detach();
}
fn init_language_model_settings(cx: &mut AppContext) { fn init_language_model_settings(cx: &mut AppContext) {
update_active_language_model_from_settings(cx); update_active_language_model_from_settings(cx);
@@ -321,9 +373,9 @@ fn update_active_language_model_from_settings(cx: &mut AppContext) {
) )
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
LanguageModelRegistry::global(cx).update(cx, |registry, model, cx| { LanguageModelRegistry::global(cx).update(cx, |registry, cx| {
registry.select_active_model(&provider_name, &model_id, model, cx); registry.select_active_model(&provider_name, &model_id, cx);
registry.select_inline_alternative_models(inline_alternatives, model, cx); registry.select_inline_alternative_models(inline_alternatives, cx);
}); });
} }
@@ -337,14 +389,30 @@ fn register_slash_commands(prompt_builder: Option<Arc<PromptBuilder>>, cx: &mut
slash_command_registry slash_command_registry
.register_command(cargo_workspace_command::CargoWorkspaceSlashCommand, true); .register_command(cargo_workspace_command::CargoWorkspaceSlashCommand, true);
slash_command_registry.register_command(prompt_command::PromptSlashCommand, true); slash_command_registry.register_command(prompt_command::PromptSlashCommand, true);
slash_command_registry.register_command(selection_command::SelectionCommand, true);
slash_command_registry.register_command(default_command::DefaultSlashCommand, false); slash_command_registry.register_command(default_command::DefaultSlashCommand, false);
slash_command_registry.register_command(terminal_command::TerminalSlashCommand, true); slash_command_registry.register_command(terminal_command::TerminalSlashCommand, true);
slash_command_registry.register_command(now_command::NowSlashCommand, false); slash_command_registry.register_command(now_command::NowSlashCommand, false);
slash_command_registry.register_command(diagnostics_command::DiagnosticsSlashCommand, true); slash_command_registry.register_command(diagnostics_command::DiagnosticsSlashCommand, true);
slash_command_registry.register_command(fetch_command::FetchSlashCommand, true); slash_command_registry.register_command(fetch_command::FetchSlashCommand, false);
slash_command_registry.register_command(fetch_command::FetchSlashCommand, false);
if let Some(prompt_builder) = prompt_builder { if let Some(prompt_builder) = prompt_builder {
cx.observe_global::<SettingsStore>({
let slash_command_registry = slash_command_registry.clone();
let prompt_builder = prompt_builder.clone();
move |cx| {
if AssistantSettings::get_global(cx).are_live_diffs_enabled(cx) {
slash_command_registry.register_command(
workflow_command::WorkflowSlashCommand::new(prompt_builder.clone()),
true,
);
} else {
slash_command_registry.unregister_command_by_name(WorkflowSlashCommand::NAME);
}
}
})
.detach();
cx.observe_flag::<project_command::ProjectSlashCommandFeatureFlag, _>({ cx.observe_flag::<project_command::ProjectSlashCommandFeatureFlag, _>({
let slash_command_registry = slash_command_registry.clone(); let slash_command_registry = slash_command_registry.clone();
move |is_enabled, _cx| { move |is_enabled, _cx| {
@@ -370,19 +438,6 @@ fn register_slash_commands(prompt_builder: Option<Arc<PromptBuilder>>, cx: &mut
}) })
.detach(); .detach();
cx.observe_flag::<streaming_example_command::StreamingExampleSlashCommandFeatureFlag, _>({
let slash_command_registry = slash_command_registry.clone();
move |is_enabled, _cx| {
if is_enabled {
slash_command_registry.register_command(
streaming_example_command::StreamingExampleSlashCommand,
false,
);
}
}
})
.detach();
update_slash_commands_from_settings(cx); update_slash_commands_from_settings(cx);
cx.observe_global::<SettingsStore>(update_slash_commands_from_settings) cx.observe_global::<SettingsStore>(update_slash_commands_from_settings)
.detach(); .detach();
@@ -417,6 +472,11 @@ fn update_slash_commands_from_settings(cx: &mut AppContext) {
} }
} }
fn register_tools(cx: &mut AppContext) {
let tool_registry = ToolRegistry::global(cx);
tool_registry.register_tool(tools::now_tool::NowTool);
}
pub fn humanize_token_count(count: usize) -> String { pub fn humanize_token_count(count: usize) -> String {
match count { match count {
0..=999 => count.to_string(), 0..=999 => count.to_string(),

File diff suppressed because it is too large Load Diff

View File

@@ -5,12 +5,13 @@ use anthropic::Model as AnthropicModel;
use feature_flags::FeatureFlagAppExt; use feature_flags::FeatureFlagAppExt;
use fs::Fs; use fs::Fs;
use gpui::{AppContext, Pixels}; use gpui::{AppContext, Pixels};
use language_model::{CloudModel, LanguageModel}; use language_model::provider::open_ai;
use language_models::{ use language_model::settings::{
provider::open_ai, AllLanguageModelSettings, AnthropicSettingsContent, AnthropicSettingsContent, AnthropicSettingsContentV1, OllamaSettingsContent,
AnthropicSettingsContentV1, OllamaSettingsContent, OpenAiSettingsContent, OpenAiSettingsContent, OpenAiSettingsContentV1, VersionedAnthropicSettingsContent,
OpenAiSettingsContentV1, VersionedAnthropicSettingsContent, VersionedOpenAiSettingsContent, VersionedOpenAiSettingsContent,
}; };
use language_model::{settings::AllLanguageModelSettings, CloudModel, LanguageModel};
use ollama::Model as OllamaModel; use ollama::Model as OllamaModel;
use schemars::{schema::Schema, JsonSchema}; use schemars::{schema::Schema, JsonSchema};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -34,17 +35,20 @@ pub enum AssistantProviderContentV1 {
OpenAi { OpenAi {
default_model: Option<OpenAiModel>, default_model: Option<OpenAiModel>,
api_url: Option<String>, api_url: Option<String>,
low_speed_timeout_in_seconds: Option<u64>,
available_models: Option<Vec<OpenAiModel>>, available_models: Option<Vec<OpenAiModel>>,
}, },
#[serde(rename = "anthropic")] #[serde(rename = "anthropic")]
Anthropic { Anthropic {
default_model: Option<AnthropicModel>, default_model: Option<AnthropicModel>,
api_url: Option<String>, api_url: Option<String>,
low_speed_timeout_in_seconds: Option<u64>,
}, },
#[serde(rename = "ollama")] #[serde(rename = "ollama")]
Ollama { Ollama {
default_model: Option<OllamaModel>, default_model: Option<OllamaModel>,
api_url: Option<String>, api_url: Option<String>,
low_speed_timeout_in_seconds: Option<u64>,
}, },
} }
@@ -111,41 +115,47 @@ impl AssistantSettingsContent {
if let VersionedAssistantSettingsContent::V1(settings) = settings { if let VersionedAssistantSettingsContent::V1(settings) = settings {
if let Some(provider) = settings.provider.clone() { if let Some(provider) = settings.provider.clone() {
match provider { match provider {
AssistantProviderContentV1::Anthropic { api_url, .. } => { AssistantProviderContentV1::Anthropic {
update_settings_file::<AllLanguageModelSettings>( api_url,
fs, low_speed_timeout_in_seconds,
cx, ..
move |content, _| { } => update_settings_file::<AllLanguageModelSettings>(
if content.anthropic.is_none() { fs,
content.anthropic = cx,
Some(AnthropicSettingsContent::Versioned( move |content, _| {
VersionedAnthropicSettingsContent::V1( if content.anthropic.is_none() {
AnthropicSettingsContentV1 { content.anthropic = Some(AnthropicSettingsContent::Versioned(
api_url, VersionedAnthropicSettingsContent::V1(
available_models: None, AnthropicSettingsContentV1 {
}, api_url,
), low_speed_timeout_in_seconds,
)); available_models: None,
} },
}, ),
) ));
} }
AssistantProviderContentV1::Ollama { api_url, .. } => { },
update_settings_file::<AllLanguageModelSettings>( ),
fs, AssistantProviderContentV1::Ollama {
cx, api_url,
move |content, _| { low_speed_timeout_in_seconds,
if content.ollama.is_none() { ..
content.ollama = Some(OllamaSettingsContent { } => update_settings_file::<AllLanguageModelSettings>(
api_url, fs,
available_models: None, cx,
}); move |content, _| {
} if content.ollama.is_none() {
}, content.ollama = Some(OllamaSettingsContent {
) api_url,
} low_speed_timeout_in_seconds,
available_models: None,
});
}
},
),
AssistantProviderContentV1::OpenAi { AssistantProviderContentV1::OpenAi {
api_url, api_url,
low_speed_timeout_in_seconds,
available_models, available_models,
.. ..
} => update_settings_file::<AllLanguageModelSettings>( } => update_settings_file::<AllLanguageModelSettings>(
@@ -178,6 +188,7 @@ impl AssistantSettingsContent {
VersionedOpenAiSettingsContent::V1( VersionedOpenAiSettingsContent::V1(
OpenAiSettingsContentV1 { OpenAiSettingsContentV1 {
api_url, api_url,
low_speed_timeout_in_seconds,
available_models, available_models,
}, },
), ),
@@ -287,41 +298,54 @@ impl AssistantSettingsContent {
log::warn!("attempted to set zed.dev model on outdated settings"); log::warn!("attempted to set zed.dev model on outdated settings");
} }
"anthropic" => { "anthropic" => {
let api_url = match &settings.provider { let (api_url, low_speed_timeout_in_seconds) = match &settings.provider {
Some(AssistantProviderContentV1::Anthropic { api_url, .. }) => { Some(AssistantProviderContentV1::Anthropic {
api_url.clone() api_url,
} low_speed_timeout_in_seconds,
_ => None, ..
}) => (api_url.clone(), *low_speed_timeout_in_seconds),
_ => (None, None),
}; };
settings.provider = Some(AssistantProviderContentV1::Anthropic { settings.provider = Some(AssistantProviderContentV1::Anthropic {
default_model: AnthropicModel::from_id(&model).ok(), default_model: AnthropicModel::from_id(&model).ok(),
api_url, api_url,
low_speed_timeout_in_seconds,
}); });
} }
"ollama" => { "ollama" => {
let api_url = match &settings.provider { let (api_url, low_speed_timeout_in_seconds) = match &settings.provider {
Some(AssistantProviderContentV1::Ollama { api_url, .. }) => { Some(AssistantProviderContentV1::Ollama {
api_url.clone() api_url,
} low_speed_timeout_in_seconds,
_ => None, ..
}) => (api_url.clone(), *low_speed_timeout_in_seconds),
_ => (None, None),
}; };
settings.provider = Some(AssistantProviderContentV1::Ollama { settings.provider = Some(AssistantProviderContentV1::Ollama {
default_model: Some(ollama::Model::new(&model, None, None)), default_model: Some(ollama::Model::new(&model, None, None)),
api_url, api_url,
low_speed_timeout_in_seconds,
}); });
} }
"openai" => { "openai" => {
let (api_url, available_models) = match &settings.provider { let (api_url, low_speed_timeout_in_seconds, available_models) =
Some(AssistantProviderContentV1::OpenAi { match &settings.provider {
api_url, Some(AssistantProviderContentV1::OpenAi {
available_models, api_url,
.. low_speed_timeout_in_seconds,
}) => (api_url.clone(), available_models.clone()), available_models,
_ => (None, None), ..
}; }) => (
api_url.clone(),
*low_speed_timeout_in_seconds,
available_models.clone(),
),
_ => (None, None, None),
};
settings.provider = Some(AssistantProviderContentV1::OpenAi { settings.provider = Some(AssistantProviderContentV1::OpenAi {
default_model: OpenAiModel::from_id(&model).ok(), default_model: OpenAiModel::from_id(&model).ok(),
api_url, api_url,
low_speed_timeout_in_seconds,
available_models, available_models,
}); });
} }
@@ -386,7 +410,7 @@ pub struct AssistantSettingsContentV2 {
/// ///
/// Default: 320 /// Default: 320
default_height: Option<f32>, default_height: Option<f32>,
/// The default model to use when creating new chats. /// The default model to use when creating new contexts.
default_model: Option<LanguageModelSelection>, default_model: Option<LanguageModelSelection>,
/// Additional models with which to generate alternatives when performing inline assists. /// Additional models with which to generate alternatives when performing inline assists.
inline_alternatives: Option<Vec<LanguageModelSelection>>, inline_alternatives: Option<Vec<LanguageModelSelection>>,
@@ -474,11 +498,11 @@ pub struct LegacyAssistantSettingsContent {
/// ///
/// Default: 320 /// Default: 320
pub default_height: Option<f32>, pub default_height: Option<f32>,
/// The default OpenAI model to use when creating new chats. /// The default OpenAI model to use when creating new contexts.
/// ///
/// Default: gpt-4-1106-preview /// Default: gpt-4-1106-preview
pub default_open_ai_model: Option<OpenAiModel>, pub default_open_ai_model: Option<OpenAiModel>,
/// OpenAI API base URL to use when creating new chats. /// OpenAI API base URL to use when creating new contexts.
/// ///
/// Default: https://api.openai.com/v1 /// Default: https://api.openai.com/v1
pub openai_api_url: Option<String>, pub openai_api_url: Option<String>,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,20 +1,16 @@
use crate::slash_command::context_server_command;
use crate::SlashCommandId;
use crate::{ use crate::{
prompts::PromptBuilder, slash_command_working_set::SlashCommandWorkingSet, Context, prompts::PromptBuilder, Context, ContextEvent, ContextId, ContextOperation, ContextVersion,
ContextEvent, ContextId, ContextOperation, ContextVersion, SavedContext, SavedContextMetadata, SavedContext, SavedContextMetadata,
}; };
use anyhow::{anyhow, Context as _, Result}; use anyhow::{anyhow, Context as _, Result};
use assistant_tool::{ToolId, ToolWorkingSet};
use client::{proto, telemetry::Telemetry, Client, TypedEnvelope}; use client::{proto, telemetry::Telemetry, Client, TypedEnvelope};
use clock::ReplicaId; use clock::ReplicaId;
use collections::HashMap;
use context_server::manager::ContextServerManager;
use context_server::{ContextServerFactoryRegistry, ContextServerTool};
use fs::Fs; use fs::Fs;
use futures::StreamExt; use futures::StreamExt;
use fuzzy::StringMatchCandidate; use fuzzy::StringMatchCandidate;
use gpui::{AppContext, AsyncAppContext, Context as _, EventEmitter, Model, Task, WeakModel}; use gpui::{
AppContext, AsyncAppContext, Context as _, EventEmitter, Model, ModelContext, Task, WeakModel,
};
use language::LanguageRegistry; use language::LanguageRegistry;
use paths::contexts_dir; use paths::contexts_dir;
use project::Project; use project::Project;
@@ -47,14 +43,9 @@ pub struct RemoteContextMetadata {
pub struct ContextStore { pub struct ContextStore {
contexts: Vec<ContextHandle>, contexts: Vec<ContextHandle>,
contexts_metadata: Vec<SavedContextMetadata>, contexts_metadata: Vec<SavedContextMetadata>,
context_server_manager: Model<ContextServerManager>,
context_server_slash_command_ids: HashMap<Arc<str>, Vec<SlashCommandId>>,
context_server_tool_ids: HashMap<Arc<str>, Vec<ToolId>>,
host_contexts: Vec<RemoteContextMetadata>, host_contexts: Vec<RemoteContextMetadata>,
fs: Arc<dyn Fs>, fs: Arc<dyn Fs>,
languages: Arc<LanguageRegistry>, languages: Arc<LanguageRegistry>,
slash_commands: Arc<SlashCommandWorkingSet>,
tools: Arc<ToolWorkingSet>,
telemetry: Arc<Telemetry>, telemetry: Arc<Telemetry>,
_watch_updates: Task<Option<()>>, _watch_updates: Task<Option<()>>,
client: Arc<Client>, client: Arc<Client>,
@@ -96,8 +87,6 @@ impl ContextStore {
pub fn new( pub fn new(
project: Model<Project>, project: Model<Project>,
prompt_builder: Arc<PromptBuilder>, prompt_builder: Arc<PromptBuilder>,
slash_commands: Arc<SlashCommandWorkingSet>,
tools: Arc<ToolWorkingSet>,
cx: &mut AppContext, cx: &mut AppContext,
) -> Task<Result<Model<Self>>> { ) -> Task<Result<Model<Self>>> {
let fs = project.read(cx).fs().clone(); let fs = project.read(cx).fs().clone();
@@ -107,33 +96,18 @@ impl ContextStore {
const CONTEXT_WATCH_DURATION: Duration = Duration::from_millis(100); const CONTEXT_WATCH_DURATION: Duration = Duration::from_millis(100);
let (mut events, _) = fs.watch(contexts_dir(), CONTEXT_WATCH_DURATION).await; let (mut events, _) = fs.watch(contexts_dir(), CONTEXT_WATCH_DURATION).await;
let this = cx.new_model(|model: &Model<Self>, cx: &mut AppContext| { let this = cx.new_model(|cx: &mut ModelContext<Self>| {
let context_server_factory_registry =
ContextServerFactoryRegistry::default_global(cx);
let context_server_manager = cx.new_model(|model, cx| {
ContextServerManager::new(
context_server_factory_registry,
project.clone(),
model,
cx,
)
});
let mut this = Self { let mut this = Self {
contexts: Vec::new(), contexts: Vec::new(),
contexts_metadata: Vec::new(), contexts_metadata: Vec::new(),
context_server_manager,
context_server_slash_command_ids: HashMap::default(),
context_server_tool_ids: HashMap::default(),
host_contexts: Vec::new(), host_contexts: Vec::new(),
fs, fs,
languages, languages,
slash_commands,
tools,
telemetry, telemetry,
_watch_updates: model.spawn(cx, |this, mut cx| { _watch_updates: cx.spawn(|this, mut cx| {
async move { async move {
while events.next().await.is_some() { while events.next().await.is_some() {
this.update(&mut cx, |this, model, cx| this.reload(model, cx))? this.update(&mut cx, |this, cx| this.reload(cx))?
.await .await
.log_err(); .log_err();
} }
@@ -151,15 +125,13 @@ impl ContextStore {
project: project.clone(), project: project.clone(),
prompt_builder, prompt_builder,
}; };
this.handle_project_changed(project.clone(), model, cx); this.handle_project_changed(project, cx);
this.synchronize_contexts(model, cx); this.synchronize_contexts(cx);
this.register_context_server_handlers(model, cx);
this this
})?; })?;
this.update(&mut cx, |this, model, cx| this.reload(model, cx))? this.update(&mut cx, |this, cx| this.reload(cx))?
.await .await
.log_err(); .log_err();
Ok(this) Ok(this)
}) })
} }
@@ -169,7 +141,7 @@ impl ContextStore {
envelope: TypedEnvelope<proto::AdvertiseContexts>, envelope: TypedEnvelope<proto::AdvertiseContexts>,
mut cx: AsyncAppContext, mut cx: AsyncAppContext,
) -> Result<()> { ) -> Result<()> {
this.update(&mut cx, |this, model, cx| { this.update(&mut cx, |this, cx| {
this.host_contexts = envelope this.host_contexts = envelope
.payload .payload
.contexts .contexts
@@ -179,7 +151,7 @@ impl ContextStore {
summary: context.summary, summary: context.summary,
}) })
.collect(); .collect();
model.notify(cx); cx.notify();
}) })
} }
@@ -189,7 +161,7 @@ impl ContextStore {
mut cx: AsyncAppContext, mut cx: AsyncAppContext,
) -> Result<proto::OpenContextResponse> { ) -> Result<proto::OpenContextResponse> {
let context_id = ContextId::from_proto(envelope.payload.context_id); let context_id = ContextId::from_proto(envelope.payload.context_id);
let operations = this.update(&mut cx, |this, model, cx| { let operations = this.update(&mut cx, |this, cx| {
if this.project.read(cx).is_via_collab() { if this.project.read(cx).is_via_collab() {
return Err(anyhow!("only the host contexts can be opened")); return Err(anyhow!("only the host contexts can be opened"));
} }
@@ -218,14 +190,14 @@ impl ContextStore {
_: TypedEnvelope<proto::CreateContext>, _: TypedEnvelope<proto::CreateContext>,
mut cx: AsyncAppContext, mut cx: AsyncAppContext,
) -> Result<proto::CreateContextResponse> { ) -> Result<proto::CreateContextResponse> {
let (context_id, operations) = this.update(&mut cx, |this, model, cx| { let (context_id, operations) = this.update(&mut cx, |this, cx| {
if this.project.read(cx).is_via_collab() { if this.project.read(cx).is_via_collab() {
return Err(anyhow!("can only create contexts as the host")); return Err(anyhow!("can only create contexts as the host"));
} }
let context = this.create(model, cx); let context = this.create(cx);
let context_id = context.read(cx).id().clone(); let context_id = context.read(cx).id().clone();
model.emit(ContextStoreEvent::ContextCreated(context_id.clone()), cx); cx.emit(ContextStoreEvent::ContextCreated(context_id.clone()));
anyhow::Ok(( anyhow::Ok((
context_id, context_id,
@@ -246,14 +218,12 @@ impl ContextStore {
envelope: TypedEnvelope<proto::UpdateContext>, envelope: TypedEnvelope<proto::UpdateContext>,
mut cx: AsyncAppContext, mut cx: AsyncAppContext,
) -> Result<()> { ) -> Result<()> {
this.update(&mut cx, |this, model, cx| { this.update(&mut cx, |this, cx| {
let context_id = ContextId::from_proto(envelope.payload.context_id); let context_id = ContextId::from_proto(envelope.payload.context_id);
if let Some(context) = this.loaded_context_for_id(&context_id, cx) { if let Some(context) = this.loaded_context_for_id(&context_id, cx) {
let operation_proto = envelope.payload.operation.context("invalid operation")?; let operation_proto = envelope.payload.operation.context("invalid operation")?;
let operation = ContextOperation::from_proto(operation_proto)?; let operation = ContextOperation::from_proto(operation_proto)?;
context.update(cx, |context, model, cx| { context.update(cx, |context, cx| context.apply_ops([operation], cx));
context.apply_ops([operation], model, cx)
});
} }
Ok(()) Ok(())
})? })?
@@ -264,7 +234,7 @@ impl ContextStore {
envelope: TypedEnvelope<proto::SynchronizeContexts>, envelope: TypedEnvelope<proto::SynchronizeContexts>,
mut cx: AsyncAppContext, mut cx: AsyncAppContext,
) -> Result<proto::SynchronizeContextsResponse> { ) -> Result<proto::SynchronizeContextsResponse> {
this.update(&mut cx, |this, model, cx| { this.update(&mut cx, |this, cx| {
if this.project.read(cx).is_via_collab() { if this.project.read(cx).is_via_collab() {
return Err(anyhow!("only the host can synchronize contexts")); return Err(anyhow!("only the host can synchronize contexts"));
} }
@@ -303,12 +273,7 @@ impl ContextStore {
})? })?
} }
fn handle_project_changed( fn handle_project_changed(&mut self, _: Model<Project>, cx: &mut ModelContext<Self>) {
&mut self,
_: Model<Project>,
model: &Model<Self>,
cx: &mut AppContext,
) {
let is_shared = self.project.read(cx).is_shared(); let is_shared = self.project.read(cx).is_shared();
let was_shared = mem::replace(&mut self.project_is_shared, is_shared); let was_shared = mem::replace(&mut self.project_is_shared, is_shared);
if is_shared == was_shared { if is_shared == was_shared {
@@ -329,7 +294,7 @@ impl ContextStore {
.client .client
.subscribe_to_entity(remote_id) .subscribe_to_entity(remote_id)
.log_err() .log_err()
.map(|subscription| subscription.set_model(model, &mut cx.to_async())); .map(|subscription| subscription.set_model(&cx.handle(), &mut cx.to_async()));
self.advertise_contexts(cx); self.advertise_contexts(cx);
} else { } else {
self.client_subscription = None; self.client_subscription = None;
@@ -340,23 +305,22 @@ impl ContextStore {
&mut self, &mut self,
_: Model<Project>, _: Model<Project>,
event: &project::Event, event: &project::Event,
model: &Model<Self>, cx: &mut ModelContext<Self>,
cx: &mut AppContext,
) { ) {
match event { match event {
project::Event::Reshared => { project::Event::Reshared => {
self.advertise_contexts(cx); self.advertise_contexts(cx);
} }
project::Event::HostReshared | project::Event::Rejoined => { project::Event::HostReshared | project::Event::Rejoined => {
self.synchronize_contexts(model, cx); self.synchronize_contexts(cx);
} }
project::Event::DisconnectedFromHost => { project::Event::DisconnectedFromHost => {
self.contexts.retain_mut(|context| { self.contexts.retain_mut(|context| {
if let Some(strong_context) = context.upgrade() { if let Some(strong_context) = context.upgrade() {
*context = ContextHandle::Weak(context.downgrade()); *context = ContextHandle::Weak(context.downgrade());
strong_context.update(cx, |context, model, cx| { strong_context.update(cx, |context, cx| {
if context.replica_id() != ReplicaId::default() { if context.replica_id() != ReplicaId::default() {
context.set_capability(language::Capability::ReadOnly, model, cx); context.set_capability(language::Capability::ReadOnly, cx);
} }
}); });
true true
@@ -365,33 +329,29 @@ impl ContextStore {
} }
}); });
self.host_contexts.clear(); self.host_contexts.clear();
model.notify(cx); cx.notify();
} }
_ => {} _ => {}
} }
} }
pub fn create(&mut self, model: &Model<Self>, cx: &mut AppContext) -> Model<Context> { pub fn create(&mut self, cx: &mut ModelContext<Self>) -> Model<Context> {
let context = cx.new_model(|model, cx| { let context = cx.new_model(|cx| {
Context::local( Context::local(
self.languages.clone(), self.languages.clone(),
Some(self.project.clone()), Some(self.project.clone()),
Some(self.telemetry.clone()), Some(self.telemetry.clone()),
self.prompt_builder.clone(), self.prompt_builder.clone(),
self.slash_commands.clone(),
self.tools.clone(),
model,
cx, cx,
) )
}); });
self.register_context(&context, model, cx); self.register_context(&context, cx);
context context
} }
pub fn create_remote_context( pub fn create_remote_context(
&mut self, &mut self,
model: &Model<Self>, cx: &mut ModelContext<Self>,
cx: &mut AppContext,
) -> Task<Result<Model<Context>>> { ) -> Task<Result<Model<Context>>> {
let project = self.project.read(cx); let project = self.project.read(cx);
let Some(project_id) = project.remote_id() else { let Some(project_id) = project.remote_id() else {
@@ -404,25 +364,20 @@ impl ContextStore {
let project = self.project.clone(); let project = self.project.clone();
let telemetry = self.telemetry.clone(); let telemetry = self.telemetry.clone();
let prompt_builder = self.prompt_builder.clone(); let prompt_builder = self.prompt_builder.clone();
let slash_commands = self.slash_commands.clone();
let tools = self.tools.clone();
let request = self.client.request(proto::CreateContext { project_id }); let request = self.client.request(proto::CreateContext { project_id });
model.spawn(cx, |this, mut cx| async move { cx.spawn(|this, mut cx| async move {
let response = request.await?; let response = request.await?;
let context_id = ContextId::from_proto(response.context_id); let context_id = ContextId::from_proto(response.context_id);
let context_proto = response.context.context("invalid context")?; let context_proto = response.context.context("invalid context")?;
let context = cx.new_model(|model, cx| { let context = cx.new_model(|cx| {
Context::new( Context::new(
context_id.clone(), context_id.clone(),
replica_id, replica_id,
capability, capability,
language_registry, language_registry,
prompt_builder, prompt_builder,
slash_commands,
tools,
Some(project), Some(project),
Some(telemetry), Some(telemetry),
model,
cx, cx,
) )
})?; })?;
@@ -437,12 +392,12 @@ impl ContextStore {
}) })
.await?; .await?;
context.update(&mut cx, |context, cx| context.apply_ops(operations, cx))?; context.update(&mut cx, |context, cx| context.apply_ops(operations, cx))?;
this.update(&mut cx, |this, model, cx| { this.update(&mut cx, |this, cx| {
if let Some(existing_context) = this.loaded_context_for_id(&context_id, cx) { if let Some(existing_context) = this.loaded_context_for_id(&context_id, cx) {
existing_context existing_context
} else { } else {
this.register_context(&context, model, cx); this.register_context(&context, cx);
this.synchronize_contexts(model, cx); this.synchronize_contexts(cx);
context context
} }
}) })
@@ -452,8 +407,7 @@ impl ContextStore {
pub fn open_local_context( pub fn open_local_context(
&mut self, &mut self,
path: PathBuf, path: PathBuf,
model: &Model<Self>, cx: &ModelContext<Self>,
cx: &AppContext,
) -> Task<Result<Model<Context>>> { ) -> Task<Result<Model<Context>>> {
if let Some(existing_context) = self.loaded_context_for_path(&path, cx) { if let Some(existing_context) = self.loaded_context_for_path(&path, cx) {
return Task::ready(Ok(existing_context)); return Task::ready(Ok(existing_context));
@@ -471,30 +425,25 @@ impl ContextStore {
} }
}); });
let prompt_builder = self.prompt_builder.clone(); let prompt_builder = self.prompt_builder.clone();
let slash_commands = self.slash_commands.clone();
let tools = self.tools.clone();
model.spawn(cx, |this, mut cx| async move { cx.spawn(|this, mut cx| async move {
let saved_context = load.await?; let saved_context = load.await?;
let context = cx.new_model(|model, cx| { let context = cx.new_model(|cx| {
Context::deserialize( Context::deserialize(
saved_context, saved_context,
path.clone(), path.clone(),
languages, languages,
prompt_builder, prompt_builder,
slash_commands,
tools,
Some(project), Some(project),
Some(telemetry), Some(telemetry),
model,
cx, cx,
) )
})?; })?;
this.update(&mut cx, |this, model, cx| { this.update(&mut cx, |this, cx| {
if let Some(existing_context) = this.loaded_context_for_path(&path, cx) { if let Some(existing_context) = this.loaded_context_for_path(&path, cx) {
existing_context existing_context
} else { } else {
this.register_context(&context, model, cx); this.register_context(&context, cx);
context context
} }
}) })
@@ -530,8 +479,7 @@ impl ContextStore {
pub fn open_remote_context( pub fn open_remote_context(
&mut self, &mut self,
context_id: ContextId, context_id: ContextId,
model: &Model<Self>, cx: &mut ModelContext<Self>,
cx: &mut AppContext,
) -> Task<Result<Model<Context>>> { ) -> Task<Result<Model<Context>>> {
let project = self.project.read(cx); let project = self.project.read(cx);
let Some(project_id) = project.remote_id() else { let Some(project_id) = project.remote_id() else {
@@ -552,23 +500,18 @@ impl ContextStore {
context_id: context_id.to_proto(), context_id: context_id.to_proto(),
}); });
let prompt_builder = self.prompt_builder.clone(); let prompt_builder = self.prompt_builder.clone();
let slash_commands = self.slash_commands.clone(); cx.spawn(|this, mut cx| async move {
let tools = self.tools.clone();
model.spawn(cx, |this, mut cx| async move {
let response = request.await?; let response = request.await?;
let context_proto = response.context.context("invalid context")?; let context_proto = response.context.context("invalid context")?;
let context = cx.new_model(|model, cx| { let context = cx.new_model(|cx| {
Context::new( Context::new(
context_id.clone(), context_id.clone(),
replica_id, replica_id,
capability, capability,
language_registry, language_registry,
prompt_builder, prompt_builder,
slash_commands,
tools,
Some(project), Some(project),
Some(telemetry), Some(telemetry),
model,
cx, cx,
) )
})?; })?;
@@ -583,24 +526,19 @@ impl ContextStore {
}) })
.await?; .await?;
context.update(&mut cx, |context, cx| context.apply_ops(operations, cx))?; context.update(&mut cx, |context, cx| context.apply_ops(operations, cx))?;
this.update(&mut cx, |this, model, cx| { this.update(&mut cx, |this, cx| {
if let Some(existing_context) = this.loaded_context_for_id(&context_id, cx) { if let Some(existing_context) = this.loaded_context_for_id(&context_id, cx) {
existing_context existing_context
} else { } else {
this.register_context(&context, model, cx); this.register_context(&context, cx);
this.synchronize_contexts(model, cx); this.synchronize_contexts(cx);
context context
} }
}) })
}) })
} }
fn register_context( fn register_context(&mut self, context: &Model<Context>, cx: &mut ModelContext<Self>) {
&mut self,
context: &Model<Context>,
model: &Model<Self>,
cx: &mut AppContext,
) {
let handle = if self.project_is_shared { let handle = if self.project_is_shared {
ContextHandle::Strong(context.clone()) ContextHandle::Strong(context.clone())
} else { } else {
@@ -615,8 +553,7 @@ impl ContextStore {
&mut self, &mut self,
context: Model<Context>, context: Model<Context>,
event: &ContextEvent, event: &ContextEvent,
model: &Model<Self>, cx: &mut ModelContext<Self>,
cx: &mut AppContext,
) { ) {
let Some(project_id) = self.project.read(cx).remote_id() else { let Some(project_id) = self.project.read(cx).remote_id() else {
return; return;
@@ -675,7 +612,7 @@ impl ContextStore {
.ok(); .ok();
} }
fn synchronize_contexts(&mut self, model: &Model<Self>, cx: &mut AppContext) { fn synchronize_contexts(&mut self, cx: &mut ModelContext<Self>) {
let Some(project_id) = self.project.read(cx).remote_id() else { let Some(project_id) = self.project.read(cx).remote_id() else {
return; return;
}; };
@@ -698,37 +635,36 @@ impl ContextStore {
project_id, project_id,
contexts, contexts,
}); });
model cx.spawn(|this, cx| async move {
.spawn(cx, |this, cx| async move { let response = request.await?;
let response = request.await?;
let mut context_ids = Vec::new(); let mut context_ids = Vec::new();
let mut operations = Vec::new(); let mut operations = Vec::new();
this.read_with(&cx, |this, cx| { this.read_with(&cx, |this, cx| {
for context_version_proto in response.contexts { for context_version_proto in response.contexts {
let context_version = ContextVersion::from_proto(&context_version_proto); let context_version = ContextVersion::from_proto(&context_version_proto);
let context_id = ContextId::from_proto(context_version_proto.context_id); let context_id = ContextId::from_proto(context_version_proto.context_id);
if let Some(context) = this.loaded_context_for_id(&context_id, cx) { if let Some(context) = this.loaded_context_for_id(&context_id, cx) {
context_ids.push(context_id); context_ids.push(context_id);
operations.push(context.read(cx).serialize_ops(&context_version, cx)); operations.push(context.read(cx).serialize_ops(&context_version, cx));
}
}
})?;
let operations = futures::future::join_all(operations).await;
for (context_id, operations) in context_ids.into_iter().zip(operations) {
for operation in operations {
client.send(proto::UpdateContext {
project_id,
context_id: context_id.to_proto(),
operation: Some(operation),
})?;
} }
} }
})?;
anyhow::Ok(()) let operations = futures::future::join_all(operations).await;
}) for (context_id, operations) in context_ids.into_iter().zip(operations) {
.detach_and_log_err(cx); for operation in operations {
client.send(proto::UpdateContext {
project_id,
context_id: context_id.to_proto(),
operation: Some(operation),
})?;
}
}
anyhow::Ok(())
})
.detach_and_log_err(cx);
} }
pub fn search(&self, query: String, cx: &AppContext) -> Task<Vec<SavedContextMetadata>> { pub fn search(&self, query: String, cx: &AppContext) -> Task<Vec<SavedContextMetadata>> {
@@ -765,9 +701,9 @@ impl ContextStore {
&self.host_contexts &self.host_contexts
} }
fn reload(&mut self, model: &Model<Self>, cx: &mut AppContext) -> Task<Result<()>> { fn reload(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
let fs = self.fs.clone(); let fs = self.fs.clone();
model.spawn(cx, |this, mut cx| async move { cx.spawn(|this, mut cx| async move {
fs.create_dir(contexts_dir()).await?; fs.create_dir(contexts_dir()).await?;
let mut paths = fs.read_dir(contexts_dir()).await?; let mut paths = fs.read_dir(contexts_dir()).await?;
@@ -796,128 +732,17 @@ impl ContextStore {
contexts.push(SavedContextMetadata { contexts.push(SavedContextMetadata {
title: title.to_string(), title: title.to_string(),
path, path,
mtime: metadata.mtime.timestamp_for_user().into(), mtime: metadata.mtime.into(),
}); });
} }
} }
} }
contexts.sort_unstable_by_key(|context| Reverse(context.mtime)); contexts.sort_unstable_by_key(|context| Reverse(context.mtime));
this.update(&mut cx, |this, model, cx| { this.update(&mut cx, |this, cx| {
this.contexts_metadata = contexts; this.contexts_metadata = contexts;
model.notify(cx); cx.notify();
}) })
}) })
} }
pub fn restart_context_servers(&mut self, model: &Model<Self>, cx: &mut AppContext) {
cx.update_model(
&self.context_server_manager,
|context_server_manager, cx| {
for server in context_server_manager.servers() {
context_server_manager
.restart_server(&server.id(), cx)
.detach_and_log_err(cx);
}
},
);
}
fn register_context_server_handlers(&self, model: &Model<Self>, cx: &mut AppContext) {
cx.subscribe(
&self.context_server_manager.clone(),
Self::handle_context_server_event,
)
.detach();
}
fn handle_context_server_event(
&mut self,
context_server_manager: Model<ContextServerManager>,
event: &context_server::manager::Event,
model: &Model<Self>,
cx: &mut AppContext,
) {
let slash_command_working_set = self.slash_commands.clone();
let tool_working_set = self.tools.clone();
match event {
context_server::manager::Event::ServerStarted { server_id } => {
if let Some(server) = context_server_manager.read(cx).get_server(server_id) {
let context_server_manager = context_server_manager.clone();
cx.spawn({
let server = server.clone();
let server_id = server_id.clone();
|this, mut cx| async move {
let Some(protocol) = server.client() else {
return;
};
if protocol.capable(context_server::protocol::ServerCapability::Prompts) {
if let Some(prompts) = protocol.list_prompts().await.log_err() {
let slash_command_ids = prompts
.into_iter()
.filter(context_server_command::acceptable_prompt)
.map(|prompt| {
log::info!(
"registering context server command: {:?}",
prompt.name
);
slash_command_working_set.insert(Arc::new(
context_server_command::ContextServerSlashCommand::new(
context_server_manager.clone(),
&server,
prompt,
),
))
})
.collect::<Vec<_>>();
this.update(&mut cx, |this, _cx| {
this.context_server_slash_command_ids
.insert(server_id.clone(), slash_command_ids);
})
.log_err();
}
}
if protocol.capable(context_server::protocol::ServerCapability::Tools) {
if let Some(tools) = protocol.list_tools().await.log_err() {
let tool_ids = tools.tools.into_iter().map(|tool| {
log::info!("registering context server tool: {:?}", tool.name);
tool_working_set.insert(
Arc::new(ContextServerTool::new(
context_server_manager.clone(),
server.id(),
tool,
)),
)
}).collect::<Vec<_>>();
this.update(&mut cx, |this, _cx| {
this.context_server_tool_ids
.insert(server_id, tool_ids);
})
.log_err();
}
}
}
})
.detach();
}
}
context_server::manager::Event::ServerStopped { server_id } => {
if let Some(slash_command_ids) =
self.context_server_slash_command_ids.remove(server_id)
{
slash_command_working_set.remove(&slash_command_ids);
}
if let Some(tool_ids) = self.context_server_tool_ids.remove(server_id) {
tool_working_set.remove(&tool_ids);
}
}
}
}
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,27 +1,34 @@
use std::sync::Arc;
use feature_flags::ZedPro; use feature_flags::ZedPro;
use gpui::{Action, AnyElement, AppContext, DismissEvent, SharedString, Task}; use gpui::Action;
use gpui::DismissEvent;
use language_model::{LanguageModel, LanguageModelAvailability, LanguageModelRegistry}; use language_model::{LanguageModel, LanguageModelAvailability, LanguageModelRegistry};
use picker::{Picker, PickerDelegate};
use proto::Plan; use proto::Plan;
use ui::{prelude::*, ListItem, ListItemSpacing, PopoverMenu, PopoverMenuHandle, PopoverTrigger};
use workspace::ShowConfiguration; use workspace::ShowConfiguration;
use std::sync::Arc;
use ui::ListItemSpacing;
use crate::assistant_settings::AssistantSettings;
use fs::Fs;
use gpui::SharedString;
use gpui::Task;
use picker::{Picker, PickerDelegate};
use settings::update_settings_file;
use ui::{prelude::*, ListItem, PopoverMenu, PopoverMenuHandle, PopoverTrigger};
const TRY_ZED_PRO_URL: &str = "https://zed.dev/pro"; const TRY_ZED_PRO_URL: &str = "https://zed.dev/pro";
type OnModelChanged = Arc<dyn Fn(Arc<dyn LanguageModel>, &AppContext) + 'static>;
#[derive(IntoElement)] #[derive(IntoElement)]
pub struct LanguageModelSelector<T: PopoverTrigger> { pub struct ModelSelector<T: PopoverTrigger> {
handle: Option<PopoverMenuHandle<Picker<LanguageModelPickerDelegate>>>, handle: Option<PopoverMenuHandle<Picker<ModelPickerDelegate>>>,
on_model_changed: OnModelChanged, fs: Arc<dyn Fs>,
trigger: T, trigger: T,
info_text: Option<SharedString>, info_text: Option<SharedString>,
} }
pub struct LanguageModelPickerDelegate { pub struct ModelPickerDelegate {
on_model_changed: OnModelChanged, fs: Arc<dyn Fs>,
all_models: Vec<ModelInfo>, all_models: Vec<ModelInfo>,
filtered_models: Vec<ModelInfo>, filtered_models: Vec<ModelInfo>,
selected_index: usize, selected_index: usize,
@@ -35,34 +42,28 @@ struct ModelInfo {
is_selected: bool, is_selected: bool,
} }
impl<T: PopoverTrigger> LanguageModelSelector<T> { impl<T: PopoverTrigger> ModelSelector<T> {
pub fn new( pub fn new(fs: Arc<dyn Fs>, trigger: T) -> Self {
on_model_changed: impl Fn(Arc<dyn LanguageModel>, &AppContext) + 'static, ModelSelector {
trigger: T,
) -> Self {
LanguageModelSelector {
handle: None, handle: None,
on_model_changed: Arc::new(on_model_changed), fs,
trigger, trigger,
info_text: None, info_text: None,
} }
} }
pub fn with_handle( pub fn with_handle(mut self, handle: PopoverMenuHandle<Picker<ModelPickerDelegate>>) -> Self {
mut self,
handle: PopoverMenuHandle<Picker<LanguageModelPickerDelegate>>,
) -> Self {
self.handle = Some(handle); self.handle = Some(handle);
self self
} }
pub fn info_text(mut self, text: impl Into<SharedString>) -> Self { pub fn with_info_text(mut self, text: impl Into<SharedString>) -> Self {
self.info_text = Some(text.into()); self.info_text = Some(text.into());
self self
} }
} }
impl PickerDelegate for LanguageModelPickerDelegate { impl PickerDelegate for ModelPickerDelegate {
type ListItem = ListItem; type ListItem = ListItem;
fn match_count(&self) -> usize { fn match_count(&self) -> usize {
@@ -73,52 +74,25 @@ impl PickerDelegate for LanguageModelPickerDelegate {
self.selected_index self.selected_index
} }
fn set_selected_index(&mut self, ix: usize, model: &Model<Picker>, cx: &mut AppContext) { fn set_selected_index(&mut self, ix: usize, cx: &mut ViewContext<Picker<Self>>) {
self.selected_index = ix.min(self.filtered_models.len().saturating_sub(1)); self.selected_index = ix.min(self.filtered_models.len().saturating_sub(1));
model.notify(cx); cx.notify();
} }
fn placeholder_text(&self, _window: &mut gpui::Window, _cx: &mut gpui::AppContext) -> Arc<str> { fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
"Select a model...".into() "Select a model...".into()
} }
fn update_matches( fn update_matches(&mut self, query: String, cx: &mut ViewContext<Picker<Self>>) -> Task<()> {
&mut self,
query: String,
model: &Model<Picker>,
cx: &mut AppContext,
) -> Task<()> {
let all_models = self.all_models.clone(); let all_models = self.all_models.clone();
cx.spawn(|this, mut cx| async move {
let llm_registry = LanguageModelRegistry::global(cx);
let configured_models: Vec<_> = llm_registry
.read(cx)
.providers()
.iter()
.filter(|provider| provider.is_authenticated(cx))
.map(|provider| provider.id())
.collect();
model.spawn(cx, |this, mut cx| async move {
let filtered_models = cx let filtered_models = cx
.background_executor() .background_executor()
.spawn(async move { .spawn(async move {
let displayed_models = if configured_models.is_empty() {
all_models
} else {
all_models
.into_iter()
.filter(|model_info| {
configured_models.contains(&model_info.model.provider_id())
})
.collect::<Vec<_>>()
};
if query.is_empty() { if query.is_empty() {
displayed_models all_models
} else { } else {
displayed_models all_models
.into_iter() .into_iter()
.filter(|model_info| { .filter(|model_info| {
model_info model_info
@@ -133,19 +107,21 @@ impl PickerDelegate for LanguageModelPickerDelegate {
}) })
.await; .await;
this.update(&mut cx, |this, model, cx| { this.update(&mut cx, |this, cx| {
this.delegate.filtered_models = filtered_models; this.delegate.filtered_models = filtered_models;
this.delegate.set_selected_index(0, cx); this.delegate.set_selected_index(0, cx);
model.notify(cx); cx.notify();
}) })
.ok(); .ok();
}) })
} }
fn confirm(&mut self, _secondary: bool, model: &Model<Picker>, cx: &mut AppContext) { fn confirm(&mut self, _secondary: bool, cx: &mut ViewContext<Picker<Self>>) {
if let Some(model_info) = self.filtered_models.get(self.selected_index) { if let Some(model_info) = self.filtered_models.get(self.selected_index) {
let model = model_info.model.clone(); let model = model_info.model.clone();
(self.on_model_changed)(model.clone(), cx); update_settings_file::<AssistantSettings>(self.fs.clone(), cx, move |settings, _| {
settings.set_model(model.clone())
});
// Update the selection status // Update the selection status
let selected_model_id = model_info.model.id(); let selected_model_id = model_info.model.id();
@@ -159,47 +135,22 @@ impl PickerDelegate for LanguageModelPickerDelegate {
&& model.model.provider_id() == selected_provider_id; && model.model.provider_id() == selected_provider_id;
} }
model.emit(DismissEvent, cx); cx.emit(DismissEvent);
} }
} }
fn dismissed(&mut self, model: &Model<Picker>, _cx: &mut AppContext) {} fn dismissed(&mut self, _cx: &mut ViewContext<Picker<Self>>) {}
fn render_header(&self, model: &Model<Picker>, cx: &mut AppContext) -> Option<AnyElement> {
let configured_models_count = LanguageModelRegistry::global(cx)
.read(cx)
.providers()
.iter()
.filter(|provider| provider.is_authenticated(cx))
.count();
if configured_models_count > 0 {
Some(
Label::new("Configured Models")
.size(LabelSize::Small)
.color(Color::Muted)
.mt_1()
.mb_0p5()
.ml_3()
.into_any_element(),
)
} else {
None
}
}
fn render_match( fn render_match(
&self, &self,
ix: usize, ix: usize,
selected: bool, selected: bool,
model: &Model<Picker>, cx: &mut ViewContext<Picker<Self>>,
cx: &mut AppContext,
) -> Option<Self::ListItem> { ) -> Option<Self::ListItem> {
use feature_flags::FeatureFlagAppExt; use feature_flags::FeatureFlagAppExt;
let show_badges = cx.has_flag::<ZedPro>();
let model_info = self.filtered_models.get(ix)?; let model_info = self.filtered_models.get(ix)?;
let provider_name: String = model_info.model.provider_name().0.clone().into(); let show_badges = cx.has_flag::<ZedPro>();
let provider_name: String = model_info.model.provider_name().0.into();
Some( Some(
ListItem::new(ix) ListItem::new(ix)
@@ -207,7 +158,7 @@ impl PickerDelegate for LanguageModelPickerDelegate {
.spacing(ListItemSpacing::Sparse) .spacing(ListItemSpacing::Sparse)
.selected(selected) .selected(selected)
.start_slot( .start_slot(
div().pr_0p5().child( div().pr_1().child(
Icon::new(model_info.icon) Icon::new(model_info.icon)
.color(Color::Muted) .color(Color::Muted)
.size(IconSize::Medium), .size(IconSize::Medium),
@@ -216,13 +167,13 @@ impl PickerDelegate for LanguageModelPickerDelegate {
.child( .child(
h_flex() h_flex()
.w_full() .w_full()
.items_center() .justify_between()
.gap_1p5() .font_buffer(cx)
.min_w(px(200.)) .min_w(px(240.))
.child(Label::new(model_info.model.name().0.clone()))
.child( .child(
h_flex() h_flex()
.gap_0p5() .gap_2()
.child(Label::new(model_info.model.name().0.clone()))
.child( .child(
Label::new(provider_name) Label::new(provider_name)
.size(LabelSize::XSmall) .size(LabelSize::XSmall)
@@ -251,11 +202,7 @@ impl PickerDelegate for LanguageModelPickerDelegate {
) )
} }
fn render_footer( fn render_footer(&self, cx: &mut ViewContext<Picker<Self>>) -> Option<gpui::AnyElement> {
&self,
model: &Model<Picker>,
cx: &mut AppContext,
) -> Option<gpui::AnyElement> {
use feature_flags::FeatureFlagAppExt; use feature_flags::FeatureFlagAppExt;
let plan = proto::Plan::ZedPro; let plan = proto::Plan::ZedPro;
@@ -265,13 +212,13 @@ impl PickerDelegate for LanguageModelPickerDelegate {
h_flex() h_flex()
.w_full() .w_full()
.border_t_1() .border_t_1()
.border_color(cx.theme().colors().border_variant) .border_color(cx.theme().colors().border)
.p_1() .p_1()
.gap_4() .gap_4()
.justify_between() .justify_between()
.when(cx.has_flag::<ZedPro>(), |this| { .when(cx.has_flag::<ZedPro>(), |this| {
this.child(match plan { this.child(match plan {
// Already a Zed Pro subscriber // Already a zed pro subscriber
Plan::ZedPro => Button::new("zed-pro", "Zed Pro") Plan::ZedPro => Button::new("zed-pro", "Zed Pro")
.icon(IconName::ZedAssistant) .icon(IconName::ZedAssistant)
.icon_size(IconSize::Small) .icon_size(IconSize::Small)
@@ -307,12 +254,11 @@ impl PickerDelegate for LanguageModelPickerDelegate {
} }
} }
impl<T: PopoverTrigger> RenderOnce for LanguageModelSelector<T> { impl<T: PopoverTrigger> RenderOnce for ModelSelector<T> {
fn render(self, _window: &mut gpui::Window, cx: &mut gpui::AppContext) -> impl IntoElement { fn render(self, cx: &mut WindowContext) -> impl IntoElement {
let selected_provider = LanguageModelRegistry::read_global(cx) let selected_provider = LanguageModelRegistry::read_global(cx)
.active_provider() .active_provider()
.map(|m| m.id()); .map(|m| m.id());
let selected_model = LanguageModelRegistry::read_global(cx) let selected_model = LanguageModelRegistry::read_global(cx)
.active_model() .active_model()
.map(|m| m.id()); .map(|m| m.id());
@@ -342,16 +288,15 @@ impl<T: PopoverTrigger> RenderOnce for LanguageModelSelector<T> {
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let delegate = LanguageModelPickerDelegate { let delegate = ModelPickerDelegate {
on_model_changed: self.on_model_changed.clone(), fs: self.fs.clone(),
all_models: all_models.clone(), all_models: all_models.clone(),
filtered_models: all_models, filtered_models: all_models,
selected_index: 0, selected_index: 0,
}; };
let picker_view = cx.new_model(|model, cx| { let picker_view = cx.new_view(|cx| {
let picker = let picker = Picker::uniform_list(delegate, cx).max_height(Some(rems(20.).into()));
Picker::uniform_list(delegate, model, cx).max_height(Some(rems(20.).into()));
picker picker
}); });

View File

@@ -33,21 +33,21 @@ pub enum AssistantEditKind {
Update { Update {
old_text: String, old_text: String,
new_text: String, new_text: String,
description: Option<String>, description: String,
}, },
Create { Create {
new_text: String, new_text: String,
description: Option<String>, description: String,
}, },
InsertBefore { InsertBefore {
old_text: String, old_text: String,
new_text: String, new_text: String,
description: Option<String>, description: String,
}, },
InsertAfter { InsertAfter {
old_text: String, old_text: String,
new_text: String, new_text: String,
description: Option<String>, description: String,
}, },
Delete { Delete {
old_text: String, old_text: String,
@@ -86,37 +86,19 @@ enum SearchDirection {
Diagonal, Diagonal,
} }
// A measure of the currently quality of an in-progress fuzzy search.
//
// Uses 60 bits to store a numeric cost, and 4 bits to store the preceding
// operation in the search.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
struct SearchState { struct SearchState {
cost: u32, score: u32,
direction: SearchDirection, direction: SearchDirection,
} }
impl SearchState { impl SearchState {
fn new(cost: u32, direction: SearchDirection) -> Self { fn new(score: u32, direction: SearchDirection) -> Self {
Self { cost, direction } Self { score, direction }
}
}
struct SearchMatrix {
cols: usize,
data: Vec<SearchState>,
}
impl SearchMatrix {
fn new(rows: usize, cols: usize) -> Self {
SearchMatrix {
cols,
data: vec![SearchState::new(0, SearchDirection::Diagonal); rows * cols],
}
}
fn get(&self, row: usize, col: usize) -> SearchState {
self.data[row * self.cols + col]
}
fn set(&mut self, row: usize, col: usize, cost: SearchState) {
self.data[row * self.cols + col] = cost;
} }
} }
@@ -140,7 +122,7 @@ impl ResolvedPatch {
edits.push((suggestion.range.clone(), suggestion.new_text.clone())); edits.push((suggestion.range.clone(), suggestion.new_text.clone()));
} }
} }
buffer.update(cx, |buffer, model, cx| { buffer.update(cx, |buffer, cx| {
buffer.edit( buffer.edit(
edits, edits,
Some(AutoindentMode::Block { Some(AutoindentMode::Block {
@@ -205,23 +187,23 @@ impl AssistantEdit {
"update" => AssistantEditKind::Update { "update" => AssistantEditKind::Update {
old_text: old_text.ok_or_else(|| anyhow!("missing old_text"))?, old_text: old_text.ok_or_else(|| anyhow!("missing old_text"))?,
new_text: new_text.ok_or_else(|| anyhow!("missing new_text"))?, new_text: new_text.ok_or_else(|| anyhow!("missing new_text"))?,
description, description: description.ok_or_else(|| anyhow!("missing description"))?,
}, },
"insert_before" => AssistantEditKind::InsertBefore { "insert_before" => AssistantEditKind::InsertBefore {
old_text: old_text.ok_or_else(|| anyhow!("missing old_text"))?, old_text: old_text.ok_or_else(|| anyhow!("missing old_text"))?,
new_text: new_text.ok_or_else(|| anyhow!("missing new_text"))?, new_text: new_text.ok_or_else(|| anyhow!("missing new_text"))?,
description, description: description.ok_or_else(|| anyhow!("missing description"))?,
}, },
"insert_after" => AssistantEditKind::InsertAfter { "insert_after" => AssistantEditKind::InsertAfter {
old_text: old_text.ok_or_else(|| anyhow!("missing old_text"))?, old_text: old_text.ok_or_else(|| anyhow!("missing old_text"))?,
new_text: new_text.ok_or_else(|| anyhow!("missing new_text"))?, new_text: new_text.ok_or_else(|| anyhow!("missing new_text"))?,
description, description: description.ok_or_else(|| anyhow!("missing description"))?,
}, },
"delete" => AssistantEditKind::Delete { "delete" => AssistantEditKind::Delete {
old_text: old_text.ok_or_else(|| anyhow!("missing old_text"))?, old_text: old_text.ok_or_else(|| anyhow!("missing old_text"))?,
}, },
"create" => AssistantEditKind::Create { "create" => AssistantEditKind::Create {
description, description: description.ok_or_else(|| anyhow!("missing description"))?,
new_text: new_text.ok_or_else(|| anyhow!("missing new_text"))?, new_text: new_text.ok_or_else(|| anyhow!("missing new_text"))?,
}, },
_ => Err(anyhow!("unknown operation {operation:?}"))?, _ => Err(anyhow!("unknown operation {operation:?}"))?,
@@ -282,7 +264,7 @@ impl AssistantEditKind {
ResolvedEdit { ResolvedEdit {
range, range,
new_text, new_text,
description, description: Some(description),
} }
} }
Self::Create { Self::Create {
@@ -290,7 +272,7 @@ impl AssistantEditKind {
description, description,
} => ResolvedEdit { } => ResolvedEdit {
range: text::Anchor::MIN..text::Anchor::MAX, range: text::Anchor::MIN..text::Anchor::MAX,
description, description: Some(description),
new_text, new_text,
}, },
Self::InsertBefore { Self::InsertBefore {
@@ -303,7 +285,7 @@ impl AssistantEditKind {
ResolvedEdit { ResolvedEdit {
range: range.start..range.start, range: range.start..range.start,
new_text, new_text,
description, description: Some(description),
} }
} }
Self::InsertAfter { Self::InsertAfter {
@@ -316,7 +298,7 @@ impl AssistantEditKind {
ResolvedEdit { ResolvedEdit {
range: range.end..range.end, range: range.end..range.end,
new_text, new_text,
description, description: Some(description),
} }
} }
Self::Delete { old_text } => { Self::Delete { old_text } => {
@@ -332,29 +314,44 @@ impl AssistantEditKind {
fn resolve_location(buffer: &text::BufferSnapshot, search_query: &str) -> Range<text::Anchor> { fn resolve_location(buffer: &text::BufferSnapshot, search_query: &str) -> Range<text::Anchor> {
const INSERTION_COST: u32 = 3; const INSERTION_COST: u32 = 3;
const DELETION_COST: u32 = 10;
const WHITESPACE_INSERTION_COST: u32 = 1; const WHITESPACE_INSERTION_COST: u32 = 1;
const DELETION_COST: u32 = 3;
const WHITESPACE_DELETION_COST: u32 = 1; const WHITESPACE_DELETION_COST: u32 = 1;
const EQUALITY_BONUS: u32 = 5;
struct Matrix {
cols: usize,
data: Vec<SearchState>,
}
impl Matrix {
fn new(rows: usize, cols: usize) -> Self {
Matrix {
cols,
data: vec![SearchState::new(0, SearchDirection::Diagonal); rows * cols],
}
}
fn get(&self, row: usize, col: usize) -> SearchState {
self.data[row * self.cols + col]
}
fn set(&mut self, row: usize, col: usize, cost: SearchState) {
self.data[row * self.cols + col] = cost;
}
}
let buffer_len = buffer.len(); let buffer_len = buffer.len();
let query_len = search_query.len(); let query_len = search_query.len();
let mut matrix = SearchMatrix::new(query_len + 1, buffer_len + 1); let mut matrix = Matrix::new(query_len + 1, buffer_len + 1);
let mut leading_deletion_cost = 0_u32;
for (row, query_byte) in search_query.bytes().enumerate() { for (row, query_byte) in search_query.bytes().enumerate() {
let deletion_cost = if query_byte.is_ascii_whitespace() {
WHITESPACE_DELETION_COST
} else {
DELETION_COST
};
leading_deletion_cost = leading_deletion_cost.saturating_add(deletion_cost);
matrix.set(
row + 1,
0,
SearchState::new(leading_deletion_cost, SearchDirection::Diagonal),
);
for (col, buffer_byte) in buffer.bytes_in_range(0..buffer.len()).flatten().enumerate() { for (col, buffer_byte) in buffer.bytes_in_range(0..buffer.len()).flatten().enumerate() {
let deletion_cost = if query_byte.is_ascii_whitespace() {
WHITESPACE_DELETION_COST
} else {
DELETION_COST
};
let insertion_cost = if buffer_byte.is_ascii_whitespace() { let insertion_cost = if buffer_byte.is_ascii_whitespace() {
WHITESPACE_INSERTION_COST WHITESPACE_INSERTION_COST
} else { } else {
@@ -362,35 +359,38 @@ impl AssistantEditKind {
}; };
let up = SearchState::new( let up = SearchState::new(
matrix.get(row, col + 1).cost.saturating_add(deletion_cost), matrix.get(row, col + 1).score.saturating_sub(deletion_cost),
SearchDirection::Up, SearchDirection::Up,
); );
let left = SearchState::new( let left = SearchState::new(
matrix.get(row + 1, col).cost.saturating_add(insertion_cost), matrix
.get(row + 1, col)
.score
.saturating_sub(insertion_cost),
SearchDirection::Left, SearchDirection::Left,
); );
let diagonal = SearchState::new( let diagonal = SearchState::new(
if query_byte == *buffer_byte { if query_byte == *buffer_byte {
matrix.get(row, col).cost matrix.get(row, col).score.saturating_add(EQUALITY_BONUS)
} else { } else {
matrix matrix
.get(row, col) .get(row, col)
.cost .score
.saturating_add(deletion_cost + insertion_cost) .saturating_sub(deletion_cost + insertion_cost)
}, },
SearchDirection::Diagonal, SearchDirection::Diagonal,
); );
matrix.set(row + 1, col + 1, up.min(left).min(diagonal)); matrix.set(row + 1, col + 1, up.max(left).max(diagonal));
} }
} }
// Traceback to find the best match // Traceback to find the best match
let mut best_buffer_end = buffer_len; let mut best_buffer_end = buffer_len;
let mut best_cost = u32::MAX; let mut best_score = 0;
for col in 1..=buffer_len { for col in 1..=buffer_len {
let cost = matrix.get(query_len, col).cost; let score = matrix.get(query_len, col).score;
if cost < best_cost { if score > best_score {
best_cost = cost; best_score = score;
best_buffer_end = col; best_buffer_end = col;
} }
} }
@@ -461,7 +461,7 @@ impl AssistantPatch {
// Expand the context ranges of each edit and group edits with overlapping context ranges. // Expand the context ranges of each edit and group edits with overlapping context ranges.
let mut edit_groups_by_buffer = HashMap::default(); let mut edit_groups_by_buffer = HashMap::default();
for (buffer, edits) in edits_by_buffer { for (buffer, edits) in edits_by_buffer {
if let Ok(snapshot) = buffer.update(cx, |buffer, model, _| buffer.text_snapshot()) { if let Ok(snapshot) = buffer.update(cx, |buffer, _| buffer.text_snapshot()) {
edit_groups_by_buffer.insert(buffer, Self::group_edits(edits, &snapshot)); edit_groups_by_buffer.insert(buffer, Self::group_edits(edits, &snapshot));
} }
} }
@@ -560,84 +560,89 @@ mod tests {
language_settings::AllLanguageSettings, Language, LanguageConfig, LanguageMatcher, language_settings::AllLanguageSettings, Language, LanguageConfig, LanguageMatcher,
}; };
use settings::SettingsStore; use settings::SettingsStore;
use text::{OffsetRangeExt, Point};
use ui::BorrowAppContext; use ui::BorrowAppContext;
use unindent::Unindent as _; use unindent::Unindent as _;
use util::test::{generate_marked_text, marked_text_ranges};
#[gpui::test] #[gpui::test]
fn test_resolve_location(cx: &mut AppContext) { fn test_resolve_location(cx: &mut AppContext) {
assert_location_resolution( {
concat!( let buffer = cx.new_model(|cx| {
" Lorem\n", Buffer::local(
"« ipsum\n", concat!(
" dolor sit amet»\n", " Lorem\n",
" consecteur", " ipsum\n",
), " dolor sit amet\n",
"ipsum\ndolor", " consecteur",
cx, ),
); cx,
)
});
let snapshot = buffer.read(cx).snapshot();
assert_eq!(
AssistantEditKind::resolve_location(&snapshot, "ipsum\ndolor").to_point(&snapshot),
Point::new(1, 0)..Point::new(2, 18)
);
}
assert_location_resolution( {
&" let buffer = cx.new_model(|cx| {
«fn foo1(a: usize) -> usize { Buffer::local(
40 concat!(
"fn foo1(a: usize) -> usize {\n",
" 40\n",
"}\n",
"\n",
"fn foo2(b: usize) -> usize {\n",
" 42\n",
"}\n",
),
cx,
)
});
let snapshot = buffer.read(cx).snapshot();
assert_eq!(
AssistantEditKind::resolve_location(&snapshot, "fn foo1(b: usize) {\n40\n}")
.to_point(&snapshot),
Point::new(0, 0)..Point::new(2, 1)
);
}
fn foo2(b: usize) -> usize { {
42 let buffer = cx.new_model(|cx| {
} Buffer::local(
" concat!(
.unindent(), "fn main() {\n",
"fn foo1(b: usize) {\n40\n}", " Foo\n",
cx, " .bar()\n",
); " .baz()\n",
" .qux()\n",
assert_location_resolution( "}\n",
&" "\n",
fn main() { "fn foo2(b: usize) -> usize {\n",
« Foo " 42\n",
.bar() "}\n",
.baz() ),
.qux()» cx,
} )
});
fn foo2(b: usize) -> usize { let snapshot = buffer.read(cx).snapshot();
42 assert_eq!(
} AssistantEditKind::resolve_location(&snapshot, "Foo.bar.baz.qux()")
" .to_point(&snapshot),
.unindent(), Point::new(1, 0)..Point::new(4, 14)
"Foo.bar.baz.qux()", );
cx, }
);
assert_location_resolution(
&"
class Something {
one() { return 1; }
« two() { return 2222; }
three() { return 333; }
four() { return 4444; }
five() { return 5555; }
six() { return 6666; }
» seven() { return 7; }
eight() { return 8; }
}
"
.unindent(),
&"
two() { return 2222; }
four() { return 4444; }
five() { return 5555; }
six() { return 6666; }
"
.unindent(),
cx,
);
} }
#[gpui::test] #[gpui::test]
fn test_resolve_edits(cx: &mut AppContext) { fn test_resolve_edits(cx: &mut AppContext) {
init_test(cx); let settings_store = SettingsStore::test(cx);
cx.set_global(settings_store);
language::init(cx);
cx.update_global::<SettingsStore, _>(|settings, cx| {
settings.update_user_settings::<AllLanguageSettings>(cx, |_| {});
});
assert_edits( assert_edits(
" "
@@ -670,7 +675,7 @@ mod tests {
last_name: String, last_name: String,
" "
.unindent(), .unindent(),
description: None, description: "".into(),
}, },
AssistantEditKind::Update { AssistantEditKind::Update {
old_text: " old_text: "
@@ -685,7 +690,7 @@ mod tests {
} }
" "
.unindent(), .unindent(),
description: None, description: "".into(),
}, },
], ],
" "
@@ -712,6 +717,7 @@ mod tests {
); );
// Ensure InsertBefore merges correctly with Update of the same text // Ensure InsertBefore merges correctly with Update of the same text
assert_edits( assert_edits(
" "
fn foo() { fn foo() {
@@ -729,7 +735,7 @@ mod tests {
qux(); qux();
}" }"
.unindent(), .unindent(),
description: Some("implement bar".into()), description: "implement bar".into(),
}, },
AssistantEditKind::Update { AssistantEditKind::Update {
old_text: " old_text: "
@@ -742,7 +748,7 @@ mod tests {
bar(); bar();
}" }"
.unindent(), .unindent(),
description: Some("call bar in foo".into()), description: "call bar in foo".into(),
}, },
AssistantEditKind::InsertAfter { AssistantEditKind::InsertAfter {
old_text: " old_text: "
@@ -757,7 +763,7 @@ mod tests {
} }
" "
.unindent(), .unindent(),
description: Some("implement qux".into()), description: "implement qux".into(),
}, },
], ],
" "
@@ -776,153 +782,6 @@ mod tests {
.unindent(), .unindent(),
cx, cx,
); );
// Correctly indent new text when replacing multiple adjacent indented blocks.
assert_edits(
"
impl Numbers {
fn one() {
1
}
fn two() {
2
}
fn three() {
3
}
}
"
.unindent(),
vec![
AssistantEditKind::Update {
old_text: "
fn one() {
1
}
"
.unindent(),
new_text: "
fn one() {
101
}
"
.unindent(),
description: None,
},
AssistantEditKind::Update {
old_text: "
fn two() {
2
}
"
.unindent(),
new_text: "
fn two() {
102
}
"
.unindent(),
description: None,
},
AssistantEditKind::Update {
old_text: "
fn three() {
3
}
"
.unindent(),
new_text: "
fn three() {
103
}
"
.unindent(),
description: None,
},
],
"
impl Numbers {
fn one() {
101
}
fn two() {
102
}
fn three() {
103
}
}
"
.unindent(),
cx,
);
assert_edits(
"
impl Person {
fn set_name(&mut self, name: String) {
self.name = name;
}
fn name(&self) -> String {
return self.name;
}
}
"
.unindent(),
vec![
AssistantEditKind::Update {
old_text: "self.name = name;".unindent(),
new_text: "self._name = name;".unindent(),
description: None,
},
AssistantEditKind::Update {
old_text: "return self.name;\n".unindent(),
new_text: "return self._name;\n".unindent(),
description: None,
},
],
"
impl Person {
fn set_name(&mut self, name: String) {
self._name = name;
}
fn name(&self) -> String {
return self._name;
}
}
"
.unindent(),
cx,
);
}
fn init_test(cx: &mut AppContext) {
let settings_store = SettingsStore::test(cx);
cx.set_global(settings_store);
language::init(cx);
cx.update_global::<SettingsStore, _>(|settings, cx| {
settings.update_user_settings::<AllLanguageSettings>(cx, |_| {});
});
}
#[track_caller]
fn assert_location_resolution(
text_with_expected_range: &str,
query: &str,
cx: &mut AppContext,
) {
let (text, _) = marked_text_ranges(text_with_expected_range, false);
let buffer = cx.new_model(|model, cx| Buffer::local(text.clone(), model, cx));
let snapshot = buffer.read(cx).snapshot();
let range = AssistantEditKind::resolve_location(&snapshot, query).to_offset(&snapshot);
let text_with_actual_range = generate_marked_text(&text, &[range], false);
pretty_assertions::assert_eq!(text_with_actual_range, text_with_expected_range);
} }
#[track_caller] #[track_caller]
@@ -932,9 +791,8 @@ mod tests {
new_text: String, new_text: String,
cx: &mut AppContext, cx: &mut AppContext,
) { ) {
let buffer = cx.new_model(|model, cx| { let buffer =
Buffer::local(old_text, model, cx).with_language(Arc::new(rust_lang()), model, cx) cx.new_model(|cx| Buffer::local(old_text, cx).with_language(Arc::new(rust_lang()), cx));
});
let snapshot = buffer.read(cx).snapshot(); let snapshot = buffer.read(cx).snapshot();
let resolved_edits = edits let resolved_edits = edits
.into_iter() .into_iter()

View File

@@ -1,4 +1,3 @@
use crate::SlashCommandWorkingSet;
use crate::{slash_command::SlashCommandCompletionProvider, AssistantPanel, InlineAssistant}; use crate::{slash_command::SlashCommandCompletionProvider, AssistantPanel, InlineAssistant};
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
@@ -38,8 +37,8 @@ use std::{
use text::LineEnding; use text::LineEnding;
use theme::ThemeSettings; use theme::ThemeSettings;
use ui::{ use ui::{
div, prelude::*, AppContext, IconButtonShape, KeyBinding, ListItem, ListItemSpacing, div, prelude::*, IconButtonShape, KeyBinding, ListItem, ListItemSpacing, ParentElement, Render,
ParentElement, Render, SharedString, Styled, Tooltip, VisualContext, SharedString, Styled, Tooltip, ViewContext, VisualContext,
}; };
use util::{ResultExt, TryFutureExt}; use util::{ResultExt, TryFutureExt};
use uuid::Uuid; use uuid::Uuid;
@@ -88,7 +87,7 @@ pub fn open_prompt_library(
.find_map(|window| window.downcast::<PromptLibrary>()); .find_map(|window| window.downcast::<PromptLibrary>());
if let Some(existing_window) = existing_window { if let Some(existing_window) = existing_window {
existing_window existing_window
.update(cx, |_, model, cx| cx.activate_window()) .update(cx, |_, cx| cx.activate_window())
.ok(); .ok();
Task::ready(Ok(existing_window)) Task::ready(Ok(existing_window))
} else { } else {
@@ -109,11 +108,7 @@ pub fn open_prompt_library(
window_bounds: Some(WindowBounds::Windowed(bounds)), window_bounds: Some(WindowBounds::Windowed(bounds)),
..Default::default() ..Default::default()
}, },
|cx| { |cx| cx.new_view(|cx| PromptLibrary::new(store, language_registry, cx)),
cx.new_model(|model, cx| {
PromptLibrary::new(store, language_registry, model, cx)
})
},
) )
})? })?
}) })
@@ -125,14 +120,14 @@ pub struct PromptLibrary {
language_registry: Arc<LanguageRegistry>, language_registry: Arc<LanguageRegistry>,
prompt_editors: HashMap<PromptId, PromptEditor>, prompt_editors: HashMap<PromptId, PromptEditor>,
active_prompt_id: Option<PromptId>, active_prompt_id: Option<PromptId>,
picker: Model<Picker<PromptPickerDelegate>>, picker: View<Picker<PromptPickerDelegate>>,
pending_load: Task<()>, pending_load: Task<()>,
_subscriptions: Vec<Subscription>, _subscriptions: Vec<Subscription>,
} }
struct PromptEditor { struct PromptEditor {
title_editor: Model<Editor>, title_editor: View<Editor>,
body_editor: Model<Editor>, body_editor: View<Editor>,
token_count: Option<usize>, token_count: Option<usize>,
pending_token_count: Task<Option<()>>, pending_token_count: Task<Option<()>>,
next_title_and_body_to_save: Option<(String, Rope)>, next_title_and_body_to_save: Option<(String, Rope)>,
@@ -162,11 +157,7 @@ impl PickerDelegate for PromptPickerDelegate {
self.matches.len() self.matches.len()
} }
fn no_matches_text( fn no_matches_text(&self, _cx: &mut WindowContext) -> SharedString {
&self,
_window: &mut gpui::Window,
_cx: &mut gpui::AppContext,
) -> SharedString {
if self.store.prompt_count() == 0 { if self.store.prompt_count() == 0 {
"No prompts.".into() "No prompts.".into()
} else { } else {
@@ -178,31 +169,23 @@ impl PickerDelegate for PromptPickerDelegate {
self.selected_index self.selected_index
} }
fn set_selected_index(&mut self, ix: usize, model: &Model<Picker>, cx: &mut AppContext) { fn set_selected_index(&mut self, ix: usize, cx: &mut ViewContext<Picker<Self>>) {
self.selected_index = ix; self.selected_index = ix;
if let Some(prompt) = self.matches.get(self.selected_index) { if let Some(prompt) = self.matches.get(self.selected_index) {
model.emit( cx.emit(PromptPickerEvent::Selected {
cx, prompt_id: prompt.id,
PromptPickerEvent::Selected { });
prompt_id: prompt.id,
},
);
} }
} }
fn placeholder_text(&self, _window: &mut gpui::Window, _cx: &mut gpui::AppContext) -> Arc<str> { fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
"Search...".into() "Search...".into()
} }
fn update_matches( fn update_matches(&mut self, query: String, cx: &mut ViewContext<Picker<Self>>) -> Task<()> {
&mut self,
query: String,
model: &Model<Picker>,
cx: &mut AppContext,
) -> Task<()> {
let search = self.store.search(query); let search = self.store.search(query);
let prev_prompt_id = self.matches.get(self.selected_index).map(|mat| mat.id); let prev_prompt_id = self.matches.get(self.selected_index).map(|mat| mat.id);
model.spawn(cx, |this, mut cx| async move { cx.spawn(|this, mut cx| async move {
let (matches, selected_index) = cx let (matches, selected_index) = cx
.background_executor() .background_executor()
.spawn(async move { .spawn(async move {
@@ -217,34 +200,30 @@ impl PickerDelegate for PromptPickerDelegate {
}) })
.await; .await;
this.update(&mut cx, |this, model, cx| { this.update(&mut cx, |this, cx| {
this.delegate.matches = matches; this.delegate.matches = matches;
this.delegate.set_selected_index(selected_index, cx); this.delegate.set_selected_index(selected_index, cx);
model.notify(cx); cx.notify();
}) })
.ok(); .ok();
}) })
} }
fn confirm(&mut self, _secondary: bool, model: &Model<Picker>, cx: &mut AppContext) { fn confirm(&mut self, _secondary: bool, cx: &mut ViewContext<Picker<Self>>) {
if let Some(prompt) = self.matches.get(self.selected_index) { if let Some(prompt) = self.matches.get(self.selected_index) {
model.emit( cx.emit(PromptPickerEvent::Confirmed {
cx, prompt_id: prompt.id,
PromptPickerEvent::Confirmed { });
prompt_id: prompt.id,
},
);
} }
} }
fn dismissed(&mut self, model: &Model<Picker>, _cx: &mut AppContext) {} fn dismissed(&mut self, _cx: &mut ViewContext<Picker<Self>>) {}
fn render_match( fn render_match(
&self, &self,
ix: usize, ix: usize,
selected: bool, selected: bool,
model: &Model<Picker>, cx: &mut ViewContext<Picker<Self>>,
cx: &mut AppContext,
) -> Option<Self::ListItem> { ) -> Option<Self::ListItem> {
let prompt = self.matches.get(ix)?; let prompt = self.matches.get(ix)?;
let default = prompt.default; let default = prompt.default;
@@ -261,9 +240,9 @@ impl PickerDelegate for PromptPickerDelegate {
.selected(true) .selected(true)
.icon_color(Color::Accent) .icon_color(Color::Accent)
.shape(IconButtonShape::Square) .shape(IconButtonShape::Square)
.tooltip(move |window, cx| Tooltip::text("Remove from Default Prompt", cx)) .tooltip(move |cx| Tooltip::text("Remove from Default Prompt", cx))
.on_click(model.listener(move |_, _, model, window, cx| { .on_click(cx.listener(move |_, _, cx| {
model.emit(PromptPickerEvent::ToggledDefault { prompt_id }, cx) cx.emit(PromptPickerEvent::ToggledDefault { prompt_id })
})) }))
})) }))
.end_hover_slot( .end_hover_slot(
@@ -273,12 +252,11 @@ impl PickerDelegate for PromptPickerDelegate {
div() div()
.id("built-in-prompt") .id("built-in-prompt")
.child(Icon::new(IconName::FileLock).color(Color::Muted)) .child(Icon::new(IconName::FileLock).color(Color::Muted))
.tooltip(move |window, cx| { .tooltip(move |cx| {
Tooltip::with_meta( Tooltip::with_meta(
"Built-in prompt", "Built-in prompt",
None, None,
BUILT_IN_TOOLTIP_TEXT, BUILT_IN_TOOLTIP_TEXT,
window,
cx, cx,
) )
}) })
@@ -287,9 +265,9 @@ impl PickerDelegate for PromptPickerDelegate {
IconButton::new("delete-prompt", IconName::Trash) IconButton::new("delete-prompt", IconName::Trash)
.icon_color(Color::Muted) .icon_color(Color::Muted)
.shape(IconButtonShape::Square) .shape(IconButtonShape::Square)
.tooltip(move |window, cx| Tooltip::text("Delete Prompt", cx)) .tooltip(move |cx| Tooltip::text("Delete Prompt", cx))
.on_click(model.listener(move |_, _, model, window, cx| { .on_click(cx.listener(move |_, _, cx| {
model.emit(PromptPickerEvent::Deleted { prompt_id }, cx) cx.emit(PromptPickerEvent::Deleted { prompt_id })
})) }))
.into_any_element() .into_any_element()
}) })
@@ -299,7 +277,7 @@ impl PickerDelegate for PromptPickerDelegate {
.selected_icon(IconName::SparkleFilled) .selected_icon(IconName::SparkleFilled)
.icon_color(if default { Color::Accent } else { Color::Muted }) .icon_color(if default { Color::Accent } else { Color::Muted })
.shape(IconButtonShape::Square) .shape(IconButtonShape::Square)
.tooltip(move |window, cx| { .tooltip(move |cx| {
Tooltip::text( Tooltip::text(
if default { if default {
"Remove from Default Prompt" "Remove from Default Prompt"
@@ -309,20 +287,15 @@ impl PickerDelegate for PromptPickerDelegate {
cx, cx,
) )
}) })
.on_click(model.listener(move |_, _, model, window, cx| { .on_click(cx.listener(move |_, _, cx| {
model.emit(PromptPickerEvent::ToggledDefault { prompt_id }, cx) cx.emit(PromptPickerEvent::ToggledDefault { prompt_id })
})), })),
), ),
); );
Some(element) Some(element)
} }
fn render_editor( fn render_editor(&self, editor: &View<Editor>, cx: &mut ViewContext<Picker<Self>>) -> Div {
&self,
editor: &Model<Editor>,
model: &Model<Picker>,
cx: &mut AppContext,
) -> Div {
h_flex() h_flex()
.bg(cx.theme().colors().editor_background) .bg(cx.theme().colors().editor_background)
.rounded_md() .rounded_md()
@@ -339,8 +312,7 @@ impl PromptLibrary {
fn new( fn new(
store: Arc<PromptStore>, store: Arc<PromptStore>,
language_registry: Arc<LanguageRegistry>, language_registry: Arc<LanguageRegistry>,
model: &Model<Self>, cx: &mut ViewContext<Self>,
cx: &mut AppContext,
) -> Self { ) -> Self {
let delegate = PromptPickerDelegate { let delegate = PromptPickerDelegate {
store: store.clone(), store: store.clone(),
@@ -348,11 +320,11 @@ impl PromptLibrary {
matches: Vec::new(), matches: Vec::new(),
}; };
let picker = cx.new_model(|model, cx| { let picker = cx.new_view(|cx| {
let picker = Picker::uniform_list(delegate, model, cx) let picker = Picker::uniform_list(delegate, cx)
.modal(false) .modal(false)
.max_height(None); .max_height(None);
picker.focus(window, cx); picker.focus(cx);
picker picker
}); });
Self { Self {
@@ -368,52 +340,47 @@ impl PromptLibrary {
fn handle_picker_event( fn handle_picker_event(
&mut self, &mut self,
_: Model<Picker<PromptPickerDelegate>>, _: View<Picker<PromptPickerDelegate>>,
event: &PromptPickerEvent, event: &PromptPickerEvent,
model: &Model<Self>, cx: &mut ViewContext<Self>,
cx: &mut AppContext,
) { ) {
match event { match event {
PromptPickerEvent::Selected { prompt_id } => { PromptPickerEvent::Selected { prompt_id } => {
self.load_prompt(*prompt_id, false, model, cx); self.load_prompt(*prompt_id, false, cx);
} }
PromptPickerEvent::Confirmed { prompt_id } => { PromptPickerEvent::Confirmed { prompt_id } => {
self.load_prompt(*prompt_id, true, model, cx); self.load_prompt(*prompt_id, true, cx);
} }
PromptPickerEvent::ToggledDefault { prompt_id } => { PromptPickerEvent::ToggledDefault { prompt_id } => {
self.toggle_default_for_prompt(*prompt_id, model, cx); self.toggle_default_for_prompt(*prompt_id, cx);
} }
PromptPickerEvent::Deleted { prompt_id } => { PromptPickerEvent::Deleted { prompt_id } => {
self.delete_prompt(*prompt_id, model, cx); self.delete_prompt(*prompt_id, cx);
} }
} }
} }
pub fn new_prompt(&mut self, model: &Model<Self>, cx: &mut AppContext) { pub fn new_prompt(&mut self, cx: &mut ViewContext<Self>) {
// If we already have an untitled prompt, use that instead // If we already have an untitled prompt, use that instead
// of creating a new one. // of creating a new one.
if let Some(metadata) = self.store.first() { if let Some(metadata) = self.store.first() {
if metadata.title.is_none() { if metadata.title.is_none() {
self.load_prompt(metadata.id, true, model, cx); self.load_prompt(metadata.id, true, cx);
return; return;
} }
} }
let prompt_id = PromptId::new(); let prompt_id = PromptId::new();
let save = self.store.save(prompt_id, None, false, "".into()); let save = self.store.save(prompt_id, None, false, "".into());
self.picker self.picker.update(cx, |picker, cx| picker.refresh(cx));
.update(cx, |picker, model, cx| picker.refresh(cx)); cx.spawn(|this, mut cx| async move {
model save.await?;
.spawn(cx, |this, mut cx| async move { this.update(&mut cx, |this, cx| this.load_prompt(prompt_id, true, cx))
save.await?; })
this.update(&mut cx, |this, model, cx| { .detach_and_log_err(cx);
this.load_prompt(prompt_id, true, cx)
})
})
.detach_and_log_err(cx);
} }
pub fn save_prompt(&mut self, prompt_id: PromptId, model: &Model<Self>, cx: &mut AppContext) { pub fn save_prompt(&mut self, prompt_id: PromptId, cx: &mut ViewContext<Self>) {
const SAVE_THROTTLE: Duration = Duration::from_millis(500); const SAVE_THROTTLE: Duration = Duration::from_millis(500);
if prompt_id.is_built_in() { if prompt_id.is_built_in() {
@@ -423,7 +390,7 @@ impl PromptLibrary {
let prompt_metadata = self.store.metadata(prompt_id).unwrap(); let prompt_metadata = self.store.metadata(prompt_id).unwrap();
let prompt_editor = self.prompt_editors.get_mut(&prompt_id).unwrap(); let prompt_editor = self.prompt_editors.get_mut(&prompt_id).unwrap();
let title = prompt_editor.title_editor.read(cx).text(cx); let title = prompt_editor.title_editor.read(cx).text(cx);
let body = prompt_editor.body_editor.update(cx, |editor, model, cx| { let body = prompt_editor.body_editor.update(cx, |editor, cx| {
editor editor
.buffer() .buffer()
.read(cx) .read(cx)
@@ -439,10 +406,10 @@ impl PromptLibrary {
prompt_editor.next_title_and_body_to_save = Some((title, body)); prompt_editor.next_title_and_body_to_save = Some((title, body));
if prompt_editor.pending_save.is_none() { if prompt_editor.pending_save.is_none() {
prompt_editor.pending_save = Some(model.spawn(cx, |this, mut cx| { prompt_editor.pending_save = Some(cx.spawn(|this, mut cx| {
async move { async move {
loop { loop {
let title_and_body = this.update(&mut cx, |this, _, _| { let title_and_body = this.update(&mut cx, |this, _| {
this.prompt_editors this.prompt_editors
.get_mut(&prompt_id)? .get_mut(&prompt_id)?
.next_title_and_body_to_save .next_title_and_body_to_save
@@ -459,10 +426,9 @@ impl PromptLibrary {
.save(prompt_id, title, prompt_metadata.default, body) .save(prompt_id, title, prompt_metadata.default, body)
.await .await
.log_err(); .log_err();
this.update(&mut cx, |this, model, cx| { this.update(&mut cx, |this, cx| {
this.picker this.picker.update(cx, |picker, cx| picker.refresh(cx));
.update(cx, |picker, model, cx| picker.refresh(cx)); cx.notify();
model.notify(cx);
})?; })?;
executor.timer(SAVE_THROTTLE).await; executor.timer(SAVE_THROTTLE).await;
@@ -482,101 +448,84 @@ impl PromptLibrary {
} }
} }
pub fn delete_active_prompt(&mut self, model: &Model<Self>, cx: &mut AppContext) { pub fn delete_active_prompt(&mut self, cx: &mut ViewContext<Self>) {
if let Some(active_prompt_id) = self.active_prompt_id { if let Some(active_prompt_id) = self.active_prompt_id {
self.delete_prompt(active_prompt_id, model, cx); self.delete_prompt(active_prompt_id, cx);
} }
} }
pub fn duplicate_active_prompt(&mut self, model: &Model<Self>, cx: &mut AppContext) { pub fn duplicate_active_prompt(&mut self, cx: &mut ViewContext<Self>) {
if let Some(active_prompt_id) = self.active_prompt_id { if let Some(active_prompt_id) = self.active_prompt_id {
self.duplicate_prompt(active_prompt_id, model, cx); self.duplicate_prompt(active_prompt_id, cx);
} }
} }
pub fn toggle_default_for_active_prompt(&mut self, model: &Model<Self>, cx: &mut AppContext) { pub fn toggle_default_for_active_prompt(&mut self, cx: &mut ViewContext<Self>) {
if let Some(active_prompt_id) = self.active_prompt_id { if let Some(active_prompt_id) = self.active_prompt_id {
self.toggle_default_for_prompt(active_prompt_id, model, cx); self.toggle_default_for_prompt(active_prompt_id, cx);
} }
} }
pub fn toggle_default_for_prompt( pub fn toggle_default_for_prompt(&mut self, prompt_id: PromptId, cx: &mut ViewContext<Self>) {
&mut self,
prompt_id: PromptId,
model: &Model<Self>,
cx: &mut AppContext,
) {
if let Some(prompt_metadata) = self.store.metadata(prompt_id) { if let Some(prompt_metadata) = self.store.metadata(prompt_id) {
self.store self.store
.save_metadata(prompt_id, prompt_metadata.title, !prompt_metadata.default) .save_metadata(prompt_id, prompt_metadata.title, !prompt_metadata.default)
.detach_and_log_err(cx); .detach_and_log_err(cx);
self.picker self.picker.update(cx, |picker, cx| picker.refresh(cx));
.update(cx, |picker, model, cx| picker.refresh(cx)); cx.notify();
model.notify(cx);
} }
} }
pub fn load_prompt( pub fn load_prompt(&mut self, prompt_id: PromptId, focus: bool, cx: &mut ViewContext<Self>) {
&mut self,
prompt_id: PromptId,
focus: bool,
model: &Model<Self>,
cx: &mut AppContext,
) {
if let Some(prompt_editor) = self.prompt_editors.get(&prompt_id) { if let Some(prompt_editor) = self.prompt_editors.get(&prompt_id) {
if focus { if focus {
prompt_editor prompt_editor
.body_editor .body_editor
.update(cx, |editor, model, cx| editor.focus(window, cx)); .update(cx, |editor, cx| editor.focus(cx));
} }
self.set_active_prompt(Some(prompt_id), model, cx); self.set_active_prompt(Some(prompt_id), cx);
} else if let Some(prompt_metadata) = self.store.metadata(prompt_id) { } else if let Some(prompt_metadata) = self.store.metadata(prompt_id) {
let language_registry = self.language_registry.clone(); let language_registry = self.language_registry.clone();
let prompt = self.store.load(prompt_id); let prompt = self.store.load(prompt_id);
self.pending_load = model.spawn(cx, |this, mut cx| async move { self.pending_load = cx.spawn(|this, mut cx| async move {
let prompt = prompt.await; let prompt = prompt.await;
let markdown = language_registry.language_for_name("Markdown").await; let markdown = language_registry.language_for_name("Markdown").await;
this.update(&mut cx, |this, model, cx| match prompt { this.update(&mut cx, |this, cx| match prompt {
Ok(prompt) => { Ok(prompt) => {
let title_editor = cx.new_model(|model, cx| { let title_editor = cx.new_view(|cx| {
let mut editor = Editor::auto_width(model, cx); let mut editor = Editor::auto_width(cx);
editor.set_placeholder_text("Untitled", model, cx); editor.set_placeholder_text("Untitled", cx);
editor.set_text(prompt_metadata.title.unwrap_or_default(), model, cx); editor.set_text(prompt_metadata.title.unwrap_or_default(), cx);
if prompt_id.is_built_in() { if prompt_id.is_built_in() {
editor.set_read_only(true); editor.set_read_only(true);
editor.set_show_inline_completions(Some(false), model, cx); editor.set_show_inline_completions(Some(false), cx);
} }
editor editor
}); });
let body_editor = cx.new_model(|model, cx| { let body_editor = cx.new_view(|cx| {
// todo!: Remove this type annotation on cx let buffer = cx.new_model(|cx| {
let buffer = cx.new_model(|model, cx: &mut AppContext| { let mut buffer = Buffer::local(prompt, cx);
let mut buffer = Buffer::local(prompt, model, cx); buffer.set_language(markdown.log_err(), cx);
buffer.set_language(markdown.log_err(), model, cx);
buffer.set_language_registry(language_registry); buffer.set_language_registry(language_registry);
buffer buffer
}); });
let mut editor = Editor::for_buffer(buffer, None, model, cx); let mut editor = Editor::for_buffer(buffer, None, cx);
if prompt_id.is_built_in() { if prompt_id.is_built_in() {
editor.set_read_only(true); editor.set_read_only(true);
editor.set_show_inline_completions(Some(false), model, cx); editor.set_show_inline_completions(Some(false), cx);
} }
editor.set_soft_wrap_mode(SoftWrap::EditorWidth, model, cx); editor.set_soft_wrap_mode(SoftWrap::EditorWidth, cx);
editor.set_show_gutter(false, model, cx); editor.set_show_gutter(false, cx);
editor.set_show_wrap_guides(false, model, cx); editor.set_show_wrap_guides(false, cx);
editor.set_show_indent_guides(false, model, cx); editor.set_show_indent_guides(false, cx);
editor.set_use_modal_editing(false); editor.set_use_modal_editing(false);
editor.set_current_line_highlight(Some(CurrentLineHighlight::None)); editor.set_current_line_highlight(Some(CurrentLineHighlight::None));
editor.set_completion_provider(Some(Box::new( editor.set_completion_provider(Some(Box::new(
SlashCommandCompletionProvider::new( SlashCommandCompletionProvider::new(None, None),
Arc::new(SlashCommandWorkingSet::default()),
None,
None,
),
))); )));
if focus { if focus {
editor.focus(window, cx); editor.focus(cx);
} }
editor editor
}); });
@@ -613,14 +562,9 @@ impl PromptLibrary {
} }
} }
fn set_active_prompt( fn set_active_prompt(&mut self, prompt_id: Option<PromptId>, cx: &mut ViewContext<Self>) {
&mut self,
prompt_id: Option<PromptId>,
model: &Model<Self>,
cx: &mut AppContext,
) {
self.active_prompt_id = prompt_id; self.active_prompt_id = prompt_id;
self.picker.update(cx, |picker, model, cx| { self.picker.update(cx, |picker, cx| {
if let Some(prompt_id) = prompt_id { if let Some(prompt_id) = prompt_id {
if picker if picker
.delegate .delegate
@@ -640,13 +584,13 @@ impl PromptLibrary {
} }
} }
} else { } else {
picker.focus(window); picker.focus(cx);
} }
}); });
model.notify(cx); cx.notify();
} }
pub fn delete_prompt(&mut self, prompt_id: PromptId, model: &Model<Self>, cx: &mut AppContext) { pub fn delete_prompt(&mut self, prompt_id: PromptId, cx: &mut ViewContext<Self>) {
if let Some(metadata) = self.store.metadata(prompt_id) { if let Some(metadata) = self.store.metadata(prompt_id) {
let confirmation = cx.prompt( let confirmation = cx.prompt(
PromptLevel::Warning, PromptLevel::Warning,
@@ -658,32 +602,25 @@ impl PromptLibrary {
&["Delete", "Cancel"], &["Delete", "Cancel"],
); );
model cx.spawn(|this, mut cx| async move {
.spawn(cx, |this, mut cx| async move { if confirmation.await.ok() == Some(0) {
if confirmation.await.ok() == Some(0) { this.update(&mut cx, |this, cx| {
this.update(&mut cx, |this, model, cx| { if this.active_prompt_id == Some(prompt_id) {
if this.active_prompt_id == Some(prompt_id) { this.set_active_prompt(None, cx);
this.set_active_prompt(None, cx); }
} this.prompt_editors.remove(&prompt_id);
this.prompt_editors.remove(&prompt_id); this.store.delete(prompt_id).detach_and_log_err(cx);
this.store.delete(prompt_id).detach_and_log_err(cx); this.picker.update(cx, |picker, cx| picker.refresh(cx));
this.picker cx.notify();
.update(cx, |picker, model, cx| picker.refresh(cx)); })?;
model.notify(cx); }
})?; anyhow::Ok(())
} })
anyhow::Ok(()) .detach_and_log_err(cx);
})
.detach_and_log_err(cx);
} }
} }
pub fn duplicate_prompt( pub fn duplicate_prompt(&mut self, prompt_id: PromptId, cx: &mut ViewContext<Self>) {
&mut self,
prompt_id: PromptId,
model: &Model<Self>,
cx: &mut AppContext,
) {
if let Some(prompt) = self.prompt_editors.get(&prompt_id) { if let Some(prompt) = self.prompt_editors.get(&prompt_id) {
const DUPLICATE_SUFFIX: &str = " copy"; const DUPLICATE_SUFFIX: &str = " copy";
let title_to_duplicate = prompt.title_editor.read(cx).text(cx); let title_to_duplicate = prompt.title_editor.read(cx).text(cx);
@@ -713,39 +650,31 @@ impl PromptLibrary {
let save = self let save = self
.store .store
.save(new_id, Some(title.into()), false, body.into()); .save(new_id, Some(title.into()), false, body.into());
self.picker self.picker.update(cx, |picker, cx| picker.refresh(cx));
.update(cx, |picker, model, cx| picker.refresh(cx)); cx.spawn(|this, mut cx| async move {
model save.await?;
.spawn(cx, |this, mut cx| async move { this.update(&mut cx, |prompt_library, cx| {
save.await?; prompt_library.load_prompt(new_id, true, cx)
this.update(&mut cx, |prompt_library, cx| {
prompt_library.load_prompt(new_id, true, cx)
})
}) })
.detach_and_log_err(cx); })
.detach_and_log_err(cx);
} }
} }
fn focus_active_prompt(&mut self, _: &Tab, model: &Model<Self>, cx: &mut AppContext) { fn focus_active_prompt(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
if let Some(active_prompt) = self.active_prompt_id { if let Some(active_prompt) = self.active_prompt_id {
self.prompt_editors[&active_prompt] self.prompt_editors[&active_prompt]
.body_editor .body_editor
.update(cx, |editor, model, cx| editor.focus(window, cx)); .update(cx, |editor, cx| editor.focus(cx));
cx.stop_propagation(); cx.stop_propagation();
} }
} }
fn focus_picker(&mut self, _: &menu::Cancel, model: &Model<Self>, cx: &mut AppContext) { fn focus_picker(&mut self, _: &menu::Cancel, cx: &mut ViewContext<Self>) {
self.picker self.picker.update(cx, |picker, cx| picker.focus(cx));
.update(cx, |picker, model, cx| picker.focus(window));
} }
pub fn inline_assist( pub fn inline_assist(&mut self, action: &InlineAssist, cx: &mut ViewContext<Self>) {
&mut self,
action: &InlineAssist,
model: &Model<Self>,
cx: &mut AppContext,
) {
let Some(active_prompt_id) = self.active_prompt_id else { let Some(active_prompt_id) = self.active_prompt_id else {
cx.propagate(); cx.propagate();
return; return;
@@ -759,13 +688,13 @@ impl PromptLibrary {
let initial_prompt = action.prompt.clone(); let initial_prompt = action.prompt.clone();
if provider.is_authenticated(cx) { if provider.is_authenticated(cx) {
InlineAssistant::update_global(cx, |assistant, cx| { InlineAssistant::update_global(cx, |assistant, cx| {
assistant.assist(&prompt_editor, None, None, initial_prompt, window, cx) assistant.assist(&prompt_editor, None, None, initial_prompt, cx)
}) })
} else { } else {
for window in cx.windows() { for window in cx.windows() {
if let Some(workspace) = window.downcast::<Workspace>() { if let Some(workspace) = window.downcast::<Workspace>() {
let panel = workspace let panel = workspace
.update(cx, |workspace, model, cx| { .update(cx, |workspace, cx| {
cx.activate_window(); cx.activate_window();
workspace.focus_panel::<AssistantPanel>(cx) workspace.focus_panel::<AssistantPanel>(cx)
}) })
@@ -779,12 +708,7 @@ impl PromptLibrary {
} }
} }
fn move_down_from_title( fn move_down_from_title(&mut self, _: &editor::actions::MoveDown, cx: &mut ViewContext<Self>) {
&mut self,
_: &editor::actions::MoveDown,
model: &Model<Self>,
cx: &mut AppContext,
) {
if let Some(prompt_id) = self.active_prompt_id { if let Some(prompt_id) = self.active_prompt_id {
if let Some(prompt_editor) = self.prompt_editors.get(&prompt_id) { if let Some(prompt_editor) = self.prompt_editors.get(&prompt_id) {
cx.focus_view(&prompt_editor.body_editor); cx.focus_view(&prompt_editor.body_editor);
@@ -792,12 +716,7 @@ impl PromptLibrary {
} }
} }
fn move_up_from_body( fn move_up_from_body(&mut self, _: &editor::actions::MoveUp, cx: &mut ViewContext<Self>) {
&mut self,
_: &editor::actions::MoveUp,
model: &Model<Self>,
cx: &mut AppContext,
) {
if let Some(prompt_id) = self.active_prompt_id { if let Some(prompt_id) = self.active_prompt_id {
if let Some(prompt_editor) = self.prompt_editors.get(&prompt_id) { if let Some(prompt_editor) = self.prompt_editors.get(&prompt_id) {
cx.focus_view(&prompt_editor.title_editor); cx.focus_view(&prompt_editor.title_editor);
@@ -808,19 +727,18 @@ impl PromptLibrary {
fn handle_prompt_title_editor_event( fn handle_prompt_title_editor_event(
&mut self, &mut self,
prompt_id: PromptId, prompt_id: PromptId,
title_editor: Model<Editor>, title_editor: View<Editor>,
event: &EditorEvent, event: &EditorEvent,
model: &Model<Self>, cx: &mut ViewContext<Self>,
cx: &mut AppContext,
) { ) {
match event { match event {
EditorEvent::BufferEdited => { EditorEvent::BufferEdited => {
self.save_prompt(prompt_id, model, cx); self.save_prompt(prompt_id, cx);
self.count_tokens(prompt_id, model, cx); self.count_tokens(prompt_id, cx);
} }
EditorEvent::Blurred => { EditorEvent::Blurred => {
title_editor.update(cx, |title_editor, model, cx| { title_editor.update(cx, |title_editor, cx| {
title_editor.change_selections(None, model, cx, |selections| { title_editor.change_selections(None, cx, |selections| {
let cursor = selections.oldest_anchor().head(); let cursor = selections.oldest_anchor().head();
selections.select_anchor_ranges([cursor..cursor]); selections.select_anchor_ranges([cursor..cursor]);
}); });
@@ -833,19 +751,18 @@ impl PromptLibrary {
fn handle_prompt_body_editor_event( fn handle_prompt_body_editor_event(
&mut self, &mut self,
prompt_id: PromptId, prompt_id: PromptId,
body_editor: Model<Editor>, body_editor: View<Editor>,
event: &EditorEvent, event: &EditorEvent,
model: &Model<Self>, cx: &mut ViewContext<Self>,
cx: &mut AppContext,
) { ) {
match event { match event {
EditorEvent::BufferEdited => { EditorEvent::BufferEdited => {
self.save_prompt(prompt_id, model, cx); self.save_prompt(prompt_id, cx);
self.count_tokens(prompt_id, model, cx); self.count_tokens(prompt_id, cx);
} }
EditorEvent::Blurred => { EditorEvent::Blurred => {
body_editor.update(cx, |body_editor, model, cx| { body_editor.update(cx, |body_editor, cx| {
body_editor.change_selections(None, model, cx, |selections| { body_editor.change_selections(None, cx, |selections| {
let cursor = selections.oldest_anchor().head(); let cursor = selections.oldest_anchor().head();
selections.select_anchor_ranges([cursor..cursor]); selections.select_anchor_ranges([cursor..cursor]);
}); });
@@ -855,7 +772,7 @@ impl PromptLibrary {
} }
} }
fn count_tokens(&mut self, prompt_id: PromptId, model: &Model<Self>, cx: &mut AppContext) { fn count_tokens(&mut self, prompt_id: PromptId, cx: &mut ViewContext<Self>) {
let Some(model) = LanguageModelRegistry::read_global(cx).active_model() else { let Some(model) = LanguageModelRegistry::read_global(cx).active_model() else {
return; return;
}; };
@@ -863,7 +780,7 @@ impl PromptLibrary {
let editor = &prompt.body_editor.read(cx); let editor = &prompt.body_editor.read(cx);
let buffer = &editor.buffer().read(cx).as_singleton().unwrap().read(cx); let buffer = &editor.buffer().read(cx).as_singleton().unwrap().read(cx);
let body = buffer.as_rope().clone(); let body = buffer.as_rope().clone();
prompt.pending_token_count = model.spawn(cx, |this, mut cx| { prompt.pending_token_count = cx.spawn(|this, mut cx| {
async move { async move {
const DEBOUNCE_TIMEOUT: Duration = Duration::from_secs(1); const DEBOUNCE_TIMEOUT: Duration = Duration::from_secs(1);
@@ -886,10 +803,10 @@ impl PromptLibrary {
})? })?
.await?; .await?;
this.update(&mut cx, |this, model, cx| { this.update(&mut cx, |this, cx| {
let prompt_editor = this.prompt_editors.get_mut(&prompt_id).unwrap(); let prompt_editor = this.prompt_editors.get_mut(&prompt_id).unwrap();
prompt_editor.token_count = Some(token_count); prompt_editor.token_count = Some(token_count);
model.notify(cx); cx.notify();
}) })
} }
.log_err() .log_err()
@@ -897,7 +814,7 @@ impl PromptLibrary {
} }
} }
fn render_prompt_list(&mut self, model: &Model<Self>, cx: &mut AppContext) -> impl IntoElement { fn render_prompt_list(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
v_flex() v_flex()
.id("prompt-list") .id("prompt-list")
.capture_action(cx.listener(Self::focus_active_prompt)) .capture_action(cx.listener(Self::focus_active_prompt))
@@ -908,7 +825,7 @@ impl PromptLibrary {
.overflow_x_hidden() .overflow_x_hidden()
.child( .child(
h_flex() h_flex()
.p(DynamicSpacing::Base04.rems(cx)) .p(Spacing::Small.rems(cx))
.h_9() .h_9()
.w_full() .w_full()
.flex_none() .flex_none()
@@ -917,9 +834,7 @@ impl PromptLibrary {
IconButton::new("new-prompt", IconName::Plus) IconButton::new("new-prompt", IconName::Plus)
.style(ButtonStyle::Transparent) .style(ButtonStyle::Transparent)
.shape(IconButtonShape::Square) .shape(IconButtonShape::Square)
.tooltip(move |window, cx| { .tooltip(move |cx| Tooltip::for_action("New Prompt", &NewPrompt, cx))
Tooltip::for_action("New Prompt", &NewPrompt, window, cx)
})
.on_click(|_, cx| { .on_click(|_, cx| {
cx.dispatch_action(Box::new(NewPrompt)); cx.dispatch_action(Box::new(NewPrompt));
}), }),
@@ -928,11 +843,7 @@ impl PromptLibrary {
.child(div().flex_grow().child(self.picker.clone())) .child(div().flex_grow().child(self.picker.clone()))
} }
fn render_active_prompt( fn render_active_prompt(&mut self, cx: &mut ViewContext<PromptLibrary>) -> gpui::Stateful<Div> {
&mut self,
model: &Model<PromptLibrary>,
cx: &mut AppContext,
) -> gpui::Stateful<Div> {
div() div()
.w_2_3() .w_2_3()
.h_full() .h_full()
@@ -955,17 +866,17 @@ impl PromptLibrary {
.size_full() .size_full()
.relative() .relative()
.overflow_hidden() .overflow_hidden()
.pl(DynamicSpacing::Base16.rems(cx)) .pl(Spacing::XXLarge.rems(cx))
.pt(DynamicSpacing::Base08.rems(cx)) .pt(Spacing::Large.rems(cx))
.on_click(model.listener(move |_, _, model, window, cx| { .on_click(cx.listener(move |_, _, cx| {
cx.focus(&focus_handle); cx.focus(&focus_handle);
})) }))
.child( .child(
h_flex() h_flex()
.group("active-editor-header") .group("active-editor-header")
.pr(DynamicSpacing::Base16.rems(cx)) .pr(Spacing::XXLarge.rems(cx))
.pt(DynamicSpacing::Base02.rems(cx)) .pt(Spacing::XSmall.rems(cx))
.pb(DynamicSpacing::Base08.rems(cx)) .pb(Spacing::Large.rems(cx))
.justify_between() .justify_between()
.child( .child(
h_flex().gap_1().child( h_flex().gap_1().child(
@@ -1011,7 +922,7 @@ impl PromptLibrary {
syntax: cx.theme().syntax().clone(), syntax: cx.theme().syntax().clone(),
status: cx.theme().status().clone(), status: cx.theme().status().clone(),
inlay_hints_style: inlay_hints_style:
editor::make_inlay_hints_style(model, cx), editor::make_inlay_hints_style(cx),
suggestions_style: HighlightStyle { suggestions_style: HighlightStyle {
color: Some(cx.theme().status().predictive), color: Some(cx.theme().status().predictive),
..HighlightStyle::default() ..HighlightStyle::default()
@@ -1027,13 +938,13 @@ impl PromptLibrary {
.child( .child(
h_flex() h_flex()
.h_full() .h_full()
.gap(DynamicSpacing::Base16.rems(cx)) .gap(Spacing::XXLarge.rems(cx))
.child(div()), .child(div()),
) )
.child( .child(
h_flex() h_flex()
.h_full() .h_full()
.gap(DynamicSpacing::Base16.rems(cx)) .gap(Spacing::XXLarge.rems(cx))
.children(prompt_editor.token_count.map( .children(prompt_editor.token_count.map(
|token_count| { |token_count| {
let token_count: SharedString = let token_count: SharedString =
@@ -1043,7 +954,7 @@ impl PromptLibrary {
h_flex() h_flex()
.id("token_count") .id("token_count")
.tooltip(move |window, cx| { .tooltip(move |cx| {
let token_count = let token_count =
token_count.clone(); token_count.clone();
@@ -1062,7 +973,6 @@ impl PromptLibrary {
.0) .0)
.unwrap_or_default() .unwrap_or_default()
), ),
model,
cx, cx,
) )
}) })
@@ -1082,12 +992,11 @@ impl PromptLibrary {
Icon::new(IconName::FileLock) Icon::new(IconName::FileLock)
.color(Color::Muted), .color(Color::Muted),
) )
.tooltip(move |window, cx| { .tooltip(move |cx| {
Tooltip::with_meta( Tooltip::with_meta(
"Built-in prompt", "Built-in prompt",
None, None,
BUILT_IN_TOOLTIP_TEXT, BUILT_IN_TOOLTIP_TEXT,
model,
cx, cx,
) )
}) })
@@ -1101,11 +1010,10 @@ impl PromptLibrary {
.style(ButtonStyle::Transparent) .style(ButtonStyle::Transparent)
.shape(IconButtonShape::Square) .shape(IconButtonShape::Square)
.size(ButtonSize::Large) .size(ButtonSize::Large)
.tooltip(move |window, cx| { .tooltip(move |cx| {
Tooltip::for_action( Tooltip::for_action(
"Delete Prompt", "Delete Prompt",
&DeletePrompt, &DeletePrompt,
model,
cx, cx,
) )
}) })
@@ -1123,11 +1031,10 @@ impl PromptLibrary {
.style(ButtonStyle::Transparent) .style(ButtonStyle::Transparent)
.shape(IconButtonShape::Square) .shape(IconButtonShape::Square)
.size(ButtonSize::Large) .size(ButtonSize::Large)
.tooltip(move |window, cx| { .tooltip(move |cx| {
Tooltip::for_action( Tooltip::for_action(
"Duplicate Prompt", "Duplicate Prompt",
&DuplicatePrompt, &DuplicatePrompt,
model,
cx, cx,
) )
}) })
@@ -1152,7 +1059,7 @@ impl PromptLibrary {
}) })
.shape(IconButtonShape::Square) .shape(IconButtonShape::Square)
.size(ButtonSize::Large) .size(ButtonSize::Large)
.tooltip(move |window, cx| { .tooltip(move |cx| {
Tooltip::text( Tooltip::text(
if prompt_metadata.default { if prompt_metadata.default {
"Remove from Default Prompt" "Remove from Default Prompt"
@@ -1186,13 +1093,8 @@ impl PromptLibrary {
} }
impl Render for PromptLibrary { impl Render for PromptLibrary {
fn render( fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
&mut self, let ui_font = theme::setup_ui_font(cx);
model: &Model<Self>,
window: &mut gpui::Window,
cx: &mut AppContext,
) -> impl IntoElement {
let ui_font = theme::setup_ui_font(window, cx);
let theme = cx.theme().clone(); let theme = cx.theme().clone();
h_flex() h_flex()
@@ -1208,7 +1110,7 @@ impl Render for PromptLibrary {
.overflow_hidden() .overflow_hidden()
.font(ui_font) .font(ui_font)
.text_color(theme.colors().text) .text_color(theme.colors().text)
.child(self.render_prompt_list(model, cx)) .child(self.render_prompt_list(cx))
.map(|el| { .map(|el| {
if self.store.prompt_count() == 0 { if self.store.prompt_count() == 0 {
el.child( el.child(
@@ -1244,7 +1146,7 @@ impl Render for PromptLibrary {
Button::new("create-prompt", "New Prompt") Button::new("create-prompt", "New Prompt")
.full_width() .full_width()
.key_binding(KeyBinding::for_action( .key_binding(KeyBinding::for_action(
&NewPrompt, window, cx, &NewPrompt, cx,
)) ))
.on_click(|_, cx| { .on_click(|_, cx| {
cx.dispatch_action(NewPrompt.boxed_clone()) cx.dispatch_action(NewPrompt.boxed_clone())
@@ -1255,7 +1157,7 @@ impl Render for PromptLibrary {
), ),
) )
} else { } else {
el.child(self.render_active_prompt(model, cx)) el.child(self.render_active_prompt(cx))
} }
}) })
} }

View File

@@ -149,7 +149,7 @@ impl PromptBuilder {
if file_path.to_string_lossy().ends_with(".hbs") { if file_path.to_string_lossy().ends_with(".hbs") {
if let Ok(content) = params.fs.load(&file_path).await { if let Ok(content) = params.fs.load(&file_path).await {
let file_name = file_path.file_stem().unwrap().to_string_lossy(); let file_name = file_path.file_stem().unwrap().to_string_lossy();
log::debug!("Registering prompt template override: {}", file_name); log::info!("Registering prompt template override: {}", file_name);
handlebars.lock().register_template_string(&file_name, content).log_err(); handlebars.lock().register_template_string(&file_name, content).log_err();
} }
} }
@@ -194,7 +194,7 @@ impl PromptBuilder {
for path in Assets.list("prompts")? { for path in Assets.list("prompts")? {
if let Some(id) = path.split('/').last().and_then(|s| s.strip_suffix(".hbs")) { if let Some(id) = path.split('/').last().and_then(|s| s.strip_suffix(".hbs")) {
if let Some(prompt) = Assets.load(path.as_ref()).log_err().flatten() { if let Some(prompt) = Assets.load(path.as_ref()).log_err().flatten() {
log::debug!("Registering built-in prompt template: {}", id); log::info!("Registering built-in prompt template: {}", id);
let prompt = String::from_utf8_lossy(prompt.as_ref()); let prompt = String::from_utf8_lossy(prompt.as_ref());
handlebars.register_template_string(id, LineEnding::normalize_cow(prompt))? handlebars.register_template_string(id, LineEnding::normalize_cow(prompt))?
} }
@@ -204,7 +204,7 @@ impl PromptBuilder {
Ok(()) Ok(())
} }
pub fn generate_inline_transformation_prompt( pub fn generate_content_prompt(
&self, &self,
user_prompt: String, user_prompt: String,
language_name: Option<&LanguageName>, language_name: Option<&LanguageName>,
@@ -310,8 +310,8 @@ impl PromptBuilder {
.render("terminal_assistant_prompt", &context) .render("terminal_assistant_prompt", &context)
} }
pub fn generate_suggest_edits_prompt(&self) -> Result<String, RenderError> { pub fn generate_workflow_prompt(&self) -> Result<String, RenderError> {
self.handlebars.lock().render("suggest_edits", &()) self.handlebars.lock().render("edit_workflow", &())
} }
pub fn generate_project_slash_command_prompt( pub fn generate_project_slash_command_prompt(

View File

@@ -1,11 +1,10 @@
use crate::assistant_panel::ContextEditor; use crate::assistant_panel::ContextEditor;
use crate::SlashCommandWorkingSet;
use anyhow::Result; use anyhow::Result;
use assistant_slash_command::AfterCompletion; use assistant_slash_command::AfterCompletion;
pub use assistant_slash_command::{SlashCommand, SlashCommandOutput}; pub use assistant_slash_command::{SlashCommand, SlashCommandOutput, SlashCommandRegistry};
use editor::{CompletionProvider, Editor}; use editor::{CompletionProvider, Editor};
use fuzzy::{match_strings, StringMatchCandidate}; use fuzzy::{match_strings, StringMatchCandidate};
use gpui::{AppContext, AppContext, Model, Task, WeakView}; use gpui::{AppContext, Model, Task, ViewContext, WeakView, WindowContext};
use language::{Anchor, Buffer, CodeLabel, Documentation, HighlightId, LanguageServerId, ToPoint}; use language::{Anchor, Buffer, CodeLabel, Documentation, HighlightId, LanguageServerId, ToPoint};
use parking_lot::{Mutex, RwLock}; use parking_lot::{Mutex, RwLock};
use project::CompletionIntent; use project::CompletionIntent;
@@ -32,17 +31,15 @@ pub mod now_command;
pub mod project_command; pub mod project_command;
pub mod prompt_command; pub mod prompt_command;
pub mod search_command; pub mod search_command;
pub mod selection_command;
pub mod streaming_example_command;
pub mod symbols_command; pub mod symbols_command;
pub mod tab_command; pub mod tab_command;
pub mod terminal_command; pub mod terminal_command;
pub mod workflow_command;
pub(crate) struct SlashCommandCompletionProvider { pub(crate) struct SlashCommandCompletionProvider {
cancel_flag: Mutex<Arc<AtomicBool>>, cancel_flag: Mutex<Arc<AtomicBool>>,
slash_commands: Arc<SlashCommandWorkingSet>, editor: Option<WeakView<ContextEditor>>,
editor: Option<WeakModel<ContextEditor>>, workspace: Option<WeakView<Workspace>>,
workspace: Option<WeakModel<Workspace>>,
} }
pub(crate) struct SlashCommandLine { pub(crate) struct SlashCommandLine {
@@ -54,13 +51,11 @@ pub(crate) struct SlashCommandLine {
impl SlashCommandCompletionProvider { impl SlashCommandCompletionProvider {
pub fn new( pub fn new(
slash_commands: Arc<SlashCommandWorkingSet>, editor: Option<WeakView<ContextEditor>>,
editor: Option<WeakModel<ContextEditor>>, workspace: Option<WeakView<Workspace>>,
workspace: Option<WeakModel<Workspace>>,
) -> Self { ) -> Self {
Self { Self {
cancel_flag: Mutex::new(Arc::new(AtomicBool::new(false))), cancel_flag: Mutex::new(Arc::new(AtomicBool::new(false))),
slash_commands,
editor, editor,
workspace, workspace,
} }
@@ -71,12 +66,11 @@ impl SlashCommandCompletionProvider {
command_name: &str, command_name: &str,
command_range: Range<Anchor>, command_range: Range<Anchor>,
name_range: Range<Anchor>, name_range: Range<Anchor>,
window: &mut gpui::Window, cx: &mut WindowContext,
cx: &mut gpui::AppContext,
) -> Task<Result<Vec<project::Completion>>> { ) -> Task<Result<Vec<project::Completion>>> {
let slash_commands = self.slash_commands.clone(); let commands = SlashCommandRegistry::global(cx);
let candidates = slash_commands let candidates = commands
.command_names(cx) .command_names()
.into_iter() .into_iter()
.enumerate() .enumerate()
.map(|(ix, def)| StringMatchCandidate { .map(|(ix, def)| StringMatchCandidate {
@@ -103,7 +97,7 @@ impl SlashCommandCompletionProvider {
matches matches
.into_iter() .into_iter()
.filter_map(|mat| { .filter_map(|mat| {
let command = slash_commands.command(&mat.string, cx)?; let command = commands.command(&mat.string)?;
let mut new_text = mat.string.clone(); let mut new_text = mat.string.clone();
let requires_argument = command.requires_argument(); let requires_argument = command.requires_argument();
let accepts_arguments = command.accepts_arguments(); let accepts_arguments = command.accepts_arguments();
@@ -121,17 +115,18 @@ impl SlashCommandCompletionProvider {
let editor = editor.clone(); let editor = editor.clone();
let workspace = workspace.clone(); let workspace = workspace.clone();
Arc::new( Arc::new(
move |intent: CompletionIntent, window: &mut gpui::Window, cx: &mut gpui::AppContext| { move |intent: CompletionIntent, cx: &mut WindowContext| {
if !requires_argument if !requires_argument
&& (!accepts_arguments || intent.is_complete()) && (!accepts_arguments || intent.is_complete())
{ {
editor editor
.update(cx, |editor, model, cx| { .update(cx, |editor, cx| {
editor.run_command( editor.run_command(
command_range.clone(), command_range.clone(),
&command_name, &command_name,
&[], &[],
true, true,
false,
workspace.clone(), workspace.clone(),
cx, cx,
); );
@@ -166,14 +161,14 @@ impl SlashCommandCompletionProvider {
command_range: Range<Anchor>, command_range: Range<Anchor>,
argument_range: Range<Anchor>, argument_range: Range<Anchor>,
last_argument_range: Range<Anchor>, last_argument_range: Range<Anchor>,
window: &mut gpui::Window, cx: &mut WindowContext,
cx: &mut gpui::AppContext,
) -> Task<Result<Vec<project::Completion>>> { ) -> Task<Result<Vec<project::Completion>>> {
let new_cancel_flag = Arc::new(AtomicBool::new(false)); let new_cancel_flag = Arc::new(AtomicBool::new(false));
let mut flag = self.cancel_flag.lock(); let mut flag = self.cancel_flag.lock();
flag.store(true, SeqCst); flag.store(true, SeqCst);
*flag = new_cancel_flag.clone(); *flag = new_cancel_flag.clone();
if let Some(command) = self.slash_commands.command(command_name, cx) { let commands = SlashCommandRegistry::global(cx);
if let Some(command) = commands.command(command_name) {
let completions = command.complete_argument( let completions = command.complete_argument(
arguments, arguments,
new_cancel_flag.clone(), new_cancel_flag.clone(),
@@ -205,17 +200,18 @@ impl SlashCommandCompletionProvider {
let command_range = command_range.clone(); let command_range = command_range.clone();
let command_name = command_name.clone(); let command_name = command_name.clone();
move |intent: CompletionIntent, window: &mut gpui::Window, cx: &mut gpui::AppContext| { move |intent: CompletionIntent, cx: &mut WindowContext| {
if new_argument.after_completion.run() if new_argument.after_completion.run()
|| intent.is_complete() || intent.is_complete()
{ {
editor editor
.update(cx, |editor, model, cx| { .update(cx, |editor, cx| {
editor.run_command( editor.run_command(
command_range.clone(), command_range.clone(),
&command_name, &command_name,
&completed_arguments, &completed_arguments,
true, true,
false,
workspace.clone(), workspace.clone(),
cx, cx,
); );
@@ -262,11 +258,10 @@ impl CompletionProvider for SlashCommandCompletionProvider {
buffer: &Model<Buffer>, buffer: &Model<Buffer>,
buffer_position: Anchor, buffer_position: Anchor,
_: editor::CompletionContext, _: editor::CompletionContext,
model: &Model<Editor>, cx: &mut ViewContext<Editor>,
cx: &mut AppContext,
) -> Task<Result<Vec<project::Completion>>> { ) -> Task<Result<Vec<project::Completion>>> {
let Some((name, arguments, command_range, last_argument_range)) = let Some((name, arguments, command_range, last_argument_range)) =
buffer.update(cx, |buffer, model, _cx| { buffer.update(cx, |buffer, _cx| {
let position = buffer_position.to_point(buffer); let position = buffer_position.to_point(buffer);
let line_start = Point::new(position.row, 0); let line_start = Point::new(position.row, 0);
let mut lines = buffer.text_for_range(line_start..position).lines(); let mut lines = buffer.text_for_range(line_start..position).lines();
@@ -321,7 +316,7 @@ impl CompletionProvider for SlashCommandCompletionProvider {
cx, cx,
) )
} else { } else {
self.complete_command_name(&name, command_range, last_argument_range, model, cx) self.complete_command_name(&name, command_range, last_argument_range, cx)
} }
} }
@@ -330,8 +325,7 @@ impl CompletionProvider for SlashCommandCompletionProvider {
_: Model<Buffer>, _: Model<Buffer>,
_: Vec<usize>, _: Vec<usize>,
_: Arc<RwLock<Box<[project::Completion]>>>, _: Arc<RwLock<Box<[project::Completion]>>>,
_: &Model<Editor>, _: &mut ViewContext<Editor>,
_: &mut AppContext,
) -> Task<Result<bool>> { ) -> Task<Result<bool>> {
Task::ready(Ok(true)) Task::ready(Ok(true))
} }
@@ -341,8 +335,7 @@ impl CompletionProvider for SlashCommandCompletionProvider {
_: Model<Buffer>, _: Model<Buffer>,
_: project::Completion, _: project::Completion,
_: bool, _: bool,
_: &Model<Editor>, _: &mut ViewContext<Editor>,
_: &mut AppContext,
) -> Task<Result<Option<language::Transaction>>> { ) -> Task<Result<Option<language::Transaction>>> {
Task::ready(Ok(None)) Task::ready(Ok(None))
} }
@@ -353,8 +346,7 @@ impl CompletionProvider for SlashCommandCompletionProvider {
position: language::Anchor, position: language::Anchor,
_text: &str, _text: &str,
_trigger_in_words: bool, _trigger_in_words: bool,
model: &Model<Editor>, cx: &mut ViewContext<Editor>,
cx: &mut AppContext,
) -> bool { ) -> bool {
let buffer = buffer.read(cx); let buffer = buffer.read(cx);
let position = position.to_point(buffer); let position = position.to_point(buffer);

View File

@@ -1,8 +1,7 @@
use super::create_label_for_command;
use super::{SlashCommand, SlashCommandOutput};
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use assistant_slash_command::{ use assistant_slash_command::{ArgumentCompletion, SlashCommandOutputSection};
ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,
SlashCommandResult,
};
use feature_flags::FeatureFlag; use feature_flags::FeatureFlag;
use futures::StreamExt; use futures::StreamExt;
use gpui::{AppContext, AsyncAppContext, Task, WeakView}; use gpui::{AppContext, AsyncAppContext, Task, WeakView};
@@ -14,12 +13,10 @@ use language_model::{
use semantic_index::{FileSummary, SemanticDb}; use semantic_index::{FileSummary, SemanticDb};
use smol::channel; use smol::channel;
use std::sync::{atomic::AtomicBool, Arc}; use std::sync::{atomic::AtomicBool, Arc};
use ui::{prelude::*, BorrowAppContext}; use ui::{BorrowAppContext, WindowContext};
use util::ResultExt; use util::ResultExt;
use workspace::Workspace; use workspace::Workspace;
use crate::slash_command::create_label_for_command;
pub struct AutoSlashCommandFeatureFlag; pub struct AutoSlashCommandFeatureFlag;
impl FeatureFlag for AutoSlashCommandFeatureFlag { impl FeatureFlag for AutoSlashCommandFeatureFlag {
@@ -37,10 +34,6 @@ impl SlashCommand for AutoCommand {
"Automatically infer what context to add".into() "Automatically infer what context to add".into()
} }
fn icon(&self) -> IconName {
IconName::Wand
}
fn menu_text(&self) -> String { fn menu_text(&self) -> String {
self.description() self.description()
} }
@@ -53,9 +46,8 @@ impl SlashCommand for AutoCommand {
self: Arc<Self>, self: Arc<Self>,
_arguments: &[String], _arguments: &[String],
_cancel: Arc<AtomicBool>, _cancel: Arc<AtomicBool>,
workspace: Option<WeakModel<Workspace>>, workspace: Option<WeakView<Workspace>>,
window: &mut gpui::Window, cx: &mut WindowContext,
cx: &mut gpui::AppContext,
) -> Task<Result<Vec<ArgumentCompletion>>> { ) -> Task<Result<Vec<ArgumentCompletion>>> {
// There's no autocomplete for a prompt, since it's arbitrary text. // There's no autocomplete for a prompt, since it's arbitrary text.
// However, we can use this opportunity to kick off a drain of the backlog. // However, we can use this opportunity to kick off a drain of the backlog.
@@ -77,7 +69,7 @@ impl SlashCommand for AutoCommand {
let cx: &mut AppContext = cx; let cx: &mut AppContext = cx;
cx.spawn(|cx: AsyncAppContext| async move { cx.spawn(|cx: gpui::AsyncAppContext| async move {
let task = project_index.read_with(&cx, |project_index, cx| { let task = project_index.read_with(&cx, |project_index, cx| {
project_index.flush_summary_backlogs(cx) project_index.flush_summary_backlogs(cx)
})?; })?;
@@ -97,11 +89,10 @@ impl SlashCommand for AutoCommand {
arguments: &[String], arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>], _context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: language::BufferSnapshot, _context_buffer: language::BufferSnapshot,
workspace: WeakModel<Workspace>, workspace: WeakView<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>, _delegate: Option<Arc<dyn LspAdapterDelegate>>,
window: &mut gpui::Window, cx: &mut WindowContext,
cx: &mut gpui::AppContext, ) -> Task<Result<SlashCommandOutput>> {
) -> Task<SlashCommandResult> {
let Some(workspace) = workspace.upgrade() else { let Some(workspace) = workspace.upgrade() else {
return Task::ready(Err(anyhow::anyhow!("workspace was dropped"))); return Task::ready(Err(anyhow::anyhow!("workspace was dropped")));
}; };
@@ -117,7 +108,7 @@ impl SlashCommand for AutoCommand {
return Task::ready(Err(anyhow!("no project indexer"))); return Task::ready(Err(anyhow!("no project indexer")));
}; };
let task = cx.spawn(|cx: AsyncAppContext| async move { let task = cx.spawn(|cx: gpui::AsyncWindowContext| async move {
let summaries = project_index let summaries = project_index
.read_with(&cx, |project_index, cx| project_index.all_summaries(cx))? .read_with(&cx, |project_index, cx| project_index.all_summaries(cx))?
.await?; .await?;
@@ -153,8 +144,7 @@ impl SlashCommand for AutoCommand {
text: prompt, text: prompt,
sections: Vec::new(), sections: Vec::new(),
run_commands_in_text: true, run_commands_in_text: true,
} })
.to_event_stream())
}) })
} }
} }

View File

@@ -1,8 +1,6 @@
use super::{SlashCommand, SlashCommandOutput};
use anyhow::{anyhow, Context, Result}; use anyhow::{anyhow, Context, Result};
use assistant_slash_command::{ use assistant_slash_command::{ArgumentCompletion, SlashCommandOutputSection};
ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,
SlashCommandResult,
};
use fs::Fs; use fs::Fs;
use gpui::{AppContext, Model, Task, WeakView}; use gpui::{AppContext, Model, Task, WeakView};
use language::{BufferSnapshot, LspAdapterDelegate}; use language::{BufferSnapshot, LspAdapterDelegate};
@@ -107,9 +105,8 @@ impl SlashCommand for CargoWorkspaceSlashCommand {
self: Arc<Self>, self: Arc<Self>,
_arguments: &[String], _arguments: &[String],
_cancel: Arc<AtomicBool>, _cancel: Arc<AtomicBool>,
_workspace: Option<WeakModel<Workspace>>, _workspace: Option<WeakView<Workspace>>,
_window: &mut gpui::Window, _cx: &mut WindowContext,
_cx: &mut gpui::AppContext,
) -> Task<Result<Vec<ArgumentCompletion>>> { ) -> Task<Result<Vec<ArgumentCompletion>>> {
Task::ready(Err(anyhow!("this command does not require argument"))) Task::ready(Err(anyhow!("this command does not require argument")))
} }
@@ -123,12 +120,11 @@ impl SlashCommand for CargoWorkspaceSlashCommand {
_arguments: &[String], _arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>], _context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot, _context_buffer: BufferSnapshot,
workspace: WeakModel<Workspace>, workspace: WeakView<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>, _delegate: Option<Arc<dyn LspAdapterDelegate>>,
window: &mut gpui::Window, cx: &mut WindowContext,
cx: &mut gpui::AppContext, ) -> Task<Result<SlashCommandOutput>> {
) -> Task<SlashCommandResult> { let output = workspace.update(cx, |workspace, cx| {
let output = workspace.update(cx, |workspace, model, cx| {
let project = workspace.project().clone(); let project = workspace.project().clone();
let fs = workspace.project().read(cx).fs().clone(); let fs = workspace.project().read(cx).fs().clone();
let path = Self::path_to_cargo_toml(project, cx); let path = Self::path_to_cargo_toml(project, cx);
@@ -149,8 +145,7 @@ impl SlashCommand for CargoWorkspaceSlashCommand {
metadata: None, metadata: None,
}], }],
run_commands_in_text: false, run_commands_in_text: false,
} })
.to_event_stream())
}) })
}); });
output.unwrap_or_else(|error| Task::ready(Err(error))) output.unwrap_or_else(|error| Task::ready(Err(error)))

View File

@@ -1,14 +1,15 @@
use super::create_label_for_command;
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use assistant_slash_command::{ use assistant_slash_command::{
AfterCompletion, ArgumentCompletion, SlashCommand, SlashCommandOutput, AfterCompletion, ArgumentCompletion, SlashCommand, SlashCommandOutput,
SlashCommandOutputSection, SlashCommandResult, SlashCommandOutputSection,
}; };
use collections::HashMap; use collections::HashMap;
use context_server::{ use context_servers::{
manager::{ContextServer, ContextServerManager}, manager::{ContextServer, ContextServerManager},
types::Prompt, types::Prompt,
}; };
use gpui::{AppContext, Model, Task, WeakView}; use gpui::{AppContext, Task, WeakView, WindowContext};
use language::{BufferSnapshot, CodeLabel, LspAdapterDelegate}; use language::{BufferSnapshot, CodeLabel, LspAdapterDelegate};
use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicBool;
use std::sync::Arc; use std::sync::Arc;
@@ -16,24 +17,16 @@ use text::LineEnding;
use ui::{IconName, SharedString}; use ui::{IconName, SharedString};
use workspace::Workspace; use workspace::Workspace;
use crate::slash_command::create_label_for_command;
pub struct ContextServerSlashCommand { pub struct ContextServerSlashCommand {
server_manager: Model<ContextServerManager>, server_id: String,
server_id: Arc<str>,
prompt: Prompt, prompt: Prompt,
} }
impl ContextServerSlashCommand { impl ContextServerSlashCommand {
pub fn new( pub fn new(server: &Arc<ContextServer>, prompt: Prompt) -> Self {
server_manager: Model<ContextServerManager>,
server: &Arc<ContextServer>,
prompt: Prompt,
) -> Self {
Self { Self {
server_id: server.id(), server_id: server.id.clone(),
prompt, prompt,
server_manager,
} }
} }
} }
@@ -77,33 +70,36 @@ impl SlashCommand for ContextServerSlashCommand {
self: Arc<Self>, self: Arc<Self>,
arguments: &[String], arguments: &[String],
_cancel: Arc<AtomicBool>, _cancel: Arc<AtomicBool>,
_workspace: Option<WeakModel<Workspace>>, _workspace: Option<WeakView<Workspace>>,
window: &mut gpui::Window, cx: &mut WindowContext,
cx: &mut gpui::AppContext,
) -> Task<Result<Vec<ArgumentCompletion>>> { ) -> Task<Result<Vec<ArgumentCompletion>>> {
let Ok((arg_name, arg_value)) = completion_argument(&self.prompt, arguments) else {
return Task::ready(Err(anyhow!("Failed to complete argument")));
};
let server_id = self.server_id.clone(); let server_id = self.server_id.clone();
let prompt_name = self.prompt.name.clone(); let prompt_name = self.prompt.name.clone();
let manager = ContextServerManager::global(cx);
let manager = manager.read(cx);
if let Some(server) = self.server_manager.read(cx).get_server(&server_id) { let (arg_name, arg_val) = match completion_argument(&self.prompt, arguments) {
Ok(tp) => tp,
Err(e) => {
return Task::ready(Err(e));
}
};
if let Some(server) = manager.get_server(&server_id) {
cx.foreground_executor().spawn(async move { cx.foreground_executor().spawn(async move {
let Some(protocol) = server.client() else { let Some(protocol) = server.client.read().clone() else {
return Err(anyhow!("Context server not initialized")); return Err(anyhow!("Context server not initialized"));
}; };
let completion_result = protocol let completion_result = protocol
.completion( .completion(
context_server::types::CompletionReference::Prompt( context_servers::types::CompletionReference::Prompt(
context_server::types::PromptReference { context_servers::types::PromptReference {
r#type: context_server::types::PromptReferenceType::Prompt, r#type: context_servers::types::PromptReferenceType::Prompt,
name: prompt_name, name: prompt_name,
}, },
), ),
arg_name, arg_name,
arg_value, arg_val,
) )
.await?; .await?;
@@ -129,11 +125,10 @@ impl SlashCommand for ContextServerSlashCommand {
arguments: &[String], arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>], _context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot, _context_buffer: BufferSnapshot,
_workspace: WeakModel<Workspace>, _workspace: WeakView<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>, _delegate: Option<Arc<dyn LspAdapterDelegate>>,
window: &mut gpui::Window, cx: &mut WindowContext,
cx: &mut gpui::AppContext, ) -> Task<Result<SlashCommandOutput>> {
) -> Task<SlashCommandResult> {
let server_id = self.server_id.clone(); let server_id = self.server_id.clone();
let prompt_name = self.prompt.name.clone(); let prompt_name = self.prompt.name.clone();
@@ -142,35 +137,15 @@ impl SlashCommand for ContextServerSlashCommand {
Err(e) => return Task::ready(Err(e)), Err(e) => return Task::ready(Err(e)),
}; };
let manager = self.server_manager.read(cx); let manager = ContextServerManager::global(cx);
let manager = manager.read(cx);
if let Some(server) = manager.get_server(&server_id) { if let Some(server) = manager.get_server(&server_id) {
cx.foreground_executor().spawn(async move { cx.foreground_executor().spawn(async move {
let Some(protocol) = server.client() else { let Some(protocol) = server.client.read().clone() else {
return Err(anyhow!("Context server not initialized")); return Err(anyhow!("Context server not initialized"));
}; };
let result = protocol.run_prompt(&prompt_name, prompt_args).await?; let result = protocol.run_prompt(&prompt_name, prompt_args).await?;
let mut prompt = result.prompt;
// Check that there are only user roles
if result
.messages
.iter()
.any(|msg| !matches!(msg.role, context_server::types::Role::User))
{
return Err(anyhow!(
"Prompt contains non-user roles, which is not supported"
));
}
// Extract text from user messages into a single prompt string
let mut prompt = result
.messages
.into_iter()
.filter_map(|msg| match msg.content {
context_server::types::MessageContent::Text { text, .. } => Some(text),
_ => None,
})
.collect::<Vec<String>>()
.join("\n\n");
// We must normalize the line endings here, since servers might return CR characters. // We must normalize the line endings here, since servers might return CR characters.
LineEnding::normalize(&mut prompt); LineEnding::normalize(&mut prompt);
@@ -188,8 +163,7 @@ impl SlashCommand for ContextServerSlashCommand {
}], }],
text: prompt, text: prompt,
run_commands_in_text: false, run_commands_in_text: false,
} })
.to_event_stream())
}) })
} else { } else {
Task::ready(Err(anyhow!("Context server not found"))) Task::ready(Err(anyhow!("Context server not found")))

View File

@@ -1,9 +1,7 @@
use super::{SlashCommand, SlashCommandOutput};
use crate::prompt_library::PromptStore; use crate::prompt_library::PromptStore;
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use assistant_slash_command::{ use assistant_slash_command::{ArgumentCompletion, SlashCommandOutputSection};
ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,
SlashCommandResult,
};
use gpui::{Task, WeakView}; use gpui::{Task, WeakView};
use language::{BufferSnapshot, LspAdapterDelegate}; use language::{BufferSnapshot, LspAdapterDelegate};
use std::{ use std::{
@@ -36,9 +34,8 @@ impl SlashCommand for DefaultSlashCommand {
self: Arc<Self>, self: Arc<Self>,
_arguments: &[String], _arguments: &[String],
_cancellation_flag: Arc<AtomicBool>, _cancellation_flag: Arc<AtomicBool>,
_workspace: Option<WeakModel<Workspace>>, _workspace: Option<WeakView<Workspace>>,
_window: &mut gpui::Window, _cx: &mut WindowContext,
_cx: &mut gpui::AppContext,
) -> Task<Result<Vec<ArgumentCompletion>>> { ) -> Task<Result<Vec<ArgumentCompletion>>> {
Task::ready(Err(anyhow!("this command does not require argument"))) Task::ready(Err(anyhow!("this command does not require argument")))
} }
@@ -48,10 +45,10 @@ impl SlashCommand for DefaultSlashCommand {
_arguments: &[String], _arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>], _context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot, _context_buffer: BufferSnapshot,
_workspace: WeakModel<Workspace>, _workspace: WeakView<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>, _delegate: Option<Arc<dyn LspAdapterDelegate>>,
window: &mut gpui::Window, cx: &mut gpui::AppContext, cx: &mut WindowContext,
) -> Task<SlashCommandResult> { ) -> Task<Result<SlashCommandOutput>> {
let store = PromptStore::global(cx); let store = PromptStore::global(cx);
cx.background_executor().spawn(async move { cx.background_executor().spawn(async move {
let store = store.await?; let store = store.await?;
@@ -70,10 +67,6 @@ impl SlashCommand for DefaultSlashCommand {
text.push('\n'); text.push('\n');
} }
if !text.ends_with('\n') {
text.push('\n');
}
Ok(SlashCommandOutput { Ok(SlashCommandOutput {
sections: vec![SlashCommandOutputSection { sections: vec![SlashCommandOutputSection {
range: 0..text.len(), range: 0..text.len(),
@@ -83,8 +76,7 @@ impl SlashCommand for DefaultSlashCommand {
}], }],
text, text,
run_commands_in_text: true, run_commands_in_text: true,
} })
.to_event_stream())
}) })
} }
} }

View File

@@ -1,16 +1,14 @@
use crate::slash_command::file_command::{FileCommandMetadata, FileSlashCommand}; use crate::slash_command::file_command::{FileCommandMetadata, FileSlashCommand};
use anyhow::{anyhow, Result}; use anyhow::Result;
use assistant_slash_command::{ use assistant_slash_command::{
ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection, ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,
SlashCommandResult,
}; };
use collections::HashSet; use collections::HashSet;
use futures::future; use futures::future;
use gpui::{Task, WeakView}; use gpui::{Task, WeakView, WindowContext};
use language::{BufferSnapshot, LspAdapterDelegate}; use language::{BufferSnapshot, LspAdapterDelegate};
use std::sync::{atomic::AtomicBool, Arc}; use std::sync::{atomic::AtomicBool, Arc};
use text::OffsetRangeExt; use text::OffsetRangeExt;
use ui::prelude::*;
use workspace::Workspace; use workspace::Workspace;
pub(crate) struct DeltaSlashCommand; pub(crate) struct DeltaSlashCommand;
@@ -28,10 +26,6 @@ impl SlashCommand for DeltaSlashCommand {
self.description() self.description()
} }
fn icon(&self) -> IconName {
IconName::Diff
}
fn requires_argument(&self) -> bool { fn requires_argument(&self) -> bool {
false false
} }
@@ -40,11 +34,10 @@ impl SlashCommand for DeltaSlashCommand {
self: Arc<Self>, self: Arc<Self>,
_arguments: &[String], _arguments: &[String],
_cancellation_flag: Arc<AtomicBool>, _cancellation_flag: Arc<AtomicBool>,
_workspace: Option<WeakModel<Workspace>>, _workspace: Option<WeakView<Workspace>>,
_window: &mut gpui::Window, _cx: &mut WindowContext,
_cx: &mut gpui::AppContext,
) -> Task<Result<Vec<ArgumentCompletion>>> { ) -> Task<Result<Vec<ArgumentCompletion>>> {
Task::ready(Err(anyhow!("this command does not require argument"))) unimplemented!()
} }
fn run( fn run(
@@ -52,15 +45,13 @@ impl SlashCommand for DeltaSlashCommand {
_arguments: &[String], _arguments: &[String],
context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>], context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
context_buffer: BufferSnapshot, context_buffer: BufferSnapshot,
workspace: WeakModel<Workspace>, workspace: WeakView<Workspace>,
delegate: Option<Arc<dyn LspAdapterDelegate>>, delegate: Option<Arc<dyn LspAdapterDelegate>>,
window: &mut gpui::Window, cx: &mut WindowContext,
cx: &mut gpui::AppContext, ) -> Task<Result<SlashCommandOutput>> {
) -> Task<SlashCommandResult> {
let mut paths = HashSet::default(); let mut paths = HashSet::default();
let mut file_command_old_outputs = Vec::new(); let mut file_command_old_outputs = Vec::new();
let mut file_command_new_outputs = Vec::new(); let mut file_command_new_outputs = Vec::new();
for section in context_slash_command_output_sections.iter().rev() { for section in context_slash_command_output_sections.iter().rev() {
if let Some(metadata) = section if let Some(metadata) = section
.metadata .metadata
@@ -79,7 +70,6 @@ impl SlashCommand for DeltaSlashCommand {
context_buffer.clone(), context_buffer.clone(),
workspace.clone(), workspace.clone(),
delegate.clone(), delegate.clone(),
model,
cx, cx,
)); ));
} }
@@ -88,7 +78,6 @@ impl SlashCommand for DeltaSlashCommand {
cx.background_executor().spawn(async move { cx.background_executor().spawn(async move {
let mut output = SlashCommandOutput::default(); let mut output = SlashCommandOutput::default();
let mut changes_detected = false;
let file_command_new_outputs = future::join_all(file_command_new_outputs).await; let file_command_new_outputs = future::join_all(file_command_new_outputs).await;
for (old_text, new_output) in file_command_old_outputs for (old_text, new_output) in file_command_old_outputs
@@ -96,33 +85,25 @@ impl SlashCommand for DeltaSlashCommand {
.zip(file_command_new_outputs) .zip(file_command_new_outputs)
{ {
if let Ok(new_output) = new_output { if let Ok(new_output) = new_output {
if let Ok(new_output) = SlashCommandOutput::from_event_stream(new_output).await if let Some(file_command_range) = new_output.sections.first() {
{ let new_text = &new_output.text[file_command_range.range.clone()];
if let Some(file_command_range) = new_output.sections.first() { if old_text.chars().ne(new_text.chars()) {
let new_text = &new_output.text[file_command_range.range.clone()]; output.sections.extend(new_output.sections.into_iter().map(
if old_text.chars().ne(new_text.chars()) { |section| SlashCommandOutputSection {
changes_detected = true; range: output.text.len() + section.range.start
output.sections.extend(new_output.sections.into_iter().map( ..output.text.len() + section.range.end,
|section| SlashCommandOutputSection { icon: section.icon,
range: output.text.len() + section.range.start label: section.label,
..output.text.len() + section.range.end, metadata: section.metadata,
icon: section.icon, },
label: section.label, ));
metadata: section.metadata, output.text.push_str(&new_output.text);
},
));
output.text.push_str(&new_output.text);
}
} }
} }
} }
} }
if !changes_detected { Ok(output)
return Err(anyhow!("no new changes detected"));
}
Ok(output.to_event_stream())
}) })
} }
} }

View File

@@ -1,8 +1,6 @@
use super::{create_label_for_command, SlashCommand, SlashCommandOutput};
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use assistant_slash_command::{ use assistant_slash_command::{ArgumentCompletion, SlashCommandOutputSection};
ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,
SlashCommandResult,
};
use fuzzy::{PathMatch, StringMatchCandidate}; use fuzzy::{PathMatch, StringMatchCandidate};
use gpui::{AppContext, Model, Task, View, WeakView}; use gpui::{AppContext, Model, Task, View, WeakView};
use language::{ use language::{
@@ -21,8 +19,6 @@ use util::paths::PathMatcher;
use util::ResultExt; use util::ResultExt;
use workspace::Workspace; use workspace::Workspace;
use crate::slash_command::create_label_for_command;
pub(crate) struct DiagnosticsSlashCommand; pub(crate) struct DiagnosticsSlashCommand;
impl DiagnosticsSlashCommand { impl DiagnosticsSlashCommand {
@@ -30,7 +26,7 @@ impl DiagnosticsSlashCommand {
&self, &self,
query: String, query: String,
cancellation_flag: Arc<AtomicBool>, cancellation_flag: Arc<AtomicBool>,
workspace: &Model<Workspace>, workspace: &View<Workspace>,
cx: &mut AppContext, cx: &mut AppContext,
) -> Task<Vec<PathMatch>> { ) -> Task<Vec<PathMatch>> {
if query.is_empty() { if query.is_empty() {
@@ -98,10 +94,6 @@ impl SlashCommand for DiagnosticsSlashCommand {
"Insert diagnostics".into() "Insert diagnostics".into()
} }
fn icon(&self) -> IconName {
IconName::XCircle
}
fn menu_text(&self) -> String { fn menu_text(&self) -> String {
self.description() self.description()
} }
@@ -118,8 +110,8 @@ impl SlashCommand for DiagnosticsSlashCommand {
self: Arc<Self>, self: Arc<Self>,
arguments: &[String], arguments: &[String],
cancellation_flag: Arc<AtomicBool>, cancellation_flag: Arc<AtomicBool>,
workspace: Option<WeakModel<Workspace>>, workspace: Option<WeakView<Workspace>>,
window: &mut gpui::Window, cx: &mut gpui::AppContext, cx: &mut WindowContext,
) -> Task<Result<Vec<ArgumentCompletion>>> { ) -> Task<Result<Vec<ArgumentCompletion>>> {
let Some(workspace) = workspace.and_then(|workspace| workspace.upgrade()) else { let Some(workspace) = workspace.and_then(|workspace| workspace.upgrade()) else {
return Task::ready(Err(anyhow!("workspace was dropped"))); return Task::ready(Err(anyhow!("workspace was dropped")));
@@ -172,10 +164,10 @@ impl SlashCommand for DiagnosticsSlashCommand {
arguments: &[String], arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>], _context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot, _context_buffer: BufferSnapshot,
workspace: WeakModel<Workspace>, workspace: WeakView<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>, _delegate: Option<Arc<dyn LspAdapterDelegate>>,
window: &mut gpui::Window, cx: &mut gpui::AppContext, cx: &mut WindowContext,
) -> Task<SlashCommandResult> { ) -> Task<Result<SlashCommandOutput>> {
let Some(workspace) = workspace.upgrade() else { let Some(workspace) = workspace.upgrade() else {
return Task::ready(Err(anyhow!("workspace was dropped"))); return Task::ready(Err(anyhow!("workspace was dropped")));
}; };
@@ -184,11 +176,7 @@ impl SlashCommand for DiagnosticsSlashCommand {
let task = collect_diagnostics(workspace.read(cx).project().clone(), options, cx); let task = collect_diagnostics(workspace.read(cx).project().clone(), options, cx);
cx.spawn(move |_| async move { cx.spawn(move |_| async move { task.await?.ok_or_else(|| anyhow!("No diagnostics found")) })
task.await?
.map(|output| output.to_event_stream())
.ok_or_else(|| anyhow!("No diagnostics found"))
})
} }
} }

View File

@@ -6,7 +6,6 @@ use std::time::Duration;
use anyhow::{anyhow, bail, Result}; use anyhow::{anyhow, bail, Result};
use assistant_slash_command::{ use assistant_slash_command::{
ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection, ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,
SlashCommandResult,
}; };
use gpui::{AppContext, BackgroundExecutor, Model, Task, WeakView}; use gpui::{AppContext, BackgroundExecutor, Model, Task, WeakView};
use indexed_docs::{ use indexed_docs::{
@@ -43,7 +42,7 @@ impl DocsSlashCommand {
/// access the workspace so we can read the project. /// access the workspace so we can read the project.
fn ensure_rust_doc_providers_are_registered( fn ensure_rust_doc_providers_are_registered(
&self, &self,
workspace: Option<WeakModel<Workspace>>, workspace: Option<WeakView<Workspace>>,
cx: &mut AppContext, cx: &mut AppContext,
) { ) {
let indexed_docs_registry = IndexedDocsRegistry::global(cx); let indexed_docs_registry = IndexedDocsRegistry::global(cx);
@@ -164,9 +163,8 @@ impl SlashCommand for DocsSlashCommand {
self: Arc<Self>, self: Arc<Self>,
arguments: &[String], arguments: &[String],
_cancel: Arc<AtomicBool>, _cancel: Arc<AtomicBool>,
workspace: Option<WeakModel<Workspace>>, workspace: Option<WeakView<Workspace>>,
window: &mut gpui::Window, cx: &mut WindowContext,
cx: &mut gpui::AppContext,
) -> Task<Result<Vec<ArgumentCompletion>>> { ) -> Task<Result<Vec<ArgumentCompletion>>> {
self.ensure_rust_doc_providers_are_registered(workspace, cx); self.ensure_rust_doc_providers_are_registered(workspace, cx);
@@ -273,11 +271,10 @@ impl SlashCommand for DocsSlashCommand {
arguments: &[String], arguments: &[String],
_context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>], _context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],
_context_buffer: BufferSnapshot, _context_buffer: BufferSnapshot,
_workspace: WeakModel<Workspace>, _workspace: WeakView<Workspace>,
_delegate: Option<Arc<dyn LspAdapterDelegate>>, _delegate: Option<Arc<dyn LspAdapterDelegate>>,
window: &mut gpui::Window, cx: &mut WindowContext,
cx: &mut gpui::AppContext, ) -> Task<Result<SlashCommandOutput>> {
) -> Task<SlashCommandResult> {
if arguments.is_empty() { if arguments.is_empty() {
return Task::ready(Err(anyhow!("missing an argument"))); return Task::ready(Err(anyhow!("missing an argument")));
}; };
@@ -358,8 +355,7 @@ impl SlashCommand for DocsSlashCommand {
}) })
.collect(), .collect(),
run_commands_in_text: false, run_commands_in_text: false,
} })
.to_event_stream())
}) })
} }
} }

Some files were not shown because too many files have changed in this diff Show More