Compare commits
24 Commits
drop-image
...
v0.144.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
549de5cea4 | ||
|
|
f11a992cf1 | ||
|
|
d77d608221 | ||
|
|
a0a28081f9 | ||
|
|
e03a50c86c | ||
|
|
80408d3779 | ||
|
|
39b937ae16 | ||
|
|
0da8464d6a | ||
|
|
b370d6fedb | ||
|
|
65d73274e8 | ||
|
|
b16e2ee46d | ||
|
|
cca31c7f07 | ||
|
|
94e8c32862 | ||
|
|
4c8821b557 | ||
|
|
c7d9867b69 | ||
|
|
89e6dffd0d | ||
|
|
4160d1869a | ||
|
|
7714982a9d | ||
|
|
7dde13e77d | ||
|
|
fbefe44e81 | ||
|
|
ba941097f6 | ||
|
|
7d36760364 | ||
|
|
8a0d5ae067 | ||
|
|
962be2e09c |
1
.github/workflows/ci.yml
vendored
1
.github/workflows/ci.yml
vendored
@@ -319,7 +319,6 @@ jobs:
|
||||
|
||||
- name: Upload app bundle to release
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: ${{ env.RELEASE_CHANNEL == 'preview' }}
|
||||
with:
|
||||
draft: true
|
||||
prerelease: ${{ env.RELEASE_CHANNEL == 'preview' }}
|
||||
|
||||
199
Cargo.lock
generated
199
Cargo.lock
generated
@@ -87,7 +87,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6d1ea4484c8676f295307a4892d478c70ac8da1dbd8c7c10830a504b7f1022f"
|
||||
dependencies = [
|
||||
"base64 0.22.0",
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"home",
|
||||
"libc",
|
||||
"log",
|
||||
@@ -110,7 +110,7 @@ version = "0.24.1-dev"
|
||||
source = "git+https://github.com/alacritty/alacritty?rev=cacdb5bb3b72bad2c729227537979d95af75978f#cacdb5bb3b72bad2c729227537979d95af75978f"
|
||||
dependencies = [
|
||||
"base64 0.22.0",
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"home",
|
||||
"libc",
|
||||
"log",
|
||||
@@ -341,8 +341,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ashpd"
|
||||
version = "0.9.0"
|
||||
source = "git+https://github.com/bilelmoussaoui/ashpd?rev=29f2e1a#29f2e1a6f4b0911f504658f5f4630c02e01b13f2"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfe7e0dd0ac5a401dc116ed9f9119cf9decc625600474cb41f0fc0a0050abc9a"
|
||||
dependencies = [
|
||||
"async-fs 2.1.1",
|
||||
"async-net 2.0.0",
|
||||
@@ -1581,7 +1582,16 @@ version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1"
|
||||
dependencies = [
|
||||
"bit-vec",
|
||||
"bit-vec 0.6.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit-set"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0481a0e032742109b1133a095184ee93d88f3dc9e0d28a5d033dc77a073f44f"
|
||||
dependencies = [
|
||||
"bit-vec 0.7.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1590,6 +1600,12 @@ version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
|
||||
|
||||
[[package]]
|
||||
name = "bit-vec"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2c54ff287cfc0a34f38a6b832ea1bd8e448a330b3e40a50859e6488bee07f22"
|
||||
|
||||
[[package]]
|
||||
name = "bit_field"
|
||||
version = "0.10.2"
|
||||
@@ -1604,9 +1620,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.4.2"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
|
||||
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
@@ -1632,11 +1648,11 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "blade-graphics"
|
||||
version = "0.4.0"
|
||||
source = "git+https://github.com/kvark/blade?rev=21a56f780e21e4cb42c70a1dcf4b59842d1ad7f7#21a56f780e21e4cb42c70a1dcf4b59842d1ad7f7"
|
||||
source = "git+https://github.com/zed-industries/blade?rev=a477c2008db27db0b9f745715e119b3ee7ab7818#a477c2008db27db0b9f745715e119b3ee7ab7818"
|
||||
dependencies = [
|
||||
"ash",
|
||||
"ash-window",
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"block",
|
||||
"bytemuck",
|
||||
"codespan-reporting",
|
||||
@@ -1662,7 +1678,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "blade-macros"
|
||||
version = "0.2.1"
|
||||
source = "git+https://github.com/kvark/blade?rev=21a56f780e21e4cb42c70a1dcf4b59842d1ad7f7#21a56f780e21e4cb42c70a1dcf4b59842d1ad7f7"
|
||||
source = "git+https://github.com/zed-industries/blade?rev=a477c2008db27db0b9f745715e119b3ee7ab7818#a477c2008db27db0b9f745715e119b3ee7ab7818"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1672,7 +1688,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "blade-util"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/kvark/blade?rev=21a56f780e21e4cb42c70a1dcf4b59842d1ad7f7#21a56f780e21e4cb42c70a1dcf4b59842d1ad7f7"
|
||||
source = "git+https://github.com/zed-industries/blade?rev=a477c2008db27db0b9f745715e119b3ee7ab7818#a477c2008db27db0b9f745715e119b3ee7ab7818"
|
||||
dependencies = [
|
||||
"blade-graphics",
|
||||
"bytemuck",
|
||||
@@ -1920,7 +1936,7 @@ version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"log",
|
||||
"polling 3.3.2",
|
||||
"rustix 0.38.32",
|
||||
@@ -2855,7 +2871,7 @@ name = "cosmic-text"
|
||||
version = "0.11.2"
|
||||
source = "git+https://github.com/pop-os/cosmic-text?rev=542b20c#542b20ca4376a3b5de5fa629db1a4ace44e18e0c"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"fontdb",
|
||||
"log",
|
||||
"rangemap",
|
||||
@@ -4008,7 +4024,7 @@ version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7493d4c459da9f84325ad297371a6b2b8a162800873a22e3b6b6512e61d18c05"
|
||||
dependencies = [
|
||||
"bit-set",
|
||||
"bit-set 0.5.3",
|
||||
"regex",
|
||||
]
|
||||
|
||||
@@ -4065,7 +4081,7 @@ name = "feedback"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"client",
|
||||
"db",
|
||||
"editor",
|
||||
@@ -4265,7 +4281,7 @@ checksum = "e32eac81c1135c1df01d4e6d4233c47ba11f6a6d07f33e0bba09d18797077770"
|
||||
dependencies = [
|
||||
"fontconfig-parser",
|
||||
"log",
|
||||
"memmap2 0.9.4",
|
||||
"memmap2",
|
||||
"slotmap",
|
||||
"tinyvec",
|
||||
"ttf-parser",
|
||||
@@ -4399,7 +4415,7 @@ dependencies = [
|
||||
name = "fsevent"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"core-foundation",
|
||||
"fsevent-sys 3.1.0",
|
||||
"parking_lot",
|
||||
@@ -4710,7 +4726,7 @@ version = "0.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b903b73e45dc0c6c596f2d37eccece7c1c8bb6e4407b001096387c63d0d93724"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"libc",
|
||||
"libgit2-sys",
|
||||
"log",
|
||||
@@ -4821,7 +4837,7 @@ version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"gpu-alloc-types",
|
||||
]
|
||||
|
||||
@@ -4842,7 +4858,7 @@ version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4892,6 +4908,7 @@ dependencies = [
|
||||
"num_cpus",
|
||||
"objc",
|
||||
"oo7",
|
||||
"open",
|
||||
"parking",
|
||||
"parking_lot",
|
||||
"pathfinder_geometry",
|
||||
@@ -5099,7 +5116,7 @@ version = "0.20.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f7acb9683d7c7068aa46d47557bfa4e35a277964b350d9504a87b03610163fd"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"byteorder",
|
||||
"heed-traits",
|
||||
"heed-types",
|
||||
@@ -5703,6 +5720,25 @@ version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6"
|
||||
|
||||
[[package]]
|
||||
name = "is-docker"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is-wsl"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5"
|
||||
dependencies = [
|
||||
"is-docker",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "isahc"
|
||||
version = "1.7.2"
|
||||
@@ -6520,15 +6556,6 @@ dependencies = [
|
||||
"rustix 0.38.32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memmap2"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43a5a03cefb0d953ec0be133036f14e109412fa594edc2f77227249db66cc3ed"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memmap2"
|
||||
version = "0.9.4"
|
||||
@@ -6662,17 +6689,17 @@ checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
|
||||
|
||||
[[package]]
|
||||
name = "naga"
|
||||
version = "0.14.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae585df4b6514cf8842ac0f1ab4992edc975892704835b549cf818dc0191249e"
|
||||
version = "0.20.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=425526828f738c95ec50b016c6a761bc00d2fb25#425526828f738c95ec50b016c6a761bc00d2fb25"
|
||||
dependencies = [
|
||||
"bit-set",
|
||||
"bitflags 2.4.2",
|
||||
"arrayvec",
|
||||
"bit-set 0.6.0",
|
||||
"bitflags 2.6.0",
|
||||
"cfg_aliases",
|
||||
"codespan-reporting",
|
||||
"hexf-parse",
|
||||
"indexmap 2.2.6",
|
||||
"log",
|
||||
"num-traits",
|
||||
"rustc-hash",
|
||||
"spirv",
|
||||
"termcolor",
|
||||
@@ -6768,7 +6795,7 @@ version = "0.27.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"memoffset",
|
||||
@@ -6780,7 +6807,7 @@ version = "0.28.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
@@ -6849,7 +6876,7 @@ version = "6.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"crossbeam-channel",
|
||||
"filetime",
|
||||
"fsevent-sys 4.1.0",
|
||||
@@ -7062,6 +7089,15 @@ dependencies = [
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_threads"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nvim-rs"
|
||||
version = "0.6.0-pre"
|
||||
@@ -7191,6 +7227,17 @@ version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
||||
|
||||
[[package]]
|
||||
name = "open"
|
||||
version = "5.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61a877bf6abd716642a53ef1b89fb498923a4afca5c754f9050b4d081c05c4b3"
|
||||
dependencies = [
|
||||
"is-wsl",
|
||||
"libc",
|
||||
"pathdiff",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "open_ai"
|
||||
version = "0.1.0"
|
||||
@@ -7211,7 +7258,7 @@ version = "0.10.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"cfg-if",
|
||||
"foreign-types 0.3.2",
|
||||
"libc",
|
||||
@@ -8225,7 +8272,7 @@ version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dce76ce678ffc8e5675b22aa1405de0b7037e2fdf8913fea40d1926c6fe1e6e7"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"memchr",
|
||||
"unicase",
|
||||
]
|
||||
@@ -9036,7 +9083,7 @@ version = "0.38.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"errno 0.3.8",
|
||||
"itoa",
|
||||
"libc",
|
||||
@@ -9111,7 +9158,7 @@ version = "0.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfb9cf8877777222e4a3bc7eb247e398b56baba500c38c1c46842431adc8b55c"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"bytemuck",
|
||||
"libm",
|
||||
"smallvec",
|
||||
@@ -9334,7 +9381,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"any_vec",
|
||||
"anyhow",
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"client",
|
||||
"collections",
|
||||
"editor",
|
||||
@@ -9762,13 +9809,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "simplelog"
|
||||
version = "0.9.0"
|
||||
version = "0.12.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bc0ffd69814a9b251d43afcabf96dad1b29f5028378056257be9e3fecc9f720"
|
||||
checksum = "16257adbfaef1ee58b1363bdc0664c9b8e1e30aed86049635fb5f147d065a9c0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"log",
|
||||
"termcolor",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -9921,12 +9968,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "spirv"
|
||||
version = "0.2.0+1.5.4"
|
||||
version = "0.3.0+sdk-1.3.268.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "246bfa38fe3db3f1dfc8ca5a2cdeb7348c78be2112740cc0ec8ef18b6d94f830"
|
||||
checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"num-traits",
|
||||
"bitflags 2.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -10102,7 +10148,7 @@ dependencies = [
|
||||
"atoi",
|
||||
"base64 0.21.7",
|
||||
"bigdecimal",
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"byteorder",
|
||||
"bytes 1.5.0",
|
||||
"chrono",
|
||||
@@ -10149,7 +10195,7 @@ dependencies = [
|
||||
"atoi",
|
||||
"base64 0.21.7",
|
||||
"bigdecimal",
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"byteorder",
|
||||
"chrono",
|
||||
"crc",
|
||||
@@ -10571,7 +10617,7 @@ version = "0.27.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9aef1f9d4c1dbdd1cb3a63be9efd2f04d8ddbc919d46112982c76818ffc2f1a7"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"cap-fs-ext",
|
||||
"cap-std",
|
||||
"fd-lock",
|
||||
@@ -10712,9 +10758,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.1.3"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
|
||||
checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
@@ -10874,18 +10920,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.60"
|
||||
version = "1.0.61"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18"
|
||||
checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.60"
|
||||
version = "1.0.61"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524"
|
||||
checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -10936,7 +10982,9 @@ checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"itoa",
|
||||
"libc",
|
||||
"num-conv",
|
||||
"num_threads",
|
||||
"powerfmt",
|
||||
"serde",
|
||||
"time-core",
|
||||
@@ -11295,7 +11343,7 @@ version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"bytes 1.5.0",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
@@ -12066,7 +12114,7 @@ version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40eb22ae96f050e0c0d6f7ce43feeae26c348fc4dea56928ca81537cfaa6188b"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"cursor-icon",
|
||||
"log",
|
||||
"serde",
|
||||
@@ -12218,7 +12266,7 @@ version = "0.201.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84e5df6dba6c0d7fafc63a450f1738451ed7a0b52295d83e868218fa286bf708"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"indexmap 2.2.6",
|
||||
"semver",
|
||||
]
|
||||
@@ -12485,7 +12533,7 @@ checksum = "371d828b6849ea06d598ae7dd1c316e8dd9e99b76f77d93d5886cb25c7f8e188"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"bytes 1.5.0",
|
||||
"cap-fs-ext",
|
||||
"cap-net-ext",
|
||||
@@ -12572,7 +12620,7 @@ version = "0.31.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "82fb96ee935c2cea6668ccb470fb7771f6215d1691746c2d896b447a00ad3f1f"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"rustix 0.38.32",
|
||||
"wayland-backend",
|
||||
"wayland-scanner",
|
||||
@@ -12595,7 +12643,7 @@ version = "0.31.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f81f365b8b4a97f422ac0e8737c438024b5951734506b0e1d775c73030561f4"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"wayland-backend",
|
||||
"wayland-client",
|
||||
"wayland-scanner",
|
||||
@@ -12607,7 +12655,7 @@ version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23803551115ff9ea9bce586860c5c5a971e360825a0309264102a9495a5ff479"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"wayland-backend",
|
||||
"wayland-client",
|
||||
"wayland-protocols",
|
||||
@@ -12726,7 +12774,7 @@ checksum = "ae1136a209614ace00b0c11f04dc7cf42540773be3b22eff6ad165110aba29c1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"thiserror",
|
||||
"tracing",
|
||||
"wasmtime",
|
||||
@@ -13156,7 +13204,7 @@ version = "0.36.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9643b83820c0cd246ecabe5fa454dd04ba4fa67996369466d0747472d337346"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
@@ -13175,7 +13223,7 @@ version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "288f992ea30e6b5c531b52cdd5f3be81c148554b09ea416f058d16556ba92c27"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"wit-bindgen-rt",
|
||||
"wit-bindgen-rust-macro",
|
||||
]
|
||||
@@ -13231,7 +13279,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "421c0c848a0660a8c22e2fd217929a0191f14476b68962afd2af89fd22e39825"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
"indexmap 2.2.6",
|
||||
"log",
|
||||
"serde",
|
||||
@@ -13437,18 +13485,17 @@ name = "xim-parser"
|
||||
version = "0.2.1"
|
||||
source = "git+https://github.com/npmania/xim-rs?rev=27132caffc5b9bc9c432ca4afad184ab6e7c16af#27132caffc5b9bc9c432ca4afad184ab6e7c16af"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"bitflags 2.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xkbcommon"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13867d259930edc7091a6c41b4ce6eee464328c6ff9659b7e4c668ca20d4c91e"
|
||||
source = "git+https://github.com/ConradIrwin/xkbcommon-rs?rev=fcbb4612185cc129ceeff51d22f7fb51810a03b2#fcbb4612185cc129ceeff51d22f7fb51810a03b2"
|
||||
dependencies = [
|
||||
"as-raw-xcb-connection",
|
||||
"libc",
|
||||
"memmap2 0.8.0",
|
||||
"memmap2",
|
||||
"xkeysym",
|
||||
]
|
||||
|
||||
@@ -13581,7 +13628,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zed"
|
||||
version = "0.144.0"
|
||||
version = "0.144.3"
|
||||
dependencies = [
|
||||
"activity_indicator",
|
||||
"anyhow",
|
||||
|
||||
11
Cargo.toml
11
Cargo.toml
@@ -274,7 +274,7 @@ zed_actions = { path = "crates/zed_actions" }
|
||||
alacritty_terminal = "0.23"
|
||||
any_vec = "0.13"
|
||||
anyhow = "1.0.57"
|
||||
ashpd = { git = "https://github.com/bilelmoussaoui/ashpd", rev = "29f2e1a" }
|
||||
ashpd = "0.9.1"
|
||||
async-compression = { version = "0.4", features = ["gzip", "futures-io"] }
|
||||
async-dispatcher = { version = "0.1" }
|
||||
async-fs = "1.6"
|
||||
@@ -284,10 +284,10 @@ async-trait = "0.1"
|
||||
async-watch = "0.3.1"
|
||||
async_zip = { version = "0.0.17", features = ["deflate", "deflate64"] }
|
||||
base64 = "0.13"
|
||||
bitflags = "2.4.2"
|
||||
blade-graphics = { git = "https://github.com/kvark/blade", rev = "21a56f780e21e4cb42c70a1dcf4b59842d1ad7f7" }
|
||||
blade-macros = { git = "https://github.com/kvark/blade", rev = "21a56f780e21e4cb42c70a1dcf4b59842d1ad7f7" }
|
||||
blade-util = { git = "https://github.com/kvark/blade", rev = "21a56f780e21e4cb42c70a1dcf4b59842d1ad7f7" }
|
||||
bitflags = "2.6.0"
|
||||
blade-graphics = { git = "https://github.com/zed-industries/blade", rev = "a477c2008db27db0b9f745715e119b3ee7ab7818" }
|
||||
blade-macros = { git = "https://github.com/zed-industries/blade", rev = "a477c2008db27db0b9f745715e119b3ee7ab7818" }
|
||||
blade-util = { git = "https://github.com/zed-industries/blade", rev = "a477c2008db27db0b9f745715e119b3ee7ab7818" }
|
||||
cap-std = "3.0"
|
||||
cargo_toml = "0.20"
|
||||
chrono = { version = "0.4", features = ["serde"] }
|
||||
@@ -365,6 +365,7 @@ shellexpand = "2.1.0"
|
||||
shlex = "1.3.0"
|
||||
signal-hook = "0.3.17"
|
||||
similar = "1.3"
|
||||
simplelog = "0.12.2"
|
||||
smallvec = { version = "1.6", features = ["union"] }
|
||||
smol = "1.2"
|
||||
strum = { version = "0.25.0", features = ["derive"] }
|
||||
|
||||
@@ -397,7 +397,7 @@
|
||||
"bindings": {
|
||||
"ctrl-shift-k": "editor::DeleteLine",
|
||||
"ctrl-shift-d": "editor::DuplicateLineDown",
|
||||
"ctrl-j": "editor::JoinLines",
|
||||
"ctrl-shift-j": "editor::JoinLines",
|
||||
"ctrl-alt-backspace": "editor::DeleteToPreviousSubwordStart",
|
||||
"ctrl-alt-h": "editor::DeleteToPreviousSubwordStart",
|
||||
"ctrl-alt-delete": "editor::DeleteToNextSubwordEnd",
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
"ctrl-,": "editor::GoToPrevHunk",
|
||||
"cmd-k cmd-u": "editor::ConvertToUpperCase",
|
||||
"cmd-k cmd-l": "editor::ConvertToLowerCase",
|
||||
"cmd-shift-j": "editor::JoinLines",
|
||||
"shift-alt-m": "markdown::OpenPreviewToTheSide",
|
||||
"ctrl-backspace": "editor::DeleteToPreviousWordStart",
|
||||
"ctrl-delete": "editor::DeleteToNextWordEnd"
|
||||
|
||||
@@ -128,14 +128,7 @@
|
||||
// The default number of lines to expand excerpts in the multibuffer by.
|
||||
"expand_excerpt_lines": 3,
|
||||
// Globs to match against file paths to determine if a file is private.
|
||||
"private_files": [
|
||||
"**/.env*",
|
||||
"**/*.pem",
|
||||
"**/*.key",
|
||||
"**/*.cert",
|
||||
"**/*.crt",
|
||||
"**/secrets.yml"
|
||||
],
|
||||
"private_files": ["**/.env*", "**/*.pem", "**/*.key", "**/*.cert", "**/*.crt", "**/secrets.yml"],
|
||||
// Whether to use additional LSP queries to format (and amend) the code after
|
||||
// every "trigger" symbol input, defined by LSP server capabilities.
|
||||
"use_on_type_format": true,
|
||||
@@ -714,10 +707,12 @@
|
||||
}
|
||||
},
|
||||
"C": {
|
||||
"format_on_save": "off"
|
||||
"format_on_save": "off",
|
||||
"use_on_type_format": false
|
||||
},
|
||||
"C++": {
|
||||
"format_on_save": "off"
|
||||
"format_on_save": "off",
|
||||
"use_on_type_format": false
|
||||
},
|
||||
"CSS": {
|
||||
"prettier": {
|
||||
@@ -769,6 +764,7 @@
|
||||
},
|
||||
"Markdown": {
|
||||
"format_on_save": "off",
|
||||
"use_on_type_format": false,
|
||||
"prettier": {
|
||||
"allowed": true
|
||||
}
|
||||
|
||||
@@ -49,13 +49,11 @@ fn display_ranges<'a>(
|
||||
.pending
|
||||
.as_ref()
|
||||
.map(|pending| &pending.selection);
|
||||
selections.disjoint.iter().chain(pending).map(move |s| {
|
||||
if s.reversed {
|
||||
s.end.to_display_point(&display_map)..s.start.to_display_point(&display_map)
|
||||
} else {
|
||||
s.start.to_display_point(&display_map)..s.end.to_display_point(&display_map)
|
||||
}
|
||||
})
|
||||
selections
|
||||
.disjoint
|
||||
.iter()
|
||||
.chain(pending)
|
||||
.map(move |s| s.start.to_display_point(&display_map)..s.end.to_display_point(&display_map))
|
||||
}
|
||||
|
||||
pub fn deploy_context_menu(
|
||||
|
||||
@@ -12,7 +12,7 @@ use editor::{Editor, EditorElement, EditorStyle};
|
||||
use extension::{ExtensionManifest, ExtensionOperation, ExtensionStore};
|
||||
use fuzzy::{match_strings, StringMatchCandidate};
|
||||
use gpui::{
|
||||
actions, uniform_list, AnyElement, AppContext, EventEmitter, FocusableView, FontStyle,
|
||||
actions, uniform_list, AnyElement, AppContext, EventEmitter, Flatten, FocusableView, FontStyle,
|
||||
InteractiveElement, KeyContext, ParentElement, Render, Styled, Task, TextStyle,
|
||||
UniformListScrollHandle, View, ViewContext, VisualContext, WeakView, WhiteSpace, WindowContext,
|
||||
};
|
||||
@@ -24,7 +24,6 @@ use std::time::Duration;
|
||||
use std::{ops::Range, sync::Arc};
|
||||
use theme::ThemeSettings;
|
||||
use ui::{prelude::*, ContextMenu, PopoverMenu, ToggleButton, Tooltip};
|
||||
use util::ResultExt as _;
|
||||
use workspace::item::TabContentParams;
|
||||
use workspace::{
|
||||
item::{Item, ItemEvent},
|
||||
@@ -58,9 +57,23 @@ pub fn init(cx: &mut AppContext) {
|
||||
multiple: false,
|
||||
});
|
||||
|
||||
let workspace_handle = cx.view().downgrade();
|
||||
cx.deref_mut()
|
||||
.spawn(|mut cx| async move {
|
||||
let extension_path = prompt.await.log_err()??.pop()?;
|
||||
let extension_path =
|
||||
match Flatten::flatten(prompt.await.map_err(|e| e.into())) {
|
||||
Ok(Some(mut paths)) => paths.pop()?,
|
||||
Ok(None) => return None,
|
||||
Err(err) => {
|
||||
workspace_handle
|
||||
.update(&mut cx, |workspace, cx| {
|
||||
workspace.show_portal_error(err.to_string(), cx);
|
||||
})
|
||||
.ok();
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
store
|
||||
.update(&mut cx, |store, cx| {
|
||||
store
|
||||
|
||||
@@ -124,6 +124,7 @@ wayland-protocols = { version = "0.31.2", features = [
|
||||
] }
|
||||
wayland-protocols-plasma = { version = "0.2.0", features = ["client"] }
|
||||
oo7 = "0.3.0"
|
||||
open = "5.2.0"
|
||||
filedescriptor = "0.8.2"
|
||||
x11rb = { version = "0.13.0", features = [
|
||||
"allow-unsafe-code",
|
||||
@@ -134,7 +135,10 @@ x11rb = { version = "0.13.0", features = [
|
||||
"resource_manager",
|
||||
"sync",
|
||||
] }
|
||||
xkbcommon = { version = "0.7", features = ["wayland", "x11"] }
|
||||
xkbcommon = { git = "https://github.com/ConradIrwin/xkbcommon-rs", rev = "fcbb4612185cc129ceeff51d22f7fb51810a03b2", features = [
|
||||
"wayland",
|
||||
"x11",
|
||||
] }
|
||||
xim = { git = "https://github.com/npmania/xim-rs", rev = "27132caffc5b9bc9c432ca4afad184ab6e7c16af", features = [
|
||||
"x11rb-xcb",
|
||||
"x11rb-client",
|
||||
|
||||
@@ -612,10 +612,11 @@ impl AppContext {
|
||||
/// Displays a platform modal for selecting paths.
|
||||
/// When one or more paths are selected, they'll be relayed asynchronously via the returned oneshot channel.
|
||||
/// If cancelled, a `None` will be relayed instead.
|
||||
/// May return an error on Linux if the file picker couldn't be opened.
|
||||
pub fn prompt_for_paths(
|
||||
&self,
|
||||
options: PathPromptOptions,
|
||||
) -> oneshot::Receiver<Option<Vec<PathBuf>>> {
|
||||
) -> oneshot::Receiver<Result<Option<Vec<PathBuf>>>> {
|
||||
self.platform.prompt_for_paths(options)
|
||||
}
|
||||
|
||||
@@ -623,7 +624,11 @@ impl AppContext {
|
||||
/// The provided directory will be used to set the initial location.
|
||||
/// When a path is selected, it is relayed asynchronously via the returned oneshot channel.
|
||||
/// If cancelled, a `None` will be relayed instead.
|
||||
pub fn prompt_for_new_path(&self, directory: &Path) -> oneshot::Receiver<Option<PathBuf>> {
|
||||
/// May return an error on Linux if the file picker couldn't be opened.
|
||||
pub fn prompt_for_new_path(
|
||||
&self,
|
||||
directory: &Path,
|
||||
) -> oneshot::Receiver<Result<Option<PathBuf>>> {
|
||||
self.platform.prompt_for_new_path(directory)
|
||||
}
|
||||
|
||||
|
||||
@@ -137,8 +137,8 @@ pub(crate) trait Platform: 'static {
|
||||
fn prompt_for_paths(
|
||||
&self,
|
||||
options: PathPromptOptions,
|
||||
) -> oneshot::Receiver<Option<Vec<PathBuf>>>;
|
||||
fn prompt_for_new_path(&self, directory: &Path) -> oneshot::Receiver<Option<PathBuf>>;
|
||||
) -> oneshot::Receiver<Result<Option<Vec<PathBuf>>>>;
|
||||
fn prompt_for_new_path(&self, directory: &Path) -> oneshot::Receiver<Result<Option<PathBuf>>>;
|
||||
fn reveal_path(&self, path: &Path);
|
||||
|
||||
fn on_quit(&self, callback: Box<dyn FnMut()>);
|
||||
|
||||
@@ -21,6 +21,7 @@ use std::{
|
||||
use anyhow::anyhow;
|
||||
use ashpd::desktop::file_chooser::{OpenFileRequest, SaveFileRequest};
|
||||
use ashpd::desktop::open_uri::{OpenDirectoryRequest, OpenFileRequest as OpenUriRequest};
|
||||
use ashpd::desktop::ResponseError;
|
||||
use ashpd::{url, ActivationToken};
|
||||
use async_task::Runnable;
|
||||
use calloop::channel::Channel;
|
||||
@@ -54,6 +55,9 @@ pub(crate) const DOUBLE_CLICK_INTERVAL: Duration = Duration::from_millis(400);
|
||||
pub(crate) const DOUBLE_CLICK_DISTANCE: Pixels = px(5.0);
|
||||
pub(crate) const KEYRING_LABEL: &str = "zed-github-account";
|
||||
|
||||
const FILE_PICKER_PORTAL_MISSING: &str =
|
||||
"Couldn't open file picker due to missing xdg-desktop-portal implementation.";
|
||||
|
||||
pub trait LinuxClient {
|
||||
fn compositor_name(&self) -> &'static str;
|
||||
fn with_common<R>(&self, f: impl FnOnce(&mut LinuxCommon) -> R) -> R;
|
||||
@@ -256,7 +260,7 @@ impl<P: LinuxClient + 'static> Platform for P {
|
||||
fn prompt_for_paths(
|
||||
&self,
|
||||
options: PathPromptOptions,
|
||||
) -> oneshot::Receiver<Option<Vec<PathBuf>>> {
|
||||
) -> oneshot::Receiver<Result<Option<Vec<PathBuf>>>> {
|
||||
let (done_tx, done_rx) = oneshot::channel();
|
||||
self.foreground_executor()
|
||||
.spawn(async move {
|
||||
@@ -274,7 +278,7 @@ impl<P: LinuxClient + 'static> Platform for P {
|
||||
}
|
||||
};
|
||||
|
||||
let result = OpenFileRequest::default()
|
||||
let request = match OpenFileRequest::default()
|
||||
.modal(true)
|
||||
.title(title)
|
||||
.accept_label("Select")
|
||||
@@ -282,49 +286,68 @@ impl<P: LinuxClient + 'static> Platform for P {
|
||||
.directory(options.directories)
|
||||
.send()
|
||||
.await
|
||||
.ok()
|
||||
.and_then(|request| request.response().ok())
|
||||
.and_then(|response| {
|
||||
{
|
||||
Ok(request) => request,
|
||||
Err(err) => {
|
||||
let result = match err {
|
||||
ashpd::Error::PortalNotFound(_) => anyhow!(FILE_PICKER_PORTAL_MISSING),
|
||||
err => err.into(),
|
||||
};
|
||||
done_tx.send(Err(result));
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let result = match request.response() {
|
||||
Ok(response) => Ok(Some(
|
||||
response
|
||||
.uris()
|
||||
.iter()
|
||||
.map(|uri| uri.to_file_path().ok())
|
||||
.collect()
|
||||
});
|
||||
|
||||
.filter_map(|uri| uri.to_file_path().ok())
|
||||
.collect::<Vec<_>>(),
|
||||
)),
|
||||
Err(ashpd::Error::Response(ResponseError::Cancelled)) => Ok(None),
|
||||
Err(e) => Err(e.into()),
|
||||
};
|
||||
done_tx.send(result);
|
||||
})
|
||||
.detach();
|
||||
done_rx
|
||||
}
|
||||
|
||||
fn prompt_for_new_path(&self, directory: &Path) -> oneshot::Receiver<Option<PathBuf>> {
|
||||
fn prompt_for_new_path(&self, directory: &Path) -> oneshot::Receiver<Result<Option<PathBuf>>> {
|
||||
let (done_tx, done_rx) = oneshot::channel();
|
||||
let directory = directory.to_owned();
|
||||
self.foreground_executor()
|
||||
.spawn(async move {
|
||||
let request = SaveFileRequest::default()
|
||||
let request = match SaveFileRequest::default()
|
||||
.modal(true)
|
||||
.title("Select new path")
|
||||
.accept_label("Accept")
|
||||
.current_folder(directory);
|
||||
|
||||
let result = if let Ok(request) = request {
|
||||
request
|
||||
.send()
|
||||
.await
|
||||
.ok()
|
||||
.and_then(|request| request.response().ok())
|
||||
.and_then(|response| {
|
||||
response
|
||||
.uris()
|
||||
.first()
|
||||
.and_then(|uri| uri.to_file_path().ok())
|
||||
})
|
||||
} else {
|
||||
None
|
||||
.current_folder(directory)
|
||||
.expect("pathbuf should not be nul terminated")
|
||||
.send()
|
||||
.await
|
||||
{
|
||||
Ok(request) => request,
|
||||
Err(err) => {
|
||||
let result = match err {
|
||||
ashpd::Error::PortalNotFound(_) => anyhow!(FILE_PICKER_PORTAL_MISSING),
|
||||
err => err.into(),
|
||||
};
|
||||
done_tx.send(Err(result));
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let result = match request.response() {
|
||||
Ok(response) => Ok(response
|
||||
.uris()
|
||||
.first()
|
||||
.and_then(|uri| uri.to_file_path().ok())),
|
||||
Err(ashpd::Error::Response(ResponseError::Cancelled)) => Ok(None),
|
||||
Err(e) => Err(e.into()),
|
||||
};
|
||||
done_tx.send(result);
|
||||
})
|
||||
.detach();
|
||||
@@ -502,11 +525,26 @@ pub(super) fn open_uri_internal(
|
||||
if let Some(uri) = url::Url::parse(uri).log_err() {
|
||||
executor
|
||||
.spawn(async move {
|
||||
OpenUriRequest::default()
|
||||
.activation_token(activation_token.map(ActivationToken::from))
|
||||
match OpenUriRequest::default()
|
||||
.activation_token(activation_token.clone().map(ActivationToken::from))
|
||||
.send_uri(&uri)
|
||||
.await
|
||||
.log_err();
|
||||
{
|
||||
Ok(_) => return,
|
||||
Err(e) => log::error!("Failed to open with dbus: {}", e),
|
||||
}
|
||||
|
||||
for mut command in open::commands(uri.to_string()) {
|
||||
if let Some(token) = activation_token.as_ref() {
|
||||
command.env("XDG_ACTIVATION_TOKEN", token);
|
||||
}
|
||||
match command.spawn() {
|
||||
Ok(_) => return,
|
||||
Err(e) => {
|
||||
log::error!("Failed to open with {:?}: {}", command.get_program(), e)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
@@ -519,12 +557,20 @@ pub(super) fn reveal_path_internal(
|
||||
) {
|
||||
executor
|
||||
.spawn(async move {
|
||||
if let Some(dir) = File::open(path).log_err() {
|
||||
OpenDirectoryRequest::default()
|
||||
if let Some(dir) = File::open(path.clone()).log_err() {
|
||||
match OpenDirectoryRequest::default()
|
||||
.activation_token(activation_token.map(ActivationToken::from))
|
||||
.send(&dir.as_fd())
|
||||
.await
|
||||
.log_err();
|
||||
{
|
||||
Ok(_) => return,
|
||||
Err(e) => log::error!("Failed to open with dbus: {}", e),
|
||||
}
|
||||
if path.is_dir() {
|
||||
open::that_detached(path).log_err();
|
||||
} else {
|
||||
open::that_detached(path.parent().unwrap_or(Path::new(""))).log_err();
|
||||
}
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
|
||||
@@ -11,6 +11,7 @@ use calloop_wayland_source::WaylandSource;
|
||||
use collections::HashMap;
|
||||
use filedescriptor::Pipe;
|
||||
|
||||
use http::Url;
|
||||
use smallvec::SmallVec;
|
||||
use util::ResultExt;
|
||||
use wayland_backend::client::ObjectId;
|
||||
@@ -1791,7 +1792,8 @@ impl Dispatch<wl_data_device::WlDataDevice, ()> for WaylandClientStatePtr {
|
||||
|
||||
let paths: SmallVec<[_; 2]> = file_list
|
||||
.lines()
|
||||
.map(|path| PathBuf::from(path.replace("file://", "")))
|
||||
.filter_map(|path| Url::parse(path).log_err())
|
||||
.filter_map(|url| url.to_file_path().log_err())
|
||||
.collect();
|
||||
let position = Point::new(x.into(), y.into());
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ use x11rb::xcb_ffi::XCBConnection;
|
||||
use xim::{x11rb::X11rbClient, Client};
|
||||
use xim::{AttributeName, InputStyle};
|
||||
use xkbc::x11::ffi::{XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION};
|
||||
use xkbcommon::xkb as xkbc;
|
||||
use xkbcommon::xkb::{self as xkbc, LayoutIndex, ModMask};
|
||||
|
||||
use crate::platform::linux::LinuxClient;
|
||||
use crate::platform::{LinuxCommon, PlatformWindow};
|
||||
@@ -94,6 +94,13 @@ impl From<xim::ClientError> for EventHandlerError {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
struct XKBStateNotiy {
|
||||
depressed_layout: LayoutIndex,
|
||||
latched_layout: LayoutIndex,
|
||||
locked_layout: LayoutIndex,
|
||||
}
|
||||
|
||||
pub struct X11ClientState {
|
||||
pub(crate) loop_handle: LoopHandle<'static, X11Client>,
|
||||
pub(crate) event_loop: Option<calloop::EventLoop<'static, X11Client>>,
|
||||
@@ -112,6 +119,7 @@ pub struct X11ClientState {
|
||||
pub(crate) windows: HashMap<xproto::Window, WindowRef>,
|
||||
pub(crate) focused_window: Option<xproto::Window>,
|
||||
pub(crate) xkb: xkbc::State,
|
||||
previous_xkb_state: XKBStateNotiy,
|
||||
pub(crate) ximc: Option<X11rbClient<Rc<XCBConnection>>>,
|
||||
pub(crate) xim_handler: Option<XimHandler>,
|
||||
pub modifiers: Modifiers,
|
||||
@@ -343,6 +351,7 @@ impl X11Client {
|
||||
windows: HashMap::default(),
|
||||
focused_window: None,
|
||||
xkb: xkb_state,
|
||||
previous_xkb_state: XKBStateNotiy::default(),
|
||||
ximc,
|
||||
xim_handler,
|
||||
|
||||
@@ -615,7 +624,11 @@ impl X11Client {
|
||||
event.latched_group as u32,
|
||||
event.locked_group.into(),
|
||||
);
|
||||
|
||||
state.previous_xkb_state = XKBStateNotiy {
|
||||
depressed_layout: event.base_group as u32,
|
||||
latched_layout: event.latched_group as u32,
|
||||
locked_layout: event.locked_group.into(),
|
||||
};
|
||||
let modifiers = Modifiers::from_xkb(&state.xkb);
|
||||
if state.modifiers == modifiers {
|
||||
drop(state);
|
||||
@@ -637,11 +650,18 @@ impl X11Client {
|
||||
let modifiers = modifiers_from_state(event.state);
|
||||
state.modifiers = modifiers;
|
||||
state.pre_ime_key_down.take();
|
||||
|
||||
let keystroke = {
|
||||
let code = event.detail.into();
|
||||
let xkb_state = state.previous_xkb_state.clone();
|
||||
state.xkb.update_mask(
|
||||
event.state.bits() as ModMask,
|
||||
0,
|
||||
0,
|
||||
xkb_state.depressed_layout,
|
||||
xkb_state.latched_layout,
|
||||
xkb_state.locked_layout,
|
||||
);
|
||||
let mut keystroke = crate::Keystroke::from_xkb(&state.xkb, modifiers, code);
|
||||
state.xkb.update_key(code, xkbc::KeyDirection::Down);
|
||||
let keysym = state.xkb.key_get_one_sym(code);
|
||||
if keysym.is_modifier_key() {
|
||||
return Some(());
|
||||
@@ -700,8 +720,16 @@ impl X11Client {
|
||||
|
||||
let keystroke = {
|
||||
let code = event.detail.into();
|
||||
let xkb_state = state.previous_xkb_state.clone();
|
||||
state.xkb.update_mask(
|
||||
event.state.bits() as ModMask,
|
||||
0,
|
||||
0,
|
||||
xkb_state.depressed_layout,
|
||||
xkb_state.latched_layout,
|
||||
xkb_state.locked_layout,
|
||||
);
|
||||
let keystroke = crate::Keystroke::from_xkb(&state.xkb, modifiers, code);
|
||||
state.xkb.update_key(code, xkbc::KeyDirection::Up);
|
||||
let keysym = state.xkb.key_get_one_sym(code);
|
||||
if keysym.is_modifier_key() {
|
||||
return Some(());
|
||||
@@ -947,20 +975,17 @@ impl X11Client {
|
||||
fn xim_handle_commit(&self, window: xproto::Window, text: String) -> Option<()> {
|
||||
let window = self.get_window(window).unwrap();
|
||||
let mut state = self.0.borrow_mut();
|
||||
if !state.composing {
|
||||
if let Some(keystroke) = state.pre_ime_key_down.take() {
|
||||
drop(state);
|
||||
window.handle_input(PlatformInput::KeyDown(crate::KeyDownEvent {
|
||||
keystroke,
|
||||
is_held: false,
|
||||
}));
|
||||
return Some(());
|
||||
}
|
||||
}
|
||||
let keystroke = state.pre_ime_key_down.take();
|
||||
state.composing = false;
|
||||
drop(state);
|
||||
if let Some(mut keystroke) = keystroke {
|
||||
keystroke.ime_key = Some(text.clone());
|
||||
window.handle_input(PlatformInput::KeyDown(crate::KeyDownEvent {
|
||||
keystroke,
|
||||
is_held: false,
|
||||
}));
|
||||
}
|
||||
|
||||
window.handle_ime_commit(text);
|
||||
Some(())
|
||||
}
|
||||
|
||||
@@ -1154,10 +1179,13 @@ impl LinuxClient for X11Client {
|
||||
let cursor = match state.cursor_cache.get(&style) {
|
||||
Some(cursor) => *cursor,
|
||||
None => {
|
||||
let cursor = state
|
||||
let Some(cursor) = state
|
||||
.cursor_handle
|
||||
.load_cursor(&state.xcb_connection, &style.to_icon_name())
|
||||
.expect("failed to load cursor");
|
||||
.log_err()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
state.cursor_cache.insert(style, cursor);
|
||||
cursor
|
||||
}
|
||||
|
||||
@@ -602,7 +602,7 @@ impl Platform for MacPlatform {
|
||||
fn prompt_for_paths(
|
||||
&self,
|
||||
options: PathPromptOptions,
|
||||
) -> oneshot::Receiver<Option<Vec<PathBuf>>> {
|
||||
) -> oneshot::Receiver<Result<Option<Vec<PathBuf>>>> {
|
||||
let (done_tx, done_rx) = oneshot::channel();
|
||||
self.foreground_executor()
|
||||
.spawn(async move {
|
||||
@@ -632,7 +632,7 @@ impl Platform for MacPlatform {
|
||||
};
|
||||
|
||||
if let Some(done_tx) = done_tx.take() {
|
||||
let _ = done_tx.send(result);
|
||||
let _ = done_tx.send(Ok(result));
|
||||
}
|
||||
});
|
||||
let block = block.copy();
|
||||
@@ -643,7 +643,7 @@ impl Platform for MacPlatform {
|
||||
done_rx
|
||||
}
|
||||
|
||||
fn prompt_for_new_path(&self, directory: &Path) -> oneshot::Receiver<Option<PathBuf>> {
|
||||
fn prompt_for_new_path(&self, directory: &Path) -> oneshot::Receiver<Result<Option<PathBuf>>> {
|
||||
let directory = directory.to_owned();
|
||||
let (done_tx, done_rx) = oneshot::channel();
|
||||
self.foreground_executor()
|
||||
@@ -665,7 +665,7 @@ impl Platform for MacPlatform {
|
||||
}
|
||||
|
||||
if let Some(done_tx) = done_tx.take() {
|
||||
let _ = done_tx.send(result);
|
||||
let _ = done_tx.send(Ok(result));
|
||||
}
|
||||
});
|
||||
let block = block.copy();
|
||||
|
||||
@@ -34,7 +34,7 @@ pub(crate) struct TestPlatform {
|
||||
#[derive(Default)]
|
||||
pub(crate) struct TestPrompts {
|
||||
multiple_choice: VecDeque<oneshot::Sender<usize>>,
|
||||
new_path: VecDeque<(PathBuf, oneshot::Sender<Option<PathBuf>>)>,
|
||||
new_path: VecDeque<(PathBuf, oneshot::Sender<Result<Option<PathBuf>>>)>,
|
||||
}
|
||||
|
||||
impl TestPlatform {
|
||||
@@ -80,7 +80,7 @@ impl TestPlatform {
|
||||
.new_path
|
||||
.pop_front()
|
||||
.expect("no pending new path prompt");
|
||||
tx.send(select_path(&path)).ok();
|
||||
tx.send(Ok(select_path(&path))).ok();
|
||||
}
|
||||
|
||||
pub(crate) fn simulate_prompt_answer(&self, response_ix: usize) {
|
||||
@@ -216,14 +216,14 @@ impl Platform for TestPlatform {
|
||||
fn prompt_for_paths(
|
||||
&self,
|
||||
_options: crate::PathPromptOptions,
|
||||
) -> oneshot::Receiver<Option<Vec<std::path::PathBuf>>> {
|
||||
) -> oneshot::Receiver<Result<Option<Vec<std::path::PathBuf>>>> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn prompt_for_new_path(
|
||||
&self,
|
||||
directory: &std::path::Path,
|
||||
) -> oneshot::Receiver<Option<std::path::PathBuf>> {
|
||||
) -> oneshot::Receiver<Result<Option<std::path::PathBuf>>> {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
self.prompts
|
||||
.borrow_mut()
|
||||
|
||||
@@ -316,7 +316,10 @@ impl Platform for WindowsPlatform {
|
||||
self.state.borrow_mut().callbacks.open_urls = Some(callback);
|
||||
}
|
||||
|
||||
fn prompt_for_paths(&self, options: PathPromptOptions) -> Receiver<Option<Vec<PathBuf>>> {
|
||||
fn prompt_for_paths(
|
||||
&self,
|
||||
options: PathPromptOptions,
|
||||
) -> Receiver<Result<Option<Vec<PathBuf>>>> {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
self.foreground_executor()
|
||||
@@ -355,7 +358,7 @@ impl Platform for WindowsPlatform {
|
||||
if hr.unwrap_err().code() == HRESULT(0x800704C7u32 as i32) {
|
||||
// user canceled error
|
||||
if let Some(tx) = tx.take() {
|
||||
tx.send(None).unwrap();
|
||||
tx.send(Ok(None)).unwrap();
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -374,10 +377,10 @@ impl Platform for WindowsPlatform {
|
||||
}
|
||||
|
||||
if let Some(tx) = tx.take() {
|
||||
if paths.len() == 0 {
|
||||
tx.send(None).unwrap();
|
||||
if paths.is_empty() {
|
||||
tx.send(Ok(None)).unwrap();
|
||||
} else {
|
||||
tx.send(Some(paths)).unwrap();
|
||||
tx.send(Ok(Some(paths))).unwrap();
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -386,27 +389,27 @@ impl Platform for WindowsPlatform {
|
||||
rx
|
||||
}
|
||||
|
||||
fn prompt_for_new_path(&self, directory: &Path) -> Receiver<Option<PathBuf>> {
|
||||
fn prompt_for_new_path(&self, directory: &Path) -> Receiver<Result<Option<PathBuf>>> {
|
||||
let directory = directory.to_owned();
|
||||
let (tx, rx) = oneshot::channel();
|
||||
self.foreground_executor()
|
||||
.spawn(async move {
|
||||
unsafe {
|
||||
let Ok(dialog) = show_savefile_dialog(directory) else {
|
||||
let _ = tx.send(None);
|
||||
let _ = tx.send(Ok(None));
|
||||
return;
|
||||
};
|
||||
let Ok(_) = dialog.Show(None) else {
|
||||
let _ = tx.send(None); // user cancel
|
||||
let _ = tx.send(Ok(None)); // user cancel
|
||||
return;
|
||||
};
|
||||
if let Ok(shell_item) = dialog.GetResult() {
|
||||
if let Ok(file) = shell_item.GetDisplayName(SIGDN_FILESYSPATH) {
|
||||
let _ = tx.send(Some(PathBuf::from(file.to_string().unwrap())));
|
||||
let _ = tx.send(Ok(Some(PathBuf::from(file.to_string().unwrap()))));
|
||||
return;
|
||||
}
|
||||
}
|
||||
let _ = tx.send(None);
|
||||
let _ = tx.send(Ok(None));
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
|
||||
@@ -57,7 +57,7 @@ gpui = { workspace = true, features = ["test-support"] }
|
||||
live_kit_server.workspace = true
|
||||
nanoid.workspace = true
|
||||
sha2.workspace = true
|
||||
simplelog = "0.9"
|
||||
simplelog.workspace = true
|
||||
|
||||
[build-dependencies]
|
||||
serde.workspace = true
|
||||
|
||||
@@ -7,7 +7,7 @@ use anyhow::{anyhow, Context, Result};
|
||||
use collections::HashMap;
|
||||
use futures::{channel::oneshot, io::BufWriter, select, AsyncRead, AsyncWrite, Future, FutureExt};
|
||||
use gpui::{AppContext, AsyncAppContext, BackgroundExecutor, Task};
|
||||
use parking_lot::Mutex;
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use postage::{barrier, prelude::Stream};
|
||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||
use serde_json::{json, value::RawValue, Value};
|
||||
@@ -24,6 +24,7 @@ use std::{
|
||||
ffi::OsString,
|
||||
fmt,
|
||||
io::Write,
|
||||
ops::DerefMut,
|
||||
path::PathBuf,
|
||||
pin::Pin,
|
||||
sync::{
|
||||
@@ -69,7 +70,7 @@ pub struct LanguageServer {
|
||||
next_id: AtomicI32,
|
||||
outbound_tx: channel::Sender<String>,
|
||||
name: Arc<str>,
|
||||
capabilities: ServerCapabilities,
|
||||
capabilities: RwLock<ServerCapabilities>,
|
||||
code_action_kinds: Option<Vec<CodeActionKind>>,
|
||||
notification_handlers: Arc<Mutex<HashMap<&'static str, NotificationHandler>>>,
|
||||
response_handlers: Arc<Mutex<Option<HashMap<RequestId, ResponseHandler>>>>,
|
||||
@@ -640,12 +641,19 @@ impl LanguageServer {
|
||||
..Default::default()
|
||||
}),
|
||||
formatting: Some(DynamicRegistrationClientCapabilities {
|
||||
dynamic_registration: None,
|
||||
dynamic_registration: Some(true),
|
||||
}),
|
||||
range_formatting: Some(DynamicRegistrationClientCapabilities {
|
||||
dynamic_registration: Some(true),
|
||||
}),
|
||||
on_type_formatting: Some(DynamicRegistrationClientCapabilities {
|
||||
dynamic_registration: None,
|
||||
dynamic_registration: Some(true),
|
||||
}),
|
||||
..Default::default()
|
||||
synchronization: Some(TextDocumentSyncClientCapabilities {
|
||||
did_save: Some(true),
|
||||
..TextDocumentSyncClientCapabilities::default()
|
||||
}),
|
||||
..TextDocumentClientCapabilities::default()
|
||||
}),
|
||||
experimental: Some(json!({
|
||||
"serverStatusNotification": true,
|
||||
@@ -676,7 +684,7 @@ impl LanguageServer {
|
||||
if let Some(info) = response.server_info {
|
||||
self.name = info.name.into();
|
||||
}
|
||||
self.capabilities = response.capabilities;
|
||||
self.capabilities = RwLock::new(response.capabilities);
|
||||
|
||||
self.notify::<notification::Initialized>(InitializedParams {})?;
|
||||
Ok(Arc::new(self))
|
||||
@@ -891,8 +899,12 @@ impl LanguageServer {
|
||||
}
|
||||
|
||||
/// Get the reported capabilities of the running language server.
|
||||
pub fn capabilities(&self) -> &ServerCapabilities {
|
||||
&self.capabilities
|
||||
pub fn capabilities(&self) -> ServerCapabilities {
|
||||
self.capabilities.read().clone()
|
||||
}
|
||||
|
||||
pub fn update_capabilities(&self, update: impl FnOnce(&mut ServerCapabilities)) {
|
||||
update(self.capabilities.write().deref_mut());
|
||||
}
|
||||
|
||||
/// Get the id of the running language server.
|
||||
|
||||
@@ -1622,11 +1622,7 @@ impl OutlinePanel {
|
||||
ExcerptOutlines::Invalidated(_) => ExcerptOutlines::NotFetched,
|
||||
ExcerptOutlines::NotFetched => ExcerptOutlines::NotFetched,
|
||||
},
|
||||
None => {
|
||||
new_collapsed_entries
|
||||
.insert(CollapsedEntry::Excerpt(buffer_id, excerpt_id));
|
||||
ExcerptOutlines::NotFetched
|
||||
}
|
||||
None => ExcerptOutlines::NotFetched,
|
||||
};
|
||||
new_excerpts.entry(buffer_id).or_default().insert(
|
||||
excerpt_id,
|
||||
@@ -1674,11 +1670,6 @@ impl OutlinePanel {
|
||||
.insert(CollapsedEntry::ExternalFile(buffer_id));
|
||||
}
|
||||
}
|
||||
|
||||
for excerpt_id in &excerpts {
|
||||
new_collapsed_entries
|
||||
.insert(CollapsedEntry::Excerpt(buffer_id, *excerpt_id));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(worktree) = worktree {
|
||||
|
||||
@@ -84,7 +84,7 @@ impl Prettier {
|
||||
path_to_check.pop();
|
||||
}
|
||||
|
||||
let mut project_path_with_prettier_dependency = None;
|
||||
let mut closest_package_json_path = None;
|
||||
loop {
|
||||
if installed_prettiers.contains(&path_to_check) {
|
||||
log::debug!("Found prettier path {path_to_check:?} in installed prettiers");
|
||||
@@ -92,61 +92,44 @@ impl Prettier {
|
||||
} else if let Some(package_json_contents) =
|
||||
read_package_json(fs, &path_to_check).await?
|
||||
{
|
||||
if has_prettier_in_package_json(&package_json_contents) {
|
||||
if has_prettier_in_node_modules(fs, &path_to_check).await? {
|
||||
log::debug!("Found prettier path {path_to_check:?} in both package.json and node_modules");
|
||||
return Ok(ControlFlow::Continue(Some(path_to_check)));
|
||||
} else if project_path_with_prettier_dependency.is_none() {
|
||||
project_path_with_prettier_dependency = Some(path_to_check.clone());
|
||||
}
|
||||
if has_prettier_in_node_modules(fs, &path_to_check).await? {
|
||||
log::debug!("Found prettier path {path_to_check:?} in the node_modules");
|
||||
return Ok(ControlFlow::Continue(Some(path_to_check)));
|
||||
} else {
|
||||
match package_json_contents.get("workspaces") {
|
||||
Some(serde_json::Value::Array(workspaces)) => {
|
||||
match &project_path_with_prettier_dependency {
|
||||
Some(project_path_with_prettier_dependency) => {
|
||||
let subproject_path = project_path_with_prettier_dependency.strip_prefix(&path_to_check).expect("traversing path parents, should be able to strip prefix");
|
||||
if workspaces.iter().filter_map(|value| {
|
||||
if let serde_json::Value::String(s) = value {
|
||||
Some(s.clone())
|
||||
} else {
|
||||
log::warn!("Skipping non-string 'workspaces' value: {value:?}");
|
||||
None
|
||||
}
|
||||
}).any(|workspace_definition| {
|
||||
if let Some(path_matcher) = PathMatcher::new(&[workspace_definition.clone()]).ok() {
|
||||
path_matcher.is_match(subproject_path)
|
||||
} else {
|
||||
workspace_definition == subproject_path.to_string_lossy()
|
||||
}
|
||||
}) {
|
||||
anyhow::ensure!(has_prettier_in_node_modules(fs, &path_to_check).await?, "Found prettier path {path_to_check:?} in the workspace root for project in {project_path_with_prettier_dependency:?}, but it's not installed into workspace root's node_modules");
|
||||
log::info!("Found prettier path {path_to_check:?} in the workspace root for project in {project_path_with_prettier_dependency:?}");
|
||||
return Ok(ControlFlow::Continue(Some(path_to_check)));
|
||||
match &closest_package_json_path {
|
||||
None => closest_package_json_path = Some(path_to_check.clone()),
|
||||
Some(closest_package_json_path) => {
|
||||
match package_json_contents.get("workspaces") {
|
||||
Some(serde_json::Value::Array(workspaces)) => {
|
||||
let subproject_path = closest_package_json_path.strip_prefix(&path_to_check).expect("traversing path parents, should be able to strip prefix");
|
||||
if workspaces.iter().filter_map(|value| {
|
||||
if let serde_json::Value::String(s) = value {
|
||||
Some(s.clone())
|
||||
} else {
|
||||
log::warn!("Skipping path {path_to_check:?} that has prettier in its 'node_modules' subdirectory, but is not included in its package.json workspaces {workspaces:?}");
|
||||
log::warn!("Skipping non-string 'workspaces' value: {value:?}");
|
||||
None
|
||||
}
|
||||
}).any(|workspace_definition| {
|
||||
workspace_definition == subproject_path.to_string_lossy() || PathMatcher::new(&[workspace_definition]).ok().map_or(false, |path_matcher| path_matcher.is_match(subproject_path))
|
||||
}) {
|
||||
anyhow::ensure!(has_prettier_in_node_modules(fs, &path_to_check).await?, "Path {path_to_check:?} is the workspace root for project in {closest_package_json_path:?}, but it has no prettier installed");
|
||||
log::info!("Found prettier path {path_to_check:?} in the workspace root for project in {closest_package_json_path:?}");
|
||||
return Ok(ControlFlow::Continue(Some(path_to_check)));
|
||||
} else {
|
||||
log::warn!("Skipping path {path_to_check:?} workspace root with workspaces {workspaces:?} that have no prettier installed");
|
||||
}
|
||||
None => {
|
||||
log::warn!("Skipping path {path_to_check:?} that has prettier in its 'node_modules' subdirectory, but has no prettier in its package.json");
|
||||
}
|
||||
}
|
||||
},
|
||||
Some(unknown) => log::error!("Failed to parse workspaces for {path_to_check:?} from package.json, got {unknown:?}. Skipping."),
|
||||
None => log::warn!("Skipping path {path_to_check:?} that has no prettier dependency and no workspaces section in its package.json"),
|
||||
},
|
||||
Some(unknown) => log::error!("Failed to parse workspaces for {path_to_check:?} from package.json, got {unknown:?}. Skipping."),
|
||||
None => log::warn!("Skipping path {path_to_check:?} that has no prettier dependency and no workspaces section in its package.json"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !path_to_check.pop() {
|
||||
match project_path_with_prettier_dependency {
|
||||
Some(closest_prettier_discovered) => {
|
||||
anyhow::bail!("No prettier found in node_modules for ancestors of {locate_from:?}, but discovered prettier package.json dependency in {closest_prettier_discovered:?}")
|
||||
}
|
||||
None => {
|
||||
log::debug!("Found no prettier in ancestors of {locate_from:?}");
|
||||
return Ok(ControlFlow::Continue(None));
|
||||
}
|
||||
}
|
||||
log::debug!("Found no prettier in ancestors of {locate_from:?}");
|
||||
return Ok(ControlFlow::Continue(None));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -448,22 +431,6 @@ async fn read_package_json(
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn has_prettier_in_package_json(
|
||||
package_json_contents: &HashMap<String, serde_json::Value>,
|
||||
) -> bool {
|
||||
if let Some(serde_json::Value::Object(o)) = package_json_contents.get("dependencies") {
|
||||
if o.contains_key(PRETTIER_PACKAGE_NAME) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if let Some(serde_json::Value::Object(o)) = package_json_contents.get("devDependencies") {
|
||||
if o.contains_key(PRETTIER_PACKAGE_NAME) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
enum Format {}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
||||
@@ -548,40 +515,36 @@ mod tests {
|
||||
)
|
||||
.await;
|
||||
|
||||
assert!(
|
||||
matches!(
|
||||
Prettier::locate_prettier_installation(
|
||||
fs.as_ref(),
|
||||
&HashSet::default(),
|
||||
Path::new("/root/.config/zed/settings.json"),
|
||||
)
|
||||
.await,
|
||||
Ok(ControlFlow::Continue(None))
|
||||
),
|
||||
"Should successfully find no prettier for path hierarchy without it"
|
||||
assert_eq!(
|
||||
Prettier::locate_prettier_installation(
|
||||
fs.as_ref(),
|
||||
&HashSet::default(),
|
||||
Path::new("/root/.config/zed/settings.json"),
|
||||
)
|
||||
.await
|
||||
.unwrap(),
|
||||
ControlFlow::Continue(None),
|
||||
"Should find no prettier for path hierarchy without it"
|
||||
);
|
||||
assert!(
|
||||
matches!(
|
||||
Prettier::locate_prettier_installation(
|
||||
fs.as_ref(),
|
||||
&HashSet::default(),
|
||||
Path::new("/root/work/project/src/index.js")
|
||||
)
|
||||
.await,
|
||||
Ok(ControlFlow::Continue(None))
|
||||
),
|
||||
"Should successfully find no prettier for path hierarchy that has node_modules with prettier, but no package.json mentions of it"
|
||||
assert_eq!(
|
||||
Prettier::locate_prettier_installation(
|
||||
fs.as_ref(),
|
||||
&HashSet::default(),
|
||||
Path::new("/root/work/project/src/index.js")
|
||||
)
|
||||
.await.unwrap(),
|
||||
ControlFlow::Continue(Some(PathBuf::from("/root/work/project"))),
|
||||
"Should successfully find a prettier for path hierarchy that has node_modules with prettier, but no package.json mentions of it"
|
||||
);
|
||||
assert!(
|
||||
matches!(
|
||||
Prettier::locate_prettier_installation(
|
||||
fs.as_ref(),
|
||||
&HashSet::default(),
|
||||
Path::new("/root/work/project/node_modules/expect/build/print.js")
|
||||
)
|
||||
.await,
|
||||
Ok(ControlFlow::Break(()))
|
||||
),
|
||||
assert_eq!(
|
||||
Prettier::locate_prettier_installation(
|
||||
fs.as_ref(),
|
||||
&HashSet::default(),
|
||||
Path::new("/root/work/project/node_modules/expect/build/print.js")
|
||||
)
|
||||
.await
|
||||
.unwrap(),
|
||||
ControlFlow::Break(()),
|
||||
"Should not format files inside node_modules/"
|
||||
);
|
||||
}
|
||||
@@ -691,18 +654,17 @@ mod tests {
|
||||
)
|
||||
.await;
|
||||
|
||||
match Prettier::locate_prettier_installation(
|
||||
fs.as_ref(),
|
||||
&HashSet::default(),
|
||||
Path::new("/root/work/web_blog/pages/[slug].tsx")
|
||||
)
|
||||
.await {
|
||||
Ok(path) => panic!("Expected to fail for prettier in package.json but not in node_modules found, but got path {path:?}"),
|
||||
Err(e) => {
|
||||
let message = e.to_string();
|
||||
assert!(message.contains("/root/work/web_blog"), "Error message should mention which project had prettier defined");
|
||||
},
|
||||
};
|
||||
assert_eq!(
|
||||
Prettier::locate_prettier_installation(
|
||||
fs.as_ref(),
|
||||
&HashSet::default(),
|
||||
Path::new("/root/work/web_blog/pages/[slug].tsx")
|
||||
)
|
||||
.await
|
||||
.unwrap(),
|
||||
ControlFlow::Continue(None),
|
||||
"Should find no prettier when node_modules don't have it"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Prettier::locate_prettier_installation(
|
||||
|
||||
@@ -2471,7 +2471,7 @@ impl LspCommand for InlayHints {
|
||||
lsp_adapter.name.0.as_ref() == "typescript-language-server";
|
||||
|
||||
let hints = message.unwrap_or_default().into_iter().map(|lsp_hint| {
|
||||
let resolve_state = if InlayHints::can_resolve_inlays(lsp_server.capabilities()) {
|
||||
let resolve_state = if InlayHints::can_resolve_inlays(&lsp_server.capabilities()) {
|
||||
ResolveState::CanResolve(lsp_server.server_id(), lsp_hint.data.clone())
|
||||
} else {
|
||||
ResolveState::Resolved
|
||||
|
||||
@@ -2853,15 +2853,21 @@ impl Project {
|
||||
};
|
||||
|
||||
for (_, _, server) in self.language_servers_for_worktree(worktree_id) {
|
||||
let text = include_text(server.as_ref()).then(|| buffer.read(cx).text());
|
||||
server
|
||||
.notify::<lsp::notification::DidSaveTextDocument>(
|
||||
lsp::DidSaveTextDocumentParams {
|
||||
text_document: text_document.clone(),
|
||||
text,
|
||||
},
|
||||
)
|
||||
.log_err();
|
||||
if let Some(include_text) = include_text(server.as_ref()) {
|
||||
let text = if include_text {
|
||||
Some(buffer.read(cx).text())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
server
|
||||
.notify::<lsp::notification::DidSaveTextDocument>(
|
||||
lsp::DidSaveTextDocumentParams {
|
||||
text_document: text_document.clone(),
|
||||
text,
|
||||
},
|
||||
)
|
||||
.log_err();
|
||||
}
|
||||
}
|
||||
|
||||
for language_server_id in self.language_server_ids_for_buffer(buffer.read(cx), cx) {
|
||||
@@ -3496,7 +3502,7 @@ impl Project {
|
||||
}
|
||||
|
||||
async fn setup_pending_language_server(
|
||||
this: WeakModel<Self>,
|
||||
project: WeakModel<Self>,
|
||||
override_options: Option<serde_json::Value>,
|
||||
pending_server: PendingLanguageServer,
|
||||
delegate: Arc<dyn LspAdapterDelegate>,
|
||||
@@ -3515,7 +3521,7 @@ impl Project {
|
||||
language_server
|
||||
.on_notification::<lsp::notification::PublishDiagnostics, _>({
|
||||
let adapter = adapter.clone();
|
||||
let this = this.clone();
|
||||
let this = project.clone();
|
||||
move |mut params, mut cx| {
|
||||
let adapter = adapter.clone();
|
||||
if let Some(this) = this.upgrade() {
|
||||
@@ -3569,7 +3575,7 @@ impl Project {
|
||||
// to these requests when initializing.
|
||||
language_server
|
||||
.on_request::<lsp::request::WorkDoneProgressCreate, _, _>({
|
||||
let this = this.clone();
|
||||
let this = project.clone();
|
||||
move |params, mut cx| {
|
||||
let this = this.clone();
|
||||
async move {
|
||||
@@ -3590,20 +3596,103 @@ impl Project {
|
||||
|
||||
language_server
|
||||
.on_request::<lsp::request::RegisterCapability, _, _>({
|
||||
let this = this.clone();
|
||||
let project = project.clone();
|
||||
move |params, mut cx| {
|
||||
let this = this.clone();
|
||||
let project = project.clone();
|
||||
async move {
|
||||
for reg in params.registrations {
|
||||
if reg.method == "workspace/didChangeWatchedFiles" {
|
||||
if let Some(options) = reg.register_options {
|
||||
let options = serde_json::from_value(options)?;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.on_lsp_did_change_watched_files(
|
||||
server_id, ®.id, options, cx,
|
||||
);
|
||||
})?;
|
||||
match reg.method.as_str() {
|
||||
"workspace/didChangeWatchedFiles" => {
|
||||
if let Some(options) = reg.register_options {
|
||||
let options = serde_json::from_value(options)?;
|
||||
project.update(&mut cx, |project, cx| {
|
||||
project.on_lsp_did_change_watched_files(
|
||||
server_id, ®.id, options, cx,
|
||||
);
|
||||
})?;
|
||||
}
|
||||
}
|
||||
"textDocument/rangeFormatting" => {
|
||||
project.update(&mut cx, |project, _| {
|
||||
if let Some(server) =
|
||||
project.language_server_for_id(server_id)
|
||||
{
|
||||
let options = reg
|
||||
.register_options
|
||||
.map(|options| {
|
||||
serde_json::from_value::<
|
||||
lsp::DocumentRangeFormattingOptions,
|
||||
>(
|
||||
options
|
||||
)
|
||||
})
|
||||
.transpose()?;
|
||||
let provider = match options {
|
||||
None => OneOf::Left(true),
|
||||
Some(options) => OneOf::Right(options),
|
||||
};
|
||||
server.update_capabilities(|capabilities| {
|
||||
capabilities.document_range_formatting_provider =
|
||||
Some(provider);
|
||||
})
|
||||
}
|
||||
anyhow::Ok(())
|
||||
})??;
|
||||
}
|
||||
"textDocument/onTypeFormatting" => {
|
||||
project.update(&mut cx, |project, _| {
|
||||
if let Some(server) =
|
||||
project.language_server_for_id(server_id)
|
||||
{
|
||||
let options = reg
|
||||
.register_options
|
||||
.map(|options| {
|
||||
serde_json::from_value::<
|
||||
lsp::DocumentOnTypeFormattingOptions,
|
||||
>(
|
||||
options
|
||||
)
|
||||
})
|
||||
.transpose()?;
|
||||
if let Some(options) = options {
|
||||
server.update_capabilities(|capabilities| {
|
||||
capabilities
|
||||
.document_on_type_formatting_provider =
|
||||
Some(options);
|
||||
})
|
||||
}
|
||||
}
|
||||
anyhow::Ok(())
|
||||
})??;
|
||||
}
|
||||
"textDocument/formatting" => {
|
||||
project.update(&mut cx, |project, _| {
|
||||
if let Some(server) =
|
||||
project.language_server_for_id(server_id)
|
||||
{
|
||||
let options = reg
|
||||
.register_options
|
||||
.map(|options| {
|
||||
serde_json::from_value::<
|
||||
lsp::DocumentFormattingOptions,
|
||||
>(
|
||||
options
|
||||
)
|
||||
})
|
||||
.transpose()?;
|
||||
let provider = match options {
|
||||
None => OneOf::Left(true),
|
||||
Some(options) => OneOf::Right(options),
|
||||
};
|
||||
server.update_capabilities(|capabilities| {
|
||||
capabilities.document_formatting_provider =
|
||||
Some(provider);
|
||||
})
|
||||
}
|
||||
anyhow::Ok(())
|
||||
})??;
|
||||
}
|
||||
_ => log::warn!("unhandled capability registration: {reg:?}"),
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@@ -3614,17 +3703,55 @@ impl Project {
|
||||
|
||||
language_server
|
||||
.on_request::<lsp::request::UnregisterCapability, _, _>({
|
||||
let this = this.clone();
|
||||
let this = project.clone();
|
||||
move |params, mut cx| {
|
||||
let this = this.clone();
|
||||
let project = this.clone();
|
||||
async move {
|
||||
for unreg in params.unregisterations.iter() {
|
||||
if unreg.method == "workspace/didChangeWatchedFiles" {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.on_lsp_unregister_did_change_watched_files(
|
||||
server_id, &unreg.id, cx,
|
||||
);
|
||||
})?;
|
||||
match unreg.method.as_str() {
|
||||
"workspace/didChangeWatchedFiles" => {
|
||||
project.update(&mut cx, |project, cx| {
|
||||
project.on_lsp_unregister_did_change_watched_files(
|
||||
server_id, &unreg.id, cx,
|
||||
);
|
||||
})?;
|
||||
}
|
||||
"textDocument/rangeFormatting" => {
|
||||
project.update(&mut cx, |project, _| {
|
||||
if let Some(server) =
|
||||
project.language_server_for_id(server_id)
|
||||
{
|
||||
server.update_capabilities(|capabilities| {
|
||||
capabilities.document_range_formatting_provider =
|
||||
None
|
||||
})
|
||||
}
|
||||
})?;
|
||||
}
|
||||
"textDocument/onTypeFormatting" => {
|
||||
project.update(&mut cx, |project, _| {
|
||||
if let Some(server) =
|
||||
project.language_server_for_id(server_id)
|
||||
{
|
||||
server.update_capabilities(|capabilities| {
|
||||
capabilities.document_on_type_formatting_provider =
|
||||
None;
|
||||
})
|
||||
}
|
||||
})?;
|
||||
}
|
||||
"textDocument/formatting" => {
|
||||
project.update(&mut cx, |project, _| {
|
||||
if let Some(server) =
|
||||
project.language_server_for_id(server_id)
|
||||
{
|
||||
server.update_capabilities(|capabilities| {
|
||||
capabilities.document_formatting_provider = None;
|
||||
})
|
||||
}
|
||||
})?;
|
||||
}
|
||||
_ => log::warn!("unhandled capability unregistration: {unreg:?}"),
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@@ -3636,7 +3763,7 @@ impl Project {
|
||||
language_server
|
||||
.on_request::<lsp::request::ApplyWorkspaceEdit, _, _>({
|
||||
let adapter = adapter.clone();
|
||||
let this = this.clone();
|
||||
let this = project.clone();
|
||||
move |params, cx| {
|
||||
Self::on_lsp_workspace_edit(
|
||||
this.clone(),
|
||||
@@ -3651,7 +3778,7 @@ impl Project {
|
||||
|
||||
language_server
|
||||
.on_request::<lsp::request::InlayHintRefreshRequest, _, _>({
|
||||
let this = this.clone();
|
||||
let this = project.clone();
|
||||
move |(), mut cx| {
|
||||
let this = this.clone();
|
||||
async move {
|
||||
@@ -3670,7 +3797,7 @@ impl Project {
|
||||
|
||||
language_server
|
||||
.on_request::<lsp::request::ShowMessageRequest, _, _>({
|
||||
let this = this.clone();
|
||||
let this = project.clone();
|
||||
let name = name.to_string();
|
||||
move |params, mut cx| {
|
||||
let this = this.clone();
|
||||
@@ -3709,7 +3836,7 @@ impl Project {
|
||||
|
||||
language_server
|
||||
.on_notification::<ServerStatus, _>({
|
||||
let this = this.clone();
|
||||
let this = project.clone();
|
||||
let name = name.to_string();
|
||||
move |params, mut cx| {
|
||||
let this = this.clone();
|
||||
@@ -3752,7 +3879,7 @@ impl Project {
|
||||
.detach();
|
||||
language_server
|
||||
.on_notification::<lsp::notification::ShowMessage, _>({
|
||||
let this = this.clone();
|
||||
let this = project.clone();
|
||||
let name = name.to_string();
|
||||
move |params, mut cx| {
|
||||
let this = this.clone();
|
||||
@@ -3779,7 +3906,7 @@ impl Project {
|
||||
.detach();
|
||||
language_server
|
||||
.on_notification::<lsp::notification::Progress, _>(move |params, mut cx| {
|
||||
if let Some(this) = this.upgrade() {
|
||||
if let Some(this) = project.upgrade() {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.on_lsp_progress(
|
||||
params,
|
||||
@@ -7026,7 +7153,7 @@ impl Project {
|
||||
} else {
|
||||
return Task::ready(Ok(hint));
|
||||
};
|
||||
if !InlayHints::can_resolve_inlays(lang_server.capabilities()) {
|
||||
if !InlayHints::can_resolve_inlays(&lang_server.capabilities()) {
|
||||
return Task::ready(Ok(hint));
|
||||
}
|
||||
|
||||
@@ -7438,7 +7565,7 @@ impl Project {
|
||||
let lsp_params = request.to_lsp(&file.abs_path(cx), buffer, &language_server, cx);
|
||||
let status = request.status();
|
||||
return cx.spawn(move |this, cx| async move {
|
||||
if !request.check_capabilities(language_server.capabilities()) {
|
||||
if !request.check_capabilities(&language_server.capabilities()) {
|
||||
return Ok(Default::default());
|
||||
}
|
||||
|
||||
@@ -7532,7 +7659,7 @@ impl Project {
|
||||
let scope = position.and_then(|position| snapshot.language_scope_at(position));
|
||||
let mut response_results = self
|
||||
.language_servers_for_buffer(buffer.read(cx), cx)
|
||||
.filter(|(_, server)| server_capabilities_check(server.capabilities()))
|
||||
.filter(|(_, server)| server_capabilities_check(&server.capabilities()))
|
||||
.filter(|(adapter, _)| {
|
||||
scope
|
||||
.as_ref()
|
||||
@@ -11713,20 +11840,27 @@ fn is_not_found_error(error: &anyhow::Error) -> bool {
|
||||
.is_some_and(|err| err.kind() == io::ErrorKind::NotFound)
|
||||
}
|
||||
|
||||
fn include_text(server: &lsp::LanguageServer) -> bool {
|
||||
server
|
||||
.capabilities()
|
||||
.text_document_sync
|
||||
.as_ref()
|
||||
.and_then(|sync| match sync {
|
||||
lsp::TextDocumentSyncCapability::Kind(_) => None,
|
||||
lsp::TextDocumentSyncCapability::Options(options) => options.save.as_ref(),
|
||||
})
|
||||
.and_then(|save_options| match save_options {
|
||||
lsp::TextDocumentSyncSaveOptions::Supported(_) => None,
|
||||
lsp::TextDocumentSyncSaveOptions::SaveOptions(options) => options.include_text,
|
||||
})
|
||||
.unwrap_or(false)
|
||||
fn include_text(server: &lsp::LanguageServer) -> Option<bool> {
|
||||
match server.capabilities().text_document_sync.as_ref()? {
|
||||
lsp::TextDocumentSyncCapability::Kind(kind) => match kind {
|
||||
&lsp::TextDocumentSyncKind::NONE => None,
|
||||
&lsp::TextDocumentSyncKind::FULL => Some(true),
|
||||
&lsp::TextDocumentSyncKind::INCREMENTAL => Some(false),
|
||||
_ => None,
|
||||
},
|
||||
lsp::TextDocumentSyncCapability::Options(options) => match options.save.as_ref()? {
|
||||
lsp::TextDocumentSyncSaveOptions::Supported(supported) => {
|
||||
if *supported {
|
||||
Some(true)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
lsp::TextDocumentSyncSaveOptions::SaveOptions(save_options) => {
|
||||
Some(save_options.include_text.unwrap_or(false))
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
async fn load_shell_environment(dir: &Path) -> Result<HashMap<String, String>> {
|
||||
|
||||
@@ -322,6 +322,12 @@ async fn test_managing_language_servers(cx: &mut gpui::TestAppContext) {
|
||||
trigger_characters: Some(vec![".".to_string(), "::".to_string()]),
|
||||
..Default::default()
|
||||
}),
|
||||
text_document_sync: Some(lsp::TextDocumentSyncCapability::Options(
|
||||
lsp::TextDocumentSyncOptions {
|
||||
save: Some(lsp::TextDocumentSyncSaveOptions::Supported(true)),
|
||||
..Default::default()
|
||||
},
|
||||
)),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
@@ -336,6 +342,12 @@ async fn test_managing_language_servers(cx: &mut gpui::TestAppContext) {
|
||||
trigger_characters: Some(vec![":".to_string()]),
|
||||
..Default::default()
|
||||
}),
|
||||
text_document_sync: Some(lsp::TextDocumentSyncCapability::Options(
|
||||
lsp::TextDocumentSyncOptions {
|
||||
save: Some(lsp::TextDocumentSyncSaveOptions::Supported(true)),
|
||||
..Default::default()
|
||||
},
|
||||
)),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
|
||||
@@ -29,7 +29,7 @@ picker.workspace = true
|
||||
project.workspace = true
|
||||
rust-embed.workspace = true
|
||||
settings.workspace = true
|
||||
simplelog = "0.9"
|
||||
simplelog.workspace = true
|
||||
story.workspace = true
|
||||
strum = { version = "0.25.0", features = ["derive"] }
|
||||
theme.workspace = true
|
||||
|
||||
@@ -20,7 +20,7 @@ schemars = { workspace = true, features = ["indexmap"] }
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
serde_json_lenient.workspace = true
|
||||
simplelog = "0.9"
|
||||
simplelog.workspace= true
|
||||
strum = { version = "0.25.0", features = ["derive"] }
|
||||
theme.workspace = true
|
||||
vscode_theme = "0.2.0"
|
||||
|
||||
@@ -12,6 +12,7 @@ use indexmap::IndexMap;
|
||||
use log::LevelFilter;
|
||||
use schemars::schema_for;
|
||||
use serde::Deserialize;
|
||||
use simplelog::ColorChoice;
|
||||
use simplelog::{TermLogger, TerminalMode};
|
||||
use theme::{Appearance, AppearanceContent, ThemeFamilyContent};
|
||||
|
||||
@@ -94,11 +95,6 @@ fn main() -> Result<()> {
|
||||
|
||||
let log_config = {
|
||||
let mut config = simplelog::ConfigBuilder::new();
|
||||
config
|
||||
.set_level_color(log::Level::Trace, simplelog::Color::Cyan)
|
||||
.set_level_color(log::Level::Info, simplelog::Color::Blue)
|
||||
.set_level_color(log::Level::Warn, simplelog::Color::Yellow)
|
||||
.set_level_color(log::Level::Error, simplelog::Color::Red);
|
||||
|
||||
if !args.warn_on_missing {
|
||||
config.add_filter_ignore_str("theme_printer");
|
||||
@@ -107,8 +103,13 @@ fn main() -> Result<()> {
|
||||
config.build()
|
||||
};
|
||||
|
||||
TermLogger::init(LevelFilter::Trace, log_config, TerminalMode::Mixed)
|
||||
.expect("could not initialize logger");
|
||||
TermLogger::init(
|
||||
LevelFilter::Trace,
|
||||
log_config,
|
||||
TerminalMode::Mixed,
|
||||
ColorChoice::Auto,
|
||||
)
|
||||
.expect("could not initialize logger");
|
||||
|
||||
if let Some(command) = args.command {
|
||||
match command {
|
||||
|
||||
@@ -123,20 +123,22 @@ impl Render for WelcomePage {
|
||||
.ok();
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
Button::new("install-cli", "Install the CLI")
|
||||
.full_width()
|
||||
.on_click(cx.listener(|this, _, cx| {
|
||||
this.telemetry.report_app_event(
|
||||
"welcome page: install cli".to_string(),
|
||||
);
|
||||
cx.app_mut()
|
||||
.spawn(|cx| async move {
|
||||
install_cli::install_cli(&cx).await
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
})),
|
||||
)
|
||||
.when(cfg!(target_os = "macos"), |el| {
|
||||
el.child(
|
||||
Button::new("install-cli", "Install the CLI")
|
||||
.full_width()
|
||||
.on_click(cx.listener(|this, _, cx| {
|
||||
this.telemetry.report_app_event(
|
||||
"welcome page: install cli".to_string(),
|
||||
);
|
||||
cx.app_mut()
|
||||
.spawn(|cx| async move {
|
||||
install_cli::install_cli(&cx).await
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
})),
|
||||
)
|
||||
})
|
||||
.child(
|
||||
Button::new("sign-in-to-copilot", "Sign in to GitHub Copilot")
|
||||
.full_width()
|
||||
|
||||
@@ -160,14 +160,23 @@ impl Workspace {
|
||||
self.show_notification(
|
||||
NotificationId::unique::<WorkspaceErrorNotification>(),
|
||||
cx,
|
||||
|cx| {
|
||||
cx.new_view(|_cx| {
|
||||
simple_message_notification::MessageNotification::new(format!("Error: {err:#}"))
|
||||
})
|
||||
},
|
||||
|cx| cx.new_view(|_cx| ErrorMessagePrompt::new(format!("Error: {err:#}"))),
|
||||
);
|
||||
}
|
||||
|
||||
pub fn show_portal_error(&mut self, err: String, cx: &mut ViewContext<Self>) {
|
||||
struct PortalError;
|
||||
|
||||
self.show_notification(NotificationId::unique::<PortalError>(), cx, |cx| {
|
||||
cx.new_view(|_cx| {
|
||||
ErrorMessagePrompt::new(err.to_string()).with_link_button(
|
||||
"See docs",
|
||||
"https://zed.dev/docs/linux#i-cant-open-any-files",
|
||||
)
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
pub fn dismiss_notification(&mut self, id: &NotificationId, cx: &mut ViewContext<Self>) {
|
||||
self.dismiss_notification_internal(id, cx)
|
||||
}
|
||||
@@ -349,6 +358,84 @@ impl Render for LanguageServerPrompt {
|
||||
|
||||
impl EventEmitter<DismissEvent> for LanguageServerPrompt {}
|
||||
|
||||
pub struct ErrorMessagePrompt {
|
||||
message: SharedString,
|
||||
label_and_url_button: Option<(SharedString, SharedString)>,
|
||||
}
|
||||
|
||||
impl ErrorMessagePrompt {
|
||||
pub fn new<S>(message: S) -> Self
|
||||
where
|
||||
S: Into<SharedString>,
|
||||
{
|
||||
Self {
|
||||
message: message.into(),
|
||||
label_and_url_button: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_link_button<S>(mut self, label: S, url: S) -> Self
|
||||
where
|
||||
S: Into<SharedString>,
|
||||
{
|
||||
self.label_and_url_button = Some((label.into(), url.into()));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for ErrorMessagePrompt {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
h_flex()
|
||||
.id("error_message_prompt_notification")
|
||||
.occlude()
|
||||
.elevation_3(cx)
|
||||
.items_start()
|
||||
.justify_between()
|
||||
.p_2()
|
||||
.gap_2()
|
||||
.w_full()
|
||||
.child(
|
||||
v_flex()
|
||||
.w_full()
|
||||
.child(
|
||||
h_flex()
|
||||
.w_full()
|
||||
.justify_between()
|
||||
.child(
|
||||
svg()
|
||||
.size(cx.text_style().font_size)
|
||||
.flex_none()
|
||||
.mr_2()
|
||||
.mt(px(-2.0))
|
||||
.map(|icon| {
|
||||
icon.path(IconName::ExclamationTriangle.path())
|
||||
.text_color(Color::Error.color(cx))
|
||||
}),
|
||||
)
|
||||
.child(
|
||||
ui::IconButton::new("close", ui::IconName::Close)
|
||||
.on_click(cx.listener(|_, _, cx| cx.emit(gpui::DismissEvent))),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.max_w_80()
|
||||
.child(Label::new(self.message.clone()).size(LabelSize::Small)),
|
||||
)
|
||||
.when_some(self.label_and_url_button.clone(), |elm, (label, url)| {
|
||||
elm.child(
|
||||
div().mt_2().child(
|
||||
ui::Button::new("error_message_prompt_notification_button", label)
|
||||
.on_click(move |_, cx| cx.open_url(&url)),
|
||||
),
|
||||
)
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl EventEmitter<DismissEvent> for ErrorMessagePrompt {}
|
||||
|
||||
pub mod simple_message_notification {
|
||||
use gpui::{
|
||||
div, DismissEvent, EventEmitter, InteractiveElement, ParentElement, Render, SharedString,
|
||||
|
||||
@@ -30,10 +30,10 @@ use gpui::{
|
||||
action_as, actions, canvas, impl_action_as, impl_actions, point, relative, size,
|
||||
transparent_black, Action, AnyElement, AnyView, AnyWeakView, AppContext, AsyncAppContext,
|
||||
AsyncWindowContext, Bounds, CursorStyle, Decorations, DragMoveEvent, Entity as _, EntityId,
|
||||
EventEmitter, FocusHandle, FocusableView, Global, Hsla, KeyContext, Keystroke, ManagedView,
|
||||
Model, ModelContext, MouseButton, PathPromptOptions, Point, PromptLevel, Render, ResizeEdge,
|
||||
Size, Stateful, Subscription, Task, Tiling, View, WeakView, WindowBounds, WindowHandle,
|
||||
WindowOptions,
|
||||
EventEmitter, Flatten, FocusHandle, FocusableView, Global, Hsla, KeyContext, Keystroke,
|
||||
ManagedView, Model, ModelContext, MouseButton, PathPromptOptions, Point, PromptLevel, Render,
|
||||
ResizeEdge, Size, Stateful, Subscription, Task, Tiling, View, WeakView, WindowBounds,
|
||||
WindowHandle, WindowOptions,
|
||||
};
|
||||
use item::{
|
||||
FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, PreviewTabsSettings,
|
||||
@@ -307,13 +307,31 @@ pub fn init(app_state: Arc<AppState>, cx: &mut AppContext) {
|
||||
|
||||
if let Some(app_state) = app_state.upgrade() {
|
||||
cx.spawn(move |cx| async move {
|
||||
if let Some(paths) = paths.await.log_err().flatten() {
|
||||
cx.update(|cx| {
|
||||
open_paths(&paths, app_state, OpenOptions::default(), cx)
|
||||
.detach_and_log_err(cx)
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
match Flatten::flatten(paths.await.map_err(|e| e.into())) {
|
||||
Ok(Some(paths)) => {
|
||||
cx.update(|cx| {
|
||||
open_paths(&paths, app_state, OpenOptions::default(), cx)
|
||||
.detach_and_log_err(cx)
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
Ok(None) => {}
|
||||
Err(err) => {
|
||||
cx.update(|cx| {
|
||||
if let Some(workspace_window) = cx
|
||||
.active_window()
|
||||
.and_then(|window| window.downcast::<Workspace>())
|
||||
{
|
||||
workspace_window
|
||||
.update(cx, |workspace, cx| {
|
||||
workspace.show_portal_error(err.to_string(), cx);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
};
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
@@ -1296,7 +1314,15 @@ impl Workspace {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
let abs_path = cx.prompt_for_new_path(&start_abs_path);
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
let abs_path = abs_path.await?;
|
||||
let abs_path: Option<PathBuf> =
|
||||
Flatten::flatten(abs_path.await.map_err(|e| e.into())).map_err(|err| {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.show_portal_error(err.to_string(), cx);
|
||||
})
|
||||
.ok();
|
||||
err
|
||||
})?;
|
||||
|
||||
let project_path = abs_path.and_then(|abs_path| {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.project.update(cx, |project, cx| {
|
||||
@@ -1585,8 +1611,16 @@ impl Workspace {
|
||||
});
|
||||
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
let Some(paths) = paths.await.log_err().flatten() else {
|
||||
return;
|
||||
let paths = match Flatten::flatten(paths.await.map_err(|e| e.into())) {
|
||||
Ok(Some(paths)) => paths,
|
||||
Ok(None) => return,
|
||||
Err(err) => {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.show_portal_error(err.to_string(), cx);
|
||||
})
|
||||
.ok();
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(task) = this
|
||||
@@ -1748,7 +1782,14 @@ impl Workspace {
|
||||
multiple: true,
|
||||
});
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
if let Some(paths) = paths.await.log_err().flatten() {
|
||||
let paths = Flatten::flatten(paths.await.map_err(|e| e.into())).map_err(|err| {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.show_portal_error(err.to_string(), cx);
|
||||
})
|
||||
.ok();
|
||||
err
|
||||
})?;
|
||||
if let Some(paths) = paths {
|
||||
let results = this
|
||||
.update(&mut cx, |this, cx| {
|
||||
this.open_paths(paths, OpenVisible::All, None, cx)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
description = "The fast, collaborative code editor."
|
||||
edition = "2021"
|
||||
name = "zed"
|
||||
version = "0.144.0"
|
||||
version = "0.144.3"
|
||||
publish = false
|
||||
license = "GPL-3.0-or-later"
|
||||
authors = ["Zed Team <hi@zed.dev>"]
|
||||
@@ -85,7 +85,7 @@ search.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
settings.workspace = true
|
||||
simplelog = "0.9"
|
||||
simplelog.workspace = true
|
||||
smol.workspace = true
|
||||
snippet_provider.workspace = true
|
||||
tab_switcher.workspace = true
|
||||
|
||||
@@ -1 +1 @@
|
||||
dev
|
||||
stable
|
||||
@@ -80,7 +80,9 @@ fn fail_to_open_window_async(e: anyhow::Error, cx: &mut AsyncAppContext) {
|
||||
}
|
||||
|
||||
fn fail_to_open_window(e: anyhow::Error, _cx: &mut AppContext) {
|
||||
eprintln!("Zed failed to open a window: {e:?}");
|
||||
eprintln!(
|
||||
"Zed failed to open a window: {e:?}. See https://zed.dev/docs/linux for troubleshooting steps."
|
||||
);
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
{
|
||||
process::exit(1);
|
||||
@@ -99,7 +101,12 @@ fn fail_to_open_window(e: anyhow::Error, _cx: &mut AppContext) {
|
||||
.add_notification(
|
||||
notification_id,
|
||||
Notification::new("Zed failed to launch")
|
||||
.body(Some(format!("{e:?}").as_str()))
|
||||
.body(Some(
|
||||
format!(
|
||||
"{e:?}. See https://zed.dev/docs/linux for troubleshooting steps."
|
||||
)
|
||||
.as_str(),
|
||||
))
|
||||
.priority(Priority::High)
|
||||
.icon(ashpd::desktop::Icon::with_names(&[
|
||||
"dialog-question-symbolic",
|
||||
@@ -708,8 +715,8 @@ fn init_logger() {
|
||||
Ok(log_file) => {
|
||||
let mut config_builder = ConfigBuilder::new();
|
||||
|
||||
config_builder.set_time_format_str("%Y-%m-%dT%T%:z");
|
||||
config_builder.set_time_to_local(true);
|
||||
config_builder.set_time_format_rfc3339();
|
||||
config_builder.set_time_offset_to_local().log_err();
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user