Compare commits
1 Commits
remove-ext
...
cole/panic
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a49611b0e |
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@@ -29,7 +29,7 @@ jobs:
|
||||
outputs:
|
||||
docs_only: ${{ steps.check_changes.outputs.docs_only }}
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Check for non-docs changes
|
||||
@@ -364,8 +364,6 @@ jobs:
|
||||
env:
|
||||
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: Checkout repo
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
@@ -412,8 +410,6 @@ jobs:
|
||||
env:
|
||||
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: Checkout repo
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
|
||||
365
Cargo.lock
generated
365
Cargo.lock
generated
@@ -258,9 +258,9 @@ checksum = "34cd60c5e3152cef0a592f1b296f1cc93715d89d2551d85315828c3a09575ff4"
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.95"
|
||||
version = "1.0.94"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
|
||||
checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7"
|
||||
|
||||
[[package]]
|
||||
name = "approx"
|
||||
@@ -388,7 +388,7 @@ dependencies = [
|
||||
"ctor",
|
||||
"db",
|
||||
"editor",
|
||||
"env_logger 0.11.6",
|
||||
"env_logger 0.11.5",
|
||||
"feature_flags",
|
||||
"fs",
|
||||
"futures 0.3.31",
|
||||
@@ -579,9 +579,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "async-broadcast"
|
||||
version = "0.7.2"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532"
|
||||
checksum = "20cd0e2e25ea8e5f7e9df04578dc6cf5c83577fd09b1a46aaf5c85e1c33f2a7e"
|
||||
dependencies = [
|
||||
"event-listener 5.3.1",
|
||||
"event-listener-strategy",
|
||||
@@ -1805,14 +1805,16 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "blade-graphics"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/kvark/blade?rev=091a8401033847bb9b6ace3fcf70448d069621c5#091a8401033847bb9b6ace3fcf70448d069621c5"
|
||||
version = "0.5.0"
|
||||
source = "git+https://github.com/kvark/blade?rev=099555282605c7c4cca9e66a8f40148298347f80#099555282605c7c4cca9e66a8f40148298347f80"
|
||||
dependencies = [
|
||||
"ash",
|
||||
"ash-window",
|
||||
"bitflags 2.6.0",
|
||||
"block",
|
||||
"bytemuck",
|
||||
"codespan-reporting",
|
||||
"core-graphics-types 0.1.3",
|
||||
"glow",
|
||||
"gpu-alloc",
|
||||
"gpu-alloc-ash",
|
||||
@@ -1821,14 +1823,10 @@ dependencies = [
|
||||
"khronos-egl",
|
||||
"libloading",
|
||||
"log",
|
||||
"metal",
|
||||
"mint",
|
||||
"naga",
|
||||
"objc2",
|
||||
"objc2-app-kit",
|
||||
"objc2-foundation",
|
||||
"objc2-metal",
|
||||
"objc2-quartz-core",
|
||||
"objc2-ui-kit",
|
||||
"objc",
|
||||
"raw-window-handle",
|
||||
"slab",
|
||||
"wasm-bindgen",
|
||||
@@ -1838,7 +1836,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "blade-macros"
|
||||
version = "0.3.0"
|
||||
source = "git+https://github.com/kvark/blade?rev=091a8401033847bb9b6ace3fcf70448d069621c5#091a8401033847bb9b6ace3fcf70448d069621c5"
|
||||
source = "git+https://github.com/kvark/blade?rev=099555282605c7c4cca9e66a8f40148298347f80#099555282605c7c4cca9e66a8f40148298347f80"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1847,8 +1845,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "blade-util"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/kvark/blade?rev=091a8401033847bb9b6ace3fcf70448d069621c5#091a8401033847bb9b6ace3fcf70448d069621c5"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/kvark/blade?rev=099555282605c7c4cca9e66a8f40148298347f80#099555282605c7c4cca9e66a8f40148298347f80"
|
||||
dependencies = [
|
||||
"blade-graphics",
|
||||
"bytemuck",
|
||||
@@ -1893,15 +1891,6 @@ dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block2"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blocking"
|
||||
version = "1.6.1"
|
||||
@@ -1945,10 +1934,10 @@ dependencies = [
|
||||
"editor",
|
||||
"gpui",
|
||||
"itertools 0.13.0",
|
||||
"outline",
|
||||
"theme",
|
||||
"ui",
|
||||
"workspace",
|
||||
"zed_actions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2152,7 +2141,7 @@ dependencies = [
|
||||
"cap-primitives",
|
||||
"cap-std",
|
||||
"io-lifetimes 2.0.4",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2180,7 +2169,7 @@ dependencies = [
|
||||
"ipnet",
|
||||
"maybe-owned",
|
||||
"rustix 0.38.42",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
"winx",
|
||||
]
|
||||
|
||||
@@ -2495,6 +2484,7 @@ dependencies = [
|
||||
"exec",
|
||||
"fork",
|
||||
"ipc-channel",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"paths",
|
||||
"plist",
|
||||
@@ -2521,6 +2511,7 @@ dependencies = [
|
||||
"gpui",
|
||||
"http_client",
|
||||
"log",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"paths",
|
||||
"postage",
|
||||
@@ -2663,7 +2654,7 @@ dependencies = [
|
||||
"dashmap 6.1.0",
|
||||
"derive_more",
|
||||
"editor",
|
||||
"env_logger 0.11.6",
|
||||
"env_logger 0.11.5",
|
||||
"envy",
|
||||
"extension",
|
||||
"file_finder",
|
||||
@@ -2819,7 +2810,7 @@ dependencies = [
|
||||
"command_palette_hooks",
|
||||
"ctor",
|
||||
"editor",
|
||||
"env_logger 0.11.6",
|
||||
"env_logger 0.11.5",
|
||||
"fuzzy",
|
||||
"go_to_line",
|
||||
"gpui",
|
||||
@@ -2928,6 +2919,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"settings",
|
||||
"smol",
|
||||
"ui",
|
||||
"url",
|
||||
"util",
|
||||
"workspace",
|
||||
@@ -3689,7 +3681,7 @@ dependencies = [
|
||||
"collections",
|
||||
"ctor",
|
||||
"editor",
|
||||
"env_logger 0.11.6",
|
||||
"env_logger 0.11.5",
|
||||
"feature_flags",
|
||||
"gpui",
|
||||
"language",
|
||||
@@ -3894,7 +3886,7 @@ dependencies = [
|
||||
"ctor",
|
||||
"db",
|
||||
"emojis",
|
||||
"env_logger 0.11.6",
|
||||
"env_logger 0.11.5",
|
||||
"feature_flags",
|
||||
"file_icons",
|
||||
"fs",
|
||||
@@ -4091,9 +4083,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.11.6"
|
||||
version = "0.11.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0"
|
||||
checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
@@ -4145,7 +4137,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4197,7 +4189,7 @@ dependencies = [
|
||||
"client",
|
||||
"clock",
|
||||
"collections",
|
||||
"env_logger 0.11.6",
|
||||
"env_logger 0.11.5",
|
||||
"feature_flags",
|
||||
"fs",
|
||||
"git",
|
||||
@@ -4313,7 +4305,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"env_logger 0.11.6",
|
||||
"env_logger 0.11.5",
|
||||
"extension",
|
||||
"fs",
|
||||
"language",
|
||||
@@ -4341,7 +4333,7 @@ dependencies = [
|
||||
"collections",
|
||||
"context_server_settings",
|
||||
"ctor",
|
||||
"env_logger 0.11.6",
|
||||
"env_logger 0.11.5",
|
||||
"extension",
|
||||
"fs",
|
||||
"futures 0.3.31",
|
||||
@@ -4534,7 +4526,7 @@ dependencies = [
|
||||
"collections",
|
||||
"ctor",
|
||||
"editor",
|
||||
"env_logger 0.11.6",
|
||||
"env_logger 0.11.5",
|
||||
"file_icons",
|
||||
"futures 0.3.31",
|
||||
"fuzzy",
|
||||
@@ -4812,7 +4804,7 @@ checksum = "5e2e6123af26f0f2c51cc66869137080199406754903cc926a7690401ce09cb4"
|
||||
dependencies = [
|
||||
"io-lifetimes 2.0.4",
|
||||
"rustix 0.38.42",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5335,7 +5327,7 @@ dependencies = [
|
||||
"ctor",
|
||||
"derive_more",
|
||||
"embed-resource",
|
||||
"env_logger 0.11.6",
|
||||
"env_logger 0.11.5",
|
||||
"etagere",
|
||||
"filedescriptor",
|
||||
"flume",
|
||||
@@ -5352,8 +5344,6 @@ dependencies = [
|
||||
"metal",
|
||||
"num_cpus",
|
||||
"objc",
|
||||
"objc2",
|
||||
"objc2-metal",
|
||||
"oo7",
|
||||
"open",
|
||||
"parking",
|
||||
@@ -6388,7 +6378,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2285ddfe3054097ef4b2fe909ef8c3bcd1ea52a8f0d274416caebeef39f04a65"
|
||||
dependencies = [
|
||||
"io-lifetimes 2.0.4",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6691,7 +6681,7 @@ dependencies = [
|
||||
"collections",
|
||||
"ctor",
|
||||
"ec4rs",
|
||||
"env_logger 0.11.6",
|
||||
"env_logger 0.11.5",
|
||||
"fs",
|
||||
"futures 0.3.31",
|
||||
"fuzzy",
|
||||
@@ -6858,7 +6848,7 @@ dependencies = [
|
||||
"collections",
|
||||
"copilot",
|
||||
"editor",
|
||||
"env_logger 0.11.6",
|
||||
"env_logger 0.11.5",
|
||||
"futures 0.3.31",
|
||||
"gpui",
|
||||
"itertools 0.13.0",
|
||||
@@ -6956,9 +6946,9 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.169"
|
||||
version = "0.2.168"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
|
||||
checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d"
|
||||
|
||||
[[package]]
|
||||
name = "libdbus-sys"
|
||||
@@ -6999,7 +6989,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-targets 0.48.5",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7043,7 +7033,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "libwebrtc"
|
||||
version = "0.3.7"
|
||||
source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=060964da10574cd9bf06463a53bf6e0769c5c45e#060964da10574cd9bf06463a53bf6e0769c5c45e"
|
||||
source = "git+https://github.com/zed-industries/rust-sdks?rev=799f10133d93ba2a88642cd480d01ec4da53408c#799f10133d93ba2a88642cd480d01ec4da53408c"
|
||||
dependencies = [
|
||||
"cxx",
|
||||
"jni",
|
||||
@@ -7134,7 +7124,7 @@ checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104"
|
||||
[[package]]
|
||||
name = "livekit"
|
||||
version = "0.7.0"
|
||||
source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=060964da10574cd9bf06463a53bf6e0769c5c45e#060964da10574cd9bf06463a53bf6e0769c5c45e"
|
||||
source = "git+https://github.com/zed-industries/rust-sdks?rev=799f10133d93ba2a88642cd480d01ec4da53408c#799f10133d93ba2a88642cd480d01ec4da53408c"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"futures-util",
|
||||
@@ -7156,7 +7146,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "livekit-api"
|
||||
version = "0.4.1"
|
||||
source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=060964da10574cd9bf06463a53bf6e0769c5c45e#060964da10574cd9bf06463a53bf6e0769c5c45e"
|
||||
source = "git+https://github.com/zed-industries/rust-sdks?rev=799f10133d93ba2a88642cd480d01ec4da53408c#799f10133d93ba2a88642cd480d01ec4da53408c"
|
||||
dependencies = [
|
||||
"async-tungstenite 0.25.1",
|
||||
"futures-util",
|
||||
@@ -7181,7 +7171,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "livekit-protocol"
|
||||
version = "0.3.6"
|
||||
source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=060964da10574cd9bf06463a53bf6e0769c5c45e#060964da10574cd9bf06463a53bf6e0769c5c45e"
|
||||
source = "git+https://github.com/zed-industries/rust-sdks?rev=799f10133d93ba2a88642cd480d01ec4da53408c#799f10133d93ba2a88642cd480d01ec4da53408c"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"livekit-runtime",
|
||||
@@ -7198,7 +7188,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "livekit-runtime"
|
||||
version = "0.3.1"
|
||||
source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=060964da10574cd9bf06463a53bf6e0769c5c45e#060964da10574cd9bf06463a53bf6e0769c5c45e"
|
||||
source = "git+https://github.com/zed-industries/rust-sdks?rev=799f10133d93ba2a88642cd480d01ec4da53408c#799f10133d93ba2a88642cd480d01ec4da53408c"
|
||||
dependencies = [
|
||||
"async-io 2.4.0",
|
||||
"async-std",
|
||||
@@ -7331,7 +7321,7 @@ dependencies = [
|
||||
"async-pipe",
|
||||
"collections",
|
||||
"ctor",
|
||||
"env_logger 0.11.6",
|
||||
"env_logger 0.11.5",
|
||||
"futures 0.3.31",
|
||||
"gpui",
|
||||
"log",
|
||||
@@ -7394,7 +7384,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"assets",
|
||||
"env_logger 0.11.6",
|
||||
"env_logger 0.11.5",
|
||||
"futures 0.3.31",
|
||||
"gpui",
|
||||
"language",
|
||||
@@ -7509,7 +7499,7 @@ dependencies = [
|
||||
"clap",
|
||||
"clap_complete",
|
||||
"elasticlunr-rs",
|
||||
"env_logger 0.11.6",
|
||||
"env_logger 0.11.5",
|
||||
"futures-util",
|
||||
"handlebars 6.2.0",
|
||||
"ignore",
|
||||
@@ -7590,8 +7580,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "metal"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c3572083504c43e14aec05447f8a3d57cce0f66d7a3c1b9058572eca4d70ab9"
|
||||
source = "git+https://github.com/gfx-rs/metal-rs?rev=ef768ff9d742ae6a0f4e83ddc8031264e7d460c4#ef768ff9d742ae6a0f4e83ddc8031264e7d460c4"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"block",
|
||||
@@ -7699,7 +7688,7 @@ dependencies = [
|
||||
"clock",
|
||||
"collections",
|
||||
"ctor",
|
||||
"env_logger 0.11.6",
|
||||
"env_logger 0.11.5",
|
||||
"futures 0.3.31",
|
||||
"gpui",
|
||||
"itertools 0.13.0",
|
||||
@@ -7731,9 +7720,8 @@ checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03"
|
||||
|
||||
[[package]]
|
||||
name = "naga"
|
||||
version = "23.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "364f94bc34f61332abebe8cad6f6cd82a5b65cff22c828d05d0968911462ca4f"
|
||||
version = "23.0.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=1a643291c2e8854ba7e4f5445a4388202731bfa1#1a643291c2e8854ba7e4f5445a4388202731bfa1"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bit-set 0.8.0",
|
||||
@@ -8163,208 +8151,6 @@ dependencies = [
|
||||
"malloc_buf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc-sys"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310"
|
||||
|
||||
[[package]]
|
||||
name = "objc2"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804"
|
||||
dependencies = [
|
||||
"objc-sys",
|
||||
"objc2-encode",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-app-kit"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"block2",
|
||||
"libc",
|
||||
"objc2",
|
||||
"objc2-core-data",
|
||||
"objc2-core-image",
|
||||
"objc2-foundation",
|
||||
"objc2-quartz-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-cloud-kit"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"block2",
|
||||
"objc2",
|
||||
"objc2-core-location",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-contacts"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889"
|
||||
dependencies = [
|
||||
"block2",
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-data"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"block2",
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-image"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80"
|
||||
dependencies = [
|
||||
"block2",
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
"objc2-metal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-location"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781"
|
||||
dependencies = [
|
||||
"block2",
|
||||
"objc2",
|
||||
"objc2-contacts",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-encode"
|
||||
version = "4.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7891e71393cd1f227313c9379a26a584ff3d7e6e7159e988851f0934c993f0f8"
|
||||
|
||||
[[package]]
|
||||
name = "objc2-foundation"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"block2",
|
||||
"libc",
|
||||
"objc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-link-presentation"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398"
|
||||
dependencies = [
|
||||
"block2",
|
||||
"objc2",
|
||||
"objc2-app-kit",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-metal"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"block2",
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-quartz-core"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"block2",
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
"objc2-metal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-symbols"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc"
|
||||
dependencies = [
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-ui-kit"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"block2",
|
||||
"objc2",
|
||||
"objc2-cloud-kit",
|
||||
"objc2-core-data",
|
||||
"objc2-core-image",
|
||||
"objc2-core-location",
|
||||
"objc2-foundation",
|
||||
"objc2-link-presentation",
|
||||
"objc2-quartz-core",
|
||||
"objc2-symbols",
|
||||
"objc2-uniform-type-identifiers",
|
||||
"objc2-user-notifications",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-uniform-type-identifiers"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe"
|
||||
dependencies = [
|
||||
"block2",
|
||||
"objc2",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-user-notifications"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"block2",
|
||||
"objc2",
|
||||
"objc2-core-location",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.36.5"
|
||||
@@ -8629,7 +8415,6 @@ dependencies = [
|
||||
"ui",
|
||||
"util",
|
||||
"workspace",
|
||||
"zed_actions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -9409,7 +9194,7 @@ dependencies = [
|
||||
"anyhow",
|
||||
"ctor",
|
||||
"editor",
|
||||
"env_logger 0.11.6",
|
||||
"env_logger 0.11.5",
|
||||
"gpui",
|
||||
"menu",
|
||||
"serde",
|
||||
@@ -9766,7 +9551,7 @@ dependencies = [
|
||||
"client",
|
||||
"clock",
|
||||
"collections",
|
||||
"env_logger 0.11.6",
|
||||
"env_logger 0.11.5",
|
||||
"fancy-regex 0.14.0",
|
||||
"fs",
|
||||
"futures 0.3.31",
|
||||
@@ -10148,7 +9933,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"socket2 0.5.8",
|
||||
"tracing",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -10481,6 +10266,7 @@ name = "release_channel"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"gpui",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -10522,7 +10308,7 @@ dependencies = [
|
||||
"clap",
|
||||
"client",
|
||||
"clock",
|
||||
"env_logger 0.11.6",
|
||||
"env_logger 0.11.5",
|
||||
"extension",
|
||||
"extension_host",
|
||||
"fork",
|
||||
@@ -10581,7 +10367,7 @@ dependencies = [
|
||||
"collections",
|
||||
"command_palette_hooks",
|
||||
"editor",
|
||||
"env_logger 0.11.6",
|
||||
"env_logger 0.11.5",
|
||||
"feature_flags",
|
||||
"file_icons",
|
||||
"futures 0.3.31",
|
||||
@@ -10856,7 +10642,7 @@ dependencies = [
|
||||
"arrayvec",
|
||||
"criterion",
|
||||
"ctor",
|
||||
"env_logger 0.11.6",
|
||||
"env_logger 0.11.5",
|
||||
"gpui",
|
||||
"log",
|
||||
"rand 0.8.5",
|
||||
@@ -10882,7 +10668,7 @@ dependencies = [
|
||||
"base64 0.22.1",
|
||||
"chrono",
|
||||
"collections",
|
||||
"env_logger 0.11.6",
|
||||
"env_logger 0.11.5",
|
||||
"futures 0.3.31",
|
||||
"gpui",
|
||||
"parking_lot",
|
||||
@@ -11048,7 +10834,7 @@ dependencies = [
|
||||
"libc",
|
||||
"linux-raw-sys 0.4.14",
|
||||
"once_cell",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -11466,7 +11252,7 @@ dependencies = [
|
||||
"client",
|
||||
"clock",
|
||||
"collections",
|
||||
"env_logger 0.11.6",
|
||||
"env_logger 0.11.5",
|
||||
"feature_flags",
|
||||
"fs",
|
||||
"futures 0.3.31",
|
||||
@@ -12468,7 +12254,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"ctor",
|
||||
"env_logger 0.11.6",
|
||||
"env_logger 0.11.5",
|
||||
"log",
|
||||
"rand 0.8.5",
|
||||
"rayon",
|
||||
@@ -12482,7 +12268,7 @@ dependencies = [
|
||||
"client",
|
||||
"collections",
|
||||
"editor",
|
||||
"env_logger 0.11.6",
|
||||
"env_logger 0.11.5",
|
||||
"futures 0.3.31",
|
||||
"gpui",
|
||||
"http_client",
|
||||
@@ -12768,7 +12554,7 @@ dependencies = [
|
||||
"fd-lock",
|
||||
"io-lifetimes 2.0.4",
|
||||
"rustix 0.38.42",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
"winx",
|
||||
]
|
||||
|
||||
@@ -12780,7 +12566,7 @@ dependencies = [
|
||||
"collections",
|
||||
"ctor",
|
||||
"editor",
|
||||
"env_logger 0.11.6",
|
||||
"env_logger 0.11.5",
|
||||
"gpui",
|
||||
"language",
|
||||
"menu",
|
||||
@@ -12900,7 +12686,7 @@ dependencies = [
|
||||
"fastrand 2.3.0",
|
||||
"once_cell",
|
||||
"rustix 0.38.42",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -13001,7 +12787,7 @@ dependencies = [
|
||||
"clock",
|
||||
"collections",
|
||||
"ctor",
|
||||
"env_logger 0.11.6",
|
||||
"env_logger 0.11.5",
|
||||
"gpui",
|
||||
"http_client",
|
||||
"log",
|
||||
@@ -14198,7 +13984,6 @@ dependencies = [
|
||||
"git2",
|
||||
"globset",
|
||||
"itertools 0.13.0",
|
||||
"libc",
|
||||
"log",
|
||||
"rand 0.8.5",
|
||||
"regex",
|
||||
@@ -15051,7 +14836,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "webrtc-sys"
|
||||
version = "0.3.5"
|
||||
source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=060964da10574cd9bf06463a53bf6e0769c5c45e#060964da10574cd9bf06463a53bf6e0769c5c45e"
|
||||
source = "git+https://github.com/zed-industries/rust-sdks?rev=799f10133d93ba2a88642cd480d01ec4da53408c#799f10133d93ba2a88642cd480d01ec4da53408c"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cxx",
|
||||
@@ -15064,7 +14849,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "webrtc-sys-build"
|
||||
version = "0.3.5"
|
||||
source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=060964da10574cd9bf06463a53bf6e0769c5c45e#060964da10574cd9bf06463a53bf6e0769c5c45e"
|
||||
source = "git+https://github.com/zed-industries/rust-sdks?rev=799f10133d93ba2a88642cd480d01ec4da53408c#799f10133d93ba2a88642cd480d01ec4da53408c"
|
||||
dependencies = [
|
||||
"fs2",
|
||||
"regex",
|
||||
@@ -15203,7 +14988,7 @@ version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||
dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -15652,7 +15437,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f3fd376f71958b862e7afb20cfe5a22830e1963462f3a17f49d82a6c1d1f42d"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -15800,7 +15585,7 @@ dependencies = [
|
||||
"collections",
|
||||
"db",
|
||||
"derive_more",
|
||||
"env_logger 0.11.6",
|
||||
"env_logger 0.11.5",
|
||||
"fs",
|
||||
"futures 0.3.31",
|
||||
"gpui",
|
||||
@@ -15836,7 +15621,7 @@ dependencies = [
|
||||
"anyhow",
|
||||
"clock",
|
||||
"collections",
|
||||
"env_logger 0.11.6",
|
||||
"env_logger 0.11.5",
|
||||
"fs",
|
||||
"futures 0.3.31",
|
||||
"fuzzy",
|
||||
@@ -16233,7 +16018,7 @@ dependencies = [
|
||||
"db",
|
||||
"diagnostics",
|
||||
"editor",
|
||||
"env_logger 0.11.6",
|
||||
"env_logger 0.11.5",
|
||||
"extension",
|
||||
"extension_host",
|
||||
"extensions_ui",
|
||||
@@ -16659,7 +16444,7 @@ dependencies = [
|
||||
"collections",
|
||||
"ctor",
|
||||
"editor",
|
||||
"env_logger 0.11.6",
|
||||
"env_logger 0.11.5",
|
||||
"futures 0.3.31",
|
||||
"gpui",
|
||||
"http_client",
|
||||
|
||||
16
Cargo.toml
16
Cargo.toml
@@ -355,9 +355,9 @@ async-watch = "0.3.1"
|
||||
async_zip = { version = "0.0.17", features = ["deflate", "deflate64"] }
|
||||
base64 = "0.22"
|
||||
bitflags = "2.6.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" }
|
||||
blade-graphics = { git = "https://github.com/kvark/blade", rev = "099555282605c7c4cca9e66a8f40148298347f80" }
|
||||
blade-macros = { git = "https://github.com/kvark/blade", rev = "099555282605c7c4cca9e66a8f40148298347f80" }
|
||||
blade-util = { git = "https://github.com/kvark/blade", rev = "099555282605c7c4cca9e66a8f40148298347f80" }
|
||||
blake3 = "1.5.3"
|
||||
bytes = "1.0"
|
||||
cargo_metadata = "0.19"
|
||||
@@ -401,13 +401,14 @@ jupyter-websocket-client = { version = "0.8.0" }
|
||||
libc = "0.2"
|
||||
libsqlite3-sys = { version = "0.30.1", features = ["bundled"] }
|
||||
linkify = "0.10.0"
|
||||
livekit = { git = "https://github.com/zed-industries/livekit-rust-sdks", rev="060964da10574cd9bf06463a53bf6e0769c5c45e", features = ["dispatcher", "services-dispatcher", "rustls-tls-native-roots"], default-features = false }
|
||||
livekit = { git = "https://github.com/zed-industries/rust-sdks", rev="799f10133d93ba2a88642cd480d01ec4da53408c", features = ["dispatcher", "services-dispatcher", "rustls-tls-native-roots"], default-features = false }
|
||||
log = { version = "0.4.16", features = ["kv_unstable_serde", "serde"] }
|
||||
markup5ever_rcdom = "0.3.0"
|
||||
nanoid = "0.4"
|
||||
nbformat = { version = "0.9.0" }
|
||||
nix = "0.29"
|
||||
num-format = "0.4.4"
|
||||
once_cell = "1.19.0"
|
||||
ordered-float = "2.1.1"
|
||||
palette = { version = "0.7.5", default-features = false, features = ["std"] }
|
||||
parking_lot = "0.12.1"
|
||||
@@ -524,7 +525,12 @@ wasmtime-wasi = "24"
|
||||
which = "6.0.0"
|
||||
wit-component = "0.201"
|
||||
zstd = "0.11"
|
||||
metal = "0.30"
|
||||
# Custom metal-rs is only needed for "macos-blade" feature of GPUI
|
||||
#TODO: switch to crates once these are published:
|
||||
# - https://github.com/gfx-rs/metal-rs/pull/335
|
||||
# - https://github.com/gfx-rs/metal-rs/pull/336
|
||||
# - https://github.com/gfx-rs/metal-rs/pull/337
|
||||
metal = { git = "https://github.com/gfx-rs/metal-rs", rev = "ef768ff9d742ae6a0f4e83ddc8031264e7d460c4" }
|
||||
|
||||
[workspace.dependencies.async-stripe]
|
||||
git = "https://github.com/zed-industries/async-stripe"
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.58 2H2.5V12.08C2.5 12.5892 2.70229 13.0776 3.06235 13.4376C3.42242 13.7977 3.91078 14 4.42 14H12.58C13.0892 14 13.5776 13.7977 13.9376 13.4376C14.2977 13.0776 14.5 12.5892 14.5 12.08V3.92C14.5 3.41078 14.2977 2.92242 13.9376 2.56235C13.5776 2.20229 13.0892 2 12.58 2ZM3.358 11.6285C3.34615 12.6668 3.96437 13.2311 4.96636 13.232H4.96621C6.06429 13.2456 6.70951 12.4798 6.63088 11.3867H5.48085C5.4899 11.601 5.47243 11.8974 5.36026 12.0313C5.27992 12.1441 5.16183 12.2005 5.00645 12.2005C4.67402 12.1952 4.50788 11.9534 4.50788 11.4753V9.19488C4.50788 8.94247 4.54407 8.75168 4.61645 8.62283C4.73423 8.38524 5.17961 8.3584 5.34825 8.58663C5.47804 8.71252 5.48974 9.04683 5.48101 9.26757H6.63104C6.66099 8.70582 6.53494 8.10381 6.20079 7.80913C5.65853 7.23521 4.37403 7.26765 3.82039 7.80102C3.51213 8.07495 3.358 8.47525 3.358 9.00159V11.6285ZM7.04116 11.3867C7.01043 12.4573 7.50713 13.2473 8.61739 13.232L8.61723 13.2317C10.1571 13.2967 10.5874 11.592 9.96023 10.4759C9.74995 10.1097 9.16994 9.80702 8.71379 9.62981C8.36155 9.46772 8.21038 9.3086 8.20711 8.92079C8.20711 8.55559 8.35983 8.37291 8.66543 8.37291C8.83688 8.37291 8.95357 8.42939 9.01519 8.54217C9.10317 8.6754 9.12454 9.0409 9.11565 9.26742H10.1612C10.1866 8.71627 10.0554 8.11739 9.75509 7.81303C9.26822 7.22257 7.99791 7.24909 7.5115 7.82504C7.0109 8.29179 6.97783 9.4437 7.3346 9.96848C7.49278 10.205 7.75143 10.409 8.1107 10.5809C8.15897 10.6051 8.21552 10.6314 8.27633 10.6598C8.53247 10.7792 8.86416 10.9338 8.97119 11.1046C9.16073 11.3241 9.13593 11.8913 9.00333 12.0877C8.9336 12.1952 8.81285 12.2489 8.64141 12.2489C8.25703 12.2785 8.09666 11.8534 8.12677 11.3867H7.04116ZM10.5474 11.3867C10.5167 12.4573 11.0134 13.2473 12.1236 13.232L12.1235 13.2317C13.6634 13.2967 14.0936 11.592 13.4665 10.4759C13.2562 10.1097 12.6762 9.80702 12.2201 9.62981C11.8678 9.46772 11.7166 9.3086 11.7134 8.92079C11.7134 8.55559 11.8661 8.37291 12.1717 8.37291C12.3431 8.37291 12.4598 8.42939 12.5214 8.54217C12.6094 8.6754 12.6308 9.0409 12.6219 9.26742H13.6674C13.6928 8.71627 13.5617 8.11739 13.2614 7.81303C12.7745 7.22257 11.5042 7.24909 11.0178 7.82504C10.5172 8.29179 10.4841 9.4437 10.8409 9.96848C10.999 10.205 11.2577 10.409 11.617 10.5809C11.6652 10.6051 11.7218 10.6314 11.7826 10.6598C12.0387 10.7792 12.3704 10.9338 12.4775 11.1046C12.667 11.3241 12.6422 11.8913 12.5096 12.0877C12.4399 12.1952 12.3191 12.2489 12.1477 12.2489C11.7633 12.2785 11.6029 11.8534 11.633 11.3867H10.5474Z" fill="black"/>
|
||||
<path d="M11.7633 4.2078H4.23674L4.3551 5.5189H10.1429L9.99592 6.87645H6.20408L6.33877 8.16255H9.86939L9.66122 9.92379L8 10.3275L6.3102 9.92021L6.20408 8.86633H4.7102L4.87755 10.7955L8 11.6457L11.0694 10.8812L11.7633 4.2078ZM2 2H14L12.9061 12.7818L7.98775 14L3.09388 12.7818L2 2Z" fill="black"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 403 B |
@@ -260,8 +260,6 @@
|
||||
"ctrl-f4": "pane::CloseActiveItem",
|
||||
"alt-ctrl-t": ["pane::CloseInactiveItems", { "close_pinned": false }],
|
||||
"alt-ctrl-shift-w": "workspace::CloseInactiveTabsAndPanes",
|
||||
"ctrl-k e": ["pane::CloseItemsToTheLeft", { "close_pinned": false }],
|
||||
"ctrl-k t": ["pane::CloseItemsToTheRight", { "close_pinned": false }],
|
||||
"ctrl-k u": ["pane::CloseCleanItems", { "close_pinned": false }],
|
||||
"ctrl-k w": ["pane::CloseAllItems", { "close_pinned": false }],
|
||||
"ctrl-shift-f": "project_search::ToggleFocus",
|
||||
|
||||
@@ -327,8 +327,6 @@
|
||||
"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 }],
|
||||
"cmd-k t": ["pane::CloseItemsToTheRight", { "close_pinned": false }],
|
||||
"cmd-k u": ["pane::CloseCleanItems", { "close_pinned": false }],
|
||||
"cmd-k cmd-w": ["pane::CloseAllItems", { "close_pinned": false }],
|
||||
"cmd-f": "project_search::ToggleFocus",
|
||||
|
||||
@@ -1103,9 +1103,6 @@
|
||||
"prettier": {
|
||||
"allowed": true
|
||||
}
|
||||
},
|
||||
"Zig": {
|
||||
"language_servers": ["zls", "..."]
|
||||
}
|
||||
},
|
||||
// Different settings for specific language models.
|
||||
|
||||
@@ -1458,10 +1458,6 @@ impl Panel for AssistantPanel {
|
||||
fn toggle_action(&self) -> Box<dyn Action> {
|
||||
Box::new(ToggleFocus)
|
||||
}
|
||||
|
||||
fn activation_priority(&self) -> u32 {
|
||||
4
|
||||
}
|
||||
}
|
||||
|
||||
impl EventEmitter<PanelEvent> for AssistantPanel {}
|
||||
@@ -4970,8 +4966,8 @@ fn fold_toggle(
|
||||
) -> impl Fn(
|
||||
MultiBufferRow,
|
||||
bool,
|
||||
Arc<dyn Fn(bool, &mut WindowContext) + Send + Sync>,
|
||||
&mut WindowContext,
|
||||
Arc<dyn Fn(bool, &mut WindowContext<'_>) + Send + Sync>,
|
||||
&mut WindowContext<'_>,
|
||||
) -> AnyElement {
|
||||
move |row, is_folded, fold, _cx| {
|
||||
Disclosure::new((name, row.0 as u64), !is_folded)
|
||||
|
||||
@@ -149,7 +149,6 @@ impl SlashCommandCompletionProvider {
|
||||
server_id: LanguageServerId(0),
|
||||
lsp_completion: Default::default(),
|
||||
confirm,
|
||||
resolved: true,
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
@@ -243,7 +242,6 @@ impl SlashCommandCompletionProvider {
|
||||
server_id: LanguageServerId(0),
|
||||
lsp_completion: Default::default(),
|
||||
confirm,
|
||||
resolved: true,
|
||||
}
|
||||
})
|
||||
.collect())
|
||||
@@ -332,6 +330,16 @@ impl CompletionProvider for SlashCommandCompletionProvider {
|
||||
Task::ready(Ok(true))
|
||||
}
|
||||
|
||||
fn apply_additional_edits_for_completion(
|
||||
&self,
|
||||
_: Model<Buffer>,
|
||||
_: project::Completion,
|
||||
_: bool,
|
||||
_: &mut ViewContext<Editor>,
|
||||
) -> Task<Result<Option<language::Transaction>>> {
|
||||
Task::ready(Ok(None))
|
||||
}
|
||||
|
||||
fn is_completion_trigger(
|
||||
&self,
|
||||
buffer: &Model<Buffer>,
|
||||
|
||||
@@ -5,7 +5,7 @@ use assistant_slash_command::{
|
||||
};
|
||||
use feature_flags::FeatureFlag;
|
||||
use futures::StreamExt;
|
||||
use gpui::{AppContext, AsyncAppContext, AsyncWindowContext, Task, WeakView, WindowContext};
|
||||
use gpui::{AppContext, AsyncAppContext, Task, WeakView};
|
||||
use language::{CodeLabel, LspAdapterDelegate};
|
||||
use language_model::{
|
||||
LanguageModelCompletionEvent, LanguageModelRegistry, LanguageModelRequest,
|
||||
@@ -14,7 +14,7 @@ use language_model::{
|
||||
use semantic_index::{FileSummary, SemanticDb};
|
||||
use smol::channel;
|
||||
use std::sync::{atomic::AtomicBool, Arc};
|
||||
use ui::{prelude::*, BorrowAppContext};
|
||||
use ui::{prelude::*, BorrowAppContext, WindowContext};
|
||||
use util::ResultExt;
|
||||
use workspace::Workspace;
|
||||
|
||||
@@ -115,7 +115,7 @@ impl SlashCommand for AutoCommand {
|
||||
return Task::ready(Err(anyhow!("no project indexer")));
|
||||
};
|
||||
|
||||
let task = cx.spawn(|cx: AsyncWindowContext| async move {
|
||||
let task = cx.spawn(|cx: gpui::AsyncWindowContext| async move {
|
||||
let summaries = project_index
|
||||
.read_with(&cx, |project_index, cx| project_index.all_summaries(cx))?
|
||||
.await?;
|
||||
|
||||
@@ -281,7 +281,7 @@ fn tab_items_for_queries(
|
||||
|
||||
fn active_item_buffer(
|
||||
workspace: &mut Workspace,
|
||||
cx: &mut ViewContext<Workspace>,
|
||||
cx: &mut ui::ViewContext<Workspace>,
|
||||
) -> anyhow::Result<BufferSnapshot> {
|
||||
let active_editor = workspace
|
||||
.active_item(cx)
|
||||
|
||||
@@ -27,8 +27,8 @@ enum SlashCommandEntry {
|
||||
Info(SlashCommandInfo),
|
||||
Advert {
|
||||
name: SharedString,
|
||||
renderer: fn(&mut WindowContext) -> AnyElement,
|
||||
on_confirm: fn(&mut WindowContext),
|
||||
renderer: fn(&mut WindowContext<'_>) -> AnyElement,
|
||||
on_confirm: fn(&mut WindowContext<'_>),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -3,9 +3,8 @@ use std::sync::Arc;
|
||||
use assistant_tool::ToolWorkingSet;
|
||||
use collections::HashMap;
|
||||
use gpui::{
|
||||
list, AbsoluteLength, AnyElement, AppContext, DefiniteLength, EdgesRefinement, Empty, Length,
|
||||
ListAlignment, ListOffset, ListState, Model, StyleRefinement, Subscription,
|
||||
TextStyleRefinement, View, WeakView,
|
||||
list, AnyElement, AppContext, Empty, ListAlignment, ListState, Model, StyleRefinement,
|
||||
Subscription, TextStyleRefinement, View, WeakView,
|
||||
};
|
||||
use language::LanguageRegistry;
|
||||
use language_model::Role;
|
||||
@@ -90,11 +89,10 @@ impl ActiveThread {
|
||||
self.list_state.splice(old_len..old_len, 1);
|
||||
|
||||
let theme_settings = ThemeSettings::get_global(cx);
|
||||
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 = cx.text_style();
|
||||
let buffer_font_size = theme_settings.buffer_font_size;
|
||||
|
||||
let mut text_style = cx.text_style();
|
||||
text_style.refine(&TextStyleRefinement {
|
||||
font_family: Some(theme_settings.ui_font.family.clone()),
|
||||
font_size: Some(ui_font_size.into()),
|
||||
@@ -107,26 +105,6 @@ impl ActiveThread {
|
||||
syntax: cx.theme().syntax().clone(),
|
||||
selection_background_color: cx.theme().players().local().selection,
|
||||
code_block: StyleRefinement {
|
||||
margin: EdgesRefinement {
|
||||
top: Some(Length::Definite(rems(1.0).into())),
|
||||
left: Some(Length::Definite(rems(0.).into())),
|
||||
right: Some(Length::Definite(rems(0.).into())),
|
||||
bottom: Some(Length::Definite(rems(1.).into())),
|
||||
},
|
||||
padding: EdgesRefinement {
|
||||
top: Some(DefiniteLength::Absolute(AbsoluteLength::Pixels(Pixels(8.)))),
|
||||
left: Some(DefiniteLength::Absolute(AbsoluteLength::Pixels(Pixels(8.)))),
|
||||
right: Some(DefiniteLength::Absolute(AbsoluteLength::Pixels(Pixels(8.)))),
|
||||
bottom: Some(DefiniteLength::Absolute(AbsoluteLength::Pixels(Pixels(8.)))),
|
||||
},
|
||||
background: Some(colors.editor_foreground.opacity(0.01).into()),
|
||||
border_color: Some(colors.border_variant.opacity(0.3)),
|
||||
border_widths: EdgesRefinement {
|
||||
top: Some(AbsoluteLength::Pixels(Pixels(1.0))),
|
||||
left: Some(AbsoluteLength::Pixels(Pixels(1.))),
|
||||
right: Some(AbsoluteLength::Pixels(Pixels(1.))),
|
||||
bottom: Some(AbsoluteLength::Pixels(Pixels(1.))),
|
||||
},
|
||||
text: Some(TextStyleRefinement {
|
||||
font_family: Some(theme_settings.buffer_font.family.clone()),
|
||||
font_size: Some(buffer_font_size.into()),
|
||||
@@ -136,8 +114,8 @@ impl ActiveThread {
|
||||
},
|
||||
inline_code: TextStyleRefinement {
|
||||
font_family: Some(theme_settings.buffer_font.family.clone()),
|
||||
font_size: Some(buffer_font_size.into()),
|
||||
background_color: Some(colors.editor_foreground.opacity(0.01)),
|
||||
font_size: Some(ui_font_size.into()),
|
||||
background_color: Some(cx.theme().colors().editor_background),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
@@ -153,10 +131,6 @@ impl ActiveThread {
|
||||
)
|
||||
});
|
||||
self.rendered_messages_by_id.insert(*id, markdown);
|
||||
self.list_state.scroll_to(ListOffset {
|
||||
item_ix: old_len,
|
||||
offset_in_item: Pixels(0.0),
|
||||
});
|
||||
}
|
||||
|
||||
fn handle_thread_event(
|
||||
@@ -230,7 +204,6 @@ impl ActiveThread {
|
||||
};
|
||||
|
||||
let context = self.thread.read(cx).context_for_message(message_id);
|
||||
let colors = cx.theme().colors();
|
||||
|
||||
let (role_icon, role_name, role_color) = match message.role {
|
||||
Role::User => (IconName::Person, "You", Color::Muted),
|
||||
@@ -245,16 +218,16 @@ impl ActiveThread {
|
||||
.child(
|
||||
v_flex()
|
||||
.border_1()
|
||||
.border_color(colors.border_variant)
|
||||
.bg(colors.editor_background)
|
||||
.border_color(cx.theme().colors().border)
|
||||
.bg(cx.theme().colors().editor_background)
|
||||
.rounded_md()
|
||||
.child(
|
||||
h_flex()
|
||||
.py_1p5()
|
||||
.px_2p5()
|
||||
.border_b_1()
|
||||
.border_color(colors.border_variant)
|
||||
.justify_between()
|
||||
.py_1()
|
||||
.px_2()
|
||||
.border_b_1()
|
||||
.border_color(cx.theme().colors().border_variant)
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_1p5()
|
||||
@@ -270,20 +243,15 @@ impl ActiveThread {
|
||||
),
|
||||
),
|
||||
)
|
||||
.child(div().p_2p5().text_ui(cx).child(markdown.clone()))
|
||||
.child(v_flex().px_2().py_1().text_ui(cx).child(markdown.clone()))
|
||||
.when_some(context, |parent, context| {
|
||||
if !context.is_empty() {
|
||||
parent.child(
|
||||
h_flex()
|
||||
.flex_wrap()
|
||||
.gap_1()
|
||||
.px_1p5()
|
||||
.pb_1p5()
|
||||
.children(context.iter().map(|c| ContextPill::new(c.clone()))),
|
||||
)
|
||||
} else {
|
||||
parent
|
||||
}
|
||||
parent.child(
|
||||
h_flex().flex_wrap().gap_2().p_1p5().children(
|
||||
context
|
||||
.iter()
|
||||
.map(|context| ContextPill::new(context.clone())),
|
||||
),
|
||||
)
|
||||
}),
|
||||
)
|
||||
.into_any()
|
||||
|
||||
@@ -286,10 +286,6 @@ impl Panel for AssistantPanel {
|
||||
fn toggle_action(&self) -> Box<dyn Action> {
|
||||
Box::new(ToggleFocus)
|
||||
}
|
||||
|
||||
fn activation_priority(&self) -> u32 {
|
||||
3
|
||||
}
|
||||
}
|
||||
|
||||
impl AssistantPanel {
|
||||
|
||||
@@ -21,7 +21,7 @@ pub struct Context {
|
||||
pub text: SharedString,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum ContextKind {
|
||||
File,
|
||||
Directory,
|
||||
|
||||
@@ -176,7 +176,7 @@ impl PickerDelegate for FetchContextPickerDelegate {
|
||||
|
||||
fn set_selected_index(&mut self, _ix: usize, _cx: &mut ViewContext<Picker<Self>>) {}
|
||||
|
||||
fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
|
||||
fn placeholder_text(&self, _cx: &mut ui::WindowContext) -> Arc<str> {
|
||||
"Enter a URL…".into()
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ use crate::context_store::ContextStore;
|
||||
use crate::thread_store::ThreadStore;
|
||||
use crate::ui::ContextPill;
|
||||
use crate::ToggleContextPicker;
|
||||
use settings::Settings;
|
||||
|
||||
pub struct ContextStrip {
|
||||
context_store: Model<ContextStore>,
|
||||
@@ -46,7 +45,7 @@ impl ContextStrip {
|
||||
|
||||
impl Render for ContextStrip {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
let context = self.context_store.read(cx).context().clone();
|
||||
let context = self.context_store.read(cx).context();
|
||||
let context_picker = self.context_picker.clone();
|
||||
let focus_handle = self.focus_handle.clone();
|
||||
|
||||
@@ -77,29 +76,6 @@ impl Render for ContextStrip {
|
||||
})
|
||||
.with_handle(self.context_picker_menu_handle.clone()),
|
||||
)
|
||||
.when(context.is_empty(), {
|
||||
|parent| {
|
||||
parent.child(
|
||||
h_flex()
|
||||
.id("no-content-info")
|
||||
.ml_1p5()
|
||||
.gap_2()
|
||||
.font(theme::ThemeSettings::get_global(cx).buffer_font.clone())
|
||||
.text_size(TextSize::Small.rems(cx))
|
||||
.text_color(cx.theme().colors().text_muted)
|
||||
.child("Add Context")
|
||||
.children(
|
||||
ui::KeyBinding::for_action_in(
|
||||
&ToggleContextPicker,
|
||||
&self.focus_handle,
|
||||
cx,
|
||||
)
|
||||
.map(|binding| binding.into_any_element()),
|
||||
)
|
||||
.opacity(0.5),
|
||||
)
|
||||
}
|
||||
})
|
||||
.children(context.iter().map(|context| {
|
||||
ContextPill::new(context.clone()).on_remove({
|
||||
let context = context.clone();
|
||||
@@ -112,21 +88,19 @@ impl Render for ContextStrip {
|
||||
}))
|
||||
})
|
||||
}))
|
||||
.when(!context.is_empty(), {
|
||||
move |parent| {
|
||||
parent.child(
|
||||
IconButton::new("remove-all-context", IconName::Eraser)
|
||||
.icon_size(IconSize::Small)
|
||||
.tooltip(move |cx| Tooltip::text("Remove All Context", cx))
|
||||
.on_click({
|
||||
let context_store = self.context_store.clone();
|
||||
cx.listener(move |_this, _event, cx| {
|
||||
context_store.update(cx, |this, _cx| this.clear());
|
||||
cx.notify();
|
||||
})
|
||||
}),
|
||||
)
|
||||
}
|
||||
.when(!context.is_empty(), |parent| {
|
||||
parent.child(
|
||||
IconButton::new("remove-all-context", IconName::Eraser)
|
||||
.icon_size(IconSize::Small)
|
||||
.tooltip(move |cx| Tooltip::text("Remove All Context", cx))
|
||||
.on_click({
|
||||
let context_store = self.context_store.clone();
|
||||
cx.listener(move |_this, _event, cx| {
|
||||
context_store.update(cx, |this, _cx| this.clear());
|
||||
cx.notify();
|
||||
})
|
||||
}),
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ impl<T: 'static> Render for PromptEditor<T> {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
let mut buttons = Vec::new();
|
||||
|
||||
let left_gutter_spacing = match &self.mode {
|
||||
let spacing = match &self.mode {
|
||||
PromptEditorMode::Buffer {
|
||||
id: _,
|
||||
codegen,
|
||||
@@ -74,31 +74,23 @@ impl<T: 'static> Render for PromptEditor<T> {
|
||||
}
|
||||
PromptEditorMode::Terminal { .. } => {
|
||||
// Give the equivalent of the same left-padding that we're using on the right
|
||||
Pixels::from(40.0)
|
||||
Pixels::from(24.0)
|
||||
}
|
||||
};
|
||||
|
||||
let bottom_padding = match &self.mode {
|
||||
PromptEditorMode::Buffer { .. } => Pixels::from(0.),
|
||||
PromptEditorMode::Terminal { .. } => Pixels::from(8.0),
|
||||
};
|
||||
|
||||
buttons.extend(self.render_buttons(cx));
|
||||
|
||||
v_flex()
|
||||
.key_context("PromptEditor")
|
||||
.bg(cx.theme().colors().editor_background)
|
||||
.block_mouse_down()
|
||||
.gap_0p5()
|
||||
.border_y_1()
|
||||
.border_color(cx.theme().status().info_border)
|
||||
.size_full()
|
||||
.pt_0p5()
|
||||
.pb(bottom_padding)
|
||||
.pr_6()
|
||||
.pt_1()
|
||||
.pb_2()
|
||||
.child(
|
||||
h_flex()
|
||||
.items_start()
|
||||
.cursor(CursorStyle::Arrow)
|
||||
.on_action(cx.listener(Self::toggle_context_picker))
|
||||
.on_action(cx.listener(Self::toggle_model_selector))
|
||||
@@ -110,8 +102,7 @@ impl<T: 'static> Render for PromptEditor<T> {
|
||||
.capture_action(cx.listener(Self::cycle_next))
|
||||
.child(
|
||||
h_flex()
|
||||
.h_full()
|
||||
.w(left_gutter_spacing)
|
||||
.w(spacing)
|
||||
.justify_center()
|
||||
.gap_2()
|
||||
.child(self.render_close_button(cx))
|
||||
@@ -171,19 +162,21 @@ impl<T: 'static> Render for PromptEditor<T> {
|
||||
.w_full()
|
||||
.justify_between()
|
||||
.child(div().flex_1().child(self.render_editor(cx)))
|
||||
.child(h_flex().gap_1().children(buttons)),
|
||||
.child(h_flex().gap_2().pr_6().children(buttons)),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
h_flex().child(div().w(left_gutter_spacing)).child(
|
||||
h_flex()
|
||||
.w_full()
|
||||
.pl_1()
|
||||
.items_start()
|
||||
.justify_between()
|
||||
.child(self.context_strip.clone())
|
||||
.child(self.model_selector.clone()),
|
||||
),
|
||||
h_flex()
|
||||
.child(h_flex().w(spacing).justify_between().gap_2())
|
||||
.child(
|
||||
h_flex()
|
||||
.w_full()
|
||||
.pl_1()
|
||||
.pr_6()
|
||||
.justify_between()
|
||||
.child(div().pl_1().child(self.context_strip.clone()))
|
||||
.child(self.model_selector.clone()),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -410,9 +403,8 @@ impl<T: 'static> PromptEditor<T> {
|
||||
match codegen_status {
|
||||
CodegenStatus::Idle => {
|
||||
vec![Button::new("start", mode.start_label())
|
||||
.label_size(LabelSize::Small)
|
||||
.icon(IconName::Return)
|
||||
.icon_size(IconSize::XSmall)
|
||||
.label_size(LabelSize::Small)
|
||||
.icon_color(Color::Muted)
|
||||
.on_click(cx.listener(|_, _, cx| cx.emit(PromptEditorEvent::StartRequested)))
|
||||
.into_any_element()]
|
||||
@@ -679,18 +671,20 @@ impl<T: 'static> PromptEditor<T> {
|
||||
let font_size = TextSize::Default.rems(cx);
|
||||
let line_height = font_size.to_pixels(cx.rem_size()) * 1.3;
|
||||
|
||||
div()
|
||||
v_flex()
|
||||
.key_context("MessageEditor")
|
||||
.size_full()
|
||||
.gap_2()
|
||||
.p_2()
|
||||
.bg(cx.theme().colors().editor_background)
|
||||
.child({
|
||||
let settings = ThemeSettings::get_global(cx);
|
||||
let text_style = TextStyle {
|
||||
color: cx.theme().colors().editor_foreground,
|
||||
font_family: settings.buffer_font.family.clone(),
|
||||
font_features: settings.buffer_font.features.clone(),
|
||||
font_family: settings.ui_font.family.clone(),
|
||||
font_features: settings.ui_font.features.clone(),
|
||||
font_size: font_size.into(),
|
||||
font_weight: settings.ui_font.weight,
|
||||
line_height: line_height.into(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
@@ -54,7 +54,7 @@ impl MessageEditor {
|
||||
|
||||
let editor = cx.new_view(|cx| {
|
||||
let mut editor = Editor::auto_height(10, cx);
|
||||
editor.set_placeholder_text("Ask anything…", cx);
|
||||
editor.set_placeholder_text("Ask anything, @ to add context", cx);
|
||||
editor.set_show_indent_guides(false, cx);
|
||||
|
||||
editor
|
||||
@@ -220,73 +220,67 @@ impl Render for MessageEditor {
|
||||
.p_2()
|
||||
.bg(bg_color)
|
||||
.child(self.context_strip.clone())
|
||||
.child(
|
||||
v_flex()
|
||||
.gap_4()
|
||||
.child({
|
||||
let settings = ThemeSettings::get_global(cx);
|
||||
let text_style = TextStyle {
|
||||
color: cx.theme().colors().text,
|
||||
font_family: settings.ui_font.family.clone(),
|
||||
font_features: settings.ui_font.features.clone(),
|
||||
font_size: font_size.into(),
|
||||
font_weight: settings.ui_font.weight,
|
||||
line_height: line_height.into(),
|
||||
..Default::default()
|
||||
};
|
||||
.child({
|
||||
let settings = ThemeSettings::get_global(cx);
|
||||
let text_style = TextStyle {
|
||||
color: cx.theme().colors().editor_foreground,
|
||||
font_family: settings.ui_font.family.clone(),
|
||||
font_features: settings.ui_font.features.clone(),
|
||||
font_size: font_size.into(),
|
||||
font_weight: settings.ui_font.weight,
|
||||
line_height: line_height.into(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
EditorElement::new(
|
||||
&self.editor,
|
||||
EditorStyle {
|
||||
background: bg_color,
|
||||
local_player: cx.theme().players().local(),
|
||||
text: text_style,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
EditorElement::new(
|
||||
&self.editor,
|
||||
EditorStyle {
|
||||
background: bg_color,
|
||||
local_player: cx.theme().players().local(),
|
||||
text: text_style,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
})
|
||||
.child(
|
||||
PopoverMenu::new("inline-context-picker")
|
||||
.menu(move |_cx| Some(inline_context_picker.clone()))
|
||||
.attach(gpui::Corner::TopLeft)
|
||||
.anchor(gpui::Corner::BottomLeft)
|
||||
.offset(gpui::Point {
|
||||
x: px(0.0),
|
||||
y: px(-16.0),
|
||||
})
|
||||
.with_handle(self.inline_context_picker_menu_handle.clone()),
|
||||
)
|
||||
.child(
|
||||
h_flex()
|
||||
.justify_between()
|
||||
.child(SwitchWithLabel::new(
|
||||
"use-tools",
|
||||
Label::new("Tools"),
|
||||
self.use_tools.into(),
|
||||
cx.listener(|this, selection, _cx| {
|
||||
this.use_tools = match selection {
|
||||
ToggleState::Selected => true,
|
||||
ToggleState::Unselected | ToggleState::Indeterminate => false,
|
||||
};
|
||||
}),
|
||||
))
|
||||
.child(
|
||||
PopoverMenu::new("inline-context-picker")
|
||||
.menu(move |_cx| Some(inline_context_picker.clone()))
|
||||
.attach(gpui::Corner::TopLeft)
|
||||
.anchor(gpui::Corner::BottomLeft)
|
||||
.offset(gpui::Point {
|
||||
x: px(0.0),
|
||||
y: px(-16.0),
|
||||
})
|
||||
.with_handle(self.inline_context_picker_menu_handle.clone()),
|
||||
)
|
||||
.child(
|
||||
h_flex()
|
||||
.justify_between()
|
||||
.child(SwitchWithLabel::new(
|
||||
"use-tools",
|
||||
Label::new("Tools"),
|
||||
self.use_tools.into(),
|
||||
cx.listener(|this, selection, _cx| {
|
||||
this.use_tools = match selection {
|
||||
ToggleState::Selected => true,
|
||||
ToggleState::Unselected | ToggleState::Indeterminate => {
|
||||
false
|
||||
}
|
||||
};
|
||||
h_flex().gap_1().child(self.model_selector.clone()).child(
|
||||
ButtonLike::new("chat")
|
||||
.style(ButtonStyle::Filled)
|
||||
.layer(ElevationIndex::ModalSurface)
|
||||
.child(Label::new("Submit"))
|
||||
.children(
|
||||
KeyBinding::for_action_in(&Chat, &focus_handle, cx)
|
||||
.map(|binding| binding.into_any_element()),
|
||||
)
|
||||
.on_click(move |_event, cx| {
|
||||
focus_handle.dispatch_action(&Chat, cx);
|
||||
}),
|
||||
))
|
||||
.child(
|
||||
h_flex().gap_1().child(self.model_selector.clone()).child(
|
||||
ButtonLike::new("chat")
|
||||
.style(ButtonStyle::Filled)
|
||||
.layer(ElevationIndex::ModalSurface)
|
||||
.child(Label::new("Submit"))
|
||||
.children(
|
||||
KeyBinding::for_action_in(&Chat, &focus_handle, cx)
|
||||
.map(|binding| binding.into_any_element()),
|
||||
)
|
||||
.on_click(move |_event, cx| {
|
||||
focus_handle.dispatch_action(&Chat, cx);
|
||||
}),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::rc::Rc;
|
||||
use gpui::ClickEvent;
|
||||
use ui::{prelude::*, IconButtonShape};
|
||||
|
||||
use crate::context::{Context, ContextKind};
|
||||
use crate::context::Context;
|
||||
|
||||
#[derive(IntoElement)]
|
||||
pub struct ContextPill {
|
||||
@@ -27,28 +27,15 @@ impl ContextPill {
|
||||
|
||||
impl RenderOnce for ContextPill {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
let padding_right = if self.on_remove.is_some() {
|
||||
px(2.)
|
||||
} else {
|
||||
px(4.)
|
||||
};
|
||||
let icon = match self.context.kind {
|
||||
ContextKind::File => IconName::File,
|
||||
ContextKind::Directory => IconName::Folder,
|
||||
ContextKind::FetchedUrl => IconName::Globe,
|
||||
ContextKind::Thread => IconName::MessageCircle,
|
||||
};
|
||||
|
||||
h_flex()
|
||||
.gap_1()
|
||||
.pl_1()
|
||||
.pr(padding_right)
|
||||
.pl_1p5()
|
||||
.pr_0p5()
|
||||
.pb(px(1.))
|
||||
.border_1()
|
||||
.border_color(cx.theme().colors().border.opacity(0.5))
|
||||
.bg(cx.theme().colors().element_background)
|
||||
.rounded_md()
|
||||
.child(Icon::new(icon).size(IconSize::XSmall).color(Color::Muted))
|
||||
.child(Label::new(self.context.name.clone()).size(LabelSize::Small))
|
||||
.when_some(self.on_remove, |parent, on_remove| {
|
||||
parent.child(
|
||||
|
||||
@@ -18,7 +18,7 @@ pub struct UpdateNotification {
|
||||
impl EventEmitter<DismissEvent> for UpdateNotification {}
|
||||
|
||||
impl Render for UpdateNotification {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl IntoElement {
|
||||
let app_name = ReleaseChannel::global(cx).display_name();
|
||||
|
||||
v_flex()
|
||||
|
||||
@@ -16,10 +16,10 @@ doctest = false
|
||||
editor.workspace = true
|
||||
gpui.workspace = true
|
||||
itertools.workspace = true
|
||||
outline.workspace = true
|
||||
theme.workspace = true
|
||||
ui.workspace = true
|
||||
workspace.workspace = true
|
||||
zed_actions.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
editor = { workspace = true, features = ["test-support"] }
|
||||
|
||||
@@ -102,11 +102,8 @@ impl Render for Breadcrumbs {
|
||||
.on_click({
|
||||
let editor = editor.clone();
|
||||
move |_, cx| {
|
||||
if let Some((editor, callback)) = editor
|
||||
.upgrade()
|
||||
.zip(zed_actions::outline::TOGGLE_OUTLINE.get())
|
||||
{
|
||||
callback(editor.to_any(), cx);
|
||||
if let Some(editor) = editor.upgrade() {
|
||||
outline::toggle(editor, &editor::actions::ToggleOutline, cx)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -115,14 +112,14 @@ impl Render for Breadcrumbs {
|
||||
let focus_handle = editor.read(cx).focus_handle(cx);
|
||||
Tooltip::for_action_in(
|
||||
"Show Symbol Outline",
|
||||
&zed_actions::outline::ToggleOutline,
|
||||
&editor::actions::ToggleOutline,
|
||||
&focus_handle,
|
||||
cx,
|
||||
)
|
||||
} else {
|
||||
Tooltip::for_action(
|
||||
"Show Symbol Outline",
|
||||
&zed_actions::outline::ToggleOutline,
|
||||
&editor::actions::ToggleOutline,
|
||||
cx,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ anyhow.workspace = true
|
||||
clap.workspace = true
|
||||
collections.workspace = true
|
||||
ipc-channel = "0.19"
|
||||
once_cell.workspace = true
|
||||
parking_lot.workspace = true
|
||||
paths.workspace = true
|
||||
release_channel.workspace = true
|
||||
|
||||
@@ -18,12 +18,6 @@ use std::{
|
||||
use tempfile::NamedTempFile;
|
||||
use util::paths::PathWithPosition;
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
|
||||
use {
|
||||
std::io::IsTerminal,
|
||||
util::{load_login_shell_environment, load_shell_from_passwd, ResultExt},
|
||||
};
|
||||
|
||||
struct Detect;
|
||||
|
||||
trait InstalledApp {
|
||||
@@ -167,16 +161,7 @@ fn main() -> Result<()> {
|
||||
None
|
||||
};
|
||||
|
||||
// On Linux, desktop entry uses `cli` to spawn `zed`, so we need to load env vars from the shell
|
||||
// since it doesn't inherit env vars from the terminal.
|
||||
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
|
||||
if !std::io::stdout().is_terminal() {
|
||||
load_shell_from_passwd().log_err();
|
||||
load_login_shell_environment().log_err();
|
||||
}
|
||||
|
||||
let env = Some(std::env::vars().collect::<HashMap<_, _>>());
|
||||
|
||||
let exit_status = Arc::new(Mutex::new(None));
|
||||
let mut paths = vec![];
|
||||
let mut urls = vec![];
|
||||
@@ -257,7 +242,6 @@ fn main() -> Result<()> {
|
||||
if args.foreground {
|
||||
app.run_foreground(url)?;
|
||||
} else {
|
||||
eprintln!("Logs are written to {:?}", paths::log_file());
|
||||
app.launch(url)?;
|
||||
sender.join().unwrap()?;
|
||||
pipe_handle.join().unwrap()?;
|
||||
@@ -278,7 +262,6 @@ mod linux {
|
||||
os::unix::net::{SocketAddr, UnixDatagram},
|
||||
path::{Path, PathBuf},
|
||||
process::{self, ExitStatus},
|
||||
sync::LazyLock,
|
||||
thread,
|
||||
time::Duration,
|
||||
};
|
||||
@@ -286,11 +269,12 @@ mod linux {
|
||||
use anyhow::anyhow;
|
||||
use cli::FORCE_CLI_MODE_ENV_VAR_NAME;
|
||||
use fork::Fork;
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
use crate::{Detect, InstalledApp};
|
||||
|
||||
static RELEASE_CHANNEL: LazyLock<String> =
|
||||
LazyLock::new(|| include_str!("../../zed/RELEASE_CHANNEL").trim().to_string());
|
||||
static RELEASE_CHANNEL: Lazy<String> =
|
||||
Lazy::new(|| include_str!("../../zed/RELEASE_CHANNEL").trim().to_string());
|
||||
|
||||
struct App(PathBuf);
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ futures.workspace = true
|
||||
gpui.workspace = true
|
||||
http_client.workspace = true
|
||||
log.workspace = true
|
||||
once_cell.workspace = true
|
||||
paths.workspace = true
|
||||
parking_lot.workspace = true
|
||||
postage.workspace = true
|
||||
|
||||
@@ -8,6 +8,7 @@ use futures::channel::mpsc;
|
||||
use futures::{Future, StreamExt};
|
||||
use gpui::{AppContext, BackgroundExecutor, Task};
|
||||
use http_client::{self, AsyncBody, HttpClient, HttpClientWithUrl, Method, Request};
|
||||
use once_cell::sync::Lazy;
|
||||
use parking_lot::Mutex;
|
||||
use release_channel::ReleaseChannel;
|
||||
use settings::{Settings, SettingsStore};
|
||||
@@ -15,12 +16,7 @@ use sha2::{Digest, Sha256};
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::time::Instant;
|
||||
use std::{
|
||||
env, mem,
|
||||
path::PathBuf,
|
||||
sync::{Arc, LazyLock},
|
||||
time::Duration,
|
||||
};
|
||||
use std::{env, mem, path::PathBuf, sync::Arc, time::Duration};
|
||||
use telemetry_events::{
|
||||
AppEvent, AssistantEvent, CallEvent, EditEvent, Event, EventRequestBody, EventWrapper,
|
||||
InlineCompletionEvent,
|
||||
@@ -88,7 +84,7 @@ const FLUSH_INTERVAL: Duration = Duration::from_secs(1);
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
const FLUSH_INTERVAL: Duration = Duration::from_secs(60 * 5);
|
||||
static ZED_CLIENT_CHECKSUM_SEED: LazyLock<Option<Vec<u8>>> = LazyLock::new(|| {
|
||||
static ZED_CLIENT_CHECKSUM_SEED: Lazy<Option<Vec<u8>>> = Lazy::new(|| {
|
||||
option_env!("ZED_CLIENT_CHECKSUM_SEED")
|
||||
.map(|s| s.as_bytes().into())
|
||||
.or_else(|| {
|
||||
|
||||
@@ -279,7 +279,6 @@ pub async fn post_panic(
|
||||
|
||||
let report: telemetry_events::PanicRequest = serde_json::from_slice(&body)
|
||||
.map_err(|_| Error::http(StatusCode::BAD_REQUEST, "invalid json".into()))?;
|
||||
let incident_id = uuid::Uuid::new_v4().to_string();
|
||||
let panic = report.panic;
|
||||
|
||||
if panic.os_name == "Linux" && panic.os_version == Some("1.0.0".to_string()) {
|
||||
@@ -289,37 +288,11 @@ pub async fn post_panic(
|
||||
))?;
|
||||
}
|
||||
|
||||
if let Some(blob_store_client) = app.blob_store_client.as_ref() {
|
||||
let response = blob_store_client
|
||||
.head_object()
|
||||
.bucket(CRASH_REPORTS_BUCKET)
|
||||
.key(incident_id.clone() + ".json")
|
||||
.send()
|
||||
.await;
|
||||
|
||||
if response.is_ok() {
|
||||
log::info!("We've already uploaded this crash");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
blob_store_client
|
||||
.put_object()
|
||||
.bucket(CRASH_REPORTS_BUCKET)
|
||||
.key(incident_id.clone() + ".json")
|
||||
.acl(aws_sdk_s3::types::ObjectCannedAcl::PublicRead)
|
||||
.body(ByteStream::from(body.to_vec()))
|
||||
.send()
|
||||
.await
|
||||
.map_err(|e| log::error!("Failed to upload crash: {}", e))
|
||||
.ok();
|
||||
}
|
||||
|
||||
tracing::error!(
|
||||
service = "client",
|
||||
version = %panic.app_version,
|
||||
os_name = %panic.os_name,
|
||||
os_version = %panic.os_version.clone().unwrap_or_default(),
|
||||
incident_id = %incident_id,
|
||||
installation_id = %panic.installation_id.clone().unwrap_or_default(),
|
||||
description = %panic.payload,
|
||||
backtrace = %panic.backtrace.join("\n"),
|
||||
@@ -358,19 +331,10 @@ pub async fn post_panic(
|
||||
panic.app_version
|
||||
)))
|
||||
.add_field({
|
||||
let hostname = app.config.blob_store_url.clone().unwrap_or_default();
|
||||
let hostname = hostname.strip_prefix("https://").unwrap_or_else(|| {
|
||||
hostname.strip_prefix("http://").unwrap_or_default()
|
||||
});
|
||||
|
||||
slack::Text::markdown(format!(
|
||||
"*{} {}:*\n<https://{}.{}/{}.json|{}…>",
|
||||
"*OS:*\n{} {}",
|
||||
panic.os_name,
|
||||
panic.os_version.unwrap_or_default(),
|
||||
CRASH_REPORTS_BUCKET,
|
||||
hostname,
|
||||
incident_id,
|
||||
incident_id.chars().take(8).collect::<String>(),
|
||||
panic.os_version.unwrap_or_default()
|
||||
))
|
||||
})
|
||||
})
|
||||
@@ -397,12 +361,6 @@ pub async fn post_panic(
|
||||
}
|
||||
|
||||
fn report_to_slack(panic: &Panic) -> bool {
|
||||
// Panics on macOS should make their way to Slack as a crash report,
|
||||
// so we don't need to send them a second time via this channel.
|
||||
if panic.os_name == "macOS" {
|
||||
return false;
|
||||
}
|
||||
|
||||
if panic.payload.contains("ERROR_SURFACE_LOST_KHR") {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1096,7 +1096,7 @@ impl FocusableView for ChatPanel {
|
||||
}
|
||||
|
||||
impl Panel for ChatPanel {
|
||||
fn position(&self, cx: &WindowContext) -> DockPosition {
|
||||
fn position(&self, cx: &gpui::WindowContext) -> DockPosition {
|
||||
ChatPanelSettings::get_global(cx).dock
|
||||
}
|
||||
|
||||
@@ -1112,7 +1112,7 @@ impl Panel for ChatPanel {
|
||||
);
|
||||
}
|
||||
|
||||
fn size(&self, cx: &WindowContext) -> Pixels {
|
||||
fn size(&self, cx: &gpui::WindowContext) -> Pixels {
|
||||
self.width
|
||||
.unwrap_or_else(|| ChatPanelSettings::get_global(cx).default_width)
|
||||
}
|
||||
@@ -1141,7 +1141,6 @@ impl Panel for ChatPanel {
|
||||
ChatPanelButton::WhenInCall => ActiveCall::global(cx)
|
||||
.read(cx)
|
||||
.room()
|
||||
.filter(|room| room.read(cx).contains_guests())
|
||||
.map(|_| ui::IconName::MessageBubbles),
|
||||
}
|
||||
}
|
||||
@@ -1160,10 +1159,6 @@ impl Panel for ChatPanel {
|
||||
.room()
|
||||
.is_some_and(|room| room.read(cx).contains_guests())
|
||||
}
|
||||
|
||||
fn activation_priority(&self) -> u32 {
|
||||
7
|
||||
}
|
||||
}
|
||||
|
||||
impl EventEmitter<PanelEvent> for ChatPanel {}
|
||||
|
||||
@@ -79,6 +79,16 @@ impl CompletionProvider for MessageEditorCompletionProvider {
|
||||
Task::ready(Ok(false))
|
||||
}
|
||||
|
||||
fn apply_additional_edits_for_completion(
|
||||
&self,
|
||||
_buffer: Model<Buffer>,
|
||||
_completion: Completion,
|
||||
_push_to_history: bool,
|
||||
_cx: &mut ViewContext<Editor>,
|
||||
) -> Task<Result<Option<language::Transaction>>> {
|
||||
Task::ready(Ok(None))
|
||||
}
|
||||
|
||||
fn is_completion_trigger(
|
||||
&self,
|
||||
_buffer: &Model<Buffer>,
|
||||
@@ -309,7 +319,6 @@ impl MessageEditor {
|
||||
server_id: LanguageServerId(0), // TODO: Make this optional or something?
|
||||
lsp_completion: Default::default(), // TODO: Make this optional or something?
|
||||
confirm: None,
|
||||
resolved: true,
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
|
||||
@@ -2719,7 +2719,7 @@ impl Render for CollabPanel {
|
||||
impl EventEmitter<PanelEvent> for CollabPanel {}
|
||||
|
||||
impl Panel for CollabPanel {
|
||||
fn position(&self, cx: &WindowContext) -> DockPosition {
|
||||
fn position(&self, cx: &gpui::WindowContext) -> DockPosition {
|
||||
CollaborationPanelSettings::get_global(cx).dock
|
||||
}
|
||||
|
||||
@@ -2735,7 +2735,7 @@ impl Panel for CollabPanel {
|
||||
);
|
||||
}
|
||||
|
||||
fn size(&self, cx: &WindowContext) -> Pixels {
|
||||
fn size(&self, cx: &gpui::WindowContext) -> Pixels {
|
||||
self.width
|
||||
.unwrap_or_else(|| CollaborationPanelSettings::get_global(cx).default_width)
|
||||
}
|
||||
@@ -2746,7 +2746,7 @@ impl Panel for CollabPanel {
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn icon(&self, cx: &WindowContext) -> Option<ui::IconName> {
|
||||
fn icon(&self, cx: &gpui::WindowContext) -> Option<ui::IconName> {
|
||||
CollaborationPanelSettings::get_global(cx)
|
||||
.button
|
||||
.then_some(ui::IconName::UserGroup)
|
||||
@@ -2763,10 +2763,6 @@ impl Panel for CollabPanel {
|
||||
fn persistent_name() -> &'static str {
|
||||
"CollabPanel"
|
||||
}
|
||||
|
||||
fn activation_priority(&self) -> u32 {
|
||||
6
|
||||
}
|
||||
}
|
||||
|
||||
impl FocusableView for CollabPanel {
|
||||
|
||||
@@ -662,7 +662,7 @@ impl Panel for NotificationPanel {
|
||||
"NotificationPanel"
|
||||
}
|
||||
|
||||
fn position(&self, cx: &WindowContext) -> DockPosition {
|
||||
fn position(&self, cx: &gpui::WindowContext) -> DockPosition {
|
||||
NotificationPanelSettings::get_global(cx).dock
|
||||
}
|
||||
|
||||
@@ -678,7 +678,7 @@ impl Panel for NotificationPanel {
|
||||
);
|
||||
}
|
||||
|
||||
fn size(&self, cx: &WindowContext) -> Pixels {
|
||||
fn size(&self, cx: &gpui::WindowContext) -> Pixels {
|
||||
self.width
|
||||
.unwrap_or_else(|| NotificationPanelSettings::get_global(cx).default_width)
|
||||
}
|
||||
@@ -702,7 +702,7 @@ impl Panel for NotificationPanel {
|
||||
}
|
||||
}
|
||||
|
||||
fn icon(&self, cx: &WindowContext) -> Option<IconName> {
|
||||
fn icon(&self, cx: &gpui::WindowContext) -> Option<IconName> {
|
||||
let show_button = NotificationPanelSettings::get_global(cx).button;
|
||||
if !show_button {
|
||||
return None;
|
||||
@@ -731,10 +731,6 @@ impl Panel for NotificationPanel {
|
||||
fn toggle_action(&self) -> Box<dyn gpui::Action> {
|
||||
Box::new(ToggleFocus)
|
||||
}
|
||||
|
||||
fn activation_priority(&self) -> u32 {
|
||||
8
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NotificationToast {
|
||||
|
||||
@@ -28,6 +28,7 @@ serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
settings.workspace = true
|
||||
smol.workspace = true
|
||||
ui.workspace = true
|
||||
url = { workspace = true, features = ["serde"] }
|
||||
util.workspace = true
|
||||
workspace.workspace = true
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::sync::Arc;
|
||||
|
||||
use anyhow::{anyhow, bail};
|
||||
use assistant_tool::Tool;
|
||||
use gpui::{Model, Task, WindowContext};
|
||||
use gpui::{Model, Task};
|
||||
|
||||
use crate::manager::ContextServerManager;
|
||||
use crate::types;
|
||||
@@ -52,7 +52,7 @@ impl Tool for ContextServerTool {
|
||||
self: std::sync::Arc<Self>,
|
||||
input: serde_json::Value,
|
||||
_workspace: gpui::WeakView<workspace::Workspace>,
|
||||
cx: &mut WindowContext,
|
||||
cx: &mut ui::WindowContext,
|
||||
) -> gpui::Task<gpui::Result<String>> {
|
||||
if let Some(server) = self.server_manager.read(cx).get_server(&self.server_id) {
|
||||
cx.foreground_executor().spawn({
|
||||
|
||||
@@ -34,9 +34,9 @@ pub enum Model {
|
||||
Gpt4,
|
||||
#[serde(alias = "gpt-3.5-turbo", rename = "gpt-3.5-turbo")]
|
||||
Gpt3_5Turbo,
|
||||
#[serde(alias = "o1-preview", rename = "o1")]
|
||||
#[serde(alias = "o1-preview", rename = "o1-preview-2024-09-12")]
|
||||
O1Preview,
|
||||
#[serde(alias = "o1-mini", rename = "o1-mini")]
|
||||
#[serde(alias = "o1-mini", rename = "o1-mini-2024-09-12")]
|
||||
O1Mini,
|
||||
#[serde(alias = "claude-3-5-sonnet", rename = "claude-3.5-sonnet")]
|
||||
Claude3_5Sonnet,
|
||||
|
||||
@@ -166,7 +166,7 @@ impl ProjectDiagnosticsEditor {
|
||||
let excerpts = cx.new_model(|cx| MultiBuffer::new(project_handle.read(cx).capability()));
|
||||
let editor = cx.new_view(|cx| {
|
||||
let mut editor =
|
||||
Editor::for_multibuffer(excerpts.clone(), Some(project_handle.clone()), true, cx);
|
||||
Editor::for_multibuffer(excerpts.clone(), Some(project_handle.clone()), false, cx);
|
||||
editor.set_vertical_scroll_margin(5, cx);
|
||||
editor
|
||||
});
|
||||
@@ -836,76 +836,65 @@ fn diagnostic_header_renderer(diagnostic: Diagnostic) -> RenderBlock {
|
||||
let (message, code_ranges) = highlight_diagnostic_message(&diagnostic, None);
|
||||
let message: SharedString = message;
|
||||
Arc::new(move |cx| {
|
||||
let color = cx.theme().colors();
|
||||
let highlight_style: HighlightStyle = color.text_accent.into();
|
||||
|
||||
let highlight_style: HighlightStyle = cx.theme().colors().text_accent.into();
|
||||
h_flex()
|
||||
.id(DIAGNOSTIC_HEADER)
|
||||
.block_mouse_down()
|
||||
.h(2. * cx.line_height())
|
||||
.pl_10()
|
||||
.pr_5()
|
||||
.w_full()
|
||||
.relative()
|
||||
.justify_between()
|
||||
.gap_2()
|
||||
.child(
|
||||
div()
|
||||
.top(px(0.))
|
||||
.absolute()
|
||||
.w_full()
|
||||
.h_px()
|
||||
.bg(color.border_variant),
|
||||
h_flex()
|
||||
.gap_3()
|
||||
.map(|stack| {
|
||||
stack.child(
|
||||
svg()
|
||||
.size(cx.text_style().font_size)
|
||||
.flex_none()
|
||||
.map(|icon| {
|
||||
if diagnostic.severity == DiagnosticSeverity::ERROR {
|
||||
icon.path(IconName::XCircle.path())
|
||||
.text_color(Color::Error.color(cx))
|
||||
} else {
|
||||
icon.path(IconName::Warning.path())
|
||||
.text_color(Color::Warning.color(cx))
|
||||
}
|
||||
}),
|
||||
)
|
||||
})
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_1()
|
||||
.child(
|
||||
StyledText::new(message.clone()).with_highlights(
|
||||
&cx.text_style(),
|
||||
code_ranges
|
||||
.iter()
|
||||
.map(|range| (range.clone(), highlight_style)),
|
||||
),
|
||||
)
|
||||
.when_some(diagnostic.code.as_ref(), |stack, code| {
|
||||
stack.child(
|
||||
div()
|
||||
.child(SharedString::from(format!("({code})")))
|
||||
.text_color(cx.theme().colors().text_muted),
|
||||
)
|
||||
}),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
h_flex()
|
||||
.block_mouse_down()
|
||||
.h(2. * cx.line_height())
|
||||
.pl_10()
|
||||
.pr_5()
|
||||
.w_full()
|
||||
.justify_between()
|
||||
.gap_2()
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_3()
|
||||
.map(|stack| {
|
||||
stack.child(svg().size(cx.text_style().font_size).flex_none().map(
|
||||
|icon| {
|
||||
if diagnostic.severity == DiagnosticSeverity::ERROR {
|
||||
icon.path(IconName::XCircle.path())
|
||||
.text_color(Color::Error.color(cx))
|
||||
} else {
|
||||
icon.path(IconName::Warning.path())
|
||||
.text_color(Color::Warning.color(cx))
|
||||
}
|
||||
},
|
||||
))
|
||||
})
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_1()
|
||||
.child(
|
||||
StyledText::new(message.clone()).with_highlights(
|
||||
&cx.text_style(),
|
||||
code_ranges
|
||||
.iter()
|
||||
.map(|range| (range.clone(), highlight_style)),
|
||||
),
|
||||
)
|
||||
.when_some(diagnostic.code.as_ref(), |stack, code| {
|
||||
stack.child(
|
||||
div()
|
||||
.child(SharedString::from(format!("({code})")))
|
||||
.text_color(cx.theme().colors().text_muted),
|
||||
)
|
||||
}),
|
||||
),
|
||||
)
|
||||
.child(h_flex().gap_1().when_some(
|
||||
diagnostic.source.as_ref(),
|
||||
|stack, source| {
|
||||
stack.child(
|
||||
div()
|
||||
.child(SharedString::from(source.clone()))
|
||||
.text_color(cx.theme().colors().text_muted),
|
||||
)
|
||||
},
|
||||
)),
|
||||
.gap_1()
|
||||
.when_some(diagnostic.source.as_ref(), |stack, source| {
|
||||
stack.child(
|
||||
div()
|
||||
.child(SharedString::from(source.clone()))
|
||||
.text_color(cx.theme().colors().text_muted),
|
||||
)
|
||||
}),
|
||||
)
|
||||
.into_any_element()
|
||||
})
|
||||
|
||||
@@ -167,10 +167,10 @@ async fn test_diagnostics(cx: &mut TestAppContext) {
|
||||
editor_blocks(&editor, cx),
|
||||
[
|
||||
(DisplayRow(0), FILE_HEADER.into()),
|
||||
(DisplayRow(3), DIAGNOSTIC_HEADER.into()),
|
||||
(DisplayRow(16), EXCERPT_HEADER.into()),
|
||||
(DisplayRow(18), DIAGNOSTIC_HEADER.into()),
|
||||
(DisplayRow(27), EXCERPT_HEADER.into()),
|
||||
(DisplayRow(2), DIAGNOSTIC_HEADER.into()),
|
||||
(DisplayRow(15), EXCERPT_HEADER.into()),
|
||||
(DisplayRow(16), DIAGNOSTIC_HEADER.into()),
|
||||
(DisplayRow(25), EXCERPT_HEADER.into()),
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -184,7 +184,6 @@ async fn test_diagnostics(cx: &mut TestAppContext) {
|
||||
// diagnostic group 1
|
||||
"\n", // primary message
|
||||
"\n", // padding
|
||||
"\n", // expand
|
||||
" let x = vec![];\n",
|
||||
" let y = vec![];\n",
|
||||
"\n", // supporting diagnostic
|
||||
@@ -196,7 +195,6 @@ async fn test_diagnostics(cx: &mut TestAppContext) {
|
||||
" c(y);\n",
|
||||
"\n", // supporting diagnostic
|
||||
" d(x);\n",
|
||||
"\n", // expand
|
||||
"\n", // context ellipsis
|
||||
// diagnostic group 2
|
||||
"\n", // primary message
|
||||
@@ -208,13 +206,11 @@ async fn test_diagnostics(cx: &mut TestAppContext) {
|
||||
" a(x);\n",
|
||||
"\n", // supporting diagnostic
|
||||
" b(y);\n",
|
||||
"\n", // expand
|
||||
"\n", // context ellipsis
|
||||
" c(y);\n",
|
||||
" d(x);\n",
|
||||
"\n", // supporting diagnostic
|
||||
"}",
|
||||
"\n", // expand
|
||||
"}"
|
||||
)
|
||||
);
|
||||
|
||||
@@ -222,7 +218,7 @@ async fn test_diagnostics(cx: &mut TestAppContext) {
|
||||
editor.update(cx, |editor, cx| {
|
||||
assert_eq!(
|
||||
editor.selections.display_ranges(cx),
|
||||
[DisplayPoint::new(DisplayRow(13), 6)..DisplayPoint::new(DisplayRow(13), 6)]
|
||||
[DisplayPoint::new(DisplayRow(12), 6)..DisplayPoint::new(DisplayRow(12), 6)]
|
||||
);
|
||||
});
|
||||
|
||||
@@ -257,12 +253,12 @@ async fn test_diagnostics(cx: &mut TestAppContext) {
|
||||
editor_blocks(&editor, cx),
|
||||
[
|
||||
(DisplayRow(0), FILE_HEADER.into()),
|
||||
(DisplayRow(3), DIAGNOSTIC_HEADER.into()),
|
||||
(DisplayRow(8), FILE_HEADER.into()),
|
||||
(DisplayRow(12), DIAGNOSTIC_HEADER.into()),
|
||||
(DisplayRow(25), EXCERPT_HEADER.into()),
|
||||
(DisplayRow(27), DIAGNOSTIC_HEADER.into()),
|
||||
(DisplayRow(36), EXCERPT_HEADER.into()),
|
||||
(DisplayRow(2), DIAGNOSTIC_HEADER.into()),
|
||||
(DisplayRow(7), FILE_HEADER.into()),
|
||||
(DisplayRow(9), DIAGNOSTIC_HEADER.into()),
|
||||
(DisplayRow(22), EXCERPT_HEADER.into()),
|
||||
(DisplayRow(23), DIAGNOSTIC_HEADER.into()),
|
||||
(DisplayRow(32), EXCERPT_HEADER.into()),
|
||||
]
|
||||
);
|
||||
|
||||
@@ -277,7 +273,6 @@ async fn test_diagnostics(cx: &mut TestAppContext) {
|
||||
// diagnostic group 1
|
||||
"\n", // primary message
|
||||
"\n", // padding
|
||||
"\n", // expand
|
||||
"const a: i32 = 'a';\n",
|
||||
"\n", // supporting diagnostic
|
||||
"const b: i32 = c;\n",
|
||||
@@ -289,8 +284,6 @@ async fn test_diagnostics(cx: &mut TestAppContext) {
|
||||
// diagnostic group 1
|
||||
"\n", // primary message
|
||||
"\n", // padding
|
||||
"\n", // expand
|
||||
"\n", // expand
|
||||
" let x = vec![];\n",
|
||||
" let y = vec![];\n",
|
||||
"\n", // supporting diagnostic
|
||||
@@ -306,7 +299,6 @@ async fn test_diagnostics(cx: &mut TestAppContext) {
|
||||
// diagnostic group 2
|
||||
"\n", // primary message
|
||||
"\n", // filename
|
||||
"\n", // expand
|
||||
"fn main() {\n",
|
||||
" let x = vec![];\n",
|
||||
"\n", // supporting diagnostic
|
||||
@@ -314,13 +306,11 @@ async fn test_diagnostics(cx: &mut TestAppContext) {
|
||||
" a(x);\n",
|
||||
"\n", // supporting diagnostic
|
||||
" b(y);\n",
|
||||
"\n", // expand
|
||||
"\n", // context ellipsis
|
||||
" c(y);\n",
|
||||
" d(x);\n",
|
||||
"\n", // supporting diagnostic
|
||||
"}",
|
||||
"\n", // expand
|
||||
"}"
|
||||
)
|
||||
);
|
||||
|
||||
@@ -328,7 +318,7 @@ async fn test_diagnostics(cx: &mut TestAppContext) {
|
||||
editor.update(cx, |editor, cx| {
|
||||
assert_eq!(
|
||||
editor.selections.display_ranges(cx),
|
||||
[DisplayPoint::new(DisplayRow(22), 6)..DisplayPoint::new(DisplayRow(22), 6)]
|
||||
[DisplayPoint::new(DisplayRow(19), 6)..DisplayPoint::new(DisplayRow(19), 6)]
|
||||
);
|
||||
});
|
||||
|
||||
@@ -376,14 +366,14 @@ async fn test_diagnostics(cx: &mut TestAppContext) {
|
||||
editor_blocks(&editor, cx),
|
||||
[
|
||||
(DisplayRow(0), FILE_HEADER.into()),
|
||||
(DisplayRow(3), DIAGNOSTIC_HEADER.into()),
|
||||
(DisplayRow(8), EXCERPT_HEADER.into()),
|
||||
(DisplayRow(10), DIAGNOSTIC_HEADER.into()),
|
||||
(DisplayRow(15), FILE_HEADER.into()),
|
||||
(DisplayRow(19), DIAGNOSTIC_HEADER.into()),
|
||||
(DisplayRow(32), EXCERPT_HEADER.into()),
|
||||
(DisplayRow(34), DIAGNOSTIC_HEADER.into()),
|
||||
(DisplayRow(43), EXCERPT_HEADER.into()),
|
||||
(DisplayRow(2), DIAGNOSTIC_HEADER.into()),
|
||||
(DisplayRow(7), EXCERPT_HEADER.into()),
|
||||
(DisplayRow(8), DIAGNOSTIC_HEADER.into()),
|
||||
(DisplayRow(13), FILE_HEADER.into()),
|
||||
(DisplayRow(15), DIAGNOSTIC_HEADER.into()),
|
||||
(DisplayRow(28), EXCERPT_HEADER.into()),
|
||||
(DisplayRow(29), DIAGNOSTIC_HEADER.into()),
|
||||
(DisplayRow(38), EXCERPT_HEADER.into()),
|
||||
]
|
||||
);
|
||||
|
||||
@@ -398,7 +388,6 @@ async fn test_diagnostics(cx: &mut TestAppContext) {
|
||||
// diagnostic group 1
|
||||
"\n", // primary message
|
||||
"\n", // padding
|
||||
"\n", // expand
|
||||
"const a: i32 = 'a';\n",
|
||||
"\n", // supporting diagnostic
|
||||
"const b: i32 = c;\n",
|
||||
@@ -406,7 +395,6 @@ async fn test_diagnostics(cx: &mut TestAppContext) {
|
||||
// diagnostic group 2
|
||||
"\n", // primary message
|
||||
"\n", // padding
|
||||
"\n", // expand
|
||||
"const a: i32 = 'a';\n",
|
||||
"const b: i32 = c;\n",
|
||||
"\n", // supporting diagnostic
|
||||
@@ -418,8 +406,6 @@ async fn test_diagnostics(cx: &mut TestAppContext) {
|
||||
// diagnostic group 1
|
||||
"\n", // primary message
|
||||
"\n", // padding
|
||||
"\n", // expand
|
||||
"\n", // expand
|
||||
" let x = vec![];\n",
|
||||
" let y = vec![];\n",
|
||||
"\n", // supporting diagnostic
|
||||
@@ -435,7 +421,6 @@ async fn test_diagnostics(cx: &mut TestAppContext) {
|
||||
// diagnostic group 2
|
||||
"\n", // primary message
|
||||
"\n", // filename
|
||||
"\n", // expand
|
||||
"fn main() {\n",
|
||||
" let x = vec![];\n",
|
||||
"\n", // supporting diagnostic
|
||||
@@ -443,13 +428,11 @@ async fn test_diagnostics(cx: &mut TestAppContext) {
|
||||
" a(x);\n",
|
||||
"\n", // supporting diagnostic
|
||||
" b(y);\n",
|
||||
"\n", // expand
|
||||
"\n", // context ellipsis
|
||||
" c(y);\n",
|
||||
" d(x);\n",
|
||||
"\n", // supporting diagnostic
|
||||
"}",
|
||||
"\n", // expand
|
||||
"}"
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -530,7 +513,7 @@ async fn test_diagnostics_multiple_servers(cx: &mut TestAppContext) {
|
||||
editor_blocks(&editor, cx),
|
||||
[
|
||||
(DisplayRow(0), FILE_HEADER.into()),
|
||||
(DisplayRow(3), DIAGNOSTIC_HEADER.into()),
|
||||
(DisplayRow(2), DIAGNOSTIC_HEADER.into()),
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -541,9 +524,8 @@ async fn test_diagnostics_multiple_servers(cx: &mut TestAppContext) {
|
||||
// diagnostic group 1
|
||||
"\n", // primary message
|
||||
"\n", // padding
|
||||
"\n", // expand
|
||||
"a();\n", //
|
||||
"b();", "\n", // expand
|
||||
"b();",
|
||||
)
|
||||
);
|
||||
|
||||
@@ -579,9 +561,9 @@ async fn test_diagnostics_multiple_servers(cx: &mut TestAppContext) {
|
||||
editor_blocks(&editor, cx),
|
||||
[
|
||||
(DisplayRow(0), FILE_HEADER.into()),
|
||||
(DisplayRow(3), DIAGNOSTIC_HEADER.into()),
|
||||
(DisplayRow(7), EXCERPT_HEADER.into()),
|
||||
(DisplayRow(9), DIAGNOSTIC_HEADER.into()),
|
||||
(DisplayRow(2), DIAGNOSTIC_HEADER.into()),
|
||||
(DisplayRow(6), EXCERPT_HEADER.into()),
|
||||
(DisplayRow(7), DIAGNOSTIC_HEADER.into()),
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -592,10 +574,8 @@ async fn test_diagnostics_multiple_servers(cx: &mut TestAppContext) {
|
||||
// diagnostic group 1
|
||||
"\n", // primary message
|
||||
"\n", // padding
|
||||
"\n", // expand
|
||||
"a();\n", // location
|
||||
"b();\n", //
|
||||
"\n", // expand
|
||||
"\n", // collapsed context
|
||||
// diagnostic group 2
|
||||
"\n", // primary message
|
||||
@@ -603,7 +583,6 @@ async fn test_diagnostics_multiple_servers(cx: &mut TestAppContext) {
|
||||
"a();\n", // context
|
||||
"b();\n", //
|
||||
"c();", // context
|
||||
"\n", // expand
|
||||
)
|
||||
);
|
||||
|
||||
@@ -650,9 +629,9 @@ async fn test_diagnostics_multiple_servers(cx: &mut TestAppContext) {
|
||||
editor_blocks(&editor, cx),
|
||||
[
|
||||
(DisplayRow(0), FILE_HEADER.into()),
|
||||
(DisplayRow(3), DIAGNOSTIC_HEADER.into()),
|
||||
(DisplayRow(8), EXCERPT_HEADER.into()),
|
||||
(DisplayRow(10), DIAGNOSTIC_HEADER.into()),
|
||||
(DisplayRow(2), DIAGNOSTIC_HEADER.into()),
|
||||
(DisplayRow(7), EXCERPT_HEADER.into()),
|
||||
(DisplayRow(8), DIAGNOSTIC_HEADER.into()),
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -663,11 +642,9 @@ async fn test_diagnostics_multiple_servers(cx: &mut TestAppContext) {
|
||||
// diagnostic group 1
|
||||
"\n", // primary message
|
||||
"\n", // padding
|
||||
"\n", // expand
|
||||
"a();\n", // location
|
||||
"b();\n", //
|
||||
"c();\n", // context
|
||||
"\n", // expand
|
||||
"\n", // collapsed context
|
||||
// diagnostic group 2
|
||||
"\n", // primary message
|
||||
@@ -675,7 +652,6 @@ async fn test_diagnostics_multiple_servers(cx: &mut TestAppContext) {
|
||||
"b();\n", // context
|
||||
"c();\n", //
|
||||
"d();", // context
|
||||
"\n", // expand
|
||||
)
|
||||
);
|
||||
|
||||
@@ -711,9 +687,9 @@ async fn test_diagnostics_multiple_servers(cx: &mut TestAppContext) {
|
||||
editor_blocks(&editor, cx),
|
||||
[
|
||||
(DisplayRow(0), FILE_HEADER.into()),
|
||||
(DisplayRow(3), DIAGNOSTIC_HEADER.into()),
|
||||
(DisplayRow(8), EXCERPT_HEADER.into()),
|
||||
(DisplayRow(10), DIAGNOSTIC_HEADER.into()),
|
||||
(DisplayRow(2), DIAGNOSTIC_HEADER.into()),
|
||||
(DisplayRow(7), EXCERPT_HEADER.into()),
|
||||
(DisplayRow(8), DIAGNOSTIC_HEADER.into()),
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -724,11 +700,9 @@ async fn test_diagnostics_multiple_servers(cx: &mut TestAppContext) {
|
||||
// diagnostic group 1
|
||||
"\n", // primary message
|
||||
"\n", // padding
|
||||
"\n", // expand
|
||||
"b();\n", // location
|
||||
"c();\n", //
|
||||
"d();\n", // context
|
||||
"\n", // expand
|
||||
"\n", // collapsed context
|
||||
// diagnostic group 2
|
||||
"\n", // primary message
|
||||
@@ -736,7 +710,6 @@ async fn test_diagnostics_multiple_servers(cx: &mut TestAppContext) {
|
||||
"c();\n", // context
|
||||
"d();\n", //
|
||||
"e();", // context
|
||||
"\n", // expand
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -388,4 +388,6 @@ gpui::actions!(
|
||||
]
|
||||
);
|
||||
|
||||
action_as!(outline, ToggleOutline as Toggle);
|
||||
|
||||
action_as!(go_to_line, ToggleGoToLine as Toggle);
|
||||
|
||||
@@ -16,7 +16,7 @@ fn is_c_language(language: &Language) -> bool {
|
||||
pub fn switch_source_header(
|
||||
editor: &mut Editor,
|
||||
_: &SwitchSourceHeader,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
cx: &mut ViewContext<'_, Editor>,
|
||||
) {
|
||||
let Some(project) = &editor.project else {
|
||||
return;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use fuzzy::{StringMatch, StringMatchCandidate};
|
||||
use gpui::{
|
||||
div, px, uniform_list, AnyElement, BackgroundExecutor, Div, FontWeight, ListSizingBehavior,
|
||||
Model, ScrollStrategy, SharedString, Size, StrikethroughStyle, StyledText,
|
||||
UniformListScrollHandle, ViewContext, WeakView,
|
||||
Model, ScrollStrategy, SharedString, StrikethroughStyle, StyledText, UniformListScrollHandle,
|
||||
ViewContext, WeakView,
|
||||
};
|
||||
use language::Buffer;
|
||||
use language::{CodeLabel, Documentation};
|
||||
@@ -30,10 +30,7 @@ use crate::{
|
||||
};
|
||||
use crate::{AcceptInlineCompletion, InlineCompletionMenuHint, InlineCompletionText};
|
||||
|
||||
pub const MENU_GAP: Pixels = px(4.);
|
||||
pub const MENU_ASIDE_X_PADDING: Pixels = px(16.);
|
||||
pub const MENU_ASIDE_MIN_WIDTH: Pixels = px(260.);
|
||||
pub const MENU_ASIDE_MAX_WIDTH: Pixels = px(500.);
|
||||
pub const MAX_COMPLETIONS_ASIDE_WIDTH: Pixels = px(500.);
|
||||
|
||||
pub enum CodeContextMenu {
|
||||
Completions(CompletionsMenu),
|
||||
@@ -134,12 +131,14 @@ impl CodeContextMenu {
|
||||
pub fn render_aside(
|
||||
&self,
|
||||
style: &EditorStyle,
|
||||
max_size: Size<Pixels>,
|
||||
max_height: Pixels,
|
||||
workspace: Option<WeakView<Workspace>>,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
) -> Option<AnyElement> {
|
||||
match self {
|
||||
CodeContextMenu::Completions(menu) => menu.render_aside(style, max_size, workspace, cx),
|
||||
CodeContextMenu::Completions(menu) => {
|
||||
menu.render_aside(style, max_height, workspace, cx)
|
||||
}
|
||||
CodeContextMenu::CodeActions(_) => None,
|
||||
}
|
||||
}
|
||||
@@ -224,7 +223,6 @@ impl CompletionsMenu {
|
||||
documentation: None,
|
||||
lsp_completion: Default::default(),
|
||||
confirm: None,
|
||||
resolved: true,
|
||||
})
|
||||
.collect();
|
||||
|
||||
@@ -615,7 +613,7 @@ impl CompletionsMenu {
|
||||
fn render_aside(
|
||||
&self,
|
||||
style: &EditorStyle,
|
||||
max_size: Size<Pixels>,
|
||||
max_height: Pixels,
|
||||
workspace: Option<WeakView<Workspace>>,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
) -> Option<AnyElement> {
|
||||
@@ -665,9 +663,10 @@ impl CompletionsMenu {
|
||||
.child(
|
||||
multiline_docs
|
||||
.id("multiline_docs")
|
||||
.px(MENU_ASIDE_X_PADDING / 2.)
|
||||
.max_w(max_size.width)
|
||||
.max_h(max_size.height)
|
||||
.max_h(max_height)
|
||||
.px_2()
|
||||
.min_w(px(260.))
|
||||
.max_w(MAX_COMPLETIONS_ASIDE_WIDTH)
|
||||
.overflow_y_scroll()
|
||||
.occlude(),
|
||||
)
|
||||
|
||||
@@ -32,7 +32,6 @@ use crate::{
|
||||
pub use block_map::{
|
||||
Block, BlockBufferRows, BlockChunks as DisplayChunks, BlockContext, BlockId, BlockMap,
|
||||
BlockPlacement, BlockPoint, BlockProperties, BlockStyle, CustomBlockId, RenderBlock,
|
||||
StickyHeaderExcerpt,
|
||||
};
|
||||
use block_map::{BlockRow, BlockSnapshot};
|
||||
use collections::{HashMap, HashSet};
|
||||
@@ -1106,10 +1105,6 @@ impl DisplaySnapshot {
|
||||
.map(|(row, block)| (DisplayRow(row), block))
|
||||
}
|
||||
|
||||
pub fn sticky_header_excerpt(&self, row: DisplayRow) -> Option<StickyHeaderExcerpt<'_>> {
|
||||
self.block_snapshot.sticky_header_excerpt(row.0)
|
||||
}
|
||||
|
||||
pub fn block_for_id(&self, id: BlockId) -> Option<Block> {
|
||||
self.block_snapshot.block_for_id(id)
|
||||
}
|
||||
|
||||
@@ -1411,66 +1411,6 @@ impl BlockSnapshot {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn sticky_header_excerpt(&self, top_row: u32) -> Option<StickyHeaderExcerpt<'_>> {
|
||||
let mut cursor = self.transforms.cursor::<BlockRow>(&());
|
||||
cursor.seek(&BlockRow(top_row), Bias::Left, &());
|
||||
|
||||
while let Some(transform) = cursor.item() {
|
||||
let start = cursor.start().0;
|
||||
let end = cursor.end(&()).0;
|
||||
|
||||
match &transform.block {
|
||||
Some(Block::ExcerptBoundary {
|
||||
prev_excerpt,
|
||||
next_excerpt,
|
||||
starts_new_buffer,
|
||||
show_excerpt_controls,
|
||||
..
|
||||
}) => {
|
||||
let matches_start = if *show_excerpt_controls && prev_excerpt.is_some() {
|
||||
start < top_row
|
||||
} else {
|
||||
start <= top_row
|
||||
};
|
||||
|
||||
if matches_start && top_row <= end {
|
||||
return next_excerpt.as_ref().map(|excerpt| StickyHeaderExcerpt {
|
||||
next_buffer_row: None,
|
||||
next_excerpt_controls_present: *show_excerpt_controls,
|
||||
excerpt,
|
||||
});
|
||||
}
|
||||
|
||||
let next_buffer_row = if *starts_new_buffer { Some(end) } else { None };
|
||||
|
||||
return prev_excerpt.as_ref().map(|excerpt| StickyHeaderExcerpt {
|
||||
excerpt,
|
||||
next_buffer_row,
|
||||
next_excerpt_controls_present: *show_excerpt_controls,
|
||||
});
|
||||
}
|
||||
Some(Block::FoldedBuffer {
|
||||
prev_excerpt: Some(excerpt),
|
||||
..
|
||||
}) if top_row <= start => {
|
||||
return Some(StickyHeaderExcerpt {
|
||||
next_buffer_row: Some(end),
|
||||
next_excerpt_controls_present: false,
|
||||
excerpt,
|
||||
});
|
||||
}
|
||||
Some(Block::FoldedBuffer { .. }) | Some(Block::Custom(_)) | None => {}
|
||||
}
|
||||
|
||||
// This is needed to iterate past None / FoldedBuffer / Custom blocks. For FoldedBuffer,
|
||||
// if scrolled slightly past the header of a folded block, the next block is needed for
|
||||
// the sticky header.
|
||||
cursor.next(&());
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
pub fn block_for_id(&self, block_id: BlockId) -> Option<Block> {
|
||||
let buffer = self.wrap_snapshot.buffer_snapshot();
|
||||
let wrap_point = match block_id {
|
||||
@@ -1754,13 +1694,6 @@ impl<'a> BlockChunks<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StickyHeaderExcerpt<'a> {
|
||||
pub excerpt: &'a ExcerptInfo,
|
||||
pub next_excerpt_controls_present: bool,
|
||||
// TODO az remove option
|
||||
pub next_buffer_row: Option<u32>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for BlockChunks<'a> {
|
||||
type Item = Chunk<'a>;
|
||||
|
||||
|
||||
@@ -992,14 +992,12 @@ pub(crate) struct FocusedBlock {
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
enum JumpData {
|
||||
MultiBufferRow(MultiBufferRow),
|
||||
MultiBufferPoint {
|
||||
excerpt_id: ExcerptId,
|
||||
position: Point,
|
||||
anchor: text::Anchor,
|
||||
line_offset_from_top: u32,
|
||||
},
|
||||
struct JumpData {
|
||||
excerpt_id: ExcerptId,
|
||||
position: Point,
|
||||
anchor: text::Anchor,
|
||||
path: Option<project::ProjectPath>,
|
||||
line_offset_from_top: u32,
|
||||
}
|
||||
|
||||
impl Editor {
|
||||
@@ -3515,7 +3513,7 @@ impl Editor {
|
||||
}
|
||||
}
|
||||
|
||||
fn visible_inlay_hints(&self, cx: &ViewContext<Editor>) -> Vec<Inlay> {
|
||||
fn visible_inlay_hints(&self, cx: &ViewContext<'_, Editor>) -> Vec<Inlay> {
|
||||
self.display_map
|
||||
.read(cx)
|
||||
.current_inlays()
|
||||
@@ -3832,11 +3830,8 @@ impl Editor {
|
||||
};
|
||||
|
||||
let buffer_handle = completions_menu.buffer;
|
||||
let completion = completions_menu
|
||||
.completions
|
||||
.borrow()
|
||||
.get(mat.candidate_id)?
|
||||
.clone();
|
||||
let completions = completions_menu.completions.borrow_mut();
|
||||
let completion = completions.get(mat.candidate_id)?;
|
||||
cx.stop_propagation();
|
||||
|
||||
let snippet;
|
||||
@@ -3980,11 +3975,9 @@ impl Editor {
|
||||
}
|
||||
|
||||
let provider = self.completion_provider.as_ref()?;
|
||||
drop(completion);
|
||||
let apply_edits = provider.apply_additional_edits_for_completion(
|
||||
buffer_handle,
|
||||
completions_menu.completions.clone(),
|
||||
mat.candidate_id,
|
||||
completion.clone(),
|
||||
true,
|
||||
cx,
|
||||
);
|
||||
@@ -5094,7 +5087,7 @@ impl Editor {
|
||||
}))
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "test-support", test))]
|
||||
#[cfg(feature = "test-support")]
|
||||
pub fn context_menu_visible(&self) -> bool {
|
||||
self.context_menu
|
||||
.borrow()
|
||||
@@ -5140,14 +5133,14 @@ impl Editor {
|
||||
fn render_context_menu_aside(
|
||||
&self,
|
||||
style: &EditorStyle,
|
||||
max_size: Size<Pixels>,
|
||||
max_height: Pixels,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
) -> Option<AnyElement> {
|
||||
self.context_menu.borrow().as_ref().and_then(|menu| {
|
||||
if menu.visible() {
|
||||
menu.render_aside(
|
||||
style,
|
||||
max_size,
|
||||
max_height,
|
||||
self.workspace.as_ref().map(|(w, _)| w.clone()),
|
||||
cx,
|
||||
)
|
||||
@@ -6011,7 +6004,7 @@ impl Editor {
|
||||
fn gather_revert_changes(
|
||||
&mut self,
|
||||
selections: &[Selection<Point>],
|
||||
cx: &mut ViewContext<Editor>,
|
||||
cx: &mut ViewContext<'_, Editor>,
|
||||
) -> HashMap<BufferId, Vec<(Range<text::Anchor>, Rope)>> {
|
||||
let mut revert_changes = HashMap::default();
|
||||
let snapshot = self.snapshot(cx);
|
||||
@@ -8938,7 +8931,7 @@ impl Editor {
|
||||
fn templates_with_tags(
|
||||
project: &Model<Project>,
|
||||
runnable: &mut Runnable,
|
||||
cx: &WindowContext,
|
||||
cx: &WindowContext<'_>,
|
||||
) -> Vec<(TaskSourceKind, TaskTemplate)> {
|
||||
let (inventory, worktree_id, file) = project.read_with(cx, |project, cx| {
|
||||
let (worktree_id, file) = project
|
||||
@@ -9250,7 +9243,7 @@ impl Editor {
|
||||
&mut self,
|
||||
snapshot: &EditorSnapshot,
|
||||
position: Point,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
cx: &mut ViewContext<'_, Editor>,
|
||||
) -> Option<MultiBufferDiffHunk> {
|
||||
for (ix, position) in [position, Point::zero()].into_iter().enumerate() {
|
||||
if let Some(hunk) = self.go_to_next_hunk_in_direction(
|
||||
@@ -9279,7 +9272,7 @@ impl Editor {
|
||||
&mut self,
|
||||
snapshot: &EditorSnapshot,
|
||||
position: Point,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
cx: &mut ViewContext<'_, Editor>,
|
||||
) -> Option<MultiBufferDiffHunk> {
|
||||
for (ix, position) in [position, snapshot.buffer_snapshot.max_point()]
|
||||
.into_iter()
|
||||
@@ -12460,46 +12453,28 @@ impl Editor {
|
||||
|
||||
let mut new_selections_by_buffer = HashMap::default();
|
||||
match &jump_data {
|
||||
Some(JumpData::MultiBufferPoint {
|
||||
excerpt_id,
|
||||
position,
|
||||
anchor,
|
||||
line_offset_from_top,
|
||||
}) => {
|
||||
Some(jump_data) => {
|
||||
let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
|
||||
if let Some(buffer) = multi_buffer_snapshot
|
||||
.buffer_id_for_excerpt(*excerpt_id)
|
||||
.buffer_id_for_excerpt(jump_data.excerpt_id)
|
||||
.and_then(|buffer_id| self.buffer.read(cx).buffer(buffer_id))
|
||||
{
|
||||
let buffer_snapshot = buffer.read(cx).snapshot();
|
||||
let jump_to_point = if buffer_snapshot.can_resolve(anchor) {
|
||||
language::ToPoint::to_point(anchor, &buffer_snapshot)
|
||||
let jump_to_point = if buffer_snapshot.can_resolve(&jump_data.anchor) {
|
||||
language::ToPoint::to_point(&jump_data.anchor, &buffer_snapshot)
|
||||
} else {
|
||||
buffer_snapshot.clip_point(*position, Bias::Left)
|
||||
buffer_snapshot.clip_point(jump_data.position, Bias::Left)
|
||||
};
|
||||
let jump_to_offset = buffer_snapshot.point_to_offset(jump_to_point);
|
||||
new_selections_by_buffer.insert(
|
||||
buffer,
|
||||
(
|
||||
vec![jump_to_offset..jump_to_offset],
|
||||
Some(*line_offset_from_top),
|
||||
Some(jump_data.line_offset_from_top),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Some(JumpData::MultiBufferRow(row)) => {
|
||||
let point = MultiBufferPoint::new(row.0, 0);
|
||||
if let Some((buffer, buffer_point, _)) =
|
||||
self.buffer.read(cx).point_to_buffer_point(point, cx)
|
||||
{
|
||||
let buffer_offset = buffer.read(cx).point_to_offset(buffer_point);
|
||||
new_selections_by_buffer
|
||||
.entry(buffer)
|
||||
.or_insert((Vec::new(), None))
|
||||
.0
|
||||
.push(buffer_offset..buffer_offset)
|
||||
}
|
||||
}
|
||||
None => {
|
||||
let selections = self.selections.all::<usize>(cx);
|
||||
let buffer = self.buffer.read(cx);
|
||||
@@ -13472,14 +13447,11 @@ pub trait CompletionProvider {
|
||||
|
||||
fn apply_additional_edits_for_completion(
|
||||
&self,
|
||||
_buffer: Model<Buffer>,
|
||||
_completions: Rc<RefCell<Box<[Completion]>>>,
|
||||
_completion_index: usize,
|
||||
_push_to_history: bool,
|
||||
_cx: &mut ViewContext<Editor>,
|
||||
) -> Task<Result<Option<language::Transaction>>> {
|
||||
Task::ready(Ok(None))
|
||||
}
|
||||
buffer: Model<Buffer>,
|
||||
completion: Completion,
|
||||
push_to_history: bool,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
) -> Task<Result<Option<language::Transaction>>>;
|
||||
|
||||
fn is_completion_trigger(
|
||||
&self,
|
||||
@@ -13638,7 +13610,6 @@ fn snippet_completions(
|
||||
Some(Completion {
|
||||
old_range: range,
|
||||
new_text: snippet.body.clone(),
|
||||
resolved: false,
|
||||
label: CodeLabel {
|
||||
text: matching_prefix.clone(),
|
||||
runs: vec![],
|
||||
@@ -13704,30 +13675,19 @@ impl CompletionProvider for Model<Project> {
|
||||
cx: &mut ViewContext<Editor>,
|
||||
) -> Task<Result<bool>> {
|
||||
self.update(cx, |project, cx| {
|
||||
project.lsp_store().update(cx, |lsp_store, cx| {
|
||||
lsp_store.resolve_completions(buffer, completion_indices, completions, cx)
|
||||
})
|
||||
project.resolve_completions(buffer, completion_indices, completions, cx)
|
||||
})
|
||||
}
|
||||
|
||||
fn apply_additional_edits_for_completion(
|
||||
&self,
|
||||
buffer: Model<Buffer>,
|
||||
completions: Rc<RefCell<Box<[Completion]>>>,
|
||||
completion_index: usize,
|
||||
completion: Completion,
|
||||
push_to_history: bool,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
) -> Task<Result<Option<language::Transaction>>> {
|
||||
self.update(cx, |project, cx| {
|
||||
project.lsp_store().update(cx, |lsp_store, cx| {
|
||||
lsp_store.apply_additional_edits_for_completion(
|
||||
buffer,
|
||||
completions,
|
||||
completion_index,
|
||||
push_to_history,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
project.apply_additional_edits_for_completion(buffer, completion, push_to_history, cx)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -13862,7 +13822,7 @@ impl SemanticsProvider for Model<Project> {
|
||||
fn inlay_hint_settings(
|
||||
location: Anchor,
|
||||
snapshot: &MultiBufferSnapshot,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
cx: &mut ViewContext<'_, Editor>,
|
||||
) -> InlayHintSettings {
|
||||
let file = snapshot.file_at(location);
|
||||
let language = snapshot.language_at(location).map(|l| l.name());
|
||||
|
||||
@@ -8402,6 +8402,7 @@ async fn test_completion(cx: &mut gpui::TestAppContext) {
|
||||
additional edit
|
||||
"});
|
||||
|
||||
handle_resolve_completion_request(&mut cx, None).await;
|
||||
apply_additional_edits.await.unwrap();
|
||||
|
||||
update_test_language_settings(&mut cx, |settings| {
|
||||
@@ -10697,14 +10698,10 @@ async fn test_completions_resolve_updates_labels_if_filter_text_matches(
|
||||
..lsp::CompletionItem::default()
|
||||
};
|
||||
|
||||
let item1 = item1.clone();
|
||||
cx.handle_request::<lsp::request::Completion, _, _>({
|
||||
cx.handle_request::<lsp::request::Completion, _, _>(move |_, _, _| {
|
||||
let item1 = item1.clone();
|
||||
move |_, _, _| {
|
||||
let item1 = item1.clone();
|
||||
let item2 = item2.clone();
|
||||
async move { Ok(Some(lsp::CompletionResponse::Array(vec![item1, item2]))) }
|
||||
}
|
||||
let item2 = item2.clone();
|
||||
async move { Ok(Some(lsp::CompletionResponse::Array(vec![item1, item2]))) }
|
||||
})
|
||||
.next()
|
||||
.await;
|
||||
@@ -10731,41 +10728,43 @@ async fn test_completions_resolve_updates_labels_if_filter_text_matches(
|
||||
}
|
||||
});
|
||||
|
||||
cx.handle_request::<lsp::request::ResolveCompletionItem, _, _>({
|
||||
let item1 = item1.clone();
|
||||
move |_, item_to_resolve, _| {
|
||||
let item1 = item1.clone();
|
||||
async move {
|
||||
if item1 == item_to_resolve {
|
||||
Ok(lsp::CompletionItem {
|
||||
label: "method id()".to_string(),
|
||||
filter_text: Some("id".to_string()),
|
||||
detail: Some("Now resolved!".to_string()),
|
||||
documentation: Some(lsp::Documentation::String("Docs".to_string())),
|
||||
text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
|
||||
range: lsp::Range::new(
|
||||
lsp::Position::new(0, 22),
|
||||
lsp::Position::new(0, 22),
|
||||
),
|
||||
new_text: ".id".to_string(),
|
||||
})),
|
||||
..lsp::CompletionItem::default()
|
||||
})
|
||||
} else {
|
||||
Ok(item_to_resolve)
|
||||
}
|
||||
}
|
||||
}
|
||||
cx.handle_request::<lsp::request::ResolveCompletionItem, _, _>(move |_, _, _| async move {
|
||||
Ok(lsp::CompletionItem {
|
||||
label: "method id()".to_string(),
|
||||
filter_text: Some("id".to_string()),
|
||||
detail: Some("Now resolved!".to_string()),
|
||||
documentation: Some(lsp::Documentation::String("Docs".to_string())),
|
||||
text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
|
||||
range: lsp::Range::new(lsp::Position::new(0, 22), lsp::Position::new(0, 22)),
|
||||
new_text: ".id".to_string(),
|
||||
})),
|
||||
..lsp::CompletionItem::default()
|
||||
})
|
||||
})
|
||||
.next()
|
||||
.await
|
||||
.unwrap();
|
||||
.await;
|
||||
cx.run_until_parked();
|
||||
|
||||
cx.update_editor(|editor, cx| {
|
||||
editor.context_menu_next(&Default::default(), cx);
|
||||
});
|
||||
|
||||
cx.handle_request::<lsp::request::ResolveCompletionItem, _, _>(move |_, _, _| async move {
|
||||
Ok(lsp::CompletionItem {
|
||||
label: "invalid changed label".to_string(),
|
||||
detail: Some("Now resolved!".to_string()),
|
||||
documentation: Some(lsp::Documentation::String("Docs".to_string())),
|
||||
text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
|
||||
range: lsp::Range::new(lsp::Position::new(0, 22), lsp::Position::new(0, 22)),
|
||||
new_text: ".id".to_string(),
|
||||
})),
|
||||
..lsp::CompletionItem::default()
|
||||
})
|
||||
})
|
||||
.next()
|
||||
.await;
|
||||
cx.run_until_parked();
|
||||
|
||||
cx.update_editor(|editor, _| {
|
||||
let context_menu = editor.context_menu.borrow_mut();
|
||||
let context_menu = context_menu
|
||||
@@ -10788,172 +10787,6 @@ async fn test_completions_resolve_updates_labels_if_filter_text_matches(
|
||||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_completions_resolve_happens_once(cx: &mut gpui::TestAppContext) {
|
||||
init_test(cx, |_| {});
|
||||
|
||||
let mut cx = EditorLspTestContext::new_rust(
|
||||
lsp::ServerCapabilities {
|
||||
completion_provider: Some(lsp::CompletionOptions {
|
||||
trigger_characters: Some(vec![".".to_string()]),
|
||||
resolve_provider: Some(true),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
cx,
|
||||
)
|
||||
.await;
|
||||
|
||||
cx.set_state(indoc! {"fn main() { let a = 2ˇ; }"});
|
||||
cx.simulate_keystroke(".");
|
||||
|
||||
let unresolved_item_1 = lsp::CompletionItem {
|
||||
label: "id".to_string(),
|
||||
filter_text: Some("id".to_string()),
|
||||
detail: None,
|
||||
documentation: None,
|
||||
text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
|
||||
range: lsp::Range::new(lsp::Position::new(0, 22), lsp::Position::new(0, 22)),
|
||||
new_text: ".id".to_string(),
|
||||
})),
|
||||
..lsp::CompletionItem::default()
|
||||
};
|
||||
let resolved_item_1 = lsp::CompletionItem {
|
||||
additional_text_edits: Some(vec![lsp::TextEdit {
|
||||
range: lsp::Range::new(lsp::Position::new(0, 20), lsp::Position::new(0, 22)),
|
||||
new_text: "!!".to_string(),
|
||||
}]),
|
||||
..unresolved_item_1.clone()
|
||||
};
|
||||
let unresolved_item_2 = lsp::CompletionItem {
|
||||
label: "other".to_string(),
|
||||
filter_text: Some("other".to_string()),
|
||||
detail: None,
|
||||
documentation: None,
|
||||
text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
|
||||
range: lsp::Range::new(lsp::Position::new(0, 22), lsp::Position::new(0, 22)),
|
||||
new_text: ".other".to_string(),
|
||||
})),
|
||||
..lsp::CompletionItem::default()
|
||||
};
|
||||
let resolved_item_2 = lsp::CompletionItem {
|
||||
additional_text_edits: Some(vec![lsp::TextEdit {
|
||||
range: lsp::Range::new(lsp::Position::new(0, 20), lsp::Position::new(0, 22)),
|
||||
new_text: "??".to_string(),
|
||||
}]),
|
||||
..unresolved_item_2.clone()
|
||||
};
|
||||
|
||||
let resolve_requests_1 = Arc::new(AtomicUsize::new(0));
|
||||
let resolve_requests_2 = Arc::new(AtomicUsize::new(0));
|
||||
cx.lsp
|
||||
.server
|
||||
.on_request::<lsp::request::ResolveCompletionItem, _, _>({
|
||||
let unresolved_item_1 = unresolved_item_1.clone();
|
||||
let resolved_item_1 = resolved_item_1.clone();
|
||||
let unresolved_item_2 = unresolved_item_2.clone();
|
||||
let resolved_item_2 = resolved_item_2.clone();
|
||||
let resolve_requests_1 = resolve_requests_1.clone();
|
||||
let resolve_requests_2 = resolve_requests_2.clone();
|
||||
move |unresolved_request, _| {
|
||||
let unresolved_item_1 = unresolved_item_1.clone();
|
||||
let resolved_item_1 = resolved_item_1.clone();
|
||||
let unresolved_item_2 = unresolved_item_2.clone();
|
||||
let resolved_item_2 = resolved_item_2.clone();
|
||||
let resolve_requests_1 = resolve_requests_1.clone();
|
||||
let resolve_requests_2 = resolve_requests_2.clone();
|
||||
async move {
|
||||
if unresolved_request == unresolved_item_1 {
|
||||
resolve_requests_1.fetch_add(1, atomic::Ordering::Release);
|
||||
Ok(resolved_item_1.clone())
|
||||
} else if unresolved_request == unresolved_item_2 {
|
||||
resolve_requests_2.fetch_add(1, atomic::Ordering::Release);
|
||||
Ok(resolved_item_2.clone())
|
||||
} else {
|
||||
panic!("Unexpected completion item {unresolved_request:?}")
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
|
||||
cx.handle_request::<lsp::request::Completion, _, _>(move |_, _, _| {
|
||||
let unresolved_item_1 = unresolved_item_1.clone();
|
||||
let unresolved_item_2 = unresolved_item_2.clone();
|
||||
async move {
|
||||
Ok(Some(lsp::CompletionResponse::Array(vec![
|
||||
unresolved_item_1,
|
||||
unresolved_item_2,
|
||||
])))
|
||||
}
|
||||
})
|
||||
.next()
|
||||
.await;
|
||||
|
||||
cx.condition(|editor, _| editor.context_menu_visible())
|
||||
.await;
|
||||
cx.update_editor(|editor, _| {
|
||||
let context_menu = editor.context_menu.borrow_mut();
|
||||
let context_menu = context_menu
|
||||
.as_ref()
|
||||
.expect("Should have the context menu deployed");
|
||||
match context_menu {
|
||||
CodeContextMenu::Completions(completions_menu) => {
|
||||
let completions = completions_menu.completions.borrow_mut();
|
||||
assert_eq!(
|
||||
completions
|
||||
.iter()
|
||||
.map(|completion| &completion.label.text)
|
||||
.collect::<Vec<_>>(),
|
||||
vec!["id", "other"]
|
||||
)
|
||||
}
|
||||
CodeContextMenu::CodeActions(_) => panic!("Should show the completions menu"),
|
||||
}
|
||||
});
|
||||
cx.run_until_parked();
|
||||
|
||||
cx.update_editor(|editor, cx| {
|
||||
editor.context_menu_next(&ContextMenuNext, cx);
|
||||
});
|
||||
cx.run_until_parked();
|
||||
cx.update_editor(|editor, cx| {
|
||||
editor.context_menu_prev(&ContextMenuPrev, cx);
|
||||
});
|
||||
cx.run_until_parked();
|
||||
cx.update_editor(|editor, cx| {
|
||||
editor.context_menu_next(&ContextMenuNext, cx);
|
||||
});
|
||||
cx.run_until_parked();
|
||||
cx.update_editor(|editor, cx| {
|
||||
editor
|
||||
.compose_completion(&ComposeCompletion::default(), cx)
|
||||
.expect("No task returned")
|
||||
})
|
||||
.await
|
||||
.expect("Completion failed");
|
||||
cx.run_until_parked();
|
||||
|
||||
cx.update_editor(|editor, cx| {
|
||||
assert_eq!(
|
||||
resolve_requests_1.load(atomic::Ordering::Acquire),
|
||||
1,
|
||||
"Should always resolve once despite multiple selections"
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_requests_2.load(atomic::Ordering::Acquire),
|
||||
1,
|
||||
"Should always resolve once after multiple selections and applying the completion"
|
||||
);
|
||||
assert_eq!(
|
||||
editor.text(cx),
|
||||
"fn main() { let a = ??.other; }",
|
||||
"Should use resolved data when applying the completion"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_completions_default_resolve_data_handling(cx: &mut gpui::TestAppContext) {
|
||||
init_test(cx, |_| {});
|
||||
@@ -11117,10 +10950,15 @@ async fn test_completions_default_resolve_data_handling(cx: &mut gpui::TestAppCo
|
||||
// Completions that have already been resolved are skipped.
|
||||
assert_eq!(
|
||||
*resolved_items.lock(),
|
||||
items_out[items_out.len() - 16..items_out.len() - 4]
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect::<Vec<lsp::CompletionItem>>()
|
||||
[
|
||||
// Selected item is always resolved even if it was resolved before.
|
||||
&items_out[items_out.len() - 1..items_out.len()],
|
||||
&items_out[items_out.len() - 16..items_out.len() - 4]
|
||||
]
|
||||
.concat()
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect::<Vec<lsp::CompletionItem>>()
|
||||
);
|
||||
resolved_items.lock().clear();
|
||||
}
|
||||
@@ -11260,7 +11098,7 @@ async fn test_document_format_with_prettier(cx: &mut gpui::TestAppContext) {
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
Some(tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into()),
|
||||
Some(tree_sitter_rust::LANGUAGE.into()),
|
||||
)));
|
||||
update_test_language_settings(cx, |settings| {
|
||||
settings.defaults.prettier = Some(PrettierSettings {
|
||||
@@ -14732,62 +14570,6 @@ fn test_inline_completion_text_with_deletions(cx: &mut TestAppContext) {
|
||||
}
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_rename_with_duplicate_edits(cx: &mut gpui::TestAppContext) {
|
||||
init_test(cx, |_| {});
|
||||
let mut cx = EditorLspTestContext::new_rust(lsp::ServerCapabilities::default(), cx).await;
|
||||
|
||||
cx.set_state(indoc! {"
|
||||
struct Fˇoo {}
|
||||
"});
|
||||
|
||||
cx.update_editor(|editor, cx| {
|
||||
let highlight_range = Point::new(0, 7)..Point::new(0, 10);
|
||||
let highlight_range = highlight_range.to_anchors(&editor.buffer().read(cx).snapshot(cx));
|
||||
editor.highlight_background::<DocumentHighlightRead>(
|
||||
&[highlight_range],
|
||||
|c| c.editor_document_highlight_read_background,
|
||||
cx,
|
||||
);
|
||||
});
|
||||
|
||||
cx.update_editor(|e, cx| e.rename(&Rename, cx))
|
||||
.expect("Rename was not started")
|
||||
.await
|
||||
.expect("Rename failed");
|
||||
let mut rename_handler =
|
||||
cx.handle_request::<lsp::request::Rename, _, _>(move |url, _, _| async move {
|
||||
let edit = lsp::TextEdit {
|
||||
range: lsp::Range {
|
||||
start: lsp::Position {
|
||||
line: 0,
|
||||
character: 7,
|
||||
},
|
||||
end: lsp::Position {
|
||||
line: 0,
|
||||
character: 10,
|
||||
},
|
||||
},
|
||||
new_text: "FooRenamed".to_string(),
|
||||
};
|
||||
Ok(Some(lsp::WorkspaceEdit::new(
|
||||
// Specify the same edit twice
|
||||
std::collections::HashMap::from_iter(Some((url, vec![edit.clone(), edit]))),
|
||||
)))
|
||||
});
|
||||
cx.update_editor(|e, cx| e.confirm_rename(&ConfirmRename, cx))
|
||||
.expect("Confirm rename was not started")
|
||||
.await
|
||||
.expect("Confirm rename failed");
|
||||
rename_handler.next().await.unwrap();
|
||||
cx.run_until_parked();
|
||||
|
||||
// Despite two edits, only one is actually applied as those are identical
|
||||
cx.assert_editor_state(indoc! {"
|
||||
struct FooRenamedˇ {}
|
||||
"});
|
||||
}
|
||||
|
||||
fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
|
||||
let point = DisplayPoint::new(DisplayRow(row as u32), column as u32);
|
||||
point..point
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -266,7 +266,7 @@ pub fn update_inlay_link_and_hover_points(
|
||||
editor: &mut Editor,
|
||||
secondary_held: bool,
|
||||
shift_held: bool,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
cx: &mut ViewContext<'_, Editor>,
|
||||
) {
|
||||
let hovered_offset = if point_for_position.column_overshoot_after_line_end == 0 {
|
||||
Some(snapshot.display_point_to_inlay_offset(point_for_position.exact_unclipped, Bias::Left))
|
||||
|
||||
@@ -365,7 +365,7 @@ impl Editor {
|
||||
&mut self,
|
||||
diff_base_buffer: Option<Model<Buffer>>,
|
||||
hunk: &HoveredHunk,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
cx: &mut ViewContext<'_, Editor>,
|
||||
) -> Option<()> {
|
||||
let buffer = self.buffer.clone();
|
||||
let multi_buffer_snapshot = buffer.read(cx).snapshot(cx);
|
||||
@@ -454,7 +454,7 @@ impl Editor {
|
||||
fn apply_diff_hunks_in_range(
|
||||
&mut self,
|
||||
range: Range<Anchor>,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
cx: &mut ViewContext<'_, Editor>,
|
||||
) -> Option<()> {
|
||||
let (buffer, range, _) = self
|
||||
.buffer
|
||||
@@ -530,7 +530,7 @@ impl Editor {
|
||||
fn hunk_header_block(
|
||||
&self,
|
||||
hunk: &HoveredHunk,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
cx: &mut ViewContext<'_, Editor>,
|
||||
) -> BlockProperties<Anchor> {
|
||||
let is_branch_buffer = self
|
||||
.buffer
|
||||
@@ -801,7 +801,7 @@ impl Editor {
|
||||
hunk: &HoveredHunk,
|
||||
diff_base_buffer: Model<Buffer>,
|
||||
deleted_text_height: u32,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
cx: &mut ViewContext<'_, Editor>,
|
||||
) -> BlockProperties<Anchor> {
|
||||
let gutter_color = match hunk.status {
|
||||
DiffHunkStatus::Added => unreachable!(),
|
||||
@@ -864,7 +864,7 @@ impl Editor {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn clear_expanded_diff_hunks(&mut self, cx: &mut ViewContext<Editor>) -> bool {
|
||||
pub(super) fn clear_expanded_diff_hunks(&mut self, cx: &mut ViewContext<'_, Editor>) -> bool {
|
||||
if self.diff_map.expand_all {
|
||||
return false;
|
||||
}
|
||||
@@ -887,7 +887,7 @@ impl Editor {
|
||||
pub(super) fn sync_expanded_diff_hunks(
|
||||
diff_map: &mut DiffMap,
|
||||
buffer_id: BufferId,
|
||||
cx: &mut ViewContext<Self>,
|
||||
cx: &mut ViewContext<'_, Self>,
|
||||
) {
|
||||
let diff_base_state = diff_map.diff_bases.get_mut(&buffer_id);
|
||||
let mut diff_base_buffer = None;
|
||||
@@ -1134,7 +1134,7 @@ fn editor_with_deleted_text(
|
||||
diff_base_buffer: Model<Buffer>,
|
||||
deleted_color: Hsla,
|
||||
hunk: &HoveredHunk,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
cx: &mut ViewContext<'_, Editor>,
|
||||
) -> (u32, View<Editor>) {
|
||||
let parent_editor = cx.view().downgrade();
|
||||
let editor = cx.new_view(|cx| {
|
||||
|
||||
@@ -579,7 +579,7 @@ impl InlayHintCache {
|
||||
buffer_id: BufferId,
|
||||
excerpt_id: ExcerptId,
|
||||
id: InlayId,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
cx: &mut ViewContext<'_, Editor>,
|
||||
) {
|
||||
if let Some(excerpt_hints) = self.hints.get(&excerpt_id) {
|
||||
let mut guard = excerpt_hints.write();
|
||||
@@ -640,7 +640,7 @@ fn spawn_new_update_tasks(
|
||||
excerpts_to_query: HashMap<ExcerptId, (Model<Buffer>, Global, Range<usize>)>,
|
||||
invalidate: InvalidationStrategy,
|
||||
update_cache_version: usize,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
cx: &mut ViewContext<'_, Editor>,
|
||||
) {
|
||||
for (excerpt_id, (excerpt_buffer, new_task_buffer_version, excerpt_visible_range)) in
|
||||
excerpts_to_query
|
||||
@@ -797,7 +797,7 @@ fn new_update_task(
|
||||
query: ExcerptQuery,
|
||||
query_ranges: QueryRanges,
|
||||
excerpt_buffer: Model<Buffer>,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
cx: &mut ViewContext<'_, Editor>,
|
||||
) -> Task<()> {
|
||||
cx.spawn(move |editor, mut cx| async move {
|
||||
let visible_range_update_results = future::join_all(
|
||||
@@ -1129,7 +1129,7 @@ fn apply_hint_update(
|
||||
invalidate: bool,
|
||||
buffer_snapshot: BufferSnapshot,
|
||||
multi_buffer_snapshot: MultiBufferSnapshot,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
cx: &mut ViewContext<'_, Editor>,
|
||||
) {
|
||||
let cached_excerpt_hints = editor
|
||||
.inlay_hint_cache
|
||||
@@ -3434,7 +3434,7 @@ pub mod tests {
|
||||
labels
|
||||
}
|
||||
|
||||
pub fn visible_hint_labels(editor: &Editor, cx: &ViewContext<Editor>) -> Vec<String> {
|
||||
pub fn visible_hint_labels(editor: &Editor, cx: &ViewContext<'_, Editor>) -> Vec<String> {
|
||||
let mut hints = editor
|
||||
.visible_inlay_hints(cx)
|
||||
.into_iter()
|
||||
|
||||
@@ -288,7 +288,7 @@ impl EventEmitter<EditorEvent> for ProposedChangesEditor {}
|
||||
impl Item for ProposedChangesEditor {
|
||||
type Event = EditorEvent;
|
||||
|
||||
fn tab_icon(&self, _cx: &WindowContext) -> Option<Icon> {
|
||||
fn tab_icon(&self, _cx: &ui::WindowContext) -> Option<Icon> {
|
||||
Some(Icon::new(IconName::Diff))
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ pub fn apply_related_actions(editor: &View<Editor>, cx: &mut WindowContext) {
|
||||
pub fn expand_macro_recursively(
|
||||
editor: &mut Editor,
|
||||
_: &ExpandMacroRecursively,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
cx: &mut ViewContext<'_, Editor>,
|
||||
) {
|
||||
if editor.selections.count() == 0 {
|
||||
return;
|
||||
@@ -98,7 +98,7 @@ pub fn expand_macro_recursively(
|
||||
.detach_and_log_err(cx);
|
||||
}
|
||||
|
||||
pub fn open_docs(editor: &mut Editor, _: &OpenDocs, cx: &mut ViewContext<Editor>) {
|
||||
pub fn open_docs(editor: &mut Editor, _: &OpenDocs, cx: &mut ViewContext<'_, Editor>) {
|
||||
if editor.selections.count() == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::{
|
||||
ScrollAnchor, ScrollCursorBottom, ScrollCursorCenter, ScrollCursorCenterTopBottom,
|
||||
ScrollCursorTop, SCROLL_CENTER_TOP_BOTTOM_DEBOUNCE_TIMEOUT,
|
||||
};
|
||||
use gpui::{AsyncWindowContext, Point, ViewContext};
|
||||
use gpui::{Point, ViewContext};
|
||||
|
||||
impl Editor {
|
||||
pub fn next_screen(&mut self, _: &NextScreen, cx: &mut ViewContext<Editor>) {
|
||||
@@ -75,7 +75,7 @@ impl Editor {
|
||||
|
||||
self.next_scroll_position = self.next_scroll_position.next();
|
||||
self._scroll_cursor_center_top_bottom_task =
|
||||
cx.spawn(|editor, mut cx: AsyncWindowContext| async move {
|
||||
cx.spawn(|editor, mut cx: gpui::AsyncWindowContext| async move {
|
||||
cx.background_executor()
|
||||
.timer(SCROLL_CENTER_TOP_BOTTOM_DEBOUNCE_TIMEOUT)
|
||||
.await;
|
||||
|
||||
@@ -8,7 +8,7 @@ use workspace::Workspace;
|
||||
|
||||
fn task_context_with_editor(
|
||||
editor: &mut Editor,
|
||||
cx: &mut WindowContext,
|
||||
cx: &mut WindowContext<'_>,
|
||||
) -> AsyncTask<Option<TaskContext>> {
|
||||
let Some(project) = editor.project.clone() else {
|
||||
return AsyncTask::ready(None);
|
||||
@@ -74,7 +74,7 @@ fn task_context_with_editor(
|
||||
})
|
||||
}
|
||||
|
||||
pub fn task_context(workspace: &Workspace, cx: &mut WindowContext) -> AsyncTask<TaskContext> {
|
||||
pub fn task_context(workspace: &Workspace, cx: &mut WindowContext<'_>) -> AsyncTask<TaskContext> {
|
||||
let Some(editor) = workspace
|
||||
.active_item(cx)
|
||||
.and_then(|item| item.act_as::<Editor>(cx))
|
||||
|
||||
@@ -843,7 +843,7 @@ impl ExtensionsPage {
|
||||
}
|
||||
}
|
||||
|
||||
fn fetch_extensions_debounced(&mut self, cx: &mut ViewContext<ExtensionsPage>) {
|
||||
fn fetch_extensions_debounced(&mut self, cx: &mut ViewContext<'_, ExtensionsPage>) {
|
||||
self.extension_fetch_task = Some(cx.spawn(|this, mut cx| async move {
|
||||
let search = this
|
||||
.update(&mut cx, |this, cx| this.search_query(cx))
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use client::telemetry;
|
||||
use gpui::{Task, WindowContext};
|
||||
use gpui::Task;
|
||||
use human_bytes::human_bytes;
|
||||
use release_channel::{AppCommitSha, AppVersion, ReleaseChannel};
|
||||
use serde::Serialize;
|
||||
use std::{env, fmt::Display};
|
||||
use sysinfo::{MemoryRefreshKind, RefreshKind, System};
|
||||
use ui::WindowContext;
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
pub struct SystemSpecs {
|
||||
|
||||
@@ -884,7 +884,7 @@ impl FileFinderDelegate {
|
||||
fn lookup_absolute_path(
|
||||
&self,
|
||||
query: FileSearchQuery,
|
||||
cx: &mut ViewContext<Picker<Self>>,
|
||||
cx: &mut ViewContext<'_, Picker<Self>>,
|
||||
) -> Task<()> {
|
||||
cx.spawn(|picker, mut cx| async move {
|
||||
let Some(project) = picker
|
||||
|
||||
@@ -10,8 +10,6 @@ use git::GitHostingProviderRegistry;
|
||||
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
|
||||
use ashpd::desktop::trash;
|
||||
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
|
||||
use collections::BTreeSet;
|
||||
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
|
||||
use smol::process::Command;
|
||||
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
|
||||
use std::fs::File;
|
||||
@@ -122,17 +120,6 @@ pub trait Fs: Send + Sync {
|
||||
path: &Path,
|
||||
) -> Result<Pin<Box<dyn Send + Stream<Item = Result<PathBuf>>>>>;
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
|
||||
async fn watch(
|
||||
&self,
|
||||
path: &Path,
|
||||
latency: Duration,
|
||||
) -> (
|
||||
Pin<Box<dyn Send + Stream<Item = BTreeSet<PathEvent>>>>,
|
||||
Arc<dyn Watcher>,
|
||||
);
|
||||
|
||||
#[cfg(not(any(target_os = "linux", target_os = "freebsd")))]
|
||||
async fn watch(
|
||||
&self,
|
||||
path: &Path,
|
||||
@@ -714,14 +701,13 @@ impl Fs for RealFs {
|
||||
path: &Path,
|
||||
latency: Duration,
|
||||
) -> (
|
||||
Pin<Box<dyn Send + Stream<Item = BTreeSet<PathEvent>>>>,
|
||||
Pin<Box<dyn Send + Stream<Item = Vec<PathEvent>>>>,
|
||||
Arc<dyn Watcher>,
|
||||
) {
|
||||
use collections::BTreeSet;
|
||||
use parking_lot::Mutex;
|
||||
|
||||
let (tx, rx) = smol::channel::unbounded();
|
||||
let pending_paths: Arc<Mutex<BTreeSet<PathEvent>>> = Default::default();
|
||||
let pending_paths: Arc<Mutex<Vec<PathEvent>>> = Default::default();
|
||||
let watcher = Arc::new(linux_watcher::LinuxWatcher::new(tx, pending_paths.clone()));
|
||||
|
||||
if watcher.add(path).is_err() {
|
||||
@@ -1952,7 +1938,6 @@ impl Fs for FakeFs {
|
||||
Ok(Box::pin(futures::stream::iter(paths)))
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "linux", target_os = "freebsd")))]
|
||||
async fn watch(
|
||||
&self,
|
||||
path: &Path,
|
||||
@@ -1981,38 +1966,6 @@ impl Fs for FakeFs {
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
|
||||
async fn watch(
|
||||
&self,
|
||||
path: &Path,
|
||||
_: Duration,
|
||||
) -> (
|
||||
Pin<Box<dyn Send + Stream<Item = BTreeSet<PathEvent>>>>,
|
||||
Arc<dyn Watcher>,
|
||||
) {
|
||||
self.simulate_random_delay().await;
|
||||
let (tx, rx) = smol::channel::unbounded();
|
||||
self.state.lock().event_txs.push(tx);
|
||||
let path = path.to_path_buf();
|
||||
let executor = self.executor.clone();
|
||||
(
|
||||
Box::pin(
|
||||
futures::StreamExt::filter(rx, move |events| {
|
||||
let result = events
|
||||
.iter()
|
||||
.any(|evt_path| evt_path.path.starts_with(&path));
|
||||
let executor = executor.clone();
|
||||
async move {
|
||||
executor.simulate_random_delay().await;
|
||||
result
|
||||
}
|
||||
})
|
||||
.map(|events| BTreeSet::from_iter(events.into_iter())),
|
||||
),
|
||||
Arc::new(FakeWatcher {}),
|
||||
)
|
||||
}
|
||||
|
||||
fn open_repo(&self, abs_dot_git: &Path) -> Option<Arc<dyn GitRepository>> {
|
||||
let state = self.state.lock();
|
||||
let entry = state.read_path(abs_dot_git).unwrap();
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use collections::BTreeSet;
|
||||
use notify::EventKind;
|
||||
use parking_lot::Mutex;
|
||||
use std::sync::{Arc, OnceLock};
|
||||
@@ -8,13 +7,13 @@ use crate::{PathEvent, PathEventKind, Watcher};
|
||||
|
||||
pub struct LinuxWatcher {
|
||||
tx: smol::channel::Sender<()>,
|
||||
pending_path_events: Arc<Mutex<BTreeSet<PathEvent>>>,
|
||||
pending_path_events: Arc<Mutex<Vec<PathEvent>>>,
|
||||
}
|
||||
|
||||
impl LinuxWatcher {
|
||||
pub fn new(
|
||||
tx: smol::channel::Sender<()>,
|
||||
pending_path_events: Arc<Mutex<BTreeSet<PathEvent>>>,
|
||||
pending_path_events: Arc<Mutex<Vec<PathEvent>>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
tx,
|
||||
@@ -41,7 +40,7 @@ impl Watcher for LinuxWatcher {
|
||||
EventKind::Remove(_) => Some(PathEventKind::Removed),
|
||||
_ => None,
|
||||
};
|
||||
let path_events = event
|
||||
let mut path_events = event
|
||||
.paths
|
||||
.iter()
|
||||
.filter_map(|event_path| {
|
||||
@@ -53,12 +52,17 @@ impl Watcher for LinuxWatcher {
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if !path_events.is_empty() {
|
||||
path_events.sort();
|
||||
let mut pending_paths = pending_paths.lock();
|
||||
let was_empty = pending_paths.is_empty();
|
||||
pending_paths.extend(path_events);
|
||||
if was_empty {
|
||||
if pending_paths.is_empty() {
|
||||
tx.try_send(()).ok();
|
||||
}
|
||||
util::extend_sorted(
|
||||
&mut *pending_paths,
|
||||
path_events,
|
||||
usize::MAX,
|
||||
|a, b| a.path.cmp(&b.path),
|
||||
);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ pub struct Matcher<'a> {
|
||||
lowercase_query: &'a [char],
|
||||
query_char_bag: CharBag,
|
||||
smart_case: bool,
|
||||
max_results: usize,
|
||||
min_score: f64,
|
||||
match_positions: Vec<usize>,
|
||||
last_positions: Vec<usize>,
|
||||
@@ -21,6 +22,11 @@ pub struct Matcher<'a> {
|
||||
best_position_matrix: Vec<usize>,
|
||||
}
|
||||
|
||||
pub trait Match: Ord {
|
||||
fn score(&self) -> f64;
|
||||
fn set_positions(&mut self, positions: Vec<usize>);
|
||||
}
|
||||
|
||||
pub trait MatchCandidate {
|
||||
fn has_chars(&self, bag: CharBag) -> bool;
|
||||
fn to_string(&self) -> Cow<'_, str>;
|
||||
@@ -32,6 +38,7 @@ impl<'a> Matcher<'a> {
|
||||
lowercase_query: &'a [char],
|
||||
query_char_bag: CharBag,
|
||||
smart_case: bool,
|
||||
max_results: usize,
|
||||
) -> Self {
|
||||
Self {
|
||||
query,
|
||||
@@ -43,11 +50,10 @@ impl<'a> Matcher<'a> {
|
||||
score_matrix: Vec::new(),
|
||||
best_position_matrix: Vec::new(),
|
||||
smart_case,
|
||||
max_results,
|
||||
}
|
||||
}
|
||||
|
||||
/// Filter and score fuzzy match candidates. Results are returned unsorted, in the same order as
|
||||
/// the input candidates.
|
||||
pub fn match_candidates<C: MatchCandidate, R, F>(
|
||||
&mut self,
|
||||
prefix: &[char],
|
||||
@@ -57,7 +63,8 @@ impl<'a> Matcher<'a> {
|
||||
cancel_flag: &AtomicBool,
|
||||
build_match: F,
|
||||
) where
|
||||
F: Fn(&C, f64, &Vec<usize>) -> R,
|
||||
R: Match,
|
||||
F: Fn(&C, f64) -> R,
|
||||
{
|
||||
let mut candidate_chars = Vec::new();
|
||||
let mut lowercase_candidate_chars = Vec::new();
|
||||
@@ -96,7 +103,20 @@ impl<'a> Matcher<'a> {
|
||||
);
|
||||
|
||||
if score > 0.0 {
|
||||
results.push(build_match(&candidate, score, &self.match_positions));
|
||||
let mut mat = build_match(&candidate, score);
|
||||
if let Err(i) = results.binary_search_by(|m| mat.cmp(m)) {
|
||||
if results.len() < self.max_results {
|
||||
mat.set_positions(self.match_positions.clone());
|
||||
results.insert(i, mat);
|
||||
} else if i < results.len() {
|
||||
results.pop();
|
||||
mat.set_positions(self.match_positions.clone());
|
||||
results.insert(i, mat);
|
||||
}
|
||||
if results.len() == self.max_results {
|
||||
self.min_score = results.last().unwrap().score();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -305,18 +325,18 @@ mod tests {
|
||||
#[test]
|
||||
fn test_get_last_positions() {
|
||||
let mut query: &[char] = &['d', 'c'];
|
||||
let mut matcher = Matcher::new(query, query, query.into(), false);
|
||||
let mut matcher = Matcher::new(query, query, query.into(), false, 10);
|
||||
let result = matcher.find_last_positions(&['a', 'b', 'c'], &['b', 'd', 'e', 'f']);
|
||||
assert!(!result);
|
||||
|
||||
query = &['c', 'd'];
|
||||
let mut matcher = Matcher::new(query, query, query.into(), false);
|
||||
let mut matcher = Matcher::new(query, query, query.into(), false, 10);
|
||||
let result = matcher.find_last_positions(&['a', 'b', 'c'], &['b', 'd', 'e', 'f']);
|
||||
assert!(result);
|
||||
assert_eq!(matcher.last_positions, vec![2, 4]);
|
||||
|
||||
query = &['z', '/', 'z', 'f'];
|
||||
let mut matcher = Matcher::new(query, query, query.into(), false);
|
||||
let mut matcher = Matcher::new(query, query, query.into(), false, 10);
|
||||
let result = matcher.find_last_positions(&['z', 'e', 'd', '/'], &['z', 'e', 'd', '/', 'f']);
|
||||
assert!(result);
|
||||
assert_eq!(matcher.last_positions, vec![0, 3, 4, 8]);
|
||||
@@ -431,7 +451,7 @@ mod tests {
|
||||
});
|
||||
}
|
||||
|
||||
let mut matcher = Matcher::new(&query, &lowercase_query, query_chars, smart_case);
|
||||
let mut matcher = Matcher::new(&query, &lowercase_query, query_chars, smart_case, 100);
|
||||
|
||||
let cancel_flag = AtomicBool::new(false);
|
||||
let mut results = Vec::new();
|
||||
@@ -442,17 +462,16 @@ mod tests {
|
||||
path_entries.into_iter(),
|
||||
&mut results,
|
||||
&cancel_flag,
|
||||
|candidate, score, positions| PathMatch {
|
||||
|candidate, score| PathMatch {
|
||||
score,
|
||||
worktree_id: 0,
|
||||
positions: positions.clone(),
|
||||
positions: Vec::new(),
|
||||
path: Arc::from(candidate.path),
|
||||
path_prefix: "".into(),
|
||||
distance_to_relative_ancestor: usize::MAX,
|
||||
is_dir: false,
|
||||
},
|
||||
);
|
||||
results.sort_by(|a, b| b.cmp(a));
|
||||
|
||||
results
|
||||
.into_iter()
|
||||
|
||||
@@ -7,7 +7,7 @@ use std::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
matcher::{MatchCandidate, Matcher},
|
||||
matcher::{Match, MatchCandidate, Matcher},
|
||||
CharBag,
|
||||
};
|
||||
|
||||
@@ -42,6 +42,16 @@ pub trait PathMatchCandidateSet<'a>: Send + Sync {
|
||||
fn candidates(&'a self, start: usize) -> Self::Candidates;
|
||||
}
|
||||
|
||||
impl Match for PathMatch {
|
||||
fn score(&self) -> f64 {
|
||||
self.score
|
||||
}
|
||||
|
||||
fn set_positions(&mut self, positions: Vec<usize>) {
|
||||
self.positions = positions;
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> MatchCandidate for PathMatchCandidate<'a> {
|
||||
fn has_chars(&self, bag: CharBag) -> bool {
|
||||
self.char_bag.is_superset(bag)
|
||||
@@ -92,7 +102,13 @@ pub fn match_fixed_path_set(
|
||||
let query = query.chars().collect::<Vec<_>>();
|
||||
let query_char_bag = CharBag::from(&lowercase_query[..]);
|
||||
|
||||
let mut matcher = Matcher::new(&query, &lowercase_query, query_char_bag, smart_case);
|
||||
let mut matcher = Matcher::new(
|
||||
&query,
|
||||
&lowercase_query,
|
||||
query_char_bag,
|
||||
smart_case,
|
||||
max_results,
|
||||
);
|
||||
|
||||
let mut results = Vec::new();
|
||||
matcher.match_candidates(
|
||||
@@ -101,17 +117,16 @@ pub fn match_fixed_path_set(
|
||||
candidates.into_iter(),
|
||||
&mut results,
|
||||
&AtomicBool::new(false),
|
||||
|candidate, score, positions| PathMatch {
|
||||
|candidate, score| PathMatch {
|
||||
score,
|
||||
worktree_id,
|
||||
positions: positions.clone(),
|
||||
positions: Vec::new(),
|
||||
is_dir: candidate.is_dir,
|
||||
path: Arc::from(candidate.path),
|
||||
path_prefix: Arc::default(),
|
||||
distance_to_relative_ancestor: usize::MAX,
|
||||
},
|
||||
);
|
||||
util::truncate_to_bottom_n_sorted_by(&mut results, max_results, &|a, b| b.cmp(a));
|
||||
results
|
||||
}
|
||||
|
||||
@@ -149,8 +164,13 @@ pub async fn match_path_sets<'a, Set: PathMatchCandidateSet<'a>>(
|
||||
scope.spawn(async move {
|
||||
let segment_start = segment_idx * segment_size;
|
||||
let segment_end = segment_start + segment_size;
|
||||
let mut matcher =
|
||||
Matcher::new(query, lowercase_query, query_char_bag, smart_case);
|
||||
let mut matcher = Matcher::new(
|
||||
query,
|
||||
lowercase_query,
|
||||
query_char_bag,
|
||||
smart_case,
|
||||
max_results,
|
||||
);
|
||||
|
||||
let mut tree_start = 0;
|
||||
for candidate_set in candidate_sets {
|
||||
@@ -173,10 +193,10 @@ pub async fn match_path_sets<'a, Set: PathMatchCandidateSet<'a>>(
|
||||
candidates,
|
||||
results,
|
||||
cancel_flag,
|
||||
|candidate, score, positions| PathMatch {
|
||||
|candidate, score| PathMatch {
|
||||
score,
|
||||
worktree_id,
|
||||
positions: positions.clone(),
|
||||
positions: Vec::new(),
|
||||
path: Arc::from(candidate.path),
|
||||
is_dir: candidate.is_dir,
|
||||
path_prefix: candidate_set.prefix(),
|
||||
@@ -202,8 +222,14 @@ pub async fn match_path_sets<'a, Set: PathMatchCandidateSet<'a>>(
|
||||
})
|
||||
.await;
|
||||
|
||||
let mut results = segment_results.concat();
|
||||
util::truncate_to_bottom_n_sorted_by(&mut results, max_results, &|a, b| b.cmp(a));
|
||||
let mut results = Vec::new();
|
||||
for segment_result in segment_results {
|
||||
if results.is_empty() {
|
||||
results = segment_result;
|
||||
} else {
|
||||
util::extend_sorted(&mut results, segment_result, max_results, |a, b| b.cmp(a));
|
||||
}
|
||||
}
|
||||
results
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
matcher::{MatchCandidate, Matcher},
|
||||
matcher::{Match, MatchCandidate, Matcher},
|
||||
CharBag,
|
||||
};
|
||||
use gpui::BackgroundExecutor;
|
||||
@@ -46,6 +46,16 @@ pub struct StringMatch {
|
||||
pub string: String,
|
||||
}
|
||||
|
||||
impl Match for StringMatch {
|
||||
fn score(&self) -> f64 {
|
||||
self.score
|
||||
}
|
||||
|
||||
fn set_positions(&mut self, positions: Vec<usize>) {
|
||||
self.positions = positions;
|
||||
}
|
||||
}
|
||||
|
||||
impl StringMatch {
|
||||
pub fn ranges(&self) -> impl '_ + Iterator<Item = Range<usize>> {
|
||||
let mut positions = self.positions.iter().peekable();
|
||||
@@ -157,8 +167,13 @@ pub async fn match_strings(
|
||||
scope.spawn(async move {
|
||||
let segment_start = cmp::min(segment_idx * segment_size, candidates.len());
|
||||
let segment_end = cmp::min(segment_start + segment_size, candidates.len());
|
||||
let mut matcher =
|
||||
Matcher::new(query, lowercase_query, query_char_bag, smart_case);
|
||||
let mut matcher = Matcher::new(
|
||||
query,
|
||||
lowercase_query,
|
||||
query_char_bag,
|
||||
smart_case,
|
||||
max_results,
|
||||
);
|
||||
|
||||
matcher.match_candidates(
|
||||
&[],
|
||||
@@ -166,10 +181,10 @@ pub async fn match_strings(
|
||||
candidates[segment_start..segment_end].iter(),
|
||||
results,
|
||||
cancel_flag,
|
||||
|candidate, score, positions| StringMatch {
|
||||
|candidate, score| StringMatch {
|
||||
candidate_id: candidate.id,
|
||||
score,
|
||||
positions: positions.clone(),
|
||||
positions: Vec::new(),
|
||||
string: candidate.string.to_string(),
|
||||
},
|
||||
);
|
||||
@@ -178,7 +193,13 @@ pub async fn match_strings(
|
||||
})
|
||||
.await;
|
||||
|
||||
let mut results = segment_results.concat();
|
||||
util::truncate_to_bottom_n_sorted_by(&mut results, max_results, &|a, b| b.cmp(a));
|
||||
let mut results = Vec::new();
|
||||
for segment_result in segment_results {
|
||||
if results.is_empty() {
|
||||
results = segment_result;
|
||||
} else {
|
||||
util::extend_sorted(&mut results, segment_result, max_results, |a, b| b.cmp(a));
|
||||
}
|
||||
}
|
||||
results
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ pub struct GitPanel {
|
||||
// not hidden by folding or such
|
||||
visible_entries: Vec<WorktreeEntries>,
|
||||
width: Option<Pixels>,
|
||||
git_diff_editor: Option<View<Editor>>,
|
||||
git_diff_editor: View<Editor>,
|
||||
git_diff_editor_updates: Task<()>,
|
||||
reveal_in_editor: Task<()>,
|
||||
}
|
||||
@@ -149,7 +149,11 @@ impl GitPanel {
|
||||
workspace: WeakView<Workspace>,
|
||||
cx: AsyncWindowContext,
|
||||
) -> Task<Result<View<Self>>> {
|
||||
cx.spawn(|mut cx| async move { workspace.update(&mut cx, Self::new) })
|
||||
cx.spawn(|mut cx| async move {
|
||||
// Clippy incorrectly classifies this as a redundant closure
|
||||
#[allow(clippy::redundant_closure)]
|
||||
workspace.update(&mut cx, |workspace, cx| Self::new(workspace, cx))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn new(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) -> View<Self> {
|
||||
@@ -164,7 +168,7 @@ impl GitPanel {
|
||||
this.hide_scrollbar(cx);
|
||||
})
|
||||
.detach();
|
||||
cx.subscribe(&project, |this, _, event, cx| match event {
|
||||
cx.subscribe(&project, |this, project, event, cx| match event {
|
||||
project::Event::WorktreeRemoved(id) => {
|
||||
this.expanded_dir_ids.remove(id);
|
||||
this.update_visible_entries(None, None, cx);
|
||||
@@ -182,10 +186,9 @@ impl GitPanel {
|
||||
}
|
||||
project::Event::Closed => {
|
||||
this.git_diff_editor_updates = Task::ready(());
|
||||
this.reveal_in_editor = Task::ready(());
|
||||
this.expanded_dir_ids.clear();
|
||||
this.visible_entries.clear();
|
||||
this.git_diff_editor = None;
|
||||
this.git_diff_editor = diff_display_editor(project.clone(), cx);
|
||||
}
|
||||
_ => {}
|
||||
})
|
||||
@@ -193,7 +196,7 @@ impl GitPanel {
|
||||
|
||||
let scroll_handle = UniformListScrollHandle::new();
|
||||
|
||||
let mut git_panel = Self {
|
||||
let mut this = Self {
|
||||
workspace: weak_workspace,
|
||||
focus_handle: cx.focus_handle(),
|
||||
fs,
|
||||
@@ -208,13 +211,13 @@ impl GitPanel {
|
||||
selected_item: None,
|
||||
show_scrollbar: !Self::should_autohide_scrollbar(cx),
|
||||
hide_scrollbar_task: None,
|
||||
git_diff_editor: Some(diff_display_editor(cx)),
|
||||
git_diff_editor: diff_display_editor(project.clone(), cx),
|
||||
git_diff_editor_updates: Task::ready(()),
|
||||
reveal_in_editor: Task::ready(()),
|
||||
project,
|
||||
};
|
||||
git_panel.update_visible_entries(None, None, cx);
|
||||
git_panel
|
||||
this.update_visible_entries(None, None, cx);
|
||||
this
|
||||
});
|
||||
|
||||
git_panel
|
||||
@@ -599,7 +602,7 @@ impl GitPanel {
|
||||
);
|
||||
}
|
||||
|
||||
let project = self.project.downgrade();
|
||||
let project = self.project.clone();
|
||||
self.git_diff_editor_updates = cx.spawn(|git_panel, mut cx| async move {
|
||||
cx.background_executor()
|
||||
.timer(UPDATE_DEBOUNCE)
|
||||
@@ -607,7 +610,7 @@ impl GitPanel {
|
||||
let Some(project_buffers) = git_panel
|
||||
.update(&mut cx, |git_panel, cx| {
|
||||
futures::future::join_all(git_panel.visible_entries.iter_mut().flat_map(
|
||||
|worktree_entries| {
|
||||
move |worktree_entries| {
|
||||
worktree_entries
|
||||
.visible_entries
|
||||
.iter()
|
||||
@@ -691,7 +694,7 @@ impl GitPanel {
|
||||
anyhow::Ok((buffer, unstaged_changes, hunks))
|
||||
});
|
||||
Some((entry_path, unstaged_changes_task))
|
||||
}).ok()??;
|
||||
})?;
|
||||
Some((entry_path, unstaged_changes_task))
|
||||
})
|
||||
.map(|(entry_path, open_task)| async move {
|
||||
@@ -713,7 +716,7 @@ impl GitPanel {
|
||||
let mut change_sets = Vec::with_capacity(project_buffers.len());
|
||||
if let Some(buffer_update_task) = git_panel
|
||||
.update(&mut cx, |git_panel, cx| {
|
||||
let editor = git_panel.git_diff_editor.clone()?;
|
||||
let editor = git_panel.git_diff_editor.clone();
|
||||
let multi_buffer = editor.read(cx).buffer().clone();
|
||||
let mut buffers_with_ranges = Vec::with_capacity(project_buffers.len());
|
||||
for (buffer_path, open_result) in project_buffers {
|
||||
@@ -732,27 +735,25 @@ impl GitPanel {
|
||||
}
|
||||
}
|
||||
|
||||
Some(multi_buffer.update(cx, |multi_buffer, cx| {
|
||||
multi_buffer.update(cx, |multi_buffer, cx| {
|
||||
multi_buffer.clear(cx);
|
||||
multi_buffer.push_multiple_excerpts_with_context_lines(
|
||||
buffers_with_ranges,
|
||||
DEFAULT_MULTIBUFFER_CONTEXT,
|
||||
cx,
|
||||
)
|
||||
}))
|
||||
})
|
||||
})
|
||||
.ok().flatten()
|
||||
.ok()
|
||||
{
|
||||
buffer_update_task.await;
|
||||
git_panel
|
||||
.update(&mut cx, |git_panel, cx| {
|
||||
if let Some(diff_editor) = git_panel.git_diff_editor.as_ref() {
|
||||
diff_editor.update(cx, |editor, cx| {
|
||||
for change_set in change_sets {
|
||||
editor.add_change_set(change_set, cx);
|
||||
}
|
||||
});
|
||||
}
|
||||
git_panel.git_diff_editor.update(cx, |editor, cx| {
|
||||
for change_set in change_sets {
|
||||
editor.add_change_set(change_set, cx);
|
||||
}
|
||||
})
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
@@ -1000,7 +1001,7 @@ impl GitPanel {
|
||||
let id = id.to_proto() as usize;
|
||||
let checkbox_id = ElementId::Name(format!("checkbox_{}", id).into());
|
||||
let is_staged = ToggleState::Selected;
|
||||
let handle = cx.view().downgrade();
|
||||
let handle = cx.view().clone();
|
||||
|
||||
h_flex()
|
||||
.id(id)
|
||||
@@ -1023,18 +1024,16 @@ impl GitPanel {
|
||||
.toggle_state(selected)
|
||||
.child(h_flex().gap_1p5().child(details.display_name.clone()))
|
||||
.on_click(move |e, cx| {
|
||||
handle
|
||||
.update(cx, |git_panel, cx| {
|
||||
git_panel.selected_item = Some(details.index);
|
||||
let change_focus = e.down.click_count > 1;
|
||||
git_panel.reveal_entry_in_git_editor(
|
||||
details.hunks.clone(),
|
||||
change_focus,
|
||||
None,
|
||||
cx,
|
||||
);
|
||||
})
|
||||
.ok();
|
||||
handle.update(cx, |git_panel, cx| {
|
||||
git_panel.selected_item = Some(details.index);
|
||||
let change_focus = e.down.click_count > 1;
|
||||
git_panel.reveal_entry_in_git_editor(
|
||||
details.hunks.clone(),
|
||||
change_focus,
|
||||
None,
|
||||
cx,
|
||||
);
|
||||
});
|
||||
}),
|
||||
)
|
||||
}
|
||||
@@ -1044,12 +1043,10 @@ impl GitPanel {
|
||||
hunks: Rc<OnceCell<Vec<DiffHunk>>>,
|
||||
change_focus: bool,
|
||||
debounce: Option<Duration>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
cx: &mut ViewContext<'_, Self>,
|
||||
) {
|
||||
let workspace = self.workspace.clone();
|
||||
let Some(diff_editor) = self.git_diff_editor.clone() else {
|
||||
return;
|
||||
};
|
||||
let diff_editor = self.git_diff_editor.clone();
|
||||
self.reveal_in_editor = cx.spawn(|_, mut cx| async move {
|
||||
if let Some(debounce) = debounce {
|
||||
cx.background_executor().timer(debounce).await;
|
||||
@@ -1199,7 +1196,7 @@ impl Panel for GitPanel {
|
||||
"GitPanel"
|
||||
}
|
||||
|
||||
fn position(&self, cx: &WindowContext) -> DockPosition {
|
||||
fn position(&self, cx: &gpui::WindowContext) -> DockPosition {
|
||||
GitPanelSettings::get_global(cx).dock
|
||||
}
|
||||
|
||||
@@ -1215,7 +1212,7 @@ impl Panel for GitPanel {
|
||||
);
|
||||
}
|
||||
|
||||
fn size(&self, cx: &WindowContext) -> Pixels {
|
||||
fn size(&self, cx: &gpui::WindowContext) -> Pixels {
|
||||
self.width
|
||||
.unwrap_or_else(|| GitPanelSettings::get_global(cx).default_width)
|
||||
}
|
||||
@@ -1237,18 +1234,14 @@ impl Panel for GitPanel {
|
||||
fn toggle_action(&self) -> Box<dyn Action> {
|
||||
Box::new(ToggleFocus)
|
||||
}
|
||||
|
||||
fn activation_priority(&self) -> u32 {
|
||||
2
|
||||
}
|
||||
}
|
||||
|
||||
fn diff_display_editor(cx: &mut WindowContext) -> View<Editor> {
|
||||
fn diff_display_editor(project: Model<Project>, cx: &mut WindowContext) -> View<Editor> {
|
||||
cx.new_view(|cx| {
|
||||
let multi_buffer = cx.new_model(|_| {
|
||||
MultiBuffer::new(language::Capability::ReadWrite).with_title("Project diff".to_string())
|
||||
let multi_buffer = cx.new_model(|cx| {
|
||||
MultiBuffer::new(project.read(cx).capability()).with_title("Project diff".to_string())
|
||||
});
|
||||
let mut editor = Editor::for_multibuffer(multi_buffer, None, true, cx);
|
||||
let mut editor = Editor::for_multibuffer(multi_buffer, Some(project), true, cx);
|
||||
editor.set_expand_all_diff_hunks();
|
||||
editor
|
||||
})
|
||||
|
||||
@@ -22,7 +22,7 @@ test-support = [
|
||||
"x11",
|
||||
]
|
||||
runtime_shaders = []
|
||||
macos-blade = ["blade-graphics", "blade-macros", "blade-util", "bytemuck", "objc2", "objc2-metal"]
|
||||
macos-blade = ["blade-graphics", "blade-macros", "blade-util", "bytemuck"]
|
||||
wayland = [
|
||||
"blade-graphics",
|
||||
"blade-macros",
|
||||
@@ -132,14 +132,11 @@ core-foundation.workspace = true
|
||||
core-foundation-sys = "0.8"
|
||||
core-graphics = "0.23"
|
||||
core-text = "20.1"
|
||||
font-kit = { git = "https://github.com/zed-industries/font-kit", rev = "40391b7", optional = true }
|
||||
font-kit = { git = "https://github.com/zed-industries/font-kit", rev = "40391b7", optional = true}
|
||||
foreign-types = "0.5"
|
||||
log.workspace = true
|
||||
media.workspace = true
|
||||
objc = "0.2"
|
||||
objc2 = { version = "0.5", optional = true }
|
||||
objc2-metal = { version = "0.2", optional = true }
|
||||
#TODO: replace with "objc2"
|
||||
metal.workspace = true
|
||||
|
||||
[target.'cfg(any(target_os = "linux", target_os = "freebsd", target_os = "macos"))'.dependencies]
|
||||
|
||||
@@ -1,574 +1,25 @@
|
||||
use gpui::{
|
||||
div, hsla, point, prelude::*, px, relative, rgb, size, App, AppContext, Bounds, BoxShadow, Div,
|
||||
SharedString, ViewContext, WindowBounds, WindowOptions,
|
||||
div, prelude::*, px, rgb, size, App, AppContext, Bounds, ViewContext, WindowBounds,
|
||||
WindowOptions,
|
||||
};
|
||||
|
||||
use smallvec::smallvec;
|
||||
|
||||
struct Shadow {}
|
||||
|
||||
impl Shadow {
|
||||
fn base() -> Div {
|
||||
div()
|
||||
.size_16()
|
||||
.bg(rgb(0xffffff))
|
||||
.rounded_full()
|
||||
.border_1()
|
||||
.border_color(hsla(0.0, 0.0, 0.0, 0.1))
|
||||
}
|
||||
|
||||
fn square() -> Div {
|
||||
div()
|
||||
.size_16()
|
||||
.bg(rgb(0xffffff))
|
||||
.border_1()
|
||||
.border_color(hsla(0.0, 0.0, 0.0, 0.1))
|
||||
}
|
||||
|
||||
fn rounded_small() -> Div {
|
||||
div()
|
||||
.size_16()
|
||||
.bg(rgb(0xffffff))
|
||||
.rounded(px(4.))
|
||||
.border_1()
|
||||
.border_color(hsla(0.0, 0.0, 0.0, 0.1))
|
||||
}
|
||||
|
||||
fn rounded_medium() -> Div {
|
||||
div()
|
||||
.size_16()
|
||||
.bg(rgb(0xffffff))
|
||||
.rounded(px(8.))
|
||||
.border_1()
|
||||
.border_color(hsla(0.0, 0.0, 0.0, 0.1))
|
||||
}
|
||||
|
||||
fn rounded_large() -> Div {
|
||||
div()
|
||||
.size_16()
|
||||
.bg(rgb(0xffffff))
|
||||
.rounded(px(12.))
|
||||
.border_1()
|
||||
.border_color(hsla(0.0, 0.0, 0.0, 0.1))
|
||||
}
|
||||
}
|
||||
|
||||
fn example(label: impl Into<SharedString>, example: impl IntoElement) -> impl IntoElement {
|
||||
let label = label.into();
|
||||
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.justify_center()
|
||||
.items_center()
|
||||
.w(relative(1. / 6.))
|
||||
.border_r_1()
|
||||
.border_color(hsla(0.0, 0.0, 0.0, 1.0))
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.items_center()
|
||||
.justify_center()
|
||||
.flex_1()
|
||||
.py_12()
|
||||
.child(example),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.w_full()
|
||||
.border_t_1()
|
||||
.border_color(hsla(0.0, 0.0, 0.0, 1.0))
|
||||
.p_1()
|
||||
.flex()
|
||||
.items_center()
|
||||
.child(label),
|
||||
)
|
||||
}
|
||||
|
||||
impl Render for Shadow {
|
||||
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
div()
|
||||
.id("shadow-example")
|
||||
.overflow_y_scroll()
|
||||
.flex()
|
||||
.bg(rgb(0xffffff))
|
||||
.size_full()
|
||||
.text_xs()
|
||||
.child(div().flex().flex_col().w_full().children(vec![
|
||||
div()
|
||||
.border_b_1()
|
||||
.border_color(hsla(0.0, 0.0, 0.0, 1.0))
|
||||
.flex()
|
||||
.flex_row()
|
||||
.children(vec![
|
||||
example(
|
||||
"Square",
|
||||
Shadow::square()
|
||||
.shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.5, 0.5, 0.3),
|
||||
offset: point(px(0.), px(8.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(0.),
|
||||
}]),
|
||||
),
|
||||
example(
|
||||
"Rounded 4",
|
||||
Shadow::rounded_small()
|
||||
.shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.5, 0.5, 0.3),
|
||||
offset: point(px(0.), px(8.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(0.),
|
||||
}]),
|
||||
),
|
||||
example(
|
||||
"Rounded 8",
|
||||
Shadow::rounded_medium()
|
||||
.shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.5, 0.5, 0.3),
|
||||
offset: point(px(0.), px(8.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(0.),
|
||||
}]),
|
||||
),
|
||||
example(
|
||||
"Rounded 16",
|
||||
Shadow::rounded_large()
|
||||
.shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.5, 0.5, 0.3),
|
||||
offset: point(px(0.), px(8.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(0.),
|
||||
}]),
|
||||
),
|
||||
example(
|
||||
"Circle",
|
||||
Shadow::base()
|
||||
.shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.5, 0.5, 0.3),
|
||||
offset: point(px(0.), px(8.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(0.),
|
||||
}]),
|
||||
),
|
||||
]),
|
||||
div()
|
||||
.border_b_1()
|
||||
.border_color(hsla(0.0, 0.0, 0.0, 1.0))
|
||||
.flex()
|
||||
.w_full()
|
||||
.children(vec![
|
||||
example("None", Shadow::base()),
|
||||
// Small shadow
|
||||
example("Small", Shadow::base().shadow_sm()),
|
||||
// Medium shadow
|
||||
example("Medium", Shadow::base().shadow_md()),
|
||||
// Large shadow
|
||||
example("Large", Shadow::base().shadow_lg()),
|
||||
example("Extra Large", Shadow::base().shadow_xl()),
|
||||
example("2X Large", Shadow::base().shadow_2xl()),
|
||||
]),
|
||||
// Horizontal list of increasing blur radii
|
||||
div()
|
||||
.border_b_1()
|
||||
.border_color(hsla(0.0, 0.0, 0.0, 1.0))
|
||||
.flex()
|
||||
.children(vec![
|
||||
example(
|
||||
"Blur 0",
|
||||
Shadow::base().shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.0, 0.0, 0.3),
|
||||
offset: point(px(0.), px(8.)),
|
||||
blur_radius: px(0.),
|
||||
spread_radius: px(0.),
|
||||
}]),
|
||||
),
|
||||
example(
|
||||
"Blur 2",
|
||||
Shadow::base().shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.0, 0.0, 0.3),
|
||||
offset: point(px(0.), px(8.)),
|
||||
blur_radius: px(2.),
|
||||
spread_radius: px(0.),
|
||||
}]),
|
||||
),
|
||||
example(
|
||||
"Blur 4",
|
||||
Shadow::base().shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.0, 0.0, 0.3),
|
||||
offset: point(px(0.), px(8.)),
|
||||
blur_radius: px(4.),
|
||||
spread_radius: px(0.),
|
||||
}]),
|
||||
),
|
||||
example(
|
||||
"Blur 8",
|
||||
Shadow::base().shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.0, 0.0, 0.3),
|
||||
offset: point(px(0.), px(8.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(0.),
|
||||
}]),
|
||||
),
|
||||
example(
|
||||
"Blur 16",
|
||||
Shadow::base().shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.0, 0.0, 0.3),
|
||||
offset: point(px(0.), px(8.)),
|
||||
blur_radius: px(16.),
|
||||
spread_radius: px(0.),
|
||||
}]),
|
||||
),
|
||||
]),
|
||||
// Horizontal list of increasing spread radii
|
||||
div()
|
||||
.border_b_1()
|
||||
.border_color(hsla(0.0, 0.0, 0.0, 1.0))
|
||||
.flex()
|
||||
.children(vec![
|
||||
example(
|
||||
"Spread 0",
|
||||
Shadow::base().shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.0, 0.0, 0.3),
|
||||
offset: point(px(0.), px(8.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(0.),
|
||||
}]),
|
||||
),
|
||||
example(
|
||||
"Spread 2",
|
||||
Shadow::base().shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.0, 0.0, 0.3),
|
||||
offset: point(px(0.), px(8.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(2.),
|
||||
}]),
|
||||
),
|
||||
example(
|
||||
"Spread 4",
|
||||
Shadow::base().shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.0, 0.0, 0.3),
|
||||
offset: point(px(0.), px(8.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(4.),
|
||||
}]),
|
||||
),
|
||||
example(
|
||||
"Spread 8",
|
||||
Shadow::base().shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.0, 0.0, 0.3),
|
||||
offset: point(px(0.), px(8.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(8.),
|
||||
}]),
|
||||
),
|
||||
example(
|
||||
"Spread 16",
|
||||
Shadow::base().shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.0, 0.0, 0.3),
|
||||
offset: point(px(0.), px(8.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(16.),
|
||||
}]),
|
||||
),
|
||||
]),
|
||||
// Square spread examples
|
||||
div()
|
||||
.border_b_1()
|
||||
.border_color(hsla(0.0, 0.0, 0.0, 1.0))
|
||||
.flex()
|
||||
.children(vec![
|
||||
example(
|
||||
"Square Spread 0",
|
||||
Shadow::square().shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.0, 0.0, 0.3),
|
||||
offset: point(px(0.), px(8.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(0.),
|
||||
}]),
|
||||
),
|
||||
example(
|
||||
"Square Spread 8",
|
||||
Shadow::square().shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.0, 0.0, 0.3),
|
||||
offset: point(px(0.), px(8.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(8.),
|
||||
}]),
|
||||
),
|
||||
example(
|
||||
"Square Spread 16",
|
||||
Shadow::square().shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.0, 0.0, 0.3),
|
||||
offset: point(px(0.), px(8.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(16.),
|
||||
}]),
|
||||
),
|
||||
]),
|
||||
// Rounded large spread examples
|
||||
div()
|
||||
.border_b_1()
|
||||
.border_color(hsla(0.0, 0.0, 0.0, 1.0))
|
||||
.flex()
|
||||
.children(vec![
|
||||
example(
|
||||
"Rounded Large Spread 0",
|
||||
Shadow::rounded_large().shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.0, 0.0, 0.3),
|
||||
offset: point(px(0.), px(8.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(0.),
|
||||
}]),
|
||||
),
|
||||
example(
|
||||
"Rounded Large Spread 8",
|
||||
Shadow::rounded_large().shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.0, 0.0, 0.3),
|
||||
offset: point(px(0.), px(8.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(8.),
|
||||
}]),
|
||||
),
|
||||
example(
|
||||
"Rounded Large Spread 16",
|
||||
Shadow::rounded_large().shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.0, 0.0, 0.3),
|
||||
offset: point(px(0.), px(8.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(16.),
|
||||
}]),
|
||||
),
|
||||
]),
|
||||
// Directional shadows
|
||||
div()
|
||||
.border_b_1()
|
||||
.border_color(hsla(0.0, 0.0, 0.0, 1.0))
|
||||
.flex()
|
||||
.children(vec![
|
||||
example(
|
||||
"Left",
|
||||
Shadow::base().shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.5, 0.5, 0.3),
|
||||
offset: point(px(-8.), px(0.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(0.),
|
||||
}]),
|
||||
),
|
||||
example(
|
||||
"Right",
|
||||
Shadow::base().shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.5, 0.5, 0.3),
|
||||
offset: point(px(8.), px(0.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(0.),
|
||||
}]),
|
||||
),
|
||||
example(
|
||||
"Top",
|
||||
Shadow::base().shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.5, 0.5, 0.3),
|
||||
offset: point(px(0.), px(-8.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(0.),
|
||||
}]),
|
||||
),
|
||||
example(
|
||||
"Bottom",
|
||||
Shadow::base().shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.5, 0.5, 0.3),
|
||||
offset: point(px(0.), px(8.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(0.),
|
||||
}]),
|
||||
),
|
||||
]),
|
||||
// Square directional shadows
|
||||
div()
|
||||
.border_b_1()
|
||||
.border_color(hsla(0.0, 0.0, 0.0, 1.0))
|
||||
.flex()
|
||||
.children(vec![
|
||||
example(
|
||||
"Square Left",
|
||||
Shadow::square().shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.5, 0.5, 0.3),
|
||||
offset: point(px(-8.), px(0.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(0.),
|
||||
}]),
|
||||
),
|
||||
example(
|
||||
"Square Right",
|
||||
Shadow::square().shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.5, 0.5, 0.3),
|
||||
offset: point(px(8.), px(0.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(0.),
|
||||
}]),
|
||||
),
|
||||
example(
|
||||
"Square Top",
|
||||
Shadow::square().shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.5, 0.5, 0.3),
|
||||
offset: point(px(0.), px(-8.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(0.),
|
||||
}]),
|
||||
),
|
||||
example(
|
||||
"Square Bottom",
|
||||
Shadow::square().shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.5, 0.5, 0.3),
|
||||
offset: point(px(0.), px(8.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(0.),
|
||||
}]),
|
||||
),
|
||||
]),
|
||||
// Rounded large directional shadows
|
||||
div()
|
||||
.border_b_1()
|
||||
.border_color(hsla(0.0, 0.0, 0.0, 1.0))
|
||||
.flex()
|
||||
.children(vec![
|
||||
example(
|
||||
"Rounded Large Left",
|
||||
Shadow::rounded_large().shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.5, 0.5, 0.3),
|
||||
offset: point(px(-8.), px(0.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(0.),
|
||||
}]),
|
||||
),
|
||||
example(
|
||||
"Rounded Large Right",
|
||||
Shadow::rounded_large().shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.5, 0.5, 0.3),
|
||||
offset: point(px(8.), px(0.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(0.),
|
||||
}]),
|
||||
),
|
||||
example(
|
||||
"Rounded Large Top",
|
||||
Shadow::rounded_large().shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.5, 0.5, 0.3),
|
||||
offset: point(px(0.), px(-8.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(0.),
|
||||
}]),
|
||||
),
|
||||
example(
|
||||
"Rounded Large Bottom",
|
||||
Shadow::rounded_large().shadow(smallvec![BoxShadow {
|
||||
color: hsla(0.0, 0.5, 0.5, 0.3),
|
||||
offset: point(px(0.), px(8.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(0.),
|
||||
}]),
|
||||
),
|
||||
]),
|
||||
// Multiple shadows for different shapes
|
||||
div()
|
||||
.border_b_1()
|
||||
.border_color(hsla(0.0, 0.0, 0.0, 1.0))
|
||||
.flex()
|
||||
.children(vec![
|
||||
example(
|
||||
"Circle Multiple",
|
||||
Shadow::base().shadow(smallvec![
|
||||
BoxShadow {
|
||||
color: hsla(0.0 / 360., 1.0, 0.5, 0.3), // Red
|
||||
offset: point(px(0.), px(-12.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(2.),
|
||||
},
|
||||
BoxShadow {
|
||||
color: hsla(60.0 / 360., 1.0, 0.5, 0.3), // Yellow
|
||||
offset: point(px(12.), px(0.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(2.),
|
||||
},
|
||||
BoxShadow {
|
||||
color: hsla(120.0 / 360., 1.0, 0.5, 0.3), // Green
|
||||
offset: point(px(0.), px(12.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(2.),
|
||||
},
|
||||
BoxShadow {
|
||||
color: hsla(240.0 / 360., 1.0, 0.5, 0.3), // Blue
|
||||
offset: point(px(-12.), px(0.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(2.),
|
||||
},
|
||||
]),
|
||||
),
|
||||
example(
|
||||
"Square Multiple",
|
||||
Shadow::square().shadow(smallvec![
|
||||
BoxShadow {
|
||||
color: hsla(0.0 / 360., 1.0, 0.5, 0.3), // Red
|
||||
offset: point(px(0.), px(-12.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(2.),
|
||||
},
|
||||
BoxShadow {
|
||||
color: hsla(60.0 / 360., 1.0, 0.5, 0.3), // Yellow
|
||||
offset: point(px(12.), px(0.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(2.),
|
||||
},
|
||||
BoxShadow {
|
||||
color: hsla(120.0 / 360., 1.0, 0.5, 0.3), // Green
|
||||
offset: point(px(0.), px(12.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(2.),
|
||||
},
|
||||
BoxShadow {
|
||||
color: hsla(240.0 / 360., 1.0, 0.5, 0.3), // Blue
|
||||
offset: point(px(-12.), px(0.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(2.),
|
||||
},
|
||||
]),
|
||||
),
|
||||
example(
|
||||
"Rounded Large Multiple",
|
||||
Shadow::rounded_large().shadow(smallvec![
|
||||
BoxShadow {
|
||||
color: hsla(0.0 / 360., 1.0, 0.5, 0.3), // Red
|
||||
offset: point(px(0.), px(-12.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(2.),
|
||||
},
|
||||
BoxShadow {
|
||||
color: hsla(60.0 / 360., 1.0, 0.5, 0.3), // Yellow
|
||||
offset: point(px(12.), px(0.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(2.),
|
||||
},
|
||||
BoxShadow {
|
||||
color: hsla(120.0 / 360., 1.0, 0.5, 0.3), // Green
|
||||
offset: point(px(0.), px(12.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(2.),
|
||||
},
|
||||
BoxShadow {
|
||||
color: hsla(240.0 / 360., 1.0, 0.5, 0.3), // Blue
|
||||
offset: point(px(-12.), px(0.)),
|
||||
blur_radius: px(8.),
|
||||
spread_radius: px(2.),
|
||||
},
|
||||
]),
|
||||
),
|
||||
]),
|
||||
]))
|
||||
.justify_center()
|
||||
.items_center()
|
||||
.child(div().size_8().shadow_sm())
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
App::new().run(|cx: &mut AppContext| {
|
||||
let bounds = Bounds::centered(None, size(px(1000.0), px(800.0)), cx);
|
||||
let bounds = Bounds::centered(None, size(px(300.0), px(300.0)), cx);
|
||||
cx.open_window(
|
||||
WindowOptions {
|
||||
window_bounds: Some(WindowBounds::Windowed(bounds)),
|
||||
@@ -577,7 +28,5 @@ fn main() {
|
||||
|cx| cx.new_view(|_cx| Shadow {}),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
cx.activate(true);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1490,7 +1490,7 @@ impl Context for AppContext {
|
||||
|
||||
fn update_window<T, F>(&mut self, handle: AnyWindowHandle, update: F) -> Result<T>
|
||||
where
|
||||
F: FnOnce(AnyView, &mut WindowContext) -> T,
|
||||
F: FnOnce(AnyView, &mut WindowContext<'_>) -> T,
|
||||
{
|
||||
self.update(|cx| {
|
||||
let mut window = cx
|
||||
|
||||
@@ -84,7 +84,7 @@ impl Context for AsyncAppContext {
|
||||
|
||||
fn update_window<T, F>(&mut self, window: AnyWindowHandle, f: F) -> Result<T>
|
||||
where
|
||||
F: FnOnce(AnyView, &mut WindowContext) -> T,
|
||||
F: FnOnce(AnyView, &mut WindowContext<'_>) -> T,
|
||||
{
|
||||
let app = self.app.upgrade().context("app was released")?;
|
||||
let mut lock = app.borrow_mut();
|
||||
@@ -349,7 +349,7 @@ impl Context for AsyncWindowContext {
|
||||
|
||||
fn update_window<T, F>(&mut self, window: AnyWindowHandle, update: F) -> Result<T>
|
||||
where
|
||||
F: FnOnce(AnyView, &mut WindowContext) -> T,
|
||||
F: FnOnce(AnyView, &mut WindowContext<'_>) -> T,
|
||||
{
|
||||
self.app.update_window(window, update)
|
||||
}
|
||||
@@ -369,7 +369,7 @@ impl Context for AsyncWindowContext {
|
||||
impl VisualContext for AsyncWindowContext {
|
||||
fn new_view<V>(
|
||||
&mut self,
|
||||
build_view_state: impl FnOnce(&mut ViewContext<V>) -> V,
|
||||
build_view_state: impl FnOnce(&mut ViewContext<'_, V>) -> V,
|
||||
) -> Self::Result<View<V>>
|
||||
where
|
||||
V: 'static + Render,
|
||||
@@ -381,7 +381,7 @@ impl VisualContext for AsyncWindowContext {
|
||||
fn update_view<V: 'static, R>(
|
||||
&mut self,
|
||||
view: &View<V>,
|
||||
update: impl FnOnce(&mut V, &mut ViewContext<V>) -> R,
|
||||
update: impl FnOnce(&mut V, &mut ViewContext<'_, V>) -> R,
|
||||
) -> Self::Result<R> {
|
||||
self.window
|
||||
.update(self, |_, cx| cx.update_view(view, update))
|
||||
@@ -389,7 +389,7 @@ impl VisualContext for AsyncWindowContext {
|
||||
|
||||
fn replace_root_view<V>(
|
||||
&mut self,
|
||||
build_view: impl FnOnce(&mut ViewContext<V>) -> V,
|
||||
build_view: impl FnOnce(&mut ViewContext<'_, V>) -> V,
|
||||
) -> Self::Result<View<V>>
|
||||
where
|
||||
V: 'static + Render,
|
||||
|
||||
@@ -263,7 +263,7 @@ impl<'a, T> Context for ModelContext<'a, T> {
|
||||
|
||||
fn update_window<R, F>(&mut self, window: AnyWindowHandle, update: F) -> Result<R>
|
||||
where
|
||||
F: FnOnce(AnyView, &mut WindowContext) -> R,
|
||||
F: FnOnce(AnyView, &mut WindowContext<'_>) -> R,
|
||||
{
|
||||
self.app.update_window(window, update)
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ impl Context for TestAppContext {
|
||||
|
||||
fn update_window<T, F>(&mut self, window: AnyWindowHandle, f: F) -> Result<T>
|
||||
where
|
||||
F: FnOnce(AnyView, &mut WindowContext) -> T,
|
||||
F: FnOnce(AnyView, &mut WindowContext<'_>) -> T,
|
||||
{
|
||||
let mut lock = self.app.borrow_mut();
|
||||
lock.update_window(window, f)
|
||||
@@ -916,7 +916,7 @@ impl Context for VisualTestContext {
|
||||
|
||||
fn update_window<T, F>(&mut self, window: AnyWindowHandle, f: F) -> Result<T>
|
||||
where
|
||||
F: FnOnce(AnyView, &mut WindowContext) -> T,
|
||||
F: FnOnce(AnyView, &mut WindowContext<'_>) -> T,
|
||||
{
|
||||
self.cx.update_window(window, f)
|
||||
}
|
||||
@@ -936,7 +936,7 @@ impl Context for VisualTestContext {
|
||||
impl VisualContext for VisualTestContext {
|
||||
fn new_view<V>(
|
||||
&mut self,
|
||||
build_view: impl FnOnce(&mut ViewContext<V>) -> V,
|
||||
build_view: impl FnOnce(&mut ViewContext<'_, V>) -> V,
|
||||
) -> Self::Result<View<V>>
|
||||
where
|
||||
V: 'static + Render,
|
||||
@@ -949,7 +949,7 @@ impl VisualContext for VisualTestContext {
|
||||
fn update_view<V: 'static, R>(
|
||||
&mut self,
|
||||
view: &View<V>,
|
||||
update: impl FnOnce(&mut V, &mut ViewContext<V>) -> R,
|
||||
update: impl FnOnce(&mut V, &mut ViewContext<'_, V>) -> R,
|
||||
) -> Self::Result<R> {
|
||||
self.window
|
||||
.update(&mut self.cx, |_, cx| cx.update_view(view, update))
|
||||
@@ -958,7 +958,7 @@ impl VisualContext for VisualTestContext {
|
||||
|
||||
fn replace_root_view<V>(
|
||||
&mut self,
|
||||
build_view: impl FnOnce(&mut ViewContext<V>) -> V,
|
||||
build_view: impl FnOnce(&mut ViewContext<'_, V>) -> V,
|
||||
) -> Self::Result<View<V>>
|
||||
where
|
||||
V: 'static + Render,
|
||||
@@ -993,7 +993,7 @@ impl AnyWindowHandle {
|
||||
pub fn build_view<V: Render + 'static>(
|
||||
&self,
|
||||
cx: &mut TestAppContext,
|
||||
build_view: impl FnOnce(&mut ViewContext<V>) -> V,
|
||||
build_view: impl FnOnce(&mut ViewContext<'_, V>) -> V,
|
||||
) -> View<V> {
|
||||
self.update(cx, |_, cx| cx.new_view(build_view)).unwrap()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use crate::{AnyElement, Element, ElementId, GlobalElementId, IntoElement, WindowContext};
|
||||
use crate::{AnyElement, Element, ElementId, GlobalElementId, IntoElement};
|
||||
|
||||
pub use easing::*;
|
||||
|
||||
@@ -104,7 +104,7 @@ impl<E: IntoElement + 'static> Element for AnimationElement<E> {
|
||||
fn request_layout(
|
||||
&mut self,
|
||||
global_id: Option<&GlobalElementId>,
|
||||
cx: &mut WindowContext,
|
||||
cx: &mut crate::WindowContext,
|
||||
) -> (crate::LayoutId, Self::RequestLayoutState) {
|
||||
cx.with_element_state(global_id.unwrap(), |state, cx| {
|
||||
let state = state.unwrap_or_else(|| AnimationState {
|
||||
@@ -145,7 +145,7 @@ impl<E: IntoElement + 'static> Element for AnimationElement<E> {
|
||||
_id: Option<&GlobalElementId>,
|
||||
_bounds: crate::Bounds<crate::Pixels>,
|
||||
element: &mut Self::RequestLayoutState,
|
||||
cx: &mut WindowContext,
|
||||
cx: &mut crate::WindowContext,
|
||||
) -> Self::PrepaintState {
|
||||
element.prepaint(cx);
|
||||
}
|
||||
@@ -156,7 +156,7 @@ impl<E: IntoElement + 'static> Element for AnimationElement<E> {
|
||||
_bounds: crate::Bounds<crate::Pixels>,
|
||||
element: &mut Self::RequestLayoutState,
|
||||
_: &mut Self::PrepaintState,
|
||||
cx: &mut WindowContext,
|
||||
cx: &mut crate::WindowContext,
|
||||
) {
|
||||
element.paint(cx);
|
||||
}
|
||||
|
||||
@@ -1417,19 +1417,6 @@ impl Interactivity {
|
||||
None
|
||||
};
|
||||
|
||||
let invalidate_tooltip = hitbox
|
||||
.as_ref()
|
||||
.map_or(true, |hitbox| !hitbox.bounds.contains(&cx.mouse_position()));
|
||||
if invalidate_tooltip {
|
||||
if let Some(active_tooltip) = element_state
|
||||
.as_ref()
|
||||
.and_then(|state| state.active_tooltip.as_ref())
|
||||
{
|
||||
*active_tooltip.borrow_mut() = None;
|
||||
self.tooltip_id = None;
|
||||
}
|
||||
}
|
||||
|
||||
let scroll_offset = self.clamp_scroll_position(bounds, &style, cx);
|
||||
let result = f(&style, scroll_offset, hitbox, cx);
|
||||
(result, element_state)
|
||||
@@ -2512,7 +2499,7 @@ impl ScrollAnchor {
|
||||
}
|
||||
}
|
||||
/// Request scroll to this item on the next frame.
|
||||
pub fn scroll_to(&self, cx: &mut WindowContext) {
|
||||
pub fn scroll_to(&self, cx: &mut WindowContext<'_>) {
|
||||
let this = self.clone();
|
||||
|
||||
cx.on_next_frame(move |_| {
|
||||
|
||||
@@ -716,7 +716,7 @@ impl Element for List {
|
||||
fn request_layout(
|
||||
&mut self,
|
||||
_id: Option<&GlobalElementId>,
|
||||
cx: &mut WindowContext,
|
||||
cx: &mut crate::WindowContext,
|
||||
) -> (crate::LayoutId, Self::RequestLayoutState) {
|
||||
let layout_id = match self.sizing_behavior {
|
||||
ListSizingBehavior::Infer => {
|
||||
@@ -827,7 +827,7 @@ impl Element for List {
|
||||
bounds: Bounds<crate::Pixels>,
|
||||
_: &mut Self::RequestLayoutState,
|
||||
prepaint: &mut Self::PrepaintState,
|
||||
cx: &mut WindowContext,
|
||||
cx: &mut crate::WindowContext,
|
||||
) {
|
||||
cx.with_content_mask(Some(ContentMask { bounds }), |cx| {
|
||||
for item in &mut prepaint.layout.item_layouts {
|
||||
|
||||
@@ -472,9 +472,9 @@ pub struct InteractiveText {
|
||||
element_id: ElementId,
|
||||
text: StyledText,
|
||||
click_listener:
|
||||
Option<Box<dyn Fn(&[Range<usize>], InteractiveTextClickEvent, &mut WindowContext)>>,
|
||||
hover_listener: Option<Box<dyn Fn(Option<usize>, MouseMoveEvent, &mut WindowContext)>>,
|
||||
tooltip_builder: Option<Rc<dyn Fn(usize, &mut WindowContext) -> Option<AnyView>>>,
|
||||
Option<Box<dyn Fn(&[Range<usize>], InteractiveTextClickEvent, &mut WindowContext<'_>)>>,
|
||||
hover_listener: Option<Box<dyn Fn(Option<usize>, MouseMoveEvent, &mut WindowContext<'_>)>>,
|
||||
tooltip_builder: Option<Rc<dyn Fn(usize, &mut WindowContext<'_>) -> Option<AnyView>>>,
|
||||
clickable_ranges: Vec<Range<usize>>,
|
||||
}
|
||||
|
||||
@@ -510,7 +510,7 @@ impl InteractiveText {
|
||||
pub fn on_click(
|
||||
mut self,
|
||||
ranges: Vec<Range<usize>>,
|
||||
listener: impl Fn(usize, &mut WindowContext) + 'static,
|
||||
listener: impl Fn(usize, &mut WindowContext<'_>) + 'static,
|
||||
) -> Self {
|
||||
self.click_listener = Some(Box::new(move |ranges, event, cx| {
|
||||
for (range_ix, range) in ranges.iter().enumerate() {
|
||||
@@ -528,7 +528,7 @@ impl InteractiveText {
|
||||
/// index of the hovered character, or None if the mouse leaves the text.
|
||||
pub fn on_hover(
|
||||
mut self,
|
||||
listener: impl Fn(Option<usize>, MouseMoveEvent, &mut WindowContext) + 'static,
|
||||
listener: impl Fn(Option<usize>, MouseMoveEvent, &mut WindowContext<'_>) + 'static,
|
||||
) -> Self {
|
||||
self.hover_listener = Some(Box::new(listener));
|
||||
self
|
||||
@@ -537,7 +537,7 @@ impl InteractiveText {
|
||||
/// tooltip lets you specify a tooltip for a given character index in the string.
|
||||
pub fn tooltip(
|
||||
mut self,
|
||||
builder: impl Fn(usize, &mut WindowContext) -> Option<AnyView> + 'static,
|
||||
builder: impl Fn(usize, &mut WindowContext<'_>) -> Option<AnyView> + 'static,
|
||||
) -> Self {
|
||||
self.tooltip_builder = Some(Rc::new(builder));
|
||||
self
|
||||
|
||||
@@ -202,7 +202,7 @@ pub trait Context {
|
||||
/// Update a window for the given handle.
|
||||
fn update_window<T, F>(&mut self, window: AnyWindowHandle, f: F) -> Result<T>
|
||||
where
|
||||
F: FnOnce(AnyView, &mut WindowContext) -> T;
|
||||
F: FnOnce(AnyView, &mut WindowContext<'_>) -> T;
|
||||
|
||||
/// Read a window off of the application context.
|
||||
fn read_window<T, R>(
|
||||
@@ -231,7 +231,7 @@ pub trait VisualContext: Context {
|
||||
/// Construct a new view in the window referenced by this context.
|
||||
fn new_view<V>(
|
||||
&mut self,
|
||||
build_view: impl FnOnce(&mut ViewContext<V>) -> V,
|
||||
build_view: impl FnOnce(&mut ViewContext<'_, V>) -> V,
|
||||
) -> Self::Result<View<V>>
|
||||
where
|
||||
V: 'static + Render;
|
||||
@@ -240,13 +240,13 @@ pub trait VisualContext: Context {
|
||||
fn update_view<V: 'static, R>(
|
||||
&mut self,
|
||||
view: &View<V>,
|
||||
update: impl FnOnce(&mut V, &mut ViewContext<V>) -> R,
|
||||
update: impl FnOnce(&mut V, &mut ViewContext<'_, V>) -> R,
|
||||
) -> Self::Result<R>;
|
||||
|
||||
/// Replace the root view of a window with a new view.
|
||||
fn replace_root_view<V>(
|
||||
&mut self,
|
||||
build_view: impl FnOnce(&mut ViewContext<V>) -> V,
|
||||
build_view: impl FnOnce(&mut ViewContext<'_, V>) -> V,
|
||||
) -> Self::Result<View<V>>
|
||||
where
|
||||
V: 'static + Render;
|
||||
|
||||
@@ -468,7 +468,7 @@ mod test {
|
||||
|
||||
use crate::{
|
||||
self as gpui, div, FocusHandle, InteractiveElement, IntoElement, KeyBinding, Keystroke,
|
||||
ParentElement, Render, TestAppContext, ViewContext, VisualContext,
|
||||
ParentElement, Render, TestAppContext, VisualContext,
|
||||
};
|
||||
|
||||
struct TestView {
|
||||
@@ -480,7 +480,7 @@ mod test {
|
||||
actions!(test, [TestAction]);
|
||||
|
||||
impl Render for TestView {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl IntoElement {
|
||||
div().id("testview").child(
|
||||
div()
|
||||
.key_context("parent")
|
||||
|
||||
@@ -214,7 +214,6 @@ impl BladeAtlasState {
|
||||
},
|
||||
array_layer_count: 1,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: gpu::TextureDimension::D2,
|
||||
usage,
|
||||
});
|
||||
|
||||
@@ -174,9 +174,8 @@ impl BladePipelines {
|
||||
..Default::default()
|
||||
},
|
||||
depth_stencil: None,
|
||||
fragment: Some(shader.at("fs_quad")),
|
||||
fragment: shader.at("fs_quad"),
|
||||
color_targets,
|
||||
multisample_state: gpu::MultisampleState::default(),
|
||||
}),
|
||||
shadows: gpu.create_render_pipeline(gpu::RenderPipelineDesc {
|
||||
name: "shadows",
|
||||
@@ -188,9 +187,8 @@ impl BladePipelines {
|
||||
..Default::default()
|
||||
},
|
||||
depth_stencil: None,
|
||||
fragment: Some(shader.at("fs_shadow")),
|
||||
fragment: shader.at("fs_shadow"),
|
||||
color_targets,
|
||||
multisample_state: gpu::MultisampleState::default(),
|
||||
}),
|
||||
path_rasterization: gpu.create_render_pipeline(gpu::RenderPipelineDesc {
|
||||
name: "path_rasterization",
|
||||
@@ -202,13 +200,12 @@ impl BladePipelines {
|
||||
..Default::default()
|
||||
},
|
||||
depth_stencil: None,
|
||||
fragment: Some(shader.at("fs_path_rasterization")),
|
||||
fragment: shader.at("fs_path_rasterization"),
|
||||
color_targets: &[gpu::ColorTargetState {
|
||||
format: PATH_TEXTURE_FORMAT,
|
||||
blend: Some(gpu::BlendState::ADDITIVE),
|
||||
write_mask: gpu::ColorWrites::default(),
|
||||
}],
|
||||
multisample_state: gpu::MultisampleState::default(),
|
||||
}),
|
||||
paths: gpu.create_render_pipeline(gpu::RenderPipelineDesc {
|
||||
name: "paths",
|
||||
@@ -220,9 +217,8 @@ impl BladePipelines {
|
||||
..Default::default()
|
||||
},
|
||||
depth_stencil: None,
|
||||
fragment: Some(shader.at("fs_path")),
|
||||
fragment: shader.at("fs_path"),
|
||||
color_targets,
|
||||
multisample_state: gpu::MultisampleState::default(),
|
||||
}),
|
||||
underlines: gpu.create_render_pipeline(gpu::RenderPipelineDesc {
|
||||
name: "underlines",
|
||||
@@ -234,9 +230,8 @@ impl BladePipelines {
|
||||
..Default::default()
|
||||
},
|
||||
depth_stencil: None,
|
||||
fragment: Some(shader.at("fs_underline")),
|
||||
fragment: shader.at("fs_underline"),
|
||||
color_targets,
|
||||
multisample_state: gpu::MultisampleState::default(),
|
||||
}),
|
||||
mono_sprites: gpu.create_render_pipeline(gpu::RenderPipelineDesc {
|
||||
name: "mono-sprites",
|
||||
@@ -248,9 +243,8 @@ impl BladePipelines {
|
||||
..Default::default()
|
||||
},
|
||||
depth_stencil: None,
|
||||
fragment: Some(shader.at("fs_mono_sprite")),
|
||||
fragment: shader.at("fs_mono_sprite"),
|
||||
color_targets,
|
||||
multisample_state: gpu::MultisampleState::default(),
|
||||
}),
|
||||
poly_sprites: gpu.create_render_pipeline(gpu::RenderPipelineDesc {
|
||||
name: "poly-sprites",
|
||||
@@ -262,9 +256,8 @@ impl BladePipelines {
|
||||
..Default::default()
|
||||
},
|
||||
depth_stencil: None,
|
||||
fragment: Some(shader.at("fs_poly_sprite")),
|
||||
fragment: shader.at("fs_poly_sprite"),
|
||||
color_targets,
|
||||
multisample_state: gpu::MultisampleState::default(),
|
||||
}),
|
||||
surfaces: gpu.create_render_pipeline(gpu::RenderPipelineDesc {
|
||||
name: "surfaces",
|
||||
@@ -276,9 +269,8 @@ impl BladePipelines {
|
||||
..Default::default()
|
||||
},
|
||||
depth_stencil: None,
|
||||
fragment: Some(shader.at("fs_surface")),
|
||||
fragment: shader.at("fs_surface"),
|
||||
color_targets,
|
||||
multisample_state: gpu::MultisampleState::default(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
@@ -358,10 +350,8 @@ impl BladeRenderer {
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
let core_video_texture_cache = unsafe {
|
||||
CVMetalTextureCache::new(
|
||||
objc2::rc::Retained::as_ptr(&context.gpu.metal_device()) as *mut _
|
||||
)
|
||||
.unwrap()
|
||||
use foreign_types::ForeignType as _;
|
||||
CVMetalTextureCache::new(context.gpu.metal_device().as_ptr()).unwrap()
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
@@ -450,12 +440,13 @@ impl BladeRenderer {
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub fn layer(&self) -> metal::MetalLayer {
|
||||
unsafe { foreign_types::ForeignType::from_ptr(self.layer_ptr()) }
|
||||
self.surface.metal_layer()
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub fn layer_ptr(&self) -> *mut metal::CAMetalLayer {
|
||||
objc2::rc::Retained::as_ptr(&self.surface.metal_layer()) as *mut _
|
||||
use metal::foreign_types::ForeignType as _;
|
||||
self.surface.metal_layer().as_ptr()
|
||||
}
|
||||
|
||||
#[profiling::function]
|
||||
@@ -687,59 +678,45 @@ impl BladeRenderer {
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
let (t_y, t_cb_cr) = unsafe {
|
||||
let (t_y, t_cb_cr) = {
|
||||
use core_foundation::base::TCFType as _;
|
||||
use std::ptr;
|
||||
|
||||
assert_eq!(
|
||||
surface.image_buffer.pixel_format_type(),
|
||||
media::core_video::kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
|
||||
);
|
||||
surface.image_buffer.pixel_format_type(),
|
||||
media::core_video::kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
|
||||
);
|
||||
|
||||
let y_texture = self
|
||||
.core_video_texture_cache
|
||||
.create_texture_from_image(
|
||||
surface.image_buffer.as_concrete_TypeRef(),
|
||||
ptr::null(),
|
||||
metal::MTLPixelFormat::R8Unorm,
|
||||
surface.image_buffer.plane_width(0),
|
||||
surface.image_buffer.plane_height(0),
|
||||
0,
|
||||
)
|
||||
.unwrap();
|
||||
let cb_cr_texture = self
|
||||
.core_video_texture_cache
|
||||
.create_texture_from_image(
|
||||
surface.image_buffer.as_concrete_TypeRef(),
|
||||
ptr::null(),
|
||||
metal::MTLPixelFormat::RG8Unorm,
|
||||
surface.image_buffer.plane_width(1),
|
||||
surface.image_buffer.plane_height(1),
|
||||
1,
|
||||
)
|
||||
.unwrap();
|
||||
let y_texture = unsafe {
|
||||
self.core_video_texture_cache
|
||||
.create_texture_from_image(
|
||||
surface.image_buffer.as_concrete_TypeRef(),
|
||||
ptr::null(),
|
||||
metal::MTLPixelFormat::R8Unorm,
|
||||
surface.image_buffer.plane_width(0),
|
||||
surface.image_buffer.plane_height(0),
|
||||
0,
|
||||
)
|
||||
.unwrap()
|
||||
};
|
||||
let cb_cr_texture = unsafe {
|
||||
self.core_video_texture_cache
|
||||
.create_texture_from_image(
|
||||
surface.image_buffer.as_concrete_TypeRef(),
|
||||
ptr::null(),
|
||||
metal::MTLPixelFormat::RG8Unorm,
|
||||
surface.image_buffer.plane_width(1),
|
||||
surface.image_buffer.plane_height(1),
|
||||
1,
|
||||
)
|
||||
.unwrap()
|
||||
};
|
||||
(
|
||||
gpu::TextureView::from_metal_texture(
|
||||
&objc2::rc::Retained::retain(
|
||||
foreign_types::ForeignTypeRef::as_ptr(
|
||||
y_texture.as_texture_ref(),
|
||||
)
|
||||
as *mut objc2::runtime::ProtocolObject<
|
||||
dyn objc2_metal::MTLTexture,
|
||||
>,
|
||||
)
|
||||
.unwrap(),
|
||||
y_texture.as_texture_ref(),
|
||||
),
|
||||
gpu::TextureView::from_metal_texture(
|
||||
&objc2::rc::Retained::retain(
|
||||
foreign_types::ForeignTypeRef::as_ptr(
|
||||
cb_cr_texture.as_texture_ref(),
|
||||
)
|
||||
as *mut objc2::runtime::ProtocolObject<
|
||||
dyn objc2_metal::MTLTexture,
|
||||
>,
|
||||
)
|
||||
.unwrap(),
|
||||
cb_cr_texture.as_texture_ref(),
|
||||
),
|
||||
)
|
||||
};
|
||||
|
||||
@@ -146,18 +146,19 @@ fn handle_size_msg(
|
||||
// Don't resize the renderer when the window is minimized, but record that it was minimized so
|
||||
// that on restore the swap chain can be recreated via `update_drawable_size_even_if_unchanged`.
|
||||
if wparam.0 == SIZE_MINIMIZED as usize {
|
||||
lock.restore_from_minimized = lock.callbacks.request_frame.take();
|
||||
lock.is_minimized = Some(true);
|
||||
return Some(0);
|
||||
}
|
||||
let may_have_been_minimized = lock.is_minimized.unwrap_or(true);
|
||||
lock.is_minimized = Some(false);
|
||||
|
||||
let width = lparam.loword().max(1) as i32;
|
||||
let height = lparam.hiword().max(1) as i32;
|
||||
let new_size = size(DevicePixels(width), DevicePixels(height));
|
||||
let scale_factor = lock.scale_factor;
|
||||
if lock.restore_from_minimized.is_some() {
|
||||
if may_have_been_minimized {
|
||||
lock.renderer
|
||||
.update_drawable_size_even_if_unchanged(new_size);
|
||||
lock.callbacks.request_frame = lock.restore_from_minimized.take();
|
||||
} else {
|
||||
lock.renderer.update_drawable_size(new_size);
|
||||
}
|
||||
|
||||
@@ -48,7 +48,6 @@ pub(crate) struct WindowsPlatform {
|
||||
|
||||
pub(crate) struct WindowsPlatformState {
|
||||
callbacks: PlatformCallbacks,
|
||||
menus: Vec<OwnedMenu>,
|
||||
// NOTE: standard cursor handles don't need to close.
|
||||
pub(crate) current_cursor: HCURSOR,
|
||||
}
|
||||
@@ -71,7 +70,6 @@ impl WindowsPlatformState {
|
||||
Self {
|
||||
callbacks,
|
||||
current_cursor,
|
||||
menus: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -451,15 +449,8 @@ impl Platform for WindowsPlatform {
|
||||
self.state.borrow_mut().callbacks.reopen = Some(callback);
|
||||
}
|
||||
|
||||
fn set_menus(&self, menus: Vec<Menu>, _keymap: &Keymap) {
|
||||
self.state.borrow_mut().menus = menus.into_iter().map(|menu| menu.owned()).collect();
|
||||
}
|
||||
|
||||
fn get_menus(&self) -> Option<Vec<OwnedMenu>> {
|
||||
Some(self.state.borrow().menus.clone())
|
||||
}
|
||||
|
||||
// todo(windows)
|
||||
fn set_menus(&self, _menus: Vec<Menu>, _keymap: &Keymap) {}
|
||||
fn set_dock_menu(&self, _menus: Vec<MenuItem>, _keymap: &Keymap) {}
|
||||
|
||||
fn on_app_menu_action(&self, callback: Box<dyn FnMut(&dyn Action)>) {
|
||||
|
||||
@@ -38,7 +38,7 @@ pub struct WindowsWindowState {
|
||||
pub fullscreen_restore_bounds: Bounds<Pixels>,
|
||||
pub border_offset: WindowBorderOffset,
|
||||
pub scale_factor: f32,
|
||||
pub restore_from_minimized: Option<Box<dyn FnMut(RequestFrameOptions)>>,
|
||||
pub is_minimized: Option<bool>,
|
||||
|
||||
pub callbacks: Callbacks,
|
||||
pub input_handler: Option<PlatformInputHandler>,
|
||||
@@ -94,7 +94,7 @@ impl WindowsWindowState {
|
||||
size: logical_size,
|
||||
};
|
||||
let border_offset = WindowBorderOffset::default();
|
||||
let restore_from_minimized = None;
|
||||
let is_minimized = None;
|
||||
let renderer = windows_renderer::init(gpu_context, hwnd, transparent)?;
|
||||
let callbacks = Callbacks::default();
|
||||
let input_handler = None;
|
||||
@@ -112,7 +112,7 @@ impl WindowsWindowState {
|
||||
fullscreen_restore_bounds,
|
||||
border_offset,
|
||||
scale_factor,
|
||||
restore_from_minimized,
|
||||
is_minimized,
|
||||
callbacks,
|
||||
input_handler,
|
||||
system_key_handled,
|
||||
|
||||
@@ -385,20 +385,28 @@ impl LineLayoutCache {
|
||||
let mut previous_frame = &mut *self.previous_frame.lock();
|
||||
let mut current_frame = &mut *self.current_frame.write();
|
||||
|
||||
for key in &previous_frame.used_lines[range.start.lines_index..range.end.lines_index] {
|
||||
if let Some((key, line)) = previous_frame.lines.remove_entry(key) {
|
||||
current_frame.lines.insert(key, line);
|
||||
if let Some(cached_keys) = previous_frame
|
||||
.used_lines
|
||||
.get(range.start.lines_index..range.end.lines_index)
|
||||
{
|
||||
for key in cached_keys {
|
||||
if let Some((key, line)) = previous_frame.lines.remove_entry(key) {
|
||||
current_frame.lines.insert(key, line);
|
||||
}
|
||||
current_frame.used_lines.push(key.clone());
|
||||
}
|
||||
current_frame.used_lines.push(key.clone());
|
||||
}
|
||||
|
||||
for key in &previous_frame.used_wrapped_lines
|
||||
[range.start.wrapped_lines_index..range.end.wrapped_lines_index]
|
||||
if let Some(cached_keys) = previous_frame
|
||||
.used_wrapped_lines
|
||||
.get(range.start.wrapped_lines_index..range.end.wrapped_lines_index)
|
||||
{
|
||||
if let Some((key, line)) = previous_frame.wrapped_lines.remove_entry(key) {
|
||||
current_frame.wrapped_lines.insert(key, line);
|
||||
for key in cached_keys {
|
||||
if let Some((key, line)) = previous_frame.wrapped_lines.remove_entry(key) {
|
||||
current_frame.wrapped_lines.insert(key, line);
|
||||
}
|
||||
current_frame.used_wrapped_lines.push(key.clone());
|
||||
}
|
||||
current_frame.used_wrapped_lines.push(key.clone());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ impl<V: 'static> View<V> {
|
||||
pub fn update<C, R>(
|
||||
&self,
|
||||
cx: &mut C,
|
||||
f: impl FnOnce(&mut V, &mut ViewContext<V>) -> R,
|
||||
f: impl FnOnce(&mut V, &mut ViewContext<'_, V>) -> R,
|
||||
) -> C::Result<R>
|
||||
where
|
||||
C: VisualContext,
|
||||
@@ -183,7 +183,7 @@ impl<V: 'static> WeakView<V> {
|
||||
pub fn update<C, R>(
|
||||
&self,
|
||||
cx: &mut C,
|
||||
f: impl FnOnce(&mut V, &mut ViewContext<V>) -> R,
|
||||
f: impl FnOnce(&mut V, &mut ViewContext<'_, V>) -> R,
|
||||
) -> Result<R>
|
||||
where
|
||||
C: VisualContext,
|
||||
|
||||
@@ -1753,12 +1753,17 @@ impl<'a> WindowContext<'a> {
|
||||
.iter_mut()
|
||||
.map(|listener| listener.take()),
|
||||
);
|
||||
window.next_frame.accessed_element_states.extend(
|
||||
window.rendered_frame.accessed_element_states[range.start.accessed_element_states_index
|
||||
..range.end.accessed_element_states_index]
|
||||
.iter()
|
||||
.map(|(id, type_id)| (GlobalElementId(id.0.clone()), *type_id)),
|
||||
);
|
||||
if let Some(element_states) = window
|
||||
.rendered_frame
|
||||
.accessed_element_states
|
||||
.get(range.start.accessed_element_states_index..range.end.accessed_element_states_index)
|
||||
{
|
||||
window.next_frame.accessed_element_states.extend(
|
||||
element_states
|
||||
.iter()
|
||||
.map(|(id, type_id)| (GlobalElementId(id.0.clone()), *type_id)),
|
||||
);
|
||||
}
|
||||
|
||||
window
|
||||
.text_system
|
||||
|
||||
@@ -11,7 +11,7 @@ pub fn derive_render(input: TokenStream) -> TokenStream {
|
||||
impl #impl_generics gpui::Render for #type_name #type_generics
|
||||
#where_clause
|
||||
{
|
||||
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl gpui::Element {
|
||||
fn render(&mut self, _cx: &mut gpui::ViewContext<Self>) -> impl gpui::Element {
|
||||
gpui::Empty
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,11 +4,12 @@ use crate::{
|
||||
LanguageModelProviderState, LanguageModelRequest,
|
||||
};
|
||||
use futures::{channel::mpsc, future::BoxFuture, stream::BoxStream, FutureExt, StreamExt};
|
||||
use gpui::{AnyView, AppContext, AsyncAppContext, Model, Task, WindowContext};
|
||||
use gpui::{AnyView, AppContext, AsyncAppContext, Task};
|
||||
use http_client::Result;
|
||||
use parking_lot::Mutex;
|
||||
use serde::Serialize;
|
||||
use std::sync::Arc;
|
||||
use ui::WindowContext;
|
||||
|
||||
pub fn language_model_id() -> LanguageModelId {
|
||||
LanguageModelId::from("fake".to_string())
|
||||
@@ -32,7 +33,7 @@ pub struct FakeLanguageModelProvider;
|
||||
impl LanguageModelProviderState for FakeLanguageModelProvider {
|
||||
type ObservableEntity = ();
|
||||
|
||||
fn observable_entity(&self) -> Option<Model<Self::ObservableEntity>> {
|
||||
fn observable_entity(&self) -> Option<gpui::Model<Self::ObservableEntity>> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
@@ -703,11 +703,15 @@ impl LspLogView {
|
||||
});
|
||||
let editor_subscription = cx.subscribe(
|
||||
&editor,
|
||||
|_, _, event: &EditorEvent, cx: &mut ViewContext<LspLogView>| cx.emit(event.clone()),
|
||||
|_, _, event: &EditorEvent, cx: &mut ViewContext<'_, LspLogView>| {
|
||||
cx.emit(event.clone())
|
||||
},
|
||||
);
|
||||
let search_subscription = cx.subscribe(
|
||||
&editor,
|
||||
|_, _, event: &SearchEvent, cx: &mut ViewContext<LspLogView>| cx.emit(event.clone()),
|
||||
|_, _, event: &SearchEvent, cx: &mut ViewContext<'_, LspLogView>| {
|
||||
cx.emit(event.clone())
|
||||
},
|
||||
);
|
||||
(editor, vec![editor_subscription, search_subscription])
|
||||
}
|
||||
@@ -726,11 +730,15 @@ impl LspLogView {
|
||||
});
|
||||
let editor_subscription = cx.subscribe(
|
||||
&editor,
|
||||
|_, _, event: &EditorEvent, cx: &mut ViewContext<LspLogView>| cx.emit(event.clone()),
|
||||
|_, _, event: &EditorEvent, cx: &mut ViewContext<'_, LspLogView>| {
|
||||
cx.emit(event.clone())
|
||||
},
|
||||
);
|
||||
let search_subscription = cx.subscribe(
|
||||
&editor,
|
||||
|_, _, event: &SearchEvent, cx: &mut ViewContext<LspLogView>| cx.emit(event.clone()),
|
||||
|_, _, event: &SearchEvent, cx: &mut ViewContext<'_, LspLogView>| {
|
||||
cx.emit(event.clone())
|
||||
},
|
||||
);
|
||||
(editor, vec![editor_subscription, search_subscription])
|
||||
}
|
||||
|
||||
@@ -273,7 +273,7 @@ impl SyntaxTreeView {
|
||||
}
|
||||
|
||||
impl Render for SyntaxTreeView {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, cx: &mut gpui::ViewContext<'_, Self>) -> impl IntoElement {
|
||||
let mut rendered = div().flex_1();
|
||||
|
||||
if let Some(layer) = self
|
||||
@@ -422,7 +422,7 @@ impl SyntaxTreeToolbarItemView {
|
||||
}
|
||||
}
|
||||
|
||||
fn render_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<PopoverMenu<ContextMenu>> {
|
||||
fn render_menu(&mut self, cx: &mut ViewContext<'_, Self>) -> Option<PopoverMenu<ContextMenu>> {
|
||||
let tree_view = self.tree_view.as_ref()?;
|
||||
let tree_view = tree_view.read(cx);
|
||||
|
||||
@@ -492,7 +492,7 @@ fn format_node_range(node: Node) -> String {
|
||||
}
|
||||
|
||||
impl Render for SyntaxTreeToolbarItemView {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, cx: &mut ViewContext<'_, Self>) -> impl IntoElement {
|
||||
self.render_menu(cx)
|
||||
.unwrap_or_else(|| PopoverMenu::new("Empty Syntax Tree"))
|
||||
}
|
||||
|
||||
@@ -194,7 +194,6 @@
|
||||
"throw"
|
||||
"try"
|
||||
"typeof"
|
||||
"using"
|
||||
"var"
|
||||
"void"
|
||||
"while"
|
||||
|
||||
@@ -284,7 +284,6 @@ impl<F: Future> LspRequestFuture<F::Output> for LspRequest<F> {
|
||||
}
|
||||
|
||||
/// Combined capabilities of the server and the adapter.
|
||||
#[derive(Debug)]
|
||||
pub struct AdapterServerCapabilities {
|
||||
// Reported capabilities by the server
|
||||
pub server_capabilities: ServerCapabilities,
|
||||
|
||||
@@ -614,11 +614,11 @@ impl Element for MarkdownElement {
|
||||
};
|
||||
builder.push_div(
|
||||
div()
|
||||
.mb_1()
|
||||
.h_flex()
|
||||
.mb_2()
|
||||
.line_height(rems(1.3))
|
||||
.items_start()
|
||||
.gap_1()
|
||||
.line_height(rems(1.3))
|
||||
.child(bullet),
|
||||
range,
|
||||
markdown_end,
|
||||
|
||||
@@ -3449,24 +3449,6 @@ impl MultiBufferSnapshot {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn buffer_ids_in_selected_rows(
|
||||
&self,
|
||||
selection: Selection<Point>,
|
||||
) -> impl Iterator<Item = BufferId> + '_ {
|
||||
let mut cursor = self.excerpts.cursor::<Point>(&());
|
||||
cursor.seek(&Point::new(selection.start.row, 0), Bias::Right, &());
|
||||
cursor.prev(&());
|
||||
|
||||
iter::from_fn(move || {
|
||||
cursor.next(&());
|
||||
if cursor.start().row <= selection.end.row {
|
||||
cursor.item().map(|item| item.buffer_id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn excerpts(
|
||||
&self,
|
||||
) -> impl Iterator<Item = (ExcerptId, &BufferSnapshot, ExcerptRange<text::Anchor>)> {
|
||||
|
||||
@@ -25,7 +25,6 @@ theme.workspace = true
|
||||
ui.workspace = true
|
||||
util.workspace = true
|
||||
workspace.workspace = true
|
||||
zed_actions.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
editor = { workspace = true, features = ["test-support"] }
|
||||
|
||||
@@ -4,7 +4,9 @@ use std::{
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use editor::{scroll::Autoscroll, Anchor, AnchorRangeExt, Editor, EditorMode};
|
||||
use editor::{
|
||||
actions::ToggleOutline, scroll::Autoscroll, Anchor, AnchorRangeExt, Editor, EditorMode,
|
||||
};
|
||||
use fuzzy::StringMatch;
|
||||
use gpui::{
|
||||
div, rems, AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView, HighlightStyle,
|
||||
@@ -22,22 +24,9 @@ use workspace::{DismissDecision, ModalView};
|
||||
|
||||
pub fn init(cx: &mut AppContext) {
|
||||
cx.observe_new_views(OutlineView::register).detach();
|
||||
zed_actions::outline::TOGGLE_OUTLINE
|
||||
.set(|view, cx| {
|
||||
let Ok(view) = view.downcast::<Editor>() else {
|
||||
return;
|
||||
};
|
||||
|
||||
toggle(view, &Default::default(), cx);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
|
||||
pub fn toggle(
|
||||
editor: View<Editor>,
|
||||
_: &zed_actions::outline::ToggleOutline,
|
||||
cx: &mut WindowContext,
|
||||
) {
|
||||
pub fn toggle(editor: View<Editor>, _: &ToggleOutline, cx: &mut WindowContext) {
|
||||
let outline = editor
|
||||
.read(cx)
|
||||
.buffer()
|
||||
@@ -470,7 +459,7 @@ mod tests {
|
||||
workspace: &View<Workspace>,
|
||||
cx: &mut VisualTestContext,
|
||||
) -> View<Picker<OutlineViewDelegate>> {
|
||||
cx.dispatch_action(zed_actions::outline::ToggleOutline);
|
||||
cx.dispatch_action(ToggleOutline);
|
||||
workspace.update(cx, |workspace, cx| {
|
||||
workspace
|
||||
.active_modal::<OutlineView>(cx)
|
||||
|
||||
@@ -149,7 +149,7 @@ impl SearchState {
|
||||
previous_matches: HashMap<Range<editor::Anchor>, Arc<OnceLock<SearchData>>>,
|
||||
new_matches: Vec<Range<editor::Anchor>>,
|
||||
theme: Arc<SyntaxTheme>,
|
||||
cx: &mut ViewContext<OutlinePanel>,
|
||||
cx: &mut ViewContext<'_, OutlinePanel>,
|
||||
) -> Self {
|
||||
let (highlight_search_match_tx, highlight_search_match_rx) = channel::unbounded();
|
||||
let (notify_tx, notify_rx) = channel::unbounded::<()>();
|
||||
@@ -1661,7 +1661,7 @@ impl OutlinePanel {
|
||||
}
|
||||
}
|
||||
|
||||
fn reveal_entry_for_selection(&mut self, editor: View<Editor>, cx: &mut ViewContext<Self>) {
|
||||
fn reveal_entry_for_selection(&mut self, editor: View<Editor>, cx: &mut ViewContext<'_, Self>) {
|
||||
if !self.active || !OutlinePanelSettings::get_global(cx).auto_reveal_entries {
|
||||
return;
|
||||
}
|
||||
@@ -2656,7 +2656,7 @@ impl OutlinePanel {
|
||||
self.clear_previous(cx);
|
||||
let buffer_search_subscription = cx.subscribe(
|
||||
&new_active_editor,
|
||||
|outline_panel: &mut Self, _, e: &SearchEvent, cx: &mut ViewContext<Self>| {
|
||||
|outline_panel: &mut Self, _, e: &SearchEvent, cx: &mut ViewContext<'_, Self>| {
|
||||
if matches!(e, SearchEvent::MatchesInvalidated) {
|
||||
outline_panel.update_search_matches(cx);
|
||||
};
|
||||
@@ -2675,7 +2675,7 @@ impl OutlinePanel {
|
||||
self.update_fs_entries(new_active_editor, None, cx);
|
||||
}
|
||||
|
||||
fn clear_previous(&mut self, cx: &mut WindowContext) {
|
||||
fn clear_previous(&mut self, cx: &mut WindowContext<'_>) {
|
||||
self.fs_entries_update_task = Task::ready(());
|
||||
self.outline_fetch_tasks.clear();
|
||||
self.cached_entries_update_task = Task::ready(());
|
||||
@@ -3124,7 +3124,7 @@ impl OutlinePanel {
|
||||
&self,
|
||||
is_singleton: bool,
|
||||
query: Option<String>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
cx: &mut ViewContext<'_, Self>,
|
||||
) -> Task<(Vec<CachedEntry>, Option<usize>)> {
|
||||
let project = self.project.clone();
|
||||
let Some(active_editor) = self.active_editor() else {
|
||||
@@ -4078,7 +4078,7 @@ impl OutlinePanel {
|
||||
query: Option<String>,
|
||||
show_indent_guides: bool,
|
||||
indent_size: f32,
|
||||
cx: &mut ViewContext<Self>,
|
||||
cx: &mut ViewContext<'_, Self>,
|
||||
) -> Div {
|
||||
let contents = if self.cached_entries.is_empty() {
|
||||
let header = if self.updating_fs_entries {
|
||||
@@ -4266,7 +4266,7 @@ impl OutlinePanel {
|
||||
v_flex().w_full().flex_1().overflow_hidden().child(contents)
|
||||
}
|
||||
|
||||
fn render_filter_footer(&mut self, pinned: bool, cx: &mut ViewContext<Self>) -> Div {
|
||||
fn render_filter_footer(&mut self, pinned: bool, cx: &mut ViewContext<'_, Self>) -> Div {
|
||||
v_flex().flex_none().child(horizontal_separator(cx)).child(
|
||||
h_flex()
|
||||
.p_2()
|
||||
@@ -4468,10 +4468,6 @@ impl Panel for OutlinePanel {
|
||||
})
|
||||
.detach()
|
||||
}
|
||||
|
||||
fn activation_priority(&self) -> u32 {
|
||||
5
|
||||
}
|
||||
}
|
||||
|
||||
impl FocusableView for OutlinePanel {
|
||||
|
||||
@@ -16,7 +16,7 @@ pub(crate) enum Head {
|
||||
impl Head {
|
||||
pub fn editor<V: 'static>(
|
||||
placeholder_text: Arc<str>,
|
||||
edit_handler: impl FnMut(&mut V, View<Editor>, &EditorEvent, &mut ViewContext<V>) + 'static,
|
||||
edit_handler: impl FnMut(&mut V, View<Editor>, &EditorEvent, &mut ViewContext<'_, V>) + 'static,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> Self {
|
||||
let editor = cx.new_view(|cx| {
|
||||
@@ -29,7 +29,7 @@ impl Head {
|
||||
}
|
||||
|
||||
pub fn empty<V: 'static>(
|
||||
blur_handler: impl FnMut(&mut V, &mut ViewContext<V>) + 'static,
|
||||
blur_handler: impl FnMut(&mut V, &mut ViewContext<'_, V>) + 'static,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> Self {
|
||||
let head = cx.new_view(EmptyHead::new);
|
||||
|
||||
@@ -425,7 +425,7 @@ impl<D: PickerDelegate> Picker<D> {
|
||||
self.cancel(&menu::Cancel, cx);
|
||||
}
|
||||
|
||||
pub fn refresh_placeholder(&mut self, cx: &mut WindowContext) {
|
||||
pub fn refresh_placeholder(&mut self, cx: &mut WindowContext<'_>) {
|
||||
match &self.head {
|
||||
Head::Editor(view) => {
|
||||
let placeholder = self.delegate.placeholder_text(cx);
|
||||
@@ -493,7 +493,7 @@ impl<D: PickerDelegate> Picker<D> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_query(&self, query: impl Into<Arc<str>>, cx: &mut WindowContext) {
|
||||
pub fn set_query(&self, query: impl Into<Arc<str>>, cx: &mut WindowContext<'_>) {
|
||||
if let Head::Editor(ref editor) = &self.head {
|
||||
editor.update(cx, |editor, cx| {
|
||||
editor.set_text(query, cx);
|
||||
|
||||
@@ -1918,7 +1918,6 @@ impl LspCommand for GetCompletions {
|
||||
new_text,
|
||||
server_id,
|
||||
lsp_completion,
|
||||
resolved: false,
|
||||
}
|
||||
})
|
||||
.collect())
|
||||
|
||||
@@ -2353,16 +2353,8 @@ impl LocalLspStore {
|
||||
let (mut edits, mut snippet_edits) = (vec![], vec![]);
|
||||
for edit in op.edits {
|
||||
match edit {
|
||||
Edit::Plain(edit) => {
|
||||
if !edits.contains(&edit) {
|
||||
edits.push(edit)
|
||||
}
|
||||
}
|
||||
Edit::Annotated(edit) => {
|
||||
if !edits.contains(&edit.text_edit) {
|
||||
edits.push(edit.text_edit)
|
||||
}
|
||||
}
|
||||
Edit::Plain(edit) => edits.push(edit),
|
||||
Edit::Annotated(edit) => edits.push(edit.text_edit),
|
||||
Edit::Snippet(edit) => {
|
||||
let Ok(snippet) = Snippet::parse(&edit.snippet.value)
|
||||
else {
|
||||
@@ -2373,13 +2365,10 @@ impl LocalLspStore {
|
||||
snippet_edits.push((edit.range, snippet));
|
||||
} else {
|
||||
// Since this buffer is not focused, apply a normal edit.
|
||||
let new_edit = TextEdit {
|
||||
edits.push(TextEdit {
|
||||
range: edit.range,
|
||||
new_text: snippet.text,
|
||||
};
|
||||
if !edits.contains(&new_edit) {
|
||||
edits.push(new_edit);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4163,27 +4152,38 @@ impl LspStore {
|
||||
let mut did_resolve = false;
|
||||
if let Some((client, project_id)) = client {
|
||||
for completion_index in completion_indices {
|
||||
let server_id = completions.borrow()[completion_index].server_id;
|
||||
let (server_id, completion) = {
|
||||
let completions = completions.borrow_mut();
|
||||
let completion = &completions[completion_index];
|
||||
did_resolve = true;
|
||||
let server_id = completion.server_id;
|
||||
let completion = completion.lsp_completion.clone();
|
||||
|
||||
if Self::resolve_completion_remote(
|
||||
(server_id, completion)
|
||||
};
|
||||
|
||||
Self::resolve_completion_remote(
|
||||
project_id,
|
||||
server_id,
|
||||
buffer_id,
|
||||
completions.clone(),
|
||||
completion_index,
|
||||
completion,
|
||||
client.clone(),
|
||||
language_registry.clone(),
|
||||
)
|
||||
.await
|
||||
.log_err()
|
||||
.is_some()
|
||||
{
|
||||
did_resolve = true;
|
||||
}
|
||||
.await;
|
||||
}
|
||||
} else {
|
||||
for completion_index in completion_indices {
|
||||
let server_id = completions.borrow()[completion_index].server_id;
|
||||
let (server_id, completion) = {
|
||||
let completions = completions.borrow_mut();
|
||||
let completion = &completions[completion_index];
|
||||
let server_id = completion.server_id;
|
||||
let completion = completion.lsp_completion.clone();
|
||||
|
||||
(server_id, completion)
|
||||
};
|
||||
|
||||
let server_and_adapter = this
|
||||
.read_with(&cx, |lsp_store, _| {
|
||||
@@ -4198,27 +4198,17 @@ impl LspStore {
|
||||
continue;
|
||||
};
|
||||
|
||||
let resolved = Self::resolve_completion_local(
|
||||
did_resolve = true;
|
||||
Self::resolve_completion_local(
|
||||
server,
|
||||
adapter,
|
||||
&buffer_snapshot,
|
||||
completions.clone(),
|
||||
completion_index,
|
||||
completion,
|
||||
language_registry.clone(),
|
||||
)
|
||||
.await
|
||||
.log_err()
|
||||
.is_some();
|
||||
if resolved {
|
||||
Self::regenerate_completion_labels(
|
||||
adapter,
|
||||
&buffer_snapshot,
|
||||
completions.clone(),
|
||||
completion_index,
|
||||
language_registry.clone(),
|
||||
)
|
||||
.await
|
||||
.log_err();
|
||||
did_resolve = true;
|
||||
}
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4228,10 +4218,13 @@ impl LspStore {
|
||||
|
||||
async fn resolve_completion_local(
|
||||
server: Arc<lsp::LanguageServer>,
|
||||
adapter: Arc<CachedLspAdapter>,
|
||||
snapshot: &BufferSnapshot,
|
||||
completions: Rc<RefCell<Box<[Completion]>>>,
|
||||
completion_index: usize,
|
||||
) -> Result<()> {
|
||||
completion: lsp::CompletionItem,
|
||||
language_registry: Arc<LanguageRegistry>,
|
||||
) {
|
||||
let can_resolve = server
|
||||
.capabilities()
|
||||
.completion_provider
|
||||
@@ -4239,17 +4232,30 @@ impl LspStore {
|
||||
.and_then(|options| options.resolve_provider)
|
||||
.unwrap_or(false);
|
||||
if !can_resolve {
|
||||
return Ok(());
|
||||
return;
|
||||
}
|
||||
|
||||
let request = {
|
||||
let completion = &completions.borrow()[completion_index];
|
||||
if completion.resolved {
|
||||
return Ok(());
|
||||
}
|
||||
server.request::<lsp::request::ResolveCompletionItem>(completion.lsp_completion.clone())
|
||||
let request = server.request::<lsp::request::ResolveCompletionItem>(completion);
|
||||
let Some(completion_item) = request.await.log_err() else {
|
||||
return;
|
||||
};
|
||||
let completion_item = request.await?;
|
||||
|
||||
if let Some(lsp_documentation) = completion_item.documentation.as_ref() {
|
||||
let documentation = language::prepare_completion_documentation(
|
||||
lsp_documentation,
|
||||
&language_registry,
|
||||
snapshot.language().cloned(),
|
||||
)
|
||||
.await;
|
||||
|
||||
let mut completions = completions.borrow_mut();
|
||||
let completion = &mut completions[completion_index];
|
||||
completion.documentation = Some(documentation);
|
||||
} else {
|
||||
let mut completions = completions.borrow_mut();
|
||||
let completion = &mut completions[completion_index];
|
||||
completion.documentation = Some(Documentation::Undocumented);
|
||||
}
|
||||
|
||||
if let Some(text_edit) = completion_item.text_edit.as_ref() {
|
||||
// Technically we don't have to parse the whole `text_edit`, since the only
|
||||
@@ -4277,61 +4283,28 @@ impl LspStore {
|
||||
}
|
||||
}
|
||||
|
||||
let mut completions = completions.borrow_mut();
|
||||
let completion = &mut completions[completion_index];
|
||||
completion.lsp_completion = completion_item;
|
||||
completion.resolved = true;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn regenerate_completion_labels(
|
||||
adapter: Arc<CachedLspAdapter>,
|
||||
snapshot: &BufferSnapshot,
|
||||
completions: Rc<RefCell<Box<[Completion]>>>,
|
||||
completion_index: usize,
|
||||
language_registry: Arc<LanguageRegistry>,
|
||||
) -> Result<()> {
|
||||
let completion_item = completions.borrow()[completion_index]
|
||||
.lsp_completion
|
||||
.clone();
|
||||
if let Some(lsp_documentation) = completion_item.documentation.as_ref() {
|
||||
let documentation = language::prepare_completion_documentation(
|
||||
lsp_documentation,
|
||||
&language_registry,
|
||||
snapshot.language().cloned(),
|
||||
)
|
||||
.await;
|
||||
|
||||
let mut completions = completions.borrow_mut();
|
||||
let completion = &mut completions[completion_index];
|
||||
completion.documentation = Some(documentation);
|
||||
} else {
|
||||
let mut completions = completions.borrow_mut();
|
||||
let completion = &mut completions[completion_index];
|
||||
completion.documentation = Some(Documentation::Undocumented);
|
||||
}
|
||||
|
||||
// NB: Zed does not have `details` inside the completion resolve capabilities, but certain language servers violate the spec and do not return `details` immediately, e.g. https://github.com/yioneko/vtsls/issues/213
|
||||
// So we have to update the label here anyway...
|
||||
let new_label = match snapshot.language() {
|
||||
Some(language) => {
|
||||
adapter
|
||||
.labels_for_completions(&[completion_item.clone()], language)
|
||||
.await?
|
||||
}
|
||||
Some(language) => adapter
|
||||
.labels_for_completions(&[completion_item.clone()], language)
|
||||
.await
|
||||
.log_err()
|
||||
.unwrap_or_default(),
|
||||
None => Vec::new(),
|
||||
}
|
||||
.pop()
|
||||
.flatten()
|
||||
.unwrap_or_else(|| {
|
||||
CodeLabel::plain(
|
||||
completion_item.label,
|
||||
completion_item.label.clone(),
|
||||
completion_item.filter_text.as_deref(),
|
||||
)
|
||||
});
|
||||
|
||||
let mut completions = completions.borrow_mut();
|
||||
let completion = &mut completions[completion_index];
|
||||
completion.lsp_completion = completion_item;
|
||||
if completion.label.filter_text() == new_label.filter_text() {
|
||||
completion.label = new_label;
|
||||
} else {
|
||||
@@ -4344,8 +4317,6 @@ impl LspStore {
|
||||
new_label.filter_text()
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
@@ -4355,30 +4326,29 @@ impl LspStore {
|
||||
buffer_id: BufferId,
|
||||
completions: Rc<RefCell<Box<[Completion]>>>,
|
||||
completion_index: usize,
|
||||
completion: lsp::CompletionItem,
|
||||
client: AnyProtoClient,
|
||||
language_registry: Arc<LanguageRegistry>,
|
||||
) -> Result<()> {
|
||||
let lsp_completion = {
|
||||
let completion = &completions.borrow()[completion_index];
|
||||
if completion.resolved {
|
||||
return Ok(());
|
||||
}
|
||||
serde_json::to_string(&completion.lsp_completion)
|
||||
.unwrap()
|
||||
.into_bytes()
|
||||
};
|
||||
) {
|
||||
let request = proto::ResolveCompletionDocumentation {
|
||||
project_id,
|
||||
language_server_id: server_id.0 as u64,
|
||||
lsp_completion,
|
||||
lsp_completion: serde_json::to_string(&completion).unwrap().into_bytes(),
|
||||
buffer_id: buffer_id.into(),
|
||||
};
|
||||
|
||||
let response = client
|
||||
let Some(response) = client
|
||||
.request(request)
|
||||
.await
|
||||
.context("completion documentation resolve proto request")?;
|
||||
let lsp_completion = serde_json::from_slice(&response.lsp_completion)?;
|
||||
.context("completion documentation resolve proto request")
|
||||
.log_err()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let Some(lsp_completion) = serde_json::from_slice(&response.lsp_completion).log_err()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
let documentation = if response.documentation.is_empty() {
|
||||
Documentation::Undocumented
|
||||
@@ -4396,7 +4366,6 @@ impl LspStore {
|
||||
let completion = &mut completions[completion_index];
|
||||
completion.documentation = Some(documentation);
|
||||
completion.lsp_completion = lsp_completion;
|
||||
completion.resolved = true;
|
||||
|
||||
let old_range = response
|
||||
.old_start
|
||||
@@ -4408,15 +4377,12 @@ impl LspStore {
|
||||
completion.old_range = old_start..old_end;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn apply_additional_edits_for_completion(
|
||||
&self,
|
||||
buffer_handle: Model<Buffer>,
|
||||
completions: Rc<RefCell<Box<[Completion]>>>,
|
||||
completion_index: usize,
|
||||
completion: Completion,
|
||||
push_to_history: bool,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> Task<Result<Option<Transaction>>> {
|
||||
@@ -4425,9 +4391,8 @@ impl LspStore {
|
||||
|
||||
if let Some((client, project_id)) = self.upstream_client() {
|
||||
cx.spawn(move |_, mut cx| async move {
|
||||
let request = {
|
||||
let completion = completions.borrow()[completion_index].clone();
|
||||
proto::ApplyCompletionAdditionalEdits {
|
||||
let response = client
|
||||
.request(proto::ApplyCompletionAdditionalEdits {
|
||||
project_id,
|
||||
buffer_id: buffer_id.into(),
|
||||
completion: Some(Self::serialize_completion(&CoreCompletion {
|
||||
@@ -4435,13 +4400,9 @@ impl LspStore {
|
||||
new_text: completion.new_text,
|
||||
server_id: completion.server_id,
|
||||
lsp_completion: completion.lsp_completion,
|
||||
resolved: completion.resolved,
|
||||
})),
|
||||
}
|
||||
};
|
||||
|
||||
let response = client.request(request).await?;
|
||||
completions.borrow_mut()[completion_index].resolved = true;
|
||||
})
|
||||
.await?;
|
||||
|
||||
if let Some(transaction) = response.transaction {
|
||||
let transaction = language::proto::deserialize_transaction(transaction)?;
|
||||
@@ -4461,31 +4422,34 @@ impl LspStore {
|
||||
}
|
||||
})
|
||||
} else {
|
||||
let server_id = completions.borrow()[completion_index].server_id;
|
||||
let server = match self.language_server_for_local_buffer(buffer, server_id, cx) {
|
||||
let server_id = completion.server_id;
|
||||
let lang_server = match self.language_server_for_local_buffer(buffer, server_id, cx) {
|
||||
Some((_, server)) => server.clone(),
|
||||
_ => return Task::ready(Ok(None)),
|
||||
_ => return Task::ready(Ok(Default::default())),
|
||||
};
|
||||
let snapshot = buffer_handle.read(&cx).snapshot();
|
||||
|
||||
cx.spawn(move |this, mut cx| async move {
|
||||
Self::resolve_completion_local(
|
||||
server.clone(),
|
||||
&snapshot,
|
||||
completions.clone(),
|
||||
completion_index,
|
||||
)
|
||||
.await
|
||||
.context("resolving completion")?;
|
||||
let completion = completions.borrow()[completion_index].clone();
|
||||
let additional_text_edits = completion.lsp_completion.additional_text_edits;
|
||||
let can_resolve = lang_server
|
||||
.capabilities()
|
||||
.completion_provider
|
||||
.as_ref()
|
||||
.and_then(|options| options.resolve_provider)
|
||||
.unwrap_or(false);
|
||||
let additional_text_edits = if can_resolve {
|
||||
lang_server
|
||||
.request::<lsp::request::ResolveCompletionItem>(completion.lsp_completion)
|
||||
.await?
|
||||
.additional_text_edits
|
||||
} else {
|
||||
completion.lsp_completion.additional_text_edits
|
||||
};
|
||||
if let Some(edits) = additional_text_edits {
|
||||
let edits = this
|
||||
.update(&mut cx, |this, cx| {
|
||||
this.as_local_mut().unwrap().edits_from_lsp(
|
||||
&buffer_handle,
|
||||
edits,
|
||||
server.server_id(),
|
||||
lang_server.server_id(),
|
||||
None,
|
||||
cx,
|
||||
)
|
||||
@@ -6839,7 +6803,7 @@ impl LspStore {
|
||||
let apply_additional_edits = this.update(&mut cx, |this, cx| {
|
||||
this.apply_additional_edits_for_completion(
|
||||
buffer,
|
||||
Rc::new(RefCell::new(Box::new([Completion {
|
||||
Completion {
|
||||
old_range: completion.old_range,
|
||||
new_text: completion.new_text,
|
||||
lsp_completion: completion.lsp_completion,
|
||||
@@ -6851,9 +6815,7 @@ impl LspStore {
|
||||
filter_range: Default::default(),
|
||||
},
|
||||
confirm: None,
|
||||
resolved: completion.resolved,
|
||||
}]))),
|
||||
0,
|
||||
},
|
||||
false,
|
||||
cx,
|
||||
)
|
||||
@@ -7818,7 +7780,6 @@ impl LspStore {
|
||||
new_text: completion.new_text.clone(),
|
||||
server_id: completion.server_id.0 as u64,
|
||||
lsp_completion: serde_json::to_vec(&completion.lsp_completion).unwrap(),
|
||||
resolved: completion.resolved,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7838,7 +7799,6 @@ impl LspStore {
|
||||
new_text: completion.new_text,
|
||||
server_id: LanguageServerId(completion.server_id as usize),
|
||||
lsp_completion,
|
||||
resolved: completion.resolved,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -7940,7 +7900,6 @@ async fn populate_labels_for_completions(
|
||||
documentation,
|
||||
lsp_completion,
|
||||
confirm: None,
|
||||
resolved: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,8 +73,10 @@ use snippet::Snippet;
|
||||
use snippet_provider::SnippetProvider;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
cell::RefCell,
|
||||
ops::Range,
|
||||
path::{Component, Path, PathBuf},
|
||||
rc::Rc,
|
||||
str,
|
||||
sync::Arc,
|
||||
time::Duration,
|
||||
@@ -351,8 +353,6 @@ pub struct Completion {
|
||||
pub documentation: Option<Documentation>,
|
||||
/// The raw completion provided by the language server.
|
||||
pub lsp_completion: lsp::CompletionItem,
|
||||
/// Whether this completion has been resolved, to ensure it happens once per completion.
|
||||
pub resolved: bool,
|
||||
/// An optional callback to invoke when this completion is confirmed.
|
||||
/// Returns, whether new completions should be retriggered after the current one.
|
||||
/// If `true` is returned, the editor will show a new completion menu after this completion is confirmed.
|
||||
@@ -380,7 +380,6 @@ pub(crate) struct CoreCompletion {
|
||||
new_text: String,
|
||||
server_id: LanguageServerId,
|
||||
lsp_completion: lsp::CompletionItem,
|
||||
resolved: bool,
|
||||
}
|
||||
|
||||
/// A code action provided by a language server.
|
||||
@@ -2864,6 +2863,35 @@ impl Project {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn resolve_completions(
|
||||
&self,
|
||||
buffer: Model<Buffer>,
|
||||
completion_indices: Vec<usize>,
|
||||
completions: Rc<RefCell<Box<[Completion]>>>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> Task<Result<bool>> {
|
||||
self.lsp_store.update(cx, |lsp_store, cx| {
|
||||
lsp_store.resolve_completions(buffer, completion_indices, completions, cx)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn apply_additional_edits_for_completion(
|
||||
&self,
|
||||
buffer_handle: Model<Buffer>,
|
||||
completion: Completion,
|
||||
push_to_history: bool,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> Task<Result<Option<Transaction>>> {
|
||||
self.lsp_store.update(cx, |lsp_store, cx| {
|
||||
lsp_store.apply_additional_edits_for_completion(
|
||||
buffer_handle,
|
||||
completion,
|
||||
push_to_history,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn code_actions<T: Clone + ToOffset>(
|
||||
&mut self,
|
||||
buffer_handle: &Model<Buffer>,
|
||||
|
||||
@@ -1209,7 +1209,7 @@ impl ProjectPanel {
|
||||
self.remove(false, action.skip_prompt, cx);
|
||||
}
|
||||
|
||||
fn remove(&mut self, trash: bool, skip_prompt: bool, cx: &mut ViewContext<ProjectPanel>) {
|
||||
fn remove(&mut self, trash: bool, skip_prompt: bool, cx: &mut ViewContext<'_, ProjectPanel>) {
|
||||
maybe!({
|
||||
let items_to_delete = self.disjoint_entries(cx);
|
||||
if items_to_delete.is_empty() {
|
||||
@@ -3705,7 +3705,7 @@ impl ProjectPanel {
|
||||
project: Model<Project>,
|
||||
entry_id: ProjectEntryId,
|
||||
skip_ignored: bool,
|
||||
cx: &mut ViewContext<Self>,
|
||||
cx: &mut ViewContext<'_, Self>,
|
||||
) {
|
||||
if let Some(worktree) = project.read(cx).worktree_for_entry(entry_id, cx) {
|
||||
let worktree = worktree.read(cx);
|
||||
@@ -3810,7 +3810,7 @@ fn item_width_estimate(depth: usize, item_text_chars: usize, is_symlink: bool) -
|
||||
}
|
||||
|
||||
impl Render for ProjectPanel {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl IntoElement {
|
||||
let has_worktree = !self.visible_entries.is_empty();
|
||||
let project = self.project.read(cx);
|
||||
let indent_size = ProjectPanelSettings::get_global(cx).indent_size;
|
||||
@@ -4252,10 +4252,6 @@ impl Panel for ProjectPanel {
|
||||
.map_or(false, |entry| entry.is_dir())
|
||||
})
|
||||
}
|
||||
|
||||
fn activation_priority(&self) -> u32 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
impl FocusableView for ProjectPanel {
|
||||
|
||||
@@ -927,7 +927,6 @@ message Completion {
|
||||
string new_text = 3;
|
||||
uint64 server_id = 4;
|
||||
bytes lsp_completion = 5;
|
||||
bool resolved = 6;
|
||||
}
|
||||
|
||||
message GetCodeActions {
|
||||
|
||||
@@ -61,7 +61,7 @@ struct CreateRemoteServer {
|
||||
}
|
||||
|
||||
impl CreateRemoteServer {
|
||||
fn new(cx: &mut WindowContext) -> Self {
|
||||
fn new(cx: &mut WindowContext<'_>) -> Self {
|
||||
let address_editor = cx.new_view(Editor::single_line);
|
||||
address_editor.update(cx, |this, cx| {
|
||||
this.focus_handle(cx).focus(cx);
|
||||
@@ -88,7 +88,7 @@ struct EditNicknameState {
|
||||
}
|
||||
|
||||
impl EditNicknameState {
|
||||
fn new(index: usize, cx: &mut WindowContext) -> Self {
|
||||
fn new(index: usize, cx: &mut WindowContext<'_>) -> Self {
|
||||
let this = Self {
|
||||
index,
|
||||
editor: cx.new_view(Editor::single_line),
|
||||
@@ -264,7 +264,7 @@ struct DefaultState {
|
||||
servers: Vec<ProjectEntry>,
|
||||
}
|
||||
impl DefaultState {
|
||||
fn new(cx: &WindowContext) -> Self {
|
||||
fn new(cx: &WindowContext<'_>) -> Self {
|
||||
let handle = ScrollHandle::new();
|
||||
let scrollbar = ScrollbarState::new(handle.clone());
|
||||
let add_new_server = NavigableEntry::new(&handle, cx);
|
||||
@@ -309,7 +309,7 @@ enum Mode {
|
||||
}
|
||||
|
||||
impl Mode {
|
||||
fn default_mode(cx: &WindowContext) -> Self {
|
||||
fn default_mode(cx: &WindowContext<'_>) -> Self {
|
||||
Self::Default(DefaultState::new(cx))
|
||||
}
|
||||
}
|
||||
@@ -1003,7 +1003,7 @@ impl RemoteServerProjects {
|
||||
fn callback(
|
||||
workspace: WeakView<Workspace>,
|
||||
connection_string: SharedString,
|
||||
cx: &mut WindowContext,
|
||||
cx: &mut WindowContext<'_>,
|
||||
) {
|
||||
cx.write_to_clipboard(ClipboardItem::new_string(
|
||||
connection_string.to_string(),
|
||||
@@ -1069,7 +1069,7 @@ impl RemoteServerProjects {
|
||||
remote_servers: View<RemoteServerProjects>,
|
||||
index: usize,
|
||||
connection_string: SharedString,
|
||||
cx: &mut WindowContext,
|
||||
cx: &mut WindowContext<'_>,
|
||||
) {
|
||||
let prompt_message =
|
||||
format!("Remove server `{}`?", connection_string);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user