Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fdc996a87c |
34
.github/ISSUE_TEMPLATE/0_feature_request.yml
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
name: Feature Request
|
||||
description: "Tip: open this issue template from within Zed with the `request feature` command palette action"
|
||||
labels: ["admin read", "triage", "enhancement"]
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Check for existing issues
|
||||
description: Check the backlog of issues to reduce the chances of creating duplicates; if an issue already exists, place a `+1` (👍) on it.
|
||||
options:
|
||||
- label: Completed
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe the feature
|
||||
description: A clear and concise description of what you want to happen.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: environment
|
||||
attributes:
|
||||
label: Zed Version and System Specs
|
||||
description: Zed version, release channel, architecture (x86_64 or aarch64), OS (macOS version / Linux distro and version) and RAM amount.
|
||||
placeholder: |
|
||||
<!-- In Zed run `copy system specs into clipboard` from the Zed command palette and paste here. -->
|
||||
<!-- Alternatively spawn `request feature` and this field will be autopopulated -->
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: |
|
||||
If applicable, add mockups / screenshots to help present your vision of the feature
|
||||
description: Drag images into the text input below
|
||||
validations:
|
||||
required: false
|
||||
83
.github/ISSUE_TEMPLATE/1_bug_report.yml
vendored
@@ -1,57 +1,54 @@
|
||||
name: Bug Report
|
||||
description: |
|
||||
Something is broken in Zed (exclude crashing).
|
||||
type: "Bug"
|
||||
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.
|
||||
labels: ["admin read", "triage", "bug"]
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Check for existing issues
|
||||
description: Check the backlog of issues to reduce the chances of creating duplicates; if an issue already exists, place a `+1` (👍) on it.
|
||||
options:
|
||||
- label: Completed
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Summary
|
||||
description: Describe the bug with a one line summary, and provide detailed reproduction steps
|
||||
value: |
|
||||
<!-- Please insert a one line summary of the issue below -->
|
||||
|
||||
SUMMARY_SENTENCE_HERE
|
||||
|
||||
<!-- Be verbose: Include all steps necessary to reproduce from a clean Zed installation. -->
|
||||
<!-- Code snippets are better than images, a repository link that reproduces the issue is ideal. -->
|
||||
|
||||
Steps to trigger the problem:
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
4.
|
||||
|
||||
Actual Behavior:
|
||||
|
||||
Expected Behavior:
|
||||
|
||||
<!--
|
||||
Is there anything additional necessary to reproduce this issue?
|
||||
- settings.json, keymap.json, .editorconfig etc?
|
||||
- Does it happen intermittently or only with specific projects / file types?
|
||||
- Have you found a workaround?
|
||||
|
||||
Did you check your Zed.log to see if there is any relevant details there?
|
||||
- When including large items (videos, screenshots, logs, configs) please wrap with:
|
||||
|
||||
<details><summary>See inside for XXXXYYY</summary>
|
||||
|
||||
```shell
|
||||
code
|
||||
```
|
||||
|
||||
</details>
|
||||
-->
|
||||
|
||||
label: Describe the bug / provide steps to reproduce it
|
||||
description: A clear and concise description of what the bug is.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: environment
|
||||
attributes:
|
||||
label: Zed Version and System Specs
|
||||
description: 'Open Zed, and in the command palette select "zed: Copy System Specs Into Clipboard"'
|
||||
description: Zed version, release channel, architecture (x86_64 or aarch64), OS (macOS version / Linux distro and version) and RAM amount.
|
||||
placeholder: |
|
||||
Output of "zed: Copy System Specs Into Clipboard"
|
||||
<!-- In Zed run `copy system specs into clipboard` from the Zed command palette and paste here. -->
|
||||
<!-- Alternatively spawn `file bug report` and this field will be autopopulated -->
|
||||
<!-- If Zed won't launch, include the equivalent with other relevant details (e.g. video card driver version for display bugs, etc) -->
|
||||
<!-- Zed Version: 0.xxx.x; Channel: Stable, OS: macOS xx.xx, RAM: XXGB, Architecture: x86_64"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: If applicable, add screenshots or screencasts of the incorrect state / behavior
|
||||
description: Drag images / videos into the text input below
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: If applicable, attach your Zed.log file to this issue.
|
||||
description: |
|
||||
macOS: `~/Library/Logs/Zed/Zed.log`
|
||||
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.
|
||||
value: |
|
||||
<details><summary>Zed.log</summary>
|
||||
|
||||
<!-- Click below this line and paste or drag-and-drop your log-->
|
||||
```
|
||||
|
||||
```
|
||||
<!-- Click above this line and paste or drag-and-drop your log--></details>
|
||||
validations:
|
||||
required: false
|
||||
|
||||
35
.github/ISSUE_TEMPLATE/2_crash_report.yml
vendored
@@ -1,33 +1,26 @@
|
||||
name: Crash Report
|
||||
description: Zed is Crashing or Hanging
|
||||
type: "Crash"
|
||||
description: |
|
||||
Use this template for crash reports.
|
||||
labels: ["admin read", "triage", "bug", "panic / crash"]
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Check for existing issues
|
||||
description: Check the backlog of issues to reduce the chances of creating duplicates; if an issue already exists, place a `+1` (👍) on it.
|
||||
options:
|
||||
- label: Completed
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Summary
|
||||
description: Describe the bug with a one line summary, and provide detailed reproduction steps
|
||||
value: |
|
||||
<!-- Please insert a one line summary of the issue below -->
|
||||
|
||||
<!-- Include all steps necessary to reproduce from a clean Zed installation. Be verbose -->
|
||||
Steps to trigger the problem:
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
|
||||
Actual Behavior:
|
||||
|
||||
Expected Behavior:
|
||||
|
||||
label: Describe the bug / provide steps to reproduce it
|
||||
description: A clear and concise description of what the bug is.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: environment
|
||||
attributes:
|
||||
label: Zed Version and System Specs
|
||||
description: 'Open Zed, and in the command palette select "zed: Copy System Specs Into Clipboard"'
|
||||
placeholder: |
|
||||
Output of "zed: Copy System Specs Into Clipboard"
|
||||
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
|
||||
|
||||
24
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,12 +1,18 @@
|
||||
# yaml-language-server: $schema=https://json.schemastore.org/github-issue-config.json
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Feature Request
|
||||
url: https://github.com/zed-industries/zed/discussions/new/choose
|
||||
about: To request a feature, open a new Discussion in one of the appropriate Discussion categories
|
||||
- name: Zed Discussion Forum
|
||||
url: https://github.com/zed-industries/zed/discussions
|
||||
about: A community discussion forum
|
||||
- name: "Zed Discord: #Support Channel"
|
||||
url: https://zed.dev/community-links
|
||||
about: Real-time discussion and user support
|
||||
- name: Language Request
|
||||
url: https://github.com/zed-industries/extensions/issues/new?assignees=&labels=language&projects=&template=1_language_request.yml&title=%3Cname_of_language%3E
|
||||
about: Request a language in the extensions repository
|
||||
- name: Theme Request
|
||||
url: https://github.com/zed-industries/extensions/issues/new?assignees=&labels=theme&projects=&template=0_theme_request.yml&title=%3Cname_of_theme%3E+theme
|
||||
about: Request a theme in the extensions repository
|
||||
- name: Top-Ranking Issues
|
||||
url: https://github.com/zed-industries/zed/issues/5393
|
||||
about: See an overview of the most popular Zed issues
|
||||
- name: Platform Support
|
||||
url: https://github.com/zed-industries/zed/issues/5391
|
||||
about: A quick note on platform support
|
||||
- name: Positive Feedback
|
||||
url: https://github.com/zed-industries/zed/discussions/5397
|
||||
about: A central location for kind words about Zed
|
||||
|
||||
2
.github/actions/run_tests/action.yml
vendored
@@ -10,7 +10,7 @@ runs:
|
||||
cargo install cargo-nextest --locked
|
||||
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4
|
||||
with:
|
||||
node-version: "18"
|
||||
|
||||
|
||||
26
.github/actions/run_tests_windows/action.yml
vendored
@@ -1,26 +0,0 @@
|
||||
name: "Run tests on Windows"
|
||||
description: "Runs the tests on Windows"
|
||||
|
||||
inputs:
|
||||
working-directory:
|
||||
description: "The working directory"
|
||||
required: true
|
||||
default: "."
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Install Rust
|
||||
shell: pwsh
|
||||
working-directory: ${{ inputs.working-directory }}
|
||||
run: cargo install cargo-nextest --locked
|
||||
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4
|
||||
with:
|
||||
node-version: "18"
|
||||
|
||||
- name: Run tests
|
||||
shell: pwsh
|
||||
working-directory: ${{ inputs.working-directory }}
|
||||
run: cargo nextest run --workspace --no-fail-fast
|
||||
1
.github/workflows/bump_patch_version.yml
vendored
@@ -14,7 +14,6 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
bump_patch_version:
|
||||
if: github.repository_owner == 'zed-industries'
|
||||
runs-on:
|
||||
- buildjet-16vcpu-ubuntu-2204
|
||||
steps:
|
||||
|
||||
50
.github/workflows/ci.yml
vendored
@@ -109,16 +109,8 @@ jobs:
|
||||
- name: cargo clippy
|
||||
run: ./script/clippy
|
||||
|
||||
- name: Install cargo-machete
|
||||
uses: clechasseur/rs-cargo@v2
|
||||
with:
|
||||
command: install
|
||||
args: cargo-machete@0.7.0
|
||||
|
||||
- name: Check unused dependencies
|
||||
uses: clechasseur/rs-cargo@v2
|
||||
with:
|
||||
command: machete
|
||||
uses: bnjbvr/cargo-machete@main
|
||||
|
||||
- name: Check licenses
|
||||
run: |
|
||||
@@ -143,7 +135,6 @@ jobs:
|
||||
cargo check -p gpui --features "macos-blade"
|
||||
cargo check -p workspace
|
||||
cargo build -p remote_server
|
||||
cargo check -p gpui --examples
|
||||
script/check-rust-livekit-macos
|
||||
|
||||
# Since the macOS runners are stateful, so we need to remove the config file to prevent potential bug.
|
||||
@@ -190,7 +181,6 @@ jobs:
|
||||
run: |
|
||||
cargo build -p zed
|
||||
cargo check -p workspace
|
||||
cargo check -p gpui --examples
|
||||
|
||||
# Even the Linux runner is not stateful, in theory there is no need to do this cleanup.
|
||||
# But, to avoid potential issues in the future if we choose to use a stateful Linux runner and forget to add code
|
||||
@@ -236,6 +226,7 @@ jobs:
|
||||
if: always()
|
||||
run: rm -rf ./../.cargo
|
||||
|
||||
# todo(windows): Actually run the tests
|
||||
windows_tests:
|
||||
timeout-minutes: 60
|
||||
name: (Windows) Run Clippy and tests
|
||||
@@ -245,55 +236,33 @@ jobs:
|
||||
# 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
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
with:
|
||||
clean: false
|
||||
|
||||
- name: Create Dev Drive using ReFS
|
||||
run: ./script/setup-dev-driver.ps1
|
||||
|
||||
# actions/checkout does not let us clone into anywhere outside ${{ github.workspace }}, so we have to copy the clone...
|
||||
- name: Copy Git Repo to Dev Drive
|
||||
run: |
|
||||
Copy-Item -Path "${{ github.workspace }}" -Destination "${{ env.ZED_WORKSPACE }}" -Recurse
|
||||
|
||||
- name: Cache dependencies
|
||||
uses: swatinem/rust-cache@f0deed1e0edfc6a9be95417288c0e1099b1eeec3 # v2
|
||||
with:
|
||||
save-if: ${{ github.ref == 'refs/heads/main' }}
|
||||
workspaces: ${{ env.ZED_WORKSPACE }}
|
||||
cache-provider: "github"
|
||||
|
||||
- name: Configure CI
|
||||
run: |
|
||||
mkdir -p ${{ env.CARGO_HOME }} -ErrorAction Ignore
|
||||
cp ./.cargo/ci-config.toml ${{ env.CARGO_HOME }}/config.toml
|
||||
mkdir -p ./../.cargo
|
||||
cp ./.cargo/ci-config.toml ./../.cargo/config.toml
|
||||
|
||||
- name: cargo clippy
|
||||
working-directory: ${{ env.ZED_WORKSPACE }}
|
||||
# Windows can't run shell scripts, so we need to use `cargo xtask`.
|
||||
run: cargo xtask clippy
|
||||
|
||||
- name: Run tests
|
||||
uses: ./.github/actions/run_tests_windows
|
||||
with:
|
||||
working-directory: ${{ env.ZED_WORKSPACE }}
|
||||
|
||||
- name: Build Zed
|
||||
working-directory: ${{ env.ZED_WORKSPACE }}
|
||||
run: cargo build
|
||||
|
||||
- name: Check dev drive space
|
||||
working-directory: ${{ env.ZED_WORKSPACE }}
|
||||
# `setup-dev-driver.ps1` creates a 100GB drive, with CI taking up ~45GB of the drive.
|
||||
run: ./script/exit-ci-if-dev-drive-is-full.ps1 95
|
||||
|
||||
# Since the Windows runners are stateful, so we need to remove the config file to prevent potential bug.
|
||||
- name: Clean CI config file
|
||||
if: always()
|
||||
run: Remove-Item -Path "${{ env.CARGO_HOME }}/config.toml" -Force
|
||||
run: Remove-Item -Path "./../.cargo" -Recurse -Force
|
||||
|
||||
bundle-mac:
|
||||
timeout-minutes: 120
|
||||
@@ -306,16 +275,15 @@ jobs:
|
||||
env:
|
||||
MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }}
|
||||
MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }}
|
||||
APPLE_NOTARIZATION_KEY: ${{ secrets.APPLE_NOTARIZATION_KEY }}
|
||||
APPLE_NOTARIZATION_KEY_ID: ${{ secrets.APPLE_NOTARIZATION_KEY_ID }}
|
||||
APPLE_NOTARIZATION_ISSUER_ID: ${{ secrets.APPLE_NOTARIZATION_ISSUER_ID }}
|
||||
APPLE_NOTARIZATION_USERNAME: ${{ secrets.APPLE_NOTARIZATION_USERNAME }}
|
||||
APPLE_NOTARIZATION_PASSWORD: ${{ secrets.APPLE_NOTARIZATION_PASSWORD }}
|
||||
ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
|
||||
ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON: ${{ secrets.ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON }}
|
||||
DIGITALOCEAN_SPACES_ACCESS_KEY: ${{ secrets.DIGITALOCEAN_SPACES_ACCESS_KEY }}
|
||||
DIGITALOCEAN_SPACES_SECRET_KEY: ${{ secrets.DIGITALOCEAN_SPACES_SECRET_KEY }}
|
||||
steps:
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4
|
||||
with:
|
||||
node-version: "18"
|
||||
|
||||
@@ -491,6 +459,6 @@ jobs:
|
||||
- bundle
|
||||
steps:
|
||||
- name: gh release
|
||||
run: gh release edit $GITHUB_REF_NAME --draft=true
|
||||
run: gh release edit $GITHUB_REF_NAME --draft=false
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -9,7 +9,7 @@ jobs:
|
||||
if: github.repository_owner == 'zed-industries'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9
|
||||
- uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
stale-issue-message: >
|
||||
@@ -19,7 +19,11 @@ jobs:
|
||||
|
||||
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."
|
||||
days-before-stale: 120
|
||||
# We will increase `days-before-stale` to 365 on or after Jan 24th,
|
||||
# 2024. This date marks one year since migrating issues from
|
||||
# 'community' to 'zed' repository. The migration added activity to all
|
||||
# issues, preventing 365 days from working until then.
|
||||
days-before-stale: 180
|
||||
days-before-close: 7
|
||||
any-of-issue-labels: "bug,panic / crash"
|
||||
operations-per-run: 1000
|
||||
|
||||
@@ -9,7 +9,6 @@ permissions:
|
||||
|
||||
jobs:
|
||||
delete_comment:
|
||||
if: github.repository_owner == 'zed-industries'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check for specific strings in comment
|
||||
|
||||
@@ -6,7 +6,6 @@ on:
|
||||
|
||||
jobs:
|
||||
discord_release:
|
||||
if: github.repository_owner == 'zed-industries'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Get release URL
|
||||
|
||||
3
.github/workflows/danger.yml
vendored
@@ -11,7 +11,6 @@ on:
|
||||
|
||||
jobs:
|
||||
danger:
|
||||
if: github.repository_owner == 'zed-industries'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
@@ -22,7 +21,7 @@ jobs:
|
||||
version: 9
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4
|
||||
with:
|
||||
node-version: "20"
|
||||
cache: "pnpm"
|
||||
|
||||
15
.github/workflows/deploy_cloudflare.yml
vendored
@@ -37,36 +37,29 @@ jobs:
|
||||
mdbook build ./docs --dest-dir=../target/deploy/docs/
|
||||
|
||||
- name: Deploy Docs
|
||||
uses: cloudflare/wrangler-action@392082e81ffbcb9ebdde27400634aa004b35ea37 # v3
|
||||
uses: cloudflare/wrangler-action@6d58852c35a27e6034745c5d0bc373d739014f7f # v3
|
||||
with:
|
||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
command: pages deploy target/deploy --project-name=docs
|
||||
|
||||
- name: Deploy Install
|
||||
uses: cloudflare/wrangler-action@392082e81ffbcb9ebdde27400634aa004b35ea37 # v3
|
||||
uses: cloudflare/wrangler-action@6d58852c35a27e6034745c5d0bc373d739014f7f # v3
|
||||
with:
|
||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
command: r2 object put -f script/install.sh zed-open-source-website-assets/install.sh
|
||||
|
||||
- name: Deploy Docs Workers
|
||||
uses: cloudflare/wrangler-action@392082e81ffbcb9ebdde27400634aa004b35ea37 # v3
|
||||
uses: cloudflare/wrangler-action@6d58852c35a27e6034745c5d0bc373d739014f7f # v3
|
||||
with:
|
||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
command: deploy .cloudflare/docs-proxy/src/worker.js
|
||||
|
||||
- name: Deploy Install Workers
|
||||
uses: cloudflare/wrangler-action@392082e81ffbcb9ebdde27400634aa004b35ea37 # v3
|
||||
uses: cloudflare/wrangler-action@6d58852c35a27e6034745c5d0bc373d739014f7f # v3
|
||||
with:
|
||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
command: deploy .cloudflare/docs-proxy/src/worker.js
|
||||
|
||||
- name: Preserve Wrangler logs
|
||||
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4
|
||||
if: always()
|
||||
with:
|
||||
name: wrangler_logs
|
||||
path: /home/runner/.config/.wrangler/logs/
|
||||
|
||||
1
.github/workflows/deploy_collab.yml
vendored
@@ -12,7 +12,6 @@ env:
|
||||
jobs:
|
||||
style:
|
||||
name: Check formatting and Clippy lints
|
||||
if: github.repository_owner == 'zed-industries'
|
||||
runs-on:
|
||||
- self-hosted
|
||||
- test
|
||||
|
||||
6
.github/workflows/docs.yml
vendored
@@ -24,13 +24,11 @@ jobs:
|
||||
- name: Prettier Check on /docs
|
||||
working-directory: ./docs
|
||||
run: |
|
||||
pnpm dlx prettier@${PRETTIER_VERSION} . --check || {
|
||||
pnpm dlx prettier . --check || {
|
||||
echo "To fix, run from the root of the zed repo:"
|
||||
echo " cd docs && pnpm dlx prettier@${PRETTIER_VERSION} . --write && cd .."
|
||||
echo " cd docs && pnpm dlx prettier . --write && cd .."
|
||||
false
|
||||
}
|
||||
env:
|
||||
PRETTIER_VERSION: 3.5.0
|
||||
|
||||
- name: Check for Typos with Typos-CLI
|
||||
uses: crate-ci/typos@8e6a4285bcbde632c5d79900a7779746e8b7ea3f # v1.24.6
|
||||
|
||||
33
.github/workflows/issue_response.yml
vendored
@@ -1,33 +0,0 @@
|
||||
name: Issue Response
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 12 * * 2"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
issue-response:
|
||||
if: github.repository_owner == 'zed-industries'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
|
||||
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
|
||||
with:
|
||||
version: 9
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4
|
||||
with:
|
||||
node-version: "20"
|
||||
cache: "pnpm"
|
||||
cache-dependency-path: "script/issue_response/pnpm-lock.yaml"
|
||||
|
||||
- run: pnpm install --dir script/issue_response
|
||||
|
||||
- name: Run Issue Response
|
||||
run: pnpm run --dir script/issue_response start
|
||||
env:
|
||||
ISSUE_RESPONSE_GITHUB_TOKEN: ${{ secrets.ISSUE_RESPONSE_GITHUB_TOKEN }}
|
||||
SLACK_ISSUE_RESPONSE_WEBHOOK_URL: ${{ secrets.SLACK_ISSUE_RESPONSE_WEBHOOK_URL }}
|
||||
1
.github/workflows/publish_extension_cli.yml
vendored
@@ -12,7 +12,6 @@ env:
|
||||
jobs:
|
||||
publish:
|
||||
name: Publish zed-extension CLI
|
||||
if: github.repository_owner == 'zed-industries'
|
||||
runs-on:
|
||||
- ubuntu-latest
|
||||
steps:
|
||||
|
||||
3
.github/workflows/randomized_tests.yml
vendored
@@ -18,12 +18,11 @@ env:
|
||||
jobs:
|
||||
tests:
|
||||
name: Run randomized tests
|
||||
if: github.repository_owner == 'zed-industries'
|
||||
runs-on:
|
||||
- buildjet-16vcpu-ubuntu-2204
|
||||
steps:
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4
|
||||
with:
|
||||
node-version: "18"
|
||||
|
||||
|
||||
7
.github/workflows/release_nightly.yml
vendored
@@ -62,16 +62,15 @@ jobs:
|
||||
env:
|
||||
MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }}
|
||||
MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }}
|
||||
APPLE_NOTARIZATION_KEY: ${{ secrets.APPLE_NOTARIZATION_KEY }}
|
||||
APPLE_NOTARIZATION_KEY_ID: ${{ secrets.APPLE_NOTARIZATION_KEY_ID }}
|
||||
APPLE_NOTARIZATION_ISSUER_ID: ${{ secrets.APPLE_NOTARIZATION_ISSUER_ID }}
|
||||
APPLE_NOTARIZATION_USERNAME: ${{ secrets.APPLE_NOTARIZATION_USERNAME }}
|
||||
APPLE_NOTARIZATION_PASSWORD: ${{ secrets.APPLE_NOTARIZATION_PASSWORD }}
|
||||
DIGITALOCEAN_SPACES_ACCESS_KEY: ${{ secrets.DIGITALOCEAN_SPACES_ACCESS_KEY }}
|
||||
DIGITALOCEAN_SPACES_SECRET_KEY: ${{ secrets.DIGITALOCEAN_SPACES_SECRET_KEY }}
|
||||
ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
|
||||
ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON: ${{ secrets.ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON }}
|
||||
steps:
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4
|
||||
with:
|
||||
node-version: "18"
|
||||
|
||||
|
||||
55
.gitignore
vendored
@@ -1,36 +1,35 @@
|
||||
**/*.db
|
||||
**/cargo-target
|
||||
**/target
|
||||
**/venv
|
||||
*.wasm
|
||||
*.xcodeproj
|
||||
.DS_Store
|
||||
.blob_store
|
||||
.build
|
||||
.envrc
|
||||
.flatpak-builder
|
||||
.idea
|
||||
.netrc
|
||||
.pytest_cache
|
||||
.swiftpm
|
||||
.swiftpm/config/registries.json
|
||||
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
|
||||
.venv
|
||||
.vscode
|
||||
.wrangler
|
||||
/.direnv
|
||||
/assets/*licenses.*
|
||||
/crates/collab/seed.json
|
||||
/crates/theme/schemas/theme.json
|
||||
/crates/zed/resources/flatpak/flatpak-cargo-sources.json
|
||||
/dev.zed.Zed*.json
|
||||
.envrc
|
||||
.idea
|
||||
**/target
|
||||
**/cargo-target
|
||||
/zed.xcworkspace
|
||||
.DS_Store
|
||||
/plugins/bin
|
||||
/script/node_modules
|
||||
/snap
|
||||
/zed.xcworkspace
|
||||
DerivedData/
|
||||
/crates/theme/schemas/theme.json
|
||||
/crates/collab/seed.json
|
||||
/crates/zed/resources/flatpak/flatpak-cargo-sources.json
|
||||
/dev.zed.Zed*.json
|
||||
/assets/*licenses.*
|
||||
**/venv
|
||||
.build
|
||||
*.wasm
|
||||
Packages
|
||||
*.xcodeproj
|
||||
xcuserdata/
|
||||
DerivedData/
|
||||
.swiftpm/config/registries.json
|
||||
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
|
||||
.netrc
|
||||
.swiftpm
|
||||
**/*.db
|
||||
.pytest_cache
|
||||
.venv
|
||||
.blob_store
|
||||
.vscode
|
||||
.wrangler
|
||||
.flatpak-builder
|
||||
|
||||
# Don't commit any secrets to the repo.
|
||||
.env.secret.toml
|
||||
|
||||
4
.mailmap
@@ -21,8 +21,6 @@ Andrei Zvonimir Crnković <andrei@0x7f.dev>
|
||||
Andrei Zvonimir Crnković <andrei@0x7f.dev> <andreicek@0x7f.dev>
|
||||
Antonio Scandurra <me@as-cii.com>
|
||||
Antonio Scandurra <me@as-cii.com> <antonio@zed.dev>
|
||||
Ben Kunkle <ben@zed.dev>
|
||||
Ben Kunkle <ben@zed.dev> <ben.kunkle@gmail.com>
|
||||
Bennet Bo Fenner <bennet@zed.dev>
|
||||
Bennet Bo Fenner <bennet@zed.dev> <53836821+bennetbo@users.noreply.github.com>
|
||||
Bennet Bo Fenner <bennet@zed.dev> <bennetbo@gmx.de>
|
||||
@@ -114,8 +112,6 @@ Sebastijan Kelnerič <sebastijan.kelneric@sebba.dev> <sebastijan.kelneric@vichav
|
||||
Sergey Onufrienko <sergey@onufrienko.com>
|
||||
Shish <webmaster@shishnet.org>
|
||||
Shish <webmaster@shishnet.org> <shish@shishnet.org>
|
||||
Smit Barmase <0xtimsb@gmail.com>
|
||||
Smit Barmase <0xtimsb@gmail.com> <smit@zed.dev>
|
||||
Thorben Kröger <dev@thorben.net>
|
||||
Thorben Kröger <dev@thorben.net> <thorben.kroeger@hexagon.com>
|
||||
Thorsten Ball <thorsten@zed.dev>
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
},
|
||||
"JSON": {
|
||||
"tab_size": 2,
|
||||
"preferred_line_length": 120,
|
||||
"preferred_line_length": 100,
|
||||
"formatter": "prettier"
|
||||
},
|
||||
"JSONC": {
|
||||
"tab_size": 2,
|
||||
"preferred_line_length": 120,
|
||||
"preferred_line_length": 100,
|
||||
"formatter": "prettier"
|
||||
},
|
||||
"JavaScript": {
|
||||
|
||||
@@ -37,16 +37,6 @@ We plan to set aside time each week to pair program with contributors on promisi
|
||||
- Pair with us and watch us code to learn the codebase
|
||||
- Low effort PRs, such as those that just re-arrange syntax, won't be merged without a compelling justification
|
||||
|
||||
## File icons
|
||||
|
||||
Zed's default icon theme consists of icons that are hand-designed to fit together in a cohesive manner.
|
||||
|
||||
We do not accept PRs for file icons that are just an off-the-shelf SVG taken from somewhere else.
|
||||
|
||||
### Adding new icons to the Zed icon theme
|
||||
|
||||
If you would like to add a new icon to the Zed icon theme, [open a Discussion](https://github.com/zed-industries/zed/discussions/new?category=ux-and-design) and we can work with you on getting an icon designed and added to Zed.
|
||||
|
||||
## Bird's-eye view of Zed
|
||||
|
||||
Zed is made up of several smaller crates - let's go over those you're most likely to interact with:
|
||||
@@ -62,9 +52,3 @@ Zed is made up of several smaller crates - let's go over those you're most likel
|
||||
- [`rpc`](/crates/rpc) defines messages to be exchanged with collaboration server.
|
||||
- [`theme`](/crates/theme) defines the theme system and provides a default theme.
|
||||
- [`ui`](/crates/ui) is a collection of UI components and common patterns used throughout Zed.
|
||||
- [`cli`](/crates/cli) is the CLI crate which invokes the Zed binary.
|
||||
- [`zed`](/crates/zed) is where all things come together, and the `main` entry point for Zed.
|
||||
|
||||
## Packaging Zed
|
||||
|
||||
Check our [notes for packaging Zed](https://zed.dev/docs/development/linux#notes-for-packaging-zed).
|
||||
|
||||
1965
Cargo.lock
generated
114
Cargo.toml
@@ -2,6 +2,7 @@
|
||||
resolver = "2"
|
||||
members = [
|
||||
"crates/activity_indicator",
|
||||
"crates/zed_predict_tos",
|
||||
"crates/anthropic",
|
||||
"crates/assets",
|
||||
"crates/assistant",
|
||||
@@ -15,10 +16,7 @@ members = [
|
||||
"crates/audio",
|
||||
"crates/auto_update",
|
||||
"crates/auto_update_ui",
|
||||
"crates/aws_http_client",
|
||||
"crates/bedrock",
|
||||
"crates/breadcrumbs",
|
||||
"crates/buffer_diff",
|
||||
"crates/call",
|
||||
"crates/channel",
|
||||
"crates/cli",
|
||||
@@ -29,14 +27,10 @@ members = [
|
||||
"crates/collections",
|
||||
"crates/command_palette",
|
||||
"crates/command_palette_hooks",
|
||||
"crates/component",
|
||||
"crates/component_preview",
|
||||
"crates/context_server",
|
||||
"crates/context_server_settings",
|
||||
"crates/copilot",
|
||||
"crates/credentials_provider",
|
||||
"crates/db",
|
||||
"crates/deepseek",
|
||||
"crates/diagnostics",
|
||||
"crates/docs_preprocessor",
|
||||
"crates/editor",
|
||||
@@ -50,17 +44,16 @@ members = [
|
||||
"crates/feedback",
|
||||
"crates/file_finder",
|
||||
"crates/file_icons",
|
||||
"crates/fireworks",
|
||||
"crates/fs",
|
||||
"crates/fsevent",
|
||||
"crates/fuzzy",
|
||||
"crates/git",
|
||||
"crates/git_hosting_providers",
|
||||
"crates/git_ui",
|
||||
"crates/go_to_line",
|
||||
"crates/google_ai",
|
||||
"crates/gpui",
|
||||
"crates/gpui_macros",
|
||||
"crates/gpui_tokio",
|
||||
"crates/html_to_markdown",
|
||||
"crates/http_client",
|
||||
"crates/image_viewer",
|
||||
@@ -77,17 +70,15 @@ members = [
|
||||
"crates/language_selector",
|
||||
"crates/language_tools",
|
||||
"crates/languages",
|
||||
"crates/livekit_api",
|
||||
"crates/livekit_client",
|
||||
"crates/livekit_client_macos",
|
||||
"crates/livekit_server",
|
||||
"crates/lmstudio",
|
||||
"crates/lsp",
|
||||
"crates/markdown",
|
||||
"crates/markdown_preview",
|
||||
"crates/media",
|
||||
"crates/menu",
|
||||
"crates/migrator",
|
||||
"crates/mistral",
|
||||
"crates/multi_buffer",
|
||||
"crates/node_runtime",
|
||||
"crates/notifications",
|
||||
@@ -95,7 +86,6 @@ members = [
|
||||
"crates/open_ai",
|
||||
"crates/outline",
|
||||
"crates/outline_panel",
|
||||
"crates/panel",
|
||||
"crates/paths",
|
||||
"crates/picker",
|
||||
"crates/prettier",
|
||||
@@ -115,7 +105,6 @@ members = [
|
||||
"crates/rich_text",
|
||||
"crates/rope",
|
||||
"crates/rpc",
|
||||
"crates/schema_generator",
|
||||
"crates/search",
|
||||
"crates/semantic_index",
|
||||
"crates/semantic_version",
|
||||
@@ -151,8 +140,9 @@ members = [
|
||||
"crates/ui",
|
||||
"crates/ui_input",
|
||||
"crates/ui_macros",
|
||||
"crates/reqwest_client",
|
||||
"crates/util",
|
||||
"crates/util_macros",
|
||||
"crates/vcs_menu",
|
||||
"crates/vim",
|
||||
"crates/vim_mode_setting",
|
||||
"crates/welcome",
|
||||
@@ -161,6 +151,7 @@ members = [
|
||||
"crates/zed",
|
||||
"crates/zed_actions",
|
||||
"crates/zeta",
|
||||
"crates/git_ui",
|
||||
|
||||
#
|
||||
# Extensions
|
||||
@@ -175,7 +166,9 @@ members = [
|
||||
"extensions/haskell",
|
||||
"extensions/html",
|
||||
"extensions/lua",
|
||||
"extensions/php",
|
||||
"extensions/perplexity",
|
||||
"extensions/prisma",
|
||||
"extensions/proto",
|
||||
"extensions/purescript",
|
||||
"extensions/ruff",
|
||||
@@ -207,6 +200,7 @@ edition = "2021"
|
||||
|
||||
activity_indicator = { path = "crates/activity_indicator" }
|
||||
ai = { path = "crates/ai" }
|
||||
zed_predict_tos = { path = "crates/zed_predict_tos" }
|
||||
anthropic = { path = "crates/anthropic" }
|
||||
assets = { path = "crates/assets" }
|
||||
assistant = { path = "crates/assistant" }
|
||||
@@ -220,8 +214,6 @@ assistant_tools = { path = "crates/assistant_tools" }
|
||||
audio = { path = "crates/audio" }
|
||||
auto_update = { path = "crates/auto_update" }
|
||||
auto_update_ui = { path = "crates/auto_update_ui" }
|
||||
aws_http_client = { path = "crates/aws_http_client" }
|
||||
bedrock = { path = "crates/bedrock" }
|
||||
breadcrumbs = { path = "crates/breadcrumbs" }
|
||||
call = { path = "crates/call" }
|
||||
channel = { path = "crates/channel" }
|
||||
@@ -233,16 +225,11 @@ collab_ui = { path = "crates/collab_ui" }
|
||||
collections = { path = "crates/collections" }
|
||||
command_palette = { path = "crates/command_palette" }
|
||||
command_palette_hooks = { path = "crates/command_palette_hooks" }
|
||||
component = { path = "crates/component" }
|
||||
component_preview = { path = "crates/component_preview" }
|
||||
context_server = { path = "crates/context_server" }
|
||||
context_server_settings = { path = "crates/context_server_settings" }
|
||||
copilot = { path = "crates/copilot" }
|
||||
credentials_provider = { path = "crates/credentials_provider" }
|
||||
db = { path = "crates/db" }
|
||||
deepseek = { path = "crates/deepseek" }
|
||||
diagnostics = { path = "crates/diagnostics" }
|
||||
buffer_diff = { path = "crates/buffer_diff" }
|
||||
editor = { path = "crates/editor" }
|
||||
extension = { path = "crates/extension" }
|
||||
extension_host = { path = "crates/extension_host" }
|
||||
@@ -251,19 +238,19 @@ feature_flags = { path = "crates/feature_flags" }
|
||||
feedback = { path = "crates/feedback" }
|
||||
file_finder = { path = "crates/file_finder" }
|
||||
file_icons = { path = "crates/file_icons" }
|
||||
fireworks = { path = "crates/fireworks" }
|
||||
fs = { path = "crates/fs" }
|
||||
fsevent = { path = "crates/fsevent" }
|
||||
fuzzy = { path = "crates/fuzzy" }
|
||||
git = { path = "crates/git" }
|
||||
git_hosting_providers = { path = "crates/git_hosting_providers" }
|
||||
git_ui = { path = "crates/git_ui" }
|
||||
git_hosting_providers = { path = "crates/git_hosting_providers" }
|
||||
go_to_line = { path = "crates/go_to_line" }
|
||||
google_ai = { path = "crates/google_ai" }
|
||||
gpui = { path = "crates/gpui", default-features = false, features = [
|
||||
"http_client",
|
||||
] }
|
||||
gpui_macros = { path = "crates/gpui_macros" }
|
||||
gpui_tokio = { path = "crates/gpui_tokio" }
|
||||
html_to_markdown = { path = "crates/html_to_markdown" }
|
||||
http_client = { path = "crates/http_client" }
|
||||
image_viewer = { path = "crates/image_viewer" }
|
||||
@@ -280,17 +267,15 @@ language_models = { path = "crates/language_models" }
|
||||
language_selector = { path = "crates/language_selector" }
|
||||
language_tools = { path = "crates/language_tools" }
|
||||
languages = { path = "crates/languages" }
|
||||
livekit_api = { path = "crates/livekit_api" }
|
||||
livekit_client = { path = "crates/livekit_client" }
|
||||
livekit_client_macos = { path = "crates/livekit_client_macos" }
|
||||
livekit_server = { path = "crates/livekit_server" }
|
||||
lmstudio = { path = "crates/lmstudio" }
|
||||
lsp = { path = "crates/lsp" }
|
||||
markdown = { path = "crates/markdown" }
|
||||
markdown_preview = { path = "crates/markdown_preview" }
|
||||
media = { path = "crates/media" }
|
||||
menu = { path = "crates/menu" }
|
||||
migrator = { path = "crates/migrator" }
|
||||
mistral = { path = "crates/mistral" }
|
||||
multi_buffer = { path = "crates/multi_buffer" }
|
||||
node_runtime = { path = "crates/node_runtime" }
|
||||
notifications = { path = "crates/notifications" }
|
||||
@@ -299,7 +284,6 @@ open_ai = { path = "crates/open_ai" }
|
||||
outline = { path = "crates/outline" }
|
||||
outline_panel = { path = "crates/outline_panel" }
|
||||
paths = { path = "crates/paths" }
|
||||
panel = { path = "crates/panel" }
|
||||
picker = { path = "crates/picker" }
|
||||
plugin = { path = "crates/plugin" }
|
||||
plugin_macros = { path = "crates/plugin_macros" }
|
||||
@@ -355,7 +339,7 @@ ui = { path = "crates/ui" }
|
||||
ui_input = { path = "crates/ui_input" }
|
||||
ui_macros = { path = "crates/ui_macros" }
|
||||
util = { path = "crates/util" }
|
||||
util_macros = { path = "crates/util_macros" }
|
||||
vcs_menu = { path = "crates/vcs_menu" }
|
||||
vim = { path = "crates/vim" }
|
||||
vim_mode_setting = { path = "crates/vim_mode_setting" }
|
||||
welcome = { path = "crates/welcome" }
|
||||
@@ -370,11 +354,12 @@ zeta = { path = "crates/zeta" }
|
||||
#
|
||||
|
||||
aho-corasick = "1.1"
|
||||
alacritty_terminal = { git = "https://github.com/zed-industries/alacritty.git", rev = "03c2907b44b4189aac5fdeaea331f5aab5c7072e"}
|
||||
# TODO(#18342): Update to version 0.25 from crates.io when it is released.
|
||||
alacritty_terminal = { git = "https://github.com/alacritty/alacritty.git", rev = "5e78d20c709cb1ab8d44ca7a8702cc26d779227c" }
|
||||
any_vec = "0.14"
|
||||
anyhow = "1.0.86"
|
||||
arrayvec = { version = "0.7.4", features = ["serde"] }
|
||||
ashpd = { version = "0.11", default-features = false, features = ["async-std"] }
|
||||
ashpd = { version = "0.10", default-features = false, features = ["async-std"]}
|
||||
async-compat = "0.2.1"
|
||||
async-compression = { version = "0.4", features = ["gzip", "futures-io"] }
|
||||
async-dispatcher = "0.1"
|
||||
@@ -386,17 +371,11 @@ async-trait = "0.1"
|
||||
async-tungstenite = "0.28"
|
||||
async-watch = "0.3.1"
|
||||
async_zip = { version = "0.0.17", features = ["deflate", "deflate64"] }
|
||||
aws-config = { version = "1.5.16", features = ["behavior-version-latest"] }
|
||||
aws-credential-types = { version = "1.2.1", features = ["hardcoded-credentials"] }
|
||||
aws-sdk-bedrockruntime = { version = "1.73.0", features = ["behavior-version-latest"] }
|
||||
aws-smithy-runtime-api = { version = "1.7.3", features = ["http-1x", "client"] }
|
||||
aws-smithy-types = { version = "1.2.13", features = ["http-body-1-x"] }
|
||||
base64 = "0.22"
|
||||
bitflags = "2.6.0"
|
||||
blade-graphics = { git = "https://github.com/kvark/blade", rev = "b16f5c7bd873c7126f48c82c39e7ae64602ae74f" }
|
||||
blade-macros = { git = "https://github.com/kvark/blade", rev = "b16f5c7bd873c7126f48c82c39e7ae64602ae74f" }
|
||||
blade-util = { git = "https://github.com/kvark/blade", rev = "b16f5c7bd873c7126f48c82c39e7ae64602ae74f" }
|
||||
naga = { version = "23.1.0", features = ["wgsl-in"] }
|
||||
bitflags = "2.8.0"
|
||||
blade-graphics = { git = "https://github.com/kvark/blade", rev = "091a8401033847bb9b6ace3fcf70448d069621c5" }
|
||||
blade-macros = { git = "https://github.com/kvark/blade", rev = "091a8401033847bb9b6ace3fcf70448d069621c5" }
|
||||
blade-util = { git = "https://github.com/kvark/blade", rev = "091a8401033847bb9b6ace3fcf70448d069621c5" }
|
||||
blake3 = "1.5.3"
|
||||
bytes = "1.0"
|
||||
cargo_metadata = "0.19"
|
||||
@@ -405,10 +384,10 @@ chrono = { version = "0.4", features = ["serde"] }
|
||||
clap = { version = "4.4", features = ["derive"] }
|
||||
cocoa = "0.26"
|
||||
cocoa-foundation = "0.2.0"
|
||||
convert_case = "0.7.0"
|
||||
convert_case = "0.6.0"
|
||||
core-foundation = "0.9.3"
|
||||
core-foundation-sys = "0.8.6"
|
||||
ctor = "0.3.0"
|
||||
ctor = "0.2.6"
|
||||
dashmap = "6.0"
|
||||
derive_more = "0.99.17"
|
||||
dirs = "4.0"
|
||||
@@ -421,8 +400,7 @@ fork = "0.2.0"
|
||||
futures = "0.3"
|
||||
futures-batch = "0.6.1"
|
||||
futures-lite = "1.13"
|
||||
# TODO: get back to regular versions when https://github.com/rust-lang/git2-rs/pull/1120 is released
|
||||
git2 = { git = "https://github.com/rust-lang/git2-rs", rev = "a3b90cb3756c1bb63e2317bf9cfa57838178de5c", default-features = false }
|
||||
git2 = { version = "0.19", default-features = false }
|
||||
globset = "0.4"
|
||||
handlebars = "4.3"
|
||||
heed = { version = "0.21.0", features = ["read-txn-no-tls"] }
|
||||
@@ -432,10 +410,8 @@ hyper = "0.14"
|
||||
http = "1.1"
|
||||
ignore = "0.4.22"
|
||||
image = "0.25.1"
|
||||
imara-diff = "0.1.8"
|
||||
indexmap = { version = "2.7.0", features = ["serde"] }
|
||||
indoc = "2"
|
||||
inventory = "0.3.19"
|
||||
itertools = "0.14.0"
|
||||
jsonwebtoken = "9.3"
|
||||
jupyter-protocol = { version = "0.6.0" }
|
||||
@@ -443,13 +419,8 @@ jupyter-websocket-client = { version = "0.9.0" }
|
||||
libc = "0.2"
|
||||
libsqlite3-sys = { version = "0.30.1", features = ["bundled"] }
|
||||
linkify = "0.10.0"
|
||||
linkme = "0.3.31"
|
||||
livekit = { git = "https://github.com/zed-industries/livekit-rust-sdks", rev = "811ceae29fabee455f110c56cd66b3f49a7e5003", features = [
|
||||
"dispatcher",
|
||||
"services-dispatcher",
|
||||
"rustls-tls-native-roots",
|
||||
], default-features = false }
|
||||
log = { version = "0.4.16", features = ["kv_unstable_serde", "serde"] }
|
||||
livekit = { git = "https://github.com/zed-industries/livekit-rust-sdks", rev="060964da10574cd9bf06463a53bf6e0769c5c45e", features = ["dispatcher", "services-dispatcher", "rustls-tls-native-roots"], default-features = false }
|
||||
log = { version = "0.4.25", features = ["kv_unstable_serde", "serde"] }
|
||||
markup5ever_rcdom = "0.3.0"
|
||||
nanoid = "0.4"
|
||||
nbformat = { version = "0.10.0" }
|
||||
@@ -469,13 +440,11 @@ pet-poetry = { git = "https://github.com/microsoft/python-environment-tools.git"
|
||||
pet-reporter = { git = "https://github.com/microsoft/python-environment-tools.git", rev = "1abe5cec5ebfbe97ca71746a4cfc7fe89bddf8e0" }
|
||||
postage = { version = "0.5", features = ["futures-traits"] }
|
||||
pretty_assertions = { version = "1.3.0", features = ["unstable"] }
|
||||
proc-macro2 = "1.0.93"
|
||||
profiling = "1"
|
||||
prost = "0.9"
|
||||
prost-build = "0.9"
|
||||
prost-types = "0.9"
|
||||
pulldown-cmark = { version = "0.12.0", default-features = false }
|
||||
quote = "1.0.9"
|
||||
rand = "0.8.5"
|
||||
rayon = "1.8"
|
||||
regex = "1.5"
|
||||
@@ -495,8 +464,8 @@ runtimelib = { version = "0.25.0", default-features = false, features = [
|
||||
rustc-demangle = "0.1.23"
|
||||
rust-embed = { version = "8.4", features = ["include-exclude"] }
|
||||
rustc-hash = "2.1.0"
|
||||
rustls = { version = "0.23.22" }
|
||||
rustls-platform-verifier = "0.5.0"
|
||||
rustls = "0.21.12"
|
||||
rustls-native-certs = "0.8.0"
|
||||
schemars = { version = "0.8", features = ["impl_json_schema", "indexmap2"] }
|
||||
semver = "1.0"
|
||||
serde = { version = "1.0", features = ["derive", "rc"] }
|
||||
@@ -511,15 +480,14 @@ sha2 = "0.10"
|
||||
shellexpand = "2.1.0"
|
||||
shlex = "1.3.0"
|
||||
signal-hook = "0.3.17"
|
||||
similar = "1.3"
|
||||
simplelog = "0.12.2"
|
||||
smallvec = { version = "1.6", features = ["union"] }
|
||||
smol = "2.0"
|
||||
sqlformat = "0.2"
|
||||
streaming-iterator = "0.1"
|
||||
strsim = "0.11"
|
||||
strum = { version = "0.26.0", features = ["derive"] }
|
||||
subtle = "2.5.0"
|
||||
syn = { version = "1.0.72", features = ["full", "extra-traits"] }
|
||||
sys-locale = "0.3.1"
|
||||
sysinfo = "0.31.0"
|
||||
take-until = "0.2.0"
|
||||
@@ -537,50 +505,48 @@ tiny_http = "0.8"
|
||||
toml = "0.8"
|
||||
tokio = { version = "1" }
|
||||
tower-http = "0.4.4"
|
||||
tree-sitter = { version = "0.25.2", features = ["wasm"] }
|
||||
tree-sitter = { version = "0.23", features = ["wasm"] }
|
||||
tree-sitter-bash = "0.23"
|
||||
tree-sitter-c = "0.23"
|
||||
tree-sitter-cpp = "0.23"
|
||||
tree-sitter-css = "0.23"
|
||||
tree-sitter-css = "0.23.2"
|
||||
tree-sitter-elixir = "0.3"
|
||||
tree-sitter-embedded-template = "0.23.0"
|
||||
tree-sitter-gitcommit = {git = "https://github.com/zed-industries/tree-sitter-git-commit", rev = "88309716a69dd13ab83443721ba6e0b491d37ee9"}
|
||||
tree-sitter-go = "0.23"
|
||||
tree-sitter-go-mod = { git = "https://github.com/camdencheek/tree-sitter-go-mod", rev = "6efb59652d30e0e9cd5f3b3a669afd6f1a926d3c", package = "tree-sitter-gomod" }
|
||||
tree-sitter-gowork = { git = "https://github.com/zed-industries/tree-sitter-go-work", rev = "acb0617bf7f4fda02c6217676cc64acb89536dc7" }
|
||||
tree-sitter-heex = { git = "https://github.com/zed-industries/tree-sitter-heex", rev = "1dd45142fbb05562e35b2040c6129c9bca346592" }
|
||||
tree-sitter-diff = "0.1.0"
|
||||
tree-sitter-html = "0.23"
|
||||
tree-sitter-html = "0.20"
|
||||
tree-sitter-jsdoc = "0.23"
|
||||
tree-sitter-json = "0.24"
|
||||
tree-sitter-md = { git = "https://github.com/tree-sitter-grammars/tree-sitter-markdown", rev = "9a23c1a96c0513d8fc6520972beedd419a973539" }
|
||||
tree-sitter-python = "0.23"
|
||||
tree-sitter-regex = "0.24"
|
||||
tree-sitter-regex = "0.23"
|
||||
tree-sitter-ruby = "0.23"
|
||||
tree-sitter-rust = "0.23"
|
||||
tree-sitter-typescript = "0.23"
|
||||
tree-sitter-yaml = { git = "https://github.com/zed-industries/tree-sitter-yaml", rev = "baff0b51c64ef6a1fb1f8390f3ad6015b83ec13a" }
|
||||
unicase = "2.6"
|
||||
unindent = "0.2.0"
|
||||
unindent = "0.1.7"
|
||||
unicode-segmentation = "1.10"
|
||||
unicode-script = "0.5.7"
|
||||
url = "2.2"
|
||||
uuid = { version = "1.1.2", features = ["v4", "v5", "v7", "serde"] }
|
||||
wasmparser = "0.221"
|
||||
wasm-encoder = "0.221"
|
||||
wasmtime = { version = "29", default-features = false, features = [
|
||||
wasmparser = "0.215"
|
||||
wasm-encoder = "0.215"
|
||||
wasmtime = { version = "24", default-features = false, features = [
|
||||
"async",
|
||||
"demangle",
|
||||
"runtime",
|
||||
"cranelift",
|
||||
"component-model",
|
||||
] }
|
||||
wasmtime-wasi = "29"
|
||||
wasmtime-wasi = "24"
|
||||
which = "6.0.0"
|
||||
wit-component = "0.221"
|
||||
zed_llm_client = "0.4"
|
||||
wit-component = "0.201"
|
||||
zstd = "0.11"
|
||||
metal = "0.31"
|
||||
metal = "0.30"
|
||||
|
||||
[workspace.dependencies.async-stripe]
|
||||
git = "https://github.com/zed-industries/async-stripe"
|
||||
@@ -639,7 +605,6 @@ features = [
|
||||
# TODO livekit https://github.com/RustAudio/cpal/pull/891
|
||||
[patch.crates-io]
|
||||
cpal = { git = "https://github.com/zed-industries/cpal", rev = "fd8bc2fd39f1f5fdee5a0690656caff9a26d9d50" }
|
||||
real-async-tls = { git = "https://github.com/zed-industries/async-tls", rev = "1e759a4b5e370f87dc15e40756ac4f8815b61d9d", package = "async-tls"}
|
||||
|
||||
[profile.dev]
|
||||
split-debuginfo = "unpacked"
|
||||
@@ -693,6 +658,7 @@ 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]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Copyright 2022 - 2025 Zed Industries, Inc.
|
||||
Copyright 2022 - 2024 Zed Industries, Inc.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Copyright 2022 - 2025 Zed Industries, Inc.
|
||||
Copyright 2022 - 2024 Zed Industries, Inc.
|
||||
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="283.6413 127.3453 56 55.9999" width="16px" height="16px">
|
||||
<path d="M 808.592 158.131 C 807.489 158.131 806.592 157.234 806.592 156.131 C 806.592 155.028 807.489 154.131 808.592 154.131 C 809.695 154.131 810.592 155.028 810.592 156.131 C 810.592 157.234 809.695 158.131 808.592 158.131 Z M 776.705 185.039 L 773.457 183.145 L 780.122 178.979 L 779.062 177.283 L 771.505 182.006 L 765.592 178.557 L 765.592 169.666 L 771.147 165.963 L 770.037 164.299 L 764.551 167.956 L 758.592 164.551 L 758.592 159.711 L 765.088 155.999 L 764.096 154.263 L 758.592 157.408 L 758.592 153.711 L 764.592 150.283 L 770.592 153.711 L 770.592 157.565 L 766.077 160.274 L 767.107 161.988 L 771.592 159.297 L 776.077 161.988 L 777.107 160.274 L 772.592 157.565 L 772.592 153.666 L 778.147 149.963 C 778.425 149.777 778.592 149.465 778.592 149.131 L 778.592 142.131 L 776.592 142.131 L 776.592 148.596 L 771.551 151.956 L 765.592 148.551 L 765.592 139.705 L 770.592 136.789 L 770.592 145.131 L 772.592 145.131 L 772.592 135.622 L 776.705 133.223 L 784.592 135.852 L 784.592 164.565 L 770.077 173.274 L 771.107 174.988 L 784.592 166.897 L 784.592 182.41 L 776.705 185.039 Z M 806.592 169.131 C 806.592 170.234 805.695 171.131 804.592 171.131 C 803.489 171.131 802.592 170.234 802.592 169.131 C 802.592 168.028 803.489 167.131 804.592 167.131 C 805.695 167.131 806.592 168.028 806.592 169.131 Z M 796.592 179.131 C 796.592 180.234 795.695 181.131 794.592 181.131 C 793.489 181.131 792.592 180.234 792.592 179.131 C 792.592 178.028 793.489 177.131 794.592 177.131 C 795.695 177.131 796.592 178.028 796.592 179.131 Z M 795.592 139.131 C 795.592 138.028 796.489 137.131 797.592 137.131 C 798.695 137.131 799.592 138.028 799.592 139.131 C 799.592 140.234 798.695 141.131 797.592 141.131 C 796.489 141.131 795.592 140.234 795.592 139.131 Z M 808.592 152.131 C 806.733 152.131 805.181 153.411 804.734 155.131 L 786.592 155.131 L 786.592 150.131 L 797.592 150.131 C 798.145 150.131 798.592 149.683 798.592 149.131 L 798.592 142.989 C 800.312 142.542 801.592 140.989 801.592 139.131 C 801.592 136.925 799.798 135.131 797.592 135.131 C 795.386 135.131 793.592 136.925 793.592 139.131 C 793.592 140.989 794.872 142.542 796.592 142.989 L 796.592 148.131 L 786.592 148.131 L 786.592 135.131 C 786.592 134.7 786.317 134.319 785.908 134.182 L 776.908 131.182 C 776.634 131.092 776.336 131.122 776.088 131.267 L 764.088 138.267 C 763.78 138.446 763.592 138.776 763.592 139.131 L 763.592 148.551 L 757.096 152.263 C 756.784 152.441 756.592 152.772 756.592 153.131 L 756.592 165.131 C 756.592 165.49 756.784 165.821 757.096 165.999 L 763.592 169.711 L 763.592 179.131 C 763.592 179.486 763.78 179.816 764.088 179.995 L 776.088 186.995 C 776.242 187.085 776.417 187.131 776.592 187.131 C 776.698 187.131 776.805 187.114 776.908 187.08 L 785.908 184.08 C 786.317 183.943 786.592 183.562 786.592 183.131 L 786.592 171.131 L 793.592 171.131 L 793.592 175.273 C 791.872 175.72 790.592 177.273 790.592 179.131 C 790.592 181.337 792.386 183.131 794.592 183.131 C 796.798 183.131 798.592 181.337 798.592 179.131 C 798.592 177.273 797.312 175.72 795.592 175.273 L 795.592 170.131 C 795.592 169.579 795.145 169.131 794.592 169.131 L 786.592 169.131 L 786.592 164.131 L 799.092 164.131 L 801.23 166.981 C 800.831 167.603 800.592 168.338 800.592 169.131 C 800.592 171.337 802.386 173.131 804.592 173.131 C 806.798 173.131 808.592 171.337 808.592 169.131 C 808.592 166.925 806.798 165.131 804.592 165.131 C 803.908 165.131 803.274 165.319 802.711 165.623 L 800.392 162.531 C 800.203 162.279 799.906 162.131 799.592 162.131 L 786.592 162.131 L 786.592 157.131 L 804.734 157.131 C 805.181 158.851 806.733 160.131 808.592 160.131 C 810.798 160.131 812.592 158.337 812.592 156.131 C 812.592 153.925 810.798 152.131 808.592 152.131 Z" fill-rule="evenodd" fill-opacity="1" style="" id="object-0" transform="matrix(1, 0, 0, 1, -472.9506530761719, -3.7858259677886963)"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.9 KiB |
@@ -1 +0,0 @@
|
||||
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>DeepSeek</title><path d="M23.748 4.482c-.254-.124-.364.113-.512.234-.051.039-.094.09-.137.136-.372.397-.806.657-1.373.626-.829-.046-1.537.214-2.163.848-.133-.782-.575-1.248-1.247-1.548-.352-.156-.708-.311-.955-.65-.172-.241-.219-.51-.305-.774-.055-.16-.11-.323-.293-.35-.2-.031-.278.136-.356.276-.313.572-.434 1.202-.422 1.84.027 1.436.633 2.58 1.838 3.393.137.093.172.187.129.323-.082.28-.18.552-.266.833-.055.179-.137.217-.329.14a5.526 5.526 0 01-1.736-1.18c-.857-.828-1.631-1.742-2.597-2.458a11.365 11.365 0 00-.689-.471c-.985-.957.13-1.743.388-1.836.27-.098.093-.432-.779-.428-.872.004-1.67.295-2.687.684a3.055 3.055 0 01-.465.137 9.597 9.597 0 00-2.883-.102c-1.885.21-3.39 1.102-4.497 2.623C.082 8.606-.231 10.684.152 12.85c.403 2.284 1.569 4.175 3.36 5.653 1.858 1.533 3.997 2.284 6.438 2.14 1.482-.085 3.133-.284 4.994-1.86.47.234.962.327 1.78.397.63.059 1.236-.03 1.705-.128.735-.156.684-.837.419-.961-2.155-1.004-1.682-.595-2.113-.926 1.096-1.296 2.746-2.642 3.392-7.003.05-.347.007-.565 0-.845-.004-.17.035-.237.23-.256a4.173 4.173 0 001.545-.475c1.396-.763 1.96-2.015 2.093-3.517.02-.23-.004-.467-.247-.588zM11.581 18c-2.089-1.642-3.102-2.183-3.52-2.16-.392.024-.321.471-.235.763.09.288.207.486.371.739.114.167.192.416-.113.603-.673.416-1.842-.14-1.897-.167-1.361-.802-2.5-1.86-3.301-3.307-.774-1.393-1.224-2.887-1.298-4.482-.02-.386.093-.522.477-.592a4.696 4.696 0 011.529-.039c2.132.312 3.946 1.265 5.468 2.774.868.86 1.525 1.887 2.202 2.891.72 1.066 1.494 2.082 2.48 2.914.348.292.625.514.891.677-.802.09-2.14.11-3.054-.614zm1-6.44a.306.306 0 01.415-.287.302.302 0 01.2.288.306.306 0 01-.31.307.303.303 0 01-.304-.308zm3.11 1.596c-.2.081-.399.151-.59.16a1.245 1.245 0 01-.798-.254c-.274-.23-.47-.358-.552-.758a1.73 1.73 0 01.016-.588c.07-.327-.008-.537-.239-.727-.187-.156-.426-.199-.688-.199a.559.559 0 01-.254-.078c-.11-.054-.2-.19-.114-.358.028-.054.16-.186.192-.21.356-.202.767-.136 1.146.016.352.144.618.408 1.001.782.391.451.462.576.685.914.176.265.336.537.445.848.067.195-.019.354-.25.452z" fill="black"></path></svg>
|
||||
|
Before Width: | Height: | Size: 2.1 KiB |
@@ -1 +0,0 @@
|
||||
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Mistral</title><g><path d="M15 6v4h-2V6h2zm4-4v4h-2V2h2zM3 2H1h2zM1 2h2v20H1V2zm8 12h2v4H9v-4zm8 0h2v8h-2v-8z"></path><path d="M19 2h4v4h-4V2zM3 2h4v4H3V2z" opacity=".4"></path><path d="M15 10V6h8v4h-8zM3 10V6h8v4H3z" opacity=".5"></path><path d="M3 14v-4h20v4z" opacity=".6"></path><path d="M11 14h4v4h-4v-4zm8 0h4v4h-4v-4zM3 14h4v4H3v-4z" opacity=".7"></path><path d="M19 18h4v4h-4v-4zM3 18h4v4H3v-4z" opacity=".8"></path></g></svg>
|
||||
|
Before Width: | Height: | Size: 598 B |
@@ -1 +0,0 @@
|
||||
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="7.25" cy="7.25" r="3" fill="currentColor"></circle></svg>
|
||||
|
Before Width: | Height: | Size: 165 B |
@@ -1,4 +1,8 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10.0001 1.33334H4.00008C3.64646 1.33334 3.30732 1.47382 3.05727 1.72387C2.80722 1.97392 2.66675 2.31305 2.66675 2.66668V13.3333C2.66675 13.687 2.80722 14.0261 3.05727 14.2762C3.30732 14.5262 3.64646 14.6667 4.00008 14.6667H12.0001C12.3537 14.6667 12.6928 14.5262 12.9429 14.2762C13.1929 14.0261 13.3334 13.687 13.3334 13.3333V4.66668L10.0001 1.33334Z" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M9.33325 1.33334V4.00001C9.33325 4.35363 9.47373 4.69277 9.72378 4.94282C9.97383 5.19287 10.313 5.33334 10.6666 5.33334H13.3333" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M3.5 2C3.22386 2 3 2.22386 3 2.5V12.5C3 12.7761 3.22386 13 3.5 13H11.5C11.7761 13 12 12.7761 12 12.5V6H8.5C8.22386 6 8 5.77614 8 5.5V2H3.5ZM9 2.70711L11.2929 5H9V2.70711ZM2 2.5C2 1.67157 2.67157 1 3.5 1H8.5C8.63261 1 8.75979 1.05268 8.85355 1.14645L12.8536 5.14645C12.9473 5.24021 13 5.36739 13 5.5V12.5C13 13.3284 12.3284 14 11.5 14H3.5C2.67157 14 2 13.3284 2 12.5V2.5Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 769 B After Width: | Height: | Size: 567 B |
214
assets/icons/file_icons/file_types.json
Normal file
@@ -0,0 +1,214 @@
|
||||
{
|
||||
"stems": {
|
||||
"Dockerfile": "docker",
|
||||
"Podfile": "ruby",
|
||||
"Procfile": "heroku"
|
||||
},
|
||||
"suffixes": {
|
||||
"Emakefile": "erlang",
|
||||
"aac": "audio",
|
||||
"accdb": "storage",
|
||||
"app.src": "erlang",
|
||||
"astro": "astro",
|
||||
"avi": "video",
|
||||
"avif": "image",
|
||||
"bak": "backup",
|
||||
"bash": "terminal",
|
||||
"bash_aliases": "terminal",
|
||||
"bash_logout": "terminal",
|
||||
"bash_profile": "terminal",
|
||||
"bashrc": "terminal",
|
||||
"bmp": "image",
|
||||
"c": "c",
|
||||
"c++": "cpp",
|
||||
"cc": "cpp",
|
||||
"cjs": "javascript",
|
||||
"coffee": "coffeescript",
|
||||
"conf": "settings",
|
||||
"cpp": "cpp",
|
||||
"css": "css",
|
||||
"csv": "storage",
|
||||
"cxx": "cpp",
|
||||
"cts": "typescript",
|
||||
"dart": "dart",
|
||||
"dat": "storage",
|
||||
"db": "storage",
|
||||
"dbf": "storage",
|
||||
"diff": "diff",
|
||||
"dll": "storage",
|
||||
"doc": "document",
|
||||
"docx": "document",
|
||||
"eex": "elixir",
|
||||
"elm": "elm",
|
||||
"erl": "erlang",
|
||||
"escript": "erlang",
|
||||
"eslintrc": "eslint",
|
||||
"eslintrc.js": "eslint",
|
||||
"eslintrc.json": "eslint",
|
||||
"ex": "elixir",
|
||||
"exs": "elixir",
|
||||
"fish": "terminal",
|
||||
"flac": "audio",
|
||||
"fmp": "storage",
|
||||
"fp7": "storage",
|
||||
"frm": "storage",
|
||||
"fs": "fsharp",
|
||||
"gdb": "storage",
|
||||
"gif": "image",
|
||||
"gitattributes": "vcs",
|
||||
"gitignore": "vcs",
|
||||
"gitkeep": "vcs",
|
||||
"gitmodules": "vcs",
|
||||
"TAG_EDITMSG": "vcs",
|
||||
"MERGE_MSG": "vcs",
|
||||
"COMMIT_EDITMSG": "vcs",
|
||||
"NOTES_EDITMSG": "vcs",
|
||||
"EDIT_DESCRIPTION": "vcs",
|
||||
"gleam": "gleam",
|
||||
"go": "go",
|
||||
"gql": "graphql",
|
||||
"graphql": "graphql",
|
||||
"graphqls": "graphql",
|
||||
"h": "c",
|
||||
"handlebars": "code",
|
||||
"hbs": "template",
|
||||
"hcl": "hcl",
|
||||
"heex": "elixir",
|
||||
"heic": "image",
|
||||
"heif": "image",
|
||||
"hh": "cpp",
|
||||
"hpp": "cpp",
|
||||
"hrl": "erlang",
|
||||
"hs": "haskell",
|
||||
"htm": "template",
|
||||
"html": "template",
|
||||
"hxx": "cpp",
|
||||
"ib": "storage",
|
||||
"ico": "image",
|
||||
"ini": "settings",
|
||||
"inl": "cpp",
|
||||
"j2k": "image",
|
||||
"java": "java",
|
||||
"jfif": "image",
|
||||
"jl": "julia",
|
||||
"jp2": "image",
|
||||
"jpeg": "image",
|
||||
"jpg": "image",
|
||||
"js": "javascript",
|
||||
"json": "storage",
|
||||
"jsonc": "storage",
|
||||
"jsx": "react",
|
||||
"jxl": "image",
|
||||
"kt": "kotlin",
|
||||
"ldf": "storage",
|
||||
"lock": "lock",
|
||||
"lockb": "bun",
|
||||
"log": "log",
|
||||
"lua": "lua",
|
||||
"m4a": "audio",
|
||||
"m4v": "video",
|
||||
"markdown": "document",
|
||||
"md": "document",
|
||||
"mdb": "storage",
|
||||
"mdf": "storage",
|
||||
"mdx": "document",
|
||||
"metadata": "code",
|
||||
"metal": "metal",
|
||||
"mjs": "javascript",
|
||||
"mka": "audio",
|
||||
"mkv": "video",
|
||||
"ml": "ocaml",
|
||||
"mli": "ocaml",
|
||||
"mod": "go",
|
||||
"mov": "video",
|
||||
"mp3": "audio",
|
||||
"mp4": "video",
|
||||
"mts": "typescript",
|
||||
"myd": "storage",
|
||||
"myi": "storage",
|
||||
"nim": "nim",
|
||||
"nix": "nix",
|
||||
"nu": "terminal",
|
||||
"odp": "document",
|
||||
"ods": "document",
|
||||
"odt": "document",
|
||||
"ogg": "audio",
|
||||
"opus": "audio",
|
||||
"otf": "font",
|
||||
"pcss": "css",
|
||||
"pdb": "storage",
|
||||
"pdf": "document",
|
||||
"php": "php",
|
||||
"plist": "template",
|
||||
"png": "image",
|
||||
"postcss": "css",
|
||||
"ppt": "document",
|
||||
"pptx": "document",
|
||||
"prettierignore": "prettier",
|
||||
"prettierrc": "prettier",
|
||||
"prisma": "prisma",
|
||||
"profile": "terminal",
|
||||
"ps1": "terminal",
|
||||
"psd": "image",
|
||||
"py": "python",
|
||||
"qoi": "image",
|
||||
"r": "r",
|
||||
"rb": "ruby",
|
||||
"rebar.config": "erlang",
|
||||
"rkt": "code",
|
||||
"roc": "roc",
|
||||
"rs": "rust",
|
||||
"rtf": "document",
|
||||
"sass": "sass",
|
||||
"sav": "storage",
|
||||
"sc": "scala",
|
||||
"scala": "scala",
|
||||
"scm": "code",
|
||||
"scss": "sass",
|
||||
"sdf": "storage",
|
||||
"sh": "terminal",
|
||||
"sql": "storage",
|
||||
"sqlite": "storage",
|
||||
"svelte": "template",
|
||||
"svg": "image",
|
||||
"swift": "swift",
|
||||
"tcl": "tcl",
|
||||
"tf": "terraform",
|
||||
"tfvars": "terraform",
|
||||
"tiff": "image",
|
||||
"toml": "toml",
|
||||
"ts": "typescript",
|
||||
"tsv": "storage",
|
||||
"tsx": "react",
|
||||
"ttf": "font",
|
||||
"txt": "document",
|
||||
"v": "v",
|
||||
"vsh": "v",
|
||||
"vv": "v",
|
||||
"vue": "vue",
|
||||
"wav": "audio",
|
||||
"webm": "video",
|
||||
"webp": "image",
|
||||
"wma": "audio",
|
||||
"wmv": "video",
|
||||
"woff": "font",
|
||||
"woff2": "font",
|
||||
"work": "go",
|
||||
"wv": "audio",
|
||||
"xls": "document",
|
||||
"xlsx": "document",
|
||||
"xml": "template",
|
||||
"xrl": "erlang",
|
||||
"yaml": "settings",
|
||||
"yml": "settings",
|
||||
"yrl": "erlang",
|
||||
"zig": "zig",
|
||||
"zlogin": "terminal",
|
||||
"zsh": "terminal",
|
||||
"zsh_aliases": "terminal",
|
||||
"zsh_histfile": "terminal",
|
||||
"zsh_profile": "terminal",
|
||||
"zshenv": "terminal",
|
||||
"zshrc": "terminal"
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M13.3333 13.3333C13.6869 13.3333 14.026 13.1929 14.2761 12.9428C14.5261 12.6928 14.6666 12.3536 14.6666 12V5.33333C14.6666 4.97971 14.5261 4.64057 14.2761 4.39052C14.026 4.14048 13.6869 4 13.3333 4H8.06659C7.84359 4.00219 7.62362 3.94841 7.42679 3.84359C7.22996 3.73877 7.06256 3.58625 6.93992 3.4L6.39992 2.6C6.27851 2.41565 6.11324 2.26432 5.91892 2.1596C5.7246 2.05488 5.50732 2.00004 5.28659 2H2.66659C2.31296 2 1.97382 2.14048 1.72378 2.39052C1.47373 2.64057 1.33325 2.97971 1.33325 3.33333V12C1.33325 12.3536 1.47373 12.6928 1.72378 12.9428C1.97382 13.1929 2.31296 13.3333 2.66659 13.3333H13.3333Z" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M8.26046 3.97337C8.3527 4.17617 8.4795 4.47151 8.57375 4.69341C8.65258 4.87898 8.83437 4.99999 9.03599 4.99999H12.5C12.7761 4.99999 13 5.22385 13 5.49999V12.125C13 12.4011 12.7761 12.625 12.5 12.625H3.5C3.22386 12.625 3 12.4011 3 12.125V3.86932C3 3.59318 3.22386 3.36932 3.5 3.36932H7.34219C7.74141 3.36932 8.09483 3.60924 8.26046 3.97337Z" stroke="black" stroke-width="1.5" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 800 B After Width: | Height: | Size: 512 B |
@@ -1,12 +1 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_2226_61)">
|
||||
<path d="M7.99992 14.6667C11.6818 14.6667 14.6666 11.6819 14.6666 8C14.6666 4.3181 11.6818 1.33333 7.99992 1.33333C4.31802 1.33333 1.33325 4.3181 1.33325 8C1.33325 11.6819 4.31802 14.6667 7.99992 14.6667Z" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M7.99992 1.33333C6.28807 3.13076 5.33325 5.51782 5.33325 8C5.33325 10.4822 6.28807 12.8692 7.99992 14.6667C9.71176 12.8692 10.6666 10.4822 10.6666 8C10.6666 5.51782 9.71176 3.13076 7.99992 1.33333Z" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M1.33325 8H14.6666" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_2226_61">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</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-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: 937 B After Width: | Height: | Size: 327 B |
@@ -1,6 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5 5C5 3.89543 5.89543 3 7 3H9C10.1046 3 11 3.89543 11 5V6H5V5Z" stroke="black" stroke-width="1.5"/>
|
||||
<path d="M8 9V11" stroke="black" stroke-width="1.5" stroke-linecap="round"/>
|
||||
<circle cx="8" cy="9" r="1" fill="black"/>
|
||||
<rect x="3.75" y="5.75" width="8.5" height="7.5" rx="1.25" stroke="black" stroke-width="1.5" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 452 B |
@@ -1,6 +1,4 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5.26659 13.3333C6.53897 13.986 8.00264 14.1628 9.39384 13.8319C10.785 13.5009 12.0123 12.6839 12.8544 11.5281C13.6966 10.3724 14.0982 8.95381 13.987 7.52811C13.8758 6.10241 13.259 4.76332 12.2478 3.75213C11.2366 2.74095 9.89751 2.12417 8.47181 2.01295C7.04611 1.90173 5.62757 2.30337 4.4718 3.1455C3.31603 3.98764 2.49905 5.21488 2.16807 6.60608C1.83709 7.99728 2.01388 9.46095 2.66659 10.7333L1.33325 14.6667L5.26659 13.3333Z" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M5.33325 8H5.33992" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M8 8H8.00667" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M10.6667 8H10.6734" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5.46115 8.43419C7.30678 8.43419 8.92229 7.43411 8.92229 5.21171C8.92229 2.98933 7.30678 1.98926 5.46115 1.98926C3.61553 1.98926 2 2.98933 2 5.21171C2 6.028 2.21794 6.67935 2.58519 7.17685C2.7184 7.35732 2.69033 7.77795 2.58387 7.97539C2.32908 8.44793 2.81048 8.9657 3.33372 8.84571C3.72539 8.75597 4.13621 8.63447 4.49574 8.4715C4.62736 8.41181 4.7727 8.38777 4.91631 8.40402C5.09471 8.42416 5.27678 8.43419 5.46115 8.43419Z" fill="black" stroke="black" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M11.3385 6.24835C11.7049 6.74561 11.9224 7.39641 11.9224 8.2117C11.9224 9.02799 11.7044 9.67934 11.3372 10.1768C11.204 10.3573 11.232 10.7779 11.3385 10.9754C11.5933 11.4479 11.1119 11.9657 10.5886 11.8457C10.197 11.756 9.78615 11.6345 9.42662 11.4715C9.295 11.4118 9.14966 11.3878 9.00605 11.404C8.82765 11.4242 8.64558 11.4342 8.46121 11.4342C7.61469 11.4342 6.81658 11.2238 6.20055 10.7816" stroke="black" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 954 B After Width: | Height: | Size: 1.1 KiB |
@@ -1,5 +1,5 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7 8.9V11C5.34478 11 4.65522 11 3 11V10.4L7 5.6V5H3V7.1" stroke="black" stroke-width="1.5"/>
|
||||
<path d="M12 5L14 8L12 11" stroke="black" stroke-width="1.5"/>
|
||||
<path d="M10 6.5L11 8L10 9.5" stroke="black" stroke-width="1.5"/>
|
||||
<path d="M7.5 8.9V11C5.43097 11 4.56903 11 2.5 11V10.4L7.5 5.6V5H2.5V7.1" stroke="black" stroke-width="1.5"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 342 B After Width: | Height: | Size: 334 B |
@@ -1,19 +0,0 @@
|
||||
<svg width="550" height="128" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<pattern id="tilePattern" width="23" height="23" patternUnits="userSpaceOnUse">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 5L14 8L12 11" stroke="black" stroke-width="1.5"/>
|
||||
<path d="M10 6.5L11 8L10 9.5" stroke="black" stroke-width="1.5"/>
|
||||
<path d="M7.5 8.9V11C5.43097 11 4.56903 11 2.5 11V10.4L7.5 5.6V5H2.5V7.1" stroke="black" stroke-width="1.5"/>
|
||||
</svg>
|
||||
</pattern>
|
||||
<linearGradient id="fade" y2="1" x2="0">
|
||||
<stop offset="0" stop-color="white" stop-opacity=".24"/>
|
||||
<stop offset="1" stop-color="white" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<mask id="fadeMask" maskContentUnits="objectBoundingBox">
|
||||
<rect width="1" height="1" fill="url(#fade)"/>
|
||||
</mask>
|
||||
</defs>
|
||||
<rect width="100%" height="100%" fill="url(#tilePattern)" mask="url(#fadeMask)"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 971 B |
@@ -1,6 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path opacity="0.6" fill-rule="evenodd" clip-rule="evenodd" d="M6.75 9.31247L8.25 10.5576V11.75H1.75V10.0803L4.49751 7.44273L5.65909 8.40693L3.73923 10.25H6.75V9.31247ZM8.25 5.85739V4.25H6.31358L8.25 5.85739ZM1.75 5.16209V7.1H3.25V6.4072L1.75 5.16209Z" fill="black"/>
|
||||
<path opacity="0.6" fill-rule="evenodd" clip-rule="evenodd" d="M10.9624 9.40853L11.9014 8L10.6241 6.08397L9.37598 6.91603L10.0986 8L9.80184 8.44518L10.9624 9.40853Z" fill="black"/>
|
||||
<path opacity="0.6" fill-rule="evenodd" clip-rule="evenodd" d="M12.8936 11.0116L14.9014 8L12.6241 4.58397L11.376 5.41603L13.0986 8L11.7331 10.0483L12.8936 11.0116Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.1225 13.809C14.0341 13.9146 13.877 13.9289 13.7711 13.8409L1.19311 3.40021C1.08659 3.31178 1.07221 3.15362 1.16104 3.04743L1.87752 2.19101C1.96588 2.0854 2.123 2.07112 2.22895 2.15906L14.8069 12.5998C14.9134 12.6882 14.9278 12.8464 14.839 12.9526L14.1225 13.809Z" fill="black"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB |
@@ -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="M15 9.33333L14.5 9.66667L12.5 11L10.5 9.66667L10 9.33333" stroke="black" stroke-width="1.5"/>
|
||||
<path d="M12.5 11V4.5" stroke="black" stroke-width="1.5"/>
|
||||
<path d="M7.5 8.9V11C5.43097 11 4.56903 11 2.5 11V10.4L7.5 5.6V5H2.5V7.1" stroke="black" stroke-width="1.5"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 375 B |
@@ -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="M10 6.66667L10.5 6.33333L12.5 5L14.5 6.33333L15 6.66667" stroke="black" stroke-width="1.5"/>
|
||||
<path d="M12.5 11V5" stroke="black" stroke-width="1.5"/>
|
||||
<path d="M7.5 8.9V11C5.43097 11 4.56903 11 2.5 11V10.4L7.5 5.6V5H2.5V7.1" stroke="black" stroke-width="1.5"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 372 B |
@@ -24,15 +24,15 @@
|
||||
"shift-escape": "workspace::ToggleZoom",
|
||||
"open": "workspace::Open",
|
||||
"ctrl-o": "workspace::Open",
|
||||
"ctrl-=": ["zed::IncreaseBufferFontSize", { "persist": false }],
|
||||
"ctrl-+": ["zed::IncreaseBufferFontSize", { "persist": false }],
|
||||
"ctrl--": ["zed::DecreaseBufferFontSize", { "persist": false }],
|
||||
"ctrl-0": ["zed::ResetBufferFontSize", { "persist": false }],
|
||||
"ctrl-=": "zed::IncreaseBufferFontSize",
|
||||
"ctrl-+": "zed::IncreaseBufferFontSize",
|
||||
"ctrl--": "zed::DecreaseBufferFontSize",
|
||||
"ctrl-0": "zed::ResetBufferFontSize",
|
||||
"ctrl-,": "zed::OpenSettings",
|
||||
"ctrl-q": "zed::Quit",
|
||||
"f11": "zed::ToggleFullScreen",
|
||||
"ctrl-alt-z": "edit_prediction::RateCompletions",
|
||||
"ctrl-shift-i": "edit_prediction::ToggleMenu"
|
||||
"ctrl-alt-z": "zeta::RateCompletions",
|
||||
"ctrl-shift-i": "inline_completion::ToggleMenu"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -84,12 +84,12 @@
|
||||
"pageup": "editor::MovePageUp",
|
||||
"alt-pageup": "editor::PageUp",
|
||||
"shift-pageup": "editor::SelectPageUp",
|
||||
"home": ["editor::MoveToBeginningOfLine", { "stop_at_soft_wraps": true, "stop_at_indent": true }],
|
||||
"home": "editor::MoveToBeginningOfLine",
|
||||
"down": "editor::MoveDown",
|
||||
"pagedown": "editor::MovePageDown",
|
||||
"alt-pagedown": "editor::PageDown",
|
||||
"shift-pagedown": "editor::SelectPageDown",
|
||||
"end": ["editor::MoveToEndOfLine", { "stop_at_soft_wraps": true }],
|
||||
"end": "editor::MoveToEndOfLine",
|
||||
"left": "editor::MoveLeft",
|
||||
"right": "editor::MoveRight",
|
||||
"ctrl-left": "editor::MoveToPreviousWordStart",
|
||||
@@ -107,23 +107,22 @@
|
||||
"ctrl-a": "editor::SelectAll",
|
||||
"ctrl-l": "editor::SelectLine",
|
||||
"ctrl-shift-i": "editor::Format",
|
||||
// "cmd-shift-left": ["editor::SelectToBeginningOfLine", {"stop_at_soft_wraps": true, "stop_at_indent": true }],
|
||||
// "ctrl-shift-a": ["editor::SelectToBeginningOfLine", { "stop_at_soft_wraps": true, "stop_at_indent": true }],
|
||||
"shift-home": ["editor::SelectToBeginningOfLine", { "stop_at_soft_wraps": true, "stop_at_indent": true }],
|
||||
// "cmd-shift-left": ["editor::SelectToBeginningOfLine", {"stop_at_soft_wraps": true }],
|
||||
// "ctrl-shift-a": ["editor::SelectToBeginningOfLine", { "stop_at_soft_wraps": true }],
|
||||
"shift-home": ["editor::SelectToBeginningOfLine", { "stop_at_soft_wraps": true }],
|
||||
// "cmd-shift-right": ["editor::SelectToEndOfLine", { "stop_at_soft_wraps": true }],
|
||||
// "ctrl-shift-e": ["editor::SelectToEndOfLine", { "stop_at_soft_wraps": true }],
|
||||
"shift-end": ["editor::SelectToEndOfLine", { "stop_at_soft_wraps": true }],
|
||||
// "alt-v": ["editor::MovePageUp", { "center_cursor": true }],
|
||||
"ctrl-alt-space": "editor::ShowCharacterPalette",
|
||||
"ctrl-;": "editor::ToggleLineNumbers",
|
||||
"ctrl-k ctrl-r": "git::Restore",
|
||||
"ctrl-'": "editor::ToggleSelectedDiffHunks",
|
||||
"ctrl-\"": "editor::ExpandAllDiffHunks",
|
||||
"ctrl-k ctrl-r": "editor::RevertSelectedHunks",
|
||||
"ctrl-'": "editor::ToggleHunkDiff",
|
||||
"ctrl-\"": "editor::ExpandAllHunkDiffs",
|
||||
"ctrl-i": "editor::ShowSignatureHelp",
|
||||
"alt-g b": "editor::ToggleGitBlame",
|
||||
"menu": "editor::OpenContextMenu",
|
||||
"shift-f10": "editor::OpenContextMenu",
|
||||
"ctrl-shift-e": "editor::ToggleEditPrediction"
|
||||
"shift-f10": "editor::OpenContextMenu"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -137,26 +136,25 @@
|
||||
"ctrl-k z": "editor::ToggleSoftWrap",
|
||||
"find": "buffer_search::Deploy",
|
||||
"ctrl-f": "buffer_search::Deploy",
|
||||
"ctrl-h": "buffer_search::DeployReplace",
|
||||
"ctrl-h": ["buffer_search::Deploy", { "replace_enabled": true }],
|
||||
// "cmd-e": ["buffer_search::Deploy", { "focus": false }],
|
||||
"ctrl->": "assistant::QuoteSelection",
|
||||
"ctrl-<": "assistant::InsertIntoEditor",
|
||||
"ctrl-alt-e": "editor::SelectEnclosingSymbol",
|
||||
"alt-enter": "editor::OpenSelectionsInMultibuffer"
|
||||
"ctrl-alt-e": "editor::SelectEnclosingSymbol"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "Editor && mode == full && edit_prediction",
|
||||
"context": "Editor && mode == full && inline_completion",
|
||||
"bindings": {
|
||||
"alt-]": "editor::NextEditPrediction",
|
||||
"alt-[": "editor::PreviousEditPrediction",
|
||||
"alt-right": "editor::AcceptPartialEditPrediction"
|
||||
"alt-]": "editor::NextInlineCompletion",
|
||||
"alt-[": "editor::PreviousInlineCompletion",
|
||||
"alt-right": "editor::AcceptPartialInlineCompletion"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "Editor && !edit_prediction",
|
||||
"context": "Editor && !inline_completion",
|
||||
"bindings": {
|
||||
"alt-\\": "editor::ShowEditPrediction"
|
||||
"alt-\\": "editor::ShowInlineCompletion"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -184,9 +182,8 @@
|
||||
"ctrl-alt-/": "assistant::ToggleModelSelector",
|
||||
"ctrl-k h": "assistant::DeployHistory",
|
||||
"ctrl-k l": "assistant::DeployPromptLibrary",
|
||||
"new": "assistant::NewChat",
|
||||
"ctrl-t": "assistant::NewChat",
|
||||
"ctrl-n": "assistant::NewChat"
|
||||
"new": "assistant::NewContext",
|
||||
"ctrl-n": "assistant::NewContext"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -205,8 +202,8 @@
|
||||
"enter": "search::SelectNextMatch",
|
||||
"shift-enter": "search::SelectPrevMatch",
|
||||
"alt-enter": "search::SelectAllMatches",
|
||||
"find": "search::FocusSearch",
|
||||
"ctrl-f": "search::FocusSearch",
|
||||
"find": "search::FocusSearch",
|
||||
"ctrl-h": "search::ToggleReplace",
|
||||
"ctrl-l": "search::ToggleSelection"
|
||||
}
|
||||
@@ -276,8 +273,8 @@
|
||||
"ctrl-pagedown": "pane::ActivateNextItem",
|
||||
"ctrl-shift-pageup": "pane::SwapItemLeft",
|
||||
"ctrl-shift-pagedown": "pane::SwapItemRight",
|
||||
"ctrl-f4": ["pane::CloseActiveItem", { "close_pinned": false }],
|
||||
"ctrl-w": ["pane::CloseActiveItem", { "close_pinned": false }],
|
||||
"ctrl-f4": "pane::CloseActiveItem",
|
||||
"ctrl-w": "pane::CloseActiveItem",
|
||||
"alt-ctrl-t": ["pane::CloseInactiveItems", { "close_pinned": false }],
|
||||
"alt-ctrl-shift-w": "workspace::CloseInactiveTabsAndPanes",
|
||||
"ctrl-k e": ["pane::CloseItemsToTheLeft", { "close_pinned": false }],
|
||||
@@ -292,15 +289,15 @@
|
||||
"f3": "search::SelectNextMatch",
|
||||
"ctrl-alt-shift-g": "search::SelectPrevMatch",
|
||||
"shift-f3": "search::SelectPrevMatch",
|
||||
"shift-find": "project_search::ToggleFocus",
|
||||
"ctrl-shift-f": "project_search::ToggleFocus",
|
||||
"shift-find": "project_search::ToggleFocus",
|
||||
"ctrl-alt-shift-h": "search::ToggleReplace",
|
||||
"ctrl-alt-shift-l": "search::ToggleSelection",
|
||||
"alt-enter": "search::SelectAllMatches",
|
||||
"alt-c": "search::ToggleCaseSensitive",
|
||||
"alt-w": "search::ToggleWholeWord",
|
||||
"alt-find": "project_search::ToggleFilters",
|
||||
"alt-ctrl-f": "project_search::ToggleFilters",
|
||||
"alt-find": "project_search::ToggleFilters",
|
||||
"ctrl-alt-shift-r": "search::ToggleRegex",
|
||||
"ctrl-alt-shift-x": "search::ToggleRegex",
|
||||
"alt-r": "search::ToggleRegex",
|
||||
@@ -344,21 +341,21 @@
|
||||
"alt-ctrl-f12": "editor::GoToTypeDefinitionSplit",
|
||||
"alt-shift-f12": "editor::FindAllReferences",
|
||||
"ctrl-m": "editor::MoveToEnclosingBracket",
|
||||
"ctrl-|": "editor::MoveToEnclosingBracket",
|
||||
"ctrl-{": "editor::Fold",
|
||||
"ctrl-}": "editor::UnfoldLines",
|
||||
"ctrl-shift-\\": "editor::MoveToEnclosingBracket",
|
||||
"ctrl-shift-[": "editor::Fold",
|
||||
"ctrl-shift-]": "editor::UnfoldLines",
|
||||
"ctrl-k ctrl-l": "editor::ToggleFold",
|
||||
"ctrl-k ctrl-[": "editor::FoldRecursive",
|
||||
"ctrl-k ctrl-]": "editor::UnfoldRecursive",
|
||||
"ctrl-k ctrl-1": ["editor::FoldAtLevel", 1],
|
||||
"ctrl-k ctrl-2": ["editor::FoldAtLevel", 2],
|
||||
"ctrl-k ctrl-3": ["editor::FoldAtLevel", 3],
|
||||
"ctrl-k ctrl-4": ["editor::FoldAtLevel", 4],
|
||||
"ctrl-k ctrl-5": ["editor::FoldAtLevel", 5],
|
||||
"ctrl-k ctrl-6": ["editor::FoldAtLevel", 6],
|
||||
"ctrl-k ctrl-7": ["editor::FoldAtLevel", 7],
|
||||
"ctrl-k ctrl-8": ["editor::FoldAtLevel", 8],
|
||||
"ctrl-k ctrl-9": ["editor::FoldAtLevel", 9],
|
||||
"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-j": "editor::UnfoldAll",
|
||||
"ctrl-space": "editor::ShowCompletions",
|
||||
@@ -368,12 +365,7 @@
|
||||
"ctrl-\\": "pane::SplitRight",
|
||||
"ctrl-k v": "markdown::OpenPreviewToTheSide",
|
||||
"ctrl-shift-v": "markdown::OpenPreview",
|
||||
"ctrl-alt-shift-c": "editor::DisplayCursorNames",
|
||||
"ctrl-alt-y": "git::ToggleStaged",
|
||||
"alt-y": "git::StageAndNext",
|
||||
"alt-shift-y": "git::UnstageAndNext",
|
||||
"alt-.": "editor::GoToHunk",
|
||||
"alt-,": "editor::GoToPrevHunk"
|
||||
"ctrl-alt-shift-c": "editor::DisplayCursorNames"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -433,20 +425,19 @@
|
||||
"ctrl-shift-m": "diagnostics::Deploy",
|
||||
"ctrl-shift-e": "project_panel::ToggleFocus",
|
||||
"ctrl-shift-b": "outline_panel::ToggleFocus",
|
||||
"ctrl-shift-g": "git_panel::ToggleFocus",
|
||||
"ctrl-?": "assistant::ToggleFocus",
|
||||
"alt-save": "workspace::SaveAll",
|
||||
"ctrl-alt-s": "workspace::SaveAll",
|
||||
"ctrl-k m": "language_selector::Toggle",
|
||||
"escape": "workspace::Unfollow",
|
||||
"ctrl-k ctrl-left": "workspace::ActivatePaneLeft",
|
||||
"ctrl-k ctrl-right": "workspace::ActivatePaneRight",
|
||||
"ctrl-k ctrl-up": "workspace::ActivatePaneUp",
|
||||
"ctrl-k ctrl-down": "workspace::ActivatePaneDown",
|
||||
"ctrl-k shift-left": "workspace::SwapPaneLeft",
|
||||
"ctrl-k shift-right": "workspace::SwapPaneRight",
|
||||
"ctrl-k shift-up": "workspace::SwapPaneUp",
|
||||
"ctrl-k shift-down": "workspace::SwapPaneDown",
|
||||
"ctrl-k ctrl-left": ["workspace::ActivatePaneInDirection", "Left"],
|
||||
"ctrl-k ctrl-right": ["workspace::ActivatePaneInDirection", "Right"],
|
||||
"ctrl-k ctrl-up": ["workspace::ActivatePaneInDirection", "Up"],
|
||||
"ctrl-k ctrl-down": ["workspace::ActivatePaneInDirection", "Down"],
|
||||
"ctrl-k shift-left": ["workspace::SwapPaneInDirection", "Left"],
|
||||
"ctrl-k shift-right": ["workspace::SwapPaneInDirection", "Right"],
|
||||
"ctrl-k shift-up": ["workspace::SwapPaneInDirection", "Up"],
|
||||
"ctrl-k shift-down": ["workspace::SwapPaneInDirection", "Down"],
|
||||
"ctrl-shift-x": "zed::Extensions",
|
||||
"ctrl-shift-r": "task::Rerun",
|
||||
"ctrl-alt-r": "task::Rerun",
|
||||
@@ -460,8 +451,8 @@
|
||||
{
|
||||
"context": "ApplicationMenu",
|
||||
"bindings": {
|
||||
"left": "app_menu::ActivateMenuLeft",
|
||||
"right": "app_menu::ActivateMenuRight"
|
||||
"left": ["app_menu::NavigateApplicationMenuInDirection", "Left"],
|
||||
"right": ["app_menu::NavigateApplicationMenuInDirection", "Right"]
|
||||
}
|
||||
},
|
||||
// Bindings from Sublime Text
|
||||
@@ -503,28 +494,17 @@
|
||||
},
|
||||
{
|
||||
"context": "Editor && showing_completions",
|
||||
"use_key_equivalents": true,
|
||||
"bindings": {
|
||||
"enter": "editor::ConfirmCompletion",
|
||||
"tab": "editor::ComposeCompletion"
|
||||
}
|
||||
},
|
||||
// Bindings for accepting edit predictions
|
||||
//
|
||||
// alt-l is provided as an alternative to tab/alt-tab. and will be displayed in the UI. This is
|
||||
// because alt-tab may not be available, as it is often used for window switching.
|
||||
{
|
||||
"context": "Editor && edit_prediction",
|
||||
"context": "Editor && inline_completion && !showing_completions",
|
||||
"use_key_equivalents": true,
|
||||
"bindings": {
|
||||
"alt-tab": "editor::AcceptEditPrediction",
|
||||
"alt-l": "editor::AcceptEditPrediction",
|
||||
"tab": "editor::AcceptEditPrediction"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "Editor && edit_prediction_conflict",
|
||||
"bindings": {
|
||||
"alt-tab": "editor::AcceptEditPrediction",
|
||||
"alt-l": "editor::AcceptEditPrediction"
|
||||
"tab": "editor::AcceptInlineCompletion"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -548,7 +528,8 @@
|
||||
{
|
||||
"bindings": {
|
||||
"ctrl-alt-shift-f": "workspace::FollowNextCollaborator",
|
||||
"ctrl-alt-i": "zed::DebugElements"
|
||||
"ctrl-alt-i": "zed::DebugElements",
|
||||
"ctrl-:": "editor::ToggleInlayHints"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -562,12 +543,11 @@
|
||||
"bindings": {
|
||||
"alt-enter": "editor::OpenExcerpts",
|
||||
"shift-enter": "editor::ExpandExcerpts",
|
||||
"ctrl-alt-enter": "editor::OpenExcerptsSplit",
|
||||
"ctrl-k enter": "editor::OpenExcerptsSplit",
|
||||
"ctrl-shift-e": "pane::RevealInProjectPanel",
|
||||
"ctrl-f8": "editor::GoToHunk",
|
||||
"ctrl-shift-f8": "editor::GoToPrevHunk",
|
||||
"ctrl-enter": "assistant::InlineAssist",
|
||||
"ctrl-:": "editor::ToggleInlayHints"
|
||||
"ctrl-enter": "assistant::InlineAssist"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -593,7 +573,6 @@
|
||||
"save": "workspace::Save",
|
||||
"ctrl->": "assistant::QuoteSelection",
|
||||
"ctrl-<": "assistant::InsertIntoEditor",
|
||||
"ctrl-alt-/": "assistant::ToggleModelSelector",
|
||||
"shift-enter": "assistant::Split",
|
||||
"ctrl-r": "assistant::CycleMessageRole",
|
||||
"enter": "assistant::ConfirmCommand",
|
||||
@@ -614,12 +593,14 @@
|
||||
},
|
||||
{
|
||||
"context": "MessageEditor > Editor",
|
||||
"use_key_equivalents": true,
|
||||
"bindings": {
|
||||
"enter": "assistant2::Chat"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "ContextStrip",
|
||||
"use_key_equivalents": true,
|
||||
"bindings": {
|
||||
"up": "assistant2::FocusUp",
|
||||
"right": "assistant2::FocusRight",
|
||||
@@ -657,14 +638,14 @@
|
||||
"right": "outline_panel::ExpandSelectedEntry",
|
||||
"alt-copy": "outline_panel::CopyPath",
|
||||
"ctrl-alt-c": "outline_panel::CopyPath",
|
||||
"alt-shift-copy": "workspace::CopyRelativePath",
|
||||
"alt-ctrl-shift-c": "workspace::CopyRelativePath",
|
||||
"alt-shift-copy": "outline_panel::CopyRelativePath",
|
||||
"alt-ctrl-shift-c": "outline_panel::CopyRelativePath",
|
||||
"alt-ctrl-r": "outline_panel::RevealInFileManager",
|
||||
"space": "outline_panel::Open",
|
||||
"shift-down": "menu::SelectNext",
|
||||
"shift-up": "menu::SelectPrev",
|
||||
"alt-enter": "editor::OpenExcerpts",
|
||||
"ctrl-alt-enter": "editor::OpenExcerptsSplit"
|
||||
"ctrl-k enter": "editor::OpenExcerptsSplit"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -686,8 +667,8 @@
|
||||
"ctrl-v": "project_panel::Paste",
|
||||
"alt-copy": "project_panel::CopyPath",
|
||||
"ctrl-alt-c": "project_panel::CopyPath",
|
||||
"alt-shift-copy": "workspace::CopyRelativePath",
|
||||
"alt-ctrl-shift-c": "workspace::CopyRelativePath",
|
||||
"alt-shift-copy": "project_panel::CopyRelativePath",
|
||||
"alt-ctrl-shift-c": "project_panel::CopyRelativePath",
|
||||
"enter": "project_panel::Rename",
|
||||
"f2": "project_panel::Rename",
|
||||
"backspace": ["project_panel::Trash", { "skip_prompt": false }],
|
||||
@@ -697,8 +678,8 @@
|
||||
"ctrl-delete": ["project_panel::Delete", { "skip_prompt": false }],
|
||||
"alt-ctrl-r": "project_panel::RevealInFileManager",
|
||||
"ctrl-shift-enter": "project_panel::OpenWithSystem",
|
||||
"shift-find": "project_panel::NewSearchInDirectory",
|
||||
"ctrl-shift-f": "project_panel::NewSearchInDirectory",
|
||||
"shift-find": "project_panel::NewSearchInDirectory",
|
||||
"shift-down": "menu::SelectNext",
|
||||
"shift-up": "menu::SelectPrev",
|
||||
"escape": "menu::Cancel"
|
||||
@@ -710,47 +691,6 @@
|
||||
"space": "project_panel::Open"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "GitPanel && ChangesList",
|
||||
"bindings": {
|
||||
"up": "menu::SelectPrev",
|
||||
"down": "menu::SelectNext",
|
||||
"enter": "menu::Confirm",
|
||||
"space": "git::ToggleStaged",
|
||||
"ctrl-space": "git::StageAll",
|
||||
"ctrl-shift-space": "git::UnstageAll",
|
||||
"tab": "git_panel::FocusEditor",
|
||||
"shift-tab": "git_panel::FocusEditor",
|
||||
"escape": "git_panel::ToggleFocus",
|
||||
"ctrl-enter": "git::Commit",
|
||||
"alt-enter": "menu::SecondaryConfirm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "GitCommit > Editor",
|
||||
"bindings": {
|
||||
"enter": "editor::Newline",
|
||||
"ctrl-enter": "git::Commit"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "GitPanel > Editor",
|
||||
"bindings": {
|
||||
"escape": "git_panel::FocusChanges",
|
||||
"tab": "git_panel::FocusChanges",
|
||||
"shift-tab": "git_panel::FocusChanges",
|
||||
"ctrl-enter": "git::Commit",
|
||||
"alt-up": "git_panel::FocusChanges"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "GitCommit > Editor",
|
||||
"use_key_equivalents": true,
|
||||
"bindings": {
|
||||
"enter": "editor::Newline",
|
||||
"ctrl-enter": "git::Commit"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "CollabPanel && not_editing",
|
||||
"bindings": {
|
||||
@@ -784,7 +724,13 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "FileFinder || (FileFinder > Picker > Editor) || (FileFinder > Picker > menu)",
|
||||
"context": "FileFinder",
|
||||
"bindings": {
|
||||
"ctrl": "file_finder::ToggleMenu"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "FileFinder && !menu_open",
|
||||
"bindings": {
|
||||
"ctrl-shift-p": "file_finder::SelectPrev",
|
||||
"ctrl-j": "pane::SplitDown",
|
||||
@@ -793,6 +739,15 @@
|
||||
"ctrl-l": "pane::SplitRight"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "FileFinder && menu_open",
|
||||
"bindings": {
|
||||
"j": "pane::SplitDown",
|
||||
"k": "pane::SplitUp",
|
||||
"h": "pane::SplitLeft",
|
||||
"l": "pane::SplitRight"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "TabSwitcher",
|
||||
"bindings": {
|
||||
@@ -813,8 +768,6 @@
|
||||
"shift-insert": "terminal::Paste",
|
||||
"ctrl-shift-v": "terminal::Paste",
|
||||
"ctrl-enter": "assistant::InlineAssist",
|
||||
"alt-b": ["terminal::SendText", "\u001bb"],
|
||||
"alt-f": ["terminal::SendText", "\u001bf"],
|
||||
// Overrides for conflicting keybindings
|
||||
"ctrl-w": ["terminal::SendKeystroke", "ctrl-w"],
|
||||
"ctrl-shift-a": "editor::SelectAll",
|
||||
@@ -829,7 +782,6 @@
|
||||
"pagedown": ["terminal::SendKeystroke", "pagedown"],
|
||||
"escape": ["terminal::SendKeystroke", "escape"],
|
||||
"enter": ["terminal::SendKeystroke", "enter"],
|
||||
"ctrl-b": ["terminal::SendKeystroke", "ctrl-b"],
|
||||
"ctrl-c": ["terminal::SendKeystroke", "ctrl-c"],
|
||||
"shift-pageup": "terminal::ScrollPageUp",
|
||||
"shift-pagedown": "terminal::ScrollPageDown",
|
||||
@@ -839,11 +791,5 @@
|
||||
"shift-end": "terminal::ScrollToBottom",
|
||||
"ctrl-shift-space": "terminal::ToggleViMode"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "ZedPredictModal",
|
||||
"bindings": {
|
||||
"escape": "menu::Cancel"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -28,10 +28,10 @@
|
||||
"cmd-shift-w": "workspace::CloseWindow",
|
||||
"shift-escape": "workspace::ToggleZoom",
|
||||
"cmd-o": "workspace::Open",
|
||||
"cmd-=": ["zed::IncreaseBufferFontSize", { "persist": false }],
|
||||
"cmd-+": ["zed::IncreaseBufferFontSize", { "persist": false }],
|
||||
"cmd--": ["zed::DecreaseBufferFontSize", { "persist": false }],
|
||||
"cmd-0": ["zed::ResetBufferFontSize", { "persist": false }],
|
||||
"cmd-=": "zed::IncreaseBufferFontSize",
|
||||
"cmd-+": "zed::IncreaseBufferFontSize",
|
||||
"cmd--": "zed::DecreaseBufferFontSize",
|
||||
"cmd-0": "zed::ResetBufferFontSize",
|
||||
"cmd-,": "zed::OpenSettings",
|
||||
"cmd-q": "zed::Quit",
|
||||
"cmd-h": "zed::Hide",
|
||||
@@ -39,8 +39,8 @@
|
||||
"cmd-m": "zed::Minimize",
|
||||
"fn-f": "zed::ToggleFullScreen",
|
||||
"ctrl-cmd-f": "zed::ToggleFullScreen",
|
||||
"ctrl-cmd-z": "edit_prediction::RateCompletions",
|
||||
"ctrl-cmd-i": "edit_prediction::ToggleMenu"
|
||||
"ctrl-shift-z": "zeta::RateCompletions",
|
||||
"ctrl-shift-i": "inline_completion::ToggleMenu"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -91,16 +91,14 @@
|
||||
"ctrl-l": "editor::ScrollCursorCenter",
|
||||
"alt-left": "editor::MoveToPreviousWordStart",
|
||||
"alt-right": "editor::MoveToNextWordEnd",
|
||||
"cmd-left": ["editor::MoveToBeginningOfLine", { "stop_at_soft_wraps": true, "stop_at_indent": true }],
|
||||
"ctrl-a": ["editor::MoveToBeginningOfLine", { "stop_at_soft_wraps": false, "stop_at_indent": true }],
|
||||
"home": ["editor::MoveToBeginningOfLine", { "stop_at_soft_wraps": true, "stop_at_indent": true }],
|
||||
"cmd-right": ["editor::MoveToEndOfLine", { "stop_at_soft_wraps": true }],
|
||||
"ctrl-e": ["editor::MoveToEndOfLine", { "stop_at_soft_wraps": false }],
|
||||
"end": ["editor::MoveToEndOfLine", { "stop_at_soft_wraps": true }],
|
||||
"cmd-up": "editor::MoveToStartOfExcerpt",
|
||||
"cmd-down": "editor::MoveToEndOfExcerpt",
|
||||
"cmd-home": "editor::MoveToBeginning", // Typed via `cmd-fn-left`
|
||||
"cmd-end": "editor::MoveToEnd", // Typed via `cmd-fn-right`
|
||||
"cmd-left": "editor::MoveToBeginningOfLine",
|
||||
"ctrl-a": "editor::MoveToBeginningOfLine",
|
||||
"home": "editor::MoveToBeginningOfLine",
|
||||
"cmd-right": "editor::MoveToEndOfLine",
|
||||
"ctrl-e": "editor::MoveToEndOfLine",
|
||||
"end": "editor::MoveToEndOfLine",
|
||||
"cmd-up": "editor::MoveToBeginning",
|
||||
"cmd-down": "editor::MoveToEnd",
|
||||
"shift-up": "editor::SelectUp",
|
||||
"ctrl-shift-p": "editor::SelectUp",
|
||||
"shift-down": "editor::SelectDown",
|
||||
@@ -113,14 +111,14 @@
|
||||
"alt-shift-right": "editor::SelectToNextWordEnd", // cursorWordRightSelect
|
||||
"ctrl-shift-up": "editor::SelectToStartOfParagraph",
|
||||
"ctrl-shift-down": "editor::SelectToEndOfParagraph",
|
||||
"cmd-shift-up": "editor::SelectToStartOfExcerpt",
|
||||
"cmd-shift-down": "editor::SelectToEndOfExcerpt",
|
||||
"cmd-shift-up": "editor::SelectToBeginning",
|
||||
"cmd-shift-down": "editor::SelectToEnd",
|
||||
"cmd-a": "editor::SelectAll",
|
||||
"cmd-l": "editor::SelectLine",
|
||||
"cmd-shift-i": "editor::Format",
|
||||
"cmd-shift-left": ["editor::SelectToBeginningOfLine", { "stop_at_soft_wraps": true, "stop_at_indent": true }],
|
||||
"shift-home": ["editor::SelectToBeginningOfLine", { "stop_at_soft_wraps": true, "stop_at_indent": true }],
|
||||
"ctrl-shift-a": ["editor::SelectToBeginningOfLine", { "stop_at_soft_wraps": true, "stop_at_indent": true }],
|
||||
"cmd-shift-left": ["editor::SelectToBeginningOfLine", { "stop_at_soft_wraps": true }],
|
||||
"shift-home": ["editor::SelectToBeginningOfLine", { "stop_at_soft_wraps": true }],
|
||||
"ctrl-shift-a": ["editor::SelectToBeginningOfLine", { "stop_at_soft_wraps": true }],
|
||||
"cmd-shift-right": ["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 }],
|
||||
@@ -128,17 +126,13 @@
|
||||
"ctrl-shift-v": ["editor::MovePageUp", { "center_cursor": true }],
|
||||
"ctrl-cmd-space": "editor::ShowCharacterPalette",
|
||||
"cmd-;": "editor::ToggleLineNumbers",
|
||||
"cmd-alt-z": "git::Restore",
|
||||
"cmd-alt-y": "git::ToggleStaged",
|
||||
"cmd-y": "git::StageAndNext",
|
||||
"cmd-shift-y": "git::UnstageAndNext",
|
||||
"cmd-'": "editor::ToggleSelectedDiffHunks",
|
||||
"cmd-\"": "editor::ExpandAllDiffHunks",
|
||||
"cmd-alt-z": "editor::RevertSelectedHunks",
|
||||
"cmd-'": "editor::ToggleHunkDiff",
|
||||
"cmd-\"": "editor::ExpandAllHunkDiffs",
|
||||
"cmd-alt-g b": "editor::ToggleGitBlame",
|
||||
"cmd-i": "editor::ShowSignatureHelp",
|
||||
"ctrl-f12": "editor::GoToDeclaration",
|
||||
"alt-ctrl-f12": "editor::GoToDeclarationSplit",
|
||||
"ctrl-cmd-e": "editor::ToggleEditPrediction"
|
||||
"alt-ctrl-f12": "editor::GoToDeclarationSplit"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -151,29 +145,28 @@
|
||||
"cmd-shift-enter": "editor::NewlineAbove",
|
||||
"cmd-k z": "editor::ToggleSoftWrap",
|
||||
"cmd-f": "buffer_search::Deploy",
|
||||
"cmd-alt-f": "buffer_search::DeployReplace",
|
||||
"cmd-alt-f": ["buffer_search::Deploy", { "replace_enabled": true }],
|
||||
"cmd-alt-l": ["buffer_search::Deploy", { "selection_search_enabled": true }],
|
||||
"cmd-e": ["buffer_search::Deploy", { "focus": false }],
|
||||
"cmd->": "assistant::QuoteSelection",
|
||||
"cmd-<": "assistant::InsertIntoEditor",
|
||||
"cmd-alt-e": "editor::SelectEnclosingSymbol",
|
||||
"alt-enter": "editor::OpenSelectionsInMultibuffer"
|
||||
"cmd-alt-e": "editor::SelectEnclosingSymbol"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "Editor && mode == full && edit_prediction",
|
||||
"context": "Editor && mode == full && inline_completion",
|
||||
"use_key_equivalents": true,
|
||||
"bindings": {
|
||||
"alt-tab": "editor::NextEditPrediction",
|
||||
"alt-shift-tab": "editor::PreviousEditPrediction",
|
||||
"ctrl-cmd-right": "editor::AcceptPartialEditPrediction"
|
||||
"alt-tab": "editor::NextInlineCompletion",
|
||||
"alt-shift-tab": "editor::PreviousInlineCompletion",
|
||||
"ctrl-cmd-right": "editor::AcceptPartialInlineCompletion"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "Editor && !edit_prediction",
|
||||
"context": "Editor && !inline_completion",
|
||||
"use_key_equivalents": true,
|
||||
"bindings": {
|
||||
"alt-tab": "editor::ShowEditPrediction"
|
||||
"alt-tab": "editor::ShowInlineCompletion"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -211,8 +204,7 @@
|
||||
"cmd-alt-/": "assistant::ToggleModelSelector",
|
||||
"cmd-k h": "assistant::DeployHistory",
|
||||
"cmd-k l": "assistant::DeployPromptLibrary",
|
||||
"cmd-t": "assistant::NewChat",
|
||||
"cmd-n": "assistant::NewChat"
|
||||
"cmd-n": "assistant::NewContext"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -224,7 +216,6 @@
|
||||
"cmd-s": "workspace::Save",
|
||||
"cmd->": "assistant::QuoteSelection",
|
||||
"cmd-<": "assistant::InsertIntoEditor",
|
||||
"cmd-alt-/": "assistant::ToggleModelSelector",
|
||||
"shift-enter": "assistant::Split",
|
||||
"ctrl-r": "assistant::CycleMessageRole",
|
||||
"enter": "assistant::ConfirmCommand",
|
||||
@@ -289,8 +280,7 @@
|
||||
"alt-enter": "search::SelectAllMatches",
|
||||
"cmd-f": "search::FocusSearch",
|
||||
"cmd-alt-f": "search::ToggleReplace",
|
||||
"cmd-alt-l": "search::ToggleSelection",
|
||||
"cmd-shift-o": "outline::Toggle"
|
||||
"cmd-alt-l": "search::ToggleSelection"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -358,7 +348,7 @@
|
||||
"cmd-}": "pane::ActivateNextItem",
|
||||
"ctrl-shift-pageup": "pane::SwapItemLeft",
|
||||
"ctrl-shift-pagedown": "pane::SwapItemRight",
|
||||
"cmd-w": ["pane::CloseActiveItem", { "close_pinned": false }],
|
||||
"cmd-w": "pane::CloseActiveItem",
|
||||
"alt-cmd-t": ["pane::CloseInactiveItems", { "close_pinned": false }],
|
||||
"ctrl-alt-cmd-w": "workspace::CloseInactiveTabsAndPanes",
|
||||
"cmd-k e": ["pane::CloseItemsToTheLeft", { "close_pinned": false }],
|
||||
@@ -422,15 +412,15 @@
|
||||
"cmd-k cmd-l": "editor::ToggleFold",
|
||||
"cmd-k cmd-[": "editor::FoldRecursive",
|
||||
"cmd-k cmd-]": "editor::UnfoldRecursive",
|
||||
"cmd-k cmd-1": ["editor::FoldAtLevel", 1],
|
||||
"cmd-k cmd-2": ["editor::FoldAtLevel", 2],
|
||||
"cmd-k cmd-3": ["editor::FoldAtLevel", 3],
|
||||
"cmd-k cmd-4": ["editor::FoldAtLevel", 4],
|
||||
"cmd-k cmd-5": ["editor::FoldAtLevel", 5],
|
||||
"cmd-k cmd-6": ["editor::FoldAtLevel", 6],
|
||||
"cmd-k cmd-7": ["editor::FoldAtLevel", 7],
|
||||
"cmd-k cmd-8": ["editor::FoldAtLevel", 8],
|
||||
"cmd-k cmd-9": ["editor::FoldAtLevel", 9],
|
||||
"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-j": "editor::UnfoldAll",
|
||||
// Using `ctrl-space` in Zed requires disabling the macOS global shortcut.
|
||||
@@ -468,7 +458,7 @@
|
||||
"ctrl-9": ["pane::ActivateItem", 8],
|
||||
"ctrl-0": "pane::ActivateLastItem",
|
||||
"ctrl--": "pane::GoBack",
|
||||
"ctrl-_": "pane::GoForward",
|
||||
"ctrl-shift--": "pane::GoForward",
|
||||
"cmd-shift-f": "pane::DeploySearch"
|
||||
}
|
||||
},
|
||||
@@ -513,19 +503,18 @@
|
||||
"cmd-shift-m": "diagnostics::Deploy",
|
||||
"cmd-shift-e": "project_panel::ToggleFocus",
|
||||
"cmd-shift-b": "outline_panel::ToggleFocus",
|
||||
"ctrl-shift-g": "git_panel::ToggleFocus",
|
||||
"cmd-?": "assistant::ToggleFocus",
|
||||
"cmd-alt-s": "workspace::SaveAll",
|
||||
"cmd-k m": "language_selector::Toggle",
|
||||
"escape": "workspace::Unfollow",
|
||||
"cmd-k cmd-left": "workspace::ActivatePaneLeft",
|
||||
"cmd-k cmd-right": "workspace::ActivatePaneRight",
|
||||
"cmd-k cmd-up": "workspace::ActivatePaneUp",
|
||||
"cmd-k cmd-down": "workspace::ActivatePaneDown",
|
||||
"cmd-k shift-left": "workspace::SwapPaneLeft",
|
||||
"cmd-k shift-right": "workspace::SwapPaneRight",
|
||||
"cmd-k shift-up": "workspace::SwapPaneUp",
|
||||
"cmd-k shift-down": "workspace::SwapPaneDown",
|
||||
"cmd-k cmd-left": ["workspace::ActivatePaneInDirection", "Left"],
|
||||
"cmd-k cmd-right": ["workspace::ActivatePaneInDirection", "Right"],
|
||||
"cmd-k cmd-up": ["workspace::ActivatePaneInDirection", "Up"],
|
||||
"cmd-k cmd-down": ["workspace::ActivatePaneInDirection", "Down"],
|
||||
"cmd-k shift-left": ["workspace::SwapPaneInDirection", "Left"],
|
||||
"cmd-k shift-right": ["workspace::SwapPaneInDirection", "Right"],
|
||||
"cmd-k shift-up": ["workspace::SwapPaneInDirection", "Up"],
|
||||
"cmd-k shift-down": ["workspace::SwapPaneInDirection", "Down"],
|
||||
"cmd-shift-x": "zed::Extensions"
|
||||
}
|
||||
},
|
||||
@@ -589,17 +578,10 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "Editor && edit_prediction",
|
||||
"bindings": {
|
||||
"alt-tab": "editor::AcceptEditPrediction",
|
||||
"tab": "editor::AcceptEditPrediction"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "Editor && edit_prediction_conflict",
|
||||
"context": "Editor && inline_completion && !showing_completions",
|
||||
"use_key_equivalents": true,
|
||||
"bindings": {
|
||||
"alt-tab": "editor::AcceptEditPrediction"
|
||||
"tab": "editor::AcceptInlineCompletion"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -628,7 +610,8 @@
|
||||
"ctrl-alt-cmd-f": "workspace::FollowNextCollaborator",
|
||||
// TODO: Move this to a dock open action
|
||||
"cmd-shift-c": "collab_panel::ToggleFocus",
|
||||
"cmd-alt-i": "zed::DebugElements"
|
||||
"cmd-alt-i": "zed::DebugElements",
|
||||
"ctrl-:": "editor::ToggleInlayHints"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -637,12 +620,11 @@
|
||||
"bindings": {
|
||||
"alt-enter": "editor::OpenExcerpts",
|
||||
"shift-enter": "editor::ExpandExcerpts",
|
||||
"cmd-alt-enter": "editor::OpenExcerptsSplit",
|
||||
"cmd-k enter": "editor::OpenExcerptsSplit",
|
||||
"cmd-shift-e": "pane::RevealInProjectPanel",
|
||||
"cmd-f8": "editor::GoToHunk",
|
||||
"cmd-shift-f8": "editor::GoToPrevHunk",
|
||||
"ctrl-enter": "assistant::InlineAssist",
|
||||
"ctrl-:": "editor::ToggleInlayHints"
|
||||
"ctrl-enter": "assistant::InlineAssist"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -678,14 +660,14 @@
|
||||
"escape": "menu::Cancel",
|
||||
"left": "outline_panel::CollapseSelectedEntry",
|
||||
"right": "outline_panel::ExpandSelectedEntry",
|
||||
"cmd-alt-c": "workspace::CopyPath",
|
||||
"alt-cmd-shift-c": "workspace::CopyRelativePath",
|
||||
"cmd-alt-c": "outline_panel::CopyPath",
|
||||
"alt-cmd-shift-c": "outline_panel::CopyRelativePath",
|
||||
"alt-cmd-r": "outline_panel::RevealInFileManager",
|
||||
"space": "outline_panel::Open",
|
||||
"shift-down": "menu::SelectNext",
|
||||
"shift-up": "menu::SelectPrev",
|
||||
"alt-enter": "editor::OpenExcerpts",
|
||||
"cmd-alt-enter": "editor::OpenExcerptsSplit"
|
||||
"cmd-k enter": "editor::OpenExcerptsSplit"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -700,8 +682,8 @@
|
||||
"cmd-x": "project_panel::Cut",
|
||||
"cmd-c": "project_panel::Copy",
|
||||
"cmd-v": "project_panel::Paste",
|
||||
"cmd-alt-c": "workspace::CopyPath",
|
||||
"alt-cmd-shift-c": "workspace::CopyRelativePath",
|
||||
"cmd-alt-c": "project_panel::CopyPath",
|
||||
"alt-cmd-shift-c": "project_panel::CopyRelativePath",
|
||||
"enter": "project_panel::Rename",
|
||||
"f2": "project_panel::Rename",
|
||||
"backspace": ["project_panel::Trash", { "skip_prompt": false }],
|
||||
@@ -724,6 +706,13 @@
|
||||
"space": "project_panel::Open"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "GitPanel && !CommitEditor",
|
||||
"use_key_equivalents": true,
|
||||
"bindings": {
|
||||
"escape": "git_panel::Close"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "GitPanel && ChangesList",
|
||||
"use_key_equivalents": true,
|
||||
@@ -736,29 +725,17 @@
|
||||
"space": "git::ToggleStaged",
|
||||
"cmd-shift-space": "git::StageAll",
|
||||
"ctrl-shift-space": "git::UnstageAll",
|
||||
"alt-down": "git_panel::FocusEditor",
|
||||
"tab": "git_panel::FocusEditor",
|
||||
"shift-tab": "git_panel::FocusEditor",
|
||||
"escape": "git_panel::ToggleFocus"
|
||||
"alt-down": "git_panel::FocusEditor"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "GitPanel > Editor",
|
||||
"context": "GitPanel && CommitEditor > Editor",
|
||||
"use_key_equivalents": true,
|
||||
"bindings": {
|
||||
"enter": "editor::Newline",
|
||||
"cmd-enter": "git::Commit",
|
||||
"tab": "git_panel::FocusChanges",
|
||||
"shift-tab": "git_panel::FocusChanges",
|
||||
"alt-up": "git_panel::FocusChanges"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "GitCommit > Editor",
|
||||
"use_key_equivalents": true,
|
||||
"bindings": {
|
||||
"enter": "editor::Newline",
|
||||
"cmd-enter": "git::Commit"
|
||||
"alt-up": "git_panel::FocusChanges",
|
||||
"escape": "git_panel::FocusChanges",
|
||||
"cmd-enter": "git::CommitChanges",
|
||||
"cmd-alt-enter": "git::CommitAllChanges"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -800,7 +777,14 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "FileFinder || (FileFinder > Picker > Editor) || (FileFinder > Picker > menu)",
|
||||
"context": "FileFinder",
|
||||
"use_key_equivalents": true,
|
||||
"bindings": {
|
||||
"cmd": "file_finder::ToggleMenu"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "FileFinder && !menu_open",
|
||||
"use_key_equivalents": true,
|
||||
"bindings": {
|
||||
"cmd-shift-p": "file_finder::SelectPrev",
|
||||
@@ -810,6 +794,16 @@
|
||||
"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",
|
||||
"use_key_equivalents": true,
|
||||
@@ -831,7 +825,6 @@
|
||||
"cmd-k": "terminal::Clear",
|
||||
"cmd-n": "workspace::NewTerminal",
|
||||
"ctrl-enter": "assistant::InlineAssist",
|
||||
"ctrl-_": null, // emacs undo
|
||||
// Some nice conveniences
|
||||
"cmd-backspace": ["terminal::SendText", "\u0015"],
|
||||
"cmd-right": ["terminal::SendText", "\u0005"],
|
||||
@@ -839,8 +832,6 @@
|
||||
// Terminal.app compatibility
|
||||
"alt-left": ["terminal::SendText", "\u001bb"],
|
||||
"alt-right": ["terminal::SendText", "\u001bf"],
|
||||
"alt-b": ["terminal::SendText", "\u001bb"],
|
||||
"alt-f": ["terminal::SendText", "\u001bf"],
|
||||
// There are conflicting bindings for these keys in the global context.
|
||||
// these bindings override them, remove at your own risk:
|
||||
"up": ["terminal::SendKeystroke", "up"],
|
||||
@@ -888,7 +879,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "ZedPredictModal",
|
||||
"context": "ZedPredictTos",
|
||||
"use_key_equivalents": true,
|
||||
"bindings": {
|
||||
"escape": "menu::Cancel"
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
"ctrl-e": ["editor::MoveToEndOfLine", { "stop_at_soft_wraps": false }], // move-end-of-line
|
||||
"shift-home": ["editor::SelectToBeginningOfLine", { "stop_at_soft_wraps": false }], // move-beginning-of-line
|
||||
"shift-end": ["editor::SelectToEndOfLine", { "stop_at_soft_wraps": false }], // move-end-of-line
|
||||
"alt-m": ["editor::MoveToBeginningOfLine", { "stop_at_soft_wraps": false, "stop_at_indent": true }], // back-to-indentation
|
||||
"alt-f": "editor::MoveToNextSubwordEnd", // forward-word
|
||||
"alt-b": "editor::MoveToPreviousSubwordStart", // backward-word
|
||||
"alt-u": "editor::ConvertToUpperCase", // upcase-word
|
||||
@@ -49,8 +48,6 @@
|
||||
"ctrl-_": "editor::Undo", // undo
|
||||
"ctrl-/": "editor::Undo", // undo
|
||||
"ctrl-x u": "editor::Undo", // undo
|
||||
"alt-{": "editor::MoveToStartOfParagraph", // backward-paragraph
|
||||
"alt-}": "editor::MoveToEndOfParagraph", // forward-paragraph
|
||||
"ctrl-v": "editor::MovePageDown", // scroll-up
|
||||
"alt-v": "editor::MovePageUp", // scroll-down
|
||||
"ctrl-x [": "editor::MoveToBeginning", // beginning-of-buffer
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
{
|
||||
"bindings": {
|
||||
"ctrl-alt-s": "zed::OpenSettings",
|
||||
"ctrl-{": "pane::ActivatePrevItem",
|
||||
"ctrl-}": "pane::ActivateNextItem"
|
||||
"ctrl-shift-[": "pane::ActivatePrevItem",
|
||||
"ctrl-shift-]": "pane::ActivateNextItem"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "Editor",
|
||||
"bindings": {
|
||||
"ctrl->": ["zed::IncreaseBufferFontSize", { "persist": true }],
|
||||
"ctrl-<": ["zed::DecreaseBufferFontSize", { "persist": true }],
|
||||
"ctrl->": "zed::IncreaseBufferFontSize",
|
||||
"ctrl-<": "zed::DecreaseBufferFontSize",
|
||||
"ctrl-shift-j": "editor::JoinLines",
|
||||
"ctrl-d": "editor::DuplicateSelection",
|
||||
"ctrl-y": "editor::DeleteLine",
|
||||
@@ -44,7 +44,7 @@
|
||||
"shift-f2": "editor::GoToPrevDiagnostic",
|
||||
"ctrl-alt-shift-down": "editor::GoToHunk",
|
||||
"ctrl-alt-shift-up": "editor::GoToPrevHunk",
|
||||
"ctrl-alt-z": "git::Restore",
|
||||
"ctrl-alt-z": "editor::RevertSelectedHunks",
|
||||
"ctrl-home": "editor::MoveToBeginning",
|
||||
"ctrl-end": "editor::MoveToEnd",
|
||||
"ctrl-shift-home": "editor::SelectToBeginning",
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
[
|
||||
{
|
||||
"bindings": {
|
||||
"ctrl-{": "pane::ActivatePrevItem",
|
||||
"ctrl-}": "pane::ActivateNextItem",
|
||||
"ctrl-shift-[": "pane::ActivatePrevItem",
|
||||
"ctrl-shift-]": "pane::ActivateNextItem",
|
||||
"ctrl-pageup": "pane::ActivatePrevItem",
|
||||
"ctrl-pagedown": "pane::ActivateNextItem",
|
||||
"ctrl-1": ["workspace::ActivatePane", 0],
|
||||
@@ -14,15 +14,15 @@
|
||||
"ctrl-7": ["workspace::ActivatePane", 6],
|
||||
"ctrl-8": ["workspace::ActivatePane", 7],
|
||||
"ctrl-9": ["workspace::ActivatePane", 8],
|
||||
"ctrl-!": ["workspace::MoveItemToPane", { "destination": 0, "focus": true }],
|
||||
"ctrl-@": ["workspace::MoveItemToPane", { "destination": 1 }],
|
||||
"ctrl-#": ["workspace::MoveItemToPane", { "destination": 2 }],
|
||||
"ctrl-$": ["workspace::MoveItemToPane", { "destination": 3 }],
|
||||
"ctrl-%": ["workspace::MoveItemToPane", { "destination": 4 }],
|
||||
"ctrl-^": ["workspace::MoveItemToPane", { "destination": 5 }],
|
||||
"ctrl-&": ["workspace::MoveItemToPane", { "destination": 6 }],
|
||||
"ctrl-*": ["workspace::MoveItemToPane", { "destination": 7 }],
|
||||
"ctrl-(": ["workspace::MoveItemToPane", { "destination": 8 }]
|
||||
"ctrl-shift-1": ["workspace::MoveItemToPane", { "destination": 0, "focus": true }],
|
||||
"ctrl-shift-2": ["workspace::MoveItemToPane", { "destination": 1 }],
|
||||
"ctrl-shift-3": ["workspace::MoveItemToPane", { "destination": 2 }],
|
||||
"ctrl-shift-4": ["workspace::MoveItemToPane", { "destination": 3 }],
|
||||
"ctrl-shift-5": ["workspace::MoveItemToPane", { "destination": 4 }],
|
||||
"ctrl-shift-6": ["workspace::MoveItemToPane", { "destination": 5 }],
|
||||
"ctrl-shift-7": ["workspace::MoveItemToPane", { "destination": 6 }],
|
||||
"ctrl-shift-8": ["workspace::MoveItemToPane", { "destination": 7 }],
|
||||
"ctrl-shift-9": ["workspace::MoveItemToPane", { "destination": 8 }]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
"ctrl-e": ["editor::MoveToEndOfLine", { "stop_at_soft_wraps": false }], // move-end-of-line
|
||||
"shift-home": ["editor::SelectToBeginningOfLine", { "stop_at_soft_wraps": false }], // move-beginning-of-line
|
||||
"shift-end": ["editor::SelectToEndOfLine", { "stop_at_soft_wraps": false }], // move-end-of-line
|
||||
"alt-m": ["editor::MoveToBeginningOfLine", { "stop_at_soft_wraps": false, "stop_at_indent": true }], // back-to-indentation
|
||||
"alt-f": "editor::MoveToNextSubwordEnd", // forward-word
|
||||
"alt-b": "editor::MoveToPreviousSubwordStart", // backward-word
|
||||
"alt-u": "editor::ConvertToUpperCase", // upcase-word
|
||||
@@ -49,8 +48,6 @@
|
||||
"ctrl-_": "editor::Undo", // undo
|
||||
"ctrl-/": "editor::Undo", // undo
|
||||
"ctrl-x u": "editor::Undo", // undo
|
||||
"alt-{": "editor::MoveToStartOfParagraph", // backward-paragraph
|
||||
"alt-}": "editor::MoveToEndOfParagraph", // forward-paragraph
|
||||
"ctrl-v": "editor::MovePageDown", // scroll-up
|
||||
"alt-v": "editor::MovePageUp", // scroll-down
|
||||
"ctrl-x [": "editor::MoveToBeginning", // beginning-of-buffer
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
[
|
||||
{
|
||||
"bindings": {
|
||||
"cmd-{": "pane::ActivatePrevItem",
|
||||
"cmd-}": "pane::ActivateNextItem"
|
||||
"cmd-shift-[": "pane::ActivatePrevItem",
|
||||
"cmd-shift-]": "pane::ActivateNextItem"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "Editor",
|
||||
"bindings": {
|
||||
"ctrl->": ["zed::IncreaseBufferFontSize", { "persist": true }],
|
||||
"ctrl-<": ["zed::DecreaseBufferFontSize", { "persist": true }],
|
||||
"ctrl->": "zed::IncreaseBufferFontSize",
|
||||
"ctrl-<": "zed::DecreaseBufferFontSize",
|
||||
"ctrl-shift-j": "editor::JoinLines",
|
||||
"cmd-d": "editor::DuplicateSelection",
|
||||
"cmd-backspace": "editor::DeleteLine",
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
[
|
||||
{
|
||||
"bindings": {
|
||||
"cmd-{": "pane::ActivatePrevItem",
|
||||
"cmd-}": "pane::ActivateNextItem",
|
||||
"cmd-shift-[": "pane::ActivatePrevItem",
|
||||
"cmd-shift-]": "pane::ActivateNextItem",
|
||||
"ctrl-pageup": "pane::ActivatePrevItem",
|
||||
"ctrl-pagedown": "pane::ActivateNextItem",
|
||||
"ctrl-1": ["workspace::ActivatePane", 0],
|
||||
@@ -14,15 +14,15 @@
|
||||
"ctrl-7": ["workspace::ActivatePane", 6],
|
||||
"ctrl-8": ["workspace::ActivatePane", 7],
|
||||
"ctrl-9": ["workspace::ActivatePane", 8],
|
||||
"ctrl-!": ["workspace::MoveItemToPane", { "destination": 0, "focus": true }],
|
||||
"ctrl-@": ["workspace::MoveItemToPane", { "destination": 1 }],
|
||||
"ctrl-#": ["workspace::MoveItemToPane", { "destination": 2 }],
|
||||
"ctrl-$": ["workspace::MoveItemToPane", { "destination": 3 }],
|
||||
"ctrl-%": ["workspace::MoveItemToPane", { "destination": 4 }],
|
||||
"ctrl-^": ["workspace::MoveItemToPane", { "destination": 5 }],
|
||||
"ctrl-&": ["workspace::MoveItemToPane", { "destination": 6 }],
|
||||
"ctrl-*": ["workspace::MoveItemToPane", { "destination": 7 }],
|
||||
"ctrl-(": ["workspace::MoveItemToPane", { "destination": 8 }]
|
||||
"ctrl-shift-1": ["workspace::MoveItemToPane", { "destination": 0, "focus": true }],
|
||||
"ctrl-shift-2": ["workspace::MoveItemToPane", { "destination": 1 }],
|
||||
"ctrl-shift-3": ["workspace::MoveItemToPane", { "destination": 2 }],
|
||||
"ctrl-shift-4": ["workspace::MoveItemToPane", { "destination": 3 }],
|
||||
"ctrl-shift-5": ["workspace::MoveItemToPane", { "destination": 4 }],
|
||||
"ctrl-shift-6": ["workspace::MoveItemToPane", { "destination": 5 }],
|
||||
"ctrl-shift-7": ["workspace::MoveItemToPane", { "destination": 6 }],
|
||||
"ctrl-shift-8": ["workspace::MoveItemToPane", { "destination": 7 }],
|
||||
"ctrl-shift-9": ["workspace::MoveItemToPane", { "destination": 8 }]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"cmd-b": "editor::GoToDefinition",
|
||||
"cmd-j": "editor::ScrollCursorCenter",
|
||||
"cmd-enter": "editor::NewlineBelow",
|
||||
"cmd-alt-enter": "editor::NewlineAbove",
|
||||
"cmd-alt-enter": "editor::NewLineAbove",
|
||||
"cmd-shift-l": "editor::SelectLine",
|
||||
"cmd-shift-t": "outline::Toggle",
|
||||
"alt-backspace": "editor::DeleteToPreviousWordStart",
|
||||
@@ -70,7 +70,7 @@
|
||||
"bindings": {
|
||||
"cmd-backspace": ["project_panel::Trash", { "skip_prompt": true }],
|
||||
"cmd-d": "project_panel::Duplicate",
|
||||
"cmd-n": "project_panel::NewDirectory",
|
||||
"cmd-n": "project_panel::NewFolder",
|
||||
"return": "project_panel::Rename",
|
||||
"cmd-c": "project_panel::Copy",
|
||||
"cmd-v": "project_panel::Paste",
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
{
|
||||
"context": "VimControl && !menu",
|
||||
"bindings": {
|
||||
"i": ["vim::PushObject", { "around": false }],
|
||||
"a": ["vim::PushObject", { "around": true }],
|
||||
"i": ["vim::PushOperator", { "Object": { "around": false } }],
|
||||
"a": ["vim::PushOperator", { "Object": { "around": true } }],
|
||||
"left": "vim::Left",
|
||||
"h": "vim::Left",
|
||||
"backspace": "vim::Backspace",
|
||||
@@ -37,9 +37,9 @@
|
||||
"[ [": "vim::PreviousSectionStart",
|
||||
"[ ]": "vim::PreviousSectionEnd",
|
||||
"] m": "vim::NextMethodStart",
|
||||
"] shift-m": "vim::NextMethodEnd",
|
||||
"] M": "vim::NextMethodEnd",
|
||||
"[ m": "vim::PreviousMethodStart",
|
||||
"[ shift-m": "vim::PreviousMethodEnd",
|
||||
"[ M": "vim::PreviousMethodEnd",
|
||||
"[ *": "vim::PreviousComment",
|
||||
"[ /": "vim::PreviousComment",
|
||||
"] *": "vim::NextComment",
|
||||
@@ -54,10 +54,10 @@
|
||||
// "b": "vim::PreviousSubwordStart",
|
||||
// "e": "vim::NextSubwordEnd",
|
||||
// "g e": "vim::PreviousSubwordEnd",
|
||||
"shift-w": ["vim::NextWordStart", { "ignore_punctuation": true }],
|
||||
"shift-e": ["vim::NextWordEnd", { "ignore_punctuation": true }],
|
||||
"shift-b": ["vim::PreviousWordStart", { "ignore_punctuation": true }],
|
||||
"g shift-e": ["vim::PreviousWordEnd", { "ignore_punctuation": true }],
|
||||
"shift-w": ["vim::NextWordStart", { "ignorePunctuation": true }],
|
||||
"shift-e": ["vim::NextWordEnd", { "ignorePunctuation": true }],
|
||||
"shift-b": ["vim::PreviousWordStart", { "ignorePunctuation": true }],
|
||||
"g shift-e": ["vim::PreviousWordEnd", { "ignorePunctuation": true }],
|
||||
"/": "vim::Search",
|
||||
"g /": "pane::DeploySearch",
|
||||
"?": ["vim::Search", { "backwards": true }],
|
||||
@@ -70,23 +70,22 @@
|
||||
"[ {": ["vim::UnmatchedBackward", { "char": "{" }],
|
||||
"] )": ["vim::UnmatchedForward", { "char": ")" }],
|
||||
"[ (": ["vim::UnmatchedBackward", { "char": "(" }],
|
||||
"f": ["vim::PushFindForward", { "before": false }],
|
||||
"t": ["vim::PushFindForward", { "before": true }],
|
||||
"shift-f": ["vim::PushFindBackward", { "after": false }],
|
||||
"shift-t": ["vim::PushFindBackward", { "after": true }],
|
||||
"m": "vim::PushMark",
|
||||
"'": ["vim::PushJump", { "line": true }],
|
||||
"`": ["vim::PushJump", { "line": false }],
|
||||
"f": ["vim::PushOperator", { "FindForward": { "before": false } }],
|
||||
"t": ["vim::PushOperator", { "FindForward": { "before": true } }],
|
||||
"shift-f": ["vim::PushOperator", { "FindBackward": { "after": false } }],
|
||||
"shift-t": ["vim::PushOperator", { "FindBackward": { "after": true } }],
|
||||
"m": ["vim::PushOperator", "Mark"],
|
||||
"'": ["vim::PushOperator", { "Jump": { "line": true } }],
|
||||
"`": ["vim::PushOperator", { "Jump": { "line": false } }],
|
||||
";": "vim::RepeatFind",
|
||||
",": "vim::RepeatFindReversed",
|
||||
"ctrl-o": "pane::GoBack",
|
||||
"ctrl-i": "pane::GoForward",
|
||||
"ctrl-]": "editor::GoToDefinition",
|
||||
"escape": "vim::SwitchToNormalMode",
|
||||
"ctrl-[": "vim::SwitchToNormalMode",
|
||||
"escape": ["vim::SwitchMode", "Normal"],
|
||||
"ctrl-[": ["vim::SwitchMode", "Normal"],
|
||||
"v": "vim::ToggleVisual",
|
||||
"shift-v": "vim::ToggleVisualLine",
|
||||
"ctrl-g": "vim::ShowLocation",
|
||||
"ctrl-v": "vim::ToggleVisualBlock",
|
||||
"ctrl-q": "vim::ToggleVisualBlock",
|
||||
"shift-k": "editor::Hover",
|
||||
@@ -102,7 +101,6 @@
|
||||
"ctrl-e": "vim::LineDown",
|
||||
"ctrl-y": "vim::LineUp",
|
||||
// "g" commands
|
||||
"g r": "vim::PushReplaceWithRegister",
|
||||
"g g": "vim::StartOfDocument",
|
||||
"g h": "editor::Hover",
|
||||
"g t": "pane::ActivateNextItem",
|
||||
@@ -125,17 +123,17 @@
|
||||
"g .": "editor::ToggleCodeActions", // zed specific
|
||||
"g shift-a": "editor::FindAllReferences", // zed specific
|
||||
"g space": "editor::OpenExcerpts", // zed specific
|
||||
"g *": ["vim::MoveToNext", { "partial_word": true }],
|
||||
"g #": ["vim::MoveToPrev", { "partial_word": true }],
|
||||
"g j": ["vim::Down", { "display_lines": true }],
|
||||
"g down": ["vim::Down", { "display_lines": true }],
|
||||
"g k": ["vim::Up", { "display_lines": true }],
|
||||
"g up": ["vim::Up", { "display_lines": true }],
|
||||
"g $": ["vim::EndOfLine", { "display_lines": true }],
|
||||
"g end": ["vim::EndOfLine", { "display_lines": true }],
|
||||
"g 0": ["vim::StartOfLine", { "display_lines": true }],
|
||||
"g home": ["vim::StartOfLine", { "display_lines": true }],
|
||||
"g ^": ["vim::FirstNonWhitespace", { "display_lines": true }],
|
||||
"g *": ["vim::MoveToNext", { "partialWord": true }],
|
||||
"g #": ["vim::MoveToPrev", { "partialWord": true }],
|
||||
"g j": ["vim::Down", { "displayLines": true }],
|
||||
"g down": ["vim::Down", { "displayLines": true }],
|
||||
"g k": ["vim::Up", { "displayLines": true }],
|
||||
"g up": ["vim::Up", { "displayLines": true }],
|
||||
"g $": ["vim::EndOfLine", { "displayLines": true }],
|
||||
"g end": ["vim::EndOfLine", { "displayLines": true }],
|
||||
"g 0": ["vim::StartOfLine", { "displayLines": true }],
|
||||
"g home": ["vim::StartOfLine", { "displayLines": true }],
|
||||
"g ^": ["vim::FirstNonWhitespace", { "displayLines": true }],
|
||||
"g v": "vim::RestoreVisualSelection",
|
||||
"g ]": "editor::GoToDiagnostic",
|
||||
"g [": "editor::GoToPrevDiagnostic",
|
||||
@@ -147,7 +145,7 @@
|
||||
"shift-l": "vim::WindowBottom",
|
||||
"q": "vim::ToggleRecord",
|
||||
"shift-q": "vim::ReplayLastRecording",
|
||||
"@": "vim::PushReplayRegister",
|
||||
"@": ["vim::PushOperator", "ReplayRegister"],
|
||||
// z commands
|
||||
"z enter": ["workspace::SendKeystrokes", "z t ^"],
|
||||
"z -": ["workspace::SendKeystrokes", "z b ^"],
|
||||
@@ -166,8 +164,8 @@
|
||||
"z f": "editor::FoldSelectedRanges",
|
||||
"z shift-m": "editor::FoldAll",
|
||||
"z shift-r": "editor::UnfoldAll",
|
||||
"shift-z shift-q": ["pane::CloseActiveItem", { "save_intent": "skip" }],
|
||||
"shift-z shift-z": ["pane::CloseActiveItem", { "save_intent": "save_all" }],
|
||||
"shift-z shift-q": ["pane::CloseActiveItem", { "saveIntent": "skip" }],
|
||||
"shift-z shift-z": ["pane::CloseActiveItem", { "saveIntent": "saveAll" }],
|
||||
// Count support
|
||||
"1": ["vim::Number", 1],
|
||||
"2": ["vim::Number", 2],
|
||||
@@ -194,13 +192,13 @@
|
||||
"escape": "editor::Cancel",
|
||||
":": "command_palette::Toggle",
|
||||
".": "vim::Repeat",
|
||||
"c": "vim::PushChange",
|
||||
"c": ["vim::PushOperator", "Change"],
|
||||
"shift-c": "vim::ChangeToEndOfLine",
|
||||
"d": "vim::PushDelete",
|
||||
"d": ["vim::PushOperator", "Delete"],
|
||||
"shift-d": "vim::DeleteToEndOfLine",
|
||||
"shift-j": "vim::JoinLines",
|
||||
"g shift-j": "vim::JoinLinesNoWhitespace",
|
||||
"y": "vim::PushYank",
|
||||
"y": ["vim::PushOperator", "Yank"],
|
||||
"shift-y": "vim::YankLine",
|
||||
"i": "vim::InsertBefore",
|
||||
"shift-i": "vim::InsertFirstNonWhitespace",
|
||||
@@ -217,19 +215,19 @@
|
||||
"shift-p": ["vim::Paste", { "before": true }],
|
||||
"u": "vim::Undo",
|
||||
"ctrl-r": "vim::Redo",
|
||||
"r": "vim::PushReplace",
|
||||
"r": ["vim::PushOperator", "Replace"],
|
||||
"s": "vim::Substitute",
|
||||
"shift-s": "vim::SubstituteLine",
|
||||
">": "vim::PushIndent",
|
||||
"<": "vim::PushOutdent",
|
||||
"=": "vim::PushAutoIndent",
|
||||
"!": "vim::PushShellCommand",
|
||||
"g u": "vim::PushLowercase",
|
||||
"g shift-u": "vim::PushUppercase",
|
||||
"g ~": "vim::PushOppositeCase",
|
||||
"\"": "vim::PushRegister",
|
||||
"g w": "vim::PushRewrap",
|
||||
"g q": "vim::PushRewrap",
|
||||
">": ["vim::PushOperator", "Indent"],
|
||||
"<": ["vim::PushOperator", "Outdent"],
|
||||
"=": ["vim::PushOperator", "AutoIndent"],
|
||||
"!": ["vim::PushOperator", "ShellCommand"],
|
||||
"g u": ["vim::PushOperator", "Lowercase"],
|
||||
"g shift-u": ["vim::PushOperator", "Uppercase"],
|
||||
"g ~": ["vim::PushOperator", "OppositeCase"],
|
||||
"\"": ["vim::PushOperator", "Register"],
|
||||
"g w": ["vim::PushOperator", "Rewrap"],
|
||||
"g q": ["vim::PushOperator", "Rewrap"],
|
||||
"ctrl-pagedown": "pane::ActivateNextItem",
|
||||
"ctrl-pageup": "pane::ActivatePrevItem",
|
||||
"insert": "vim::InsertBefore",
|
||||
@@ -240,7 +238,7 @@
|
||||
"[ d": "editor::GoToPrevDiagnostic",
|
||||
"] c": "editor::GoToHunk",
|
||||
"[ c": "editor::GoToPrevHunk",
|
||||
"g c": "vim::PushToggleComments"
|
||||
"g c": ["vim::PushOperator", "ToggleComments"]
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -265,14 +263,14 @@
|
||||
"y": "vim::VisualYank",
|
||||
"shift-y": "vim::VisualYankLine",
|
||||
"p": "vim::Paste",
|
||||
"shift-p": ["vim::Paste", { "preserve_clipboard": true }],
|
||||
"shift-p": ["vim::Paste", { "preserveClipboard": true }],
|
||||
"c": "vim::Substitute",
|
||||
"s": "vim::Substitute",
|
||||
"shift-r": "vim::SubstituteLine",
|
||||
"shift-s": "vim::SubstituteLine",
|
||||
"~": "vim::ChangeCase",
|
||||
"*": ["vim::MoveToNext", { "partial_word": true }],
|
||||
"#": ["vim::MoveToPrev", { "partial_word": true }],
|
||||
"*": ["vim::MoveToNext", { "partialWord": true }],
|
||||
"#": ["vim::MoveToPrev", { "partialWord": true }],
|
||||
"ctrl-a": "vim::Increment",
|
||||
"ctrl-x": "vim::Decrement",
|
||||
"g ctrl-a": ["vim::Increment", { "step": true }],
|
||||
@@ -283,20 +281,19 @@
|
||||
"g shift-a": "vim::VisualInsertEndOfLine",
|
||||
"shift-j": "vim::JoinLines",
|
||||
"g shift-j": "vim::JoinLinesNoWhitespace",
|
||||
"r": "vim::PushReplace",
|
||||
"ctrl-c": "vim::SwitchToNormalMode",
|
||||
"ctrl-[": "vim::SwitchToNormalMode",
|
||||
"escape": "vim::SwitchToNormalMode",
|
||||
"r": ["vim::PushOperator", "Replace"],
|
||||
"ctrl-c": ["vim::SwitchMode", "Normal"],
|
||||
"ctrl-[": ["vim::SwitchMode", "Normal"],
|
||||
"escape": ["vim::SwitchMode", "Normal"],
|
||||
">": "vim::Indent",
|
||||
"<": "vim::Outdent",
|
||||
"=": "vim::AutoIndent",
|
||||
"!": "vim::ShellCommand",
|
||||
"i": ["vim::PushObject", { "around": false }],
|
||||
"a": ["vim::PushObject", { "around": true }],
|
||||
"g r": ["vim::Paste", { "preserve_clipboard": true }],
|
||||
"i": ["vim::PushOperator", { "Object": { "around": false } }],
|
||||
"a": ["vim::PushOperator", { "Object": { "around": true } }],
|
||||
"g c": "vim::ToggleComments",
|
||||
"g q": "vim::Rewrap",
|
||||
"\"": "vim::PushRegister",
|
||||
"\"": ["vim::PushOperator", "Register"],
|
||||
// tree-sitter related commands
|
||||
"[ x": "editor::SelectLargerSyntaxNode",
|
||||
"] x": "editor::SelectSmallerSyntaxNode"
|
||||
@@ -311,19 +308,19 @@
|
||||
"ctrl-x": null,
|
||||
"ctrl-x ctrl-o": "editor::ShowCompletions",
|
||||
"ctrl-x ctrl-a": "assistant::InlineAssist", // zed specific
|
||||
"ctrl-x ctrl-c": "editor::ShowEditPrediction", // zed specific
|
||||
"ctrl-x ctrl-c": "editor::ShowInlineCompletion", // zed specific
|
||||
"ctrl-x ctrl-l": "editor::ToggleCodeActions", // zed specific
|
||||
"ctrl-x ctrl-z": "editor::Cancel",
|
||||
"ctrl-w": "editor::DeleteToPreviousWordStart",
|
||||
"ctrl-u": "editor::DeleteToBeginningOfLine",
|
||||
"ctrl-t": "vim::Indent",
|
||||
"ctrl-d": "vim::Outdent",
|
||||
"ctrl-k": ["vim::PushDigraph", {}],
|
||||
"ctrl-v": ["vim::PushLiteral", {}],
|
||||
"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::PushLiteral", {}],
|
||||
"ctrl-shift-q": ["vim::PushLiteral", {}],
|
||||
"ctrl-r": "vim::PushRegister",
|
||||
"ctrl-q": ["vim::PushOperator", { "Literal": {} }],
|
||||
"ctrl-shift-q": ["vim::PushOperator", { "Literal": {} }],
|
||||
"ctrl-r": ["vim::PushOperator", "Register"],
|
||||
"insert": "vim::ToggleReplace",
|
||||
"ctrl-o": "vim::TemporaryNormal"
|
||||
}
|
||||
@@ -358,11 +355,11 @@
|
||||
"ctrl-c": "vim::NormalBefore",
|
||||
"ctrl-[": "vim::NormalBefore",
|
||||
"escape": "vim::NormalBefore",
|
||||
"ctrl-k": ["vim::PushDigraph", {}],
|
||||
"ctrl-v": ["vim::PushLiteral", {}],
|
||||
"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::PushLiteral", {}],
|
||||
"ctrl-shift-q": ["vim::PushLiteral", {}],
|
||||
"ctrl-q": ["vim::PushOperator", { "Literal": {} }],
|
||||
"ctrl-shift-q": ["vim::PushOperator", { "Literal": {} }],
|
||||
"backspace": "vim::UndoReplace",
|
||||
"tab": "vim::Tab",
|
||||
"enter": "vim::Enter",
|
||||
@@ -377,15 +374,9 @@
|
||||
"ctrl-c": "vim::ClearOperators",
|
||||
"ctrl-[": "vim::ClearOperators",
|
||||
"escape": "vim::ClearOperators",
|
||||
"ctrl-k": ["vim::PushDigraph", {}],
|
||||
"ctrl-v": ["vim::PushLiteral", {}],
|
||||
"ctrl-q": ["vim::PushLiteral", {}]
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "Editor && vim_mode == waiting && (vim_operator == ys || vim_operator == cs)",
|
||||
"bindings": {
|
||||
"escape": "vim::SwitchToNormalMode"
|
||||
"ctrl-k": ["vim::PushOperator", { "Digraph": {} }],
|
||||
"ctrl-v": ["vim::PushOperator", { "Literal": {} }],
|
||||
"ctrl-q": ["vim::PushOperator", { "Literal": {} }]
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -401,10 +392,10 @@
|
||||
"context": "vim_operator == a || vim_operator == i || vim_operator == cs",
|
||||
"bindings": {
|
||||
"w": "vim::Word",
|
||||
"shift-w": ["vim::Word", { "ignore_punctuation": true }],
|
||||
"shift-w": ["vim::Word", { "ignorePunctuation": true }],
|
||||
// Subword TextObject
|
||||
// "w": "vim::Subword",
|
||||
// "shift-w": ["vim::Subword", { "ignore_punctuation": true }],
|
||||
// "shift-w": ["vim::Subword", { "ignorePunctuation": true }],
|
||||
"t": "vim::Tag",
|
||||
"s": "vim::Sentence",
|
||||
"p": "vim::Paragraph",
|
||||
@@ -416,7 +407,6 @@
|
||||
"(": "vim::Parentheses",
|
||||
")": "vim::Parentheses",
|
||||
"b": "vim::Parentheses",
|
||||
// "b": "vim::AnyBrackets",
|
||||
"[": "vim::SquareBrackets",
|
||||
"]": "vim::SquareBrackets",
|
||||
"r": "vim::SquareBrackets",
|
||||
@@ -427,28 +417,26 @@
|
||||
">": "vim::AngleBrackets",
|
||||
"a": "vim::Argument",
|
||||
"i": "vim::IndentObj",
|
||||
"shift-i": ["vim::IndentObj", { "include_below": true }],
|
||||
"shift-i": ["vim::IndentObj", { "includeBelow": true }],
|
||||
"f": "vim::Method",
|
||||
"c": "vim::Class",
|
||||
"e": "vim::EntireFile"
|
||||
"c": "vim::Class"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "vim_operator == c",
|
||||
"bindings": {
|
||||
"c": "vim::CurrentLine",
|
||||
"x": "vim::Exchange",
|
||||
"d": "editor::Rename", // zed specific
|
||||
"s": ["vim::PushChangeSurrounds", {}]
|
||||
"s": ["vim::PushOperator", { "ChangeSurrounds": {} }]
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "vim_operator == d",
|
||||
"bindings": {
|
||||
"d": "vim::CurrentLine",
|
||||
"s": "vim::PushDeleteSurrounds",
|
||||
"o": "editor::ToggleSelectedDiffHunks", // "d o"
|
||||
"p": "git::Restore" // "d p"
|
||||
"s": ["vim::PushOperator", "DeleteSurrounds"],
|
||||
"o": "editor::ToggleHunkDiff", // "d o"
|
||||
"p": "editor::RevertSelectedHunks" // "d p"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -485,7 +473,7 @@
|
||||
"context": "vim_operator == y",
|
||||
"bindings": {
|
||||
"y": "vim::CurrentLine",
|
||||
"s": ["vim::PushAddSurrounds", {}]
|
||||
"s": ["vim::PushOperator", { "AddSurrounds": {} }]
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -524,19 +512,6 @@
|
||||
"c": "vim::CurrentLine"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "vim_operator == gr",
|
||||
"bindings": {
|
||||
"r": "vim::CurrentLine"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "vim_operator == cx",
|
||||
"bindings": {
|
||||
"x": "vim::CurrentLine",
|
||||
"c": "vim::ClearExchange"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "vim_mode == literal",
|
||||
"bindings": {
|
||||
@@ -588,34 +563,34 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "GitPanel || ProjectPanel || CollabPanel || OutlinePanel || ChatPanel || VimControl || EmptyPane || SharedScreen || MarkdownPreview || KeyContextView",
|
||||
"context": "ProjectPanel || CollabPanel || OutlinePanel || ChatPanel || VimControl || EmptyPane || SharedScreen || MarkdownPreview || KeyContextView",
|
||||
"bindings": {
|
||||
// window related commands (ctrl-w X)
|
||||
"ctrl-w": null,
|
||||
"ctrl-w left": "workspace::ActivatePaneLeft",
|
||||
"ctrl-w right": "workspace::ActivatePaneRight",
|
||||
"ctrl-w up": "workspace::ActivatePaneUp",
|
||||
"ctrl-w down": "workspace::ActivatePaneDown",
|
||||
"ctrl-w ctrl-h": "workspace::ActivatePaneLeft",
|
||||
"ctrl-w ctrl-l": "workspace::ActivatePaneRight",
|
||||
"ctrl-w ctrl-k": "workspace::ActivatePaneUp",
|
||||
"ctrl-w ctrl-j": "workspace::ActivatePaneDown",
|
||||
"ctrl-w h": "workspace::ActivatePaneLeft",
|
||||
"ctrl-w l": "workspace::ActivatePaneRight",
|
||||
"ctrl-w k": "workspace::ActivatePaneUp",
|
||||
"ctrl-w j": "workspace::ActivatePaneDown",
|
||||
"ctrl-w shift-left": "workspace::SwapPaneLeft",
|
||||
"ctrl-w shift-right": "workspace::SwapPaneRight",
|
||||
"ctrl-w shift-up": "workspace::SwapPaneUp",
|
||||
"ctrl-w shift-down": "workspace::SwapPaneDown",
|
||||
"ctrl-w shift-h": "workspace::SwapPaneLeft",
|
||||
"ctrl-w shift-l": "workspace::SwapPaneRight",
|
||||
"ctrl-w shift-k": "workspace::SwapPaneUp",
|
||||
"ctrl-w shift-j": "workspace::SwapPaneDown",
|
||||
"ctrl-w >": "vim::ResizePaneRight",
|
||||
"ctrl-w <": "vim::ResizePaneLeft",
|
||||
"ctrl-w -": "vim::ResizePaneDown",
|
||||
"ctrl-w +": "vim::ResizePaneUp",
|
||||
"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 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 h": ["workspace::ActivatePaneInDirection", "Left"],
|
||||
"ctrl-w l": ["workspace::ActivatePaneInDirection", "Right"],
|
||||
"ctrl-w k": ["workspace::ActivatePaneInDirection", "Up"],
|
||||
"ctrl-w 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",
|
||||
@@ -633,12 +608,10 @@
|
||||
"ctrl-w shift-s": "pane::SplitHorizontal",
|
||||
"ctrl-w ctrl-s": "pane::SplitHorizontal",
|
||||
"ctrl-w s": "pane::SplitHorizontal",
|
||||
"ctrl-w ctrl-c": "pane::CloseActiveItem",
|
||||
"ctrl-w c": "pane::CloseActiveItem",
|
||||
"ctrl-w ctrl-q": "pane::CloseActiveItem",
|
||||
"ctrl-w q": "pane::CloseActiveItem",
|
||||
"ctrl-w ctrl-a": "pane::CloseAllItems",
|
||||
"ctrl-w a": "pane::CloseAllItems",
|
||||
"ctrl-w ctrl-c": "pane::CloseAllItems",
|
||||
"ctrl-w c": "pane::CloseAllItems",
|
||||
"ctrl-w ctrl-q": "pane::CloseAllItems",
|
||||
"ctrl-w q": "pane::CloseAllItems",
|
||||
"ctrl-w ctrl-o": "workspace::CloseInactiveTabsAndPanes",
|
||||
"ctrl-w o": "workspace::CloseInactiveTabsAndPanes",
|
||||
"ctrl-w ctrl-n": "workspace::NewFileSplitHorizontal",
|
||||
@@ -646,7 +619,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "ChangesList || EmptyPane || SharedScreen || MarkdownPreview || KeyContextView || Welcome",
|
||||
"context": "EmptyPane || SharedScreen || MarkdownPreview || KeyContextView || Welcome",
|
||||
"bindings": {
|
||||
":": "command_palette::Toggle",
|
||||
"g /": "pane::DeploySearch"
|
||||
@@ -694,37 +667,5 @@
|
||||
"shift-g": "menu::SelectLast",
|
||||
"g g": "menu::SelectFirst"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "GitPanel && ChangesList",
|
||||
"use_key_equivalents": true,
|
||||
"bindings": {
|
||||
"k": "menu::SelectPrev",
|
||||
"j": "menu::SelectNext",
|
||||
"g g": "menu::SelectFirst",
|
||||
"shift-g": "menu::SelectLast",
|
||||
"g f": "menu::Confirm",
|
||||
"i": "git_panel::FocusEditor",
|
||||
"x": "git::ToggleStaged",
|
||||
"shift-x": "git::StageAll",
|
||||
"shift-u": "git::UnstageAll"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "Editor && edit_prediction",
|
||||
"bindings": {
|
||||
// This is identical to the binding in the base keymap, but the vim bindings above to
|
||||
// "vim::Tab" shadow it, so it needs to be bound again.
|
||||
"tab": "editor::AcceptEditPrediction"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "os != macos && Editor && edit_prediction_conflict",
|
||||
"bindings": {
|
||||
// alt-l is provided as an alternative to tab/alt-tab. and will be displayed in the UI. This
|
||||
// is because alt-tab may not be available, as it is often used for window switching on Linux
|
||||
// and Windows.
|
||||
"alt-l": "editor::AcceptEditPrediction"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -10,9 +10,8 @@
|
||||
"light": "One Light",
|
||||
"dark": "One Dark"
|
||||
},
|
||||
"icon_theme": "Zed (Default)",
|
||||
// The name of a base set of key bindings to use.
|
||||
// This setting can take six values, each named after another
|
||||
// This setting can take four values, each named after another
|
||||
// text editor:
|
||||
//
|
||||
// 1. "VSCode"
|
||||
@@ -24,8 +23,8 @@
|
||||
"base_keymap": "VSCode",
|
||||
// Features that can be globally enabled or disabled
|
||||
"features": {
|
||||
// Which edit prediction provider to use.
|
||||
"edit_prediction_provider": "copilot"
|
||||
// Which inline completion provider to use.
|
||||
"inline_completion_provider": "copilot"
|
||||
},
|
||||
// The name of a font to use for rendering text in the editor
|
||||
"buffer_font_family": "Zed Plex Mono",
|
||||
@@ -93,13 +92,6 @@
|
||||
// workspace when the centered layout is used.
|
||||
"right_padding": 0.2
|
||||
},
|
||||
// All settings related to the image viewer.
|
||||
"image_viewer": {
|
||||
// The unit for image file sizes.
|
||||
// By default we're setting it to binary.
|
||||
// The second option is decimal.
|
||||
"unit": "binary"
|
||||
},
|
||||
// The key to use for adding multiple cursors
|
||||
// Currently "alt" or "cmd_or_ctrl" (also aliased as
|
||||
// "cmd" and "ctrl") are supported.
|
||||
@@ -126,13 +118,6 @@
|
||||
// 3. Never close the window
|
||||
// "when_closing_with_no_tabs": "keep_window_open",
|
||||
"when_closing_with_no_tabs": "platform_default",
|
||||
// What to do when the last window is closed.
|
||||
// May take 2 values:
|
||||
// 1. Use the current platform's convention
|
||||
// "on_last_window_closed": "platform_default"
|
||||
// 2. Always quit the application
|
||||
// "on_last_window_closed": "quit_app",
|
||||
"on_last_window_closed": "platform_default",
|
||||
// Whether to use the system provided dialogs for Open and Save As.
|
||||
// When set to false, Zed will use the built-in keyboard-first pickers.
|
||||
"use_system_path_prompts": true,
|
||||
@@ -161,10 +146,6 @@
|
||||
// 4. Highlight the full line (default):
|
||||
// "all"
|
||||
"current_line_highlight": "all",
|
||||
// Whether to highlight all occurrences of the selected text in an editor.
|
||||
"selection_highlight": true,
|
||||
// The debounce delay before querying highlights based on the selected text.
|
||||
"selection_highlight_debounce": 50,
|
||||
// The debounce delay before querying highlights from the language
|
||||
// server based on the current cursor location.
|
||||
"lsp_highlight_debounce": 75,
|
||||
@@ -179,6 +160,9 @@
|
||||
/// 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.
|
||||
"show_signature_help_after_edits": false,
|
||||
/// Whether to show the inline completions next to the completions provided by a language server.
|
||||
/// Only has an effect if inline completion provider supports it.
|
||||
"show_inline_completions_in_menu": true,
|
||||
// Whether to show wrap guides (vertical rulers) in the editor.
|
||||
// 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
|
||||
@@ -211,31 +195,14 @@
|
||||
// Otherwise(when `true`), the closing characters are always skipped over and auto-removed
|
||||
// no matter how they were inserted.
|
||||
"always_treat_brackets_as_autoclosed": false,
|
||||
// Controls where the `editor::Rewrap` action is allowed in the current language scope.
|
||||
//
|
||||
// This setting can take three values:
|
||||
//
|
||||
// 1. Only allow rewrapping in comments:
|
||||
// "in_comments"
|
||||
// 2. Only allow rewrapping in the current selection(s):
|
||||
// "in_selections"
|
||||
// 3. Allow rewrapping anywhere:
|
||||
// "anywhere"
|
||||
//
|
||||
// When using values other than `in_comments`, it is possible for the rewrapping to produce code
|
||||
// that is syntactically invalid. Keep this in mind when selecting which behavior you would like
|
||||
// to use.
|
||||
//
|
||||
// Note: This setting has no effect in Vim mode, as rewrap is already allowed everywhere.
|
||||
"allow_rewrap": "in_comments",
|
||||
// Controls whether edit predictions are shown immediately (true)
|
||||
// or manually by triggering `editor::ShowEditPrediction` (false).
|
||||
"show_edit_predictions": true,
|
||||
// Controls whether edit predictions are shown in a given language scope.
|
||||
// Controls whether inline completions are shown immediately (true)
|
||||
// or manually by triggering `editor::ShowInlineCompletion` (false).
|
||||
"show_inline_completions": true,
|
||||
// Controls whether inline completions are shown in a given language scope.
|
||||
// Example: ["string", "comment"]
|
||||
"edit_predictions_disabled_in": [],
|
||||
"inline_completions_disabled_in": [],
|
||||
// Whether to show tabs and spaces in the editor.
|
||||
// This setting can take four values:
|
||||
// This setting can take three values:
|
||||
//
|
||||
// 1. Draw tabs and spaces only for the selected text (default):
|
||||
// "selection"
|
||||
@@ -287,8 +254,6 @@
|
||||
"git_diff": true,
|
||||
// Whether to show buffer search results in the scrollbar.
|
||||
"search_results": true,
|
||||
// Whether to show selected text occurrences in the scrollbar.
|
||||
"selected_text": true,
|
||||
// Whether to show selected symbol occurrences in the scrollbar.
|
||||
"selected_symbol": true,
|
||||
// Which diagnostic indicators to show in the scrollbar:
|
||||
@@ -427,7 +392,7 @@
|
||||
/// Scrollbar-related settings
|
||||
"scrollbar": {
|
||||
/// When to show the scrollbar in the project panel.
|
||||
/// This setting can take five values:
|
||||
/// This setting can take four values:
|
||||
///
|
||||
/// 1. null (default): Inherit editor settings
|
||||
/// 2. Show the scrollbar if there's important information or
|
||||
@@ -499,7 +464,7 @@
|
||||
/// Scrollbar-related settings
|
||||
"scrollbar": {
|
||||
/// When to show the scrollbar in the project panel.
|
||||
/// This setting can take five values:
|
||||
/// This setting can take four values:
|
||||
///
|
||||
/// 1. null (default): Inherit editor settings
|
||||
/// 2. Show the scrollbar if there's important information or
|
||||
@@ -581,7 +546,7 @@
|
||||
// The provider to use.
|
||||
"provider": "zed.dev",
|
||||
// The model to use.
|
||||
"model": "claude-3-5-sonnet-latest"
|
||||
"model": "claude-3-5-sonnet"
|
||||
}
|
||||
},
|
||||
// The settings for slash commands.
|
||||
@@ -627,9 +592,7 @@
|
||||
// Whether or not to show the tab bar in the editor
|
||||
"show": true,
|
||||
// Whether or not to show the navigation history buttons.
|
||||
"show_nav_history_buttons": true,
|
||||
/// Whether or not to show the tab bar buttons.
|
||||
"show_tab_bar_buttons": true
|
||||
"show_nav_history_buttons": true
|
||||
},
|
||||
// Settings related to the editor's tabs
|
||||
"tabs": {
|
||||
@@ -682,15 +645,15 @@
|
||||
// There are 5 possible width values:
|
||||
//
|
||||
// 1. Small: This value is essentially a fixed width.
|
||||
// "modal_max_width": "small"
|
||||
// "modal_width": "small"
|
||||
// 2. Medium:
|
||||
// "modal_max_width": "medium"
|
||||
// "modal_width": "medium"
|
||||
// 3. Large:
|
||||
// "modal_max_width": "large"
|
||||
// "modal_width": "large"
|
||||
// 4. Extra Large:
|
||||
// "modal_max_width": "xlarge"
|
||||
// "modal_width": "xlarge"
|
||||
// 5. Fullscreen: This value removes any horizontal padding, as it consumes the whole viewport width.
|
||||
// "modal_max_width": "full"
|
||||
// "modal_width": "full"
|
||||
//
|
||||
// Default: small
|
||||
"modal_max_width": "small"
|
||||
@@ -758,28 +721,11 @@
|
||||
// Diagnostics configuration.
|
||||
"diagnostics": {
|
||||
// Whether to show warnings or not by default.
|
||||
"include_warnings": true,
|
||||
// Settings for inline diagnostics
|
||||
"inline": {
|
||||
// Whether to show diagnostics inline or not
|
||||
"enabled": false,
|
||||
// The delay in milliseconds to show inline diagnostics after the
|
||||
// last diagnostic update.
|
||||
"update_debounce_ms": 150,
|
||||
// The amount of padding between the end of the source line and the start
|
||||
// of the inline diagnostic in units of em widths.
|
||||
"padding": 4,
|
||||
// The minimum column to display inline diagnostics. This setting can be
|
||||
// used to horizontally align inline diagnostics at some column. Lines
|
||||
// longer than this value will still push diagnostics further to the right.
|
||||
"min_column": 0,
|
||||
// The minimum severity of the diagnostics to show inline.
|
||||
// Shows all diagnostics when not specified.
|
||||
"max_severity": null
|
||||
}
|
||||
"include_warnings": true
|
||||
},
|
||||
// Files or globs of files that will be excluded by Zed entirely. They will be skipped during file
|
||||
// scans, file searches, and not be displayed in the project file tree. Takes precedence over `file_scan_inclusions`.
|
||||
// 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
|
||||
// will lack the corresponding file entries. Overrides `file_scan_inclusions`.
|
||||
"file_scan_exclusions": [
|
||||
"**/.git",
|
||||
"**/.svn",
|
||||
@@ -791,10 +737,10 @@
|
||||
"**/.classpath",
|
||||
"**/.settings"
|
||||
],
|
||||
// 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. `file_scan_exclusions` takes
|
||||
// precedence over these inclusions.
|
||||
// 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": {
|
||||
@@ -825,26 +771,9 @@
|
||||
// 2. Load direnv configuration through the shell hook, works for POSIX shells and fish.
|
||||
// "load_direnv": "shell_hook"
|
||||
"load_direnv": "direct",
|
||||
"edit_predictions": {
|
||||
// A list of globs representing files that edit predictions should be disabled for.
|
||||
// There's a sensible default list of globs already included.
|
||||
// Any addition to this list will be merged with the default list.
|
||||
"disabled_globs": [
|
||||
"**/.env*",
|
||||
"**/*.pem",
|
||||
"**/*.key",
|
||||
"**/*.cert",
|
||||
"**/*.crt",
|
||||
"**/.dev.vars",
|
||||
"**/secrets.yml"
|
||||
],
|
||||
// When to show edit predictions previews in buffer.
|
||||
// This setting takes two possible values:
|
||||
// 1. Display inline when there are no language server completions available.
|
||||
// "mode": "eager_preview"
|
||||
// 2. Display inline when holding modifier key (alt by default).
|
||||
// "mode": "auto"
|
||||
"mode": "eager_preview"
|
||||
"inline_completions": {
|
||||
// A list of globs representing files that inline completions should be disabled for.
|
||||
"disabled_globs": [".env"]
|
||||
},
|
||||
// Settings specific to journaling
|
||||
"journal": {
|
||||
@@ -983,7 +912,7 @@
|
||||
/// Scrollbar-related settings
|
||||
"scrollbar": {
|
||||
/// When to show the scrollbar in the terminal.
|
||||
/// This setting can take five values:
|
||||
/// This setting can take four values:
|
||||
///
|
||||
/// 1. null (default): Inherit editor settings
|
||||
/// 2. Show the scrollbar if there's important information or
|
||||
@@ -1093,7 +1022,6 @@
|
||||
"tab_size": 2
|
||||
},
|
||||
"Diff": {
|
||||
"show_edit_predictions": false,
|
||||
"remove_trailing_whitespace_on_save": false,
|
||||
"ensure_final_newline_on_save": false
|
||||
},
|
||||
@@ -1103,9 +1031,6 @@
|
||||
"Erlang": {
|
||||
"language_servers": ["erlang-ls", "!elp", "..."]
|
||||
},
|
||||
"Git Commit": {
|
||||
"allow_rewrap": "anywhere"
|
||||
},
|
||||
"Go": {
|
||||
"code_actions_on_format": {
|
||||
"source.organizeImports": true
|
||||
@@ -1149,7 +1074,6 @@
|
||||
"Markdown": {
|
||||
"format_on_save": "off",
|
||||
"use_on_type_format": false,
|
||||
"allow_rewrap": "anywhere",
|
||||
"prettier": {
|
||||
"allowed": true
|
||||
}
|
||||
@@ -1162,9 +1086,6 @@
|
||||
"parser": "php"
|
||||
}
|
||||
},
|
||||
"Plain Text": {
|
||||
"allow_rewrap": "anywhere"
|
||||
},
|
||||
"Ruby": {
|
||||
"language_servers": ["solargraph", "!ruby-lsp", "!rubocop", "..."]
|
||||
},
|
||||
@@ -1245,12 +1166,6 @@
|
||||
},
|
||||
"lmstudio": {
|
||||
"api_url": "http://localhost:1234/api/v0"
|
||||
},
|
||||
"deepseek": {
|
||||
"api_url": "https://api.deepseek.com"
|
||||
},
|
||||
"mistral": {
|
||||
"api_url": "https://api.mistral.ai/v1"
|
||||
}
|
||||
},
|
||||
// Zed's Prettier integration settings.
|
||||
|
||||
@@ -1,3 +1,549 @@
|
||||
## [Andromeda](https://github.com/EliverLara/Andromeda)
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017 <eliverlara@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
********************************************************************************
|
||||
|
||||
## [Atelier Cave Dark](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
********************************************************************************
|
||||
|
||||
## [Atelier Cave Light](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
********************************************************************************
|
||||
|
||||
## [Atelier Dune Dark](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
********************************************************************************
|
||||
|
||||
## [Atelier Dune Light](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
********************************************************************************
|
||||
|
||||
## [Atelier Estuary Dark](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
********************************************************************************
|
||||
|
||||
## [Atelier Estuary Light](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
********************************************************************************
|
||||
|
||||
## [Atelier Forest Dark](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
********************************************************************************
|
||||
|
||||
## [Atelier Forest Light](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
********************************************************************************
|
||||
|
||||
## [Atelier Heath Dark](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
********************************************************************************
|
||||
|
||||
## [Atelier Heath Light](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
********************************************************************************
|
||||
|
||||
## [Atelier Lakeside Dark](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
********************************************************************************
|
||||
|
||||
## [Atelier Lakeside Light](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
********************************************************************************
|
||||
|
||||
## [Atelier Plateau Dark](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
********************************************************************************
|
||||
|
||||
## [Atelier Plateau Light](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
********************************************************************************
|
||||
|
||||
## [Atelier Savanna Dark](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
********************************************************************************
|
||||
|
||||
## [Atelier Savanna Light](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
********************************************************************************
|
||||
|
||||
## [Atelier Seaside Dark](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
********************************************************************************
|
||||
|
||||
## [Atelier Seaside Light](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
********************************************************************************
|
||||
|
||||
## [Atelier Sulphurpool Dark](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
********************************************************************************
|
||||
|
||||
## [Atelier Sulphurpool Light](https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/)
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
********************************************************************************
|
||||
|
||||
## [Ayu Dark](https://github.com/dempfi/ayu)
|
||||
|
||||
The MIT License (MIT)
|
||||
@@ -281,3 +827,187 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
********************************************************************************
|
||||
|
||||
## [Rosé Pine](https://github.com/edunfelt/base16-rose-pine-scheme)
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2021 Emilia Dunfelt
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
********************************************************************************
|
||||
|
||||
## [Rosé Pine Dawn](https://github.com/edunfelt/base16-rose-pine-scheme)
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2021 Emilia Dunfelt
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
********************************************************************************
|
||||
|
||||
## [Rosé Pine Moon](https://github.com/edunfelt/base16-rose-pine-scheme)
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2021 Emilia Dunfelt
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
********************************************************************************
|
||||
|
||||
## [Sandcastle](https://github.com/gessig/base16-sandcastle-scheme)
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2019 George Essig
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
********************************************************************************
|
||||
|
||||
## [Solarized Dark](https://github.com/altercation/solarized)
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2011 Ethan Schoonover
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
********************************************************************************
|
||||
|
||||
## [Solarized Light](https://github.com/altercation/solarized)
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2011 Ethan Schoonover
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
********************************************************************************
|
||||
|
||||
## [Summercamp](https://github.com/zoefiri/base16-sc)
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2019 Zoe FiriH
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
********************************************************************************
|
||||
|
||||
21
assets/themes/andromeda/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017 <eliverlara@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
378
assets/themes/andromeda/andromeda.json
Normal file
@@ -0,0 +1,378 @@
|
||||
{
|
||||
"$schema": "https://zed.dev/schema/themes/v0.2.0.json",
|
||||
"name": "Andromeda",
|
||||
"author": "Zed Industries",
|
||||
"themes": [
|
||||
{
|
||||
"name": "Andromeda",
|
||||
"appearance": "dark",
|
||||
"style": {
|
||||
"border": "#2b2f38ff",
|
||||
"border.variant": "#252931ff",
|
||||
"border.focused": "#183934ff",
|
||||
"border.selected": "#183934ff",
|
||||
"border.transparent": "#00000000",
|
||||
"border.disabled": "#292d37ff",
|
||||
"elevated_surface.background": "#21242bff",
|
||||
"surface.background": "#21242bff",
|
||||
"background": "#262933ff",
|
||||
"element.background": "#21242bff",
|
||||
"element.hover": "#252931ff",
|
||||
"element.active": "#2a2f39ff",
|
||||
"element.selected": "#2a2f39ff",
|
||||
"element.disabled": "#21242bff",
|
||||
"drop_target.background": "#aca8ae80",
|
||||
"ghost_element.background": "#00000000",
|
||||
"ghost_element.hover": "#252931ff",
|
||||
"ghost_element.active": "#2a2f39ff",
|
||||
"ghost_element.selected": "#2a2f39ff",
|
||||
"ghost_element.disabled": "#21242bff",
|
||||
"text": "#f7f7f8ff",
|
||||
"text.muted": "#aca8aeff",
|
||||
"text.placeholder": "#6b6b73ff",
|
||||
"text.disabled": "#6b6b73ff",
|
||||
"text.accent": "#10a793ff",
|
||||
"icon": "#f7f7f8ff",
|
||||
"icon.muted": "#aca8aeff",
|
||||
"icon.disabled": "#6b6b73ff",
|
||||
"icon.placeholder": "#aca8aeff",
|
||||
"icon.accent": "#10a793ff",
|
||||
"status_bar.background": "#262933ff",
|
||||
"title_bar.background": "#262933ff",
|
||||
"title_bar.inactive_background": "#21242bff",
|
||||
"toolbar.background": "#1e2025ff",
|
||||
"tab_bar.background": "#21242bff",
|
||||
"tab.inactive_background": "#21242bff",
|
||||
"tab.active_background": "#1e2025ff",
|
||||
"search.match_background": "#11a79366",
|
||||
"panel.background": "#21242bff",
|
||||
"panel.focused_border": "#10a793ff",
|
||||
"pane.focused_border": null,
|
||||
"scrollbar.thumb.background": "#f7f7f84c",
|
||||
"scrollbar.thumb.hover_background": "#252931ff",
|
||||
"scrollbar.thumb.border": "#252931ff",
|
||||
"scrollbar.track.background": "#00000000",
|
||||
"scrollbar.track.border": "#21232aff",
|
||||
"editor.foreground": "#f7f7f8ff",
|
||||
"editor.background": "#1e2025ff",
|
||||
"editor.gutter.background": "#1e2025ff",
|
||||
"editor.subheader.background": "#21242bff",
|
||||
"editor.active_line.background": "#21242bbf",
|
||||
"editor.highlighted_line.background": "#21242bff",
|
||||
"editor.line_number": "#565960",
|
||||
"editor.active_line_number": "#f8f8f9",
|
||||
"editor.hover_line_number": "#cbcdd0",
|
||||
"editor.invisible": "#64646dff",
|
||||
"editor.wrap_guide": "#f7f7f80d",
|
||||
"editor.active_wrap_guide": "#f7f7f81a",
|
||||
"editor.document_highlight.read_background": "#10a7931a",
|
||||
"editor.document_highlight.write_background": "#64646d66",
|
||||
"terminal.background": "#1e2025ff",
|
||||
"terminal.foreground": "#f7f7f8ff",
|
||||
"terminal.bright_foreground": "#f7f7f8ff",
|
||||
"terminal.dim_foreground": "#1e2025ff",
|
||||
"terminal.ansi.black": "#1e2025ff",
|
||||
"terminal.ansi.bright_black": "#40434cff",
|
||||
"terminal.ansi.dim_black": "#f7f7f8ff",
|
||||
"terminal.ansi.red": "#f82871ff",
|
||||
"terminal.ansi.bright_red": "#8e0f3aff",
|
||||
"terminal.ansi.dim_red": "#ffa3b5ff",
|
||||
"terminal.ansi.green": "#96df71ff",
|
||||
"terminal.ansi.bright_green": "#457c38ff",
|
||||
"terminal.ansi.dim_green": "#cef0b9ff",
|
||||
"terminal.ansi.yellow": "#fee56cff",
|
||||
"terminal.ansi.bright_yellow": "#958334ff",
|
||||
"terminal.ansi.dim_yellow": "#fef1b7ff",
|
||||
"terminal.ansi.blue": "#10a793ff",
|
||||
"terminal.ansi.bright_blue": "#1a5148ff",
|
||||
"terminal.ansi.dim_blue": "#9cd4c7ff",
|
||||
"terminal.ansi.magenta": "#c74cecff",
|
||||
"terminal.ansi.bright_magenta": "#682681ff",
|
||||
"terminal.ansi.dim_magenta": "#e7abf7ff",
|
||||
"terminal.ansi.cyan": "#08e7c5ff",
|
||||
"terminal.ansi.bright_cyan": "#008169ff",
|
||||
"terminal.ansi.dim_cyan": "#a9f4e1ff",
|
||||
"terminal.ansi.white": "#f7f7f8ff",
|
||||
"terminal.ansi.bright_white": "#f7f7f8ff",
|
||||
"terminal.ansi.dim_white": "#87858cff",
|
||||
"link_text.hover": "#10a793ff",
|
||||
"conflict": "#fee56cff",
|
||||
"conflict.background": "#5c5014ff",
|
||||
"conflict.border": "#796b26ff",
|
||||
"created": "#96df71ff",
|
||||
"created.background": "#184618ff",
|
||||
"created.border": "#306129ff",
|
||||
"deleted": "#f82871ff",
|
||||
"deleted.background": "#54051bff",
|
||||
"deleted.border": "#72092aff",
|
||||
"error": "#f82871ff",
|
||||
"error.background": "#54051bff",
|
||||
"error.border": "#72092aff",
|
||||
"hidden": "#6b6b73ff",
|
||||
"hidden.background": "#262933ff",
|
||||
"hidden.border": "#292d37ff",
|
||||
"hint": "#618399ff",
|
||||
"hint.background": "#12231fff",
|
||||
"hint.border": "#183934ff",
|
||||
"ignored": "#6b6b73ff",
|
||||
"ignored.background": "#262933ff",
|
||||
"ignored.border": "#2b2f38ff",
|
||||
"info": "#10a793ff",
|
||||
"info.background": "#12231fff",
|
||||
"info.border": "#183934ff",
|
||||
"modified": "#fee56cff",
|
||||
"modified.background": "#5c5014ff",
|
||||
"modified.border": "#796b26ff",
|
||||
"predictive": "#315f70ff",
|
||||
"predictive.background": "#184618ff",
|
||||
"predictive.border": "#306129ff",
|
||||
"renamed": "#10a793ff",
|
||||
"renamed.background": "#12231fff",
|
||||
"renamed.border": "#183934ff",
|
||||
"success": "#96df71ff",
|
||||
"success.background": "#184618ff",
|
||||
"success.border": "#306129ff",
|
||||
"unreachable": "#aca8aeff",
|
||||
"unreachable.background": "#262933ff",
|
||||
"unreachable.border": "#2b2f38ff",
|
||||
"warning": "#fee56cff",
|
||||
"warning.background": "#5c5014ff",
|
||||
"warning.border": "#796b26ff",
|
||||
"players": [
|
||||
{
|
||||
"cursor": "#10a793ff",
|
||||
"background": "#10a793ff",
|
||||
"selection": "#10a7933d"
|
||||
},
|
||||
{
|
||||
"cursor": "#c74cecff",
|
||||
"background": "#c74cecff",
|
||||
"selection": "#c74cec3d"
|
||||
},
|
||||
{
|
||||
"cursor": "#f29c14ff",
|
||||
"background": "#f29c14ff",
|
||||
"selection": "#f29c143d"
|
||||
},
|
||||
{
|
||||
"cursor": "#893ea6ff",
|
||||
"background": "#893ea6ff",
|
||||
"selection": "#893ea63d"
|
||||
},
|
||||
{
|
||||
"cursor": "#08e7c5ff",
|
||||
"background": "#08e7c5ff",
|
||||
"selection": "#08e7c53d"
|
||||
},
|
||||
{
|
||||
"cursor": "#f82871ff",
|
||||
"background": "#f82871ff",
|
||||
"selection": "#f828713d"
|
||||
},
|
||||
{
|
||||
"cursor": "#fee56cff",
|
||||
"background": "#fee56cff",
|
||||
"selection": "#fee56c3d"
|
||||
},
|
||||
{
|
||||
"cursor": "#96df71ff",
|
||||
"background": "#96df71ff",
|
||||
"selection": "#96df713d"
|
||||
}
|
||||
],
|
||||
"syntax": {
|
||||
"attribute": {
|
||||
"color": "#10a793ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"boolean": {
|
||||
"color": "#96df71ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"comment": {
|
||||
"color": "#afabb1ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"comment.doc": {
|
||||
"color": "#afabb1ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"constant": {
|
||||
"color": "#96df71ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"constructor": {
|
||||
"color": "#10a793ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"embedded": {
|
||||
"color": "#f7f7f8ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"emphasis": {
|
||||
"color": "#10a793ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"emphasis.strong": {
|
||||
"color": "#10a793ff",
|
||||
"font_style": null,
|
||||
"font_weight": 700
|
||||
},
|
||||
"enum": {
|
||||
"color": "#f29c14ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"function": {
|
||||
"color": "#fee56cff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"hint": {
|
||||
"color": "#618399ff",
|
||||
"font_style": null,
|
||||
"font_weight": 700
|
||||
},
|
||||
"keyword": {
|
||||
"color": "#10a793ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"label": {
|
||||
"color": "#10a793ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"link_text": {
|
||||
"color": "#f29c14ff",
|
||||
"font_style": "italic",
|
||||
"font_weight": null
|
||||
},
|
||||
"link_uri": {
|
||||
"color": "#96df71ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"number": {
|
||||
"color": "#96df71ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"operator": {
|
||||
"color": "#f29c14ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"predictive": {
|
||||
"color": "#315f70ff",
|
||||
"font_style": "italic",
|
||||
"font_weight": null
|
||||
},
|
||||
"preproc": {
|
||||
"color": "#f7f7f8ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"primary": {
|
||||
"color": "#f7f7f8ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"property": {
|
||||
"color": "#10a793ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"punctuation": {
|
||||
"color": "#d8d5dbff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"punctuation.bracket": {
|
||||
"color": "#d8d5dbff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"punctuation.delimiter": {
|
||||
"color": "#d8d5dbff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"punctuation.list_marker": {
|
||||
"color": "#d8d5dbff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"punctuation.special": {
|
||||
"color": "#d8d5dbff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"string": {
|
||||
"color": "#f29c14ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"string.escape": {
|
||||
"color": "#afabb1ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"string.regex": {
|
||||
"color": "#f29c14ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"string.special": {
|
||||
"color": "#f29c14ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"string.special.symbol": {
|
||||
"color": "#f29c14ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"tag": {
|
||||
"color": "#10a793ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"text.literal": {
|
||||
"color": "#f29c14ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"title": {
|
||||
"color": "#f7f7f8ff",
|
||||
"font_style": null,
|
||||
"font_weight": 700
|
||||
},
|
||||
"type": {
|
||||
"color": "#08e7c5ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"variable": {
|
||||
"color": "#f7f7f8ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"variant": {
|
||||
"color": "#10a793ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
21
assets/themes/atelier/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2023 Bram de Haan, http://atelierbramdehaan.nl
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
7727
assets/themes/atelier/atelier.json
Normal file
@@ -105,9 +105,6 @@
|
||||
"terminal.ansi.bright_white": "#fbf1c7ff",
|
||||
"terminal.ansi.dim_white": "#b0a189ff",
|
||||
"link_text.hover": "#83a598ff",
|
||||
"version_control_added": "#b7bb26ff",
|
||||
"version_control_modified": "#f9bd2fff",
|
||||
"version_control_deleted": "#fb4a35ff",
|
||||
"conflict": "#f9bd2fff",
|
||||
"conflict.background": "#572e10ff",
|
||||
"conflict.border": "#754916ff",
|
||||
@@ -379,7 +376,7 @@
|
||||
"font_weight": null
|
||||
},
|
||||
"variable": {
|
||||
"color": "#ebdbb2ff",
|
||||
"color": "#83a598ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
@@ -493,9 +490,6 @@
|
||||
"terminal.ansi.bright_white": "#fbf1c7ff",
|
||||
"terminal.ansi.dim_white": "#b0a189ff",
|
||||
"link_text.hover": "#83a598ff",
|
||||
"version_control_added": "#b7bb26ff",
|
||||
"version_control_modified": "#f9bd2fff",
|
||||
"version_control_deleted": "#fb4a35ff",
|
||||
"conflict": "#f9bd2fff",
|
||||
"conflict.background": "#572e10ff",
|
||||
"conflict.border": "#754916ff",
|
||||
@@ -767,7 +761,7 @@
|
||||
"font_weight": null
|
||||
},
|
||||
"variable": {
|
||||
"color": "#ebdbb2ff",
|
||||
"color": "#83a598ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
@@ -881,9 +875,6 @@
|
||||
"terminal.ansi.bright_white": "#fbf1c7ff",
|
||||
"terminal.ansi.dim_white": "#b0a189ff",
|
||||
"link_text.hover": "#83a598ff",
|
||||
"version_control_added": "#b7bb26ff",
|
||||
"version_control_modified": "#f9bd2fff",
|
||||
"version_control_deleted": "#fb4a35ff",
|
||||
"conflict": "#f9bd2fff",
|
||||
"conflict.background": "#572e10ff",
|
||||
"conflict.border": "#754916ff",
|
||||
@@ -1155,7 +1146,7 @@
|
||||
"font_weight": null
|
||||
},
|
||||
"variable": {
|
||||
"color": "#ebdbb2ff",
|
||||
"color": "#83a598ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
@@ -1269,9 +1260,6 @@
|
||||
"terminal.ansi.bright_white": "#282828ff",
|
||||
"terminal.ansi.dim_white": "#73675eff",
|
||||
"link_text.hover": "#0b6678ff",
|
||||
"version_control_added": "#797410ff",
|
||||
"version_control_modified": "#b57615ff",
|
||||
"version_control_deleted": "#9d0308ff",
|
||||
"conflict": "#b57615ff",
|
||||
"conflict.background": "#f5e2d0ff",
|
||||
"conflict.border": "#ebccabff",
|
||||
@@ -1543,7 +1531,7 @@
|
||||
"font_weight": null
|
||||
},
|
||||
"variable": {
|
||||
"color": "#282828ff",
|
||||
"color": "#066578ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
@@ -1657,9 +1645,6 @@
|
||||
"terminal.ansi.bright_white": "#282828ff",
|
||||
"terminal.ansi.dim_white": "#73675eff",
|
||||
"link_text.hover": "#0b6678ff",
|
||||
"version_control_added": "#797410ff",
|
||||
"version_control_modified": "#b57615ff",
|
||||
"version_control_deleted": "#9d0308ff",
|
||||
"conflict": "#b57615ff",
|
||||
"conflict.background": "#f5e2d0ff",
|
||||
"conflict.border": "#ebccabff",
|
||||
@@ -1931,7 +1916,7 @@
|
||||
"font_weight": null
|
||||
},
|
||||
"variable": {
|
||||
"color": "#282828ff",
|
||||
"color": "#066578ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
@@ -2045,9 +2030,6 @@
|
||||
"terminal.ansi.bright_white": "#282828ff",
|
||||
"terminal.ansi.dim_white": "#73675eff",
|
||||
"link_text.hover": "#0b6678ff",
|
||||
"version_control_added": "#797410ff",
|
||||
"version_control_modified": "#b57615ff",
|
||||
"version_control_deleted": "#9d0308ff",
|
||||
"conflict": "#b57615ff",
|
||||
"conflict.background": "#f5e2d0ff",
|
||||
"conflict.border": "#ebccabff",
|
||||
@@ -2319,7 +2301,7 @@
|
||||
"font_weight": null
|
||||
},
|
||||
"variable": {
|
||||
"color": "#282828ff",
|
||||
"color": "#066578ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
"terminal.ansi.bright_green": "#4d6140ff",
|
||||
"terminal.ansi.dim_green": "#d1e0bfff",
|
||||
"terminal.ansi.yellow": "#dec184ff",
|
||||
"terminal.ansi.bright_yellow": "#e5c07bff",
|
||||
"terminal.ansi.bright_yellow": "#786441ff",
|
||||
"terminal.ansi.dim_yellow": "#f1dfc1ff",
|
||||
"terminal.ansi.blue": "#74ade8ff",
|
||||
"terminal.ansi.bright_blue": "#385378ff",
|
||||
@@ -96,9 +96,6 @@
|
||||
"terminal.ansi.bright_white": "#dce0e5ff",
|
||||
"terminal.ansi.dim_white": "#575d65ff",
|
||||
"link_text.hover": "#74ade8ff",
|
||||
"version_control_added": "#a7c088ff",
|
||||
"version_control_modified": "#dec184ff",
|
||||
"version_control_deleted": "#d07277ff",
|
||||
"conflict": "#dec184ff",
|
||||
"conflict.background": "#dec1841a",
|
||||
"conflict.border": "#5d4c2fff",
|
||||
@@ -365,7 +362,7 @@
|
||||
"font_weight": null
|
||||
},
|
||||
"variable": {
|
||||
"color": "#acb2beff",
|
||||
"color": "#dce0e5ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
@@ -444,7 +441,7 @@
|
||||
"editor.invisible": "#a3a3a4ff",
|
||||
"editor.wrap_guide": "#383a410d",
|
||||
"editor.active_wrap_guide": "#383a411a",
|
||||
"editor.document_highlight.read_background": "#5c78e225",
|
||||
"editor.document_highlight.read_background": "#5c78e21a",
|
||||
"editor.document_highlight.write_background": "#a3a3a466",
|
||||
"terminal.background": "#fafafaff",
|
||||
"terminal.foreground": "#242529ff",
|
||||
@@ -460,7 +457,7 @@
|
||||
"terminal.ansi.bright_green": "#b2cfa9ff",
|
||||
"terminal.ansi.dim_green": "#354d2eff",
|
||||
"terminal.ansi.yellow": "#dec184ff",
|
||||
"terminal.ansi.bright_yellow": "#826221ff",
|
||||
"terminal.ansi.bright_yellow": "#f1dfc1ff",
|
||||
"terminal.ansi.dim_yellow": "#786441ff",
|
||||
"terminal.ansi.blue": "#5c78e2ff",
|
||||
"terminal.ansi.bright_blue": "#b5baf2ff",
|
||||
@@ -475,9 +472,6 @@
|
||||
"terminal.ansi.bright_white": "#242529ff",
|
||||
"terminal.ansi.dim_white": "#97979aff",
|
||||
"link_text.hover": "#5c78e2ff",
|
||||
"version_control_added": "#669f59ff",
|
||||
"version_control_modified": "#a48819ff",
|
||||
"version_control_deleted": "#d36151ff",
|
||||
"conflict": "#a48819ff",
|
||||
"conflict.background": "#faf2e6ff",
|
||||
"conflict.border": "#f4e7d1ff",
|
||||
|
||||
21
assets/themes/rose_pine/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2021 Emilia Dunfelt
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
1150
assets/themes/rose_pine/rose_pine.json
Normal file
21
assets/themes/sandcastle/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2019 George Essig
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
378
assets/themes/sandcastle/sandcastle.json
Normal file
@@ -0,0 +1,378 @@
|
||||
{
|
||||
"$schema": "https://zed.dev/schema/themes/v0.2.0.json",
|
||||
"name": "Sandcastle",
|
||||
"author": "Zed Industries",
|
||||
"themes": [
|
||||
{
|
||||
"name": "Sandcastle",
|
||||
"appearance": "dark",
|
||||
"style": {
|
||||
"border": "#3d4350ff",
|
||||
"border.variant": "#313741ff",
|
||||
"border.focused": "#223131ff",
|
||||
"border.selected": "#223131ff",
|
||||
"border.transparent": "#00000000",
|
||||
"border.disabled": "#393f4aff",
|
||||
"elevated_surface.background": "#2b3038ff",
|
||||
"surface.background": "#2b3038ff",
|
||||
"background": "#333944ff",
|
||||
"element.background": "#2b3038ff",
|
||||
"element.hover": "#313741ff",
|
||||
"element.active": "#3d4350ff",
|
||||
"element.selected": "#3d4350ff",
|
||||
"element.disabled": "#2b3038ff",
|
||||
"drop_target.background": "#a6978280",
|
||||
"ghost_element.background": "#00000000",
|
||||
"ghost_element.hover": "#313741ff",
|
||||
"ghost_element.active": "#3d4350ff",
|
||||
"ghost_element.selected": "#3d4350ff",
|
||||
"ghost_element.disabled": "#2b3038ff",
|
||||
"text": "#fdf4c1ff",
|
||||
"text.muted": "#a69782ff",
|
||||
"text.placeholder": "#827568ff",
|
||||
"text.disabled": "#827568ff",
|
||||
"text.accent": "#518b8bff",
|
||||
"icon": "#fdf4c1ff",
|
||||
"icon.muted": "#a69782ff",
|
||||
"icon.disabled": "#827568ff",
|
||||
"icon.placeholder": "#a69782ff",
|
||||
"icon.accent": "#518b8bff",
|
||||
"status_bar.background": "#333944ff",
|
||||
"title_bar.background": "#333944ff",
|
||||
"title_bar.inactive_background": "#2b3038ff",
|
||||
"toolbar.background": "#282c33ff",
|
||||
"tab_bar.background": "#2b3038ff",
|
||||
"tab.inactive_background": "#2b3038ff",
|
||||
"tab.active_background": "#282c33ff",
|
||||
"search.match_background": "#528b8b66",
|
||||
"panel.background": "#2b3038ff",
|
||||
"panel.focused_border": "#518b8bff",
|
||||
"pane.focused_border": null,
|
||||
"scrollbar.thumb.background": "#fdf4c14c",
|
||||
"scrollbar.thumb.hover_background": "#313741ff",
|
||||
"scrollbar.thumb.border": "#313741ff",
|
||||
"scrollbar.track.background": "#00000000",
|
||||
"scrollbar.track.border": "#2a2f38ff",
|
||||
"editor.foreground": "#fdf4c1ff",
|
||||
"editor.background": "#282c33ff",
|
||||
"editor.gutter.background": "#282c33ff",
|
||||
"editor.subheader.background": "#2b3038ff",
|
||||
"editor.active_line.background": "#2b3038bf",
|
||||
"editor.highlighted_line.background": "#2b3038ff",
|
||||
"editor.line_number": "#6b6b61",
|
||||
"editor.active_line_number": "#dbdbd7",
|
||||
"editor.hover_line_number": "#b6b6af",
|
||||
"editor.invisible": "#7c6f64ff",
|
||||
"editor.wrap_guide": "#fdf4c10d",
|
||||
"editor.active_wrap_guide": "#fdf4c11a",
|
||||
"editor.document_highlight.read_background": "#518b8b1a",
|
||||
"editor.document_highlight.write_background": "#7c6f6466",
|
||||
"terminal.background": "#282c33ff",
|
||||
"terminal.foreground": "#fdf4c1ff",
|
||||
"terminal.bright_foreground": "#fdf4c1ff",
|
||||
"terminal.dim_foreground": "#282c33ff",
|
||||
"terminal.ansi.black": "#282c33ff",
|
||||
"terminal.ansi.bright_black": "#5e5753ff",
|
||||
"terminal.ansi.dim_black": "#fdf4c1ff",
|
||||
"terminal.ansi.red": "#b3627aff",
|
||||
"terminal.ansi.bright_red": "#57333dff",
|
||||
"terminal.ansi.dim_red": "#dcb0bbff",
|
||||
"terminal.ansi.green": "#83a598ff",
|
||||
"terminal.ansi.bright_green": "#414f4aff",
|
||||
"terminal.ansi.dim_green": "#c0d2cbff",
|
||||
"terminal.ansi.yellow": "#a07d3aff",
|
||||
"terminal.ansi.bright_yellow": "#4e3f22ff",
|
||||
"terminal.ansi.dim_yellow": "#d3bd9aff",
|
||||
"terminal.ansi.blue": "#518b8bff",
|
||||
"terminal.ansi.bright_blue": "#2c4444ff",
|
||||
"terminal.ansi.dim_blue": "#a8c4c4ff",
|
||||
"terminal.ansi.magenta": "#a87222ff",
|
||||
"terminal.ansi.bright_magenta": "#523918ff",
|
||||
"terminal.ansi.dim_magenta": "#dab78eff",
|
||||
"terminal.ansi.cyan": "#83a598ff",
|
||||
"terminal.ansi.bright_cyan": "#414f4aff",
|
||||
"terminal.ansi.dim_cyan": "#c0d2cbff",
|
||||
"terminal.ansi.white": "#fdf4c1ff",
|
||||
"terminal.ansi.bright_white": "#fdf4c1ff",
|
||||
"terminal.ansi.dim_white": "#958776ff",
|
||||
"link_text.hover": "#518b8bff",
|
||||
"conflict": "#a07d3aff",
|
||||
"conflict.background": "#231d12ff",
|
||||
"conflict.border": "#392e19ff",
|
||||
"created": "#83a598ff",
|
||||
"created.background": "#1e2321ff",
|
||||
"created.border": "#303a36ff",
|
||||
"deleted": "#b3627aff",
|
||||
"deleted.background": "#26191cff",
|
||||
"deleted.border": "#3e272dff",
|
||||
"error": "#b3627aff",
|
||||
"error.background": "#26191cff",
|
||||
"error.border": "#3e272dff",
|
||||
"hidden": "#827568ff",
|
||||
"hidden.background": "#333944ff",
|
||||
"hidden.border": "#393f4aff",
|
||||
"hint": "#727d68ff",
|
||||
"hint.background": "#171e1eff",
|
||||
"hint.border": "#223131ff",
|
||||
"ignored": "#827568ff",
|
||||
"ignored.background": "#333944ff",
|
||||
"ignored.border": "#3d4350ff",
|
||||
"info": "#518b8bff",
|
||||
"info.background": "#171e1eff",
|
||||
"info.border": "#223131ff",
|
||||
"modified": "#a07d3aff",
|
||||
"modified.background": "#231d12ff",
|
||||
"modified.border": "#392e19ff",
|
||||
"predictive": "#5c6152ff",
|
||||
"predictive.background": "#1e2321ff",
|
||||
"predictive.border": "#303a36ff",
|
||||
"renamed": "#518b8bff",
|
||||
"renamed.background": "#171e1eff",
|
||||
"renamed.border": "#223131ff",
|
||||
"success": "#83a598ff",
|
||||
"success.background": "#1e2321ff",
|
||||
"success.border": "#303a36ff",
|
||||
"unreachable": "#a69782ff",
|
||||
"unreachable.background": "#333944ff",
|
||||
"unreachable.border": "#3d4350ff",
|
||||
"warning": "#a07d3aff",
|
||||
"warning.background": "#231d12ff",
|
||||
"warning.border": "#392e19ff",
|
||||
"players": [
|
||||
{
|
||||
"cursor": "#518b8bff",
|
||||
"background": "#518b8bff",
|
||||
"selection": "#518b8b3d"
|
||||
},
|
||||
{
|
||||
"cursor": "#a87222ff",
|
||||
"background": "#a87222ff",
|
||||
"selection": "#a872223d"
|
||||
},
|
||||
{
|
||||
"cursor": "#a07d3aff",
|
||||
"background": "#a07d3aff",
|
||||
"selection": "#a07d3a3d"
|
||||
},
|
||||
{
|
||||
"cursor": "#d75f5fff",
|
||||
"background": "#d75f5fff",
|
||||
"selection": "#d75f5f3d"
|
||||
},
|
||||
{
|
||||
"cursor": "#83a598ff",
|
||||
"background": "#83a598ff",
|
||||
"selection": "#83a5983d"
|
||||
},
|
||||
{
|
||||
"cursor": "#b3627aff",
|
||||
"background": "#b3627aff",
|
||||
"selection": "#b3627a3d"
|
||||
},
|
||||
{
|
||||
"cursor": "#a07d3aff",
|
||||
"background": "#a07d3aff",
|
||||
"selection": "#a07d3a3d"
|
||||
},
|
||||
{
|
||||
"cursor": "#83a598ff",
|
||||
"background": "#83a598ff",
|
||||
"selection": "#83a5983d"
|
||||
}
|
||||
],
|
||||
"syntax": {
|
||||
"attribute": {
|
||||
"color": "#518b8bff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"boolean": {
|
||||
"color": "#83a598ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"comment": {
|
||||
"color": "#a89984ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"comment.doc": {
|
||||
"color": "#a89984ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"constant": {
|
||||
"color": "#83a598ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"constructor": {
|
||||
"color": "#518b8bff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"embedded": {
|
||||
"color": "#fdf4c1ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"emphasis": {
|
||||
"color": "#518b8bff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"emphasis.strong": {
|
||||
"color": "#518b8bff",
|
||||
"font_style": null,
|
||||
"font_weight": 700
|
||||
},
|
||||
"enum": {
|
||||
"color": "#a07d3aff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"function": {
|
||||
"color": "#a07d3aff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"hint": {
|
||||
"color": "#727d68ff",
|
||||
"font_style": null,
|
||||
"font_weight": 700
|
||||
},
|
||||
"keyword": {
|
||||
"color": "#518b8bff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"label": {
|
||||
"color": "#518b8bff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"link_text": {
|
||||
"color": "#a07d3aff",
|
||||
"font_style": "italic",
|
||||
"font_weight": null
|
||||
},
|
||||
"link_uri": {
|
||||
"color": "#83a598ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"number": {
|
||||
"color": "#83a598ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"operator": {
|
||||
"color": "#a07d3aff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"predictive": {
|
||||
"color": "#5c6152ff",
|
||||
"font_style": "italic",
|
||||
"font_weight": null
|
||||
},
|
||||
"preproc": {
|
||||
"color": "#fdf4c1ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"primary": {
|
||||
"color": "#fdf4c1ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"property": {
|
||||
"color": "#518b8bff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"punctuation": {
|
||||
"color": "#d5c5a1ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"punctuation.bracket": {
|
||||
"color": "#d5c5a1ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"punctuation.delimiter": {
|
||||
"color": "#d5c5a1ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"punctuation.list_marker": {
|
||||
"color": "#d5c5a1ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"punctuation.special": {
|
||||
"color": "#d5c5a1ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"string": {
|
||||
"color": "#a07d3aff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"string.escape": {
|
||||
"color": "#a89984ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"string.regex": {
|
||||
"color": "#a07d3aff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"string.special": {
|
||||
"color": "#a07d3aff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"string.special.symbol": {
|
||||
"color": "#a07d3aff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"tag": {
|
||||
"color": "#518b8bff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"text.literal": {
|
||||
"color": "#a07d3aff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"title": {
|
||||
"color": "#fdf4c1ff",
|
||||
"font_style": null,
|
||||
"font_weight": 700
|
||||
},
|
||||
"type": {
|
||||
"color": "#83a598ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"variable": {
|
||||
"color": "#fdf4c1ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"variant": {
|
||||
"color": "#518b8bff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
21
assets/themes/solarized/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2011 Ethan Schoonover
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
749
assets/themes/solarized/solarized.json
Normal file
@@ -0,0 +1,749 @@
|
||||
{
|
||||
"$schema": "https://zed.dev/schema/themes/v0.2.0.json",
|
||||
"name": "Solarized",
|
||||
"author": "Zed Industries",
|
||||
"themes": [
|
||||
{
|
||||
"name": "Solarized Dark",
|
||||
"appearance": "dark",
|
||||
"style": {
|
||||
"border": "#2b4e58ff",
|
||||
"border.variant": "#053541ff",
|
||||
"border.focused": "#1b3149ff",
|
||||
"border.selected": "#1b3149ff",
|
||||
"border.transparent": "#00000000",
|
||||
"border.disabled": "#19424dff",
|
||||
"elevated_surface.background": "#04313bff",
|
||||
"surface.background": "#04313bff",
|
||||
"background": "#073743ff",
|
||||
"element.background": "#04313bff",
|
||||
"element.hover": "#053541ff",
|
||||
"element.active": "#294d58ff",
|
||||
"element.selected": "#294d58ff",
|
||||
"element.disabled": "#04313bff",
|
||||
"drop_target.background": "#93a1a180",
|
||||
"ghost_element.background": "#00000000",
|
||||
"ghost_element.hover": "#053541ff",
|
||||
"ghost_element.active": "#294d58ff",
|
||||
"ghost_element.selected": "#294d58ff",
|
||||
"ghost_element.disabled": "#04313bff",
|
||||
"text": "#fdf6e3ff",
|
||||
"text.muted": "#93a1a1ff",
|
||||
"text.placeholder": "#6f8389ff",
|
||||
"text.disabled": "#6f8389ff",
|
||||
"text.accent": "#278ad1ff",
|
||||
"icon": "#fdf6e3ff",
|
||||
"icon.muted": "#93a1a1ff",
|
||||
"icon.disabled": "#6f8389ff",
|
||||
"icon.placeholder": "#93a1a1ff",
|
||||
"icon.accent": "#278ad1ff",
|
||||
"status_bar.background": "#073743ff",
|
||||
"title_bar.background": "#073743ff",
|
||||
"title_bar.inactive_background": "#04313bff",
|
||||
"toolbar.background": "#002a35ff",
|
||||
"tab_bar.background": "#04313bff",
|
||||
"tab.inactive_background": "#04313bff",
|
||||
"tab.active_background": "#002a35ff",
|
||||
"search.match_background": "#288bd166",
|
||||
"panel.background": "#04313bff",
|
||||
"panel.focused_border": "#278ad1ff",
|
||||
"pane.focused_border": null,
|
||||
"scrollbar.thumb.background": "#fdf6e34c",
|
||||
"scrollbar.thumb.hover_background": "#053541ff",
|
||||
"scrollbar.thumb.border": "#053541ff",
|
||||
"scrollbar.track.background": "#00000000",
|
||||
"scrollbar.track.border": "#022f3bff",
|
||||
"editor.foreground": "#fdf6e3ff",
|
||||
"editor.background": "#002a35ff",
|
||||
"editor.gutter.background": "#002a35ff",
|
||||
"editor.subheader.background": "#04313bff",
|
||||
"editor.active_line.background": "#04313bbf",
|
||||
"editor.highlighted_line.background": "#04313bff",
|
||||
"editor.line_number": "#5a6d6f",
|
||||
"editor.active_line_number": "#e3e8e8",
|
||||
"editor.hover_line_number": "#abb9ba",
|
||||
"editor.invisible": "#6c8287ff",
|
||||
"editor.wrap_guide": "#fdf6e30d",
|
||||
"editor.active_wrap_guide": "#fdf6e31a",
|
||||
"editor.document_highlight.read_background": "#278ad11a",
|
||||
"editor.document_highlight.write_background": "#6c828766",
|
||||
"terminal.background": "#002a35ff",
|
||||
"terminal.foreground": "#fdf6e3ff",
|
||||
"terminal.bright_foreground": "#fdf6e3ff",
|
||||
"terminal.dim_foreground": "#002a35ff",
|
||||
"terminal.ansi.black": "#002a35ff",
|
||||
"terminal.ansi.bright_black": "#5c7279ff",
|
||||
"terminal.ansi.dim_black": "#fdf6e3ff",
|
||||
"terminal.ansi.red": "#dc3330ff",
|
||||
"terminal.ansi.bright_red": "#7d181cff",
|
||||
"terminal.ansi.dim_red": "#faa091ff",
|
||||
"terminal.ansi.green": "#849903ff",
|
||||
"terminal.ansi.bright_green": "#434a10ff",
|
||||
"terminal.ansi.dim_green": "#c6cb8bff",
|
||||
"terminal.ansi.yellow": "#b58902ff",
|
||||
"terminal.ansi.bright_yellow": "#5d430fff",
|
||||
"terminal.ansi.dim_yellow": "#e0c189ff",
|
||||
"terminal.ansi.blue": "#278ad1ff",
|
||||
"terminal.ansi.bright_blue": "#214365ff",
|
||||
"terminal.ansi.dim_blue": "#a5c3e9ff",
|
||||
"terminal.ansi.magenta": "#d33781ff",
|
||||
"terminal.ansi.bright_magenta": "#6f1f3fff",
|
||||
"terminal.ansi.dim_magenta": "#f0a2beff",
|
||||
"terminal.ansi.cyan": "#2ba198ff",
|
||||
"terminal.ansi.bright_cyan": "#204e4aff",
|
||||
"terminal.ansi.dim_cyan": "#9fd0cbff",
|
||||
"terminal.ansi.white": "#fdf6e3ff",
|
||||
"terminal.ansi.bright_white": "#fdf6e3ff",
|
||||
"terminal.ansi.dim_white": "#7b8e91ff",
|
||||
"link_text.hover": "#278ad1ff",
|
||||
"conflict": "#b58902ff",
|
||||
"conflict.background": "#2e1d0cff",
|
||||
"conflict.border": "#47300fff",
|
||||
"created": "#849903ff",
|
||||
"created.background": "#1e210cff",
|
||||
"created.border": "#313510ff",
|
||||
"deleted": "#dc3330ff",
|
||||
"deleted.background": "#4a080eff",
|
||||
"deleted.border": "#641015ff",
|
||||
"error": "#dc3330ff",
|
||||
"error.background": "#4a080eff",
|
||||
"error.border": "#641015ff",
|
||||
"hidden": "#6f8389ff",
|
||||
"hidden.background": "#073743ff",
|
||||
"hidden.border": "#19424dff",
|
||||
"hint": "#4f8297ff",
|
||||
"hint.background": "#141f2cff",
|
||||
"hint.border": "#1b3149ff",
|
||||
"ignored": "#6f8389ff",
|
||||
"ignored.background": "#073743ff",
|
||||
"ignored.border": "#2b4e58ff",
|
||||
"info": "#278ad1ff",
|
||||
"info.background": "#141f2cff",
|
||||
"info.border": "#1b3149ff",
|
||||
"modified": "#b58902ff",
|
||||
"modified.background": "#2e1d0cff",
|
||||
"modified.border": "#47300fff",
|
||||
"predictive": "#3f718bff",
|
||||
"predictive.background": "#1e210cff",
|
||||
"predictive.border": "#313510ff",
|
||||
"renamed": "#278ad1ff",
|
||||
"renamed.background": "#141f2cff",
|
||||
"renamed.border": "#1b3149ff",
|
||||
"success": "#849903ff",
|
||||
"success.background": "#1e210cff",
|
||||
"success.border": "#313510ff",
|
||||
"unreachable": "#93a1a1ff",
|
||||
"unreachable.background": "#073743ff",
|
||||
"unreachable.border": "#2b4e58ff",
|
||||
"warning": "#b58902ff",
|
||||
"warning.background": "#2e1d0cff",
|
||||
"warning.border": "#47300fff",
|
||||
"players": [
|
||||
{
|
||||
"cursor": "#278ad1ff",
|
||||
"background": "#278ad1ff",
|
||||
"selection": "#278ad13d"
|
||||
},
|
||||
{
|
||||
"cursor": "#d33781ff",
|
||||
"background": "#d33781ff",
|
||||
"selection": "#d337813d"
|
||||
},
|
||||
{
|
||||
"cursor": "#cb4b16ff",
|
||||
"background": "#cb4b16ff",
|
||||
"selection": "#cb4b163d"
|
||||
},
|
||||
{
|
||||
"cursor": "#6c71c4ff",
|
||||
"background": "#6c71c4ff",
|
||||
"selection": "#6c71c43d"
|
||||
},
|
||||
{
|
||||
"cursor": "#2ba198ff",
|
||||
"background": "#2ba198ff",
|
||||
"selection": "#2ba1983d"
|
||||
},
|
||||
{
|
||||
"cursor": "#dc3330ff",
|
||||
"background": "#dc3330ff",
|
||||
"selection": "#dc33303d"
|
||||
},
|
||||
{
|
||||
"cursor": "#b58902ff",
|
||||
"background": "#b58902ff",
|
||||
"selection": "#b589023d"
|
||||
},
|
||||
{
|
||||
"cursor": "#849903ff",
|
||||
"background": "#849903ff",
|
||||
"selection": "#8499033d"
|
||||
}
|
||||
],
|
||||
"syntax": {
|
||||
"attribute": {
|
||||
"color": "#278ad1ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"boolean": {
|
||||
"color": "#849903ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"comment": {
|
||||
"color": "#99a5a4ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"comment.doc": {
|
||||
"color": "#99a5a4ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"constant": {
|
||||
"color": "#849903ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"constructor": {
|
||||
"color": "#278ad1ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"embedded": {
|
||||
"color": "#fdf6e3ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"emphasis": {
|
||||
"color": "#278ad1ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"emphasis.strong": {
|
||||
"color": "#278ad1ff",
|
||||
"font_style": null,
|
||||
"font_weight": 700
|
||||
},
|
||||
"enum": {
|
||||
"color": "#cb4b16ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"function": {
|
||||
"color": "#b58902ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"hint": {
|
||||
"color": "#4f8297ff",
|
||||
"font_style": null,
|
||||
"font_weight": 700
|
||||
},
|
||||
"keyword": {
|
||||
"color": "#278ad1ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"label": {
|
||||
"color": "#278ad1ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"link_text": {
|
||||
"color": "#cb4b16ff",
|
||||
"font_style": "italic",
|
||||
"font_weight": null
|
||||
},
|
||||
"link_uri": {
|
||||
"color": "#849903ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"number": {
|
||||
"color": "#849903ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"operator": {
|
||||
"color": "#cb4b16ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"predictive": {
|
||||
"color": "#3f718bff",
|
||||
"font_style": "italic",
|
||||
"font_weight": null
|
||||
},
|
||||
"preproc": {
|
||||
"color": "#fdf6e3ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"primary": {
|
||||
"color": "#fdf6e3ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"property": {
|
||||
"color": "#278ad1ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"punctuation": {
|
||||
"color": "#efe9d6ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"punctuation.bracket": {
|
||||
"color": "#efe9d6ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"punctuation.delimiter": {
|
||||
"color": "#efe9d6ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"punctuation.list_marker": {
|
||||
"color": "#efe9d6ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"punctuation.special": {
|
||||
"color": "#efe9d6ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"string": {
|
||||
"color": "#cb4b16ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"string.escape": {
|
||||
"color": "#99a5a4ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"string.regex": {
|
||||
"color": "#cb4b16ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"string.special": {
|
||||
"color": "#cb4b16ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"string.special.symbol": {
|
||||
"color": "#cb4b16ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"tag": {
|
||||
"color": "#278ad1ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"text.literal": {
|
||||
"color": "#cb4b16ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"title": {
|
||||
"color": "#fdf6e3ff",
|
||||
"font_style": null,
|
||||
"font_weight": 700
|
||||
},
|
||||
"type": {
|
||||
"color": "#2ba198ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"variable": {
|
||||
"color": "#fdf6e3ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"variant": {
|
||||
"color": "#278ad1ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Solarized Light",
|
||||
"appearance": "light",
|
||||
"style": {
|
||||
"border": "#9faaa8ff",
|
||||
"border.variant": "#dcdacbff",
|
||||
"border.focused": "#bfd3efff",
|
||||
"border.selected": "#bfd3efff",
|
||||
"border.transparent": "#00000000",
|
||||
"border.disabled": "#b6bcb5ff",
|
||||
"elevated_surface.background": "#f3eddaff",
|
||||
"surface.background": "#f3eddaff",
|
||||
"background": "#cfd0c4ff",
|
||||
"element.background": "#f3eddaff",
|
||||
"element.hover": "#dcdacbff",
|
||||
"element.active": "#a2aca9ff",
|
||||
"element.selected": "#a2aca9ff",
|
||||
"element.disabled": "#f3eddaff",
|
||||
"drop_target.background": "#34555e80",
|
||||
"ghost_element.background": "#00000000",
|
||||
"ghost_element.hover": "#dcdacbff",
|
||||
"ghost_element.active": "#a2aca9ff",
|
||||
"ghost_element.selected": "#a2aca9ff",
|
||||
"ghost_element.disabled": "#f3eddaff",
|
||||
"text": "#002a35ff",
|
||||
"text.muted": "#34555eff",
|
||||
"text.placeholder": "#6a7f86ff",
|
||||
"text.disabled": "#6a7f86ff",
|
||||
"text.accent": "#288bd1ff",
|
||||
"icon": "#002a35ff",
|
||||
"icon.muted": "#34555eff",
|
||||
"icon.disabled": "#6a7f86ff",
|
||||
"icon.placeholder": "#34555eff",
|
||||
"icon.accent": "#288bd1ff",
|
||||
"status_bar.background": "#cfd0c4ff",
|
||||
"title_bar.background": "#cfd0c4ff",
|
||||
"title_bar.inactive_background": "#f3eddaff",
|
||||
"toolbar.background": "#fdf6e3ff",
|
||||
"tab_bar.background": "#f3eddaff",
|
||||
"tab.inactive_background": "#f3eddaff",
|
||||
"tab.active_background": "#fdf6e3ff",
|
||||
"search.match_background": "#298bd166",
|
||||
"panel.background": "#f3eddaff",
|
||||
"panel.focused_border": "#288bd1ff",
|
||||
"pane.focused_border": null,
|
||||
"scrollbar.thumb.background": "#002a354c",
|
||||
"scrollbar.thumb.hover_background": "#dcdacbff",
|
||||
"scrollbar.thumb.border": "#dcdacbff",
|
||||
"scrollbar.track.background": "#00000000",
|
||||
"scrollbar.track.border": "#f5eedbff",
|
||||
"editor.foreground": "#002a35ff",
|
||||
"editor.background": "#fdf6e3ff",
|
||||
"editor.gutter.background": "#fdf6e3ff",
|
||||
"editor.subheader.background": "#f3eddaff",
|
||||
"editor.active_line.background": "#f3eddabf",
|
||||
"editor.highlighted_line.background": "#f3eddaff",
|
||||
"editor.line_number": "#a8ad9f",
|
||||
"editor.active_line_number": "#272923",
|
||||
"editor.hover_line_number": "#42453b",
|
||||
"editor.invisible": "#6c8287ff",
|
||||
"editor.wrap_guide": "#002a350d",
|
||||
"editor.active_wrap_guide": "#002a351a",
|
||||
"editor.document_highlight.read_background": "#288bd11a",
|
||||
"editor.document_highlight.write_background": "#6c828766",
|
||||
"terminal.background": "#fdf6e3ff",
|
||||
"terminal.foreground": "#002a35ff",
|
||||
"terminal.bright_foreground": "#002a35ff",
|
||||
"terminal.dim_foreground": "#fdf6e3ff",
|
||||
"terminal.ansi.black": "#fdf6e3ff",
|
||||
"terminal.ansi.bright_black": "#7b8e91ff",
|
||||
"terminal.ansi.dim_black": "#002a35ff",
|
||||
"terminal.ansi.red": "#dc3330ff",
|
||||
"terminal.ansi.bright_red": "#faa091ff",
|
||||
"terminal.ansi.dim_red": "#7d181cff",
|
||||
"terminal.ansi.green": "#849903ff",
|
||||
"terminal.ansi.bright_green": "#c6cb8bff",
|
||||
"terminal.ansi.dim_green": "#434a10ff",
|
||||
"terminal.ansi.yellow": "#b58903ff",
|
||||
"terminal.ansi.bright_yellow": "#e0c189ff",
|
||||
"terminal.ansi.dim_yellow": "#5d430fff",
|
||||
"terminal.ansi.blue": "#288bd1ff",
|
||||
"terminal.ansi.bright_blue": "#a5c3e9ff",
|
||||
"terminal.ansi.dim_blue": "#214365ff",
|
||||
"terminal.ansi.magenta": "#d33781ff",
|
||||
"terminal.ansi.bright_magenta": "#f0a2beff",
|
||||
"terminal.ansi.dim_magenta": "#6f1f3fff",
|
||||
"terminal.ansi.cyan": "#2ba198ff",
|
||||
"terminal.ansi.bright_cyan": "#9fd0cbff",
|
||||
"terminal.ansi.dim_cyan": "#204e4aff",
|
||||
"terminal.ansi.white": "#002a35ff",
|
||||
"terminal.ansi.bright_white": "#002a35ff",
|
||||
"terminal.ansi.dim_white": "#5c7279ff",
|
||||
"link_text.hover": "#288bd1ff",
|
||||
"conflict": "#b58903ff",
|
||||
"conflict.background": "#f5e6d0ff",
|
||||
"conflict.border": "#ebd3aaff",
|
||||
"created": "#849903ff",
|
||||
"created.background": "#e9ead0ff",
|
||||
"created.border": "#d6d9abff",
|
||||
"deleted": "#dc3330ff",
|
||||
"deleted.background": "#ffd9d2ff",
|
||||
"deleted.border": "#ffbbafff",
|
||||
"error": "#dc3330ff",
|
||||
"error.background": "#ffd9d2ff",
|
||||
"error.border": "#ffbbafff",
|
||||
"hidden": "#6a7f86ff",
|
||||
"hidden.background": "#cfd0c4ff",
|
||||
"hidden.border": "#b6bcb5ff",
|
||||
"hint": "#5789a3ff",
|
||||
"hint.background": "#dbe6f6ff",
|
||||
"hint.border": "#bfd3efff",
|
||||
"ignored": "#6a7f86ff",
|
||||
"ignored.background": "#cfd0c4ff",
|
||||
"ignored.border": "#9faaa8ff",
|
||||
"info": "#288bd1ff",
|
||||
"info.background": "#dbe6f6ff",
|
||||
"info.border": "#bfd3efff",
|
||||
"modified": "#b58903ff",
|
||||
"modified.background": "#f5e6d0ff",
|
||||
"modified.border": "#ebd3aaff",
|
||||
"predictive": "#679aafff",
|
||||
"predictive.background": "#e9ead0ff",
|
||||
"predictive.border": "#d6d9abff",
|
||||
"renamed": "#288bd1ff",
|
||||
"renamed.background": "#dbe6f6ff",
|
||||
"renamed.border": "#bfd3efff",
|
||||
"success": "#849903ff",
|
||||
"success.background": "#e9ead0ff",
|
||||
"success.border": "#d6d9abff",
|
||||
"unreachable": "#34555eff",
|
||||
"unreachable.background": "#cfd0c4ff",
|
||||
"unreachable.border": "#9faaa8ff",
|
||||
"warning": "#b58903ff",
|
||||
"warning.background": "#f5e6d0ff",
|
||||
"warning.border": "#ebd3aaff",
|
||||
"players": [
|
||||
{
|
||||
"cursor": "#288bd1ff",
|
||||
"background": "#288bd1ff",
|
||||
"selection": "#288bd13d"
|
||||
},
|
||||
{
|
||||
"cursor": "#d33781ff",
|
||||
"background": "#d33781ff",
|
||||
"selection": "#d337813d"
|
||||
},
|
||||
{
|
||||
"cursor": "#cb4b16ff",
|
||||
"background": "#cb4b16ff",
|
||||
"selection": "#cb4b173d"
|
||||
},
|
||||
{
|
||||
"cursor": "#6c71c3ff",
|
||||
"background": "#6c71c3ff",
|
||||
"selection": "#6c71c33d"
|
||||
},
|
||||
{
|
||||
"cursor": "#2ba198ff",
|
||||
"background": "#2ba198ff",
|
||||
"selection": "#2ba1983d"
|
||||
},
|
||||
{
|
||||
"cursor": "#dc3330ff",
|
||||
"background": "#dc3330ff",
|
||||
"selection": "#dc33303d"
|
||||
},
|
||||
{
|
||||
"cursor": "#b58903ff",
|
||||
"background": "#b58903ff",
|
||||
"selection": "#b589033d"
|
||||
},
|
||||
{
|
||||
"cursor": "#849903ff",
|
||||
"background": "#849903ff",
|
||||
"selection": "#8499033d"
|
||||
}
|
||||
],
|
||||
"syntax": {
|
||||
"attribute": {
|
||||
"color": "#288bd1ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"boolean": {
|
||||
"color": "#849903ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"comment": {
|
||||
"color": "#30525bff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"comment.doc": {
|
||||
"color": "#30525bff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"constant": {
|
||||
"color": "#849903ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"constructor": {
|
||||
"color": "#288bd1ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"embedded": {
|
||||
"color": "#002a35ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"emphasis": {
|
||||
"color": "#288bd1ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"emphasis.strong": {
|
||||
"color": "#288bd1ff",
|
||||
"font_style": null,
|
||||
"font_weight": 700
|
||||
},
|
||||
"enum": {
|
||||
"color": "#cb4b16ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"function": {
|
||||
"color": "#b58903ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"hint": {
|
||||
"color": "#5789a3ff",
|
||||
"font_style": null,
|
||||
"font_weight": 700
|
||||
},
|
||||
"keyword": {
|
||||
"color": "#288bd1ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"label": {
|
||||
"color": "#288bd1ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"link_text": {
|
||||
"color": "#cb4b16ff",
|
||||
"font_style": "italic",
|
||||
"font_weight": null
|
||||
},
|
||||
"link_uri": {
|
||||
"color": "#849903ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"number": {
|
||||
"color": "#849903ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"operator": {
|
||||
"color": "#cb4b16ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"predictive": {
|
||||
"color": "#679aafff",
|
||||
"font_style": "italic",
|
||||
"font_weight": null
|
||||
},
|
||||
"preproc": {
|
||||
"color": "#002a35ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"primary": {
|
||||
"color": "#002a35ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"property": {
|
||||
"color": "#288bd1ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"punctuation": {
|
||||
"color": "#04333eff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"punctuation.bracket": {
|
||||
"color": "#04333eff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"punctuation.delimiter": {
|
||||
"color": "#04333eff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"punctuation.list_marker": {
|
||||
"color": "#04333eff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"punctuation.special": {
|
||||
"color": "#04333eff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"string": {
|
||||
"color": "#cb4b16ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"string.escape": {
|
||||
"color": "#30525bff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"string.regex": {
|
||||
"color": "#cb4b16ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"string.special": {
|
||||
"color": "#cb4b16ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"string.special.symbol": {
|
||||
"color": "#cb4b16ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"tag": {
|
||||
"color": "#288bd1ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"text.literal": {
|
||||
"color": "#cb4b16ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"title": {
|
||||
"color": "#002a35ff",
|
||||
"font_style": null,
|
||||
"font_weight": 700
|
||||
},
|
||||
"type": {
|
||||
"color": "#2ba198ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"variable": {
|
||||
"color": "#002a35ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"variant": {
|
||||
"color": "#288bd1ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
21
assets/themes/summercamp/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2019 Zoe FiriH
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
378
assets/themes/summercamp/summercamp.json
Normal file
@@ -0,0 +1,378 @@
|
||||
{
|
||||
"$schema": "https://zed.dev/schema/themes/v0.2.0.json",
|
||||
"name": "Summercamp",
|
||||
"author": "Zed Industries",
|
||||
"themes": [
|
||||
{
|
||||
"name": "Summercamp",
|
||||
"appearance": "dark",
|
||||
"style": {
|
||||
"border": "#302c21ff",
|
||||
"border.variant": "#29251bff",
|
||||
"border.focused": "#193760ff",
|
||||
"border.selected": "#193760ff",
|
||||
"border.transparent": "#00000000",
|
||||
"border.disabled": "#2e2a1fff",
|
||||
"elevated_surface.background": "#231f16ff",
|
||||
"surface.background": "#231f16ff",
|
||||
"background": "#2a261cff",
|
||||
"element.background": "#231f16ff",
|
||||
"element.hover": "#29251bff",
|
||||
"element.active": "#2f2b20ff",
|
||||
"element.selected": "#2f2b20ff",
|
||||
"element.disabled": "#231f16ff",
|
||||
"drop_target.background": "#736e5580",
|
||||
"ghost_element.background": "#00000000",
|
||||
"ghost_element.hover": "#29251bff",
|
||||
"ghost_element.active": "#2f2b20ff",
|
||||
"ghost_element.selected": "#2f2b20ff",
|
||||
"ghost_element.disabled": "#231f16ff",
|
||||
"text": "#f8f5deff",
|
||||
"text.muted": "#736e55ff",
|
||||
"text.placeholder": "#4c4735ff",
|
||||
"text.disabled": "#4c4735ff",
|
||||
"text.accent": "#499befff",
|
||||
"icon": "#f8f5deff",
|
||||
"icon.muted": "#736e55ff",
|
||||
"icon.disabled": "#4c4735ff",
|
||||
"icon.placeholder": "#736e55ff",
|
||||
"icon.accent": "#499befff",
|
||||
"status_bar.background": "#2a261cff",
|
||||
"title_bar.background": "#2a261cff",
|
||||
"title_bar.inactive_background": "#231f16ff",
|
||||
"toolbar.background": "#1b1810ff",
|
||||
"tab_bar.background": "#231f16ff",
|
||||
"tab.inactive_background": "#231f16ff",
|
||||
"tab.active_background": "#1b1810ff",
|
||||
"search.match_background": "#499bef66",
|
||||
"panel.background": "#231f16ff",
|
||||
"panel.focused_border": "#499befff",
|
||||
"pane.focused_border": null,
|
||||
"scrollbar.thumb.background": "#f8f5de4c",
|
||||
"scrollbar.thumb.hover_background": "#29251bff",
|
||||
"scrollbar.thumb.border": "#29251bff",
|
||||
"scrollbar.track.background": "#00000000",
|
||||
"scrollbar.track.border": "#221e15ff",
|
||||
"editor.foreground": "#f8f5deff",
|
||||
"editor.background": "#1b1810ff",
|
||||
"editor.gutter.background": "#1b1810ff",
|
||||
"editor.subheader.background": "#231f16ff",
|
||||
"editor.active_line.background": "#231f16bf",
|
||||
"editor.highlighted_line.background": "#231f16ff",
|
||||
"editor.line_number": "#676559",
|
||||
"editor.active_line_number": "#e3e2de",
|
||||
"editor.hover_line_number": "#b8b6ad",
|
||||
"editor.invisible": "#494433ff",
|
||||
"editor.wrap_guide": "#f8f5de0d",
|
||||
"editor.active_wrap_guide": "#f8f5de1a",
|
||||
"editor.document_highlight.read_background": "#499bef1a",
|
||||
"editor.document_highlight.write_background": "#49443366",
|
||||
"terminal.background": "#1b1810ff",
|
||||
"terminal.foreground": "#f8f5deff",
|
||||
"terminal.bright_foreground": "#f8f5deff",
|
||||
"terminal.dim_foreground": "#1b1810ff",
|
||||
"terminal.ansi.black": "#1b1810ff",
|
||||
"terminal.ansi.bright_black": "#3a3527ff",
|
||||
"terminal.ansi.dim_black": "#f8f5deff",
|
||||
"terminal.ansi.red": "#e35041ff",
|
||||
"terminal.ansi.bright_red": "#7f2724ff",
|
||||
"terminal.ansi.dim_red": "#faaa9bff",
|
||||
"terminal.ansi.green": "#5dea5aff",
|
||||
"terminal.ansi.bright_green": "#28842cff",
|
||||
"terminal.ansi.dim_green": "#b9f7aeff",
|
||||
"terminal.ansi.yellow": "#f1fe28ff",
|
||||
"terminal.ansi.bright_yellow": "#8c9a0fff",
|
||||
"terminal.ansi.dim_yellow": "#ffffa2ff",
|
||||
"terminal.ansi.blue": "#499befff",
|
||||
"terminal.ansi.bright_blue": "#234b7fff",
|
||||
"terminal.ansi.dim_blue": "#b1ccf8ff",
|
||||
"terminal.ansi.magenta": "#f59be6ff",
|
||||
"terminal.ansi.bright_magenta": "#88487eff",
|
||||
"terminal.ansi.dim_magenta": "#fccef3ff",
|
||||
"terminal.ansi.cyan": "#5aeabbff",
|
||||
"terminal.ansi.bright_cyan": "#288461ff",
|
||||
"terminal.ansi.dim_cyan": "#b7f6ddff",
|
||||
"terminal.ansi.white": "#f8f5deff",
|
||||
"terminal.ansi.bright_white": "#f8f5deff",
|
||||
"terminal.ansi.dim_white": "#57533fff",
|
||||
"link_text.hover": "#499befff",
|
||||
"conflict": "#f1fe28ff",
|
||||
"conflict.background": "#546205ff",
|
||||
"conflict.border": "#717f0aff",
|
||||
"created": "#5dea5aff",
|
||||
"created.background": "#094d12ff",
|
||||
"created.border": "#1a6a20ff",
|
||||
"deleted": "#e35041ff",
|
||||
"deleted.background": "#490f12ff",
|
||||
"deleted.border": "#651c1cff",
|
||||
"error": "#e35041ff",
|
||||
"error.background": "#490f12ff",
|
||||
"error.border": "#651c1cff",
|
||||
"hidden": "#4c4735ff",
|
||||
"hidden.background": "#2a261cff",
|
||||
"hidden.border": "#2e2a1fff",
|
||||
"hint": "#246e61ff",
|
||||
"hint.background": "#0e2242ff",
|
||||
"hint.border": "#193760ff",
|
||||
"ignored": "#4c4735ff",
|
||||
"ignored.background": "#2a261cff",
|
||||
"ignored.border": "#302c21ff",
|
||||
"info": "#499befff",
|
||||
"info.background": "#0e2242ff",
|
||||
"info.border": "#193760ff",
|
||||
"modified": "#f1fe28ff",
|
||||
"modified.background": "#546205ff",
|
||||
"modified.border": "#717f0aff",
|
||||
"predictive": "#78434aff",
|
||||
"predictive.background": "#094d12ff",
|
||||
"predictive.border": "#1a6a20ff",
|
||||
"renamed": "#499befff",
|
||||
"renamed.background": "#0e2242ff",
|
||||
"renamed.border": "#193760ff",
|
||||
"success": "#5dea5aff",
|
||||
"success.background": "#094d12ff",
|
||||
"success.border": "#1a6a20ff",
|
||||
"unreachable": "#736e55ff",
|
||||
"unreachable.background": "#2a261cff",
|
||||
"unreachable.border": "#302c21ff",
|
||||
"warning": "#f1fe28ff",
|
||||
"warning.background": "#546205ff",
|
||||
"warning.border": "#717f0aff",
|
||||
"players": [
|
||||
{
|
||||
"cursor": "#499befff",
|
||||
"background": "#499befff",
|
||||
"selection": "#499bef3d"
|
||||
},
|
||||
{
|
||||
"cursor": "#f59be6ff",
|
||||
"background": "#f59be6ff",
|
||||
"selection": "#f59be63d"
|
||||
},
|
||||
{
|
||||
"cursor": "#faa11cff",
|
||||
"background": "#faa11cff",
|
||||
"selection": "#faa11c3d"
|
||||
},
|
||||
{
|
||||
"cursor": "#fe8080ff",
|
||||
"background": "#fe8080ff",
|
||||
"selection": "#fe80803d"
|
||||
},
|
||||
{
|
||||
"cursor": "#5aeabbff",
|
||||
"background": "#5aeabbff",
|
||||
"selection": "#5aeabb3d"
|
||||
},
|
||||
{
|
||||
"cursor": "#e35041ff",
|
||||
"background": "#e35041ff",
|
||||
"selection": "#e350413d"
|
||||
},
|
||||
{
|
||||
"cursor": "#f1fe28ff",
|
||||
"background": "#f1fe28ff",
|
||||
"selection": "#f1fe283d"
|
||||
},
|
||||
{
|
||||
"cursor": "#5dea5aff",
|
||||
"background": "#5dea5aff",
|
||||
"selection": "#5dea5a3d"
|
||||
}
|
||||
],
|
||||
"syntax": {
|
||||
"attribute": {
|
||||
"color": "#499befff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"boolean": {
|
||||
"color": "#5dea5aff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"comment": {
|
||||
"color": "#777159ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"comment.doc": {
|
||||
"color": "#777159ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"constant": {
|
||||
"color": "#5dea5aff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"constructor": {
|
||||
"color": "#499befff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"embedded": {
|
||||
"color": "#f8f5deff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"emphasis": {
|
||||
"color": "#499befff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"emphasis.strong": {
|
||||
"color": "#499befff",
|
||||
"font_style": null,
|
||||
"font_weight": 700
|
||||
},
|
||||
"enum": {
|
||||
"color": "#faa11cff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"function": {
|
||||
"color": "#f1fe28ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"hint": {
|
||||
"color": "#246e61ff",
|
||||
"font_style": null,
|
||||
"font_weight": 700
|
||||
},
|
||||
"keyword": {
|
||||
"color": "#499befff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"label": {
|
||||
"color": "#499befff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"link_text": {
|
||||
"color": "#faa11cff",
|
||||
"font_style": "italic",
|
||||
"font_weight": null
|
||||
},
|
||||
"link_uri": {
|
||||
"color": "#5dea5aff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"number": {
|
||||
"color": "#5dea5aff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"operator": {
|
||||
"color": "#faa11cff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"predictive": {
|
||||
"color": "#78434aff",
|
||||
"font_style": "italic",
|
||||
"font_weight": null
|
||||
},
|
||||
"preproc": {
|
||||
"color": "#f8f5deff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"primary": {
|
||||
"color": "#f8f5deff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"property": {
|
||||
"color": "#499befff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"punctuation": {
|
||||
"color": "#bfbb9bff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"punctuation.bracket": {
|
||||
"color": "#bfbb9bff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"punctuation.delimiter": {
|
||||
"color": "#bfbb9bff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"punctuation.list_marker": {
|
||||
"color": "#bfbb9bff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"punctuation.special": {
|
||||
"color": "#bfbb9bff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"string": {
|
||||
"color": "#faa11cff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"string.escape": {
|
||||
"color": "#777159ff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"string.regex": {
|
||||
"color": "#faa11cff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"string.special": {
|
||||
"color": "#faa11cff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"string.special.symbol": {
|
||||
"color": "#faa11cff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"tag": {
|
||||
"color": "#499befff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"text.literal": {
|
||||
"color": "#faa11cff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"title": {
|
||||
"color": "#f8f5deff",
|
||||
"font_style": null,
|
||||
"font_weight": 700
|
||||
},
|
||||
"type": {
|
||||
"color": "#5aeabbff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"variable": {
|
||||
"color": "#f8f5deff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
},
|
||||
"variant": {
|
||||
"color": "#499befff",
|
||||
"font_style": null,
|
||||
"font_weight": null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -3,9 +3,9 @@ use editor::Editor;
|
||||
use extension_host::ExtensionStore;
|
||||
use futures::StreamExt;
|
||||
use gpui::{
|
||||
actions, percentage, Animation, AnimationExt as _, App, Context, CursorStyle, Entity,
|
||||
EventEmitter, InteractiveElement as _, ParentElement as _, Render, SharedString,
|
||||
StatefulInteractiveElement, Styled, Transformation, Window,
|
||||
actions, percentage, Animation, AnimationExt as _, AppContext, CursorStyle, EventEmitter,
|
||||
InteractiveElement as _, Model, ParentElement as _, Render, SharedString,
|
||||
StatefulInteractiveElement, Styled, Transformation, View, ViewContext, VisualContext as _,
|
||||
};
|
||||
use language::{LanguageRegistry, LanguageServerBinaryStatus, LanguageServerId};
|
||||
use lsp::LanguageServerName;
|
||||
@@ -27,8 +27,8 @@ pub enum Event {
|
||||
|
||||
pub struct ActivityIndicator {
|
||||
statuses: Vec<LspStatus>,
|
||||
project: Entity<Project>,
|
||||
auto_updater: Option<Entity<AutoUpdater>>,
|
||||
project: Model<Project>,
|
||||
auto_updater: Option<Model<AutoUpdater>>,
|
||||
context_menu_handle: PopoverMenuHandle<ContextMenu>,
|
||||
}
|
||||
|
||||
@@ -46,24 +46,22 @@ struct PendingWork<'a> {
|
||||
struct Content {
|
||||
icon: Option<gpui::AnyElement>,
|
||||
message: String,
|
||||
on_click:
|
||||
Option<Arc<dyn Fn(&mut ActivityIndicator, &mut Window, &mut Context<ActivityIndicator>)>>,
|
||||
on_click: Option<Arc<dyn Fn(&mut ActivityIndicator, &mut ViewContext<ActivityIndicator>)>>,
|
||||
}
|
||||
|
||||
impl ActivityIndicator {
|
||||
pub fn new(
|
||||
workspace: &mut Workspace,
|
||||
languages: Arc<LanguageRegistry>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Workspace>,
|
||||
) -> Entity<ActivityIndicator> {
|
||||
cx: &mut ViewContext<Workspace>,
|
||||
) -> View<ActivityIndicator> {
|
||||
let project = workspace.project().clone();
|
||||
let auto_updater = AutoUpdater::get(cx);
|
||||
let this = cx.new(|cx| {
|
||||
let this = cx.new_view(|cx: &mut ViewContext<Self>| {
|
||||
let mut status_events = languages.language_server_binary_statuses();
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
while let Some((name, status)) = status_events.next().await {
|
||||
this.update(&mut cx, |this: &mut ActivityIndicator, cx| {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.statuses.retain(|s| s.name != name);
|
||||
this.statuses.push(LspStatus { name, status });
|
||||
cx.notify();
|
||||
@@ -72,7 +70,6 @@ impl ActivityIndicator {
|
||||
anyhow::Ok(())
|
||||
})
|
||||
.detach();
|
||||
|
||||
cx.observe(&project, |_, _, cx| cx.notify()).detach();
|
||||
|
||||
if let Some(auto_updater) = auto_updater.as_ref() {
|
||||
@@ -87,13 +84,13 @@ impl ActivityIndicator {
|
||||
}
|
||||
});
|
||||
|
||||
cx.subscribe_in(&this, window, move |_, _, event, window, cx| match event {
|
||||
cx.subscribe(&this, move |_, _, event, cx| match event {
|
||||
Event::ShowError { lsp_name, error } => {
|
||||
let create_buffer = project.update(cx, |project, cx| project.create_buffer(cx));
|
||||
let project = project.clone();
|
||||
let error = error.clone();
|
||||
let lsp_name = lsp_name.clone();
|
||||
cx.spawn_in(window, |workspace, mut cx| async move {
|
||||
cx.spawn(|workspace, mut cx| async move {
|
||||
let buffer = create_buffer.await?;
|
||||
buffer.update(&mut cx, |buffer, cx| {
|
||||
buffer.edit(
|
||||
@@ -106,14 +103,13 @@ impl ActivityIndicator {
|
||||
);
|
||||
buffer.set_capability(language::Capability::ReadOnly, cx);
|
||||
})?;
|
||||
workspace.update_in(&mut cx, |workspace, window, cx| {
|
||||
workspace.update(&mut cx, |workspace, cx| {
|
||||
workspace.add_item_to_active_pane(
|
||||
Box::new(cx.new(|cx| {
|
||||
Editor::for_buffer(buffer, Some(project.clone()), window, cx)
|
||||
Box::new(cx.new_view(|cx| {
|
||||
Editor::for_buffer(buffer, Some(project.clone()), cx)
|
||||
})),
|
||||
None,
|
||||
true,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
})?;
|
||||
@@ -127,7 +123,7 @@ impl ActivityIndicator {
|
||||
this
|
||||
}
|
||||
|
||||
fn show_error_message(&mut self, _: &ShowErrorMessage, _: &mut Window, cx: &mut Context<Self>) {
|
||||
fn show_error_message(&mut self, _: &ShowErrorMessage, cx: &mut ViewContext<Self>) {
|
||||
self.statuses.retain(|status| {
|
||||
if let LanguageServerBinaryStatus::Failed { error } = &status.status {
|
||||
cx.emit(Event::ShowError {
|
||||
@@ -143,12 +139,7 @@ impl ActivityIndicator {
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn dismiss_error_message(
|
||||
&mut self,
|
||||
_: &DismissErrorMessage,
|
||||
_: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
fn dismiss_error_message(&mut self, _: &DismissErrorMessage, cx: &mut ViewContext<Self>) {
|
||||
if let Some(updater) = &self.auto_updater {
|
||||
updater.update(cx, |updater, cx| {
|
||||
updater.dismiss_error(cx);
|
||||
@@ -159,7 +150,7 @@ impl ActivityIndicator {
|
||||
|
||||
fn pending_language_server_work<'a>(
|
||||
&self,
|
||||
cx: &'a App,
|
||||
cx: &'a AppContext,
|
||||
) -> impl Iterator<Item = PendingWork<'a>> {
|
||||
self.project
|
||||
.read(cx)
|
||||
@@ -187,12 +178,12 @@ impl ActivityIndicator {
|
||||
|
||||
fn pending_environment_errors<'a>(
|
||||
&'a self,
|
||||
cx: &'a App,
|
||||
cx: &'a AppContext,
|
||||
) -> impl Iterator<Item = (&'a WorktreeId, &'a EnvironmentErrorMessage)> {
|
||||
self.project.read(cx).shell_environment_errors(cx)
|
||||
}
|
||||
|
||||
fn content_to_render(&mut self, cx: &mut Context<Self>) -> Option<Content> {
|
||||
fn content_to_render(&mut self, cx: &mut ViewContext<Self>) -> Option<Content> {
|
||||
// Show if any direnv calls failed
|
||||
if let Some((&worktree_id, error)) = self.pending_environment_errors(cx).next() {
|
||||
return Some(Content {
|
||||
@@ -202,11 +193,11 @@ impl ActivityIndicator {
|
||||
.into_any_element(),
|
||||
),
|
||||
message: error.0.clone(),
|
||||
on_click: Some(Arc::new(move |this, window, cx| {
|
||||
on_click: Some(Arc::new(move |this, cx| {
|
||||
this.project.update(cx, |project, cx| {
|
||||
project.remove_environment_error(cx, worktree_id);
|
||||
});
|
||||
window.dispatch_action(Box::new(workspace::OpenLog), cx);
|
||||
cx.dispatch_action(Box::new(workspace::OpenLog));
|
||||
})),
|
||||
});
|
||||
}
|
||||
@@ -289,10 +280,10 @@ impl ActivityIndicator {
|
||||
}
|
||||
)
|
||||
),
|
||||
on_click: Some(Arc::new(move |this, window, cx| {
|
||||
on_click: Some(Arc::new(move |this, cx| {
|
||||
this.statuses
|
||||
.retain(|status| !downloading.contains(&status.name));
|
||||
this.dismiss_error_message(&DismissErrorMessage, window, cx)
|
||||
this.dismiss_error_message(&DismissErrorMessage, cx)
|
||||
})),
|
||||
});
|
||||
}
|
||||
@@ -317,10 +308,10 @@ impl ActivityIndicator {
|
||||
}
|
||||
),
|
||||
),
|
||||
on_click: Some(Arc::new(move |this, window, cx| {
|
||||
on_click: Some(Arc::new(move |this, cx| {
|
||||
this.statuses
|
||||
.retain(|status| !checking_for_update.contains(&status.name));
|
||||
this.dismiss_error_message(&DismissErrorMessage, window, cx)
|
||||
this.dismiss_error_message(&DismissErrorMessage, cx)
|
||||
})),
|
||||
});
|
||||
}
|
||||
@@ -345,8 +336,8 @@ impl ActivityIndicator {
|
||||
acc
|
||||
}),
|
||||
),
|
||||
on_click: Some(Arc::new(|this, window, cx| {
|
||||
this.show_error_message(&Default::default(), window, cx)
|
||||
on_click: Some(Arc::new(|this, cx| {
|
||||
this.show_error_message(&Default::default(), cx)
|
||||
})),
|
||||
});
|
||||
}
|
||||
@@ -360,11 +351,11 @@ impl ActivityIndicator {
|
||||
.into_any_element(),
|
||||
),
|
||||
message: format!("Formatting failed: {}. Click to see logs.", failure),
|
||||
on_click: Some(Arc::new(|indicator, window, cx| {
|
||||
on_click: Some(Arc::new(|indicator, cx| {
|
||||
indicator.project.update(cx, |project, cx| {
|
||||
project.reset_last_formatting_failure(cx);
|
||||
});
|
||||
window.dispatch_action(Box::new(workspace::OpenLog), cx);
|
||||
cx.dispatch_action(Box::new(workspace::OpenLog));
|
||||
})),
|
||||
});
|
||||
}
|
||||
@@ -379,8 +370,8 @@ impl ActivityIndicator {
|
||||
.into_any_element(),
|
||||
),
|
||||
message: "Checking for Zed updates…".to_string(),
|
||||
on_click: Some(Arc::new(|this, window, cx| {
|
||||
this.dismiss_error_message(&DismissErrorMessage, window, cx)
|
||||
on_click: Some(Arc::new(|this, cx| {
|
||||
this.dismiss_error_message(&DismissErrorMessage, cx)
|
||||
})),
|
||||
}),
|
||||
AutoUpdateStatus::Downloading => Some(Content {
|
||||
@@ -390,8 +381,8 @@ impl ActivityIndicator {
|
||||
.into_any_element(),
|
||||
),
|
||||
message: "Downloading Zed update…".to_string(),
|
||||
on_click: Some(Arc::new(|this, window, cx| {
|
||||
this.dismiss_error_message(&DismissErrorMessage, window, cx)
|
||||
on_click: Some(Arc::new(|this, cx| {
|
||||
this.dismiss_error_message(&DismissErrorMessage, cx)
|
||||
})),
|
||||
}),
|
||||
AutoUpdateStatus::Installing => Some(Content {
|
||||
@@ -401,8 +392,8 @@ impl ActivityIndicator {
|
||||
.into_any_element(),
|
||||
),
|
||||
message: "Installing Zed update…".to_string(),
|
||||
on_click: Some(Arc::new(|this, window, cx| {
|
||||
this.dismiss_error_message(&DismissErrorMessage, window, cx)
|
||||
on_click: Some(Arc::new(|this, cx| {
|
||||
this.dismiss_error_message(&DismissErrorMessage, cx)
|
||||
})),
|
||||
}),
|
||||
AutoUpdateStatus::Updated { binary_path } => Some(Content {
|
||||
@@ -412,7 +403,7 @@ impl ActivityIndicator {
|
||||
let reload = workspace::Reload {
|
||||
binary_path: Some(binary_path.clone()),
|
||||
};
|
||||
move |_, _, cx| workspace::reload(&reload, cx)
|
||||
move |_, cx| workspace::reload(&reload, cx)
|
||||
})),
|
||||
}),
|
||||
AutoUpdateStatus::Errored => Some(Content {
|
||||
@@ -422,8 +413,8 @@ impl ActivityIndicator {
|
||||
.into_any_element(),
|
||||
),
|
||||
message: "Auto update failed".to_string(),
|
||||
on_click: Some(Arc::new(|this, window, cx| {
|
||||
this.dismiss_error_message(&DismissErrorMessage, window, cx)
|
||||
on_click: Some(Arc::new(|this, cx| {
|
||||
this.dismiss_error_message(&DismissErrorMessage, cx)
|
||||
})),
|
||||
}),
|
||||
AutoUpdateStatus::Idle => None,
|
||||
@@ -441,8 +432,8 @@ impl ActivityIndicator {
|
||||
.into_any_element(),
|
||||
),
|
||||
message: format!("Updating {extension_id} extension…"),
|
||||
on_click: Some(Arc::new(|this, window, cx| {
|
||||
this.dismiss_error_message(&DismissErrorMessage, window, cx)
|
||||
on_click: Some(Arc::new(|this, cx| {
|
||||
this.dismiss_error_message(&DismissErrorMessage, cx)
|
||||
})),
|
||||
});
|
||||
}
|
||||
@@ -451,12 +442,8 @@ impl ActivityIndicator {
|
||||
None
|
||||
}
|
||||
|
||||
fn toggle_language_server_work_context_menu(
|
||||
&mut self,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
self.context_menu_handle.toggle(window, cx);
|
||||
fn toggle_language_server_work_context_menu(&mut self, cx: &mut ViewContext<Self>) {
|
||||
self.context_menu_handle.toggle(cx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -465,7 +452,7 @@ impl EventEmitter<Event> for ActivityIndicator {}
|
||||
const MAX_MESSAGE_LEN: usize = 50;
|
||||
|
||||
impl Render for ActivityIndicator {
|
||||
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
let result = h_flex()
|
||||
.id("activity-indicator")
|
||||
.on_action(cx.listener(Self::show_error_message))
|
||||
@@ -473,7 +460,7 @@ impl Render for ActivityIndicator {
|
||||
let Some(content) = self.content_to_render(cx) else {
|
||||
return result;
|
||||
};
|
||||
let this = cx.entity().downgrade();
|
||||
let this = cx.view().downgrade();
|
||||
let truncate_content = content.message.len() > MAX_MESSAGE_LEN;
|
||||
result.gap_2().child(
|
||||
PopoverMenu::new("activity-indicator-popover")
|
||||
@@ -493,24 +480,24 @@ impl Render for ActivityIndicator {
|
||||
))
|
||||
.size(LabelSize::Small),
|
||||
)
|
||||
.tooltip(Tooltip::text(content.message))
|
||||
.tooltip(move |cx| Tooltip::text(&content.message, cx))
|
||||
} else {
|
||||
button.child(Label::new(content.message).size(LabelSize::Small))
|
||||
}
|
||||
})
|
||||
.when_some(content.on_click, |this, handler| {
|
||||
this.on_click(cx.listener(move |this, _, window, cx| {
|
||||
handler(this, window, cx);
|
||||
this.on_click(cx.listener(move |this, _, cx| {
|
||||
handler(this, cx);
|
||||
}))
|
||||
.cursor(CursorStyle::PointingHand)
|
||||
}),
|
||||
),
|
||||
)
|
||||
.anchor(gpui::Corner::BottomLeft)
|
||||
.menu(move |window, cx| {
|
||||
.menu(move |cx| {
|
||||
let strong_this = this.upgrade()?;
|
||||
let mut has_work = false;
|
||||
let menu = ContextMenu::build(window, cx, |mut menu, _, cx| {
|
||||
let menu = ContextMenu::build(cx, |mut menu, cx| {
|
||||
for work in strong_this.read(cx).pending_language_server_work(cx) {
|
||||
has_work = true;
|
||||
let this = this.clone();
|
||||
@@ -526,7 +513,7 @@ impl Render for ActivityIndicator {
|
||||
let token = work.progress_token.to_string();
|
||||
let title = SharedString::from(title);
|
||||
menu = menu.custom_entry(
|
||||
move |_, _| {
|
||||
move |_| {
|
||||
h_flex()
|
||||
.w_full()
|
||||
.justify_between()
|
||||
@@ -534,7 +521,7 @@ impl Render for ActivityIndicator {
|
||||
.child(Icon::new(IconName::XCircle))
|
||||
.into_any_element()
|
||||
},
|
||||
move |_, cx| {
|
||||
move |cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.project.update(cx, |project, cx| {
|
||||
project.cancel_language_server_work(
|
||||
@@ -567,11 +554,5 @@ impl Render for ActivityIndicator {
|
||||
}
|
||||
|
||||
impl StatusItemView for ActivityIndicator {
|
||||
fn set_active_pane_item(
|
||||
&mut self,
|
||||
_: Option<&dyn ItemHandle>,
|
||||
_window: &mut Window,
|
||||
_: &mut Context<Self>,
|
||||
) {
|
||||
}
|
||||
fn set_active_pane_item(&mut self, _: Option<&dyn ItemHandle>, _: &mut ViewContext<Self>) {}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ name = "anthropic"
|
||||
version = "0.1.0"
|
||||
edition.workspace = true
|
||||
publish.workspace = true
|
||||
license = "GPL-3.0-or-later"
|
||||
license = "AGPL-3.0-or-later"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
1
crates/anthropic/LICENSE-AGPL
Symbolic link
@@ -0,0 +1 @@
|
||||
../../LICENSE-AGPL
|
||||
@@ -2,7 +2,7 @@ mod supported_countries;
|
||||
|
||||
use std::{pin::Pin, str::FromStr};
|
||||
|
||||
use anyhow::{anyhow, Context as _, Result};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use chrono::{DateTime, Utc};
|
||||
use futures::{io::BufReader, stream::BoxStream, AsyncBufReadExt, AsyncReadExt, Stream, StreamExt};
|
||||
use http_client::http::{HeaderMap, HeaderValue};
|
||||
@@ -30,8 +30,6 @@ pub enum Model {
|
||||
#[default]
|
||||
#[serde(rename = "claude-3-5-sonnet", alias = "claude-3-5-sonnet-latest")]
|
||||
Claude3_5Sonnet,
|
||||
#[serde(rename = "claude-3-7-sonnet", alias = "claude-3-7-sonnet-latest")]
|
||||
Claude3_7Sonnet,
|
||||
#[serde(rename = "claude-3-5-haiku", alias = "claude-3-5-haiku-latest")]
|
||||
Claude3_5Haiku,
|
||||
#[serde(rename = "claude-3-opus", alias = "claude-3-opus-latest")]
|
||||
@@ -61,8 +59,6 @@ impl Model {
|
||||
pub fn from_id(id: &str) -> Result<Self> {
|
||||
if id.starts_with("claude-3-5-sonnet") {
|
||||
Ok(Self::Claude3_5Sonnet)
|
||||
} else if id.starts_with("claude-3-7-sonnet") {
|
||||
Ok(Self::Claude3_7Sonnet)
|
||||
} else if id.starts_with("claude-3-5-haiku") {
|
||||
Ok(Self::Claude3_5Haiku)
|
||||
} else if id.starts_with("claude-3-opus") {
|
||||
@@ -79,7 +75,6 @@ impl Model {
|
||||
pub fn id(&self) -> &str {
|
||||
match self {
|
||||
Model::Claude3_5Sonnet => "claude-3-5-sonnet-latest",
|
||||
Model::Claude3_7Sonnet => "claude-3-7-sonnet-latest",
|
||||
Model::Claude3_5Haiku => "claude-3-5-haiku-latest",
|
||||
Model::Claude3Opus => "claude-3-opus-latest",
|
||||
Model::Claude3Sonnet => "claude-3-sonnet-20240229",
|
||||
@@ -90,7 +85,6 @@ impl Model {
|
||||
|
||||
pub fn display_name(&self) -> &str {
|
||||
match self {
|
||||
Self::Claude3_7Sonnet => "Claude 3.7 Sonnet",
|
||||
Self::Claude3_5Sonnet => "Claude 3.5 Sonnet",
|
||||
Self::Claude3_5Haiku => "Claude 3.5 Haiku",
|
||||
Self::Claude3Opus => "Claude 3 Opus",
|
||||
@@ -104,14 +98,13 @@ impl Model {
|
||||
|
||||
pub fn cache_configuration(&self) -> Option<AnthropicModelCacheConfiguration> {
|
||||
match self {
|
||||
Self::Claude3_5Sonnet
|
||||
| Self::Claude3_5Haiku
|
||||
| Self::Claude3_7Sonnet
|
||||
| Self::Claude3Haiku => Some(AnthropicModelCacheConfiguration {
|
||||
min_total_token: 2_048,
|
||||
should_speculate: true,
|
||||
max_cache_anchors: 4,
|
||||
}),
|
||||
Self::Claude3_5Sonnet | Self::Claude3_5Haiku | Self::Claude3Haiku => {
|
||||
Some(AnthropicModelCacheConfiguration {
|
||||
min_total_token: 2_048,
|
||||
should_speculate: true,
|
||||
max_cache_anchors: 4,
|
||||
})
|
||||
}
|
||||
Self::Custom {
|
||||
cache_configuration,
|
||||
..
|
||||
@@ -124,7 +117,6 @@ impl Model {
|
||||
match self {
|
||||
Self::Claude3_5Sonnet
|
||||
| Self::Claude3_5Haiku
|
||||
| Self::Claude3_7Sonnet
|
||||
| Self::Claude3Opus
|
||||
| Self::Claude3Sonnet
|
||||
| Self::Claude3Haiku => 200_000,
|
||||
@@ -135,7 +127,7 @@ impl Model {
|
||||
pub fn max_output_tokens(&self) -> u32 {
|
||||
match self {
|
||||
Self::Claude3Opus | Self::Claude3Sonnet | Self::Claude3Haiku => 4_096,
|
||||
Self::Claude3_5Sonnet | Self::Claude3_7Sonnet | Self::Claude3_5Haiku => 8_192,
|
||||
Self::Claude3_5Sonnet | Self::Claude3_5Haiku => 8_192,
|
||||
Self::Custom {
|
||||
max_output_tokens, ..
|
||||
} => max_output_tokens.unwrap_or(4_096),
|
||||
@@ -145,7 +137,6 @@ impl Model {
|
||||
pub fn default_temperature(&self) -> f32 {
|
||||
match self {
|
||||
Self::Claude3_5Sonnet
|
||||
| Self::Claude3_7Sonnet
|
||||
| Self::Claude3_5Haiku
|
||||
| Self::Claude3Opus
|
||||
| Self::Claude3Sonnet
|
||||
@@ -157,13 +148,8 @@ impl Model {
|
||||
}
|
||||
}
|
||||
|
||||
pub const DEFAULT_BETA_HEADERS: &[&str] = &["prompt-caching-2024-07-31"];
|
||||
|
||||
pub fn beta_headers(&self) -> String {
|
||||
let mut headers = Self::DEFAULT_BETA_HEADERS
|
||||
.into_iter()
|
||||
.map(|header| header.to_string())
|
||||
.collect::<Vec<_>>();
|
||||
let mut headers = vec!["prompt-caching-2024-07-31".to_string()];
|
||||
|
||||
if let Self::Custom {
|
||||
extra_beta_headers, ..
|
||||
@@ -200,14 +186,12 @@ pub async fn complete(
|
||||
request: Request,
|
||||
) -> Result<Response, AnthropicError> {
|
||||
let uri = format!("{api_url}/v1/messages");
|
||||
let beta_headers = Model::from_id(&request.model)
|
||||
.map(|model| model.beta_headers())
|
||||
.unwrap_or_else(|_err| Model::DEFAULT_BETA_HEADERS.join(","));
|
||||
let model = Model::from_id(&request.model)?;
|
||||
let request_builder = HttpRequest::builder()
|
||||
.method(Method::POST)
|
||||
.uri(uri)
|
||||
.header("Anthropic-Version", "2023-06-01")
|
||||
.header("Anthropic-Beta", beta_headers)
|
||||
.header("Anthropic-Beta", model.beta_headers())
|
||||
.header("X-Api-Key", api_key)
|
||||
.header("Content-Type", "application/json");
|
||||
|
||||
@@ -259,7 +243,7 @@ pub async fn stream_completion(
|
||||
.map(|output| output.0)
|
||||
}
|
||||
|
||||
/// <https://docs.anthropic.com/en/api/rate-limits#response-headers>
|
||||
/// https://docs.anthropic.com/en/api/rate-limits#response-headers
|
||||
#[derive(Debug)]
|
||||
pub struct RateLimitInfo {
|
||||
pub requests_limit: usize,
|
||||
@@ -318,14 +302,12 @@ pub async fn stream_completion_with_rate_limit_info(
|
||||
stream: true,
|
||||
};
|
||||
let uri = format!("{api_url}/v1/messages");
|
||||
let beta_headers = Model::from_id(&request.base.model)
|
||||
.map(|model| model.beta_headers())
|
||||
.unwrap_or_else(|_err| Model::DEFAULT_BETA_HEADERS.join(","));
|
||||
let model = Model::from_id(&request.base.model)?;
|
||||
let request_builder = HttpRequest::builder()
|
||||
.method(Method::POST)
|
||||
.uri(uri)
|
||||
.header("Anthropic-Version", "2023-06-01")
|
||||
.header("Anthropic-Beta", beta_headers)
|
||||
.header("Anthropic-Beta", model.beta_headers())
|
||||
.header("X-Api-Key", api_key)
|
||||
.header("Content-Type", "application/json");
|
||||
let serialized_request =
|
||||
@@ -635,7 +617,7 @@ pub struct ApiError {
|
||||
}
|
||||
|
||||
/// An Anthropic API error code.
|
||||
/// <https://docs.anthropic.com/en/api/errors#http-errors>
|
||||
/// https://docs.anthropic.com/en/api/errors#http-errors
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, EnumString)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum ApiErrorCode {
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::sync::LazyLock;
|
||||
|
||||
/// Returns whether the given country code is supported by Anthropic.
|
||||
///
|
||||
/// <https://www.anthropic.com/supported-countries>
|
||||
/// https://www.anthropic.com/supported-countries
|
||||
pub fn is_supported_country(country_code: &str) -> bool {
|
||||
SUPPORTED_COUNTRIES.contains(&country_code)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This crate was essentially pulled out verbatim from main `zed` crate to avoid having to run RustEmbed macro whenever zed has to be rebuilt. It saves a second or two on an incremental build.
|
||||
use anyhow::anyhow;
|
||||
|
||||
use gpui::{App, AssetSource, Result, SharedString};
|
||||
use gpui::{AppContext, AssetSource, Result, SharedString};
|
||||
use rust_embed::RustEmbed;
|
||||
|
||||
#[derive(RustEmbed)]
|
||||
@@ -39,7 +39,7 @@ impl AssetSource for Assets {
|
||||
|
||||
impl Assets {
|
||||
/// Populate the [`TextSystem`] of the given [`AppContext`] with all `.ttf` fonts in the `fonts` directory.
|
||||
pub fn load_fonts(&self, cx: &App) -> gpui::Result<()> {
|
||||
pub fn load_fonts(&self, cx: &AppContext) -> gpui::Result<()> {
|
||||
let font_paths = self.list("fonts")?;
|
||||
let mut embedded_fonts = Vec::new();
|
||||
for font_path in font_paths {
|
||||
@@ -55,7 +55,7 @@ impl Assets {
|
||||
cx.text_system().add_fonts(embedded_fonts)
|
||||
}
|
||||
|
||||
pub fn load_test_fonts(&self, cx: &App) {
|
||||
pub fn load_test_fonts(&self, cx: &AppContext) {
|
||||
cx.text_system()
|
||||
.add_fonts(vec![self
|
||||
.load("fonts/plex-mono/ZedPlexMono-Regular.ttf")
|
||||
|
||||
@@ -43,6 +43,7 @@ indoc.workspace = true
|
||||
language.workspace = true
|
||||
language_model.workspace = true
|
||||
language_model_selector.workspace = true
|
||||
language_models.workspace = true
|
||||
log.workspace = true
|
||||
lsp.workspace = true
|
||||
menu.workspace = true
|
||||
@@ -58,6 +59,7 @@ search.workspace = true
|
||||
semantic_index.workspace = true
|
||||
serde.workspace = true
|
||||
settings.workspace = true
|
||||
similar.workspace = true
|
||||
smol.workspace = true
|
||||
streaming_diff.workspace = true
|
||||
telemetry.workspace = true
|
||||
|
||||
@@ -15,7 +15,7 @@ use client::Client;
|
||||
use command_palette_hooks::CommandPaletteFilter;
|
||||
use feature_flags::FeatureFlagAppExt;
|
||||
use fs::Fs;
|
||||
use gpui::{actions, App, Global, UpdateGlobal};
|
||||
use gpui::{actions, AppContext, Global, UpdateGlobal};
|
||||
use language_model::{
|
||||
LanguageModelId, LanguageModelProviderId, LanguageModelRegistry, LanguageModelResponseMessage,
|
||||
};
|
||||
@@ -33,7 +33,7 @@ actions!(
|
||||
[
|
||||
InsertActivePrompt,
|
||||
DeployHistory,
|
||||
NewChat,
|
||||
NewContext,
|
||||
CycleNextInlineAssist,
|
||||
CyclePreviousInlineAssist
|
||||
]
|
||||
@@ -67,7 +67,7 @@ impl Global for Assistant {}
|
||||
impl Assistant {
|
||||
const NAMESPACE: &'static str = "assistant";
|
||||
|
||||
fn set_enabled(&mut self, enabled: bool, cx: &mut App) {
|
||||
fn set_enabled(&mut self, enabled: bool, cx: &mut AppContext) {
|
||||
if self.enabled == enabled {
|
||||
return;
|
||||
}
|
||||
@@ -92,7 +92,7 @@ pub fn init(
|
||||
fs: Arc<dyn Fs>,
|
||||
client: Arc<Client>,
|
||||
prompt_builder: Arc<PromptBuilder>,
|
||||
cx: &mut App,
|
||||
cx: &mut AppContext,
|
||||
) {
|
||||
cx.set_global(Assistant::default());
|
||||
AssistantSettings::register(cx);
|
||||
@@ -165,7 +165,7 @@ pub fn init(
|
||||
.detach();
|
||||
}
|
||||
|
||||
fn init_language_model_settings(cx: &mut App) {
|
||||
fn init_language_model_settings(cx: &mut AppContext) {
|
||||
update_active_language_model_from_settings(cx);
|
||||
|
||||
cx.observe_global::<SettingsStore>(update_active_language_model_from_settings)
|
||||
@@ -184,7 +184,7 @@ fn init_language_model_settings(cx: &mut App) {
|
||||
.detach();
|
||||
}
|
||||
|
||||
fn update_active_language_model_from_settings(cx: &mut App) {
|
||||
fn update_active_language_model_from_settings(cx: &mut AppContext) {
|
||||
let settings = AssistantSettings::get_global(cx);
|
||||
let provider_name = LanguageModelProviderId::from(settings.default_model.provider.clone());
|
||||
let model_id = LanguageModelId::from(settings.default_model.model.clone());
|
||||
@@ -204,7 +204,7 @@ fn update_active_language_model_from_settings(cx: &mut App) {
|
||||
});
|
||||
}
|
||||
|
||||
fn register_slash_commands(prompt_builder: Option<Arc<PromptBuilder>>, cx: &mut App) {
|
||||
fn register_slash_commands(prompt_builder: Option<Arc<PromptBuilder>>, cx: &mut AppContext) {
|
||||
let slash_command_registry = SlashCommandRegistry::global(cx);
|
||||
|
||||
slash_command_registry.register_command(assistant_slash_commands::FileSlashCommand, true);
|
||||
@@ -278,7 +278,7 @@ fn register_slash_commands(prompt_builder: Option<Arc<PromptBuilder>>, cx: &mut
|
||||
.detach();
|
||||
}
|
||||
|
||||
fn update_slash_commands_from_settings(cx: &mut App) {
|
||||
fn update_slash_commands_from_settings(cx: &mut AppContext) {
|
||||
let slash_command_registry = SlashCommandRegistry::global(cx);
|
||||
let settings = SlashCommandSettings::get_global(cx);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use collections::HashMap;
|
||||
use gpui::{canvas, AnyView, App, EventEmitter, FocusHandle, Focusable, Subscription};
|
||||
use gpui::{canvas, AnyView, AppContext, EventEmitter, FocusHandle, FocusableView, Subscription};
|
||||
use language_model::{LanguageModelProvider, LanguageModelProviderId, LanguageModelRegistry};
|
||||
use ui::{prelude::*, ElevationIndex};
|
||||
use workspace::Item;
|
||||
@@ -13,17 +13,16 @@ pub struct ConfigurationView {
|
||||
}
|
||||
|
||||
impl ConfigurationView {
|
||||
pub fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
|
||||
pub fn new(cx: &mut ViewContext<Self>) -> Self {
|
||||
let focus_handle = cx.focus_handle();
|
||||
|
||||
let registry_subscription = cx.subscribe_in(
|
||||
let registry_subscription = cx.subscribe(
|
||||
&LanguageModelRegistry::global(cx),
|
||||
window,
|
||||
|this, _, event: &language_model::Event, window, cx| match event {
|
||||
|this, _, event: &language_model::Event, cx| match event {
|
||||
language_model::Event::AddedProvider(provider_id) => {
|
||||
let provider = LanguageModelRegistry::read_global(cx).provider(provider_id);
|
||||
if let Some(provider) = provider {
|
||||
this.add_configuration_view(&provider, window, cx);
|
||||
this.add_configuration_view(&provider, cx);
|
||||
}
|
||||
}
|
||||
language_model::Event::RemovedProvider(provider_id) => {
|
||||
@@ -38,14 +37,14 @@ impl ConfigurationView {
|
||||
configuration_views: HashMap::default(),
|
||||
_registry_subscription: registry_subscription,
|
||||
};
|
||||
this.build_configuration_views(window, cx);
|
||||
this.build_configuration_views(cx);
|
||||
this
|
||||
}
|
||||
|
||||
fn build_configuration_views(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
fn build_configuration_views(&mut self, cx: &mut ViewContext<Self>) {
|
||||
let providers = LanguageModelRegistry::read_global(cx).providers();
|
||||
for provider in providers {
|
||||
self.add_configuration_view(&provider, window, cx);
|
||||
self.add_configuration_view(&provider, cx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,10 +55,9 @@ impl ConfigurationView {
|
||||
fn add_configuration_view(
|
||||
&mut self,
|
||||
provider: &Arc<dyn LanguageModelProvider>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
let configuration_view = provider.configuration_view(window, cx);
|
||||
let configuration_view = provider.configuration_view(cx);
|
||||
self.configuration_views
|
||||
.insert(provider.id(), configuration_view);
|
||||
}
|
||||
@@ -67,7 +65,7 @@ impl ConfigurationView {
|
||||
fn render_provider_view(
|
||||
&mut self,
|
||||
provider: &Arc<dyn LanguageModelProvider>,
|
||||
cx: &mut Context<Self>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Div {
|
||||
let provider_id = provider.id().0.clone();
|
||||
let provider_name = provider.name().0.clone();
|
||||
@@ -75,7 +73,7 @@ impl ConfigurationView {
|
||||
|
||||
let open_new_context = cx.listener({
|
||||
let provider = provider.clone();
|
||||
move |_, _, _window, cx| {
|
||||
move |_, _, cx| {
|
||||
cx.emit(ConfigurationViewEvent::NewProviderContextEditor(
|
||||
provider.clone(),
|
||||
))
|
||||
@@ -125,7 +123,7 @@ impl ConfigurationView {
|
||||
}
|
||||
|
||||
impl Render for ConfigurationView {
|
||||
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
let providers = LanguageModelRegistry::read_global(cx).providers();
|
||||
let provider_views = providers
|
||||
.into_iter()
|
||||
@@ -165,12 +163,12 @@ impl Render for ConfigurationView {
|
||||
// We use a canvas here to get scrolling to work in the ConfigurationView. It's a workaround
|
||||
// because we couldn't the element to take up the size of the parent.
|
||||
canvas(
|
||||
move |bounds, window, cx| {
|
||||
element.prepaint_as_root(bounds.origin, bounds.size.into(), window, cx);
|
||||
move |bounds, cx| {
|
||||
element.prepaint_as_root(bounds.origin, bounds.size.into(), cx);
|
||||
element
|
||||
},
|
||||
|_, mut element, window, cx| {
|
||||
element.paint(window, cx);
|
||||
|_, mut element, cx| {
|
||||
element.paint(cx);
|
||||
},
|
||||
)
|
||||
.flex_1()
|
||||
@@ -184,8 +182,8 @@ pub enum ConfigurationViewEvent {
|
||||
|
||||
impl EventEmitter<ConfigurationViewEvent> for ConfigurationView {}
|
||||
|
||||
impl Focusable for ConfigurationView {
|
||||
fn focus_handle(&self, _: &App) -> FocusHandle {
|
||||
impl FocusableView for ConfigurationView {
|
||||
fn focus_handle(&self, _: &AppContext) -> FocusHandle {
|
||||
self.focus_handle.clone()
|
||||
}
|
||||
}
|
||||
@@ -193,7 +191,7 @@ impl Focusable for ConfigurationView {
|
||||
impl Item for ConfigurationView {
|
||||
type Event = ConfigurationViewEvent;
|
||||
|
||||
fn tab_content_text(&self, _window: &Window, _cx: &App) -> Option<SharedString> {
|
||||
fn tab_content_text(&self, _cx: &WindowContext) -> Option<SharedString> {
|
||||
Some("Configuration".into())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use gpui::App;
|
||||
use gpui::AppContext;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use settings::{Settings, SettingsSources};
|
||||
@@ -36,7 +36,7 @@ impl Settings for SlashCommandSettings {
|
||||
|
||||
type FileContent = Self;
|
||||
|
||||
fn load(sources: SettingsSources<Self::FileContent>, _cx: &mut App) -> Result<Self> {
|
||||
fn load(sources: SettingsSources<Self::FileContent>, _cx: &mut AppContext) -> Result<Self> {
|
||||
SettingsSources::<Self::FileContent>::json_merge_with(
|
||||
[sources.default]
|
||||
.into_iter()
|
||||
|
||||
@@ -11,15 +11,15 @@ use editor::{
|
||||
use fs::Fs;
|
||||
use futures::{channel::mpsc, SinkExt, StreamExt};
|
||||
use gpui::{
|
||||
App, Context, Entity, EventEmitter, FocusHandle, Focusable, Global, Subscription, Task,
|
||||
TextStyle, UpdateGlobal, WeakEntity,
|
||||
AppContext, Context, EventEmitter, FocusHandle, FocusableView, Global, Model, ModelContext,
|
||||
Subscription, Task, TextStyle, UpdateGlobal, View, WeakView,
|
||||
};
|
||||
use language::Buffer;
|
||||
use language_model::{
|
||||
report_assistant_event, LanguageModelRegistry, LanguageModelRequest,
|
||||
LanguageModelRequestMessage, Role,
|
||||
LanguageModelRegistry, LanguageModelRequest, LanguageModelRequestMessage, Role,
|
||||
};
|
||||
use language_model_selector::{LanguageModelSelector, LanguageModelSelectorPopoverMenu};
|
||||
use language_models::report_assistant_event;
|
||||
use prompt_library::PromptBuilder;
|
||||
use settings::{update_settings_file, Settings};
|
||||
use std::{
|
||||
@@ -39,7 +39,7 @@ pub fn init(
|
||||
fs: Arc<dyn Fs>,
|
||||
prompt_builder: Arc<PromptBuilder>,
|
||||
telemetry: Arc<Telemetry>,
|
||||
cx: &mut App,
|
||||
cx: &mut AppContext,
|
||||
) {
|
||||
cx.set_global(TerminalInlineAssistant::new(fs, prompt_builder, telemetry));
|
||||
}
|
||||
@@ -86,20 +86,20 @@ impl TerminalInlineAssistant {
|
||||
|
||||
pub fn assist(
|
||||
&mut self,
|
||||
terminal_view: &Entity<TerminalView>,
|
||||
workspace: Option<WeakEntity<Workspace>>,
|
||||
assistant_panel: Option<&Entity<AssistantPanel>>,
|
||||
terminal_view: &View<TerminalView>,
|
||||
workspace: Option<WeakView<Workspace>>,
|
||||
assistant_panel: Option<&View<AssistantPanel>>,
|
||||
initial_prompt: Option<String>,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
cx: &mut WindowContext,
|
||||
) {
|
||||
let terminal = terminal_view.read(cx).terminal().clone();
|
||||
let assist_id = self.next_assist_id.post_inc();
|
||||
let prompt_buffer = cx.new(|cx| Buffer::local(initial_prompt.unwrap_or_default(), cx));
|
||||
let prompt_buffer = cx.new(|cx| MultiBuffer::singleton(prompt_buffer, cx));
|
||||
let codegen = cx.new(|_| Codegen::new(terminal, self.telemetry.clone()));
|
||||
let prompt_buffer =
|
||||
cx.new_model(|cx| Buffer::local(initial_prompt.unwrap_or_default(), cx));
|
||||
let prompt_buffer = cx.new_model(|cx| MultiBuffer::singleton(prompt_buffer, cx));
|
||||
let codegen = cx.new_model(|_| Codegen::new(terminal, self.telemetry.clone()));
|
||||
|
||||
let prompt_editor = cx.new(|cx| {
|
||||
let prompt_editor = cx.new_view(|cx| {
|
||||
PromptEditor::new(
|
||||
assist_id,
|
||||
self.prompt_history.clone(),
|
||||
@@ -108,7 +108,6 @@ impl TerminalInlineAssistant {
|
||||
assistant_panel,
|
||||
workspace.clone(),
|
||||
self.fs.clone(),
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
});
|
||||
@@ -118,7 +117,7 @@ impl TerminalInlineAssistant {
|
||||
render: Box::new(move |_| prompt_editor_render.clone().into_any_element()),
|
||||
};
|
||||
terminal_view.update(cx, |terminal_view, cx| {
|
||||
terminal_view.set_block_below_cursor(block, window, cx);
|
||||
terminal_view.set_block_below_cursor(block, cx);
|
||||
});
|
||||
|
||||
let terminal_assistant = TerminalInlineAssist::new(
|
||||
@@ -127,27 +126,21 @@ impl TerminalInlineAssistant {
|
||||
assistant_panel.is_some(),
|
||||
prompt_editor,
|
||||
workspace.clone(),
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
|
||||
self.assists.insert(assist_id, terminal_assistant);
|
||||
|
||||
self.focus_assist(assist_id, window, cx);
|
||||
self.focus_assist(assist_id, cx);
|
||||
}
|
||||
|
||||
fn focus_assist(
|
||||
&mut self,
|
||||
assist_id: TerminalInlineAssistId,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) {
|
||||
fn focus_assist(&mut self, assist_id: TerminalInlineAssistId, cx: &mut WindowContext) {
|
||||
let assist = &self.assists[&assist_id];
|
||||
if let Some(prompt_editor) = assist.prompt_editor.as_ref() {
|
||||
prompt_editor.update(cx, |this, cx| {
|
||||
this.editor.update(cx, |editor, cx| {
|
||||
window.focus(&editor.focus_handle(cx));
|
||||
editor.select_all(&SelectAll, window, cx);
|
||||
editor.focus(cx);
|
||||
editor.select_all(&SelectAll, cx);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -155,10 +148,9 @@ impl TerminalInlineAssistant {
|
||||
|
||||
fn handle_prompt_editor_event(
|
||||
&mut self,
|
||||
prompt_editor: Entity<PromptEditor>,
|
||||
prompt_editor: View<PromptEditor>,
|
||||
event: &PromptEditorEvent,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
cx: &mut WindowContext,
|
||||
) {
|
||||
let assist_id = prompt_editor.read(cx).id;
|
||||
match event {
|
||||
@@ -169,21 +161,21 @@ impl TerminalInlineAssistant {
|
||||
self.stop_assist(assist_id, cx);
|
||||
}
|
||||
PromptEditorEvent::ConfirmRequested { execute } => {
|
||||
self.finish_assist(assist_id, false, *execute, window, cx);
|
||||
self.finish_assist(assist_id, false, *execute, cx);
|
||||
}
|
||||
PromptEditorEvent::CancelRequested => {
|
||||
self.finish_assist(assist_id, true, false, window, cx);
|
||||
self.finish_assist(assist_id, true, false, cx);
|
||||
}
|
||||
PromptEditorEvent::DismissRequested => {
|
||||
self.dismiss_assist(assist_id, window, cx);
|
||||
self.dismiss_assist(assist_id, cx);
|
||||
}
|
||||
PromptEditorEvent::Resized { height_in_lines } => {
|
||||
self.insert_prompt_editor_into_terminal(assist_id, *height_in_lines, window, cx);
|
||||
self.insert_prompt_editor_into_terminal(assist_id, *height_in_lines, cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn start_assist(&mut self, assist_id: TerminalInlineAssistId, cx: &mut App) {
|
||||
fn start_assist(&mut self, assist_id: TerminalInlineAssistId, cx: &mut WindowContext) {
|
||||
let assist = if let Some(assist) = self.assists.get_mut(&assist_id) {
|
||||
assist
|
||||
} else {
|
||||
@@ -221,7 +213,7 @@ impl TerminalInlineAssistant {
|
||||
codegen.update(cx, |codegen, cx| codegen.start(request, cx));
|
||||
}
|
||||
|
||||
fn stop_assist(&mut self, assist_id: TerminalInlineAssistId, cx: &mut App) {
|
||||
fn stop_assist(&mut self, assist_id: TerminalInlineAssistId, cx: &mut WindowContext) {
|
||||
let assist = if let Some(assist) = self.assists.get_mut(&assist_id) {
|
||||
assist
|
||||
} else {
|
||||
@@ -234,7 +226,7 @@ impl TerminalInlineAssistant {
|
||||
fn request_for_inline_assist(
|
||||
&self,
|
||||
assist_id: TerminalInlineAssistId,
|
||||
cx: &mut App,
|
||||
cx: &mut WindowContext,
|
||||
) -> Result<LanguageModelRequest> {
|
||||
let assist = self.assists.get(&assist_id).context("invalid assist")?;
|
||||
|
||||
@@ -242,7 +234,7 @@ impl TerminalInlineAssistant {
|
||||
let (latest_output, working_directory) = assist
|
||||
.terminal
|
||||
.update(cx, |terminal, cx| {
|
||||
let terminal = terminal.entity().read(cx);
|
||||
let terminal = terminal.model().read(cx);
|
||||
let latest_output = terminal.last_n_non_empty_lines(DEFAULT_CONTEXT_LINES);
|
||||
let working_directory = terminal
|
||||
.working_directory()
|
||||
@@ -304,17 +296,16 @@ impl TerminalInlineAssistant {
|
||||
assist_id: TerminalInlineAssistId,
|
||||
undo: bool,
|
||||
execute: bool,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
cx: &mut WindowContext,
|
||||
) {
|
||||
self.dismiss_assist(assist_id, window, cx);
|
||||
self.dismiss_assist(assist_id, cx);
|
||||
|
||||
if let Some(assist) = self.assists.remove(&assist_id) {
|
||||
assist
|
||||
.terminal
|
||||
.update(cx, |this, cx| {
|
||||
this.clear_block_below_cursor(cx);
|
||||
this.focus_handle(cx).focus(window);
|
||||
this.focus_handle(cx).focus(cx);
|
||||
})
|
||||
.log_err();
|
||||
|
||||
@@ -357,8 +348,7 @@ impl TerminalInlineAssistant {
|
||||
fn dismiss_assist(
|
||||
&mut self,
|
||||
assist_id: TerminalInlineAssistId,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
cx: &mut WindowContext,
|
||||
) -> bool {
|
||||
let Some(assist) = self.assists.get_mut(&assist_id) else {
|
||||
return false;
|
||||
@@ -371,7 +361,7 @@ impl TerminalInlineAssistant {
|
||||
.terminal
|
||||
.update(cx, |this, cx| {
|
||||
this.clear_block_below_cursor(cx);
|
||||
this.focus_handle(cx).focus(window);
|
||||
this.focus_handle(cx).focus(cx);
|
||||
})
|
||||
.is_ok()
|
||||
}
|
||||
@@ -380,8 +370,7 @@ impl TerminalInlineAssistant {
|
||||
&mut self,
|
||||
assist_id: TerminalInlineAssistId,
|
||||
height: u8,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
cx: &mut WindowContext,
|
||||
) {
|
||||
if let Some(assist) = self.assists.get_mut(&assist_id) {
|
||||
if let Some(prompt_editor) = assist.prompt_editor.as_ref().cloned() {
|
||||
@@ -393,7 +382,7 @@ impl TerminalInlineAssistant {
|
||||
height,
|
||||
render: Box::new(move |_| prompt_editor.clone().into_any_element()),
|
||||
};
|
||||
terminal.set_block_below_cursor(block, window, cx);
|
||||
terminal.set_block_below_cursor(block, cx);
|
||||
})
|
||||
.log_err();
|
||||
}
|
||||
@@ -402,10 +391,10 @@ impl TerminalInlineAssistant {
|
||||
}
|
||||
|
||||
struct TerminalInlineAssist {
|
||||
terminal: WeakEntity<TerminalView>,
|
||||
prompt_editor: Option<Entity<PromptEditor>>,
|
||||
codegen: Entity<Codegen>,
|
||||
workspace: Option<WeakEntity<Workspace>>,
|
||||
terminal: WeakView<TerminalView>,
|
||||
prompt_editor: Option<View<PromptEditor>>,
|
||||
codegen: Model<Codegen>,
|
||||
workspace: Option<WeakView<Workspace>>,
|
||||
include_context: bool,
|
||||
_subscriptions: Vec<Subscription>,
|
||||
}
|
||||
@@ -413,12 +402,11 @@ struct TerminalInlineAssist {
|
||||
impl TerminalInlineAssist {
|
||||
pub fn new(
|
||||
assist_id: TerminalInlineAssistId,
|
||||
terminal: &Entity<TerminalView>,
|
||||
terminal: &View<TerminalView>,
|
||||
include_context: bool,
|
||||
prompt_editor: Entity<PromptEditor>,
|
||||
workspace: Option<WeakEntity<Workspace>>,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
prompt_editor: View<PromptEditor>,
|
||||
workspace: Option<WeakView<Workspace>>,
|
||||
cx: &mut WindowContext,
|
||||
) -> Self {
|
||||
let codegen = prompt_editor.read(cx).codegen.clone();
|
||||
Self {
|
||||
@@ -428,12 +416,12 @@ impl TerminalInlineAssist {
|
||||
workspace: workspace.clone(),
|
||||
include_context,
|
||||
_subscriptions: vec![
|
||||
window.subscribe(&prompt_editor, cx, |prompt_editor, event, window, cx| {
|
||||
cx.subscribe(&prompt_editor, |prompt_editor, event, cx| {
|
||||
TerminalInlineAssistant::update_global(cx, |this, cx| {
|
||||
this.handle_prompt_editor_event(prompt_editor, event, window, cx)
|
||||
this.handle_prompt_editor_event(prompt_editor, event, cx)
|
||||
})
|
||||
}),
|
||||
window.subscribe(&codegen, cx, move |codegen, event, window, cx| {
|
||||
cx.subscribe(&codegen, move |codegen, event, cx| {
|
||||
TerminalInlineAssistant::update_global(cx, |this, cx| match event {
|
||||
CodegenEvent::Finished => {
|
||||
let assist = if let Some(assist) = this.assists.get(&assist_id) {
|
||||
@@ -466,7 +454,7 @@ impl TerminalInlineAssist {
|
||||
}
|
||||
|
||||
if assist.prompt_editor.is_none() {
|
||||
this.finish_assist(assist_id, false, false, window, cx);
|
||||
this.finish_assist(assist_id, false, false, cx);
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -488,25 +476,25 @@ enum PromptEditorEvent {
|
||||
struct PromptEditor {
|
||||
id: TerminalInlineAssistId,
|
||||
height_in_lines: u8,
|
||||
editor: Entity<Editor>,
|
||||
language_model_selector: Entity<LanguageModelSelector>,
|
||||
editor: View<Editor>,
|
||||
language_model_selector: View<LanguageModelSelector>,
|
||||
edited_since_done: bool,
|
||||
prompt_history: VecDeque<String>,
|
||||
prompt_history_ix: Option<usize>,
|
||||
pending_prompt: String,
|
||||
codegen: Entity<Codegen>,
|
||||
codegen: Model<Codegen>,
|
||||
_codegen_subscription: Subscription,
|
||||
editor_subscriptions: Vec<Subscription>,
|
||||
pending_token_count: Task<Result<()>>,
|
||||
token_count: Option<usize>,
|
||||
_token_count_subscriptions: Vec<Subscription>,
|
||||
workspace: Option<WeakEntity<Workspace>>,
|
||||
workspace: Option<WeakView<Workspace>>,
|
||||
}
|
||||
|
||||
impl EventEmitter<PromptEditorEvent> for PromptEditor {}
|
||||
|
||||
impl Render for PromptEditor {
|
||||
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
let status = &self.codegen.read(cx).status;
|
||||
let buttons = match status {
|
||||
CodegenStatus::Idle => {
|
||||
@@ -514,20 +502,16 @@ impl Render for PromptEditor {
|
||||
IconButton::new("cancel", IconName::Close)
|
||||
.icon_color(Color::Muted)
|
||||
.shape(IconButtonShape::Square)
|
||||
.tooltip(|window, cx| {
|
||||
Tooltip::for_action("Cancel Assist", &menu::Cancel, window, cx)
|
||||
})
|
||||
.tooltip(|cx| Tooltip::for_action("Cancel Assist", &menu::Cancel, cx))
|
||||
.on_click(
|
||||
cx.listener(|_, _, _, cx| cx.emit(PromptEditorEvent::CancelRequested)),
|
||||
cx.listener(|_, _, cx| cx.emit(PromptEditorEvent::CancelRequested)),
|
||||
),
|
||||
IconButton::new("start", IconName::SparkleAlt)
|
||||
.icon_color(Color::Muted)
|
||||
.shape(IconButtonShape::Square)
|
||||
.tooltip(|window, cx| {
|
||||
Tooltip::for_action("Generate", &menu::Confirm, window, cx)
|
||||
})
|
||||
.tooltip(|cx| Tooltip::for_action("Generate", &menu::Confirm, cx))
|
||||
.on_click(
|
||||
cx.listener(|_, _, _, cx| cx.emit(PromptEditorEvent::StartRequested)),
|
||||
cx.listener(|_, _, cx| cx.emit(PromptEditorEvent::StartRequested)),
|
||||
),
|
||||
]
|
||||
}
|
||||
@@ -536,24 +520,23 @@ impl Render for PromptEditor {
|
||||
IconButton::new("cancel", IconName::Close)
|
||||
.icon_color(Color::Muted)
|
||||
.shape(IconButtonShape::Square)
|
||||
.tooltip(Tooltip::text("Cancel Assist"))
|
||||
.tooltip(|cx| Tooltip::text("Cancel Assist", cx))
|
||||
.on_click(
|
||||
cx.listener(|_, _, _, cx| cx.emit(PromptEditorEvent::CancelRequested)),
|
||||
cx.listener(|_, _, cx| cx.emit(PromptEditorEvent::CancelRequested)),
|
||||
),
|
||||
IconButton::new("stop", IconName::Stop)
|
||||
.icon_color(Color::Error)
|
||||
.shape(IconButtonShape::Square)
|
||||
.tooltip(|window, cx| {
|
||||
.tooltip(|cx| {
|
||||
Tooltip::with_meta(
|
||||
"Interrupt Generation",
|
||||
Some(&menu::Cancel),
|
||||
"Changes won't be discarded",
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.on_click(
|
||||
cx.listener(|_, _, _, cx| cx.emit(PromptEditorEvent::StopRequested)),
|
||||
cx.listener(|_, _, cx| cx.emit(PromptEditorEvent::StopRequested)),
|
||||
),
|
||||
]
|
||||
}
|
||||
@@ -561,12 +544,8 @@ impl Render for PromptEditor {
|
||||
let cancel = IconButton::new("cancel", IconName::Close)
|
||||
.icon_color(Color::Muted)
|
||||
.shape(IconButtonShape::Square)
|
||||
.tooltip(|window, cx| {
|
||||
Tooltip::for_action("Cancel Assist", &menu::Cancel, window, cx)
|
||||
})
|
||||
.on_click(
|
||||
cx.listener(|_, _, _, cx| cx.emit(PromptEditorEvent::CancelRequested)),
|
||||
);
|
||||
.tooltip(|cx| Tooltip::for_action("Cancel Assist", &menu::Cancel, cx))
|
||||
.on_click(cx.listener(|_, _, cx| cx.emit(PromptEditorEvent::CancelRequested)));
|
||||
|
||||
let has_error = matches!(status, CodegenStatus::Error(_));
|
||||
if has_error || self.edited_since_done {
|
||||
@@ -575,16 +554,15 @@ impl Render for PromptEditor {
|
||||
IconButton::new("restart", IconName::RotateCw)
|
||||
.icon_color(Color::Info)
|
||||
.shape(IconButtonShape::Square)
|
||||
.tooltip(|window, cx| {
|
||||
.tooltip(|cx| {
|
||||
Tooltip::with_meta(
|
||||
"Restart Generation",
|
||||
Some(&menu::Confirm),
|
||||
"Changes will be discarded",
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.on_click(cx.listener(|_, _, _, cx| {
|
||||
.on_click(cx.listener(|_, _, cx| {
|
||||
cx.emit(PromptEditorEvent::StartRequested);
|
||||
})),
|
||||
]
|
||||
@@ -594,29 +572,23 @@ impl Render for PromptEditor {
|
||||
IconButton::new("accept", IconName::Check)
|
||||
.icon_color(Color::Info)
|
||||
.shape(IconButtonShape::Square)
|
||||
.tooltip(|window, cx| {
|
||||
Tooltip::for_action(
|
||||
"Accept Generated Command",
|
||||
&menu::Confirm,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
.tooltip(|cx| {
|
||||
Tooltip::for_action("Accept Generated Command", &menu::Confirm, cx)
|
||||
})
|
||||
.on_click(cx.listener(|_, _, _, cx| {
|
||||
.on_click(cx.listener(|_, _, cx| {
|
||||
cx.emit(PromptEditorEvent::ConfirmRequested { execute: false });
|
||||
})),
|
||||
IconButton::new("confirm", IconName::Play)
|
||||
.icon_color(Color::Info)
|
||||
.shape(IconButtonShape::Square)
|
||||
.tooltip(|window, cx| {
|
||||
.tooltip(|cx| {
|
||||
Tooltip::for_action(
|
||||
"Execute Generated Command",
|
||||
&menu::SecondaryConfirm,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.on_click(cx.listener(|_, _, _, cx| {
|
||||
.on_click(cx.listener(|_, _, cx| {
|
||||
cx.emit(PromptEditorEvent::ConfirmRequested { execute: true });
|
||||
})),
|
||||
]
|
||||
@@ -646,23 +618,21 @@ impl Render for PromptEditor {
|
||||
IconButton::new("context", IconName::SettingsAlt)
|
||||
.shape(IconButtonShape::Square)
|
||||
.icon_size(IconSize::Small)
|
||||
.icon_color(Color::Muted),
|
||||
move |window, cx| {
|
||||
Tooltip::with_meta(
|
||||
format!(
|
||||
"Using {}",
|
||||
LanguageModelRegistry::read_global(cx)
|
||||
.active_model()
|
||||
.map(|model| model.name().0)
|
||||
.unwrap_or_else(|| "No model selected".into()),
|
||||
),
|
||||
None,
|
||||
"Change Model",
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
},
|
||||
gpui::Corner::TopRight,
|
||||
.icon_color(Color::Muted)
|
||||
.tooltip(move |cx| {
|
||||
Tooltip::with_meta(
|
||||
format!(
|
||||
"Using {}",
|
||||
LanguageModelRegistry::read_global(cx)
|
||||
.active_model()
|
||||
.map(|model| model.name().0)
|
||||
.unwrap_or_else(|| "No model selected".into()),
|
||||
),
|
||||
None,
|
||||
"Change Model",
|
||||
cx,
|
||||
)
|
||||
}),
|
||||
))
|
||||
.children(
|
||||
if let CodegenStatus::Error(error) = &self.codegen.read(cx).status {
|
||||
@@ -670,7 +640,7 @@ impl Render for PromptEditor {
|
||||
Some(
|
||||
div()
|
||||
.id("error")
|
||||
.tooltip(Tooltip::text(error_message))
|
||||
.tooltip(move |cx| Tooltip::text(error_message.clone(), cx))
|
||||
.child(
|
||||
Icon::new(IconName::XCircle)
|
||||
.size(IconSize::Small)
|
||||
@@ -693,8 +663,8 @@ impl Render for PromptEditor {
|
||||
}
|
||||
}
|
||||
|
||||
impl Focusable for PromptEditor {
|
||||
fn focus_handle(&self, cx: &App) -> FocusHandle {
|
||||
impl FocusableView for PromptEditor {
|
||||
fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
|
||||
self.editor.focus_handle(cx)
|
||||
}
|
||||
}
|
||||
@@ -706,15 +676,14 @@ impl PromptEditor {
|
||||
fn new(
|
||||
id: TerminalInlineAssistId,
|
||||
prompt_history: VecDeque<String>,
|
||||
prompt_buffer: Entity<MultiBuffer>,
|
||||
codegen: Entity<Codegen>,
|
||||
assistant_panel: Option<&Entity<AssistantPanel>>,
|
||||
workspace: Option<WeakEntity<Workspace>>,
|
||||
prompt_buffer: Model<MultiBuffer>,
|
||||
codegen: Model<Codegen>,
|
||||
assistant_panel: Option<&View<AssistantPanel>>,
|
||||
workspace: Option<WeakView<Workspace>>,
|
||||
fs: Arc<dyn Fs>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Self {
|
||||
let prompt_editor = cx.new(|cx| {
|
||||
let prompt_editor = cx.new_view(|cx| {
|
||||
let mut editor = Editor::new(
|
||||
EditorMode::AutoHeight {
|
||||
max_lines: Self::MAX_LINES as usize,
|
||||
@@ -722,28 +691,24 @@ impl PromptEditor {
|
||||
prompt_buffer,
|
||||
None,
|
||||
false,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
editor.set_soft_wrap_mode(language::language_settings::SoftWrap::EditorWidth, cx);
|
||||
editor.set_placeholder_text(Self::placeholder_text(window, cx), cx);
|
||||
editor.set_placeholder_text(Self::placeholder_text(cx), cx);
|
||||
editor
|
||||
});
|
||||
|
||||
let mut token_count_subscriptions = Vec::new();
|
||||
if let Some(assistant_panel) = assistant_panel {
|
||||
token_count_subscriptions.push(cx.subscribe_in(
|
||||
assistant_panel,
|
||||
window,
|
||||
Self::handle_assistant_panel_event,
|
||||
));
|
||||
token_count_subscriptions
|
||||
.push(cx.subscribe(assistant_panel, Self::handle_assistant_panel_event));
|
||||
}
|
||||
|
||||
let mut this = Self {
|
||||
id,
|
||||
height_in_lines: 1,
|
||||
editor: prompt_editor,
|
||||
language_model_selector: cx.new(|cx| {
|
||||
language_model_selector: cx.new_view(|cx| {
|
||||
let fs = fs.clone();
|
||||
LanguageModelSelector::new(
|
||||
move |model, cx| {
|
||||
@@ -753,7 +718,6 @@ impl PromptEditor {
|
||||
move |settings, _| settings.set_model(model.clone()),
|
||||
);
|
||||
},
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
}),
|
||||
@@ -761,7 +725,7 @@ impl PromptEditor {
|
||||
prompt_history,
|
||||
prompt_history_ix: None,
|
||||
pending_prompt: String::new(),
|
||||
_codegen_subscription: cx.observe_in(&codegen, window, Self::handle_codegen_changed),
|
||||
_codegen_subscription: cx.observe(&codegen, Self::handle_codegen_changed),
|
||||
editor_subscriptions: Vec::new(),
|
||||
codegen,
|
||||
pending_token_count: Task::ready(Ok(())),
|
||||
@@ -775,15 +739,15 @@ impl PromptEditor {
|
||||
this
|
||||
}
|
||||
|
||||
fn placeholder_text(window: &Window, cx: &App) -> String {
|
||||
let context_keybinding = text_for_action(&zed_actions::assistant::ToggleFocus, window, cx)
|
||||
fn placeholder_text(cx: &WindowContext) -> String {
|
||||
let context_keybinding = text_for_action(&zed_actions::assistant::ToggleFocus, cx)
|
||||
.map(|keybinding| format!(" • {keybinding} for context"))
|
||||
.unwrap_or_default();
|
||||
|
||||
format!("Generate…{context_keybinding} • ↓↑ for history")
|
||||
}
|
||||
|
||||
fn subscribe_to_editor(&mut self, cx: &mut Context<Self>) {
|
||||
fn subscribe_to_editor(&mut self, cx: &mut ViewContext<Self>) {
|
||||
self.editor_subscriptions.clear();
|
||||
self.editor_subscriptions
|
||||
.push(cx.observe(&self.editor, Self::handle_prompt_editor_changed));
|
||||
@@ -791,11 +755,11 @@ impl PromptEditor {
|
||||
.push(cx.subscribe(&self.editor, Self::handle_prompt_editor_events));
|
||||
}
|
||||
|
||||
fn prompt(&self, cx: &App) -> String {
|
||||
fn prompt(&self, cx: &AppContext) -> String {
|
||||
self.editor.read(cx).text(cx)
|
||||
}
|
||||
|
||||
fn count_lines(&mut self, cx: &mut Context<Self>) {
|
||||
fn count_lines(&mut self, cx: &mut ViewContext<Self>) {
|
||||
let height_in_lines = cmp::max(
|
||||
2, // Make the editor at least two lines tall, to account for padding and buttons.
|
||||
cmp::min(
|
||||
@@ -813,16 +777,15 @@ impl PromptEditor {
|
||||
|
||||
fn handle_assistant_panel_event(
|
||||
&mut self,
|
||||
_: &Entity<AssistantPanel>,
|
||||
_: View<AssistantPanel>,
|
||||
event: &AssistantPanelEvent,
|
||||
_: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
let AssistantPanelEvent::ContextEdited { .. } = event;
|
||||
self.count_tokens(cx);
|
||||
}
|
||||
|
||||
fn count_tokens(&mut self, cx: &mut Context<Self>) {
|
||||
fn count_tokens(&mut self, cx: &mut ViewContext<Self>) {
|
||||
let assist_id = self.id;
|
||||
let Some(model) = LanguageModelRegistry::read_global(cx).active_model() else {
|
||||
return;
|
||||
@@ -842,15 +805,15 @@ impl PromptEditor {
|
||||
})
|
||||
}
|
||||
|
||||
fn handle_prompt_editor_changed(&mut self, _: Entity<Editor>, cx: &mut Context<Self>) {
|
||||
fn handle_prompt_editor_changed(&mut self, _: View<Editor>, cx: &mut ViewContext<Self>) {
|
||||
self.count_lines(cx);
|
||||
}
|
||||
|
||||
fn handle_prompt_editor_events(
|
||||
&mut self,
|
||||
_: Entity<Editor>,
|
||||
_: View<Editor>,
|
||||
event: &EditorEvent,
|
||||
cx: &mut Context<Self>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
match event {
|
||||
EditorEvent::Edited { .. } => {
|
||||
@@ -873,12 +836,7 @@ impl PromptEditor {
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_codegen_changed(
|
||||
&mut self,
|
||||
_: Entity<Codegen>,
|
||||
_: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
fn handle_codegen_changed(&mut self, _: Model<Codegen>, cx: &mut ViewContext<Self>) {
|
||||
match &self.codegen.read(cx).status {
|
||||
CodegenStatus::Idle => {
|
||||
self.editor
|
||||
@@ -896,7 +854,7 @@ impl PromptEditor {
|
||||
}
|
||||
}
|
||||
|
||||
fn cancel(&mut self, _: &editor::actions::Cancel, _: &mut Window, cx: &mut Context<Self>) {
|
||||
fn cancel(&mut self, _: &editor::actions::Cancel, cx: &mut ViewContext<Self>) {
|
||||
match &self.codegen.read(cx).status {
|
||||
CodegenStatus::Idle | CodegenStatus::Done | CodegenStatus::Error(_) => {
|
||||
cx.emit(PromptEditorEvent::CancelRequested);
|
||||
@@ -907,7 +865,7 @@ impl PromptEditor {
|
||||
}
|
||||
}
|
||||
|
||||
fn confirm(&mut self, _: &menu::Confirm, _: &mut Window, cx: &mut Context<Self>) {
|
||||
fn confirm(&mut self, _: &menu::Confirm, cx: &mut ViewContext<Self>) {
|
||||
match &self.codegen.read(cx).status {
|
||||
CodegenStatus::Idle => {
|
||||
if !self.editor.read(cx).text(cx).trim().is_empty() {
|
||||
@@ -930,58 +888,53 @@ impl PromptEditor {
|
||||
}
|
||||
}
|
||||
|
||||
fn secondary_confirm(
|
||||
&mut self,
|
||||
_: &menu::SecondaryConfirm,
|
||||
_: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
fn secondary_confirm(&mut self, _: &menu::SecondaryConfirm, cx: &mut ViewContext<Self>) {
|
||||
if matches!(self.codegen.read(cx).status, CodegenStatus::Done) {
|
||||
cx.emit(PromptEditorEvent::ConfirmRequested { execute: true });
|
||||
}
|
||||
}
|
||||
|
||||
fn move_up(&mut self, _: &MoveUp, window: &mut Window, cx: &mut Context<Self>) {
|
||||
fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
|
||||
if let Some(ix) = self.prompt_history_ix {
|
||||
if ix > 0 {
|
||||
self.prompt_history_ix = Some(ix - 1);
|
||||
let prompt = self.prompt_history[ix - 1].as_str();
|
||||
self.editor.update(cx, |editor, cx| {
|
||||
editor.set_text(prompt, window, cx);
|
||||
editor.move_to_beginning(&Default::default(), window, cx);
|
||||
editor.set_text(prompt, cx);
|
||||
editor.move_to_beginning(&Default::default(), cx);
|
||||
});
|
||||
}
|
||||
} else if !self.prompt_history.is_empty() {
|
||||
self.prompt_history_ix = Some(self.prompt_history.len() - 1);
|
||||
let prompt = self.prompt_history[self.prompt_history.len() - 1].as_str();
|
||||
self.editor.update(cx, |editor, cx| {
|
||||
editor.set_text(prompt, window, cx);
|
||||
editor.move_to_beginning(&Default::default(), window, cx);
|
||||
editor.set_text(prompt, cx);
|
||||
editor.move_to_beginning(&Default::default(), cx);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn move_down(&mut self, _: &MoveDown, window: &mut Window, cx: &mut Context<Self>) {
|
||||
fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
|
||||
if let Some(ix) = self.prompt_history_ix {
|
||||
if ix < self.prompt_history.len() - 1 {
|
||||
self.prompt_history_ix = Some(ix + 1);
|
||||
let prompt = self.prompt_history[ix + 1].as_str();
|
||||
self.editor.update(cx, |editor, cx| {
|
||||
editor.set_text(prompt, window, cx);
|
||||
editor.move_to_end(&Default::default(), window, cx)
|
||||
editor.set_text(prompt, cx);
|
||||
editor.move_to_end(&Default::default(), cx)
|
||||
});
|
||||
} else {
|
||||
self.prompt_history_ix = None;
|
||||
let prompt = self.pending_prompt.as_str();
|
||||
self.editor.update(cx, |editor, cx| {
|
||||
editor.set_text(prompt, window, cx);
|
||||
editor.move_to_end(&Default::default(), window, cx)
|
||||
editor.set_text(prompt, cx);
|
||||
editor.move_to_end(&Default::default(), cx)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn render_token_count(&self, cx: &mut Context<Self>) -> Option<impl IntoElement> {
|
||||
fn render_token_count(&self, cx: &mut ViewContext<Self>) -> Option<impl IntoElement> {
|
||||
let model = LanguageModelRegistry::read_global(cx).active_model()?;
|
||||
let token_count = self.token_count?;
|
||||
let max_token_count = model.max_token_count();
|
||||
@@ -1011,35 +964,34 @@ impl PromptEditor {
|
||||
);
|
||||
if let Some(workspace) = self.workspace.clone() {
|
||||
token_count = token_count
|
||||
.tooltip(|window, cx| {
|
||||
.tooltip(|cx| {
|
||||
Tooltip::with_meta(
|
||||
"Tokens Used by Inline Assistant",
|
||||
None,
|
||||
"Click to Open Assistant Panel",
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.cursor_pointer()
|
||||
.on_mouse_down(gpui::MouseButton::Left, |_, _, cx| cx.stop_propagation())
|
||||
.on_click(move |_, window, cx| {
|
||||
.on_mouse_down(gpui::MouseButton::Left, |_, cx| cx.stop_propagation())
|
||||
.on_click(move |_, cx| {
|
||||
cx.stop_propagation();
|
||||
workspace
|
||||
.update(cx, |workspace, cx| {
|
||||
workspace.focus_panel::<AssistantPanel>(window, cx)
|
||||
workspace.focus_panel::<AssistantPanel>(cx)
|
||||
})
|
||||
.ok();
|
||||
});
|
||||
} else {
|
||||
token_count = token_count
|
||||
.cursor_default()
|
||||
.tooltip(Tooltip::text("Tokens Used by Inline Assistant"));
|
||||
.tooltip(|cx| Tooltip::text("Tokens Used by Inline Assistant", cx));
|
||||
}
|
||||
|
||||
Some(token_count)
|
||||
}
|
||||
|
||||
fn render_prompt_editor(&self, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
fn render_prompt_editor(&self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
let settings = ThemeSettings::get_global(cx);
|
||||
let text_style = TextStyle {
|
||||
color: if self.editor.read(cx).read_only(cx) {
|
||||
@@ -1049,7 +1001,7 @@ impl PromptEditor {
|
||||
},
|
||||
font_family: settings.buffer_font.family.clone(),
|
||||
font_fallbacks: settings.buffer_font.fallbacks.clone(),
|
||||
font_size: settings.buffer_font_size(cx).into(),
|
||||
font_size: settings.buffer_font_size.into(),
|
||||
font_weight: settings.buffer_font.weight,
|
||||
line_height: relative(settings.buffer_line_height.value()),
|
||||
..Default::default()
|
||||
@@ -1077,27 +1029,27 @@ const CLEAR_INPUT: &str = "\x15";
|
||||
const CARRIAGE_RETURN: &str = "\x0d";
|
||||
|
||||
struct TerminalTransaction {
|
||||
terminal: Entity<Terminal>,
|
||||
terminal: Model<Terminal>,
|
||||
}
|
||||
|
||||
impl TerminalTransaction {
|
||||
pub fn start(terminal: Entity<Terminal>) -> Self {
|
||||
pub fn start(terminal: Model<Terminal>) -> Self {
|
||||
Self { terminal }
|
||||
}
|
||||
|
||||
pub fn push(&mut self, hunk: String, cx: &mut App) {
|
||||
pub fn push(&mut self, hunk: String, cx: &mut AppContext) {
|
||||
// Ensure that the assistant cannot accidentally execute commands that are streamed into the terminal
|
||||
let input = Self::sanitize_input(hunk);
|
||||
self.terminal
|
||||
.update(cx, |terminal, _| terminal.input(input));
|
||||
}
|
||||
|
||||
pub fn undo(&self, cx: &mut App) {
|
||||
pub fn undo(&self, cx: &mut AppContext) {
|
||||
self.terminal
|
||||
.update(cx, |terminal, _| terminal.input(CLEAR_INPUT.to_string()));
|
||||
}
|
||||
|
||||
pub fn complete(&self, cx: &mut App) {
|
||||
pub fn complete(&self, cx: &mut AppContext) {
|
||||
self.terminal.update(cx, |terminal, _| {
|
||||
terminal.input(CARRIAGE_RETURN.to_string())
|
||||
});
|
||||
@@ -1111,14 +1063,14 @@ impl TerminalTransaction {
|
||||
pub struct Codegen {
|
||||
status: CodegenStatus,
|
||||
telemetry: Option<Arc<Telemetry>>,
|
||||
terminal: Entity<Terminal>,
|
||||
terminal: Model<Terminal>,
|
||||
generation: Task<()>,
|
||||
message_id: Option<String>,
|
||||
transaction: Option<TerminalTransaction>,
|
||||
}
|
||||
|
||||
impl Codegen {
|
||||
pub fn new(terminal: Entity<Terminal>, telemetry: Option<Arc<Telemetry>>) -> Self {
|
||||
pub fn new(terminal: Model<Terminal>, telemetry: Option<Arc<Telemetry>>) -> Self {
|
||||
Self {
|
||||
terminal,
|
||||
telemetry,
|
||||
@@ -1129,7 +1081,7 @@ impl Codegen {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start(&mut self, prompt: LanguageModelRequest, cx: &mut Context<Self>) {
|
||||
pub fn start(&mut self, prompt: LanguageModelRequest, cx: &mut ModelContext<Self>) {
|
||||
let Some(model) = LanguageModelRegistry::read_global(cx).active_model() else {
|
||||
return;
|
||||
};
|
||||
@@ -1151,7 +1103,7 @@ impl Codegen {
|
||||
|
||||
let (mut hunks_tx, mut hunks_rx) = mpsc::channel(1);
|
||||
|
||||
let task = cx.background_spawn({
|
||||
let task = cx.background_executor().spawn({
|
||||
let message_id = message_id.clone();
|
||||
let executor = cx.background_executor().clone();
|
||||
async move {
|
||||
@@ -1229,20 +1181,20 @@ impl Codegen {
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
pub fn stop(&mut self, cx: &mut Context<Self>) {
|
||||
pub fn stop(&mut self, cx: &mut ModelContext<Self>) {
|
||||
self.status = CodegenStatus::Done;
|
||||
self.generation = Task::ready(());
|
||||
cx.emit(CodegenEvent::Finished);
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
pub fn complete(&mut self, cx: &mut Context<Self>) {
|
||||
pub fn complete(&mut self, cx: &mut ModelContext<Self>) {
|
||||
if let Some(transaction) = self.transaction.take() {
|
||||
transaction.complete(cx);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn undo(&mut self, cx: &mut Context<Self>) {
|
||||
pub fn undo(&mut self, cx: &mut ModelContext<Self>) {
|
||||
if let Some(transaction) = self.transaction.take() {
|
||||
transaction.undo(cx);
|
||||
}
|
||||
|
||||
@@ -39,20 +39,19 @@ fs.workspace = true
|
||||
futures.workspace = true
|
||||
fuzzy.workspace = true
|
||||
gpui.workspace = true
|
||||
heed.workspace = true
|
||||
html_to_markdown.workspace = true
|
||||
http_client.workspace = true
|
||||
itertools.workspace = true
|
||||
language.workspace = true
|
||||
language_model.workspace = true
|
||||
language_model_selector.workspace = true
|
||||
language_models.workspace = true
|
||||
log.workspace = true
|
||||
lsp.workspace = true
|
||||
markdown.workspace = true
|
||||
menu.workspace = true
|
||||
multi_buffer.workspace = true
|
||||
parking_lot.workspace = true
|
||||
paths.workspace = true
|
||||
picker.workspace = true
|
||||
project.workspace = true
|
||||
prompt_library.workspace = true
|
||||
@@ -61,6 +60,7 @@ rope.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
settings.workspace = true
|
||||
similar.workspace = true
|
||||
smol.workspace = true
|
||||
streaming_diff.workspace = true
|
||||
telemetry_events.workspace = true
|
||||
@@ -71,16 +71,12 @@ theme.workspace = true
|
||||
time.workspace = true
|
||||
time_format.workspace = true
|
||||
ui.workspace = true
|
||||
unindent.workspace = true
|
||||
util.workspace = true
|
||||
uuid.workspace = true
|
||||
workspace.workspace = true
|
||||
zed_actions.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
editor = { workspace = true, features = ["test-support"] }
|
||||
gpui = { workspace = true, "features" = ["test-support"] }
|
||||
language = { workspace = true, "features" = ["test-support"] }
|
||||
language_model = { workspace = true, "features" = ["test-support"] }
|
||||
project = { workspace = true, features = ["test-support"] }
|
||||
rand.workspace = true
|
||||
indoc.workspace = true
|
||||
|
||||
@@ -3,9 +3,9 @@ use std::sync::Arc;
|
||||
use assistant_tool::ToolWorkingSet;
|
||||
use collections::HashMap;
|
||||
use gpui::{
|
||||
list, AbsoluteLength, AnyElement, App, DefiniteLength, EdgesRefinement, Empty, Entity, Length,
|
||||
ListAlignment, ListOffset, ListState, StyleRefinement, Subscription, TextStyleRefinement,
|
||||
UnderlineStyle, WeakEntity,
|
||||
list, AbsoluteLength, AnyElement, AppContext, DefiniteLength, EdgesRefinement, Empty, Length,
|
||||
ListAlignment, ListOffset, ListState, Model, StyleRefinement, Subscription,
|
||||
TextStyleRefinement, UnderlineStyle, View, WeakView,
|
||||
};
|
||||
use language::LanguageRegistry;
|
||||
use language_model::Role;
|
||||
@@ -16,48 +16,43 @@ use ui::prelude::*;
|
||||
use workspace::Workspace;
|
||||
|
||||
use crate::thread::{MessageId, Thread, ThreadError, ThreadEvent};
|
||||
use crate::thread_store::ThreadStore;
|
||||
use crate::ui::ContextPill;
|
||||
|
||||
pub struct ActiveThread {
|
||||
workspace: WeakEntity<Workspace>,
|
||||
workspace: WeakView<Workspace>,
|
||||
language_registry: Arc<LanguageRegistry>,
|
||||
tools: Arc<ToolWorkingSet>,
|
||||
thread_store: Entity<ThreadStore>,
|
||||
thread: Entity<Thread>,
|
||||
pub(crate) thread: Model<Thread>,
|
||||
messages: Vec<MessageId>,
|
||||
list_state: ListState,
|
||||
rendered_messages_by_id: HashMap<MessageId, Entity<Markdown>>,
|
||||
rendered_messages_by_id: HashMap<MessageId, View<Markdown>>,
|
||||
last_error: Option<ThreadError>,
|
||||
_subscriptions: Vec<Subscription>,
|
||||
}
|
||||
|
||||
impl ActiveThread {
|
||||
pub fn new(
|
||||
thread: Entity<Thread>,
|
||||
thread_store: Entity<ThreadStore>,
|
||||
workspace: WeakEntity<Workspace>,
|
||||
thread: Model<Thread>,
|
||||
workspace: WeakView<Workspace>,
|
||||
language_registry: Arc<LanguageRegistry>,
|
||||
tools: Arc<ToolWorkingSet>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Self {
|
||||
let subscriptions = vec![
|
||||
cx.observe(&thread, |_, _, cx| cx.notify()),
|
||||
cx.subscribe_in(&thread, window, Self::handle_thread_event),
|
||||
cx.subscribe(&thread, Self::handle_thread_event),
|
||||
];
|
||||
|
||||
let mut this = Self {
|
||||
workspace,
|
||||
language_registry,
|
||||
tools,
|
||||
thread_store,
|
||||
thread: thread.clone(),
|
||||
messages: Vec::new(),
|
||||
rendered_messages_by_id: HashMap::default(),
|
||||
list_state: ListState::new(0, ListAlignment::Bottom, px(1024.), {
|
||||
let this = cx.entity().downgrade();
|
||||
move |ix, _: &mut Window, cx: &mut App| {
|
||||
let this = cx.view().downgrade();
|
||||
move |ix, cx: &mut WindowContext| {
|
||||
this.update(cx, |this, cx| this.render_message(ix, cx))
|
||||
.unwrap()
|
||||
}
|
||||
@@ -67,29 +62,25 @@ impl ActiveThread {
|
||||
};
|
||||
|
||||
for message in thread.read(cx).messages().cloned().collect::<Vec<_>>() {
|
||||
this.push_message(&message.id, message.text.clone(), window, cx);
|
||||
this.push_message(&message.id, message.text.clone(), cx);
|
||||
}
|
||||
|
||||
this
|
||||
}
|
||||
|
||||
pub fn thread(&self) -> &Entity<Thread> {
|
||||
&self.thread
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.messages.is_empty()
|
||||
}
|
||||
|
||||
pub fn summary(&self, cx: &App) -> Option<SharedString> {
|
||||
pub fn summary(&self, cx: &AppContext) -> Option<SharedString> {
|
||||
self.thread.read(cx).summary()
|
||||
}
|
||||
|
||||
pub fn summary_or_default(&self, cx: &App) -> SharedString {
|
||||
pub fn summary_or_default(&self, cx: &AppContext) -> SharedString {
|
||||
self.thread.read(cx).summary_or_default()
|
||||
}
|
||||
|
||||
pub fn cancel_last_completion(&mut self, cx: &mut App) -> bool {
|
||||
pub fn cancel_last_completion(&mut self, cx: &mut AppContext) -> bool {
|
||||
self.last_error.take();
|
||||
self.thread
|
||||
.update(cx, |thread, _cx| thread.cancel_last_completion())
|
||||
@@ -103,13 +94,7 @@ impl ActiveThread {
|
||||
self.last_error.take();
|
||||
}
|
||||
|
||||
fn push_message(
|
||||
&mut self,
|
||||
id: &MessageId,
|
||||
text: String,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
fn push_message(&mut self, id: &MessageId, text: String, cx: &mut ViewContext<Self>) {
|
||||
let old_len = self.messages.len();
|
||||
self.messages.push(*id);
|
||||
self.list_state.splice(old_len..old_len, 1);
|
||||
@@ -118,7 +103,7 @@ impl ActiveThread {
|
||||
let colors = cx.theme().colors();
|
||||
let ui_font_size = TextSize::Default.rems(cx);
|
||||
let buffer_font_size = TextSize::Small.rems(cx);
|
||||
let mut text_style = window.text_style();
|
||||
let mut text_style = cx.text_style();
|
||||
|
||||
text_style.refine(&TextStyleRefinement {
|
||||
font_family: Some(theme_settings.ui_font.family.clone()),
|
||||
@@ -177,9 +162,9 @@ impl ActiveThread {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let markdown = cx.new(|cx| {
|
||||
let markdown = cx.new_view(|cx| {
|
||||
Markdown::new(
|
||||
text.into(),
|
||||
text,
|
||||
markdown_style,
|
||||
Some(self.language_registry.clone()),
|
||||
None,
|
||||
@@ -195,22 +180,16 @@ impl ActiveThread {
|
||||
|
||||
fn handle_thread_event(
|
||||
&mut self,
|
||||
_: &Entity<Thread>,
|
||||
_: Model<Thread>,
|
||||
event: &ThreadEvent,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
match event {
|
||||
ThreadEvent::ShowError(error) => {
|
||||
self.last_error = Some(error.clone());
|
||||
}
|
||||
ThreadEvent::StreamedCompletion | ThreadEvent::SummaryChanged => {
|
||||
self.thread_store
|
||||
.update(cx, |thread_store, cx| {
|
||||
thread_store.save_thread(&self.thread, cx)
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
}
|
||||
ThreadEvent::StreamedCompletion => {}
|
||||
ThreadEvent::SummaryChanged => {}
|
||||
ThreadEvent::StreamedAssistantText(message_id, text) => {
|
||||
if let Some(markdown) = self.rendered_messages_by_id.get_mut(&message_id) {
|
||||
markdown.update(cx, |markdown, cx| {
|
||||
@@ -225,15 +204,9 @@ impl ActiveThread {
|
||||
.message(*message_id)
|
||||
.map(|message| message.text.clone())
|
||||
{
|
||||
self.push_message(message_id, message_text, window, cx);
|
||||
self.push_message(message_id, message_text, cx);
|
||||
}
|
||||
|
||||
self.thread_store
|
||||
.update(cx, |thread_store, cx| {
|
||||
thread_store.save_thread(&self.thread, cx)
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
|
||||
cx.notify();
|
||||
}
|
||||
ThreadEvent::UsePendingTools => {
|
||||
@@ -248,7 +221,7 @@ impl ActiveThread {
|
||||
|
||||
for tool_use in pending_tool_uses {
|
||||
if let Some(tool) = self.tools.tool(&tool_use.name, cx) {
|
||||
let task = tool.run(tool_use.input, self.workspace.clone(), window, cx);
|
||||
let task = tool.run(tool_use.input, self.workspace.clone(), cx);
|
||||
|
||||
self.thread.update(cx, |thread, cx| {
|
||||
thread.insert_tool_output(
|
||||
@@ -265,7 +238,7 @@ impl ActiveThread {
|
||||
}
|
||||
}
|
||||
|
||||
fn render_message(&self, ix: usize, cx: &mut Context<Self>) -> AnyElement {
|
||||
fn render_message(&self, ix: usize, cx: &mut ViewContext<Self>) -> AnyElement {
|
||||
let message_id = self.messages[ix];
|
||||
let Some(message) = self.thread.read(cx).message(message_id) else {
|
||||
return Empty.into_any();
|
||||
@@ -297,7 +270,7 @@ impl ActiveThread {
|
||||
let styled_message = match message.role {
|
||||
Role::User => v_flex()
|
||||
.id(("message-container", ix))
|
||||
.pt_2p5()
|
||||
.py_1()
|
||||
.px_2p5()
|
||||
.child(
|
||||
v_flex()
|
||||
@@ -346,9 +319,10 @@ impl ActiveThread {
|
||||
}
|
||||
|
||||
impl Render for ActiveThread {
|
||||
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
v_flex()
|
||||
.size_full()
|
||||
.pt_1p5()
|
||||
.child(list(self.list_state.clone()).flex_grow())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ mod context;
|
||||
mod context_picker;
|
||||
mod context_store;
|
||||
mod context_strip;
|
||||
mod history_store;
|
||||
mod inline_assistant;
|
||||
mod inline_prompt_editor;
|
||||
mod message_editor;
|
||||
@@ -25,7 +24,7 @@ use client::Client;
|
||||
use command_palette_hooks::CommandPaletteFilter;
|
||||
use feature_flags::{Assistant2FeatureFlag, FeatureFlagAppExt};
|
||||
use fs::Fs;
|
||||
use gpui::{actions, App};
|
||||
use gpui::{actions, AppContext};
|
||||
use prompt_library::PromptBuilder;
|
||||
use settings::Settings as _;
|
||||
|
||||
@@ -41,6 +40,7 @@ actions!(
|
||||
ToggleModelSelector,
|
||||
RemoveAllContext,
|
||||
OpenHistory,
|
||||
OpenPromptEditorHistory,
|
||||
OpenConfiguration,
|
||||
RemoveSelectedThread,
|
||||
Chat,
|
||||
@@ -63,10 +63,9 @@ pub fn init(
|
||||
fs: Arc<dyn Fs>,
|
||||
client: Arc<Client>,
|
||||
prompt_builder: Arc<PromptBuilder>,
|
||||
cx: &mut App,
|
||||
cx: &mut AppContext,
|
||||
) {
|
||||
AssistantSettings::register(cx);
|
||||
thread_store::init(cx);
|
||||
assistant_panel::init(cx);
|
||||
|
||||
inline_assistant::init(
|
||||
@@ -85,7 +84,7 @@ pub fn init(
|
||||
feature_gate_assistant2_actions(cx);
|
||||
}
|
||||
|
||||
fn feature_gate_assistant2_actions(cx: &mut App) {
|
||||
fn feature_gate_assistant2_actions(cx: &mut AppContext) {
|
||||
CommandPaletteFilter::update_global(cx, |filter, _cx| {
|
||||
filter.hide_namespace(NAMESPACE);
|
||||
});
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use collections::HashMap;
|
||||
use gpui::{AnyView, App, EventEmitter, FocusHandle, Focusable, Subscription};
|
||||
use gpui::{Action, AnyView, AppContext, EventEmitter, FocusHandle, FocusableView, Subscription};
|
||||
use language_model::{LanguageModelProvider, LanguageModelProviderId, LanguageModelRegistry};
|
||||
use ui::{prelude::*, Divider, DividerColor, ElevationIndex};
|
||||
use ui::{prelude::*, ElevationIndex};
|
||||
use zed_actions::assistant::DeployPromptLibrary;
|
||||
|
||||
pub struct AssistantConfiguration {
|
||||
@@ -13,17 +13,16 @@ pub struct AssistantConfiguration {
|
||||
}
|
||||
|
||||
impl AssistantConfiguration {
|
||||
pub fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
|
||||
pub fn new(cx: &mut ViewContext<Self>) -> Self {
|
||||
let focus_handle = cx.focus_handle();
|
||||
|
||||
let registry_subscription = cx.subscribe_in(
|
||||
let registry_subscription = cx.subscribe(
|
||||
&LanguageModelRegistry::global(cx),
|
||||
window,
|
||||
|this, _, event: &language_model::Event, window, cx| match event {
|
||||
|this, _, event: &language_model::Event, cx| match event {
|
||||
language_model::Event::AddedProvider(provider_id) => {
|
||||
let provider = LanguageModelRegistry::read_global(cx).provider(provider_id);
|
||||
if let Some(provider) = provider {
|
||||
this.add_provider_configuration_view(&provider, window, cx);
|
||||
this.add_provider_configuration_view(&provider, cx);
|
||||
}
|
||||
}
|
||||
language_model::Event::RemovedProvider(provider_id) => {
|
||||
@@ -38,14 +37,14 @@ impl AssistantConfiguration {
|
||||
configuration_views_by_provider: HashMap::default(),
|
||||
_registry_subscription: registry_subscription,
|
||||
};
|
||||
this.build_provider_configuration_views(window, cx);
|
||||
this.build_provider_configuration_views(cx);
|
||||
this
|
||||
}
|
||||
|
||||
fn build_provider_configuration_views(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
fn build_provider_configuration_views(&mut self, cx: &mut ViewContext<Self>) {
|
||||
let providers = LanguageModelRegistry::read_global(cx).providers();
|
||||
for provider in providers {
|
||||
self.add_provider_configuration_view(&provider, window, cx);
|
||||
self.add_provider_configuration_view(&provider, cx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,17 +55,16 @@ impl AssistantConfiguration {
|
||||
fn add_provider_configuration_view(
|
||||
&mut self,
|
||||
provider: &Arc<dyn LanguageModelProvider>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
let configuration_view = provider.configuration_view(window, cx);
|
||||
let configuration_view = provider.configuration_view(cx);
|
||||
self.configuration_views_by_provider
|
||||
.insert(provider.id(), configuration_view);
|
||||
}
|
||||
}
|
||||
|
||||
impl Focusable for AssistantConfiguration {
|
||||
fn focus_handle(&self, _: &App) -> FocusHandle {
|
||||
impl FocusableView for AssistantConfiguration {
|
||||
fn focus_handle(&self, _: &AppContext) -> FocusHandle {
|
||||
self.focus_handle.clone()
|
||||
}
|
||||
}
|
||||
@@ -81,7 +79,7 @@ impl AssistantConfiguration {
|
||||
fn render_provider_configuration(
|
||||
&mut self,
|
||||
provider: &Arc<dyn LanguageModelProvider>,
|
||||
cx: &mut Context<Self>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> impl IntoElement {
|
||||
let provider_id = provider.id().0.clone();
|
||||
let provider_name = provider.name().0.clone();
|
||||
@@ -91,47 +89,38 @@ impl AssistantConfiguration {
|
||||
.cloned();
|
||||
|
||||
v_flex()
|
||||
.gap_1p5()
|
||||
.gap_2()
|
||||
.child(
|
||||
h_flex()
|
||||
.justify_between()
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_2()
|
||||
.child(
|
||||
Icon::new(provider.icon())
|
||||
.size(IconSize::Small)
|
||||
.color(Color::Muted),
|
||||
)
|
||||
.child(Label::new(provider_name.clone())),
|
||||
)
|
||||
.child(Headline::new(provider_name.clone()).size(HeadlineSize::Small))
|
||||
.when(provider.is_authenticated(cx), |parent| {
|
||||
parent.child(
|
||||
Button::new(
|
||||
SharedString::from(format!("new-thread-{provider_id}")),
|
||||
"Start New Thread",
|
||||
)
|
||||
.icon_position(IconPosition::Start)
|
||||
.icon(IconName::Plus)
|
||||
.icon_size(IconSize::Small)
|
||||
.style(ButtonStyle::Filled)
|
||||
.layer(ElevationIndex::ModalSurface)
|
||||
.label_size(LabelSize::Small)
|
||||
.on_click(cx.listener({
|
||||
let provider = provider.clone();
|
||||
move |_this, _event, _window, cx| {
|
||||
cx.emit(AssistantConfigurationEvent::NewThread(
|
||||
provider.clone(),
|
||||
))
|
||||
}
|
||||
})),
|
||||
h_flex().justify_end().child(
|
||||
Button::new(
|
||||
SharedString::from(format!("new-thread-{provider_id}")),
|
||||
"Open New Thread",
|
||||
)
|
||||
.icon_position(IconPosition::Start)
|
||||
.icon(IconName::Plus)
|
||||
.style(ButtonStyle::Filled)
|
||||
.layer(ElevationIndex::ModalSurface)
|
||||
.on_click(cx.listener({
|
||||
let provider = provider.clone();
|
||||
move |_this, _event, cx| {
|
||||
cx.emit(AssistantConfigurationEvent::NewThread(
|
||||
provider.clone(),
|
||||
))
|
||||
}
|
||||
})),
|
||||
),
|
||||
)
|
||||
}),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.p(DynamicSpacing::Base08.rems(cx))
|
||||
.bg(cx.theme().colors().editor_background)
|
||||
.bg(cx.theme().colors().surface_background)
|
||||
.border_1()
|
||||
.border_color(cx.theme().colors().border_variant)
|
||||
.rounded_md()
|
||||
@@ -146,49 +135,34 @@ impl AssistantConfiguration {
|
||||
}
|
||||
|
||||
impl Render for AssistantConfiguration {
|
||||
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
let providers = LanguageModelRegistry::read_global(cx).providers();
|
||||
|
||||
v_flex()
|
||||
.id("assistant-configuration")
|
||||
.track_focus(&self.focus_handle(cx))
|
||||
.bg(cx.theme().colors().panel_background)
|
||||
.bg(cx.theme().colors().editor_background)
|
||||
.size_full()
|
||||
.overflow_y_scroll()
|
||||
.child(
|
||||
v_flex()
|
||||
.p(DynamicSpacing::Base16.rems(cx))
|
||||
.gap_1()
|
||||
.child(Headline::new("Prompt Library").size(HeadlineSize::Small))
|
||||
.child(
|
||||
Button::new("open-prompt-library", "Open Prompt Library")
|
||||
.style(ButtonStyle::Filled)
|
||||
.layer(ElevationIndex::ModalSurface)
|
||||
.full_width()
|
||||
.icon(IconName::Book)
|
||||
.icon_size(IconSize::Small)
|
||||
.icon_position(IconPosition::Start)
|
||||
.on_click(|_event, _window, cx| {
|
||||
cx.dispatch_action(&DeployPromptLibrary)
|
||||
}),
|
||||
),
|
||||
h_flex().p(DynamicSpacing::Base16.rems(cx)).child(
|
||||
Button::new("open-prompt-library", "Open Prompt Library")
|
||||
.style(ButtonStyle::Filled)
|
||||
.full_width()
|
||||
.icon(IconName::Book)
|
||||
.icon_size(IconSize::Small)
|
||||
.icon_position(IconPosition::Start)
|
||||
.on_click(|_event, cx| {
|
||||
cx.dispatch_action(DeployPromptLibrary.boxed_clone())
|
||||
}),
|
||||
),
|
||||
)
|
||||
.child(Divider::horizontal().color(DividerColor::Border))
|
||||
.child(
|
||||
v_flex()
|
||||
.p(DynamicSpacing::Base16.rems(cx))
|
||||
.mt_1()
|
||||
.gap_6()
|
||||
.flex_1()
|
||||
.child(
|
||||
v_flex()
|
||||
.gap_0p5()
|
||||
.child(Headline::new("LLM Providers").size(HeadlineSize::Small))
|
||||
.child(
|
||||
Label::new("Add at least one provider to use AI-powered features.")
|
||||
.color(Color::Muted),
|
||||
),
|
||||
)
|
||||
.children(
|
||||
providers
|
||||
.into_iter()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use assistant_settings::AssistantSettings;
|
||||
use fs::Fs;
|
||||
use gpui::{Entity, FocusHandle, SharedString};
|
||||
use gpui::{FocusHandle, View};
|
||||
use language_model::LanguageModelRegistry;
|
||||
use language_model_selector::{LanguageModelSelector, LanguageModelSelectorPopoverMenu};
|
||||
use settings::update_settings_file;
|
||||
@@ -10,7 +10,7 @@ use ui::{prelude::*, ButtonLike, PopoverMenuHandle, Tooltip};
|
||||
use crate::ToggleModelSelector;
|
||||
|
||||
pub struct AssistantModelSelector {
|
||||
selector: Entity<LanguageModelSelector>,
|
||||
selector: View<LanguageModelSelector>,
|
||||
menu_handle: PopoverMenuHandle<LanguageModelSelector>,
|
||||
focus_handle: FocusHandle,
|
||||
}
|
||||
@@ -20,11 +20,10 @@ impl AssistantModelSelector {
|
||||
fs: Arc<dyn Fs>,
|
||||
menu_handle: PopoverMenuHandle<LanguageModelSelector>,
|
||||
focus_handle: FocusHandle,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
cx: &mut WindowContext,
|
||||
) -> Self {
|
||||
Self {
|
||||
selector: cx.new(|cx| {
|
||||
selector: cx.new_view(|cx| {
|
||||
let fs = fs.clone();
|
||||
LanguageModelSelector::new(
|
||||
move |model, cx| {
|
||||
@@ -34,7 +33,6 @@ impl AssistantModelSelector {
|
||||
move |settings, _cx| settings.set_model(model.clone()),
|
||||
);
|
||||
},
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
}),
|
||||
@@ -45,13 +43,9 @@ impl AssistantModelSelector {
|
||||
}
|
||||
|
||||
impl Render for AssistantModelSelector {
|
||||
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
let active_model = LanguageModelRegistry::read_global(cx).active_model();
|
||||
let focus_handle = self.focus_handle.clone();
|
||||
let model_name = match active_model {
|
||||
Some(model) => model.name().0,
|
||||
_ => SharedString::from("No model selected"),
|
||||
};
|
||||
|
||||
LanguageModelSelectorPopoverMenu::new(
|
||||
self.selector.clone(),
|
||||
@@ -61,26 +55,33 @@ impl Render for AssistantModelSelector {
|
||||
h_flex()
|
||||
.gap_0p5()
|
||||
.child(
|
||||
Label::new(model_name)
|
||||
.size(LabelSize::Small)
|
||||
.color(Color::Muted),
|
||||
div()
|
||||
.overflow_x_hidden()
|
||||
.flex_grow()
|
||||
.whitespace_nowrap()
|
||||
.child(match active_model {
|
||||
Some(model) => h_flex()
|
||||
.child(
|
||||
Label::new(model.name().0)
|
||||
.size(LabelSize::Small)
|
||||
.color(Color::Muted),
|
||||
)
|
||||
.into_any_element(),
|
||||
_ => Label::new("No model selected")
|
||||
.size(LabelSize::Small)
|
||||
.color(Color::Muted)
|
||||
.into_any_element(),
|
||||
}),
|
||||
)
|
||||
.child(
|
||||
Icon::new(IconName::ChevronDown)
|
||||
.color(Color::Muted)
|
||||
.size(IconSize::XSmall),
|
||||
),
|
||||
),
|
||||
move |window, cx| {
|
||||
Tooltip::for_action_in(
|
||||
"Change Model",
|
||||
&ToggleModelSelector,
|
||||
&focus_handle,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
},
|
||||
gpui::Corner::BottomRight,
|
||||
.tooltip(move |cx| {
|
||||
Tooltip::for_action_in("Change Model", &ToggleModelSelector, &focus_handle, cx)
|
||||
}),
|
||||
)
|
||||
.with_handle(self.menu_handle.clone())
|
||||
}
|
||||
|
||||
@@ -6,12 +6,13 @@ use client::telemetry::Telemetry;
|
||||
use collections::HashSet;
|
||||
use editor::{Anchor, AnchorRangeExt, MultiBuffer, MultiBufferSnapshot, ToOffset as _, ToPoint};
|
||||
use futures::{channel::mpsc, future::LocalBoxFuture, join, SinkExt, Stream, StreamExt};
|
||||
use gpui::{App, AppContext as _, Context, Entity, EventEmitter, Subscription, Task};
|
||||
use language::{line_diff, Buffer, IndentKind, Point, TransactionId};
|
||||
use gpui::{AppContext, Context as _, EventEmitter, Model, ModelContext, Subscription, Task};
|
||||
use language::{Buffer, IndentKind, Point, TransactionId};
|
||||
use language_model::{
|
||||
report_assistant_event, LanguageModel, LanguageModelRegistry, LanguageModelRequest,
|
||||
LanguageModelRequestMessage, LanguageModelTextStream, Role,
|
||||
LanguageModel, LanguageModelRegistry, LanguageModelRequest, LanguageModelRequestMessage,
|
||||
LanguageModelTextStream, Role,
|
||||
};
|
||||
use language_models::report_assistant_event;
|
||||
use multi_buffer::MultiBufferRow;
|
||||
use parking_lot::Mutex;
|
||||
use prompt_library::PromptBuilder;
|
||||
@@ -31,14 +32,14 @@ use streaming_diff::{CharOperation, LineDiff, LineOperation, StreamingDiff};
|
||||
use telemetry_events::{AssistantEvent, AssistantKind, AssistantPhase};
|
||||
|
||||
pub struct BufferCodegen {
|
||||
alternatives: Vec<Entity<CodegenAlternative>>,
|
||||
alternatives: Vec<Model<CodegenAlternative>>,
|
||||
pub active_alternative: usize,
|
||||
seen_alternatives: HashSet<usize>,
|
||||
subscriptions: Vec<Subscription>,
|
||||
buffer: Entity<MultiBuffer>,
|
||||
buffer: Model<MultiBuffer>,
|
||||
range: Range<Anchor>,
|
||||
initial_transaction_id: Option<TransactionId>,
|
||||
context_store: Entity<ContextStore>,
|
||||
context_store: Model<ContextStore>,
|
||||
telemetry: Arc<Telemetry>,
|
||||
builder: Arc<PromptBuilder>,
|
||||
pub is_insertion: bool,
|
||||
@@ -46,15 +47,15 @@ pub struct BufferCodegen {
|
||||
|
||||
impl BufferCodegen {
|
||||
pub fn new(
|
||||
buffer: Entity<MultiBuffer>,
|
||||
buffer: Model<MultiBuffer>,
|
||||
range: Range<Anchor>,
|
||||
initial_transaction_id: Option<TransactionId>,
|
||||
context_store: Entity<ContextStore>,
|
||||
context_store: Model<ContextStore>,
|
||||
telemetry: Arc<Telemetry>,
|
||||
builder: Arc<PromptBuilder>,
|
||||
cx: &mut Context<Self>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> Self {
|
||||
let codegen = cx.new(|cx| {
|
||||
let codegen = cx.new_model(|cx| {
|
||||
CodegenAlternative::new(
|
||||
buffer.clone(),
|
||||
range.clone(),
|
||||
@@ -82,7 +83,7 @@ impl BufferCodegen {
|
||||
this
|
||||
}
|
||||
|
||||
fn subscribe_to_alternative(&mut self, cx: &mut Context<Self>) {
|
||||
fn subscribe_to_alternative(&mut self, cx: &mut ModelContext<Self>) {
|
||||
let codegen = self.active_alternative().clone();
|
||||
self.subscriptions.clear();
|
||||
self.subscriptions
|
||||
@@ -91,22 +92,22 @@ impl BufferCodegen {
|
||||
.push(cx.subscribe(&codegen, |_, _, event, cx| cx.emit(*event)));
|
||||
}
|
||||
|
||||
pub fn active_alternative(&self) -> &Entity<CodegenAlternative> {
|
||||
pub fn active_alternative(&self) -> &Model<CodegenAlternative> {
|
||||
&self.alternatives[self.active_alternative]
|
||||
}
|
||||
|
||||
pub fn status<'a>(&self, cx: &'a App) -> &'a CodegenStatus {
|
||||
pub fn status<'a>(&self, cx: &'a AppContext) -> &'a CodegenStatus {
|
||||
&self.active_alternative().read(cx).status
|
||||
}
|
||||
|
||||
pub fn alternative_count(&self, cx: &App) -> usize {
|
||||
pub fn alternative_count(&self, cx: &AppContext) -> usize {
|
||||
LanguageModelRegistry::read_global(cx)
|
||||
.inline_alternative_models()
|
||||
.len()
|
||||
+ 1
|
||||
}
|
||||
|
||||
pub fn cycle_prev(&mut self, cx: &mut Context<Self>) {
|
||||
pub fn cycle_prev(&mut self, cx: &mut ModelContext<Self>) {
|
||||
let next_active_ix = if self.active_alternative == 0 {
|
||||
self.alternatives.len() - 1
|
||||
} else {
|
||||
@@ -115,12 +116,12 @@ impl BufferCodegen {
|
||||
self.activate(next_active_ix, cx);
|
||||
}
|
||||
|
||||
pub fn cycle_next(&mut self, cx: &mut Context<Self>) {
|
||||
pub fn cycle_next(&mut self, cx: &mut ModelContext<Self>) {
|
||||
let next_active_ix = (self.active_alternative + 1) % self.alternatives.len();
|
||||
self.activate(next_active_ix, cx);
|
||||
}
|
||||
|
||||
fn activate(&mut self, index: usize, cx: &mut Context<Self>) {
|
||||
fn activate(&mut self, index: usize, cx: &mut ModelContext<Self>) {
|
||||
self.active_alternative()
|
||||
.update(cx, |codegen, cx| codegen.set_active(false, cx));
|
||||
self.seen_alternatives.insert(index);
|
||||
@@ -131,7 +132,7 @@ impl BufferCodegen {
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
pub fn start(&mut self, user_prompt: String, cx: &mut Context<Self>) -> Result<()> {
|
||||
pub fn start(&mut self, user_prompt: String, cx: &mut ModelContext<Self>) -> Result<()> {
|
||||
let alternative_models = LanguageModelRegistry::read_global(cx)
|
||||
.inline_alternative_models()
|
||||
.to_vec();
|
||||
@@ -142,7 +143,7 @@ impl BufferCodegen {
|
||||
self.alternatives.truncate(1);
|
||||
|
||||
for _ in 0..alternative_models.len() {
|
||||
self.alternatives.push(cx.new(|cx| {
|
||||
self.alternatives.push(cx.new_model(|cx| {
|
||||
CodegenAlternative::new(
|
||||
self.buffer.clone(),
|
||||
self.range.clone(),
|
||||
@@ -171,13 +172,13 @@ impl BufferCodegen {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn stop(&mut self, cx: &mut Context<Self>) {
|
||||
pub fn stop(&mut self, cx: &mut ModelContext<Self>) {
|
||||
for codegen in &self.alternatives {
|
||||
codegen.update(cx, |codegen, cx| codegen.stop(cx));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn undo(&mut self, cx: &mut Context<Self>) {
|
||||
pub fn undo(&mut self, cx: &mut ModelContext<Self>) {
|
||||
self.active_alternative()
|
||||
.update(cx, |codegen, cx| codegen.undo(cx));
|
||||
|
||||
@@ -189,27 +190,27 @@ impl BufferCodegen {
|
||||
});
|
||||
}
|
||||
|
||||
pub fn buffer(&self, cx: &App) -> Entity<MultiBuffer> {
|
||||
pub fn buffer(&self, cx: &AppContext) -> Model<MultiBuffer> {
|
||||
self.active_alternative().read(cx).buffer.clone()
|
||||
}
|
||||
|
||||
pub fn old_buffer(&self, cx: &App) -> Entity<Buffer> {
|
||||
pub fn old_buffer(&self, cx: &AppContext) -> Model<Buffer> {
|
||||
self.active_alternative().read(cx).old_buffer.clone()
|
||||
}
|
||||
|
||||
pub fn snapshot(&self, cx: &App) -> MultiBufferSnapshot {
|
||||
pub fn snapshot(&self, cx: &AppContext) -> MultiBufferSnapshot {
|
||||
self.active_alternative().read(cx).snapshot.clone()
|
||||
}
|
||||
|
||||
pub fn edit_position(&self, cx: &App) -> Option<Anchor> {
|
||||
pub fn edit_position(&self, cx: &AppContext) -> Option<Anchor> {
|
||||
self.active_alternative().read(cx).edit_position
|
||||
}
|
||||
|
||||
pub fn diff<'a>(&self, cx: &'a App) -> &'a Diff {
|
||||
pub fn diff<'a>(&self, cx: &'a AppContext) -> &'a Diff {
|
||||
&self.active_alternative().read(cx).diff
|
||||
}
|
||||
|
||||
pub fn last_equal_ranges<'a>(&self, cx: &'a App) -> &'a [Range<Anchor>] {
|
||||
pub fn last_equal_ranges<'a>(&self, cx: &'a AppContext) -> &'a [Range<Anchor>] {
|
||||
self.active_alternative().read(cx).last_equal_ranges()
|
||||
}
|
||||
}
|
||||
@@ -217,8 +218,8 @@ impl BufferCodegen {
|
||||
impl EventEmitter<CodegenEvent> for BufferCodegen {}
|
||||
|
||||
pub struct CodegenAlternative {
|
||||
buffer: Entity<MultiBuffer>,
|
||||
old_buffer: Entity<Buffer>,
|
||||
buffer: Model<MultiBuffer>,
|
||||
old_buffer: Model<Buffer>,
|
||||
snapshot: MultiBufferSnapshot,
|
||||
edit_position: Option<Anchor>,
|
||||
range: Range<Anchor>,
|
||||
@@ -227,7 +228,7 @@ pub struct CodegenAlternative {
|
||||
status: CodegenStatus,
|
||||
generation: Task<()>,
|
||||
diff: Diff,
|
||||
context_store: Option<Entity<ContextStore>>,
|
||||
context_store: Option<Model<ContextStore>>,
|
||||
telemetry: Option<Arc<Telemetry>>,
|
||||
_subscription: gpui::Subscription,
|
||||
builder: Arc<PromptBuilder>,
|
||||
@@ -244,27 +245,27 @@ impl EventEmitter<CodegenEvent> for CodegenAlternative {}
|
||||
|
||||
impl CodegenAlternative {
|
||||
pub fn new(
|
||||
buffer: Entity<MultiBuffer>,
|
||||
buffer: Model<MultiBuffer>,
|
||||
range: Range<Anchor>,
|
||||
active: bool,
|
||||
context_store: Option<Entity<ContextStore>>,
|
||||
context_store: Option<Model<ContextStore>>,
|
||||
telemetry: Option<Arc<Telemetry>>,
|
||||
builder: Arc<PromptBuilder>,
|
||||
cx: &mut Context<Self>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> Self {
|
||||
let snapshot = buffer.read(cx).snapshot(cx);
|
||||
|
||||
let (old_buffer, _, _) = snapshot
|
||||
let (old_excerpt, _) = snapshot
|
||||
.range_to_buffer_ranges(range.clone())
|
||||
.pop()
|
||||
.unwrap();
|
||||
let old_buffer = cx.new(|cx| {
|
||||
let text = old_buffer.as_rope().clone();
|
||||
let line_ending = old_buffer.line_ending();
|
||||
let language = old_buffer.language().cloned();
|
||||
let old_buffer = cx.new_model(|cx| {
|
||||
let text = old_excerpt.buffer().as_rope().clone();
|
||||
let line_ending = old_excerpt.buffer().line_ending();
|
||||
let language = old_excerpt.buffer().language().cloned();
|
||||
let language_registry = buffer
|
||||
.read(cx)
|
||||
.buffer(old_buffer.remote_id())
|
||||
.buffer(old_excerpt.buffer_id())
|
||||
.unwrap()
|
||||
.read(cx)
|
||||
.language_registry();
|
||||
@@ -302,7 +303,7 @@ impl CodegenAlternative {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_active(&mut self, active: bool, cx: &mut Context<Self>) {
|
||||
pub fn set_active(&mut self, active: bool, cx: &mut ModelContext<Self>) {
|
||||
if active != self.active {
|
||||
self.active = active;
|
||||
|
||||
@@ -326,9 +327,9 @@ impl CodegenAlternative {
|
||||
|
||||
fn handle_buffer_event(
|
||||
&mut self,
|
||||
_buffer: Entity<MultiBuffer>,
|
||||
_buffer: Model<MultiBuffer>,
|
||||
event: &multi_buffer::Event,
|
||||
cx: &mut Context<Self>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) {
|
||||
if let multi_buffer::Event::TransactionUndone { transaction_id } = event {
|
||||
if self.transformation_transaction_id == Some(*transaction_id) {
|
||||
@@ -347,7 +348,7 @@ impl CodegenAlternative {
|
||||
&mut self,
|
||||
user_prompt: String,
|
||||
model: Arc<dyn LanguageModel>,
|
||||
cx: &mut Context<Self>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> Result<()> {
|
||||
if let Some(transformation_transaction_id) = self.transformation_transaction_id.take() {
|
||||
self.buffer.update(cx, |buffer, cx| {
|
||||
@@ -374,7 +375,11 @@ impl CodegenAlternative {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn build_request(&self, user_prompt: String, cx: &mut App) -> Result<LanguageModelRequest> {
|
||||
fn build_request(
|
||||
&self,
|
||||
user_prompt: String,
|
||||
cx: &mut AppContext,
|
||||
) -> Result<LanguageModelRequest> {
|
||||
let buffer = self.buffer.read(cx).snapshot(cx);
|
||||
let language = buffer.language_at(self.range.start);
|
||||
let language_name = if let Some(language) = language.as_ref() {
|
||||
@@ -433,7 +438,7 @@ impl CodegenAlternative {
|
||||
model_provider_id: String,
|
||||
model_api_key: Option<String>,
|
||||
stream: impl 'static + Future<Output = Result<LanguageModelTextStream>>,
|
||||
cx: &mut Context<Self>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) {
|
||||
let start_time = Instant::now();
|
||||
let snapshot = self.snapshot.clone();
|
||||
@@ -470,7 +475,7 @@ impl CodegenAlternative {
|
||||
let ranges = snapshot.range_to_buffer_ranges(self.range.clone());
|
||||
ranges
|
||||
.first()
|
||||
.and_then(|(buffer, _, _)| buffer.language())
|
||||
.and_then(|(excerpt, _)| excerpt.buffer().language())
|
||||
.map(|language| language.name())
|
||||
};
|
||||
|
||||
@@ -492,7 +497,7 @@ impl CodegenAlternative {
|
||||
let executor = cx.background_executor().clone();
|
||||
let message_id = message_id.clone();
|
||||
let line_based_stream_diff: Task<anyhow::Result<()>> =
|
||||
cx.background_spawn(async move {
|
||||
cx.background_executor().spawn(async move {
|
||||
let mut response_latency = None;
|
||||
let request_start = Instant::now();
|
||||
let diff = async {
|
||||
@@ -691,7 +696,7 @@ impl CodegenAlternative {
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
pub fn stop(&mut self, cx: &mut Context<Self>) {
|
||||
pub fn stop(&mut self, cx: &mut ModelContext<Self>) {
|
||||
self.last_equal_ranges.clear();
|
||||
if self.diff.is_empty() {
|
||||
self.status = CodegenStatus::Idle;
|
||||
@@ -703,7 +708,7 @@ impl CodegenAlternative {
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
pub fn undo(&mut self, cx: &mut Context<Self>) {
|
||||
pub fn undo(&mut self, cx: &mut ModelContext<Self>) {
|
||||
self.buffer.update(cx, |buffer, cx| {
|
||||
if let Some(transaction_id) = self.transformation_transaction_id.take() {
|
||||
buffer.undo_transaction(transaction_id, cx);
|
||||
@@ -715,7 +720,7 @@ impl CodegenAlternative {
|
||||
fn apply_edits(
|
||||
&mut self,
|
||||
edits: impl IntoIterator<Item = (Range<Anchor>, String)>,
|
||||
cx: &mut Context<CodegenAlternative>,
|
||||
cx: &mut ModelContext<CodegenAlternative>,
|
||||
) {
|
||||
let transaction = self.buffer.update(cx, |buffer, cx| {
|
||||
// Avoid grouping assistant edits with user edits.
|
||||
@@ -742,7 +747,7 @@ impl CodegenAlternative {
|
||||
fn reapply_line_based_diff(
|
||||
&mut self,
|
||||
line_operations: impl IntoIterator<Item = LineOperation>,
|
||||
cx: &mut Context<Self>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) {
|
||||
let old_snapshot = self.snapshot.clone();
|
||||
let old_range = self.range.to_point(&old_snapshot);
|
||||
@@ -798,7 +803,7 @@ impl CodegenAlternative {
|
||||
}
|
||||
}
|
||||
|
||||
fn reapply_batch_diff(&mut self, cx: &mut Context<Self>) -> Task<()> {
|
||||
fn reapply_batch_diff(&mut self, cx: &mut ModelContext<Self>) -> Task<()> {
|
||||
let old_snapshot = self.snapshot.clone();
|
||||
let old_range = self.range.to_point(&old_snapshot);
|
||||
let new_snapshot = self.buffer.read(cx).snapshot(cx);
|
||||
@@ -806,7 +811,8 @@ impl CodegenAlternative {
|
||||
|
||||
cx.spawn(|codegen, mut cx| async move {
|
||||
let (deleted_row_ranges, inserted_row_ranges) = cx
|
||||
.background_spawn(async move {
|
||||
.background_executor()
|
||||
.spawn(async move {
|
||||
let old_text = old_snapshot
|
||||
.text_for_range(
|
||||
Point::new(old_range.start.row, 0)
|
||||
@@ -826,29 +832,52 @@ impl CodegenAlternative {
|
||||
)
|
||||
.collect::<String>();
|
||||
|
||||
let old_start_row = old_range.start.row;
|
||||
let new_start_row = new_range.start.row;
|
||||
let mut old_row = old_range.start.row;
|
||||
let mut new_row = new_range.start.row;
|
||||
let batch_diff =
|
||||
similar::TextDiff::from_lines(old_text.as_str(), new_text.as_str());
|
||||
|
||||
let mut deleted_row_ranges: Vec<(Anchor, RangeInclusive<u32>)> = Vec::new();
|
||||
let mut inserted_row_ranges = Vec::new();
|
||||
for (old_rows, new_rows) in line_diff(&old_text, &new_text) {
|
||||
let old_rows = old_start_row + old_rows.start..old_start_row + old_rows.end;
|
||||
let new_rows = new_start_row + new_rows.start..new_start_row + new_rows.end;
|
||||
if !old_rows.is_empty() {
|
||||
deleted_row_ranges.push((
|
||||
new_snapshot.anchor_before(Point::new(new_rows.start, 0)),
|
||||
old_rows.start..=old_rows.end - 1,
|
||||
));
|
||||
}
|
||||
if !new_rows.is_empty() {
|
||||
let start = new_snapshot.anchor_before(Point::new(new_rows.start, 0));
|
||||
let new_end_row = new_rows.end - 1;
|
||||
let end = new_snapshot.anchor_before(Point::new(
|
||||
new_end_row,
|
||||
new_snapshot.line_len(MultiBufferRow(new_end_row)),
|
||||
));
|
||||
inserted_row_ranges.push(start..end);
|
||||
for change in batch_diff.iter_all_changes() {
|
||||
let line_count = change.value().lines().count() as u32;
|
||||
match change.tag() {
|
||||
similar::ChangeTag::Equal => {
|
||||
old_row += line_count;
|
||||
new_row += line_count;
|
||||
}
|
||||
similar::ChangeTag::Delete => {
|
||||
let old_end_row = old_row + line_count - 1;
|
||||
let new_row = new_snapshot.anchor_before(Point::new(new_row, 0));
|
||||
|
||||
if let Some((_, last_deleted_row_range)) =
|
||||
deleted_row_ranges.last_mut()
|
||||
{
|
||||
if *last_deleted_row_range.end() + 1 == old_row {
|
||||
*last_deleted_row_range =
|
||||
*last_deleted_row_range.start()..=old_end_row;
|
||||
} else {
|
||||
deleted_row_ranges.push((new_row, old_row..=old_end_row));
|
||||
}
|
||||
} else {
|
||||
deleted_row_ranges.push((new_row, old_row..=old_end_row));
|
||||
}
|
||||
|
||||
old_row += line_count;
|
||||
}
|
||||
similar::ChangeTag::Insert => {
|
||||
let new_end_row = new_row + line_count - 1;
|
||||
let start = new_snapshot.anchor_before(Point::new(new_row, 0));
|
||||
let end = new_snapshot.anchor_before(Point::new(
|
||||
new_end_row,
|
||||
new_snapshot.line_len(MultiBufferRow(new_end_row)),
|
||||
));
|
||||
inserted_row_ranges.push(start..end);
|
||||
new_row += line_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(deleted_row_ranges, inserted_row_ranges)
|
||||
})
|
||||
.await;
|
||||
@@ -1052,14 +1081,15 @@ mod tests {
|
||||
}
|
||||
}
|
||||
"};
|
||||
let buffer = cx.new(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
|
||||
let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
|
||||
let buffer =
|
||||
cx.new_model(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
|
||||
let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
|
||||
let range = buffer.read_with(cx, |buffer, cx| {
|
||||
let snapshot = buffer.snapshot(cx);
|
||||
snapshot.anchor_before(Point::new(1, 0))..snapshot.anchor_after(Point::new(4, 5))
|
||||
});
|
||||
let prompt_builder = Arc::new(PromptBuilder::new(None).unwrap());
|
||||
let codegen = cx.new(|cx| {
|
||||
let codegen = cx.new_model(|cx| {
|
||||
CodegenAlternative::new(
|
||||
buffer.clone(),
|
||||
range.clone(),
|
||||
@@ -1116,14 +1146,15 @@ mod tests {
|
||||
le
|
||||
}
|
||||
"};
|
||||
let buffer = cx.new(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
|
||||
let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
|
||||
let buffer =
|
||||
cx.new_model(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
|
||||
let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
|
||||
let range = buffer.read_with(cx, |buffer, cx| {
|
||||
let snapshot = buffer.snapshot(cx);
|
||||
snapshot.anchor_before(Point::new(1, 6))..snapshot.anchor_after(Point::new(1, 6))
|
||||
});
|
||||
let prompt_builder = Arc::new(PromptBuilder::new(None).unwrap());
|
||||
let codegen = cx.new(|cx| {
|
||||
let codegen = cx.new_model(|cx| {
|
||||
CodegenAlternative::new(
|
||||
buffer.clone(),
|
||||
range.clone(),
|
||||
@@ -1183,14 +1214,15 @@ mod tests {
|
||||
" \n",
|
||||
"}\n" //
|
||||
);
|
||||
let buffer = cx.new(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
|
||||
let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
|
||||
let buffer =
|
||||
cx.new_model(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
|
||||
let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
|
||||
let range = buffer.read_with(cx, |buffer, cx| {
|
||||
let snapshot = buffer.snapshot(cx);
|
||||
snapshot.anchor_before(Point::new(1, 2))..snapshot.anchor_after(Point::new(1, 2))
|
||||
});
|
||||
let prompt_builder = Arc::new(PromptBuilder::new(None).unwrap());
|
||||
let codegen = cx.new(|cx| {
|
||||
let codegen = cx.new_model(|cx| {
|
||||
CodegenAlternative::new(
|
||||
buffer.clone(),
|
||||
range.clone(),
|
||||
@@ -1250,14 +1282,14 @@ mod tests {
|
||||
\t}
|
||||
}
|
||||
"};
|
||||
let buffer = cx.new(|cx| Buffer::local(text, cx));
|
||||
let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
|
||||
let buffer = cx.new_model(|cx| Buffer::local(text, cx));
|
||||
let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
|
||||
let range = buffer.read_with(cx, |buffer, cx| {
|
||||
let snapshot = buffer.snapshot(cx);
|
||||
snapshot.anchor_before(Point::new(0, 0))..snapshot.anchor_after(Point::new(4, 2))
|
||||
});
|
||||
let prompt_builder = Arc::new(PromptBuilder::new(None).unwrap());
|
||||
let codegen = cx.new(|cx| {
|
||||
let codegen = cx.new_model(|cx| {
|
||||
CodegenAlternative::new(
|
||||
buffer.clone(),
|
||||
range.clone(),
|
||||
@@ -1305,14 +1337,15 @@ mod tests {
|
||||
let x = 0;
|
||||
}
|
||||
"};
|
||||
let buffer = cx.new(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
|
||||
let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
|
||||
let buffer =
|
||||
cx.new_model(|cx| Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx));
|
||||
let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
|
||||
let range = buffer.read_with(cx, |buffer, cx| {
|
||||
let snapshot = buffer.snapshot(cx);
|
||||
snapshot.anchor_before(Point::new(1, 0))..snapshot.anchor_after(Point::new(1, 14))
|
||||
});
|
||||
let prompt_builder = Arc::new(PromptBuilder::new(None).unwrap());
|
||||
let codegen = cx.new(|cx| {
|
||||
let codegen = cx.new_model(|cx| {
|
||||
CodegenAlternative::new(
|
||||
buffer.clone(),
|
||||
range.clone(),
|
||||
@@ -1399,7 +1432,7 @@ mod tests {
|
||||
}
|
||||
|
||||
fn simulate_response_stream(
|
||||
codegen: Entity<CodegenAlternative>,
|
||||
codegen: Model<CodegenAlternative>,
|
||||
cx: &mut TestAppContext,
|
||||
) -> mpsc::UnboundedSender<String> {
|
||||
let (chunks_tx, chunks_rx) = mpsc::unbounded();
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::path::Path;
|
||||
use std::rc::Rc;
|
||||
|
||||
use file_icons::FileIcons;
|
||||
use gpui::{App, Entity, SharedString};
|
||||
use gpui::{AppContext, Model, SharedString};
|
||||
use language::Buffer;
|
||||
use language_model::{LanguageModelRequestMessage, MessageContent};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -63,14 +63,14 @@ impl ContextKind {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum AssistantContext {
|
||||
pub enum Context {
|
||||
File(FileContext),
|
||||
Directory(DirectoryContext),
|
||||
FetchedUrl(FetchedUrlContext),
|
||||
Thread(ThreadContext),
|
||||
}
|
||||
|
||||
impl AssistantContext {
|
||||
impl Context {
|
||||
pub fn id(&self) -> ContextId {
|
||||
match self {
|
||||
Self::File(file) => file.id,
|
||||
@@ -107,7 +107,7 @@ pub struct FetchedUrlContext {
|
||||
#[derive(Debug)]
|
||||
pub struct ThreadContext {
|
||||
pub id: ContextId,
|
||||
pub thread: Entity<Thread>,
|
||||
pub thread: Model<Thread>,
|
||||
pub text: SharedString,
|
||||
}
|
||||
|
||||
@@ -117,13 +117,13 @@ pub struct ThreadContext {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ContextBuffer {
|
||||
pub id: BufferId,
|
||||
pub buffer: Entity<Buffer>,
|
||||
pub buffer: Model<Buffer>,
|
||||
pub version: clock::Global,
|
||||
pub text: SharedString,
|
||||
}
|
||||
|
||||
impl AssistantContext {
|
||||
pub fn snapshot(&self, cx: &App) -> Option<ContextSnapshot> {
|
||||
impl Context {
|
||||
pub fn snapshot(&self, cx: &AppContext) -> Option<ContextSnapshot> {
|
||||
match &self {
|
||||
Self::File(file_context) => file_context.snapshot(cx),
|
||||
Self::Directory(directory_context) => Some(directory_context.snapshot()),
|
||||
@@ -134,7 +134,7 @@ impl AssistantContext {
|
||||
}
|
||||
|
||||
impl FileContext {
|
||||
pub fn snapshot(&self, cx: &App) -> Option<ContextSnapshot> {
|
||||
pub fn snapshot(&self, cx: &AppContext) -> Option<ContextSnapshot> {
|
||||
let buffer = self.context_buffer.buffer.read(cx);
|
||||
let path = buffer_path_log_err(buffer)?;
|
||||
let full_path: SharedString = path.to_string_lossy().into_owned().into();
|
||||
@@ -221,7 +221,7 @@ impl FetchedUrlContext {
|
||||
}
|
||||
|
||||
impl ThreadContext {
|
||||
pub fn snapshot(&self, cx: &App) -> ContextSnapshot {
|
||||
pub fn snapshot(&self, cx: &AppContext) -> ContextSnapshot {
|
||||
let thread = self.thread.read(cx);
|
||||
ContextSnapshot {
|
||||
id: self.id,
|
||||
|
||||
@@ -6,10 +6,11 @@ mod thread_context_picker;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use editor::Editor;
|
||||
use file_context_picker::render_file_context_entry;
|
||||
use gpui::{App, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, Task, WeakEntity};
|
||||
use gpui::{
|
||||
AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView, View, WeakModel, WeakView,
|
||||
};
|
||||
use project::ProjectPath;
|
||||
use thread_context_picker::{render_thread_context_entry, ThreadContextEntry};
|
||||
use ui::{prelude::*, ContextMenu, ContextMenuEntry, ContextMenuItem};
|
||||
@@ -32,38 +33,33 @@ pub enum ConfirmBehavior {
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
enum ContextPickerMode {
|
||||
Default(Entity<ContextMenu>),
|
||||
File(Entity<FileContextPicker>),
|
||||
Directory(Entity<DirectoryContextPicker>),
|
||||
Fetch(Entity<FetchContextPicker>),
|
||||
Thread(Entity<ThreadContextPicker>),
|
||||
Default(View<ContextMenu>),
|
||||
File(View<FileContextPicker>),
|
||||
Directory(View<DirectoryContextPicker>),
|
||||
Fetch(View<FetchContextPicker>),
|
||||
Thread(View<ThreadContextPicker>),
|
||||
}
|
||||
|
||||
pub(super) struct ContextPicker {
|
||||
mode: ContextPickerMode,
|
||||
workspace: WeakEntity<Workspace>,
|
||||
editor: WeakEntity<Editor>,
|
||||
context_store: WeakEntity<ContextStore>,
|
||||
thread_store: Option<WeakEntity<ThreadStore>>,
|
||||
workspace: WeakView<Workspace>,
|
||||
editor: WeakView<Editor>,
|
||||
context_store: WeakModel<ContextStore>,
|
||||
thread_store: Option<WeakModel<ThreadStore>>,
|
||||
confirm_behavior: ConfirmBehavior,
|
||||
}
|
||||
|
||||
impl ContextPicker {
|
||||
pub fn new(
|
||||
workspace: WeakEntity<Workspace>,
|
||||
thread_store: Option<WeakEntity<ThreadStore>>,
|
||||
context_store: WeakEntity<ContextStore>,
|
||||
editor: WeakEntity<Editor>,
|
||||
workspace: WeakView<Workspace>,
|
||||
thread_store: Option<WeakModel<ThreadStore>>,
|
||||
context_store: WeakModel<ContextStore>,
|
||||
editor: WeakView<Editor>,
|
||||
confirm_behavior: ConfirmBehavior,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Self {
|
||||
ContextPicker {
|
||||
mode: ContextPickerMode::Default(ContextMenu::build(
|
||||
window,
|
||||
cx,
|
||||
|menu, _window, _cx| menu,
|
||||
)),
|
||||
mode: ContextPickerMode::Default(ContextMenu::build(cx, |menu, _cx| menu)),
|
||||
workspace,
|
||||
context_store,
|
||||
thread_store,
|
||||
@@ -72,15 +68,15 @@ impl ContextPicker {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
self.mode = ContextPickerMode::Default(self.build_menu(window, cx));
|
||||
pub fn init(&mut self, cx: &mut ViewContext<Self>) {
|
||||
self.mode = ContextPickerMode::Default(self.build_menu(cx));
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn build_menu(&mut self, window: &mut Window, cx: &mut Context<Self>) -> Entity<ContextMenu> {
|
||||
let context_picker = cx.entity().clone();
|
||||
fn build_menu(&mut self, cx: &mut ViewContext<Self>) -> View<ContextMenu> {
|
||||
let context_picker = cx.view().clone();
|
||||
|
||||
let menu = ContextMenu::build(window, cx, move |menu, _window, cx| {
|
||||
let menu = ContextMenu::build(cx, move |menu, cx| {
|
||||
let recent = self.recent_entries(cx);
|
||||
let has_recent = !recent.is_empty();
|
||||
let recent_entries = recent
|
||||
@@ -99,7 +95,7 @@ impl ContextPicker {
|
||||
|
||||
let menu = menu
|
||||
.when(has_recent, |menu| {
|
||||
menu.custom_row(|_, _| {
|
||||
menu.custom_row(|_| {
|
||||
div()
|
||||
.mb_1()
|
||||
.child(
|
||||
@@ -117,10 +113,8 @@ impl ContextPicker {
|
||||
|
||||
ContextMenuEntry::new(kind.label())
|
||||
.icon(kind.icon())
|
||||
.icon_size(IconSize::XSmall)
|
||||
.icon_color(Color::Muted)
|
||||
.handler(move |window, cx| {
|
||||
context_picker.update(cx, |this, cx| this.select_kind(kind, window, cx))
|
||||
.handler(move |cx| {
|
||||
context_picker.update(cx, |this, cx| this.select_kind(kind, cx))
|
||||
})
|
||||
}));
|
||||
|
||||
@@ -143,56 +137,52 @@ impl ContextPicker {
|
||||
self.thread_store.is_some()
|
||||
}
|
||||
|
||||
fn select_kind(&mut self, kind: ContextKind, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let context_picker = cx.entity().downgrade();
|
||||
fn select_kind(&mut self, kind: ContextKind, cx: &mut ViewContext<Self>) {
|
||||
let context_picker = cx.view().downgrade();
|
||||
|
||||
match kind {
|
||||
ContextKind::File => {
|
||||
self.mode = ContextPickerMode::File(cx.new(|cx| {
|
||||
self.mode = ContextPickerMode::File(cx.new_view(|cx| {
|
||||
FileContextPicker::new(
|
||||
context_picker.clone(),
|
||||
self.workspace.clone(),
|
||||
self.editor.clone(),
|
||||
self.context_store.clone(),
|
||||
self.confirm_behavior,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
}));
|
||||
}
|
||||
ContextKind::Directory => {
|
||||
self.mode = ContextPickerMode::Directory(cx.new(|cx| {
|
||||
self.mode = ContextPickerMode::Directory(cx.new_view(|cx| {
|
||||
DirectoryContextPicker::new(
|
||||
context_picker.clone(),
|
||||
self.workspace.clone(),
|
||||
self.context_store.clone(),
|
||||
self.confirm_behavior,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
}));
|
||||
}
|
||||
ContextKind::FetchedUrl => {
|
||||
self.mode = ContextPickerMode::Fetch(cx.new(|cx| {
|
||||
self.mode = ContextPickerMode::Fetch(cx.new_view(|cx| {
|
||||
FetchContextPicker::new(
|
||||
context_picker.clone(),
|
||||
self.workspace.clone(),
|
||||
self.context_store.clone(),
|
||||
self.confirm_behavior,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
}));
|
||||
}
|
||||
ContextKind::Thread => {
|
||||
if let Some(thread_store) = self.thread_store.as_ref() {
|
||||
self.mode = ContextPickerMode::Thread(cx.new(|cx| {
|
||||
self.mode = ContextPickerMode::Thread(cx.new_view(|cx| {
|
||||
ThreadContextPicker::new(
|
||||
thread_store.clone(),
|
||||
context_picker.clone(),
|
||||
self.context_store.clone(),
|
||||
self.confirm_behavior,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
}));
|
||||
@@ -201,12 +191,12 @@ impl ContextPicker {
|
||||
}
|
||||
|
||||
cx.notify();
|
||||
cx.focus_self(window);
|
||||
cx.focus_self();
|
||||
}
|
||||
|
||||
fn recent_menu_item(
|
||||
&self,
|
||||
context_picker: Entity<ContextPicker>,
|
||||
context_picker: View<ContextPicker>,
|
||||
ix: usize,
|
||||
entry: RecentEntry,
|
||||
) -> ContextMenuItem {
|
||||
@@ -219,7 +209,7 @@ impl ContextPicker {
|
||||
let path = project_path.path.clone();
|
||||
|
||||
ContextMenuItem::custom_entry(
|
||||
move |_window, cx| {
|
||||
move |cx| {
|
||||
render_file_context_entry(
|
||||
ElementId::NamedInteger("ctx-recent".into(), ix),
|
||||
&path,
|
||||
@@ -229,9 +219,9 @@ impl ContextPicker {
|
||||
)
|
||||
.into_any()
|
||||
},
|
||||
move |window, cx| {
|
||||
move |cx| {
|
||||
context_picker.update(cx, |this, cx| {
|
||||
this.add_recent_file(project_path.clone(), window, cx);
|
||||
this.add_recent_file(project_path.clone(), cx);
|
||||
})
|
||||
},
|
||||
)
|
||||
@@ -241,14 +231,13 @@ impl ContextPicker {
|
||||
let view_thread = thread.clone();
|
||||
|
||||
ContextMenuItem::custom_entry(
|
||||
move |_window, cx| {
|
||||
move |cx| {
|
||||
render_thread_context_entry(&view_thread, context_store.clone(), cx)
|
||||
.into_any()
|
||||
},
|
||||
move |_window, cx| {
|
||||
move |cx| {
|
||||
context_picker.update(cx, |this, cx| {
|
||||
this.add_recent_thread(thread.clone(), cx)
|
||||
.detach_and_log_err(cx);
|
||||
this.add_recent_thread(thread.clone(), cx);
|
||||
})
|
||||
},
|
||||
)
|
||||
@@ -256,12 +245,7 @@ impl ContextPicker {
|
||||
}
|
||||
}
|
||||
|
||||
fn add_recent_file(
|
||||
&self,
|
||||
project_path: ProjectPath,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
fn add_recent_file(&self, project_path: ProjectPath, cx: &mut ViewContext<Self>) {
|
||||
let Some(context_store) = self.context_store.upgrade() else {
|
||||
return;
|
||||
};
|
||||
@@ -270,43 +254,34 @@ impl ContextPicker {
|
||||
context_store.add_file_from_path(project_path.clone(), cx)
|
||||
});
|
||||
|
||||
cx.spawn_in(window, |_, mut cx| async move {
|
||||
task.await.notify_async_err(&mut cx)
|
||||
})
|
||||
.detach();
|
||||
cx.spawn(|_, mut cx| async move { task.await.notify_async_err(&mut cx) })
|
||||
.detach();
|
||||
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn add_recent_thread(
|
||||
&self,
|
||||
thread: ThreadContextEntry,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Task<Result<()>> {
|
||||
fn add_recent_thread(&self, thread: ThreadContextEntry, cx: &mut ViewContext<Self>) {
|
||||
let Some(context_store) = self.context_store.upgrade() else {
|
||||
return Task::ready(Err(anyhow!("context store not available")));
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(thread_store) = self
|
||||
let Some(thread) = self
|
||||
.thread_store
|
||||
.as_ref()
|
||||
.and_then(|thread_store| thread_store.upgrade())
|
||||
.clone()
|
||||
.and_then(|this| this.upgrade())
|
||||
.and_then(|this| this.update(cx, |this, cx| this.open_thread(&thread.id, cx)))
|
||||
else {
|
||||
return Task::ready(Err(anyhow!("thread store not available")));
|
||||
return;
|
||||
};
|
||||
|
||||
let open_thread_task = thread_store.update(cx, |this, cx| this.open_thread(&thread.id, cx));
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
let thread = open_thread_task.await?;
|
||||
context_store.update(&mut cx, |context_store, cx| {
|
||||
context_store.add_thread(thread, cx);
|
||||
})?;
|
||||
context_store.update(cx, |context_store, cx| {
|
||||
context_store.add_thread(thread, cx);
|
||||
});
|
||||
|
||||
this.update(&mut cx, |_this, cx| cx.notify())
|
||||
})
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn recent_entries(&self, cx: &mut App) -> Vec<RecentEntry> {
|
||||
fn recent_entries(&self, cx: &mut WindowContext) -> Vec<RecentEntry> {
|
||||
let Some(workspace) = self.workspace.upgrade().map(|w| w.read(cx)) else {
|
||||
return vec![];
|
||||
};
|
||||
@@ -357,17 +332,19 @@ impl ContextPicker {
|
||||
return recent;
|
||||
};
|
||||
|
||||
thread_store.update(cx, |thread_store, _cx| {
|
||||
thread_store.update(cx, |thread_store, cx| {
|
||||
recent.extend(
|
||||
thread_store
|
||||
.threads()
|
||||
.threads(cx)
|
||||
.into_iter()
|
||||
.filter(|thread| !current_threads.contains(&thread.id))
|
||||
.filter(|thread| !current_threads.contains(thread.read(cx).id()))
|
||||
.take(2)
|
||||
.map(|thread| {
|
||||
let thread = thread.read(cx);
|
||||
|
||||
RecentEntry::Thread(ThreadContextEntry {
|
||||
id: thread.id,
|
||||
summary: thread.summary,
|
||||
id: thread.id().clone(),
|
||||
summary: thread.summary_or_default(),
|
||||
})
|
||||
}),
|
||||
)
|
||||
@@ -376,7 +353,7 @@ impl ContextPicker {
|
||||
recent
|
||||
}
|
||||
|
||||
fn active_singleton_buffer_path(workspace: &Workspace, cx: &App) -> Option<PathBuf> {
|
||||
fn active_singleton_buffer_path(workspace: &Workspace, cx: &AppContext) -> Option<PathBuf> {
|
||||
let active_item = workspace.active_item(cx)?;
|
||||
|
||||
let editor = active_item.to_any().downcast::<Editor>().ok()?.read(cx);
|
||||
@@ -389,8 +366,8 @@ impl ContextPicker {
|
||||
|
||||
impl EventEmitter<DismissEvent> for ContextPicker {}
|
||||
|
||||
impl Focusable for ContextPicker {
|
||||
fn focus_handle(&self, cx: &App) -> FocusHandle {
|
||||
impl FocusableView for ContextPicker {
|
||||
fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
|
||||
match &self.mode {
|
||||
ContextPickerMode::Default(menu) => menu.focus_handle(cx),
|
||||
ContextPickerMode::File(file_picker) => file_picker.focus_handle(cx),
|
||||
@@ -402,7 +379,7 @@ impl Focusable for ContextPicker {
|
||||
}
|
||||
|
||||
impl Render for ContextPicker {
|
||||
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
v_flex()
|
||||
.w(px(400.))
|
||||
.min_w(px(400.))
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::sync::atomic::AtomicBool;
|
||||
use std::sync::Arc;
|
||||
|
||||
use fuzzy::PathMatch;
|
||||
use gpui::{App, DismissEvent, Entity, FocusHandle, Focusable, Task, WeakEntity};
|
||||
use gpui::{AppContext, DismissEvent, FocusHandle, FocusableView, Task, View, WeakModel, WeakView};
|
||||
use picker::{Picker, PickerDelegate};
|
||||
use project::{PathMatchCandidateSet, ProjectPath, WorktreeId};
|
||||
use ui::{prelude::*, ListItem};
|
||||
@@ -14,17 +14,16 @@ use crate::context_picker::{ConfirmBehavior, ContextPicker};
|
||||
use crate::context_store::ContextStore;
|
||||
|
||||
pub struct DirectoryContextPicker {
|
||||
picker: Entity<Picker<DirectoryContextPickerDelegate>>,
|
||||
picker: View<Picker<DirectoryContextPickerDelegate>>,
|
||||
}
|
||||
|
||||
impl DirectoryContextPicker {
|
||||
pub fn new(
|
||||
context_picker: WeakEntity<ContextPicker>,
|
||||
workspace: WeakEntity<Workspace>,
|
||||
context_store: WeakEntity<ContextStore>,
|
||||
context_picker: WeakView<ContextPicker>,
|
||||
workspace: WeakView<Workspace>,
|
||||
context_store: WeakModel<ContextStore>,
|
||||
confirm_behavior: ConfirmBehavior,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Self {
|
||||
let delegate = DirectoryContextPickerDelegate::new(
|
||||
context_picker,
|
||||
@@ -32,28 +31,28 @@ impl DirectoryContextPicker {
|
||||
context_store,
|
||||
confirm_behavior,
|
||||
);
|
||||
let picker = cx.new(|cx| Picker::uniform_list(delegate, window, cx));
|
||||
let picker = cx.new_view(|cx| Picker::uniform_list(delegate, cx));
|
||||
|
||||
Self { picker }
|
||||
}
|
||||
}
|
||||
|
||||
impl Focusable for DirectoryContextPicker {
|
||||
fn focus_handle(&self, cx: &App) -> FocusHandle {
|
||||
impl FocusableView for DirectoryContextPicker {
|
||||
fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
|
||||
self.picker.focus_handle(cx)
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for DirectoryContextPicker {
|
||||
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
self.picker.clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DirectoryContextPickerDelegate {
|
||||
context_picker: WeakEntity<ContextPicker>,
|
||||
workspace: WeakEntity<Workspace>,
|
||||
context_store: WeakEntity<ContextStore>,
|
||||
context_picker: WeakView<ContextPicker>,
|
||||
workspace: WeakView<Workspace>,
|
||||
context_store: WeakModel<ContextStore>,
|
||||
confirm_behavior: ConfirmBehavior,
|
||||
matches: Vec<PathMatch>,
|
||||
selected_index: usize,
|
||||
@@ -61,9 +60,9 @@ pub struct DirectoryContextPickerDelegate {
|
||||
|
||||
impl DirectoryContextPickerDelegate {
|
||||
pub fn new(
|
||||
context_picker: WeakEntity<ContextPicker>,
|
||||
workspace: WeakEntity<Workspace>,
|
||||
context_store: WeakEntity<ContextStore>,
|
||||
context_picker: WeakView<ContextPicker>,
|
||||
workspace: WeakView<Workspace>,
|
||||
context_store: WeakModel<ContextStore>,
|
||||
confirm_behavior: ConfirmBehavior,
|
||||
) -> Self {
|
||||
Self {
|
||||
@@ -80,8 +79,8 @@ impl DirectoryContextPickerDelegate {
|
||||
&mut self,
|
||||
query: String,
|
||||
cancellation_flag: Arc<AtomicBool>,
|
||||
workspace: &Entity<Workspace>,
|
||||
cx: &mut Context<Picker<Self>>,
|
||||
workspace: &View<Workspace>,
|
||||
cx: &mut ViewContext<Picker<Self>>,
|
||||
) -> Task<Vec<PathMatch>> {
|
||||
if query.is_empty() {
|
||||
let workspace = workspace.read(cx);
|
||||
@@ -147,25 +146,15 @@ impl PickerDelegate for DirectoryContextPickerDelegate {
|
||||
self.selected_index
|
||||
}
|
||||
|
||||
fn set_selected_index(
|
||||
&mut self,
|
||||
ix: usize,
|
||||
_window: &mut Window,
|
||||
_cx: &mut Context<Picker<Self>>,
|
||||
) {
|
||||
fn set_selected_index(&mut self, ix: usize, _cx: &mut ViewContext<Picker<Self>>) {
|
||||
self.selected_index = ix;
|
||||
}
|
||||
|
||||
fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
|
||||
fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
|
||||
"Search folders…".into()
|
||||
}
|
||||
|
||||
fn update_matches(
|
||||
&mut self,
|
||||
query: String,
|
||||
_window: &mut Window,
|
||||
cx: &mut Context<Picker<Self>>,
|
||||
) -> Task<()> {
|
||||
fn update_matches(&mut self, query: String, cx: &mut ViewContext<Picker<Self>>) -> Task<()> {
|
||||
let Some(workspace) = self.workspace.upgrade() else {
|
||||
return Task::ready(());
|
||||
};
|
||||
@@ -184,7 +173,7 @@ impl PickerDelegate for DirectoryContextPickerDelegate {
|
||||
})
|
||||
}
|
||||
|
||||
fn confirm(&mut self, _secondary: bool, window: &mut Window, cx: &mut Context<Picker<Self>>) {
|
||||
fn confirm(&mut self, _secondary: bool, cx: &mut ViewContext<Picker<Self>>) {
|
||||
let Some(mat) = self.matches.get(self.selected_index) else {
|
||||
return;
|
||||
};
|
||||
@@ -205,19 +194,19 @@ impl PickerDelegate for DirectoryContextPickerDelegate {
|
||||
};
|
||||
|
||||
let confirm_behavior = self.confirm_behavior;
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
match task.await.notify_async_err(&mut cx) {
|
||||
None => anyhow::Ok(()),
|
||||
Some(()) => this.update_in(&mut cx, |this, window, cx| match confirm_behavior {
|
||||
Some(()) => this.update(&mut cx, |this, cx| match confirm_behavior {
|
||||
ConfirmBehavior::KeepOpen => {}
|
||||
ConfirmBehavior::Close => this.delegate.dismissed(window, cx),
|
||||
ConfirmBehavior::Close => this.delegate.dismissed(cx),
|
||||
}),
|
||||
}
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
}
|
||||
|
||||
fn dismissed(&mut self, _window: &mut Window, cx: &mut Context<Picker<Self>>) {
|
||||
fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {
|
||||
self.context_picker
|
||||
.update(cx, |_, cx| {
|
||||
cx.emit(DismissEvent);
|
||||
@@ -229,8 +218,7 @@ impl PickerDelegate for DirectoryContextPickerDelegate {
|
||||
&self,
|
||||
ix: usize,
|
||||
selected: bool,
|
||||
_window: &mut Window,
|
||||
cx: &mut Context<Picker<Self>>,
|
||||
cx: &mut ViewContext<Picker<Self>>,
|
||||
) -> Option<Self::ListItem> {
|
||||
let path_match = &self.matches[ix];
|
||||
let directory_name = path_match.path.to_string_lossy().to_string();
|
||||
@@ -246,12 +234,7 @@ impl PickerDelegate for DirectoryContextPickerDelegate {
|
||||
ListItem::new(ix)
|
||||
.inset(true)
|
||||
.toggle_state(selected)
|
||||
.start_slot(
|
||||
Icon::new(IconName::Folder)
|
||||
.size(IconSize::XSmall)
|
||||
.color(Color::Muted),
|
||||
)
|
||||
.child(Label::new(directory_name))
|
||||
.child(h_flex().gap_2().child(Label::new(directory_name)))
|
||||
.when(added, |el| {
|
||||
el.end_slot(
|
||||
h_flex()
|
||||
|
||||
@@ -4,28 +4,27 @@ use std::sync::Arc;
|
||||
|
||||
use anyhow::{bail, Context as _, Result};
|
||||
use futures::AsyncReadExt as _;
|
||||
use gpui::{App, DismissEvent, Entity, FocusHandle, Focusable, Task, WeakEntity};
|
||||
use gpui::{AppContext, DismissEvent, FocusHandle, FocusableView, Task, View, WeakModel, WeakView};
|
||||
use html_to_markdown::{convert_html_to_markdown, markdown, TagHandler};
|
||||
use http_client::{AsyncBody, HttpClientWithUrl};
|
||||
use picker::{Picker, PickerDelegate};
|
||||
use ui::{prelude::*, Context, ListItem, Window};
|
||||
use ui::{prelude::*, ListItem, ViewContext};
|
||||
use workspace::Workspace;
|
||||
|
||||
use crate::context_picker::{ConfirmBehavior, ContextPicker};
|
||||
use crate::context_store::ContextStore;
|
||||
|
||||
pub struct FetchContextPicker {
|
||||
picker: Entity<Picker<FetchContextPickerDelegate>>,
|
||||
picker: View<Picker<FetchContextPickerDelegate>>,
|
||||
}
|
||||
|
||||
impl FetchContextPicker {
|
||||
pub fn new(
|
||||
context_picker: WeakEntity<ContextPicker>,
|
||||
workspace: WeakEntity<Workspace>,
|
||||
context_store: WeakEntity<ContextStore>,
|
||||
context_picker: WeakView<ContextPicker>,
|
||||
workspace: WeakView<Workspace>,
|
||||
context_store: WeakModel<ContextStore>,
|
||||
confirm_behavior: ConfirmBehavior,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Self {
|
||||
let delegate = FetchContextPickerDelegate::new(
|
||||
context_picker,
|
||||
@@ -33,20 +32,20 @@ impl FetchContextPicker {
|
||||
context_store,
|
||||
confirm_behavior,
|
||||
);
|
||||
let picker = cx.new(|cx| Picker::uniform_list(delegate, window, cx));
|
||||
let picker = cx.new_view(|cx| Picker::uniform_list(delegate, cx));
|
||||
|
||||
Self { picker }
|
||||
}
|
||||
}
|
||||
|
||||
impl Focusable for FetchContextPicker {
|
||||
fn focus_handle(&self, cx: &App) -> FocusHandle {
|
||||
impl FocusableView for FetchContextPicker {
|
||||
fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
|
||||
self.picker.focus_handle(cx)
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for FetchContextPicker {
|
||||
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
self.picker.clone()
|
||||
}
|
||||
}
|
||||
@@ -59,18 +58,18 @@ enum ContentType {
|
||||
}
|
||||
|
||||
pub struct FetchContextPickerDelegate {
|
||||
context_picker: WeakEntity<ContextPicker>,
|
||||
workspace: WeakEntity<Workspace>,
|
||||
context_store: WeakEntity<ContextStore>,
|
||||
context_picker: WeakView<ContextPicker>,
|
||||
workspace: WeakView<Workspace>,
|
||||
context_store: WeakModel<ContextStore>,
|
||||
confirm_behavior: ConfirmBehavior,
|
||||
url: String,
|
||||
}
|
||||
|
||||
impl FetchContextPickerDelegate {
|
||||
pub fn new(
|
||||
context_picker: WeakEntity<ContextPicker>,
|
||||
workspace: WeakEntity<Workspace>,
|
||||
context_store: WeakEntity<ContextStore>,
|
||||
context_picker: WeakView<ContextPicker>,
|
||||
workspace: WeakView<Workspace>,
|
||||
context_store: WeakModel<ContextStore>,
|
||||
confirm_behavior: ConfirmBehavior,
|
||||
) -> Self {
|
||||
FetchContextPickerDelegate {
|
||||
@@ -167,7 +166,7 @@ impl PickerDelegate for FetchContextPickerDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
fn no_matches_text(&self, _window: &mut Window, _cx: &mut App) -> SharedString {
|
||||
fn no_matches_text(&self, _cx: &mut WindowContext) -> SharedString {
|
||||
"Enter the URL that you would like to fetch".into()
|
||||
}
|
||||
|
||||
@@ -175,30 +174,19 @@ impl PickerDelegate for FetchContextPickerDelegate {
|
||||
0
|
||||
}
|
||||
|
||||
fn set_selected_index(
|
||||
&mut self,
|
||||
_ix: usize,
|
||||
_window: &mut Window,
|
||||
_cx: &mut Context<Picker<Self>>,
|
||||
) {
|
||||
}
|
||||
fn set_selected_index(&mut self, _ix: usize, _cx: &mut ViewContext<Picker<Self>>) {}
|
||||
|
||||
fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
|
||||
fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
|
||||
"Enter a URL…".into()
|
||||
}
|
||||
|
||||
fn update_matches(
|
||||
&mut self,
|
||||
query: String,
|
||||
_window: &mut Window,
|
||||
_cx: &mut Context<Picker<Self>>,
|
||||
) -> Task<()> {
|
||||
fn update_matches(&mut self, query: String, _cx: &mut ViewContext<Picker<Self>>) -> Task<()> {
|
||||
self.url = query;
|
||||
|
||||
Task::ready(())
|
||||
}
|
||||
|
||||
fn confirm(&mut self, _secondary: bool, window: &mut Window, cx: &mut Context<Picker<Self>>) {
|
||||
fn confirm(&mut self, _secondary: bool, cx: &mut ViewContext<Picker<Self>>) {
|
||||
let Some(workspace) = self.workspace.upgrade() else {
|
||||
return;
|
||||
};
|
||||
@@ -206,12 +194,13 @@ impl PickerDelegate for FetchContextPickerDelegate {
|
||||
let http_client = workspace.read(cx).client().http_client().clone();
|
||||
let url = self.url.clone();
|
||||
let confirm_behavior = self.confirm_behavior;
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
let text = cx
|
||||
.background_spawn(Self::build_message(http_client, url.clone()))
|
||||
.background_executor()
|
||||
.spawn(Self::build_message(http_client, url.clone()))
|
||||
.await?;
|
||||
|
||||
this.update_in(&mut cx, |this, window, cx| {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.delegate
|
||||
.context_store
|
||||
.update(cx, |context_store, _cx| {
|
||||
@@ -220,7 +209,7 @@ impl PickerDelegate for FetchContextPickerDelegate {
|
||||
|
||||
match confirm_behavior {
|
||||
ConfirmBehavior::KeepOpen => {}
|
||||
ConfirmBehavior::Close => this.delegate.dismissed(window, cx),
|
||||
ConfirmBehavior::Close => this.delegate.dismissed(cx),
|
||||
}
|
||||
|
||||
anyhow::Ok(())
|
||||
@@ -231,7 +220,7 @@ impl PickerDelegate for FetchContextPickerDelegate {
|
||||
.detach_and_log_err(cx);
|
||||
}
|
||||
|
||||
fn dismissed(&mut self, _window: &mut Window, cx: &mut Context<Picker<Self>>) {
|
||||
fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {
|
||||
self.context_picker
|
||||
.update(cx, |_, cx| {
|
||||
cx.emit(DismissEvent);
|
||||
@@ -243,8 +232,7 @@ impl PickerDelegate for FetchContextPickerDelegate {
|
||||
&self,
|
||||
ix: usize,
|
||||
selected: bool,
|
||||
_window: &mut Window,
|
||||
cx: &mut Context<Picker<Self>>,
|
||||
cx: &mut ViewContext<Picker<Self>>,
|
||||
) -> Option<Self::ListItem> {
|
||||
let added = self.context_store.upgrade().map_or(false, |context_store| {
|
||||
context_store.read(cx).includes_url(&self.url).is_some()
|
||||
|
||||
@@ -7,19 +7,19 @@ use std::sync::Arc;
|
||||
use editor::actions::FoldAt;
|
||||
use editor::display_map::{Crease, FoldId};
|
||||
use editor::scroll::Autoscroll;
|
||||
use editor::{Anchor, AnchorRangeExt, Editor, FoldPlaceholder, ToPoint};
|
||||
use editor::{Anchor, Editor, FoldPlaceholder, ToPoint};
|
||||
use file_icons::FileIcons;
|
||||
use fuzzy::PathMatch;
|
||||
use gpui::{
|
||||
AnyElement, App, AppContext, DismissEvent, Empty, Entity, FocusHandle, Focusable, Stateful,
|
||||
Task, WeakEntity,
|
||||
AnyElement, AppContext, DismissEvent, Empty, FocusHandle, FocusableView, Stateful, Task, View,
|
||||
WeakModel, WeakView,
|
||||
};
|
||||
use multi_buffer::{MultiBufferPoint, MultiBufferRow};
|
||||
use picker::{Picker, PickerDelegate};
|
||||
use project::{PathMatchCandidateSet, ProjectPath, WorktreeId};
|
||||
use rope::Point;
|
||||
use text::SelectionGoal;
|
||||
use ui::{prelude::*, ButtonLike, Disclosure, ListItem, TintColor, Tooltip};
|
||||
use ui::{prelude::*, ButtonLike, Disclosure, ElevationIndex, ListItem, Tooltip};
|
||||
use util::ResultExt as _;
|
||||
use workspace::{notifications::NotifyResultExt, Workspace};
|
||||
|
||||
@@ -27,18 +27,17 @@ use crate::context_picker::{ConfirmBehavior, ContextPicker};
|
||||
use crate::context_store::{ContextStore, FileInclusion};
|
||||
|
||||
pub struct FileContextPicker {
|
||||
picker: Entity<Picker<FileContextPickerDelegate>>,
|
||||
picker: View<Picker<FileContextPickerDelegate>>,
|
||||
}
|
||||
|
||||
impl FileContextPicker {
|
||||
pub fn new(
|
||||
context_picker: WeakEntity<ContextPicker>,
|
||||
workspace: WeakEntity<Workspace>,
|
||||
editor: WeakEntity<Editor>,
|
||||
context_store: WeakEntity<ContextStore>,
|
||||
context_picker: WeakView<ContextPicker>,
|
||||
workspace: WeakView<Workspace>,
|
||||
editor: WeakView<Editor>,
|
||||
context_store: WeakModel<ContextStore>,
|
||||
confirm_behavior: ConfirmBehavior,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Self {
|
||||
let delegate = FileContextPickerDelegate::new(
|
||||
context_picker,
|
||||
@@ -47,29 +46,29 @@ impl FileContextPicker {
|
||||
context_store,
|
||||
confirm_behavior,
|
||||
);
|
||||
let picker = cx.new(|cx| Picker::uniform_list(delegate, window, cx));
|
||||
let picker = cx.new_view(|cx| Picker::uniform_list(delegate, cx));
|
||||
|
||||
Self { picker }
|
||||
}
|
||||
}
|
||||
|
||||
impl Focusable for FileContextPicker {
|
||||
fn focus_handle(&self, cx: &App) -> FocusHandle {
|
||||
impl FocusableView for FileContextPicker {
|
||||
fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
|
||||
self.picker.focus_handle(cx)
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for FileContextPicker {
|
||||
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
self.picker.clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FileContextPickerDelegate {
|
||||
context_picker: WeakEntity<ContextPicker>,
|
||||
workspace: WeakEntity<Workspace>,
|
||||
editor: WeakEntity<Editor>,
|
||||
context_store: WeakEntity<ContextStore>,
|
||||
context_picker: WeakView<ContextPicker>,
|
||||
workspace: WeakView<Workspace>,
|
||||
editor: WeakView<Editor>,
|
||||
context_store: WeakModel<ContextStore>,
|
||||
confirm_behavior: ConfirmBehavior,
|
||||
matches: Vec<PathMatch>,
|
||||
selected_index: usize,
|
||||
@@ -77,10 +76,10 @@ pub struct FileContextPickerDelegate {
|
||||
|
||||
impl FileContextPickerDelegate {
|
||||
pub fn new(
|
||||
context_picker: WeakEntity<ContextPicker>,
|
||||
workspace: WeakEntity<Workspace>,
|
||||
editor: WeakEntity<Editor>,
|
||||
context_store: WeakEntity<ContextStore>,
|
||||
context_picker: WeakView<ContextPicker>,
|
||||
workspace: WeakView<Workspace>,
|
||||
editor: WeakView<Editor>,
|
||||
context_store: WeakModel<ContextStore>,
|
||||
confirm_behavior: ConfirmBehavior,
|
||||
) -> Self {
|
||||
Self {
|
||||
@@ -98,9 +97,8 @@ impl FileContextPickerDelegate {
|
||||
&mut self,
|
||||
query: String,
|
||||
cancellation_flag: Arc<AtomicBool>,
|
||||
workspace: &Entity<Workspace>,
|
||||
|
||||
cx: &mut Context<Picker<Self>>,
|
||||
workspace: &View<Workspace>,
|
||||
cx: &mut ViewContext<Picker<Self>>,
|
||||
) -> Task<Vec<PathMatch>> {
|
||||
if query.is_empty() {
|
||||
let workspace = workspace.read(cx);
|
||||
@@ -124,7 +122,7 @@ impl FileContextPickerDelegate {
|
||||
let file_matches = project.worktrees(cx).flat_map(|worktree| {
|
||||
let worktree = worktree.read(cx);
|
||||
let path_prefix: Arc<str> = worktree.root_name().into();
|
||||
worktree.files(false, 0).map(move |entry| PathMatch {
|
||||
worktree.files(true, 0).map(move |entry| PathMatch {
|
||||
score: 0.,
|
||||
positions: Vec::new(),
|
||||
worktree_id: worktree.id().to_usize(),
|
||||
@@ -182,32 +180,22 @@ impl PickerDelegate for FileContextPickerDelegate {
|
||||
self.selected_index
|
||||
}
|
||||
|
||||
fn set_selected_index(
|
||||
&mut self,
|
||||
ix: usize,
|
||||
_window: &mut Window,
|
||||
_cx: &mut Context<Picker<Self>>,
|
||||
) {
|
||||
fn set_selected_index(&mut self, ix: usize, _cx: &mut ViewContext<Picker<Self>>) {
|
||||
self.selected_index = ix;
|
||||
}
|
||||
|
||||
fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
|
||||
fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
|
||||
"Search files…".into()
|
||||
}
|
||||
|
||||
fn update_matches(
|
||||
&mut self,
|
||||
query: String,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Picker<Self>>,
|
||||
) -> Task<()> {
|
||||
fn update_matches(&mut self, query: String, cx: &mut ViewContext<Picker<Self>>) -> Task<()> {
|
||||
let Some(workspace) = self.workspace.upgrade() else {
|
||||
return Task::ready(());
|
||||
};
|
||||
|
||||
let search_task = self.search(query, Arc::<AtomicBool>::default(), &workspace, cx);
|
||||
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
// TODO: This should be probably be run in the background.
|
||||
let paths = search_task.await;
|
||||
|
||||
@@ -218,7 +206,7 @@ impl PickerDelegate for FileContextPickerDelegate {
|
||||
})
|
||||
}
|
||||
|
||||
fn confirm(&mut self, _secondary: bool, window: &mut Window, cx: &mut Context<Picker<Self>>) {
|
||||
fn confirm(&mut self, _secondary: bool, cx: &mut ViewContext<Picker<Self>>) {
|
||||
let Some(mat) = self.matches.get(self.selected_index) else {
|
||||
return;
|
||||
};
|
||||
@@ -238,12 +226,12 @@ impl PickerDelegate for FileContextPickerDelegate {
|
||||
path: mat.path.clone(),
|
||||
};
|
||||
|
||||
let Some(editor_entity) = self.editor.upgrade() else {
|
||||
let Some(editor) = self.editor.upgrade() else {
|
||||
return;
|
||||
};
|
||||
|
||||
editor_entity.update(cx, |editor, cx| {
|
||||
editor.transact(window, cx, |editor, window, cx| {
|
||||
editor.update(cx, |editor, cx| {
|
||||
editor.transact(cx, |editor, cx| {
|
||||
// Move empty selections left by 1 column to select the `@`s, so they get overwritten when we insert.
|
||||
{
|
||||
let mut selections = editor.selections.all::<MultiBufferPoint>(cx);
|
||||
@@ -259,9 +247,7 @@ impl PickerDelegate for FileContextPickerDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
|
||||
s.select(selections)
|
||||
});
|
||||
editor.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
|
||||
}
|
||||
|
||||
let start_anchors = {
|
||||
@@ -274,7 +260,7 @@ impl PickerDelegate for FileContextPickerDelegate {
|
||||
.collect::<Vec<_>>()
|
||||
};
|
||||
|
||||
editor.insert(&full_path, window, cx);
|
||||
editor.insert(&full_path, cx);
|
||||
|
||||
let end_anchors = {
|
||||
let snapshot = editor.buffer().read(cx).snapshot(cx);
|
||||
@@ -286,22 +272,14 @@ impl PickerDelegate for FileContextPickerDelegate {
|
||||
.collect::<Vec<_>>()
|
||||
};
|
||||
|
||||
editor.insert("\n", window, cx); // Needed to end the fold
|
||||
|
||||
let file_icon = FileIcons::get_icon(&Path::new(&full_path), cx)
|
||||
.unwrap_or_else(|| SharedString::new(""));
|
||||
editor.insert("\n", cx); // Needed to end the fold
|
||||
|
||||
let placeholder = FoldPlaceholder {
|
||||
render: render_fold_icon_button(
|
||||
file_icon,
|
||||
file_name.into(),
|
||||
editor_entity.downgrade(),
|
||||
),
|
||||
render: render_fold_icon_button(IconName::File, file_name.into()),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let render_trailer =
|
||||
move |_row, _unfold, _window: &mut Window, _cx: &mut App| Empty.into_any();
|
||||
let render_trailer = move |_row, _unfold, _cx: &mut WindowContext| Empty.into_any();
|
||||
|
||||
let buffer = editor.buffer().read(cx).snapshot(cx);
|
||||
let mut rows_to_fold = BTreeSet::new();
|
||||
@@ -322,7 +300,7 @@ impl PickerDelegate for FileContextPickerDelegate {
|
||||
editor.insert_creases(crease_iter, cx);
|
||||
|
||||
for buffer_row in rows_to_fold {
|
||||
editor.fold_at(&FoldAt { buffer_row }, window, cx);
|
||||
editor.fold_at(&FoldAt { buffer_row }, cx);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -338,19 +316,19 @@ impl PickerDelegate for FileContextPickerDelegate {
|
||||
};
|
||||
|
||||
let confirm_behavior = self.confirm_behavior;
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
match task.await.notify_async_err(&mut cx) {
|
||||
None => anyhow::Ok(()),
|
||||
Some(()) => this.update_in(&mut cx, |this, window, cx| match confirm_behavior {
|
||||
Some(()) => this.update(&mut cx, |this, cx| match confirm_behavior {
|
||||
ConfirmBehavior::KeepOpen => {}
|
||||
ConfirmBehavior::Close => this.delegate.dismissed(window, cx),
|
||||
ConfirmBehavior::Close => this.delegate.dismissed(cx),
|
||||
}),
|
||||
}
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
}
|
||||
|
||||
fn dismissed(&mut self, _: &mut Window, cx: &mut Context<Picker<Self>>) {
|
||||
fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {
|
||||
self.context_picker
|
||||
.update(cx, |_, cx| {
|
||||
cx.emit(DismissEvent);
|
||||
@@ -362,8 +340,7 @@ impl PickerDelegate for FileContextPickerDelegate {
|
||||
&self,
|
||||
ix: usize,
|
||||
selected: bool,
|
||||
_window: &mut Window,
|
||||
cx: &mut Context<Picker<Self>>,
|
||||
cx: &mut ViewContext<Picker<Self>>,
|
||||
) -> Option<Self::ListItem> {
|
||||
let path_match = &self.matches[ix];
|
||||
|
||||
@@ -386,8 +363,8 @@ pub fn render_file_context_entry(
|
||||
id: ElementId,
|
||||
path: &Path,
|
||||
path_prefix: &Arc<str>,
|
||||
context_store: WeakEntity<ContextStore>,
|
||||
cx: &App,
|
||||
context_store: WeakModel<ContextStore>,
|
||||
cx: &WindowContext,
|
||||
) -> Stateful<Div> {
|
||||
let (file_name, directory) = if path == Path::new("") {
|
||||
(SharedString::from(path_prefix.clone()), None)
|
||||
@@ -419,12 +396,12 @@ pub fn render_file_context_entry(
|
||||
|
||||
h_flex()
|
||||
.id(id)
|
||||
.gap_1p5()
|
||||
.gap_1()
|
||||
.w_full()
|
||||
.child(file_icon.size(IconSize::Small).color(Color::Muted))
|
||||
.child(file_icon.size(IconSize::Small))
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_1()
|
||||
.gap_2()
|
||||
.child(Label::new(file_name))
|
||||
.children(directory.map(|directory| {
|
||||
Label::new(directory)
|
||||
@@ -432,12 +409,11 @@ pub fn render_file_context_entry(
|
||||
.color(Color::Muted)
|
||||
})),
|
||||
)
|
||||
.child(div().w_full())
|
||||
.when_some(added, |el, added| match added {
|
||||
FileInclusion::Direct(_) => el.child(
|
||||
h_flex()
|
||||
.w_full()
|
||||
.justify_end()
|
||||
.gap_0p5()
|
||||
.gap_1()
|
||||
.child(
|
||||
Icon::new(IconName::Check)
|
||||
.size(IconSize::Small)
|
||||
@@ -450,9 +426,7 @@ pub fn render_file_context_entry(
|
||||
|
||||
el.child(
|
||||
h_flex()
|
||||
.w_full()
|
||||
.justify_end()
|
||||
.gap_0p5()
|
||||
.gap_1()
|
||||
.child(
|
||||
Icon::new(IconName::Check)
|
||||
.size(IconSize::Small)
|
||||
@@ -460,72 +434,21 @@ pub fn render_file_context_entry(
|
||||
)
|
||||
.child(Label::new("Included").size(LabelSize::Small)),
|
||||
)
|
||||
.tooltip(Tooltip::text(format!("in {dir_name}")))
|
||||
.tooltip(move |cx| Tooltip::text(format!("in {dir_name}"), cx))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn render_fold_icon_button(
|
||||
icon: SharedString,
|
||||
icon: IconName,
|
||||
label: SharedString,
|
||||
editor: WeakEntity<Editor>,
|
||||
) -> Arc<dyn Send + Sync + Fn(FoldId, Range<Anchor>, &mut App) -> AnyElement> {
|
||||
Arc::new(move |fold_id, fold_range, cx| {
|
||||
let is_in_text_selection = editor.upgrade().is_some_and(|editor| {
|
||||
editor.update(cx, |editor, cx| {
|
||||
let snapshot = editor
|
||||
.buffer()
|
||||
.update(cx, |multi_buffer, cx| multi_buffer.snapshot(cx));
|
||||
|
||||
let is_in_pending_selection = || {
|
||||
editor
|
||||
.selections
|
||||
.pending
|
||||
.as_ref()
|
||||
.is_some_and(|pending_selection| {
|
||||
pending_selection
|
||||
.selection
|
||||
.range()
|
||||
.includes(&fold_range, &snapshot)
|
||||
})
|
||||
};
|
||||
|
||||
let mut is_in_complete_selection = || {
|
||||
editor
|
||||
.selections
|
||||
.disjoint_in_range::<usize>(fold_range.clone(), cx)
|
||||
.into_iter()
|
||||
.any(|selection| {
|
||||
// This is needed to cover a corner case, if we just check for an existing
|
||||
// selection in the fold range, having a cursor at the start of the fold
|
||||
// marks it as selected. Non-empty selections don't cause this.
|
||||
let length = selection.end - selection.start;
|
||||
length > 0
|
||||
})
|
||||
};
|
||||
|
||||
is_in_pending_selection() || is_in_complete_selection()
|
||||
})
|
||||
});
|
||||
|
||||
) -> Arc<dyn Send + Sync + Fn(FoldId, Range<Anchor>, &mut WindowContext) -> AnyElement> {
|
||||
Arc::new(move |fold_id, _fold_range, _cx| {
|
||||
ButtonLike::new(fold_id)
|
||||
.style(ButtonStyle::Filled)
|
||||
.selected_style(ButtonStyle::Tinted(TintColor::Accent))
|
||||
.toggle_state(is_in_text_selection)
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_1()
|
||||
.child(
|
||||
Icon::from_path(icon.clone())
|
||||
.size(IconSize::Small)
|
||||
.color(Color::Muted),
|
||||
)
|
||||
.child(
|
||||
Label::new(label.clone())
|
||||
.size(LabelSize::Small)
|
||||
.single_line(),
|
||||
),
|
||||
)
|
||||
.layer(ElevationIndex::ElevatedSurface)
|
||||
.child(Icon::new(icon))
|
||||
.child(Label::new(label.clone()).single_line())
|
||||
.into_any_element()
|
||||
})
|
||||
}
|
||||
@@ -535,14 +458,13 @@ fn fold_toggle(
|
||||
) -> impl Fn(
|
||||
MultiBufferRow,
|
||||
bool,
|
||||
Arc<dyn Fn(bool, &mut Window, &mut App) + Send + Sync>,
|
||||
&mut Window,
|
||||
&mut App,
|
||||
Arc<dyn Fn(bool, &mut WindowContext) + Send + Sync>,
|
||||
&mut WindowContext,
|
||||
) -> AnyElement {
|
||||
move |row, is_folded, fold, _window, _cx| {
|
||||
move |row, is_folded, fold, _cx| {
|
||||
Disclosure::new((name, row.0 as u64), !is_folded)
|
||||
.toggle_state(is_folded)
|
||||
.on_click(move |_e, window, cx| fold(!is_folded, window, cx))
|
||||
.on_click(move |_e, cx| fold(!is_folded, cx))
|
||||
.into_any_element()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use fuzzy::StringMatchCandidate;
|
||||
use gpui::{App, DismissEvent, Entity, FocusHandle, Focusable, Task, WeakEntity};
|
||||
use gpui::{AppContext, DismissEvent, FocusHandle, FocusableView, Task, View, WeakModel, WeakView};
|
||||
use picker::{Picker, PickerDelegate};
|
||||
use ui::{prelude::*, ListItem};
|
||||
|
||||
@@ -11,17 +11,16 @@ use crate::thread::ThreadId;
|
||||
use crate::thread_store::ThreadStore;
|
||||
|
||||
pub struct ThreadContextPicker {
|
||||
picker: Entity<Picker<ThreadContextPickerDelegate>>,
|
||||
picker: View<Picker<ThreadContextPickerDelegate>>,
|
||||
}
|
||||
|
||||
impl ThreadContextPicker {
|
||||
pub fn new(
|
||||
thread_store: WeakEntity<ThreadStore>,
|
||||
context_picker: WeakEntity<ContextPicker>,
|
||||
context_store: WeakEntity<context_store::ContextStore>,
|
||||
thread_store: WeakModel<ThreadStore>,
|
||||
context_picker: WeakView<ContextPicker>,
|
||||
context_store: WeakModel<context_store::ContextStore>,
|
||||
confirm_behavior: ConfirmBehavior,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Self {
|
||||
let delegate = ThreadContextPickerDelegate::new(
|
||||
thread_store,
|
||||
@@ -29,20 +28,20 @@ impl ThreadContextPicker {
|
||||
context_store,
|
||||
confirm_behavior,
|
||||
);
|
||||
let picker = cx.new(|cx| Picker::uniform_list(delegate, window, cx));
|
||||
let picker = cx.new_view(|cx| Picker::uniform_list(delegate, cx));
|
||||
|
||||
ThreadContextPicker { picker }
|
||||
}
|
||||
}
|
||||
|
||||
impl Focusable for ThreadContextPicker {
|
||||
fn focus_handle(&self, cx: &App) -> FocusHandle {
|
||||
impl FocusableView for ThreadContextPicker {
|
||||
fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
|
||||
self.picker.focus_handle(cx)
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for ThreadContextPicker {
|
||||
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
self.picker.clone()
|
||||
}
|
||||
}
|
||||
@@ -54,9 +53,9 @@ pub struct ThreadContextEntry {
|
||||
}
|
||||
|
||||
pub struct ThreadContextPickerDelegate {
|
||||
thread_store: WeakEntity<ThreadStore>,
|
||||
context_picker: WeakEntity<ContextPicker>,
|
||||
context_store: WeakEntity<context_store::ContextStore>,
|
||||
thread_store: WeakModel<ThreadStore>,
|
||||
context_picker: WeakView<ContextPicker>,
|
||||
context_store: WeakModel<context_store::ContextStore>,
|
||||
confirm_behavior: ConfirmBehavior,
|
||||
matches: Vec<ThreadContextEntry>,
|
||||
selected_index: usize,
|
||||
@@ -64,9 +63,9 @@ pub struct ThreadContextPickerDelegate {
|
||||
|
||||
impl ThreadContextPickerDelegate {
|
||||
pub fn new(
|
||||
thread_store: WeakEntity<ThreadStore>,
|
||||
context_picker: WeakEntity<ContextPicker>,
|
||||
context_store: WeakEntity<context_store::ContextStore>,
|
||||
thread_store: WeakModel<ThreadStore>,
|
||||
context_picker: WeakView<ContextPicker>,
|
||||
context_store: WeakModel<context_store::ContextStore>,
|
||||
confirm_behavior: ConfirmBehavior,
|
||||
) -> Self {
|
||||
ThreadContextPickerDelegate {
|
||||
@@ -91,31 +90,22 @@ impl PickerDelegate for ThreadContextPickerDelegate {
|
||||
self.selected_index
|
||||
}
|
||||
|
||||
fn set_selected_index(
|
||||
&mut self,
|
||||
ix: usize,
|
||||
_window: &mut Window,
|
||||
_cx: &mut Context<Picker<Self>>,
|
||||
) {
|
||||
fn set_selected_index(&mut self, ix: usize, _cx: &mut ViewContext<Picker<Self>>) {
|
||||
self.selected_index = ix;
|
||||
}
|
||||
|
||||
fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
|
||||
fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
|
||||
"Search threads…".into()
|
||||
}
|
||||
|
||||
fn update_matches(
|
||||
&mut self,
|
||||
query: String,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Picker<Self>>,
|
||||
) -> Task<()> {
|
||||
let Ok(threads) = self.thread_store.update(cx, |this, _cx| {
|
||||
this.threads()
|
||||
fn update_matches(&mut self, query: String, cx: &mut ViewContext<Picker<Self>>) -> Task<()> {
|
||||
let Ok(threads) = self.thread_store.update(cx, |this, cx| {
|
||||
this.threads(cx)
|
||||
.into_iter()
|
||||
.map(|thread| ThreadContextEntry {
|
||||
id: thread.id,
|
||||
summary: thread.summary,
|
||||
.map(|thread| {
|
||||
let id = thread.read(cx).id().clone();
|
||||
let summary = thread.read(cx).summary_or_default();
|
||||
ThreadContextEntry { id, summary }
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
}) else {
|
||||
@@ -123,7 +113,7 @@ impl PickerDelegate for ThreadContextPickerDelegate {
|
||||
};
|
||||
|
||||
let executor = cx.background_executor().clone();
|
||||
let search_task = cx.background_spawn(async move {
|
||||
let search_task = cx.background_executor().spawn(async move {
|
||||
if query.is_empty() {
|
||||
threads
|
||||
} else {
|
||||
@@ -149,7 +139,7 @@ impl PickerDelegate for ThreadContextPickerDelegate {
|
||||
}
|
||||
});
|
||||
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
let matches = search_task.await;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.delegate.matches = matches;
|
||||
@@ -160,7 +150,7 @@ impl PickerDelegate for ThreadContextPickerDelegate {
|
||||
})
|
||||
}
|
||||
|
||||
fn confirm(&mut self, _secondary: bool, window: &mut Window, cx: &mut Context<Picker<Self>>) {
|
||||
fn confirm(&mut self, _secondary: bool, cx: &mut ViewContext<Picker<Self>>) {
|
||||
let Some(entry) = self.matches.get(self.selected_index) else {
|
||||
return;
|
||||
};
|
||||
@@ -169,26 +159,22 @@ impl PickerDelegate for ThreadContextPickerDelegate {
|
||||
return;
|
||||
};
|
||||
|
||||
let open_thread_task = thread_store.update(cx, |this, cx| this.open_thread(&entry.id, cx));
|
||||
let Some(thread) = thread_store.update(cx, |this, cx| this.open_thread(&entry.id, cx))
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
let thread = open_thread_task.await?;
|
||||
this.update_in(&mut cx, |this, window, cx| {
|
||||
this.delegate
|
||||
.context_store
|
||||
.update(cx, |context_store, cx| context_store.add_thread(thread, cx))
|
||||
.ok();
|
||||
self.context_store
|
||||
.update(cx, |context_store, cx| context_store.add_thread(thread, cx))
|
||||
.ok();
|
||||
|
||||
match this.delegate.confirm_behavior {
|
||||
ConfirmBehavior::KeepOpen => {}
|
||||
ConfirmBehavior::Close => this.delegate.dismissed(window, cx),
|
||||
}
|
||||
})
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
match self.confirm_behavior {
|
||||
ConfirmBehavior::KeepOpen => {}
|
||||
ConfirmBehavior::Close => self.dismissed(cx),
|
||||
}
|
||||
}
|
||||
|
||||
fn dismissed(&mut self, _window: &mut Window, cx: &mut Context<Picker<Self>>) {
|
||||
fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {
|
||||
self.context_picker
|
||||
.update(cx, |_, cx| {
|
||||
cx.emit(DismissEvent);
|
||||
@@ -200,8 +186,7 @@ impl PickerDelegate for ThreadContextPickerDelegate {
|
||||
&self,
|
||||
ix: usize,
|
||||
selected: bool,
|
||||
_window: &mut Window,
|
||||
cx: &mut Context<Picker<Self>>,
|
||||
cx: &mut ViewContext<Picker<Self>>,
|
||||
) -> Option<Self::ListItem> {
|
||||
let thread = &self.matches[ix];
|
||||
|
||||
@@ -213,21 +198,17 @@ impl PickerDelegate for ThreadContextPickerDelegate {
|
||||
|
||||
pub fn render_thread_context_entry(
|
||||
thread: &ThreadContextEntry,
|
||||
context_store: WeakEntity<ContextStore>,
|
||||
cx: &mut App,
|
||||
context_store: WeakModel<ContextStore>,
|
||||
cx: &mut WindowContext,
|
||||
) -> Div {
|
||||
let added = context_store.upgrade().map_or(false, |ctx_store| {
|
||||
ctx_store.read(cx).includes_thread(&thread.id).is_some()
|
||||
});
|
||||
|
||||
h_flex()
|
||||
.gap_1p5()
|
||||
.gap_1()
|
||||
.w_full()
|
||||
.child(
|
||||
Icon::new(IconName::MessageCircle)
|
||||
.size(IconSize::XSmall)
|
||||
.color(Color::Muted),
|
||||
)
|
||||
.child(Icon::new(IconName::MessageCircle).size(IconSize::Small))
|
||||
.child(Label::new(thread.summary.clone()))
|
||||
.child(div().w_full())
|
||||
.when(added, |el| {
|
||||
|
||||
@@ -4,7 +4,7 @@ use std::sync::Arc;
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
use collections::{BTreeMap, HashMap, HashSet};
|
||||
use futures::{self, future, Future, FutureExt};
|
||||
use gpui::{App, AppContext as _, AsyncApp, Context, Entity, SharedString, Task, WeakEntity};
|
||||
use gpui::{AppContext, AsyncAppContext, Model, ModelContext, SharedString, Task, WeakView};
|
||||
use language::Buffer;
|
||||
use project::{ProjectPath, Worktree};
|
||||
use rope::Rope;
|
||||
@@ -12,15 +12,15 @@ use text::BufferId;
|
||||
use workspace::Workspace;
|
||||
|
||||
use crate::context::{
|
||||
AssistantContext, ContextBuffer, ContextId, ContextSnapshot, DirectoryContext,
|
||||
FetchedUrlContext, FileContext, ThreadContext,
|
||||
Context, ContextBuffer, ContextId, ContextSnapshot, DirectoryContext, FetchedUrlContext,
|
||||
FileContext, ThreadContext,
|
||||
};
|
||||
use crate::context_strip::SuggestedContext;
|
||||
use crate::thread::{Thread, ThreadId};
|
||||
|
||||
pub struct ContextStore {
|
||||
workspace: WeakEntity<Workspace>,
|
||||
context: Vec<AssistantContext>,
|
||||
workspace: WeakView<Workspace>,
|
||||
context: Vec<Context>,
|
||||
// TODO: If an EntityId is used for all context types (like BufferId), can remove ContextId.
|
||||
next_context_id: ContextId,
|
||||
files: BTreeMap<BufferId, ContextId>,
|
||||
@@ -30,7 +30,7 @@ pub struct ContextStore {
|
||||
}
|
||||
|
||||
impl ContextStore {
|
||||
pub fn new(workspace: WeakEntity<Workspace>) -> Self {
|
||||
pub fn new(workspace: WeakView<Workspace>) -> Self {
|
||||
Self {
|
||||
workspace,
|
||||
context: Vec::new(),
|
||||
@@ -42,13 +42,16 @@ impl ContextStore {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn snapshot<'a>(&'a self, cx: &'a App) -> impl Iterator<Item = ContextSnapshot> + 'a {
|
||||
pub fn snapshot<'a>(
|
||||
&'a self,
|
||||
cx: &'a AppContext,
|
||||
) -> impl Iterator<Item = ContextSnapshot> + 'a {
|
||||
self.context()
|
||||
.iter()
|
||||
.flat_map(|context| context.snapshot(cx))
|
||||
}
|
||||
|
||||
pub fn context(&self) -> &Vec<AssistantContext> {
|
||||
pub fn context(&self) -> &Vec<Context> {
|
||||
&self.context
|
||||
}
|
||||
|
||||
@@ -63,7 +66,7 @@ impl ContextStore {
|
||||
pub fn add_file_from_path(
|
||||
&mut self,
|
||||
project_path: ProjectPath,
|
||||
cx: &mut Context<Self>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> Task<Result<()>> {
|
||||
let workspace = self.workspace.clone();
|
||||
|
||||
@@ -79,8 +82,8 @@ impl ContextStore {
|
||||
project.open_buffer(project_path.clone(), cx)
|
||||
})?;
|
||||
|
||||
let buffer_entity = open_buffer_task.await?;
|
||||
let buffer_id = this.update(&mut cx, |_, cx| buffer_entity.read(cx).remote_id())?;
|
||||
let buffer_model = open_buffer_task.await?;
|
||||
let buffer_id = this.update(&mut cx, |_, cx| buffer_model.read(cx).remote_id())?;
|
||||
|
||||
let already_included = this.update(&mut cx, |this, _cx| {
|
||||
match this.will_include_buffer(buffer_id, &project_path.path) {
|
||||
@@ -98,10 +101,10 @@ impl ContextStore {
|
||||
}
|
||||
|
||||
let (buffer_info, text_task) = this.update(&mut cx, |_, cx| {
|
||||
let buffer = buffer_entity.read(cx);
|
||||
let buffer = buffer_model.read(cx);
|
||||
collect_buffer_info_and_text(
|
||||
project_path.path.clone(),
|
||||
buffer_entity,
|
||||
buffer_model,
|
||||
buffer,
|
||||
cx.to_async(),
|
||||
)
|
||||
@@ -119,18 +122,18 @@ impl ContextStore {
|
||||
|
||||
pub fn add_file_from_buffer(
|
||||
&mut self,
|
||||
buffer_entity: Entity<Buffer>,
|
||||
cx: &mut Context<Self>,
|
||||
buffer_model: Model<Buffer>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> Task<Result<()>> {
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
let (buffer_info, text_task) = this.update(&mut cx, |_, cx| {
|
||||
let buffer = buffer_entity.read(cx);
|
||||
let buffer = buffer_model.read(cx);
|
||||
let Some(file) = buffer.file() else {
|
||||
return Err(anyhow!("Buffer has no path."));
|
||||
};
|
||||
Ok(collect_buffer_info_and_text(
|
||||
file.path().clone(),
|
||||
buffer_entity,
|
||||
buffer_model,
|
||||
buffer,
|
||||
cx.to_async(),
|
||||
))
|
||||
@@ -150,13 +153,13 @@ impl ContextStore {
|
||||
let id = self.next_context_id.post_inc();
|
||||
self.files.insert(context_buffer.id, id);
|
||||
self.context
|
||||
.push(AssistantContext::File(FileContext { id, context_buffer }));
|
||||
.push(Context::File(FileContext { id, context_buffer }));
|
||||
}
|
||||
|
||||
pub fn add_directory(
|
||||
&mut self,
|
||||
project_path: ProjectPath,
|
||||
cx: &mut Context<Self>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> Task<Result<()>> {
|
||||
let workspace = self.workspace.clone();
|
||||
let Some(project) = workspace
|
||||
@@ -207,11 +210,11 @@ impl ContextStore {
|
||||
let mut buffer_infos = Vec::new();
|
||||
let mut text_tasks = Vec::new();
|
||||
this.update(&mut cx, |_, cx| {
|
||||
for (path, buffer_entity) in files.into_iter().zip(buffers) {
|
||||
let buffer_entity = buffer_entity?;
|
||||
let buffer = buffer_entity.read(cx);
|
||||
for (path, buffer_model) in files.into_iter().zip(buffers) {
|
||||
let buffer_model = buffer_model?;
|
||||
let buffer = buffer_model.read(cx);
|
||||
let (buffer_info, text_task) =
|
||||
collect_buffer_info_and_text(path, buffer_entity, buffer, cx.to_async());
|
||||
collect_buffer_info_and_text(path, buffer_model, buffer, cx.to_async());
|
||||
buffer_infos.push(buffer_info);
|
||||
text_tasks.push(text_task);
|
||||
}
|
||||
@@ -241,15 +244,14 @@ impl ContextStore {
|
||||
let id = self.next_context_id.post_inc();
|
||||
self.directories.insert(path.to_path_buf(), id);
|
||||
|
||||
self.context
|
||||
.push(AssistantContext::Directory(DirectoryContext::new(
|
||||
id,
|
||||
path,
|
||||
context_buffers,
|
||||
)));
|
||||
self.context.push(Context::Directory(DirectoryContext::new(
|
||||
id,
|
||||
path,
|
||||
context_buffers,
|
||||
)));
|
||||
}
|
||||
|
||||
pub fn add_thread(&mut self, thread: Entity<Thread>, cx: &mut Context<Self>) {
|
||||
pub fn add_thread(&mut self, thread: Model<Thread>, cx: &mut ModelContext<Self>) {
|
||||
if let Some(context_id) = self.includes_thread(&thread.read(cx).id()) {
|
||||
self.remove_context(context_id);
|
||||
} else {
|
||||
@@ -257,13 +259,13 @@ impl ContextStore {
|
||||
}
|
||||
}
|
||||
|
||||
fn insert_thread(&mut self, thread: Entity<Thread>, cx: &App) {
|
||||
fn insert_thread(&mut self, thread: Model<Thread>, cx: &AppContext) {
|
||||
let id = self.next_context_id.post_inc();
|
||||
let text = thread.read(cx).text().into();
|
||||
|
||||
self.threads.insert(thread.read(cx).id().clone(), id);
|
||||
self.context
|
||||
.push(AssistantContext::Thread(ThreadContext { id, thread, text }));
|
||||
.push(Context::Thread(ThreadContext { id, thread, text }));
|
||||
}
|
||||
|
||||
pub fn add_fetched_url(&mut self, url: String, text: impl Into<SharedString>) {
|
||||
@@ -276,18 +278,17 @@ impl ContextStore {
|
||||
let id = self.next_context_id.post_inc();
|
||||
|
||||
self.fetched_urls.insert(url.clone(), id);
|
||||
self.context
|
||||
.push(AssistantContext::FetchedUrl(FetchedUrlContext {
|
||||
id,
|
||||
url: url.into(),
|
||||
text: text.into(),
|
||||
}));
|
||||
self.context.push(Context::FetchedUrl(FetchedUrlContext {
|
||||
id,
|
||||
url: url.into(),
|
||||
text: text.into(),
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn accept_suggested_context(
|
||||
&mut self,
|
||||
suggested: &SuggestedContext,
|
||||
cx: &mut Context<ContextStore>,
|
||||
cx: &mut ModelContext<ContextStore>,
|
||||
) -> Task<Result<()>> {
|
||||
match suggested {
|
||||
SuggestedContext::File {
|
||||
@@ -314,16 +315,16 @@ impl ContextStore {
|
||||
};
|
||||
|
||||
match self.context.remove(ix) {
|
||||
AssistantContext::File(_) => {
|
||||
Context::File(_) => {
|
||||
self.files.retain(|_, context_id| *context_id != id);
|
||||
}
|
||||
AssistantContext::Directory(_) => {
|
||||
Context::Directory(_) => {
|
||||
self.directories.retain(|_, context_id| *context_id != id);
|
||||
}
|
||||
AssistantContext::FetchedUrl(_) => {
|
||||
Context::FetchedUrl(_) => {
|
||||
self.fetched_urls.retain(|_, context_id| *context_id != id);
|
||||
}
|
||||
AssistantContext::Thread(_) => {
|
||||
Context::Thread(_) => {
|
||||
self.threads.retain(|_, context_id| *context_id != id);
|
||||
}
|
||||
}
|
||||
@@ -342,10 +343,10 @@ impl ContextStore {
|
||||
|
||||
/// Returns whether this file path is already included directly in the context, or if it will be
|
||||
/// included in the context via a directory.
|
||||
pub fn will_include_file_path(&self, path: &Path, cx: &App) -> Option<FileInclusion> {
|
||||
pub fn will_include_file_path(&self, path: &Path, cx: &AppContext) -> Option<FileInclusion> {
|
||||
if !self.files.is_empty() {
|
||||
let found_file_context = self.context.iter().find(|context| match &context {
|
||||
AssistantContext::File(file_context) => {
|
||||
Context::File(file_context) => {
|
||||
let buffer = file_context.context_buffer.buffer.read(cx);
|
||||
if let Some(file_path) = buffer_path_log_err(buffer) {
|
||||
*file_path == *path
|
||||
@@ -392,7 +393,7 @@ impl ContextStore {
|
||||
}
|
||||
|
||||
/// Replaces the context that matches the ID of the new context, if any match.
|
||||
fn replace_context(&mut self, new_context: AssistantContext) {
|
||||
fn replace_context(&mut self, new_context: Context) {
|
||||
let id = new_context.id();
|
||||
for context in self.context.iter_mut() {
|
||||
if context.id() == id {
|
||||
@@ -402,17 +403,15 @@ impl ContextStore {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn file_paths(&self, cx: &App) -> HashSet<PathBuf> {
|
||||
pub fn file_paths(&self, cx: &AppContext) -> HashSet<PathBuf> {
|
||||
self.context
|
||||
.iter()
|
||||
.filter_map(|context| match context {
|
||||
AssistantContext::File(file) => {
|
||||
Context::File(file) => {
|
||||
let buffer = file.context_buffer.buffer.read(cx);
|
||||
buffer_path_log_err(buffer).map(|p| p.to_path_buf())
|
||||
}
|
||||
AssistantContext::Directory(_)
|
||||
| AssistantContext::FetchedUrl(_)
|
||||
| AssistantContext::Thread(_) => None,
|
||||
Context::Directory(_) | Context::FetchedUrl(_) | Context::Thread(_) => None,
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
@@ -429,7 +428,7 @@ pub enum FileInclusion {
|
||||
|
||||
// ContextBuffer without text.
|
||||
struct BufferInfo {
|
||||
buffer_entity: Entity<Buffer>,
|
||||
buffer_model: Model<Buffer>,
|
||||
id: BufferId,
|
||||
version: clock::Global,
|
||||
}
|
||||
@@ -437,7 +436,7 @@ struct BufferInfo {
|
||||
fn make_context_buffer(info: BufferInfo, text: SharedString) -> ContextBuffer {
|
||||
ContextBuffer {
|
||||
id: info.id,
|
||||
buffer: info.buffer_entity,
|
||||
buffer: info.buffer_model,
|
||||
version: info.version,
|
||||
text,
|
||||
}
|
||||
@@ -445,18 +444,20 @@ fn make_context_buffer(info: BufferInfo, text: SharedString) -> ContextBuffer {
|
||||
|
||||
fn collect_buffer_info_and_text(
|
||||
path: Arc<Path>,
|
||||
buffer_entity: Entity<Buffer>,
|
||||
buffer_model: Model<Buffer>,
|
||||
buffer: &Buffer,
|
||||
cx: AsyncApp,
|
||||
cx: AsyncAppContext,
|
||||
) -> (BufferInfo, Task<SharedString>) {
|
||||
let buffer_info = BufferInfo {
|
||||
id: buffer.remote_id(),
|
||||
buffer_entity,
|
||||
buffer_model,
|
||||
version: buffer.version(),
|
||||
};
|
||||
// Important to collect version at the same time as content so that staleness logic is correct.
|
||||
let content = buffer.as_rope().clone();
|
||||
let text_task = cx.background_spawn(async move { to_fenced_codeblock(&path, content) });
|
||||
let text_task = cx
|
||||
.background_executor()
|
||||
.spawn(async move { to_fenced_codeblock(&path, content) });
|
||||
(buffer_info, text_task)
|
||||
}
|
||||
|
||||
@@ -524,32 +525,32 @@ fn collect_files_in_path(worktree: &Worktree, path: &Path) -> Vec<Arc<Path>> {
|
||||
}
|
||||
|
||||
pub fn refresh_context_store_text(
|
||||
context_store: Entity<ContextStore>,
|
||||
cx: &App,
|
||||
context_store: Model<ContextStore>,
|
||||
cx: &AppContext,
|
||||
) -> impl Future<Output = ()> {
|
||||
let mut tasks = Vec::new();
|
||||
for context in &context_store.read(cx).context {
|
||||
match context {
|
||||
AssistantContext::File(file_context) => {
|
||||
Context::File(file_context) => {
|
||||
let context_store = context_store.clone();
|
||||
if let Some(task) = refresh_file_text(context_store, file_context, cx) {
|
||||
tasks.push(task);
|
||||
}
|
||||
}
|
||||
AssistantContext::Directory(directory_context) => {
|
||||
Context::Directory(directory_context) => {
|
||||
let context_store = context_store.clone();
|
||||
if let Some(task) = refresh_directory_text(context_store, directory_context, cx) {
|
||||
tasks.push(task);
|
||||
}
|
||||
}
|
||||
AssistantContext::Thread(thread_context) => {
|
||||
Context::Thread(thread_context) => {
|
||||
let context_store = context_store.clone();
|
||||
tasks.push(refresh_thread_text(context_store, thread_context, cx));
|
||||
}
|
||||
// Intentionally omit refreshing fetched URLs as it doesn't seem all that useful,
|
||||
// and doing the caching properly could be tricky (unless it's already handled by
|
||||
// the HttpClient?).
|
||||
AssistantContext::FetchedUrl(_) => {}
|
||||
Context::FetchedUrl(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -557,9 +558,9 @@ pub fn refresh_context_store_text(
|
||||
}
|
||||
|
||||
fn refresh_file_text(
|
||||
context_store: Entity<ContextStore>,
|
||||
context_store: Model<ContextStore>,
|
||||
file_context: &FileContext,
|
||||
cx: &App,
|
||||
cx: &AppContext,
|
||||
) -> Option<Task<()>> {
|
||||
let id = file_context.id;
|
||||
let task = refresh_context_buffer(&file_context.context_buffer, cx);
|
||||
@@ -569,7 +570,7 @@ fn refresh_file_text(
|
||||
context_store
|
||||
.update(&mut cx, |context_store, _| {
|
||||
let new_file_context = FileContext { id, context_buffer };
|
||||
context_store.replace_context(AssistantContext::File(new_file_context));
|
||||
context_store.replace_context(Context::File(new_file_context));
|
||||
})
|
||||
.ok();
|
||||
}))
|
||||
@@ -579,9 +580,9 @@ fn refresh_file_text(
|
||||
}
|
||||
|
||||
fn refresh_directory_text(
|
||||
context_store: Entity<ContextStore>,
|
||||
context_store: Model<ContextStore>,
|
||||
directory_context: &DirectoryContext,
|
||||
cx: &App,
|
||||
cx: &AppContext,
|
||||
) -> Option<Task<()>> {
|
||||
let mut stale = false;
|
||||
let futures = directory_context
|
||||
@@ -610,16 +611,16 @@ fn refresh_directory_text(
|
||||
context_store
|
||||
.update(&mut cx, |context_store, _| {
|
||||
let new_directory_context = DirectoryContext::new(id, &path, context_buffers);
|
||||
context_store.replace_context(AssistantContext::Directory(new_directory_context));
|
||||
context_store.replace_context(Context::Directory(new_directory_context));
|
||||
})
|
||||
.ok();
|
||||
}))
|
||||
}
|
||||
|
||||
fn refresh_thread_text(
|
||||
context_store: Entity<ContextStore>,
|
||||
context_store: Model<ContextStore>,
|
||||
thread_context: &ThreadContext,
|
||||
cx: &App,
|
||||
cx: &AppContext,
|
||||
) -> Task<()> {
|
||||
let id = thread_context.id;
|
||||
let thread = thread_context.thread.clone();
|
||||
@@ -627,11 +628,7 @@ fn refresh_thread_text(
|
||||
context_store
|
||||
.update(&mut cx, |context_store, cx| {
|
||||
let text = thread.read(cx).text().into();
|
||||
context_store.replace_context(AssistantContext::Thread(ThreadContext {
|
||||
id,
|
||||
thread,
|
||||
text,
|
||||
}));
|
||||
context_store.replace_context(Context::Thread(ThreadContext { id, thread, text }));
|
||||
})
|
||||
.ok();
|
||||
})
|
||||
@@ -639,7 +636,7 @@ fn refresh_thread_text(
|
||||
|
||||
fn refresh_context_buffer(
|
||||
context_buffer: &ContextBuffer,
|
||||
cx: &App,
|
||||
cx: &AppContext,
|
||||
) -> Option<impl Future<Output = ContextBuffer>> {
|
||||
let buffer = context_buffer.buffer.read(cx);
|
||||
let path = buffer_path_log_err(buffer)?;
|
||||
|
||||
@@ -4,8 +4,8 @@ use collections::HashSet;
|
||||
use editor::Editor;
|
||||
use file_icons::FileIcons;
|
||||
use gpui::{
|
||||
App, Bounds, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, Subscription,
|
||||
WeakEntity,
|
||||
AppContext, Bounds, DismissEvent, EventEmitter, FocusHandle, FocusableView, Model,
|
||||
Subscription, View, WeakModel, WeakView,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use language::Buffer;
|
||||
@@ -24,37 +24,34 @@ use crate::{
|
||||
};
|
||||
|
||||
pub struct ContextStrip {
|
||||
context_store: Entity<ContextStore>,
|
||||
pub context_picker: Entity<ContextPicker>,
|
||||
context_store: Model<ContextStore>,
|
||||
pub context_picker: View<ContextPicker>,
|
||||
context_picker_menu_handle: PopoverMenuHandle<ContextPicker>,
|
||||
focus_handle: FocusHandle,
|
||||
suggest_context_kind: SuggestContextKind,
|
||||
workspace: WeakEntity<Workspace>,
|
||||
workspace: WeakView<Workspace>,
|
||||
_subscriptions: Vec<Subscription>,
|
||||
focused_index: Option<usize>,
|
||||
children_bounds: Option<Vec<Bounds<Pixels>>>,
|
||||
}
|
||||
|
||||
impl ContextStrip {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
context_store: Entity<ContextStore>,
|
||||
workspace: WeakEntity<Workspace>,
|
||||
editor: WeakEntity<Editor>,
|
||||
thread_store: Option<WeakEntity<ThreadStore>>,
|
||||
context_store: Model<ContextStore>,
|
||||
workspace: WeakView<Workspace>,
|
||||
editor: WeakView<Editor>,
|
||||
thread_store: Option<WeakModel<ThreadStore>>,
|
||||
context_picker_menu_handle: PopoverMenuHandle<ContextPicker>,
|
||||
suggest_context_kind: SuggestContextKind,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Self {
|
||||
let context_picker = cx.new(|cx| {
|
||||
let context_picker = cx.new_view(|cx| {
|
||||
ContextPicker::new(
|
||||
workspace.clone(),
|
||||
thread_store.clone(),
|
||||
context_store.downgrade(),
|
||||
editor.clone(),
|
||||
ConfirmBehavior::KeepOpen,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
});
|
||||
@@ -62,9 +59,9 @@ impl ContextStrip {
|
||||
let focus_handle = cx.focus_handle();
|
||||
|
||||
let subscriptions = vec![
|
||||
cx.subscribe_in(&context_picker, window, Self::handle_context_picker_event),
|
||||
cx.on_focus(&focus_handle, window, Self::handle_focus),
|
||||
cx.on_blur(&focus_handle, window, Self::handle_blur),
|
||||
cx.subscribe(&context_picker, Self::handle_context_picker_event),
|
||||
cx.on_focus(&focus_handle, Self::handle_focus),
|
||||
cx.on_blur(&focus_handle, Self::handle_blur),
|
||||
];
|
||||
|
||||
Self {
|
||||
@@ -80,20 +77,20 @@ impl ContextStrip {
|
||||
}
|
||||
}
|
||||
|
||||
fn suggested_context(&self, cx: &Context<Self>) -> Option<SuggestedContext> {
|
||||
fn suggested_context(&self, cx: &ViewContext<Self>) -> Option<SuggestedContext> {
|
||||
match self.suggest_context_kind {
|
||||
SuggestContextKind::File => self.suggested_file(cx),
|
||||
SuggestContextKind::Thread => self.suggested_thread(cx),
|
||||
}
|
||||
}
|
||||
|
||||
fn suggested_file(&self, cx: &Context<Self>) -> Option<SuggestedContext> {
|
||||
fn suggested_file(&self, cx: &ViewContext<Self>) -> Option<SuggestedContext> {
|
||||
let workspace = self.workspace.upgrade()?;
|
||||
let active_item = workspace.read(cx).active_item(cx)?;
|
||||
|
||||
let editor = active_item.to_any().downcast::<Editor>().ok()?.read(cx);
|
||||
let active_buffer_entity = editor.buffer().read(cx).as_singleton()?;
|
||||
let active_buffer = active_buffer_entity.read(cx);
|
||||
let active_buffer_model = editor.buffer().read(cx).as_singleton()?;
|
||||
let active_buffer = active_buffer_model.read(cx);
|
||||
|
||||
let path = active_buffer.file()?.path();
|
||||
|
||||
@@ -115,12 +112,12 @@ impl ContextStrip {
|
||||
|
||||
Some(SuggestedContext::File {
|
||||
name,
|
||||
buffer: active_buffer_entity.downgrade(),
|
||||
buffer: active_buffer_model.downgrade(),
|
||||
icon_path,
|
||||
})
|
||||
}
|
||||
|
||||
fn suggested_thread(&self, cx: &Context<Self>) -> Option<SuggestedContext> {
|
||||
fn suggested_thread(&self, cx: &ViewContext<Self>) -> Option<SuggestedContext> {
|
||||
if !self.context_picker.read(cx).allow_threads() {
|
||||
return None;
|
||||
}
|
||||
@@ -152,25 +149,24 @@ impl ContextStrip {
|
||||
|
||||
fn handle_context_picker_event(
|
||||
&mut self,
|
||||
_picker: &Entity<ContextPicker>,
|
||||
_picker: View<ContextPicker>,
|
||||
_event: &DismissEvent,
|
||||
_window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
cx.emit(ContextStripEvent::PickerDismissed);
|
||||
}
|
||||
|
||||
fn handle_focus(&mut self, _window: &mut Window, cx: &mut Context<Self>) {
|
||||
fn handle_focus(&mut self, cx: &mut ViewContext<Self>) {
|
||||
self.focused_index = self.last_pill_index();
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn handle_blur(&mut self, _window: &mut Window, cx: &mut Context<Self>) {
|
||||
fn handle_blur(&mut self, cx: &mut ViewContext<Self>) {
|
||||
self.focused_index = None;
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn focus_left(&mut self, _: &FocusLeft, _window: &mut Window, cx: &mut Context<Self>) {
|
||||
fn focus_left(&mut self, _: &FocusLeft, cx: &mut ViewContext<Self>) {
|
||||
self.focused_index = match self.focused_index {
|
||||
Some(index) if index > 0 => Some(index - 1),
|
||||
_ => self.last_pill_index(),
|
||||
@@ -179,7 +175,7 @@ impl ContextStrip {
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn focus_right(&mut self, _: &FocusRight, _window: &mut Window, cx: &mut Context<Self>) {
|
||||
fn focus_right(&mut self, _: &FocusRight, cx: &mut ViewContext<Self>) {
|
||||
let Some(last_index) = self.last_pill_index() else {
|
||||
return;
|
||||
};
|
||||
@@ -192,7 +188,7 @@ impl ContextStrip {
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn focus_up(&mut self, _: &FocusUp, _window: &mut Window, cx: &mut Context<Self>) {
|
||||
fn focus_up(&mut self, _: &FocusUp, cx: &mut ViewContext<Self>) {
|
||||
let Some(focused_index) = self.focused_index else {
|
||||
return;
|
||||
};
|
||||
@@ -210,7 +206,7 @@ impl ContextStrip {
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn focus_down(&mut self, _: &FocusDown, _window: &mut Window, cx: &mut Context<Self>) {
|
||||
fn focus_down(&mut self, _: &FocusDown, cx: &mut ViewContext<Self>) {
|
||||
let Some(focused_index) = self.focused_index else {
|
||||
return;
|
||||
};
|
||||
@@ -280,12 +276,7 @@ impl ContextStrip {
|
||||
best.map(|(index, _, _)| index)
|
||||
}
|
||||
|
||||
fn remove_focused_context(
|
||||
&mut self,
|
||||
_: &RemoveFocusedContext,
|
||||
_window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
fn remove_focused_context(&mut self, _: &RemoveFocusedContext, cx: &mut ViewContext<Self>) {
|
||||
if let Some(index) = self.focused_index {
|
||||
let mut is_empty = false;
|
||||
|
||||
@@ -311,32 +302,22 @@ impl ContextStrip {
|
||||
self.focused_index == Some(context.len())
|
||||
}
|
||||
|
||||
fn accept_suggested_context(
|
||||
&mut self,
|
||||
_: &AcceptSuggestedContext,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
fn accept_suggested_context(&mut self, _: &AcceptSuggestedContext, cx: &mut ViewContext<Self>) {
|
||||
if let Some(suggested) = self.suggested_context(cx) {
|
||||
let context_store = self.context_store.read(cx);
|
||||
|
||||
if self.is_suggested_focused(context_store.context()) {
|
||||
self.add_suggested_context(&suggested, window, cx);
|
||||
self.add_suggested_context(&suggested, cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn add_suggested_context(
|
||||
&mut self,
|
||||
suggested: &SuggestedContext,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
fn add_suggested_context(&mut self, suggested: &SuggestedContext, cx: &mut ViewContext<Self>) {
|
||||
let task = self.context_store.update(cx, |context_store, cx| {
|
||||
context_store.accept_suggested_context(&suggested, cx)
|
||||
});
|
||||
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
match task.await.notify_async_err(&mut cx) {
|
||||
None => {}
|
||||
Some(()) => {
|
||||
@@ -353,14 +334,14 @@ impl ContextStrip {
|
||||
}
|
||||
}
|
||||
|
||||
impl Focusable for ContextStrip {
|
||||
fn focus_handle(&self, _cx: &App) -> FocusHandle {
|
||||
impl FocusableView for ContextStrip {
|
||||
fn focus_handle(&self, _cx: &AppContext) -> FocusHandle {
|
||||
self.focus_handle.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for ContextStrip {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
let context_store = self.context_store.read(cx);
|
||||
let context = context_store
|
||||
.context()
|
||||
@@ -393,40 +374,39 @@ impl Render for ContextStrip {
|
||||
.on_action(cx.listener(Self::remove_focused_context))
|
||||
.on_action(cx.listener(Self::accept_suggested_context))
|
||||
.on_children_prepainted({
|
||||
let entity = cx.entity().downgrade();
|
||||
move |children_bounds, _window, cx| {
|
||||
entity
|
||||
.update(cx, |this, _| {
|
||||
this.children_bounds = Some(children_bounds);
|
||||
})
|
||||
.ok();
|
||||
let view = cx.view().downgrade();
|
||||
move |children_bounds, cx| {
|
||||
view.update(cx, |this, _| {
|
||||
this.children_bounds = Some(children_bounds);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
})
|
||||
.child(
|
||||
PopoverMenu::new("context-picker")
|
||||
.menu(move |window, cx| {
|
||||
.menu(move |cx| {
|
||||
context_picker.update(cx, |this, cx| {
|
||||
this.init(window, cx);
|
||||
this.init(cx);
|
||||
});
|
||||
|
||||
Some(context_picker.clone())
|
||||
})
|
||||
.trigger_with_tooltip(
|
||||
.trigger(
|
||||
IconButton::new("add-context", IconName::Plus)
|
||||
.icon_size(IconSize::Small)
|
||||
.style(ui::ButtonStyle::Filled),
|
||||
{
|
||||
let focus_handle = focus_handle.clone();
|
||||
move |window, cx| {
|
||||
Tooltip::for_action_in(
|
||||
"Add Context",
|
||||
&ToggleContextPicker,
|
||||
&focus_handle,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
}
|
||||
},
|
||||
.style(ui::ButtonStyle::Filled)
|
||||
.tooltip({
|
||||
let focus_handle = focus_handle.clone();
|
||||
|
||||
move |cx| {
|
||||
Tooltip::for_action_in(
|
||||
"Add Context",
|
||||
&ToggleContextPicker,
|
||||
&focus_handle,
|
||||
cx,
|
||||
)
|
||||
}
|
||||
}),
|
||||
)
|
||||
.attach(gpui::Corner::TopLeft)
|
||||
.anchor(gpui::Corner::BottomLeft)
|
||||
@@ -449,13 +429,8 @@ impl Render for ContextStrip {
|
||||
)
|
||||
.opacity(0.5)
|
||||
.children(
|
||||
KeyBinding::for_action_in(
|
||||
&ToggleContextPicker,
|
||||
&focus_handle,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
.map(|binding| binding.into_any_element()),
|
||||
KeyBinding::for_action_in(&ToggleContextPicker, &focus_handle, cx)
|
||||
.map(|binding| binding.into_any_element()),
|
||||
),
|
||||
)
|
||||
}
|
||||
@@ -468,7 +443,7 @@ impl Render for ContextStrip {
|
||||
Some({
|
||||
let id = context.id;
|
||||
let context_store = self.context_store.clone();
|
||||
Rc::new(cx.listener(move |_this, _event, _window, cx| {
|
||||
Rc::new(cx.listener(move |_this, _event, cx| {
|
||||
context_store.update(cx, |this, _cx| {
|
||||
this.remove_context(id);
|
||||
});
|
||||
@@ -476,7 +451,7 @@ impl Render for ContextStrip {
|
||||
}))
|
||||
}),
|
||||
)
|
||||
.on_click(Rc::new(cx.listener(move |this, _, _window, cx| {
|
||||
.on_click(Rc::new(cx.listener(move |this, _, cx| {
|
||||
this.focused_index = Some(i);
|
||||
cx.notify();
|
||||
})))
|
||||
@@ -489,11 +464,9 @@ impl Render for ContextStrip {
|
||||
suggested.kind(),
|
||||
self.is_suggested_focused(&context),
|
||||
)
|
||||
.on_click(Rc::new(cx.listener(
|
||||
move |this, _event, window, cx| {
|
||||
this.add_suggested_context(&suggested, window, cx);
|
||||
},
|
||||
))),
|
||||
.on_click(Rc::new(cx.listener(move |this, _event, cx| {
|
||||
this.add_suggested_context(&suggested, cx);
|
||||
}))),
|
||||
)
|
||||
})
|
||||
.when(!context.is_empty(), {
|
||||
@@ -503,20 +476,19 @@ impl Render for ContextStrip {
|
||||
.icon_size(IconSize::Small)
|
||||
.tooltip({
|
||||
let focus_handle = focus_handle.clone();
|
||||
move |window, cx| {
|
||||
move |cx| {
|
||||
Tooltip::for_action_in(
|
||||
"Remove All Context",
|
||||
&RemoveAllContext,
|
||||
&focus_handle,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
}
|
||||
})
|
||||
.on_click(cx.listener({
|
||||
let focus_handle = focus_handle.clone();
|
||||
move |_this, _event, window, cx| {
|
||||
focus_handle.dispatch_action(&RemoveAllContext, window, cx);
|
||||
move |_this, _event, cx| {
|
||||
focus_handle.dispatch_action(&RemoveAllContext, cx);
|
||||
}
|
||||
})),
|
||||
)
|
||||
@@ -544,11 +516,11 @@ pub enum SuggestedContext {
|
||||
File {
|
||||
name: SharedString,
|
||||
icon_path: Option<SharedString>,
|
||||
buffer: WeakEntity<Buffer>,
|
||||
buffer: WeakModel<Buffer>,
|
||||
},
|
||||
Thread {
|
||||
name: SharedString,
|
||||
thread: WeakEntity<Thread>,
|
||||
thread: WeakModel<Thread>,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
use assistant_context_editor::SavedContextMetadata;
|
||||
use chrono::{DateTime, Utc};
|
||||
use gpui::{prelude::*, Entity};
|
||||
|
||||
use crate::thread_store::{SavedThreadMetadata, ThreadStore};
|
||||
|
||||
pub enum HistoryEntry {
|
||||
Thread(SavedThreadMetadata),
|
||||
Context(SavedContextMetadata),
|
||||
}
|
||||
|
||||
impl HistoryEntry {
|
||||
pub fn updated_at(&self) -> DateTime<Utc> {
|
||||
match self {
|
||||
HistoryEntry::Thread(thread) => thread.updated_at,
|
||||
HistoryEntry::Context(context) => context.mtime.to_utc(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct HistoryStore {
|
||||
thread_store: Entity<ThreadStore>,
|
||||
context_store: Entity<assistant_context_editor::ContextStore>,
|
||||
}
|
||||
|
||||
impl HistoryStore {
|
||||
pub fn new(
|
||||
thread_store: Entity<ThreadStore>,
|
||||
context_store: Entity<assistant_context_editor::ContextStore>,
|
||||
_cx: &mut Context<Self>,
|
||||
) -> Self {
|
||||
Self {
|
||||
thread_store,
|
||||
context_store,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the number of history entries.
|
||||
pub fn entry_count(&self, cx: &mut Context<Self>) -> usize {
|
||||
self.entries(cx).len()
|
||||
}
|
||||
|
||||
pub fn entries(&self, cx: &mut Context<Self>) -> Vec<HistoryEntry> {
|
||||
let mut history_entries = Vec::new();
|
||||
|
||||
for thread in self.thread_store.update(cx, |this, _cx| this.threads()) {
|
||||
history_entries.push(HistoryEntry::Thread(thread));
|
||||
}
|
||||
|
||||
for context in self.context_store.update(cx, |this, _cx| this.contexts()) {
|
||||
history_entries.push(HistoryEntry::Context(context));
|
||||
}
|
||||
|
||||
history_entries.sort_unstable_by_key(|entry| std::cmp::Reverse(entry.updated_at()));
|
||||
history_entries
|
||||
}
|
||||
|
||||
pub fn recent_entries(&self, limit: usize, cx: &mut Context<Self>) -> Vec<HistoryEntry> {
|
||||
self.entries(cx).into_iter().take(limit).collect()
|
||||
}
|
||||
}
|
||||
@@ -16,8 +16,9 @@ use editor::{
|
||||
use feature_flags::{FeatureFlagAppExt as _, ZedPro};
|
||||
use fs::Fs;
|
||||
use gpui::{
|
||||
anchored, deferred, point, AnyElement, App, ClickEvent, Context, CursorStyle, Entity,
|
||||
EventEmitter, FocusHandle, Focusable, FontWeight, Subscription, TextStyle, WeakEntity, Window,
|
||||
anchored, deferred, point, AnyElement, AppContext, ClickEvent, CursorStyle, EventEmitter,
|
||||
FocusHandle, FocusableView, FontWeight, Model, Subscription, TextStyle, View, ViewContext,
|
||||
WeakModel, WeakView, WindowContext,
|
||||
};
|
||||
use language_model::{LanguageModel, LanguageModelRegistry};
|
||||
use language_model_selector::LanguageModelSelector;
|
||||
@@ -34,12 +35,12 @@ use util::ResultExt;
|
||||
use workspace::Workspace;
|
||||
|
||||
pub struct PromptEditor<T> {
|
||||
pub editor: Entity<Editor>,
|
||||
pub editor: View<Editor>,
|
||||
mode: PromptEditorMode,
|
||||
context_store: Entity<ContextStore>,
|
||||
context_strip: Entity<ContextStrip>,
|
||||
context_store: Model<ContextStore>,
|
||||
context_strip: View<ContextStrip>,
|
||||
context_picker_menu_handle: PopoverMenuHandle<ContextPicker>,
|
||||
model_selector: Entity<AssistantModelSelector>,
|
||||
model_selector: View<AssistantModelSelector>,
|
||||
model_selector_menu_handle: PopoverMenuHandle<LanguageModelSelector>,
|
||||
edited_since_done: bool,
|
||||
prompt_history: VecDeque<String>,
|
||||
@@ -55,8 +56,8 @@ pub struct PromptEditor<T> {
|
||||
impl<T: 'static> EventEmitter<PromptEditorEvent> for PromptEditor<T> {}
|
||||
|
||||
impl<T: 'static> Render for PromptEditor<T> {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let ui_font_size = ThemeSettings::get_global(cx).ui_font_size(cx);
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
let ui_font_size = ThemeSettings::get_global(cx).ui_font_size;
|
||||
let mut buttons = Vec::new();
|
||||
|
||||
let left_gutter_width = match &self.mode {
|
||||
@@ -86,7 +87,7 @@ impl<T: 'static> Render for PromptEditor<T> {
|
||||
PromptEditorMode::Terminal { .. } => Pixels::from(8.0),
|
||||
};
|
||||
|
||||
buttons.extend(self.render_buttons(window, cx));
|
||||
buttons.extend(self.render_buttons(cx));
|
||||
|
||||
v_flex()
|
||||
.key_context("PromptEditor")
|
||||
@@ -162,7 +163,9 @@ impl<T: 'static> Render for PromptEditor<T> {
|
||||
el.child(
|
||||
div()
|
||||
.id("error")
|
||||
.tooltip(Tooltip::text(error_message))
|
||||
.tooltip(move |cx| {
|
||||
Tooltip::text(error_message.clone(), cx)
|
||||
})
|
||||
.child(
|
||||
Icon::new(IconName::XCircle)
|
||||
.size(IconSize::Small)
|
||||
@@ -176,7 +179,7 @@ impl<T: 'static> Render for PromptEditor<T> {
|
||||
h_flex()
|
||||
.w_full()
|
||||
.justify_between()
|
||||
.child(div().flex_1().child(self.render_editor(window, cx)))
|
||||
.child(div().flex_1().child(self.render_editor(cx)))
|
||||
.child(
|
||||
WithRemSize::new(ui_font_size)
|
||||
.flex()
|
||||
@@ -206,8 +209,8 @@ impl<T: 'static> Render for PromptEditor<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: 'static> Focusable for PromptEditor<T> {
|
||||
fn focus_handle(&self, cx: &App) -> FocusHandle {
|
||||
impl<T: 'static> FocusableView for PromptEditor<T> {
|
||||
fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
|
||||
self.editor.focus_handle(cx)
|
||||
}
|
||||
}
|
||||
@@ -215,50 +218,47 @@ impl<T: 'static> Focusable for PromptEditor<T> {
|
||||
impl<T: 'static> PromptEditor<T> {
|
||||
const MAX_LINES: u8 = 8;
|
||||
|
||||
fn codegen_status<'a>(&'a self, cx: &'a App) -> &'a CodegenStatus {
|
||||
fn codegen_status<'a>(&'a self, cx: &'a AppContext) -> &'a CodegenStatus {
|
||||
match &self.mode {
|
||||
PromptEditorMode::Buffer { codegen, .. } => codegen.read(cx).status(cx),
|
||||
PromptEditorMode::Terminal { codegen, .. } => &codegen.read(cx).status,
|
||||
}
|
||||
}
|
||||
|
||||
fn subscribe_to_editor(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
fn subscribe_to_editor(&mut self, cx: &mut ViewContext<Self>) {
|
||||
self.editor_subscriptions.clear();
|
||||
self.editor_subscriptions.push(cx.subscribe_in(
|
||||
&self.editor,
|
||||
window,
|
||||
Self::handle_prompt_editor_events,
|
||||
));
|
||||
self.editor_subscriptions
|
||||
.push(cx.subscribe(&self.editor, Self::handle_prompt_editor_events));
|
||||
}
|
||||
|
||||
pub fn set_show_cursor_when_unfocused(
|
||||
&mut self,
|
||||
show_cursor_when_unfocused: bool,
|
||||
cx: &mut Context<Self>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
self.editor.update(cx, |editor, cx| {
|
||||
editor.set_show_cursor_when_unfocused(show_cursor_when_unfocused, cx)
|
||||
});
|
||||
}
|
||||
|
||||
pub fn unlink(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
pub fn unlink(&mut self, cx: &mut ViewContext<Self>) {
|
||||
let prompt = self.prompt(cx);
|
||||
let focus = self.editor.focus_handle(cx).contains_focused(window, cx);
|
||||
self.editor = cx.new(|cx| {
|
||||
let mut editor = Editor::auto_height(Self::MAX_LINES as usize, window, cx);
|
||||
let focus = self.editor.focus_handle(cx).contains_focused(cx);
|
||||
self.editor = cx.new_view(|cx| {
|
||||
let mut editor = Editor::auto_height(Self::MAX_LINES as usize, cx);
|
||||
editor.set_soft_wrap_mode(language::language_settings::SoftWrap::EditorWidth, cx);
|
||||
editor.set_placeholder_text(Self::placeholder_text(&self.mode, window, cx), cx);
|
||||
editor.set_placeholder_text(Self::placeholder_text(&self.mode, cx), cx);
|
||||
editor.set_placeholder_text("Add a prompt…", cx);
|
||||
editor.set_text(prompt, window, cx);
|
||||
editor.set_text(prompt, cx);
|
||||
if focus {
|
||||
window.focus(&editor.focus_handle(cx));
|
||||
editor.focus(cx);
|
||||
}
|
||||
editor
|
||||
});
|
||||
self.subscribe_to_editor(window, cx);
|
||||
self.subscribe_to_editor(cx);
|
||||
}
|
||||
|
||||
pub fn placeholder_text(mode: &PromptEditorMode, window: &mut Window, cx: &mut App) -> String {
|
||||
pub fn placeholder_text(mode: &PromptEditorMode, cx: &WindowContext) -> String {
|
||||
let action = match mode {
|
||||
PromptEditorMode::Buffer { codegen, .. } => {
|
||||
if codegen.read(cx).is_insertion {
|
||||
@@ -271,50 +271,46 @@ impl<T: 'static> PromptEditor<T> {
|
||||
};
|
||||
|
||||
let assistant_panel_keybinding =
|
||||
ui::text_for_action(&zed_actions::assistant::ToggleFocus, window, cx)
|
||||
ui::text_for_action(&zed_actions::assistant::ToggleFocus, cx)
|
||||
.map(|keybinding| format!("{keybinding} to chat ― "))
|
||||
.unwrap_or_default();
|
||||
|
||||
format!("{action}… ({assistant_panel_keybinding}↓↑ for history)")
|
||||
}
|
||||
|
||||
pub fn prompt(&self, cx: &App) -> String {
|
||||
pub fn prompt(&self, cx: &AppContext) -> String {
|
||||
self.editor.read(cx).text(cx)
|
||||
}
|
||||
|
||||
fn toggle_rate_limit_notice(
|
||||
&mut self,
|
||||
_: &ClickEvent,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
fn toggle_rate_limit_notice(&mut self, _: &ClickEvent, cx: &mut ViewContext<Self>) {
|
||||
self.show_rate_limit_notice = !self.show_rate_limit_notice;
|
||||
if self.show_rate_limit_notice {
|
||||
window.focus(&self.editor.focus_handle(cx));
|
||||
cx.focus_view(&self.editor);
|
||||
}
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn handle_prompt_editor_events(
|
||||
&mut self,
|
||||
_: &Entity<Editor>,
|
||||
_: View<Editor>,
|
||||
event: &EditorEvent,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
match event {
|
||||
EditorEvent::Edited { .. } => {
|
||||
if let Some(workspace) = window.root::<Workspace>().flatten() {
|
||||
workspace.update(cx, |workspace, cx| {
|
||||
let is_via_ssh = workspace
|
||||
.project()
|
||||
.update(cx, |project, _| project.is_via_ssh());
|
||||
if let Some(workspace) = cx.window_handle().downcast::<Workspace>() {
|
||||
workspace
|
||||
.update(cx, |workspace, cx| {
|
||||
let is_via_ssh = workspace
|
||||
.project()
|
||||
.update(cx, |project, _| project.is_via_ssh());
|
||||
|
||||
workspace
|
||||
.client()
|
||||
.telemetry()
|
||||
.log_edit_event("inline assist", is_via_ssh);
|
||||
});
|
||||
workspace
|
||||
.client()
|
||||
.telemetry()
|
||||
.log_edit_event("inline assist", is_via_ssh);
|
||||
})
|
||||
.log_err();
|
||||
}
|
||||
let prompt = self.editor.read(cx).text(cx);
|
||||
if self
|
||||
@@ -338,40 +334,20 @@ impl<T: 'static> PromptEditor<T> {
|
||||
}
|
||||
}
|
||||
|
||||
fn toggle_context_picker(
|
||||
&mut self,
|
||||
_: &ToggleContextPicker,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
self.context_picker_menu_handle.toggle(window, cx);
|
||||
fn toggle_context_picker(&mut self, _: &ToggleContextPicker, cx: &mut ViewContext<Self>) {
|
||||
self.context_picker_menu_handle.toggle(cx);
|
||||
}
|
||||
|
||||
fn toggle_model_selector(
|
||||
&mut self,
|
||||
_: &ToggleModelSelector,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
self.model_selector_menu_handle.toggle(window, cx);
|
||||
fn toggle_model_selector(&mut self, _: &ToggleModelSelector, cx: &mut ViewContext<Self>) {
|
||||
self.model_selector_menu_handle.toggle(cx);
|
||||
}
|
||||
|
||||
pub fn remove_all_context(
|
||||
&mut self,
|
||||
_: &RemoveAllContext,
|
||||
_window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
pub fn remove_all_context(&mut self, _: &RemoveAllContext, cx: &mut ViewContext<Self>) {
|
||||
self.context_store.update(cx, |store, _cx| store.clear());
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn cancel(
|
||||
&mut self,
|
||||
_: &editor::actions::Cancel,
|
||||
_window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
fn cancel(&mut self, _: &editor::actions::Cancel, cx: &mut ViewContext<Self>) {
|
||||
match self.codegen_status(cx) {
|
||||
CodegenStatus::Idle | CodegenStatus::Done | CodegenStatus::Error(_) => {
|
||||
cx.emit(PromptEditorEvent::CancelRequested);
|
||||
@@ -382,7 +358,7 @@ impl<T: 'static> PromptEditor<T> {
|
||||
}
|
||||
}
|
||||
|
||||
fn confirm(&mut self, _: &menu::Confirm, _window: &mut Window, cx: &mut Context<Self>) {
|
||||
fn confirm(&mut self, _: &menu::Confirm, cx: &mut ViewContext<Self>) {
|
||||
match self.codegen_status(cx) {
|
||||
CodegenStatus::Idle => {
|
||||
cx.emit(PromptEditorEvent::StartRequested);
|
||||
@@ -403,49 +379,49 @@ impl<T: 'static> PromptEditor<T> {
|
||||
}
|
||||
}
|
||||
|
||||
fn move_up(&mut self, _: &MoveUp, window: &mut Window, cx: &mut Context<Self>) {
|
||||
fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
|
||||
if let Some(ix) = self.prompt_history_ix {
|
||||
if ix > 0 {
|
||||
self.prompt_history_ix = Some(ix - 1);
|
||||
let prompt = self.prompt_history[ix - 1].as_str();
|
||||
self.editor.update(cx, |editor, cx| {
|
||||
editor.set_text(prompt, window, cx);
|
||||
editor.move_to_beginning(&Default::default(), window, cx);
|
||||
editor.set_text(prompt, cx);
|
||||
editor.move_to_beginning(&Default::default(), cx);
|
||||
});
|
||||
}
|
||||
} else if !self.prompt_history.is_empty() {
|
||||
self.prompt_history_ix = Some(self.prompt_history.len() - 1);
|
||||
let prompt = self.prompt_history[self.prompt_history.len() - 1].as_str();
|
||||
self.editor.update(cx, |editor, cx| {
|
||||
editor.set_text(prompt, window, cx);
|
||||
editor.move_to_beginning(&Default::default(), window, cx);
|
||||
editor.set_text(prompt, cx);
|
||||
editor.move_to_beginning(&Default::default(), cx);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn move_down(&mut self, _: &MoveDown, window: &mut Window, cx: &mut Context<Self>) {
|
||||
fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
|
||||
if let Some(ix) = self.prompt_history_ix {
|
||||
if ix < self.prompt_history.len() - 1 {
|
||||
self.prompt_history_ix = Some(ix + 1);
|
||||
let prompt = self.prompt_history[ix + 1].as_str();
|
||||
self.editor.update(cx, |editor, cx| {
|
||||
editor.set_text(prompt, window, cx);
|
||||
editor.move_to_end(&Default::default(), window, cx)
|
||||
editor.set_text(prompt, cx);
|
||||
editor.move_to_end(&Default::default(), cx)
|
||||
});
|
||||
} else {
|
||||
self.prompt_history_ix = None;
|
||||
let prompt = self.pending_prompt.as_str();
|
||||
self.editor.update(cx, |editor, cx| {
|
||||
editor.set_text(prompt, window, cx);
|
||||
editor.move_to_end(&Default::default(), window, cx)
|
||||
editor.set_text(prompt, cx);
|
||||
editor.move_to_end(&Default::default(), cx)
|
||||
});
|
||||
}
|
||||
} else {
|
||||
self.context_strip.focus_handle(cx).focus(window);
|
||||
cx.focus_view(&self.context_strip);
|
||||
}
|
||||
}
|
||||
|
||||
fn render_buttons(&self, _window: &mut Window, cx: &mut Context<Self>) -> Vec<AnyElement> {
|
||||
fn render_buttons(&self, cx: &mut ViewContext<Self>) -> Vec<AnyElement> {
|
||||
let mode = match &self.mode {
|
||||
PromptEditorMode::Buffer { codegen, .. } => {
|
||||
let codegen = codegen.read(cx);
|
||||
@@ -467,22 +443,21 @@ impl<T: 'static> PromptEditor<T> {
|
||||
.icon(IconName::Return)
|
||||
.icon_size(IconSize::XSmall)
|
||||
.icon_color(Color::Muted)
|
||||
.on_click(cx.listener(|_, _, _, cx| cx.emit(PromptEditorEvent::StartRequested)))
|
||||
.on_click(cx.listener(|_, _, cx| cx.emit(PromptEditorEvent::StartRequested)))
|
||||
.into_any_element()]
|
||||
}
|
||||
CodegenStatus::Pending => vec![IconButton::new("stop", IconName::Stop)
|
||||
.icon_color(Color::Error)
|
||||
.shape(IconButtonShape::Square)
|
||||
.tooltip(move |window, cx| {
|
||||
.tooltip(move |cx| {
|
||||
Tooltip::with_meta(
|
||||
mode.tooltip_interrupt(),
|
||||
Some(&menu::Cancel),
|
||||
"Changes won't be discarded",
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.on_click(cx.listener(|_, _, _, cx| cx.emit(PromptEditorEvent::StopRequested)))
|
||||
.on_click(cx.listener(|_, _, cx| cx.emit(PromptEditorEvent::StopRequested)))
|
||||
.into_any_element()],
|
||||
CodegenStatus::Done | CodegenStatus::Error(_) => {
|
||||
let has_error = matches!(codegen_status, CodegenStatus::Error(_));
|
||||
@@ -490,16 +465,15 @@ impl<T: 'static> PromptEditor<T> {
|
||||
vec![IconButton::new("restart", IconName::RotateCw)
|
||||
.icon_color(Color::Info)
|
||||
.shape(IconButtonShape::Square)
|
||||
.tooltip(move |window, cx| {
|
||||
.tooltip(move |cx| {
|
||||
Tooltip::with_meta(
|
||||
mode.tooltip_restart(),
|
||||
Some(&menu::Confirm),
|
||||
"Changes will be discarded",
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.on_click(cx.listener(|_, _, _, cx| {
|
||||
.on_click(cx.listener(|_, _, cx| {
|
||||
cx.emit(PromptEditorEvent::StartRequested);
|
||||
}))
|
||||
.into_any_element()]
|
||||
@@ -507,10 +481,10 @@ impl<T: 'static> PromptEditor<T> {
|
||||
let accept = IconButton::new("accept", IconName::Check)
|
||||
.icon_color(Color::Info)
|
||||
.shape(IconButtonShape::Square)
|
||||
.tooltip(move |window, cx| {
|
||||
Tooltip::for_action(mode.tooltip_accept(), &menu::Confirm, window, cx)
|
||||
.tooltip(move |cx| {
|
||||
Tooltip::for_action(mode.tooltip_accept(), &menu::Confirm, cx)
|
||||
})
|
||||
.on_click(cx.listener(|_, _, _, cx| {
|
||||
.on_click(cx.listener(|_, _, cx| {
|
||||
cx.emit(PromptEditorEvent::ConfirmRequested { execute: false });
|
||||
}))
|
||||
.into_any_element();
|
||||
@@ -521,15 +495,14 @@ impl<T: 'static> PromptEditor<T> {
|
||||
IconButton::new("confirm", IconName::Play)
|
||||
.icon_color(Color::Info)
|
||||
.shape(IconButtonShape::Square)
|
||||
.tooltip(|window, cx| {
|
||||
.tooltip(|cx| {
|
||||
Tooltip::for_action(
|
||||
"Execute Generated Command",
|
||||
&menu::SecondaryConfirm,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.on_click(cx.listener(|_, _, _, cx| {
|
||||
.on_click(cx.listener(|_, _, cx| {
|
||||
cx.emit(PromptEditorEvent::ConfirmRequested { execute: true });
|
||||
}))
|
||||
.into_any_element(),
|
||||
@@ -541,12 +514,7 @@ impl<T: 'static> PromptEditor<T> {
|
||||
}
|
||||
}
|
||||
|
||||
fn cycle_prev(
|
||||
&mut self,
|
||||
_: &CyclePreviousInlineAssist,
|
||||
_: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
fn cycle_prev(&mut self, _: &CyclePreviousInlineAssist, cx: &mut ViewContext<Self>) {
|
||||
match &self.mode {
|
||||
PromptEditorMode::Buffer { codegen, .. } => {
|
||||
codegen.update(cx, |codegen, cx| codegen.cycle_prev(cx));
|
||||
@@ -557,7 +525,7 @@ impl<T: 'static> PromptEditor<T> {
|
||||
}
|
||||
}
|
||||
|
||||
fn cycle_next(&mut self, _: &CycleNextInlineAssist, _: &mut Window, cx: &mut Context<Self>) {
|
||||
fn cycle_next(&mut self, _: &CycleNextInlineAssist, cx: &mut ViewContext<Self>) {
|
||||
match &self.mode {
|
||||
PromptEditorMode::Buffer { codegen, .. } => {
|
||||
codegen.update(cx, |codegen, cx| codegen.cycle_next(cx));
|
||||
@@ -568,16 +536,16 @@ impl<T: 'static> PromptEditor<T> {
|
||||
}
|
||||
}
|
||||
|
||||
fn render_close_button(&self, cx: &mut Context<Self>) -> AnyElement {
|
||||
fn render_close_button(&self, cx: &ViewContext<Self>) -> AnyElement {
|
||||
IconButton::new("cancel", IconName::Close)
|
||||
.icon_color(Color::Muted)
|
||||
.shape(IconButtonShape::Square)
|
||||
.tooltip(Tooltip::text("Close Assistant"))
|
||||
.on_click(cx.listener(|_, _, _, cx| cx.emit(PromptEditorEvent::CancelRequested)))
|
||||
.tooltip(|cx| Tooltip::text("Close Assistant", cx))
|
||||
.on_click(cx.listener(|_, _, cx| cx.emit(PromptEditorEvent::CancelRequested)))
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
fn render_cycle_controls(&self, codegen: &BufferCodegen, cx: &Context<Self>) -> AnyElement {
|
||||
fn render_cycle_controls(&self, codegen: &BufferCodegen, cx: &ViewContext<Self>) -> AnyElement {
|
||||
let disabled = matches!(codegen.status(cx), CodegenStatus::Idle);
|
||||
|
||||
let model_registry = LanguageModelRegistry::read_global(cx);
|
||||
@@ -617,13 +585,12 @@ impl<T: 'static> PromptEditor<T> {
|
||||
.shape(IconButtonShape::Square)
|
||||
.tooltip({
|
||||
let focus_handle = self.editor.focus_handle(cx);
|
||||
move |window, cx| {
|
||||
cx.new(|cx| {
|
||||
move |cx| {
|
||||
cx.new_view(|cx| {
|
||||
let mut tooltip = Tooltip::new("Previous Alternative").key_binding(
|
||||
KeyBinding::for_action_in(
|
||||
&CyclePreviousInlineAssist,
|
||||
&focus_handle,
|
||||
window,
|
||||
cx,
|
||||
),
|
||||
);
|
||||
@@ -635,8 +602,8 @@ impl<T: 'static> PromptEditor<T> {
|
||||
.into()
|
||||
}
|
||||
})
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
this.cycle_prev(&CyclePreviousInlineAssist, window, cx);
|
||||
.on_click(cx.listener(|this, _, cx| {
|
||||
this.cycle_prev(&CyclePreviousInlineAssist, cx);
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
@@ -659,13 +626,12 @@ impl<T: 'static> PromptEditor<T> {
|
||||
.shape(IconButtonShape::Square)
|
||||
.tooltip({
|
||||
let focus_handle = self.editor.focus_handle(cx);
|
||||
move |window, cx| {
|
||||
cx.new(|cx| {
|
||||
move |cx| {
|
||||
cx.new_view(|cx| {
|
||||
let mut tooltip = Tooltip::new("Next Alternative").key_binding(
|
||||
KeyBinding::for_action_in(
|
||||
&CycleNextInlineAssist,
|
||||
&focus_handle,
|
||||
window,
|
||||
cx,
|
||||
),
|
||||
);
|
||||
@@ -677,14 +643,14 @@ impl<T: 'static> PromptEditor<T> {
|
||||
.into()
|
||||
}
|
||||
})
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
this.cycle_next(&CycleNextInlineAssist, window, cx)
|
||||
})),
|
||||
.on_click(
|
||||
cx.listener(|this, _, cx| this.cycle_next(&CycleNextInlineAssist, cx)),
|
||||
),
|
||||
)
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
fn render_rate_limit_notice(&self, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
fn render_rate_limit_notice(&self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
Popover::new().child(
|
||||
v_flex()
|
||||
.occlude()
|
||||
@@ -708,7 +674,7 @@ impl<T: 'static> PromptEditor<T> {
|
||||
} else {
|
||||
ui::ToggleState::Unselected
|
||||
},
|
||||
|selection, _, cx| {
|
||||
|selection, cx| {
|
||||
let is_dismissed = match selection {
|
||||
ui::ToggleState::Unselected => false,
|
||||
ui::ToggleState::Indeterminate => return,
|
||||
@@ -727,11 +693,10 @@ impl<T: 'static> PromptEditor<T> {
|
||||
.on_click(cx.listener(Self::toggle_rate_limit_notice)),
|
||||
)
|
||||
.child(Button::new("more-info", "More Info").on_click(
|
||||
|_event, window, cx| {
|
||||
window.dispatch_action(
|
||||
Box::new(zed_actions::OpenAccountSettings),
|
||||
cx,
|
||||
)
|
||||
|_event, cx| {
|
||||
cx.dispatch_action(Box::new(
|
||||
zed_actions::OpenAccountSettings,
|
||||
))
|
||||
},
|
||||
)),
|
||||
),
|
||||
@@ -739,9 +704,9 @@ impl<T: 'static> PromptEditor<T> {
|
||||
)
|
||||
}
|
||||
|
||||
fn render_editor(&mut self, window: &mut Window, cx: &mut Context<Self>) -> AnyElement {
|
||||
fn render_editor(&mut self, cx: &mut ViewContext<Self>) -> AnyElement {
|
||||
let font_size = TextSize::Default.rems(cx);
|
||||
let line_height = font_size.to_pixels(window.rem_size()) * 1.3;
|
||||
let line_height = font_size.to_pixels(cx.rem_size()) * 1.3;
|
||||
|
||||
div()
|
||||
.key_context("InlineAssistEditor")
|
||||
@@ -775,15 +740,17 @@ impl<T: 'static> PromptEditor<T> {
|
||||
|
||||
fn handle_context_strip_event(
|
||||
&mut self,
|
||||
_context_strip: &Entity<ContextStrip>,
|
||||
_context_strip: View<ContextStrip>,
|
||||
event: &ContextStripEvent,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
match event {
|
||||
ContextStripEvent::PickerDismissed
|
||||
| ContextStripEvent::BlurredEmpty
|
||||
| ContextStripEvent::BlurredUp => self.editor.focus_handle(cx).focus(window),
|
||||
| ContextStripEvent::BlurredUp => {
|
||||
let editor_focus_handle = self.editor.focus_handle(cx);
|
||||
cx.focus(&editor_focus_handle);
|
||||
}
|
||||
ContextStripEvent::BlurredDown => {}
|
||||
}
|
||||
}
|
||||
@@ -792,12 +759,12 @@ impl<T: 'static> PromptEditor<T> {
|
||||
pub enum PromptEditorMode {
|
||||
Buffer {
|
||||
id: InlineAssistId,
|
||||
codegen: Entity<BufferCodegen>,
|
||||
codegen: Model<BufferCodegen>,
|
||||
gutter_dimensions: Arc<Mutex<GutterDimensions>>,
|
||||
},
|
||||
Terminal {
|
||||
id: TerminalInlineAssistId,
|
||||
codegen: Entity<TerminalCodegen>,
|
||||
codegen: Model<TerminalCodegen>,
|
||||
height_in_lines: u8,
|
||||
},
|
||||
}
|
||||
@@ -828,14 +795,13 @@ impl PromptEditor<BufferCodegen> {
|
||||
id: InlineAssistId,
|
||||
gutter_dimensions: Arc<Mutex<GutterDimensions>>,
|
||||
prompt_history: VecDeque<String>,
|
||||
prompt_buffer: Entity<MultiBuffer>,
|
||||
codegen: Entity<BufferCodegen>,
|
||||
prompt_buffer: Model<MultiBuffer>,
|
||||
codegen: Model<BufferCodegen>,
|
||||
fs: Arc<dyn Fs>,
|
||||
context_store: Entity<ContextStore>,
|
||||
workspace: WeakEntity<Workspace>,
|
||||
thread_store: Option<WeakEntity<ThreadStore>>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<PromptEditor<BufferCodegen>>,
|
||||
context_store: Model<ContextStore>,
|
||||
workspace: WeakView<Workspace>,
|
||||
thread_store: Option<WeakModel<ThreadStore>>,
|
||||
cx: &mut ViewContext<PromptEditor<BufferCodegen>>,
|
||||
) -> PromptEditor<BufferCodegen> {
|
||||
let codegen_subscription = cx.observe(&codegen, Self::handle_codegen_changed);
|
||||
let mode = PromptEditorMode::Buffer {
|
||||
@@ -844,7 +810,7 @@ impl PromptEditor<BufferCodegen> {
|
||||
gutter_dimensions,
|
||||
};
|
||||
|
||||
let prompt_editor = cx.new(|cx| {
|
||||
let prompt_editor = cx.new_view(|cx| {
|
||||
let mut editor = Editor::new(
|
||||
EditorMode::AutoHeight {
|
||||
max_lines: Self::MAX_LINES as usize,
|
||||
@@ -852,7 +818,6 @@ impl PromptEditor<BufferCodegen> {
|
||||
prompt_buffer,
|
||||
None,
|
||||
false,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
editor.set_soft_wrap_mode(language::language_settings::SoftWrap::EditorWidth, cx);
|
||||
@@ -860,13 +825,13 @@ impl PromptEditor<BufferCodegen> {
|
||||
// always show the cursor (even when it isn't focused) because
|
||||
// typing in one will make what you typed appear in all of them.
|
||||
editor.set_show_cursor_when_unfocused(true, cx);
|
||||
editor.set_placeholder_text(Self::placeholder_text(&mode, window, cx), cx);
|
||||
editor.set_placeholder_text(Self::placeholder_text(&mode, cx), cx);
|
||||
editor
|
||||
});
|
||||
let context_picker_menu_handle = PopoverMenuHandle::default();
|
||||
let model_selector_menu_handle = PopoverMenuHandle::default();
|
||||
|
||||
let context_strip = cx.new(|cx| {
|
||||
let context_strip = cx.new_view(|cx| {
|
||||
ContextStrip::new(
|
||||
context_store.clone(),
|
||||
workspace.clone(),
|
||||
@@ -874,25 +839,23 @@ impl PromptEditor<BufferCodegen> {
|
||||
thread_store.clone(),
|
||||
context_picker_menu_handle.clone(),
|
||||
SuggestContextKind::Thread,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
});
|
||||
|
||||
let context_strip_subscription =
|
||||
cx.subscribe_in(&context_strip, window, Self::handle_context_strip_event);
|
||||
cx.subscribe(&context_strip, Self::handle_context_strip_event);
|
||||
|
||||
let mut this: PromptEditor<BufferCodegen> = PromptEditor {
|
||||
editor: prompt_editor.clone(),
|
||||
context_store,
|
||||
context_strip,
|
||||
context_picker_menu_handle,
|
||||
model_selector: cx.new(|cx| {
|
||||
model_selector: cx.new_view(|cx| {
|
||||
AssistantModelSelector::new(
|
||||
fs,
|
||||
model_selector_menu_handle.clone(),
|
||||
prompt_editor.focus_handle(cx),
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
}),
|
||||
@@ -909,14 +872,14 @@ impl PromptEditor<BufferCodegen> {
|
||||
_phantom: Default::default(),
|
||||
};
|
||||
|
||||
this.subscribe_to_editor(window, cx);
|
||||
this.subscribe_to_editor(cx);
|
||||
this
|
||||
}
|
||||
|
||||
fn handle_codegen_changed(
|
||||
&mut self,
|
||||
_: Entity<BufferCodegen>,
|
||||
cx: &mut Context<PromptEditor<BufferCodegen>>,
|
||||
_: Model<BufferCodegen>,
|
||||
cx: &mut ViewContext<PromptEditor<BufferCodegen>>,
|
||||
) {
|
||||
match self.codegen_status(cx) {
|
||||
CodegenStatus::Idle => {
|
||||
@@ -955,7 +918,7 @@ impl PromptEditor<BufferCodegen> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn codegen(&self) -> &Entity<BufferCodegen> {
|
||||
pub fn codegen(&self) -> &Model<BufferCodegen> {
|
||||
match &self.mode {
|
||||
PromptEditorMode::Buffer { codegen, .. } => codegen,
|
||||
PromptEditorMode::Terminal { .. } => unreachable!(),
|
||||
@@ -988,14 +951,13 @@ impl PromptEditor<TerminalCodegen> {
|
||||
pub fn new_terminal(
|
||||
id: TerminalInlineAssistId,
|
||||
prompt_history: VecDeque<String>,
|
||||
prompt_buffer: Entity<MultiBuffer>,
|
||||
codegen: Entity<TerminalCodegen>,
|
||||
prompt_buffer: Model<MultiBuffer>,
|
||||
codegen: Model<TerminalCodegen>,
|
||||
fs: Arc<dyn Fs>,
|
||||
context_store: Entity<ContextStore>,
|
||||
workspace: WeakEntity<Workspace>,
|
||||
thread_store: Option<WeakEntity<ThreadStore>>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
context_store: Model<ContextStore>,
|
||||
workspace: WeakView<Workspace>,
|
||||
thread_store: Option<WeakModel<ThreadStore>>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Self {
|
||||
let codegen_subscription = cx.observe(&codegen, Self::handle_codegen_changed);
|
||||
let mode = PromptEditorMode::Terminal {
|
||||
@@ -1004,7 +966,7 @@ impl PromptEditor<TerminalCodegen> {
|
||||
height_in_lines: 1,
|
||||
};
|
||||
|
||||
let prompt_editor = cx.new(|cx| {
|
||||
let prompt_editor = cx.new_view(|cx| {
|
||||
let mut editor = Editor::new(
|
||||
EditorMode::AutoHeight {
|
||||
max_lines: Self::MAX_LINES as usize,
|
||||
@@ -1012,17 +974,16 @@ impl PromptEditor<TerminalCodegen> {
|
||||
prompt_buffer,
|
||||
None,
|
||||
false,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
editor.set_soft_wrap_mode(language::language_settings::SoftWrap::EditorWidth, cx);
|
||||
editor.set_placeholder_text(Self::placeholder_text(&mode, window, cx), cx);
|
||||
editor.set_placeholder_text(Self::placeholder_text(&mode, cx), cx);
|
||||
editor
|
||||
});
|
||||
let context_picker_menu_handle = PopoverMenuHandle::default();
|
||||
let model_selector_menu_handle = PopoverMenuHandle::default();
|
||||
|
||||
let context_strip = cx.new(|cx| {
|
||||
let context_strip = cx.new_view(|cx| {
|
||||
ContextStrip::new(
|
||||
context_store.clone(),
|
||||
workspace.clone(),
|
||||
@@ -1030,25 +991,23 @@ impl PromptEditor<TerminalCodegen> {
|
||||
thread_store.clone(),
|
||||
context_picker_menu_handle.clone(),
|
||||
SuggestContextKind::Thread,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
});
|
||||
|
||||
let context_strip_subscription =
|
||||
cx.subscribe_in(&context_strip, window, Self::handle_context_strip_event);
|
||||
cx.subscribe(&context_strip, Self::handle_context_strip_event);
|
||||
|
||||
let mut this = Self {
|
||||
editor: prompt_editor.clone(),
|
||||
context_store,
|
||||
context_strip,
|
||||
context_picker_menu_handle,
|
||||
model_selector: cx.new(|cx| {
|
||||
model_selector: cx.new_view(|cx| {
|
||||
AssistantModelSelector::new(
|
||||
fs,
|
||||
model_selector_menu_handle.clone(),
|
||||
prompt_editor.focus_handle(cx),
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
}),
|
||||
@@ -1065,11 +1024,11 @@ impl PromptEditor<TerminalCodegen> {
|
||||
_phantom: Default::default(),
|
||||
};
|
||||
this.count_lines(cx);
|
||||
this.subscribe_to_editor(window, cx);
|
||||
this.subscribe_to_editor(cx);
|
||||
this
|
||||
}
|
||||
|
||||
fn count_lines(&mut self, cx: &mut Context<Self>) {
|
||||
fn count_lines(&mut self, cx: &mut ViewContext<Self>) {
|
||||
let height_in_lines = cmp::max(
|
||||
2, // Make the editor at least two lines tall, to account for padding and buttons.
|
||||
cmp::min(
|
||||
@@ -1093,7 +1052,7 @@ impl PromptEditor<TerminalCodegen> {
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_codegen_changed(&mut self, _: Entity<TerminalCodegen>, cx: &mut Context<Self>) {
|
||||
fn handle_codegen_changed(&mut self, _: Model<TerminalCodegen>, cx: &mut ViewContext<Self>) {
|
||||
match &self.codegen().read(cx).status {
|
||||
CodegenStatus::Idle => {
|
||||
self.editor
|
||||
@@ -1111,7 +1070,7 @@ impl PromptEditor<TerminalCodegen> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn codegen(&self) -> &Entity<TerminalCodegen> {
|
||||
pub fn codegen(&self) -> &Model<TerminalCodegen> {
|
||||
match &self.mode {
|
||||
PromptEditorMode::Buffer { .. } => unreachable!(),
|
||||
PromptEditorMode::Terminal { codegen, .. } => codegen,
|
||||
@@ -1135,7 +1094,7 @@ fn dismissed_rate_limit_notice() -> bool {
|
||||
.map_or(false, |s| s.is_some())
|
||||
}
|
||||
|
||||
fn set_rate_limit_notice_dismissed(is_dismissed: bool, cx: &mut App) {
|
||||
fn set_rate_limit_notice_dismissed(is_dismissed: bool, cx: &mut AppContext) {
|
||||
db::write_and_log(cx, move || async move {
|
||||
if is_dismissed {
|
||||
db::kvp::KEY_VALUE_STORE
|
||||
|
||||
@@ -4,19 +4,16 @@ use editor::actions::MoveUp;
|
||||
use editor::{Editor, EditorElement, EditorEvent, EditorStyle};
|
||||
use fs::Fs;
|
||||
use gpui::{
|
||||
pulsating_between, Animation, AnimationExt, App, DismissEvent, Entity, Focusable, Subscription,
|
||||
TextStyle, WeakEntity,
|
||||
pulsating_between, Animation, AnimationExt, AppContext, DismissEvent, FocusableView, Model,
|
||||
Subscription, TextStyle, View, WeakModel, WeakView,
|
||||
};
|
||||
use language_model::{LanguageModelRegistry, LanguageModelRequestTool};
|
||||
use language_model_selector::LanguageModelSelector;
|
||||
use rope::Point;
|
||||
use settings::Settings;
|
||||
use std::time::Duration;
|
||||
use text::Bias;
|
||||
use theme::ThemeSettings;
|
||||
use ui::{
|
||||
prelude::*, ButtonLike, KeyBinding, PopoverMenu, PopoverMenuHandle, Switch, TintColor, Tooltip,
|
||||
};
|
||||
use ui::{prelude::*, ButtonLike, KeyBinding, PopoverMenu, PopoverMenuHandle, Switch, TintColor};
|
||||
use workspace::Workspace;
|
||||
|
||||
use crate::assistant_model_selector::AssistantModelSelector;
|
||||
@@ -28,14 +25,14 @@ use crate::thread_store::ThreadStore;
|
||||
use crate::{Chat, ChatMode, RemoveAllContext, ToggleContextPicker, ToggleModelSelector};
|
||||
|
||||
pub struct MessageEditor {
|
||||
thread: Entity<Thread>,
|
||||
editor: Entity<Editor>,
|
||||
context_store: Entity<ContextStore>,
|
||||
context_strip: Entity<ContextStrip>,
|
||||
thread: Model<Thread>,
|
||||
editor: View<Editor>,
|
||||
context_store: Model<ContextStore>,
|
||||
context_strip: View<ContextStrip>,
|
||||
context_picker_menu_handle: PopoverMenuHandle<ContextPicker>,
|
||||
inline_context_picker: Entity<ContextPicker>,
|
||||
inline_context_picker: View<ContextPicker>,
|
||||
inline_context_picker_menu_handle: PopoverMenuHandle<ContextPicker>,
|
||||
model_selector: Entity<AssistantModelSelector>,
|
||||
model_selector: View<AssistantModelSelector>,
|
||||
model_selector_menu_handle: PopoverMenuHandle<LanguageModelSelector>,
|
||||
use_tools: bool,
|
||||
_subscriptions: Vec<Subscription>,
|
||||
@@ -44,38 +41,36 @@ pub struct MessageEditor {
|
||||
impl MessageEditor {
|
||||
pub fn new(
|
||||
fs: Arc<dyn Fs>,
|
||||
workspace: WeakEntity<Workspace>,
|
||||
thread_store: WeakEntity<ThreadStore>,
|
||||
thread: Entity<Thread>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
workspace: WeakView<Workspace>,
|
||||
thread_store: WeakModel<ThreadStore>,
|
||||
thread: Model<Thread>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Self {
|
||||
let context_store = cx.new(|_cx| ContextStore::new(workspace.clone()));
|
||||
let context_store = cx.new_model(|_cx| ContextStore::new(workspace.clone()));
|
||||
let context_picker_menu_handle = PopoverMenuHandle::default();
|
||||
let inline_context_picker_menu_handle = PopoverMenuHandle::default();
|
||||
let model_selector_menu_handle = PopoverMenuHandle::default();
|
||||
|
||||
let editor = cx.new(|cx| {
|
||||
let mut editor = Editor::auto_height(10, window, cx);
|
||||
let editor = cx.new_view(|cx| {
|
||||
let mut editor = Editor::auto_height(10, cx);
|
||||
editor.set_placeholder_text("Ask anything, @ to mention, ↑ to select", cx);
|
||||
editor.set_show_indent_guides(false, cx);
|
||||
|
||||
editor
|
||||
});
|
||||
|
||||
let inline_context_picker = cx.new(|cx| {
|
||||
let inline_context_picker = cx.new_view(|cx| {
|
||||
ContextPicker::new(
|
||||
workspace.clone(),
|
||||
Some(thread_store.clone()),
|
||||
context_store.downgrade(),
|
||||
editor.downgrade(),
|
||||
ConfirmBehavior::Close,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
});
|
||||
|
||||
let context_strip = cx.new(|cx| {
|
||||
let context_strip = cx.new_view(|cx| {
|
||||
ContextStrip::new(
|
||||
context_store.clone(),
|
||||
workspace.clone(),
|
||||
@@ -83,19 +78,17 @@ impl MessageEditor {
|
||||
Some(thread_store.clone()),
|
||||
context_picker_menu_handle.clone(),
|
||||
SuggestContextKind::File,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
});
|
||||
|
||||
let subscriptions = vec![
|
||||
cx.subscribe_in(&editor, window, Self::handle_editor_event),
|
||||
cx.subscribe_in(
|
||||
cx.subscribe(&editor, Self::handle_editor_event),
|
||||
cx.subscribe(
|
||||
&inline_context_picker,
|
||||
window,
|
||||
Self::handle_inline_context_picker_event,
|
||||
),
|
||||
cx.subscribe_in(&context_strip, window, Self::handle_context_strip_event),
|
||||
cx.subscribe(&context_strip, Self::handle_context_strip_event),
|
||||
];
|
||||
|
||||
Self {
|
||||
@@ -106,12 +99,11 @@ impl MessageEditor {
|
||||
context_picker_menu_handle,
|
||||
inline_context_picker,
|
||||
inline_context_picker_menu_handle,
|
||||
model_selector: cx.new(|cx| {
|
||||
model_selector: cx.new_view(|cx| {
|
||||
AssistantModelSelector::new(
|
||||
fs,
|
||||
model_selector_menu_handle.clone(),
|
||||
editor.focus_handle(cx),
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
}),
|
||||
@@ -121,59 +113,29 @@ impl MessageEditor {
|
||||
}
|
||||
}
|
||||
|
||||
fn toggle_model_selector(
|
||||
&mut self,
|
||||
_: &ToggleModelSelector,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
self.model_selector_menu_handle.toggle(window, cx)
|
||||
fn toggle_model_selector(&mut self, _: &ToggleModelSelector, cx: &mut ViewContext<Self>) {
|
||||
self.model_selector_menu_handle.toggle(cx)
|
||||
}
|
||||
|
||||
fn toggle_chat_mode(&mut self, _: &ChatMode, _window: &mut Window, cx: &mut Context<Self>) {
|
||||
fn toggle_chat_mode(&mut self, _: &ChatMode, cx: &mut ViewContext<Self>) {
|
||||
self.use_tools = !self.use_tools;
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn toggle_context_picker(
|
||||
&mut self,
|
||||
_: &ToggleContextPicker,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
self.context_picker_menu_handle.toggle(window, cx);
|
||||
fn toggle_context_picker(&mut self, _: &ToggleContextPicker, cx: &mut ViewContext<Self>) {
|
||||
self.context_picker_menu_handle.toggle(cx);
|
||||
}
|
||||
|
||||
pub fn remove_all_context(
|
||||
&mut self,
|
||||
_: &RemoveAllContext,
|
||||
_window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
pub fn remove_all_context(&mut self, _: &RemoveAllContext, cx: &mut ViewContext<Self>) {
|
||||
self.context_store.update(cx, |store, _cx| store.clear());
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn chat(&mut self, _: &Chat, window: &mut Window, cx: &mut Context<Self>) {
|
||||
self.send_to_model(RequestKind::Chat, window, cx);
|
||||
fn chat(&mut self, _: &Chat, cx: &mut ViewContext<Self>) {
|
||||
self.send_to_model(RequestKind::Chat, cx);
|
||||
}
|
||||
|
||||
fn is_editor_empty(&self, cx: &App) -> bool {
|
||||
self.editor.read(cx).text(cx).is_empty()
|
||||
}
|
||||
|
||||
fn is_model_selected(&self, cx: &App) -> bool {
|
||||
LanguageModelRegistry::read_global(cx)
|
||||
.active_model()
|
||||
.is_some()
|
||||
}
|
||||
|
||||
fn send_to_model(
|
||||
&mut self,
|
||||
request_kind: RequestKind,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
fn send_to_model(&mut self, request_kind: RequestKind, cx: &mut ViewContext<Self>) {
|
||||
let provider = LanguageModelRegistry::read_global(cx).active_provider();
|
||||
if provider
|
||||
.as_ref()
|
||||
@@ -190,7 +152,7 @@ impl MessageEditor {
|
||||
|
||||
let user_message = self.editor.update(cx, |editor, cx| {
|
||||
let text = editor.text(cx);
|
||||
editor.clear(window, cx);
|
||||
editor.clear(cx);
|
||||
text
|
||||
});
|
||||
|
||||
@@ -229,10 +191,9 @@ impl MessageEditor {
|
||||
|
||||
fn handle_editor_event(
|
||||
&mut self,
|
||||
editor: &Entity<Editor>,
|
||||
editor: View<Editor>,
|
||||
event: &EditorEvent,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
match event {
|
||||
EditorEvent::SelectionsChanged { .. } => {
|
||||
@@ -240,13 +201,10 @@ impl MessageEditor {
|
||||
let snapshot = editor.buffer().read(cx).snapshot(cx);
|
||||
let newest_cursor = editor.selections.newest::<Point>(cx).head();
|
||||
if newest_cursor.column > 0 {
|
||||
let behind_cursor = snapshot.clip_point(
|
||||
Point::new(newest_cursor.row, newest_cursor.column - 1),
|
||||
Bias::Left,
|
||||
);
|
||||
let behind_cursor = Point::new(newest_cursor.row, newest_cursor.column - 1);
|
||||
let char_behind_cursor = snapshot.chars_at(behind_cursor).next();
|
||||
if char_behind_cursor == Some('@') {
|
||||
self.inline_context_picker_menu_handle.show(window, cx);
|
||||
self.inline_context_picker_menu_handle.show(cx);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -257,66 +215,57 @@ impl MessageEditor {
|
||||
|
||||
fn handle_inline_context_picker_event(
|
||||
&mut self,
|
||||
_inline_context_picker: &Entity<ContextPicker>,
|
||||
_inline_context_picker: View<ContextPicker>,
|
||||
_event: &DismissEvent,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
let editor_focus_handle = self.editor.focus_handle(cx);
|
||||
window.focus(&editor_focus_handle);
|
||||
cx.focus(&editor_focus_handle);
|
||||
}
|
||||
|
||||
fn handle_context_strip_event(
|
||||
&mut self,
|
||||
_context_strip: &Entity<ContextStrip>,
|
||||
_context_strip: View<ContextStrip>,
|
||||
event: &ContextStripEvent,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
match event {
|
||||
ContextStripEvent::PickerDismissed
|
||||
| ContextStripEvent::BlurredEmpty
|
||||
| ContextStripEvent::BlurredDown => {
|
||||
let editor_focus_handle = self.editor.focus_handle(cx);
|
||||
window.focus(&editor_focus_handle);
|
||||
cx.focus(&editor_focus_handle);
|
||||
}
|
||||
ContextStripEvent::BlurredUp => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn move_up(&mut self, _: &MoveUp, window: &mut Window, cx: &mut Context<Self>) {
|
||||
fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
|
||||
if self.context_picker_menu_handle.is_deployed()
|
||||
|| self.inline_context_picker_menu_handle.is_deployed()
|
||||
{
|
||||
cx.propagate();
|
||||
} else {
|
||||
self.context_strip.focus_handle(cx).focus(window);
|
||||
cx.focus_view(&self.context_strip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Focusable for MessageEditor {
|
||||
fn focus_handle(&self, cx: &App) -> gpui::FocusHandle {
|
||||
impl FocusableView for MessageEditor {
|
||||
fn focus_handle(&self, cx: &AppContext) -> gpui::FocusHandle {
|
||||
self.editor.focus_handle(cx)
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for MessageEditor {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
let font_size = TextSize::Default.rems(cx);
|
||||
let line_height = font_size.to_pixels(window.rem_size()) * 1.5;
|
||||
let line_height = font_size.to_pixels(cx.rem_size()) * 1.5;
|
||||
let focus_handle = self.editor.focus_handle(cx);
|
||||
let inline_context_picker = self.inline_context_picker.clone();
|
||||
let bg_color = cx.theme().colors().editor_background;
|
||||
let is_streaming_completion = self.thread.read(cx).is_streaming();
|
||||
let button_width = px(64.);
|
||||
let is_model_selected = self.is_model_selected(cx);
|
||||
let is_editor_empty = self.is_editor_empty(cx);
|
||||
let submit_label_color = if is_editor_empty {
|
||||
Color::Muted
|
||||
} else {
|
||||
Color::Default
|
||||
};
|
||||
|
||||
v_flex()
|
||||
.key_context("MessageEditor")
|
||||
@@ -358,9 +307,9 @@ impl Render for MessageEditor {
|
||||
})
|
||||
.child(
|
||||
PopoverMenu::new("inline-context-picker")
|
||||
.menu(move |window, cx| {
|
||||
.menu(move |cx| {
|
||||
inline_context_picker.update(cx, |this, cx| {
|
||||
this.init(window, cx);
|
||||
this.init(cx);
|
||||
});
|
||||
|
||||
Some(inline_context_picker.clone())
|
||||
@@ -369,7 +318,11 @@ impl Render for MessageEditor {
|
||||
.anchor(gpui::Corner::BottomLeft)
|
||||
.offset(gpui::Point {
|
||||
x: px(0.0),
|
||||
y: (-ThemeSettings::get_global(cx).ui_font_size(cx) * 2) - px(4.0),
|
||||
y: px(-ThemeSettings::clamp_font_size(
|
||||
ThemeSettings::get_global(cx).ui_font_size,
|
||||
)
|
||||
.0 * 2.0)
|
||||
- px(4.0),
|
||||
})
|
||||
.with_handle(self.inline_context_picker_menu_handle.clone()),
|
||||
)
|
||||
@@ -379,7 +332,7 @@ impl Render for MessageEditor {
|
||||
.child(
|
||||
Switch::new("use-tools", self.use_tools.into())
|
||||
.label("Tools")
|
||||
.on_click(cx.listener(|this, selection, _window, _cx| {
|
||||
.on_click(cx.listener(|this, selection, _cx| {
|
||||
this.use_tools = match selection {
|
||||
ToggleState::Selected => true,
|
||||
ToggleState::Unselected
|
||||
@@ -389,7 +342,6 @@ impl Render for MessageEditor {
|
||||
.key_binding(KeyBinding::for_action_in(
|
||||
&ChatMode,
|
||||
&focus_handle,
|
||||
window,
|
||||
cx,
|
||||
)),
|
||||
)
|
||||
@@ -419,54 +371,35 @@ impl Render for MessageEditor {
|
||||
KeyBinding::for_action_in(
|
||||
&editor::actions::Cancel,
|
||||
&focus_handle,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
.map(|binding| binding.into_any_element()),
|
||||
),
|
||||
)
|
||||
.on_click(move |_event, window, cx| {
|
||||
focus_handle.dispatch_action(
|
||||
&editor::actions::Cancel,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
.on_click(move |_event, cx| {
|
||||
focus_handle
|
||||
.dispatch_action(&editor::actions::Cancel, cx);
|
||||
})
|
||||
} else {
|
||||
ButtonLike::new("submit-message")
|
||||
.width(button_width.into())
|
||||
.style(ButtonStyle::Filled)
|
||||
.disabled(is_editor_empty || !is_model_selected)
|
||||
.child(
|
||||
h_flex()
|
||||
.w_full()
|
||||
.justify_between()
|
||||
.child(
|
||||
Label::new("Submit")
|
||||
.size(LabelSize::Small)
|
||||
.color(submit_label_color),
|
||||
)
|
||||
.child(Label::new("Submit").size(LabelSize::Small))
|
||||
.children(
|
||||
KeyBinding::for_action_in(
|
||||
&Chat,
|
||||
&focus_handle,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
.map(|binding| binding.into_any_element()),
|
||||
),
|
||||
)
|
||||
.on_click(move |_event, window, cx| {
|
||||
focus_handle.dispatch_action(&Chat, window, cx);
|
||||
})
|
||||
.when(is_editor_empty, |button| {
|
||||
button
|
||||
.tooltip(Tooltip::text("Type a message to submit"))
|
||||
})
|
||||
.when(!is_model_selected, |button| {
|
||||
button.tooltip(Tooltip::text(
|
||||
"Select a model to continue",
|
||||
))
|
||||
.on_click(move |_event, cx| {
|
||||
focus_handle.dispatch_action(&Chat, cx);
|
||||
})
|
||||
},
|
||||
)),
|
||||
|
||||