diff --git a/Cargo.lock b/Cargo.lock index 0448538c35..fedb6258f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,7 +8,7 @@ version = "0.1.0" dependencies = [ "auto_update", "editor", - "futures", + "futures 0.3.24", "gpui", "language", "project", @@ -183,6 +183,19 @@ dependencies = [ "futures-core", ] +[[package]] +name = "async-compat" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b48b4ff0c2026db683dea961cd8ea874737f56cffca86fa84415eaddc51c00d" +dependencies = [ + "futures-core", + "futures-io", + "once_cell", + "pin-project-lite 0.2.9", + "tokio", +] + [[package]] name = "async-compression" version = "0.3.14" @@ -265,7 +278,7 @@ name = "async-pipe" version = "0.1.3" source = "git+https://github.com/zed-industries/async-pipe-rs?rev=82d00a04211cf4e1236029aa03e6b6ce2a74c553#82d00a04211cf4e1236029aa03e6b6ce2a74c553" dependencies = [ - "futures", + "futures 0.3.24", "log", ] @@ -338,9 +351,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.56" +version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96cf8829f67d2eab0b2dfa42c5d0ef737e0724e4a82b01b3e292456202b19716" +checksum = "76464446b8bc32758d7e88ee1a804d9914cd9b1cb264c029899680b0be29826f" dependencies = [ "proc-macro2", "quote", @@ -443,7 +456,7 @@ dependencies = [ "axum-core", "base64", "bitflags", - "bytes", + "bytes 1.2.1", "futures-util", "headers", "http", @@ -475,7 +488,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf4d047478b986f14a13edad31a009e2e05cb241f9805d0d75e4cba4e129ad4d" dependencies = [ "async-trait", - "bytes", + "bytes 1.2.1", "futures-util", "http", "http-body", @@ -489,7 +502,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "277c75e6c814b061ae4947d02335d9659db9771b9950cca670002ae986372f44" dependencies = [ "axum", - "bytes", + "bytes 1.2.1", "futures-util", "http", "mime", @@ -661,6 +674,16 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "bytes" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +dependencies = [ + "byteorder", + "iovec", +] + [[package]] name = "bytes" version = "1.2.1" @@ -691,7 +714,7 @@ dependencies = [ "anyhow", "client", "collections", - "futures", + "futures 0.3.24", "gpui", "postage", "project", @@ -772,12 +795,12 @@ dependencies = [ "bindgen", "block", "byteorder", - "bytes", + "bytes 1.2.1", "cocoa", "core-foundation", "core-graphics", "foreign-types", - "futures", + "futures 0.3.24", "gpui", "hmac 0.12.1", "jwt", @@ -960,7 +983,7 @@ dependencies = [ "async-tungstenite", "collections", "db", - "futures", + "futures 0.3.24", "gpui", "image", "isahc", @@ -1045,7 +1068,8 @@ dependencies = [ "editor", "env_logger", "envy", - "futures", + "fs", + "futures 0.3.24", "git", "gpui", "hyper", @@ -1060,6 +1084,7 @@ dependencies = [ "prometheus", "rand 0.8.5", "reqwest", + "rope", "rpc", "scrypt", "serde", @@ -1092,7 +1117,7 @@ dependencies = [ "clock", "collections", "editor", - "futures", + "futures 0.3.24", "fuzzy", "gpui", "log", @@ -1551,6 +1576,7 @@ dependencies = [ "language", "postage", "project", + "rope", "serde_json", "settings", "smallvec", @@ -1689,7 +1715,7 @@ dependencies = [ "context_menu", "ctor", "env_logger", - "futures", + "futures 0.3.24", "fuzzy", "git", "gpui", @@ -1704,6 +1730,7 @@ dependencies = [ "postage", "project", "rand 0.8.5", + "rope", "rpc", "serde", "settings", @@ -1984,6 +2011,31 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "fs" +version = "0.1.0" +dependencies = [ + "anyhow", + "async-trait", + "collections", + "fsevent", + "futures 0.3.24", + "git2", + "gpui", + "lazy_static", + "libc", + "log", + "lsp", + "parking_lot 0.11.2", + "regex", + "rope", + "serde", + "serde_json", + "smol", + "tempfile", + "util", +] + [[package]] name = "fs-set-times" version = "0.15.0" @@ -2038,9 +2090,15 @@ checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" [[package]] name = "futures" -version = "0.3.21" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" +checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" + +[[package]] +name = "futures" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f21eda599937fba36daeb58a22e8f5cee2d14c4a17b5b7739c7c8e5e3b8230c" dependencies = [ "futures-channel", "futures-core", @@ -2053,9 +2111,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050" dependencies = [ "futures-core", "futures-sink", @@ -2063,15 +2121,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" +checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf" [[package]] name = "futures-executor" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" +checksum = "9ff63c23854bee61b6e9cd331d523909f238fc7636290b96826e9cfa5faa00ab" dependencies = [ "futures-core", "futures-task", @@ -2091,9 +2149,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" +checksum = "bbf4d2a7a308fd4578637c0b17c7e1c7ba127b8f6ba00b29f717e9655d85eb68" [[package]] name = "futures-lite" @@ -2112,9 +2170,9 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" +checksum = "42cd15d1c7456c04dbdf7e88bcd69760d74f3a798d6444e16974b505b0e62f17" dependencies = [ "proc-macro2", "quote", @@ -2123,22 +2181,23 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" +checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56" [[package]] name = "futures-task" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" +checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1" [[package]] name = "futures-util" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90" dependencies = [ + "futures 0.1.31", "futures-channel", "futures-core", "futures-io", @@ -2149,6 +2208,7 @@ dependencies = [ "pin-project-lite 0.2.9", "pin-utils", "slab", + "tokio-io", ] [[package]] @@ -2229,11 +2289,12 @@ dependencies = [ "async-trait", "clock", "collections", - "futures", + "futures 0.3.24", "git2", "lazy_static", "log", "parking_lot 0.11.2", + "rope", "smol", "sum_tree", "text", @@ -2281,6 +2342,7 @@ dependencies = [ "gpui", "menu", "postage", + "rope", "settings", "text", "workspace", @@ -2307,9 +2369,10 @@ dependencies = [ "etagere", "font-kit", "foreign-types", - "futures", + "futures 0.3.24", "gpui_macros", "image", + "itertools", "lazy_static", "log", "media", @@ -2355,7 +2418,7 @@ version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57" dependencies = [ - "bytes", + "bytes 1.2.1", "fnv", "futures-core", "futures-sink", @@ -2364,7 +2427,7 @@ dependencies = [ "indexmap", "slab", "tokio", - "tokio-util 0.7.3", + "tokio-util 0.7.4", "tracing", ] @@ -2403,7 +2466,7 @@ checksum = "4cff78e5788be1e0ab65b04d306b2ed5092c815ec97ec70f4ebd5aee158aa55d" dependencies = [ "base64", "bitflags", - "bytes", + "bytes 1.2.1", "headers-core", "http", "httpdate", @@ -2496,7 +2559,7 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ - "bytes", + "bytes 1.2.1", "fnv", "itoa", ] @@ -2507,7 +2570,7 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ - "bytes", + "bytes 1.2.1", "http", "pin-project-lite 0.2.9", ] @@ -2542,7 +2605,7 @@ version = "0.14.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42dc3c131584288d375f2d07f822b0cb012d8c6fb899a5b9fdb3cb7eb9b6004f" dependencies = [ - "bytes", + "bytes 1.2.1", "futures-channel", "futures-core", "futures-util", @@ -2578,7 +2641,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ - "bytes", + "bytes 1.2.1", "hyper", "native-tls", "tokio", @@ -2868,7 +2931,8 @@ dependencies = [ "collections", "ctor", "env_logger", - "futures", + "fs", + "futures 0.3.24", "fuzzy", "git", "gpui", @@ -2879,6 +2943,7 @@ dependencies = [ "postage", "rand 0.8.5", "regex", + "rope", "rpc", "serde", "serde_json", @@ -3029,7 +3094,7 @@ dependencies = [ "anyhow", "core-foundation", "core-graphics", - "futures", + "futures 0.3.24", "media", "parking_lot 0.11.2", "serde", @@ -3066,7 +3131,7 @@ dependencies = [ "collections", "ctor", "env_logger", - "futures", + "futures 0.3.24", "gpui", "log", "lsp-types", @@ -3159,7 +3224,7 @@ dependencies = [ "anyhow", "bindgen", "block", - "bytes", + "bytes 1.2.1", "core-foundation", "foreign-types", "metal", @@ -3519,6 +3584,21 @@ dependencies = [ "libc", ] +[[package]] +name = "nvim-rs" +version = "0.5.0" +source = "git+https://github.com/KillTheMule/nvim-rs?branch=master#d701c2790dcb2579f8f4d7003ba30e2100a7d25b" +dependencies = [ + "async-trait", + "futures 0.3.24", + "log", + "parity-tokio-ipc", + "rmp", + "rmpv", + "tokio", + "tokio-util 0.7.4", +] + [[package]] name = "objc" version = "0.2.7" @@ -3639,6 +3719,20 @@ dependencies = [ "workspace", ] +[[package]] +name = "parity-tokio-ipc" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9981e32fb75e004cc148f5fb70342f393830e0a4aa62e3cc93b50976218d42b6" +dependencies = [ + "futures 0.3.24", + "libc", + "log", + "rand 0.7.3", + "tokio", + "winapi 0.3.9", +] + [[package]] name = "parking" version = "2.0.0" @@ -3943,7 +4037,7 @@ checksum = "a63d25391d04a097954b76aba742b6b5b74f213dfe3dbaeeb36e8ddc1c657f0b" dependencies = [ "atomic", "crossbeam-queue", - "futures", + "futures 0.3.24", "log", "pin-project", "pollster", @@ -4012,15 +4106,15 @@ dependencies = [ "clock", "collections", "db", + "fs", "fsevent", - "futures", + "futures 0.3.24", "fuzzy", "git", "gpui", "ignore", "language", "lazy_static", - "libc", "log", "lsp", "parking_lot 0.11.2", @@ -4029,6 +4123,7 @@ dependencies = [ "rand 0.8.5", "regex", "rocksdb", + "rope", "rpc", "serde", "serde_json", @@ -4051,7 +4146,7 @@ version = "0.1.0" dependencies = [ "context_menu", "editor", - "futures", + "futures 0.3.24", "gpui", "menu", "postage", @@ -4070,7 +4165,7 @@ version = "0.1.0" dependencies = [ "anyhow", "editor", - "futures", + "futures 0.3.24", "fuzzy", "gpui", "language", @@ -4107,7 +4202,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de5e2533f59d08fcf364fd374ebda0692a70bd6d7e66ef97f306f45c6c5d8020" dependencies = [ - "bytes", + "bytes 1.2.1", "prost-derive 0.8.0", ] @@ -4117,7 +4212,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" dependencies = [ - "bytes", + "bytes 1.2.1", "prost-derive 0.9.0", ] @@ -4127,7 +4222,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62941722fb675d463659e49c4f3fe1fe792ff24fe5bbaa9c08cd3b98a1c354f5" dependencies = [ - "bytes", + "bytes 1.2.1", "heck 0.3.3", "itertools", "lazy_static", @@ -4173,7 +4268,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a" dependencies = [ - "bytes", + "bytes 1.2.1", "prost 0.9.0", ] @@ -4436,7 +4531,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b75aa69a3f06bbcc66ede33af2af253c6f7a86b1ca0033f60c580a27074fbf92" dependencies = [ "base64", - "bytes", + "bytes 1.2.1", "encoding_rs", "futures-core", "futures-util", @@ -4506,6 +4601,27 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "rmp" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44519172358fd6d58656c86ab8e7fbc9e1490c3e8f14d35ed78ca0dd07403c9f" +dependencies = [ + "byteorder", + "num-traits", + "paste", +] + +[[package]] +name = "rmpv" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de8813b3a2f95c5138fe5925bfb8784175d88d6bff059ba8ce090aa891319754" +dependencies = [ + "num-traits", + "rmp", +] + [[package]] name = "rocksdb" version = "0.18.0" @@ -4515,6 +4631,20 @@ dependencies = [ "librocksdb-sys", ] +[[package]] +name = "rope" +version = "0.1.0" +dependencies = [ + "arrayvec 0.7.2", + "bromberg_sl2", + "gpui", + "log", + "rand 0.8.5", + "smallvec", + "sum_tree", + "util", +] + [[package]] name = "roxmltree" version = "0.14.1" @@ -4536,7 +4666,7 @@ dependencies = [ "collections", "ctor", "env_logger", - "futures", + "futures 0.3.24", "gpui", "parking_lot 0.11.2", "prost 0.8.0", @@ -5013,14 +5143,21 @@ dependencies = [ "anyhow", "assets", "collections", + "fs", + "futures 0.3.24", "gpui", "json_comments", + "postage", + "rope", "schemars", "serde", "serde_json", "serde_path_to_error", "theme", "toml", + "tree-sitter", + "tree-sitter-json 0.19.0", + "unindent", "util", ] @@ -5290,7 +5427,7 @@ dependencies = [ "base64", "bitflags", "byteorder", - "bytes", + "bytes 1.2.1", "crc", "crossbeam-queue", "dirs 4.0.0", @@ -5543,7 +5680,7 @@ dependencies = [ "context_menu", "dirs 4.0.0", "editor", - "futures", + "futures 0.3.24", "gpui", "itertools", "lazy_static", @@ -5569,13 +5706,12 @@ name = "text" version = "0.1.0" dependencies = [ "anyhow", - "arrayvec 0.7.2", - "bromberg_sl2", "clock", "collections", "ctor", "digest 0.9.0", "env_logger", + "fs", "gpui", "lazy_static", "log", @@ -5583,6 +5719,7 @@ dependencies = [ "postage", "rand 0.8.5", "regex", + "rope", "smallvec", "sum_tree", "util", @@ -5754,16 +5891,16 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.19.2" +version = "1.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439" +checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099" dependencies = [ - "bytes", + "autocfg 1.1.0", + "bytes 1.2.1", "libc", "memchr", "mio 0.8.4", "num_cpus", - "once_cell", "parking_lot 0.12.1", "pin-project-lite 0.2.9", "signal-hook-registry", @@ -5772,6 +5909,17 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "tokio-io" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" +dependencies = [ + "bytes 0.4.12", + "futures 0.1.31", + "log", +] + [[package]] name = "tokio-io-timeout" version = "1.2.0" @@ -5843,7 +5991,7 @@ version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" dependencies = [ - "bytes", + "bytes 1.2.1", "futures-core", "futures-sink", "log", @@ -5853,12 +6001,13 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" +checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" dependencies = [ - "bytes", + "bytes 1.2.1", "futures-core", + "futures-io", "futures-sink", "pin-project-lite 0.2.9", "tokio", @@ -5883,7 +6032,7 @@ dependencies = [ "async-stream", "async-trait", "base64", - "bytes", + "bytes 1.2.1", "futures-core", "futures-util", "h2", @@ -5919,7 +6068,7 @@ dependencies = [ "rand 0.8.5", "slab", "tokio", - "tokio-util 0.7.3", + "tokio-util 0.7.4", "tower-layer", "tower-service", "tracing", @@ -5932,7 +6081,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c530c8675c1dbf98facee631536fa116b5fb6382d7dd6dc1b118d970eafe3ba" dependencies = [ "bitflags", - "bytes", + "bytes 1.2.1", "futures-core", "futures-util", "http", @@ -6211,7 +6360,7 @@ checksum = "6ad3713a14ae247f22a728a0456a545df14acf3867f905adff84be99e23b3ad1" dependencies = [ "base64", "byteorder", - "bytes", + "bytes 1.2.1", "http", "httparse", "log", @@ -6230,7 +6379,7 @@ checksum = "d96a2dea40e7570482f28eb57afbe42d97551905da6a9400acc5c328d24004f5" dependencies = [ "base64", "byteorder", - "bytes", + "bytes 1.2.1", "http", "httparse", "log", @@ -6406,7 +6555,7 @@ name = "util" version = "0.1.0" dependencies = [ "anyhow", - "futures", + "futures 0.3.24", "git2", "lazy_static", "log", @@ -6476,6 +6625,8 @@ name = "vim" version = "0.1.0" dependencies = [ "assets", + "async-compat", + "async-trait", "collections", "command_palette", "editor", @@ -6483,11 +6634,17 @@ dependencies = [ "indoc", "itertools", "language", + "lazy_static", "log", + "nvim-rs", + "parking_lot 0.11.2", "project", + "rope", "search", "serde", + "serde_json", "settings", + "tokio", "util", "workspace", ] @@ -7173,7 +7330,8 @@ dependencies = [ "collections", "context_menu", "drag_and_drop", - "futures", + "fs", + "futures 0.3.24", "gpui", "language", "log", @@ -7256,8 +7414,9 @@ dependencies = [ "editor", "env_logger", "file_finder", + "fs", "fsevent", - "futures", + "futures 0.3.24", "fuzzy", "go_to_line", "gpui", diff --git a/Cargo.toml b/Cargo.toml index 31a9118a1a..8d2a3fcc40 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,11 @@ members = ["crates/*"] default-members = ["crates/zed"] resolver = "2" +[workspace.dependencies] +serde = { version = "1.0", features = ["derive", "rc"] } +serde_json = { version = "1.0", features = ["preserve_order", "raw_value"] } +rand = { version = "0.8" } + [patch.crates-io] tree-sitter = { git = "https://github.com/tree-sitter/tree-sitter", rev = "366210ae925d7ea0891bc7a0c738f60c77c04d7b" } async-task = { git = "https://github.com/zed-industries/async-task", rev = "341b57d6de98cdfd7b418567b8de2022ca993a6e" } @@ -21,3 +26,4 @@ split-debuginfo = "unpacked" [profile.release] debug = true + diff --git a/crates/collab/Cargo.toml b/crates/collab/Cargo.toml index 840199c2bb..cf6b7f8b68 100644 --- a/crates/collab/Cargo.toml +++ b/crates/collab/Cargo.toml @@ -16,7 +16,8 @@ required-features = ["seed-support"] collections = { path = "../collections" } rpc = { path = "../rpc" } util = { path = "../util" } - +fs = { path = "../fs" } +rope = { path = "../rope" } anyhow = "1.0.40" async-trait = "0.1.50" async-tungstenite = "0.16" diff --git a/crates/collab/src/integration_tests.rs b/crates/collab/src/integration_tests.rs index f289dd9d27..f6f0f5c7f2 100644 --- a/crates/collab/src/integration_tests.rs +++ b/crates/collab/src/integration_tests.rs @@ -15,6 +15,7 @@ use editor::{ self, ConfirmCodeAction, ConfirmCompletion, ConfirmRename, Editor, Redo, Rename, ToOffset, ToggleCodeActions, Undo, }; +use fs::{FakeFs, Fs as _, LineEnding}; use futures::{channel::mpsc, Future, StreamExt as _}; use gpui::{ executor::{self, Deterministic}, @@ -24,17 +25,16 @@ use gpui::{ }; use language::{ range_to_lsp, tree_sitter_rust, Diagnostic, DiagnosticEntry, FakeLspAdapter, Language, - LanguageConfig, LanguageRegistry, LineEnding, OffsetRangeExt, Point, Rope, + LanguageConfig, LanguageRegistry, OffsetRangeExt, Rope, }; use lsp::{self, FakeLanguageServer}; use parking_lot::Mutex; use project::{ - fs::{FakeFs, Fs as _}, - search::SearchQuery, - worktree::WorktreeHandle, - DiagnosticSummary, Project, ProjectPath, ProjectStore, WorktreeId, + search::SearchQuery, worktree::WorktreeHandle, DiagnosticSummary, Project, ProjectPath, + ProjectStore, WorktreeId, }; use rand::prelude::*; +use rope::point::Point; use rpc::PeerId; use serde_json::json; use settings::{Formatter, Settings}; diff --git a/crates/diagnostics/Cargo.toml b/crates/diagnostics/Cargo.toml index 616f69117f..c4b851917e 100644 --- a/crates/diagnostics/Cargo.toml +++ b/crates/diagnostics/Cargo.toml @@ -15,6 +15,7 @@ editor = { path = "../editor" } language = { path = "../language" } gpui = { path = "../gpui" } project = { path = "../project" } +rope = { path = "../rope" } settings = { path = "../settings" } theme = { path = "../theme" } util = { path = "../util" } diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index 3111d7a9f1..608b333d0d 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -14,10 +14,10 @@ use gpui::{ ViewHandle, WeakViewHandle, }; use language::{ - Anchor, Bias, Buffer, Diagnostic, DiagnosticEntry, DiagnosticSeverity, Point, Selection, - SelectionGoal, + Anchor, Bias, Buffer, Diagnostic, DiagnosticEntry, DiagnosticSeverity, Selection, SelectionGoal, }; use project::{DiagnosticSummary, Project, ProjectPath}; +use rope::point::Point; use serde_json::json; use settings::Settings; use smallvec::SmallVec; @@ -738,7 +738,8 @@ mod tests { DisplayPoint, }; use gpui::TestAppContext; - use language::{Diagnostic, DiagnosticEntry, DiagnosticSeverity, PointUtf16}; + use language::{Diagnostic, DiagnosticEntry, DiagnosticSeverity}; + use rope::point_utf16::PointUtf16; use serde_json::json; use unindent::Unindent as _; use workspace::AppState; diff --git a/crates/editor/Cargo.toml b/crates/editor/Cargo.toml index e8695e5ddc..4e0a10b70d 100644 --- a/crates/editor/Cargo.toml +++ b/crates/editor/Cargo.toml @@ -30,6 +30,7 @@ gpui = { path = "../gpui" } language = { path = "../language" } lsp = { path = "../lsp" } project = { path = "../project" } +rope = { path = "../rope" } rpc = { path = "../rpc" } settings = { path = "../settings" } snippet = { path = "../snippet" } @@ -48,7 +49,7 @@ ordered-float = "2.1.1" parking_lot = "0.11" postage = { version = "0.4", features = ["futures-traits"] } rand = { version = "0.8.3", optional = true } -serde = { version = "1.0", features = ["derive", "rc"] } +serde = { workspace = true } smallvec = { version = "1.6", features = ["union"] } smol = "1.2" tree-sitter-rust = { version = "*", optional = true } diff --git a/crates/editor/src/display_map.rs b/crates/editor/src/display_map.rs index ac85bf68ee..91a3a30267 100644 --- a/crates/editor/src/display_map.rs +++ b/crates/editor/src/display_map.rs @@ -11,7 +11,8 @@ use gpui::{ fonts::{FontId, HighlightStyle}, Entity, ModelContext, ModelHandle, }; -use language::{OffsetUtf16, Point, Subscription as BufferSubscription}; +use language::Subscription as BufferSubscription; +use rope::{offset_utf16::OffsetUtf16, point::Point}; use settings::Settings; use std::{any::TypeId, fmt::Debug, num::NonZeroU32, ops::Range, sync::Arc}; use sum_tree::{Bias, TreeMap}; @@ -622,7 +623,7 @@ pub mod tests { use super::*; use crate::{movement, test::marked_display_snapshot}; use gpui::{color::Color, elements::*, test::observe, MutableAppContext}; - use language::{Buffer, Language, LanguageConfig, RandomCharIter, SelectionGoal}; + use language::{Buffer, Language, LanguageConfig, SelectionGoal}; use rand::{prelude::*, Rng}; use smol::stream::StreamExt; use std::{env, sync::Arc}; @@ -666,7 +667,9 @@ pub mod tests { let buffer = cx.update(|cx| { if rng.gen() { let len = rng.gen_range(0..10); - let text = RandomCharIter::new(&mut rng).take(len).collect::(); + let text = util::RandomCharIter::new(&mut rng) + .take(len) + .collect::(); MultiBuffer::build_simple(&text, cx) } else { MultiBuffer::build_random(&mut rng, cx) diff --git a/crates/editor/src/display_map/block_map.rs b/crates/editor/src/display_map/block_map.rs index 210daccac2..f0f2720f1a 100644 --- a/crates/editor/src/display_map/block_map.rs +++ b/crates/editor/src/display_map/block_map.rs @@ -7,6 +7,7 @@ use collections::{Bound, HashMap, HashSet}; use gpui::{ElementBox, RenderContext}; use language::{BufferSnapshot, Chunk, Patch}; use parking_lot::Mutex; +use rope::point::Point; use std::{ cell::RefCell, cmp::{self, Ordering}, @@ -18,7 +19,7 @@ use std::{ }, }; use sum_tree::{Bias, SumTree}; -use text::{Edit, Point}; +use text::Edit; const NEWLINES: &[u8] = &[b'\n'; u8::MAX as usize]; @@ -42,7 +43,7 @@ pub struct BlockSnapshot { pub struct BlockId(usize); #[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)] -pub struct BlockPoint(pub super::Point); +pub struct BlockPoint(pub Point); #[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)] struct BlockRow(u32); @@ -994,7 +995,7 @@ mod tests { use rand::prelude::*; use settings::Settings; use std::env; - use text::RandomCharIter; + use util::RandomCharIter; #[gpui::test] fn test_offset_for_row() { diff --git a/crates/editor/src/display_map/fold_map.rs b/crates/editor/src/display_map/fold_map.rs index c17cfa39f2..5bd1670542 100644 --- a/crates/editor/src/display_map/fold_map.rs +++ b/crates/editor/src/display_map/fold_map.rs @@ -5,8 +5,9 @@ use crate::{ }; use collections::BTreeMap; use gpui::fonts::HighlightStyle; -use language::{Chunk, Edit, Point, TextSummary}; +use language::{Chunk, Edit, TextSummary}; use parking_lot::Mutex; +use rope::point::Point; use std::{ any::TypeId, cmp::{self, Ordering}, @@ -18,11 +19,11 @@ use std::{ use sum_tree::{Bias, Cursor, FilterCursor, SumTree}; #[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)] -pub struct FoldPoint(pub super::Point); +pub struct FoldPoint(pub Point); impl FoldPoint { pub fn new(row: u32, column: u32) -> Self { - Self(super::Point::new(row, column)) + Self(Point::new(row, column)) } pub fn row(self) -> u32 { @@ -1196,8 +1197,8 @@ mod tests { use settings::Settings; use std::{cmp::Reverse, env, mem, sync::Arc}; use sum_tree::TreeMap; - use text::RandomCharIter; use util::test::sample_text; + use util::RandomCharIter; use Bias::{Left, Right}; #[gpui::test] diff --git a/crates/editor/src/display_map/tab_map.rs b/crates/editor/src/display_map/tab_map.rs index 4d89767a19..b7d8fac770 100644 --- a/crates/editor/src/display_map/tab_map.rs +++ b/crates/editor/src/display_map/tab_map.rs @@ -3,11 +3,12 @@ use super::{ TextHighlights, }; use crate::MultiBufferSnapshot; -use language::{rope, Chunk}; +use language::Chunk; use parking_lot::Mutex; +use rope; +use rope::point::Point; use std::{cmp, mem, num::NonZeroU32, ops::Range}; use sum_tree::Bias; -use text::Point; pub struct TabMap(Mutex); @@ -332,11 +333,11 @@ impl TabSnapshot { } #[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)] -pub struct TabPoint(pub super::Point); +pub struct TabPoint(pub Point); impl TabPoint { pub fn new(row: u32, column: u32) -> Self { - Self(super::Point::new(row, column)) + Self(Point::new(row, column)) } pub fn zero() -> Self { @@ -352,8 +353,8 @@ impl TabPoint { } } -impl From for TabPoint { - fn from(point: super::Point) -> Self { +impl From for TabPoint { + fn from(point: Point) -> Self { Self(point) } } @@ -362,7 +363,7 @@ pub type TabEdit = text::Edit; #[derive(Clone, Debug, Default, Eq, PartialEq)] pub struct TextSummary { - pub lines: super::Point, + pub lines: Point, pub first_line_chars: u32, pub last_line_chars: u32, pub longest_row: u32, @@ -485,7 +486,6 @@ mod tests { use super::*; use crate::{display_map::fold_map::FoldMap, MultiBuffer}; use rand::{prelude::StdRng, Rng}; - use text::{RandomCharIter, Rope}; #[test] fn test_expand_tabs() { @@ -508,7 +508,9 @@ mod tests { let tab_size = NonZeroU32::new(rng.gen_range(1..=4)).unwrap(); let len = rng.gen_range(0..30); let buffer = if rng.gen() { - let text = RandomCharIter::new(&mut rng).take(len).collect::(); + let text = util::RandomCharIter::new(&mut rng) + .take(len) + .collect::(); MultiBuffer::build_simple(&text, cx) } else { MultiBuffer::build_random(&mut rng, cx) @@ -522,7 +524,7 @@ mod tests { log::info!("FoldMap text: {:?}", folds_snapshot.text()); let (_, tabs_snapshot) = TabMap::new(folds_snapshot.clone(), tab_size); - let text = Rope::from(tabs_snapshot.text().as_str()); + let text = rope::Rope::from(tabs_snapshot.text().as_str()); log::info!( "TabMap text (tab size: {}): {:?}", tab_size, diff --git a/crates/editor/src/display_map/wrap_map.rs b/crates/editor/src/display_map/wrap_map.rs index ee6ce2860d..42156b905f 100644 --- a/crates/editor/src/display_map/wrap_map.rs +++ b/crates/editor/src/display_map/wrap_map.rs @@ -3,13 +3,14 @@ use super::{ tab_map::{self, TabEdit, TabPoint, TabSnapshot}, TextHighlights, }; -use crate::{MultiBufferSnapshot, Point}; +use crate::MultiBufferSnapshot; use gpui::{ fonts::FontId, text_layout::LineWrapper, Entity, ModelContext, ModelHandle, MutableAppContext, Task, }; use language::Chunk; use lazy_static::lazy_static; +use rope::point::Point; use smol::future::yield_now; use std::{cmp, collections::VecDeque, mem, ops::Range, time::Duration}; use sum_tree::{Bias, Cursor, SumTree}; @@ -52,7 +53,7 @@ struct TransformSummary { } #[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)] -pub struct WrapPoint(pub super::Point); +pub struct WrapPoint(pub Point); pub struct WrapChunks<'a> { input_chunks: tab_map::TabChunks<'a>, @@ -959,7 +960,7 @@ impl SumTreeExt for SumTree { impl WrapPoint { pub fn new(row: u32, column: u32) -> Self { - Self(super::Point::new(row, column)) + Self(Point::new(row, column)) } pub fn row(self) -> u32 { @@ -1029,7 +1030,6 @@ mod tests { MultiBuffer, }; use gpui::test::observe; - use language::RandomCharIter; use rand::prelude::*; use settings::Settings; use smol::stream::StreamExt; @@ -1067,7 +1067,9 @@ mod tests { MultiBuffer::build_random(&mut rng, cx) } else { let len = rng.gen_range(0..10); - let text = RandomCharIter::new(&mut rng).take(len).collect::(); + let text = util::RandomCharIter::new(&mut rng) + .take(len) + .collect::(); MultiBuffer::build_simple(&text, cx) } }); diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index a7acc9f609..c8bb16ee00 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -43,8 +43,8 @@ pub use items::MAX_TAB_TITLE_LEN; pub use language::{char_kind, CharKind}; use language::{ AutoindentMode, BracketPair, Buffer, CodeAction, CodeLabel, Completion, Diagnostic, - DiagnosticSeverity, IndentKind, IndentSize, Language, OffsetRangeExt, OffsetUtf16, Point, - Selection, SelectionGoal, TransactionId, + DiagnosticSeverity, IndentKind, IndentSize, Language, OffsetRangeExt, Selection, SelectionGoal, + TransactionId, }; use link_go_to_definition::{hide_link_definition, LinkGoToDefinitionState}; pub use multi_buffer::{ @@ -54,6 +54,7 @@ pub use multi_buffer::{ use multi_buffer::{MultiBufferChunks, ToOffsetUtf16}; use ordered_float::OrderedFloat; use project::{FormatTrigger, LocationLink, Project, ProjectPath, ProjectTransaction}; +use rope::{offset_utf16::OffsetUtf16, point::Point}; use selections_collection::{resolve_multiple, MutableSelectionsCollection, SelectionsCollection}; use serde::{Deserialize, Serialize}; use settings::Settings; diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index 24260a497e..8b41990574 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -15,8 +15,8 @@ use gpui::{ }; use language::{FakeLspAdapter, LanguageConfig, LanguageRegistry}; use project::FakeFs; +use rope::point::Point; use settings::EditorSettings; -use text::Point; use util::{ assert_set_eq, test::{marked_text_ranges, marked_text_ranges_by, sample_text, TextRangeMarker}, diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 36d717641e..2842928914 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -35,8 +35,9 @@ use gpui::{ WeakViewHandle, }; use json::json; -use language::{Bias, DiagnosticSeverity, OffsetUtf16, Selection}; +use language::{Bias, DiagnosticSeverity, Selection}; use project::ProjectPath; +use rope::offset_utf16::OffsetUtf16; use settings::{GitGutter, Settings}; use smallvec::SmallVec; use std::{ diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index c1082020e5..727ee1f094 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -11,6 +11,7 @@ use gpui::{ }; use language::{Bias, Buffer, File as _, OffsetRangeExt, SelectionGoal}; use project::{File, FormatTrigger, Project, ProjectEntryId, ProjectPath}; +use rope::point::Point; use rpc::proto::{self, update_view}; use settings::Settings; use smallvec::SmallVec; @@ -21,7 +22,7 @@ use std::{ ops::Range, path::{Path, PathBuf}, }; -use text::{Point, Selection}; +use text::Selection; use util::TryFutureExt; use workspace::{ searchable::{Direction, SearchEvent, SearchableItem, SearchableItemHandle}, diff --git a/crates/editor/src/movement.rs b/crates/editor/src/movement.rs index 9261a6d445..e5dcf94841 100644 --- a/crates/editor/src/movement.rs +++ b/crates/editor/src/movement.rs @@ -1,6 +1,7 @@ +use rope::point::Point; + use super::{Bias, DisplayPoint, DisplaySnapshot, SelectionGoal, ToDisplayPoint}; use crate::{char_kind, CharKind, ToPoint}; -use language::Point; use std::ops::Range; pub fn left(map: &DisplaySnapshot, mut point: DisplayPoint) -> DisplayPoint { @@ -336,7 +337,7 @@ pub fn surrounding_word(map: &DisplaySnapshot, position: DisplayPoint) -> Range< mod tests { use super::*; use crate::{test::marked_display_snapshot, Buffer, DisplayMap, ExcerptRange, MultiBuffer}; - use language::Point; + use rope::point::Point; use settings::Settings; #[gpui::test] diff --git a/crates/editor/src/multi_buffer.rs b/crates/editor/src/multi_buffer.rs index a0eedb850c..23ee7df657 100644 --- a/crates/editor/src/multi_buffer.rs +++ b/crates/editor/src/multi_buffer.rs @@ -12,6 +12,7 @@ use language::{ DiagnosticEntry, Event, File, IndentSize, Language, OffsetRangeExt, Outline, OutlineItem, Selection, ToOffset as _, ToOffsetUtf16 as _, ToPoint as _, ToPointUtf16 as _, TransactionId, }; +use rope::{offset_utf16::OffsetUtf16, point::Point, point_utf16::PointUtf16, TextDimension}; use smallvec::SmallVec; use std::{ borrow::Cow, @@ -27,9 +28,8 @@ use std::{ use sum_tree::{Bias, Cursor, SumTree}; use text::{ locator::Locator, - rope::TextDimension, subscription::{Subscription, Topic}, - Edit, OffsetUtf16, Point, PointUtf16, TextSummary, + Edit, TextSummary, }; use theme::SyntaxTheme; use util::post_inc; @@ -168,7 +168,7 @@ struct ExcerptChunks<'a> { } struct ExcerptBytes<'a> { - content_bytes: language::rope::Bytes<'a>, + content_bytes: rope::Bytes<'a>, footer_height: usize, } @@ -1412,7 +1412,7 @@ impl MultiBuffer { edit_count: usize, cx: &mut ModelContext, ) { - use text::RandomCharIter; + use util::RandomCharIter; let snapshot = self.read(cx); let mut edits: Vec<(Range, Arc)> = Vec::new(); @@ -1451,7 +1451,7 @@ impl MultiBuffer { ) { use rand::prelude::*; use std::env; - use text::RandomCharIter; + use util::RandomCharIter; let max_excerpts = env::var("MAX_EXCERPTS") .map(|i| i.parse().expect("invalid `MAX_EXCERPTS` variable")) @@ -3337,7 +3337,7 @@ mod tests { use rand::prelude::*; use settings::Settings; use std::{env, rc::Rc}; - use text::{Point, RandomCharIter}; + use util::test::sample_text; #[gpui::test] @@ -3955,7 +3955,9 @@ mod tests { } _ => { let buffer_handle = if buffers.is_empty() || rng.gen_bool(0.4) { - let base_text = RandomCharIter::new(&mut rng).take(10).collect::(); + let base_text = util::RandomCharIter::new(&mut rng) + .take(10) + .collect::(); buffers.push(cx.add_model(|cx| Buffer::new(0, base_text, cx))); buffers.last().unwrap() } else { diff --git a/crates/editor/src/multi_buffer/anchor.rs b/crates/editor/src/multi_buffer/anchor.rs index cb8a1692b9..b30e4b5780 100644 --- a/crates/editor/src/multi_buffer/anchor.rs +++ b/crates/editor/src/multi_buffer/anchor.rs @@ -1,10 +1,10 @@ use super::{ExcerptId, MultiBufferSnapshot, ToOffset, ToOffsetUtf16, ToPoint}; +use rope::{offset_utf16::OffsetUtf16, point::Point, TextDimension}; use std::{ cmp::Ordering, ops::{Range, Sub}, }; use sum_tree::Bias; -use text::{rope::TextDimension, OffsetUtf16, Point}; #[derive(Clone, Eq, PartialEq, Debug, Hash)] pub struct Anchor { diff --git a/crates/editor/src/selections_collection.rs b/crates/editor/src/selections_collection.rs index 9d6450f8ec..ed983d22d9 100644 --- a/crates/editor/src/selections_collection.rs +++ b/crates/editor/src/selections_collection.rs @@ -8,7 +8,8 @@ use std::{ use collections::HashMap; use gpui::{AppContext, ModelHandle, MutableAppContext}; use itertools::Itertools; -use language::{rope::TextDimension, Bias, Point, Selection, SelectionGoal, ToPoint}; +use language::{Bias, Selection, SelectionGoal, ToPoint}; +use rope::{point::Point, TextDimension}; use util::post_inc; use crate::{ diff --git a/crates/fs/Cargo.toml b/crates/fs/Cargo.toml new file mode 100644 index 0000000000..5b9082d114 --- /dev/null +++ b/crates/fs/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "fs" +version = "0.1.0" +edition = "2021" + +[lib] +path = "src/fs.rs" + +[dependencies] +collections = { path = "../collections" } +gpui = { path = "../gpui" } +lsp = { path = "../lsp" } +rope = { path = "../rope" } +util = { path = "../util" } +anyhow = "1.0.57" +async-trait = "0.1" +futures = "0.3" +tempfile = "3" +fsevent = { path = "../fsevent" } +lazy_static = "1.4.0" +parking_lot = "0.11.1" +smol = "1.2.5" +regex = "1.5" +git2 = { version = "0.15", default-features = false } +serde = { workspace = true } +serde_json = { workspace = true } +log = { version = "0.4.16", features = ["kv_unstable_serde"] } +libc = "0.2" + +[features] +test-support = [] diff --git a/crates/project/src/fs.rs b/crates/fs/src/fs.rs similarity index 91% rename from crates/project/src/fs.rs rename to crates/fs/src/fs.rs index a9a0a1707f..2061d3734b 100644 --- a/crates/project/src/fs.rs +++ b/crates/fs/src/fs.rs @@ -1,10 +1,18 @@ +pub mod repository; + use anyhow::{anyhow, Result}; use fsevent::EventStream; use futures::{future::BoxFuture, Stream, StreamExt}; -use git::repository::{GitRepository, LibGitRepository}; -use language::LineEnding; +use git2::Repository as LibGitRepository; +use lazy_static::lazy_static; use parking_lot::Mutex as SyncMutex; +use regex::Regex; +use repository::GitRepository; +use rope::Rope; use smol::io::{AsyncReadExt, AsyncWriteExt}; +use std::borrow::Cow; +use std::cmp; +use std::io::Write; use std::sync::Arc; use std::{ io, @@ -13,7 +21,7 @@ use std::{ pin::Pin, time::{Duration, SystemTime}, }; -use text::Rope; +use tempfile::NamedTempFile; use util::ResultExt; #[cfg(any(test, feature = "test-support"))] @@ -21,10 +29,69 @@ use collections::{btree_map, BTreeMap}; #[cfg(any(test, feature = "test-support"))] use futures::lock::Mutex; #[cfg(any(test, feature = "test-support"))] -use git::repository::FakeGitRepositoryState; +use repository::FakeGitRepositoryState; #[cfg(any(test, feature = "test-support"))] use std::sync::Weak; +lazy_static! { + static ref CARRIAGE_RETURNS_REGEX: Regex = Regex::new("\r\n|\r").unwrap(); +} + +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum LineEnding { + Unix, + Windows, +} + +impl Default for LineEnding { + fn default() -> Self { + #[cfg(unix)] + return Self::Unix; + + #[cfg(not(unix))] + return Self::CRLF; + } +} + +impl LineEnding { + pub fn as_str(&self) -> &'static str { + match self { + LineEnding::Unix => "\n", + LineEnding::Windows => "\r\n", + } + } + + pub fn detect(text: &str) -> Self { + let mut max_ix = cmp::min(text.len(), 1000); + while !text.is_char_boundary(max_ix) { + max_ix -= 1; + } + + if let Some(ix) = text[..max_ix].find(&['\n']) { + if ix > 0 && text.as_bytes()[ix - 1] == b'\r' { + Self::Windows + } else { + Self::Unix + } + } else { + Self::default() + } + } + + pub fn normalize(text: &mut String) { + if let Cow::Owned(replaced) = CARRIAGE_RETURNS_REGEX.replace_all(text, "\n") { + *text = replaced; + } + } + + pub fn normalize_arc(text: Arc) -> Arc { + if let Cow::Owned(replaced) = CARRIAGE_RETURNS_REGEX.replace_all(&text, "\n") { + replaced.into() + } else { + text + } + } +} #[async_trait::async_trait] pub trait Fs: Send + Sync { async fn create_dir(&self, path: &Path) -> Result<()>; @@ -35,6 +102,7 @@ pub trait Fs: Send + Sync { async fn remove_file(&self, path: &Path, options: RemoveOptions) -> Result<()>; async fn open_sync(&self, path: &Path) -> Result>; async fn load(&self, path: &Path) -> Result; + async fn atomic_write(&self, path: PathBuf, text: String) -> Result<()>; async fn save(&self, path: &Path, text: &Rope, line_ending: LineEnding) -> Result<()>; async fn canonicalize(&self, path: &Path) -> Result; async fn is_file(&self, path: &Path) -> bool; @@ -86,6 +154,33 @@ pub struct Metadata { pub is_dir: bool, } +impl From for CreateOptions { + fn from(options: lsp::CreateFileOptions) -> Self { + Self { + overwrite: options.overwrite.unwrap_or(false), + ignore_if_exists: options.ignore_if_exists.unwrap_or(false), + } + } +} + +impl From for RenameOptions { + fn from(options: lsp::RenameFileOptions) -> Self { + Self { + overwrite: options.overwrite.unwrap_or(false), + ignore_if_exists: options.ignore_if_exists.unwrap_or(false), + } + } +} + +impl From for RemoveOptions { + fn from(options: lsp::DeleteFileOptions) -> Self { + Self { + recursive: options.recursive.unwrap_or(false), + ignore_if_not_exists: options.ignore_if_not_exists.unwrap_or(false), + } + } +} + pub struct RealFs; #[async_trait::async_trait] @@ -168,6 +263,18 @@ impl Fs for RealFs { Ok(text) } + async fn atomic_write(&self, path: PathBuf, data: String) -> Result<()> { + smol::unblock(move || { + let mut tmp_file = NamedTempFile::new()?; + tmp_file.write_all(data.as_bytes())?; + tmp_file.persist(path)?; + Ok::<(), anyhow::Error>(()) + }) + .await?; + + Ok(()) + } + async fn save(&self, path: &Path, text: &Rope, line_ending: LineEnding) -> Result<()> { let buffer_size = text.summary().len.min(10 * 1024); let file = smol::fs::File::create(path).await?; @@ -285,7 +392,7 @@ enum FakeFsEntry { inode: u64, mtime: SystemTime, entries: BTreeMap>>, - git_repo_state: Option>>, + git_repo_state: Option>>, }, Symlink { target: PathBuf, @@ -788,6 +895,14 @@ impl Fs for FakeFs { entry.file_content(&path).cloned() } + async fn atomic_write(&self, path: PathBuf, data: String) -> Result<()> { + self.simulate_random_delay().await; + let path = normalize_path(path.as_path()); + self.insert_file(path, data.to_string()).await; + + Ok(()) + } + async fn save(&self, path: &Path, text: &Rope, line_ending: LineEnding) -> Result<()> { self.simulate_random_delay().await; let path = normalize_path(path); @@ -897,7 +1012,7 @@ impl Fs for FakeFs { Arc::new(SyncMutex::new(FakeGitRepositoryState::default())) }) .clone(); - Some(git::repository::FakeGitRepository::open(state)) + Some(repository::FakeGitRepository::open(state)) } else { None } diff --git a/crates/git/src/repository.rs b/crates/fs/src/repository.rs similarity index 100% rename from crates/git/src/repository.rs rename to crates/fs/src/repository.rs diff --git a/crates/git/Cargo.toml b/crates/git/Cargo.toml index b8f3aac0b9..1d15c2b123 100644 --- a/crates/git/Cargo.toml +++ b/crates/git/Cargo.toml @@ -9,7 +9,7 @@ path = "src/git.rs" [dependencies] anyhow = "1.0.38" clock = { path = "../clock" } -git2 = { version = "0.15", default-features = false } +rope = { path = "../rope" } lazy_static = "1.4.0" sum_tree = { path = "../sum_tree" } text = { path = "../text" } @@ -20,6 +20,7 @@ smol = "1.2" parking_lot = "0.11.1" async-trait = "0.1" futures = "0.3" +git2 = { version = "0.15", default-features = false } [dev-dependencies] unindent = "0.1.7" diff --git a/crates/git/src/diff.rs b/crates/git/src/diff.rs index 4191e5d260..7f3f6101ce 100644 --- a/crates/git/src/diff.rs +++ b/crates/git/src/diff.rs @@ -1,7 +1,8 @@ use std::ops::Range; +use rope::point::Point; use sum_tree::SumTree; -use text::{Anchor, BufferSnapshot, OffsetRangeExt, Point}; +use text::{Anchor, BufferSnapshot, OffsetRangeExt}; pub use git2 as libgit; use libgit::{DiffLineType as GitDiffLineType, DiffOptions as GitOptions, Patch as GitPatch}; diff --git a/crates/git/src/git.rs b/crates/git/src/git.rs index 36f54e706a..b1b885eca2 100644 --- a/crates/git/src/git.rs +++ b/crates/git/src/git.rs @@ -4,7 +4,6 @@ pub use git2 as libgit; pub use lazy_static::lazy_static; pub mod diff; -pub mod repository; lazy_static! { pub static ref DOT_GIT: &'static OsStr = OsStr::new(".git"); diff --git a/crates/go_to_line/Cargo.toml b/crates/go_to_line/Cargo.toml index 93ae96f93e..d69b1f239c 100644 --- a/crates/go_to_line/Cargo.toml +++ b/crates/go_to_line/Cargo.toml @@ -13,5 +13,6 @@ gpui = { path = "../gpui" } menu = { path = "../menu" } settings = { path = "../settings" } text = { path = "../text" } +rope = { path = "../rope" } workspace = { path = "../workspace" } postage = { version = "0.4", features = ["futures-traits"] } diff --git a/crates/go_to_line/src/go_to_line.rs b/crates/go_to_line/src/go_to_line.rs index 3ca50cee42..51ff87a943 100644 --- a/crates/go_to_line/src/go_to_line.rs +++ b/crates/go_to_line/src/go_to_line.rs @@ -4,8 +4,9 @@ use gpui::{ MutableAppContext, RenderContext, View, ViewContext, ViewHandle, }; use menu::{Cancel, Confirm}; +use rope::point::Point; use settings::Settings; -use text::{Bias, Point}; +use text::Bias; use workspace::Workspace; actions!(go_to_line, [Toggle]); diff --git a/crates/language/Cargo.toml b/crates/language/Cargo.toml index e5b6f4c79b..54d2147929 100644 --- a/crates/language/Cargo.toml +++ b/crates/language/Cargo.toml @@ -25,9 +25,11 @@ client = { path = "../client" } clock = { path = "../clock" } collections = { path = "../collections" } fuzzy = { path = "../fuzzy" } +fs = { path = "../fs" } git = { path = "../git" } gpui = { path = "../gpui" } lsp = { path = "../lsp" } +rope = { path = "../rope" } rpc = { path = "../rpc" } settings = { path = "../settings" } sum_tree = { path = "../sum_tree" } diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index a3c0c54d01..a9af41bb23 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -13,9 +13,11 @@ use crate::{ }; use anyhow::{anyhow, Result}; use clock::ReplicaId; +use fs::LineEnding; use futures::FutureExt as _; use gpui::{fonts::HighlightStyle, AppContext, Entity, ModelContext, MutableAppContext, Task}; use parking_lot::Mutex; +use rope::point::Point; use settings::Settings; use similar::{ChangeTag, TextDiff}; use smol::future::yield_now; @@ -38,6 +40,8 @@ use sum_tree::TreeMap; use text::operation_queue::OperationQueue; pub use text::{Buffer as TextBuffer, BufferSnapshot as TextBufferSnapshot, Operation as _, *}; use theme::SyntaxTheme; +#[cfg(any(test, feature = "test-support"))] +use util::RandomCharIter; use util::TryFutureExt as _; #[cfg(any(test, feature = "test-support"))] @@ -368,7 +372,7 @@ impl Buffer { file, ); this.text.set_line_ending(proto::deserialize_line_ending( - proto::LineEnding::from_i32(message.line_ending) + rpc::proto::LineEnding::from_i32(message.line_ending) .ok_or_else(|| anyhow!("missing line_ending"))?, )); Ok(this) @@ -1633,9 +1637,7 @@ impl Buffer { last_end = Some(range.end); let new_text_len = rng.gen_range(0..10); - let new_text: String = crate::random_char_iter::RandomCharIter::new(&mut *rng) - .take(new_text_len) - .collect(); + let new_text: String = RandomCharIter::new(&mut *rng).take(new_text_len).collect(); edits.push((range, new_text)); } diff --git a/crates/language/src/buffer_tests.rs b/crates/language/src/buffer_tests.rs index 3cfddce71f..313c843b02 100644 --- a/crates/language/src/buffer_tests.rs +++ b/crates/language/src/buffer_tests.rs @@ -1,9 +1,11 @@ use super::*; use clock::ReplicaId; use collections::BTreeMap; +use fs::LineEnding; use gpui::{ModelHandle, MutableAppContext}; use proto::deserialize_operation; use rand::prelude::*; +use rope::point::Point; use settings::Settings; use std::{ cell::RefCell, @@ -14,7 +16,7 @@ use std::{ }; use text::network::Network; use unindent::Unindent as _; -use util::{post_inc, test::marked_text_ranges}; +use util::{post_inc, test::marked_text_ranges, RandomCharIter}; #[cfg(test)] #[ctor::ctor] diff --git a/crates/language/src/diagnostic_set.rs b/crates/language/src/diagnostic_set.rs index b52327cac0..dfbc32149c 100644 --- a/crates/language/src/diagnostic_set.rs +++ b/crates/language/src/diagnostic_set.rs @@ -1,12 +1,13 @@ use crate::Diagnostic; use collections::HashMap; +use rope::point_utf16::PointUtf16; use std::{ cmp::{Ordering, Reverse}, iter, ops::Range, }; use sum_tree::{self, Bias, SumTree}; -use text::{Anchor, FromAnchor, PointUtf16, ToOffset}; +use text::{Anchor, FromAnchor, ToOffset}; #[derive(Clone, Debug, Default)] pub struct DiagnosticSet { diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index bb75edbc32..4f8615606c 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -22,6 +22,7 @@ use lazy_static::lazy_static; use parking_lot::{Mutex, RwLock}; use postage::watch; use regex::Regex; +use rope::point_utf16::PointUtf16; use serde::{de, Deserialize, Deserializer}; use serde_json::Value; use std::{ diff --git a/crates/language/src/proto.rs b/crates/language/src/proto.rs index fddfb7961f..9e3ee7d46b 100644 --- a/crates/language/src/proto.rs +++ b/crates/language/src/proto.rs @@ -8,19 +8,19 @@ use rpc::proto; use std::{ops::Range, sync::Arc}; use text::*; -pub use proto::{BufferState, LineEnding, Operation, SelectionSet}; +pub use proto::{BufferState, Operation, SelectionSet}; -pub fn deserialize_line_ending(message: proto::LineEnding) -> text::LineEnding { +pub fn deserialize_line_ending(message: proto::LineEnding) -> fs::LineEnding { match message { - LineEnding::Unix => text::LineEnding::Unix, - LineEnding::Windows => text::LineEnding::Windows, + proto::LineEnding::Unix => fs::LineEnding::Unix, + proto::LineEnding::Windows => fs::LineEnding::Windows, } } -pub fn serialize_line_ending(message: text::LineEnding) -> proto::LineEnding { +pub fn serialize_line_ending(message: fs::LineEnding) -> proto::LineEnding { match message { - text::LineEnding::Unix => proto::LineEnding::Unix, - text::LineEnding::Windows => proto::LineEnding::Windows, + fs::LineEnding::Unix => proto::LineEnding::Unix, + fs::LineEnding::Windows => proto::LineEnding::Windows, } } diff --git a/crates/language/src/syntax_map.rs b/crates/language/src/syntax_map.rs index 64145e535b..3992d41081 100644 --- a/crates/language/src/syntax_map.rs +++ b/crates/language/src/syntax_map.rs @@ -1,6 +1,7 @@ use crate::{Grammar, InjectionConfig, Language, LanguageRegistry}; use lazy_static::lazy_static; use parking_lot::Mutex; +use rope::point::Point; use std::{ borrow::Cow, cell::RefCell, @@ -10,7 +11,7 @@ use std::{ sync::Arc, }; use sum_tree::{Bias, SeekTarget, SumTree}; -use text::{rope, Anchor, BufferSnapshot, OffsetRangeExt, Point, Rope, ToOffset, ToPoint}; +use text::{Anchor, BufferSnapshot, OffsetRangeExt, Rope, ToOffset, ToPoint}; use tree_sitter::{ Node, Parser, Query, QueryCapture, QueryCaptures, QueryCursor, QueryMatches, Tree, }; @@ -1242,7 +1243,7 @@ mod tests { use crate::LanguageConfig; use rand::rngs::StdRng; use std::env; - use text::{Buffer, Point}; + use text::Buffer; use unindent::Unindent as _; use util::test::marked_text_ranges; diff --git a/crates/project/Cargo.toml b/crates/project/Cargo.toml index 1e45e3c6ed..7a41318b86 100644 --- a/crates/project/Cargo.toml +++ b/crates/project/Cargo.toml @@ -22,12 +22,14 @@ client = { path = "../client" } clock = { path = "../clock" } collections = { path = "../collections" } db = { path = "../db" } +fs = { path = "../fs" } fsevent = { path = "../fsevent" } fuzzy = { path = "../fuzzy" } git = { path = "../git" } gpui = { path = "../gpui" } language = { path = "../language" } lsp = { path = "../lsp" } +rope = { path = "../rope" } rpc = { path = "../rpc" } settings = { path = "../settings" } sum_tree = { path = "../sum_tree" } @@ -38,7 +40,6 @@ async-trait = "0.1" futures = "0.3" ignore = "0.4" lazy_static = "1.4.0" -libc = "0.2" log = { version = "0.4.16", features = ["kv_unstable_serde"] } parking_lot = "0.11.1" postage = { version = "0.4.1", features = ["futures-traits"] } @@ -58,6 +59,7 @@ rocksdb = "0.18" client = { path = "../client", features = ["test-support"] } collections = { path = "../collections", features = ["test-support"] } db = { path = "../db", features = ["test-support"] } +fs = { path = "../fs", features = ["test-support"] } gpui = { path = "../gpui", features = ["test-support"] } language = { path = "../language", features = ["test-support"] } lsp = { path = "../lsp", features = ["test-support"] } diff --git a/crates/project/src/lsp_command.rs b/crates/project/src/lsp_command.rs index 37f6e76340..42098d2e8b 100644 --- a/crates/project/src/lsp_command.rs +++ b/crates/project/src/lsp_command.rs @@ -8,10 +8,11 @@ use gpui::{AppContext, AsyncAppContext, ModelHandle}; use language::{ point_from_lsp, point_to_lsp, proto::{deserialize_anchor, deserialize_version, serialize_anchor, serialize_version}, - range_from_lsp, Anchor, Bias, Buffer, CachedLspAdapter, PointUtf16, ToPointUtf16, + range_from_lsp, Anchor, Bias, Buffer, CachedLspAdapter, ToPointUtf16, }; use lsp::{DocumentHighlightKind, LanguageServer, ServerCapabilities}; use pulldown_cmark::{CodeBlockKind, Event, Options, Parser, Tag}; +use rope::point_utf16::PointUtf16; use std::{cmp::Reverse, ops::Range, path::Path, sync::Arc}; #[async_trait(?Send)] diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 84f45070fd..11792bcf1e 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -1,4 +1,3 @@ -pub mod fs; mod ignore; mod lsp_command; pub mod search; @@ -25,9 +24,8 @@ use language::{ }, range_from_lsp, range_to_lsp, Anchor, Bias, Buffer, CachedLspAdapter, CharKind, CodeAction, CodeLabel, Completion, Diagnostic, DiagnosticEntry, DiagnosticSet, Event as BufferEvent, - File as _, Language, LanguageRegistry, LanguageServerName, LineEnding, LocalFile, - OffsetRangeExt, Operation, Patch, PointUtf16, TextBufferSnapshot, ToOffset, ToPointUtf16, - Transaction, + File as _, Language, LanguageRegistry, LanguageServerName, LocalFile, OffsetRangeExt, + Operation, Patch, TextBufferSnapshot, ToOffset, ToPointUtf16, Transaction, }; use lsp::{ DiagnosticSeverity, DiagnosticTag, DocumentHighlightKind, LanguageServer, LanguageString, @@ -37,6 +35,7 @@ use lsp_command::*; use parking_lot::Mutex; use postage::watch; use rand::prelude::*; +use rope::point_utf16::PointUtf16; use search::SearchQuery; use serde::Serialize; use settings::{FormatOnSave, Formatter, Settings}; @@ -6019,33 +6018,6 @@ impl> From<(WorktreeId, P)> for ProjectPath { } } -impl From for fs::CreateOptions { - fn from(options: lsp::CreateFileOptions) -> Self { - Self { - overwrite: options.overwrite.unwrap_or(false), - ignore_if_exists: options.ignore_if_exists.unwrap_or(false), - } - } -} - -impl From for fs::RenameOptions { - fn from(options: lsp::RenameFileOptions) -> Self { - Self { - overwrite: options.overwrite.unwrap_or(false), - ignore_if_exists: options.ignore_if_exists.unwrap_or(false), - } - } -} - -impl From for fs::RemoveOptions { - fn from(options: lsp::DeleteFileOptions) -> Self { - Self { - recursive: options.recursive.unwrap_or(false), - ignore_if_not_exists: options.ignore_if_not_exists.unwrap_or(false), - } - } -} - fn serialize_symbol(symbol: &Symbol) -> proto::Symbol { proto::Symbol { language_server_name: symbol.language_server_name.0.to_string(), diff --git a/crates/project/src/project_tests.rs b/crates/project/src/project_tests.rs index ceb5d033a7..12da0a75db 100644 --- a/crates/project/src/project_tests.rs +++ b/crates/project/src/project_tests.rs @@ -1,12 +1,14 @@ use crate::{worktree::WorktreeHandle, Event, *}; -use fs::RealFs; +use fs::LineEnding; +use fs::{FakeFs, RealFs}; use futures::{future, StreamExt}; use gpui::{executor::Deterministic, test::subscribe}; use language::{ tree_sitter_rust, tree_sitter_typescript, Diagnostic, FakeLspAdapter, LanguageConfig, - LineEnding, OffsetRangeExt, Point, ToPoint, + OffsetRangeExt, ToPoint, }; use lsp::Url; +use rope::point::Point; use serde_json::json; use std::{cell::RefCell, os::unix, rc::Rc, task::Poll}; use unindent::Unindent as _; diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index 968c2d4bc7..3073392a52 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -1,14 +1,12 @@ -use super::{ - fs::{self, Fs}, - ignore::IgnoreStack, - DiagnosticSummary, -}; +use super::{ignore::IgnoreStack, DiagnosticSummary}; use crate::{copy_recursive, ProjectEntryId, RemoveOptions}; use ::ignore::gitignore::{Gitignore, GitignoreBuilder}; use anyhow::{anyhow, Context, Result}; use client::{proto, Client}; use clock::ReplicaId; use collections::{HashMap, VecDeque}; +use fs::LineEnding; +use fs::{repository::GitRepository, Fs}; use futures::{ channel::{ mpsc::{self, UnboundedSender}, @@ -17,7 +15,6 @@ use futures::{ Stream, StreamExt, }; use fuzzy::CharBag; -use git::repository::GitRepository; use git::{DOT_GIT, GITIGNORE}; use gpui::{ executor, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, MutableAppContext, @@ -25,13 +22,14 @@ use gpui::{ }; use language::{ proto::{deserialize_version, serialize_line_ending, serialize_version}, - Buffer, DiagnosticEntry, LineEnding, PointUtf16, Rope, + Buffer, DiagnosticEntry, Rope, }; use parking_lot::Mutex; use postage::{ prelude::{Sink as _, Stream as _}, watch, }; +use rope::point_utf16::PointUtf16; use smol::channel::{self, Sender}; use std::{ @@ -2970,11 +2968,10 @@ async fn send_worktree_update(client: &Arc, update: proto::UpdateWorktre #[cfg(test)] mod tests { use super::*; - use crate::fs::FakeFs; use anyhow::Result; use client::test::FakeHttpClient; - use fs::RealFs; - use git::repository::FakeGitRepository; + use fs::repository::FakeGitRepository; + use fs::{FakeFs, RealFs}; use gpui::{executor::Deterministic, TestAppContext}; use rand::prelude::*; use serde_json::json; diff --git a/crates/rope/Cargo.toml b/crates/rope/Cargo.toml new file mode 100644 index 0000000000..0f754c1fb3 --- /dev/null +++ b/crates/rope/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "rope" +version = "0.1.0" +edition = "2021" + +[lib] +path = "src/rope.rs" + +[dependencies] +bromberg_sl2 = "0.6" +smallvec = { version = "1.6", features = ["union"] } +sum_tree = { path = "../sum_tree" } +arrayvec = "0.7.1" +log = { version = "0.4.16", features = ["kv_unstable_serde"] } + + +[dev-dependencies] +rand = "0.8.3" +util = { path = "../util", features = ["test-support"] } +gpui = { path = "../gpui", features = ["test-support"] } diff --git a/crates/text/src/offset_utf16.rs b/crates/rope/src/offset_utf16.rs similarity index 100% rename from crates/text/src/offset_utf16.rs rename to crates/rope/src/offset_utf16.rs diff --git a/crates/text/src/point.rs b/crates/rope/src/point.rs similarity index 100% rename from crates/text/src/point.rs rename to crates/rope/src/point.rs diff --git a/crates/text/src/point_utf16.rs b/crates/rope/src/point_utf16.rs similarity index 100% rename from crates/text/src/point_utf16.rs rename to crates/rope/src/point_utf16.rs diff --git a/crates/text/src/rope.rs b/crates/rope/src/rope.rs similarity index 99% rename from crates/text/src/rope.rs rename to crates/rope/src/rope.rs index e148c048bb..39dc9dc049 100644 --- a/crates/text/src/rope.rs +++ b/crates/rope/src/rope.rs @@ -1,7 +1,12 @@ -use super::Point; -use crate::{OffsetUtf16, PointUtf16}; +pub mod offset_utf16; +pub mod point; +pub mod point_utf16; + use arrayvec::ArrayString; use bromberg_sl2::{DigestString, HashMatrix}; +use offset_utf16::OffsetUtf16; +use point::Point; +use point_utf16::PointUtf16; use smallvec::SmallVec; use std::{cmp, fmt, io, mem, ops::Range, str}; use sum_tree::{Bias, Dimension, SumTree}; @@ -1073,9 +1078,9 @@ fn find_split_ix(text: &str) -> usize { #[cfg(test)] mod tests { use super::*; - use crate::random_char_iter::RandomCharIter; use rand::prelude::*; use std::{cmp::Ordering, env, io::Read}; + use util::RandomCharIter; use Bias::{Left, Right}; #[test] diff --git a/crates/settings/Cargo.toml b/crates/settings/Cargo.toml index 78440a2418..1cc73fabc4 100644 --- a/crates/settings/Cargo.toml +++ b/crates/settings/Cargo.toml @@ -14,12 +14,23 @@ test-support = [] assets = { path = "../assets" } collections = { path = "../collections" } gpui = { path = "../gpui" } +fs = { path = "../fs" } +anyhow = "1.0.38" +futures = "0.3" theme = { path = "../theme" } util = { path = "../util" } -anyhow = "1.0.38" +rope = { path = "../rope" } json_comments = "0.2" +postage = { version = "0.4.1", features = ["futures-traits"] } schemars = "0.8" -serde = { version = "1.0", features = ["derive", "rc"] } -serde_json = { version = "1.0", features = ["preserve_order"] } +serde = { workspace = true } +serde_json = { workspace = true } serde_path_to_error = "0.1.4" toml = "0.5" +tree-sitter = "*" +tree-sitter-json = "*" + +[dev-dependencies] +unindent = "0.1" +gpui = { path = "../gpui", features = ["test-support"] } +fs = { path = "../fs", features = ["test-support"] } diff --git a/crates/settings/src/settings.rs b/crates/settings/src/settings.rs index d661eb0f21..2e7dc08d16 100644 --- a/crates/settings/src/settings.rs +++ b/crates/settings/src/settings.rs @@ -1,4 +1,5 @@ mod keymap_file; +pub mod settings_file; use anyhow::Result; use gpui::{ @@ -12,8 +13,9 @@ use schemars::{ }; use serde::{de::DeserializeOwned, Deserialize}; use serde_json::Value; -use std::{collections::HashMap, num::NonZeroU32, str, sync::Arc}; +use std::{collections::HashMap, fmt::Write as _, num::NonZeroU32, str, sync::Arc}; use theme::{Theme, ThemeRegistry}; +use tree_sitter::Query; use util::ResultExt as _; pub use keymap_file::{keymap_file_json_schema, KeymapFileContent}; @@ -501,6 +503,101 @@ pub fn settings_file_json_schema( serde_json::to_value(root_schema).unwrap() } +pub fn write_top_level_setting( + mut settings_content: String, + top_level_key: &str, + new_val: &str, +) -> String { + let mut parser = tree_sitter::Parser::new(); + parser.set_language(tree_sitter_json::language()).unwrap(); + let tree = parser.parse(&settings_content, None).unwrap(); + + let mut cursor = tree_sitter::QueryCursor::new(); + + let query = Query::new( + tree_sitter_json::language(), + " + (document + (object + (pair + key: (string) @key + value: (_) @value))) + ", + ) + .unwrap(); + + let mut first_key_start = None; + let mut existing_value_range = None; + let matches = cursor.matches(&query, tree.root_node(), settings_content.as_bytes()); + for mat in matches { + if mat.captures.len() != 2 { + continue; + } + + let key = mat.captures[0]; + let value = mat.captures[1]; + + first_key_start.get_or_insert_with(|| key.node.start_byte()); + + if let Some(key_text) = settings_content.get(key.node.byte_range()) { + if key_text == format!("\"{top_level_key}\"") { + existing_value_range = Some(value.node.byte_range()); + break; + } + } + } + + match (first_key_start, existing_value_range) { + (None, None) => { + // No document, create a new object and overwrite + settings_content.clear(); + write!( + settings_content, + "{{\n \"{}\": \"{new_val}\"\n}}\n", + top_level_key + ) + .unwrap(); + } + + (_, Some(existing_value_range)) => { + // Existing theme key, overwrite + settings_content.replace_range(existing_value_range, &format!("\"{new_val}\"")); + } + + (Some(first_key_start), None) => { + // No existing theme key, but other settings. Prepend new theme settings and + // match style of first key + let mut row = 0; + let mut column = 0; + for (ix, char) in settings_content.char_indices() { + if ix == first_key_start { + break; + } + if char == '\n' { + row += 1; + column = 0; + } else { + column += char.len_utf8(); + } + } + + let content = format!(r#""{top_level_key}": "{new_val}","#); + settings_content.insert_str(first_key_start, &content); + + if row > 0 { + settings_content.insert_str( + first_key_start + content.len(), + &format!("\n{:width$}", ' ', width = column), + ) + } else { + settings_content.insert_str(first_key_start + content.len(), " ") + } + } + } + + settings_content +} + fn merge(target: &mut T, value: Option) { if let Some(value) = value { *target = value; @@ -512,3 +609,108 @@ pub fn parse_json_with_comments(content: &str) -> Result json_comments::CommentSettings::c_style().strip_comments(content.as_bytes()), )?) } + +#[cfg(test)] +mod tests { + use crate::write_top_level_setting; + use unindent::Unindent; + + #[test] + fn test_write_theme_into_settings_with_theme() { + let settings = r#" + { + "theme": "one-dark" + } + "# + .unindent(); + + let new_settings = r#" + { + "theme": "summerfruit-light" + } + "# + .unindent(); + + let settings_after_theme = write_top_level_setting(settings, "theme", "summerfruit-light"); + + assert_eq!(settings_after_theme, new_settings) + } + + #[test] + fn test_write_theme_into_empty_settings() { + let settings = r#" + { + } + "# + .unindent(); + + let new_settings = r#" + { + "theme": "summerfruit-light" + } + "# + .unindent(); + + let settings_after_theme = write_top_level_setting(settings, "theme", "summerfruit-light"); + + assert_eq!(settings_after_theme, new_settings) + } + + #[test] + fn test_write_theme_into_no_settings() { + let settings = "".to_string(); + + let new_settings = r#" + { + "theme": "summerfruit-light" + } + "# + .unindent(); + + let settings_after_theme = write_top_level_setting(settings, "theme", "summerfruit-light"); + + assert_eq!(settings_after_theme, new_settings) + } + + #[test] + fn test_write_theme_into_single_line_settings_without_theme() { + let settings = r#"{ "a": "", "ok": true }"#.to_string(); + let new_settings = r#"{ "theme": "summerfruit-light", "a": "", "ok": true }"#; + + let settings_after_theme = write_top_level_setting(settings, "theme", "summerfruit-light"); + + assert_eq!(settings_after_theme, new_settings) + } + + #[test] + fn test_write_theme_pre_object_whitespace() { + let settings = r#" { "a": "", "ok": true }"#.to_string(); + let new_settings = r#" { "theme": "summerfruit-light", "a": "", "ok": true }"#; + + let settings_after_theme = write_top_level_setting(settings, "theme", "summerfruit-light"); + + assert_eq!(settings_after_theme, new_settings) + } + + #[test] + fn test_write_theme_into_multi_line_settings_without_theme() { + let settings = r#" + { + "a": "b" + } + "# + .unindent(); + + let new_settings = r#" + { + "theme": "summerfruit-light", + "a": "b" + } + "# + .unindent(); + + let settings_after_theme = write_top_level_setting(settings, "theme", "summerfruit-light"); + + assert_eq!(settings_after_theme, new_settings) + } +} diff --git a/crates/zed/src/settings_file.rs b/crates/settings/src/settings_file.rs similarity index 83% rename from crates/zed/src/settings_file.rs rename to crates/settings/src/settings_file.rs index 14c9f63e95..6a7c96fd81 100644 --- a/crates/zed/src/settings_file.rs +++ b/crates/settings/src/settings_file.rs @@ -1,14 +1,59 @@ +use fs::Fs; use futures::StreamExt; use gpui::{executor, MutableAppContext}; use postage::sink::Sink as _; use postage::{prelude::Stream, watch}; -use project::Fs; use serde::Deserialize; -use settings::{parse_json_with_comments, KeymapFileContent, Settings, SettingsFileContent}; + use std::{path::Path, sync::Arc, time::Duration}; use theme::ThemeRegistry; use util::ResultExt; +use crate::{ + parse_json_with_comments, write_top_level_setting, KeymapFileContent, Settings, + SettingsFileContent, +}; + +// TODO: Switch SettingsFile to open a worktree and buffer for synchronization +// And instant updates in the Zed editor +#[derive(Clone)] +pub struct SettingsFile { + path: &'static Path, + fs: Arc, +} + +impl SettingsFile { + pub fn new(path: &'static Path, fs: Arc) -> Self { + SettingsFile { path, fs } + } + + pub async fn rewrite_settings_file(&self, f: F) -> anyhow::Result<()> + where + F: Fn(String) -> String, + { + let content = self.fs.load(self.path).await?; + + let new_settings = f(content); + + self.fs + .atomic_write(self.path.to_path_buf(), new_settings) + .await?; + + Ok(()) + } +} + +pub fn write_setting(key: &'static str, val: String, cx: &mut MutableAppContext) { + let settings_file = cx.global::().clone(); + cx.background() + .spawn(async move { + settings_file + .rewrite_settings_file(|settings| write_top_level_setting(settings, key, &val)) + .await + }) + .detach_and_log_err(cx); +} + #[derive(Clone)] pub struct WatchedJsonFile(pub watch::Receiver); @@ -73,7 +118,7 @@ pub fn watch_settings_file( pub fn keymap_updated(content: KeymapFileContent, cx: &mut MutableAppContext) { cx.clear_bindings(); - settings::KeymapFileContent::load_defaults(cx); + KeymapFileContent::load_defaults(cx); content.add_to_cx(cx).log_err(); } @@ -101,8 +146,8 @@ pub fn watch_keymap_file(mut file: WatchedJsonFile, cx: &mut #[cfg(test)] mod tests { use super::*; - use project::FakeFs; - use settings::{EditorSettings, SoftWrap}; + use crate::{EditorSettings, SoftWrap}; + use fs::FakeFs; #[gpui::test] async fn test_watch_settings_files(cx: &mut gpui::TestAppContext) { diff --git a/crates/text/Cargo.toml b/crates/text/Cargo.toml index 4fc09eff46..ad960ec93e 100644 --- a/crates/text/Cargo.toml +++ b/crates/text/Cargo.toml @@ -13,23 +13,24 @@ test-support = ["rand"] [dependencies] clock = { path = "../clock" } collections = { path = "../collections" } +fs = { path = "../fs" } +rope = { path = "../rope" } sum_tree = { path = "../sum_tree" } anyhow = "1.0.38" -arrayvec = "0.7.1" digest = { version = "0.9", features = ["std"] } -bromberg_sl2 = "0.6" lazy_static = "1.4" log = { version = "0.4.16", features = ["kv_unstable_serde"] } parking_lot = "0.11" postage = { version = "0.4.1", features = ["futures-traits"] } rand = { version = "0.8.3", optional = true } -regex = "1.5" smallvec = { version = "1.6", features = ["union"] } +util = { path = "../util" } +regex = "1.5" + [dev-dependencies] collections = { path = "../collections", features = ["test-support"] } gpui = { path = "../gpui", features = ["test-support"] } -util = { path = "../util", features = ["test-support"] } ctor = "0.1" env_logger = "0.9" rand = "0.8.3" diff --git a/crates/text/src/anchor.rs b/crates/text/src/anchor.rs index 9f70ae1cc7..024c7e643b 100644 --- a/crates/text/src/anchor.rs +++ b/crates/text/src/anchor.rs @@ -1,9 +1,10 @@ -use super::{Point, ToOffset}; -use crate::{rope::TextDimension, BufferSnapshot, PointUtf16, ToPoint, ToPointUtf16}; use anyhow::Result; +use rope::{point::Point, point_utf16::PointUtf16, TextDimension}; use std::{cmp::Ordering, fmt::Debug, ops::Range}; use sum_tree::Bias; +use crate::{BufferSnapshot, ToOffset, ToPoint, ToPointUtf16}; + #[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, Default)] pub struct Anchor { pub timestamp: clock::Local, diff --git a/crates/text/src/random_char_iter.rs b/crates/text/src/random_char_iter.rs deleted file mode 100644 index 04cdcd3524..0000000000 --- a/crates/text/src/random_char_iter.rs +++ /dev/null @@ -1,36 +0,0 @@ -use rand::prelude::*; - -pub struct RandomCharIter(T); - -impl RandomCharIter { - pub fn new(rng: T) -> Self { - Self(rng) - } -} - -impl Iterator for RandomCharIter { - type Item = char; - - fn next(&mut self) -> Option { - if std::env::var("SIMPLE_TEXT").map_or(false, |v| !v.is_empty()) { - return if self.0.gen_range(0..100) < 5 { - Some('\n') - } else { - Some(self.0.gen_range(b'a'..b'z' + 1).into()) - }; - } - - match self.0.gen_range(0..100) { - // whitespace - 0..=19 => [' ', '\n', '\r', '\t'].choose(&mut self.0).copied(), - // two-byte greek letters - 20..=32 => char::from_u32(self.0.gen_range(('α' as u32)..('ω' as u32 + 1))), - // // three-byte characters - 33..=45 => ['✋', '✅', '❌', '❎', '⭐'].choose(&mut self.0).copied(), - // // four-byte characters - 46..=58 => ['🍐', '🏀', '🍗', '🎉'].choose(&mut self.0).copied(), - // ascii letters - _ => Some(self.0.gen_range(b'a'..b'z' + 1).into()), - } - } -} diff --git a/crates/text/src/selection.rs b/crates/text/src/selection.rs index e5acbd21bc..881fc8c432 100644 --- a/crates/text/src/selection.rs +++ b/crates/text/src/selection.rs @@ -1,5 +1,7 @@ -use crate::Anchor; -use crate::{rope::TextDimension, BufferSnapshot}; +use rope::TextDimension; + +use crate::{Anchor, BufferSnapshot}; + use std::cmp::Ordering; use std::ops::Range; diff --git a/crates/text/src/text.rs b/crates/text/src/text.rs index d201f87443..2196e870f2 100644 --- a/crates/text/src/text.rs +++ b/crates/text/src/text.rs @@ -2,14 +2,8 @@ mod anchor; pub mod locator; #[cfg(any(test, feature = "test-support"))] pub mod network; -mod offset_utf16; pub mod operation_queue; mod patch; -mod point; -mod point_utf16; -#[cfg(any(test, feature = "test-support"))] -pub mod random_char_iter; -pub mod rope; mod selection; pub mod subscription; #[cfg(test)] @@ -20,22 +14,15 @@ pub use anchor::*; use anyhow::Result; use clock::ReplicaId; use collections::{HashMap, HashSet}; -use lazy_static::lazy_static; +use fs::LineEnding; use locator::Locator; -pub use offset_utf16::*; use operation_queue::OperationQueue; pub use patch::Patch; -pub use point::*; -pub use point_utf16::*; use postage::{barrier, oneshot, prelude::*}; -#[cfg(any(test, feature = "test-support"))] -pub use random_char_iter::*; -use regex::Regex; -use rope::TextDimension; +use rope::{offset_utf16::OffsetUtf16, point::Point, point_utf16::PointUtf16, TextDimension}; pub use rope::{Chunks, Rope, TextSummary}; pub use selection::*; use std::{ - borrow::Cow, cmp::{self, Ordering, Reverse}, future::Future, iter::Iterator, @@ -49,9 +36,8 @@ pub use sum_tree::Bias; use sum_tree::{FilterCursor, SumTree, TreeMap}; use undo_map::UndoMap; -lazy_static! { - static ref CARRIAGE_RETURNS_REGEX: Regex = Regex::new("\r\n|\r").unwrap(); -} +#[cfg(any(test, feature = "test-support"))] +use util::RandomCharIter; pub type TransactionId = clock::Local; @@ -96,12 +82,6 @@ pub struct Transaction { pub start: clock::Global, } -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum LineEnding { - Unix, - Windows, -} - impl HistoryEntry { pub fn transaction_id(&self) -> TransactionId { self.transaction.id @@ -1464,9 +1444,7 @@ impl Buffer { last_end = Some(range.end); let new_text_len = rng.gen_range(0..10); - let new_text: String = crate::random_char_iter::RandomCharIter::new(&mut *rng) - .take(new_text_len) - .collect(); + let new_text: String = RandomCharIter::new(&mut *rng).take(new_text_len).collect(); edits.push((range, new_text.into())); } @@ -2370,56 +2348,6 @@ impl operation_queue::Operation for Operation { } } -impl Default for LineEnding { - fn default() -> Self { - #[cfg(unix)] - return Self::Unix; - - #[cfg(not(unix))] - return Self::CRLF; - } -} - -impl LineEnding { - pub fn as_str(&self) -> &'static str { - match self { - LineEnding::Unix => "\n", - LineEnding::Windows => "\r\n", - } - } - - pub fn detect(text: &str) -> Self { - let mut max_ix = cmp::min(text.len(), 1000); - while !text.is_char_boundary(max_ix) { - max_ix -= 1; - } - - if let Some(ix) = text[..max_ix].find(&['\n']) { - if ix > 0 && text.as_bytes()[ix - 1] == b'\r' { - Self::Windows - } else { - Self::Unix - } - } else { - Self::default() - } - } - - pub fn normalize(text: &mut String) { - if let Cow::Owned(replaced) = CARRIAGE_RETURNS_REGEX.replace_all(text, "\n") { - *text = replaced; - } - } - - fn normalize_arc(text: Arc) -> Arc { - if let Cow::Owned(replaced) = CARRIAGE_RETURNS_REGEX.replace_all(&text, "\n") { - replaced.into() - } else { - text - } - } -} - pub trait ToOffset { fn to_offset(&self, snapshot: &BufferSnapshot) -> usize; } diff --git a/crates/theme_selector/Cargo.toml b/crates/theme_selector/Cargo.toml index 804eff2c7a..59cb5fbc2c 100644 --- a/crates/theme_selector/Cargo.toml +++ b/crates/theme_selector/Cargo.toml @@ -19,3 +19,4 @@ log = { version = "0.4.16", features = ["kv_unstable_serde"] } parking_lot = "0.11.1" postage = { version = "0.4.1", features = ["futures-traits"] } smol = "1.2.5" + diff --git a/crates/theme_selector/src/theme_selector.rs b/crates/theme_selector/src/theme_selector.rs index 59b0bc7e6a..f3ca38b78b 100644 --- a/crates/theme_selector/src/theme_selector.rs +++ b/crates/theme_selector/src/theme_selector.rs @@ -107,7 +107,9 @@ impl ThemeSelector { fn show_selected_theme(&mut self, cx: &mut ViewContext) { if let Some(mat) = self.matches.get(self.selected_index) { match self.registry.get(&mat.string) { - Ok(theme) => Self::set_theme(theme, cx), + Ok(theme) => { + Self::set_theme(theme, cx); + } Err(error) => { log::error!("error loading theme {}: {}", mat.string, error) } @@ -151,6 +153,10 @@ impl PickerDelegate for ThemeSelector { fn confirm(&mut self, cx: &mut ViewContext) { self.selection_completed = true; + + let theme_name = cx.global::().theme.meta.name.clone(); + settings::settings_file::write_setting("theme", theme_name, cx); + cx.emit(Event::Dismissed); } diff --git a/crates/util/Cargo.toml b/crates/util/Cargo.toml index 78416aa5b5..c083137156 100644 --- a/crates/util/Cargo.toml +++ b/crates/util/Cargo.toml @@ -7,21 +7,20 @@ edition = "2021" doctest = false [features] -test-support = ["rand", "serde_json", "tempdir", "git2"] +test-support = ["serde_json", "tempdir", "git2"] [dependencies] anyhow = "1.0.38" futures = "0.3" log = { version = "0.4.16", features = ["kv_unstable_serde"] } lazy_static = "1.4.0" -rand = { version = "0.8", optional = true } +rand = { workspace = true } tempdir = { version = "0.3.7", optional = true } serde_json = { version = "1.0", features = ["preserve_order"], optional = true } git2 = { version = "0.15", default-features = false, optional = true } [dev-dependencies] -rand = { version = "0.8" } tempdir = { version = "0.3.7" } serde_json = { version = "1.0", features = ["preserve_order"] } git2 = { version = "0.15", default-features = false } diff --git a/crates/util/src/lib.rs b/crates/util/src/lib.rs index 97f409f410..e35f2df7d4 100644 --- a/crates/util/src/lib.rs +++ b/crates/util/src/lib.rs @@ -2,6 +2,7 @@ pub mod test; use futures::Future; +use rand::{seq::SliceRandom, Rng}; use std::{ cmp::Ordering, ops::AddAssign, @@ -155,6 +156,41 @@ pub fn defer(f: F) -> impl Drop { Defer(Some(f)) } +pub struct RandomCharIter(T); + +impl RandomCharIter { + pub fn new(rng: T) -> Self { + Self(rng) + } +} + +impl Iterator for RandomCharIter { + type Item = char; + + fn next(&mut self) -> Option { + if std::env::var("SIMPLE_TEXT").map_or(false, |v| !v.is_empty()) { + return if self.0.gen_range(0..100) < 5 { + Some('\n') + } else { + Some(self.0.gen_range(b'a'..b'z' + 1).into()) + }; + } + + match self.0.gen_range(0..100) { + // whitespace + 0..=19 => [' ', '\n', '\r', '\t'].choose(&mut self.0).copied(), + // two-byte greek letters + 20..=32 => char::from_u32(self.0.gen_range(('α' as u32)..('ω' as u32 + 1))), + // // three-byte characters + 33..=45 => ['✋', '✅', '❌', '❎', '⭐'].choose(&mut self.0).copied(), + // // four-byte characters + 46..=58 => ['🍐', '🏀', '🍗', '🎉'].choose(&mut self.0).copied(), + // ascii letters + _ => Some(self.0.gen_range(b'a'..b'z' + 1).into()), + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/vim/Cargo.toml b/crates/vim/Cargo.toml index 44f2a8cb16..85c9636c69 100644 --- a/crates/vim/Cargo.toml +++ b/crates/vim/Cargo.toml @@ -27,6 +27,7 @@ command_palette = { path = "../command_palette" } editor = { path = "../editor" } gpui = { path = "../gpui" } language = { path = "../language" } +rope = { path = "../rope" } search = { path = "../search" } settings = { path = "../settings" } workspace = { path = "../workspace" } diff --git a/crates/vim/src/normal.rs b/crates/vim/src/normal.rs index 894b77e6e8..6741d8ac0b 100644 --- a/crates/vim/src/normal.rs +++ b/crates/vim/src/normal.rs @@ -15,7 +15,8 @@ use editor::{ display_map::ToDisplayPoint, Anchor, Autoscroll, Bias, ClipboardSelection, DisplayPoint, }; use gpui::{actions, MutableAppContext, ViewContext}; -use language::{AutoindentMode, Point, SelectionGoal}; +use language::{AutoindentMode, SelectionGoal}; +use rope::point::Point; use workspace::Workspace; use self::{ diff --git a/crates/vim/src/test/neovim_backed_test_context.rs b/crates/vim/src/test/neovim_backed_test_context.rs index bb8ba26b74..bdac8fe158 100644 --- a/crates/vim/src/test/neovim_backed_test_context.rs +++ b/crates/vim/src/test/neovim_backed_test_context.rs @@ -51,7 +51,7 @@ impl<'a> NeovimBackedTestContext<'a> { pub async fn set_shared_state(&mut self, marked_text: &str) -> ContextHandle { let context_handle = self.set_state(marked_text, Mode::Normal); - let selection = self.editor(|editor, cx| editor.selections.newest::(cx)); + let selection = self.editor(|editor, cx| editor.selections.newest::(cx)); let text = self.buffer_text(); self.neovim.set_state(selection, &text).await; diff --git a/crates/vim/src/test/neovim_connection.rs b/crates/vim/src/test/neovim_connection.rs index ff4e10cfe5..60ac345323 100644 --- a/crates/vim/src/test/neovim_connection.rs +++ b/crates/vim/src/test/neovim_connection.rs @@ -8,7 +8,10 @@ use async_compat::Compat; use async_trait::async_trait; #[cfg(feature = "neovim")] use gpui::keymap::Keystroke; -use language::{Point, Selection}; + +use language::Selection; +use rope::point::Point; + #[cfg(feature = "neovim")] use lazy_static::lazy_static; #[cfg(feature = "neovim")] diff --git a/crates/workspace/Cargo.toml b/crates/workspace/Cargo.toml index 2fd43b7bcb..54e7eaf463 100644 --- a/crates/workspace/Cargo.toml +++ b/crates/workspace/Cargo.toml @@ -12,7 +12,9 @@ test-support = [ "call/test-support", "client/test-support", "project/test-support", - "settings/test-support" + "settings/test-support", + "gpui/test-support", + "fs/test-support" ] [dependencies] @@ -21,6 +23,7 @@ client = { path = "../client" } collections = { path = "../collections" } context_menu = { path = "../context_menu" } drag_and_drop = { path = "../drag_and_drop" } +fs = { path = "../fs" } gpui = { path = "../gpui" } language = { path = "../language" } menu = { path = "../menu" } @@ -42,4 +45,5 @@ call = { path = "../call", features = ["test-support"] } client = { path = "../client", features = ["test-support"] } gpui = { path = "../gpui", features = ["test-support"] } project = { path = "../project", features = ["test-support"] } -settings = { path = "../settings", features = ["test-support"] } \ No newline at end of file +settings = { path = "../settings", features = ["test-support"] } +fs = { path = "../fs", features = ["test-support"] } \ No newline at end of file diff --git a/crates/workspace/src/dock.rs b/crates/workspace/src/dock.rs index 7e626c60a9..30607afdff 100644 --- a/crates/workspace/src/dock.rs +++ b/crates/workspace/src/dock.rs @@ -35,16 +35,23 @@ pub fn init(cx: &mut MutableAppContext) { cx.add_action(Dock::move_dock); cx.add_action( |workspace: &mut Workspace, _: &AnchorDockRight, cx: &mut ViewContext| { + settings::settings_file::write_setting("default_dock_anchor", "right".to_string(), cx); Dock::move_dock(workspace, &MoveDock(DockAnchor::Right), cx) }, ); cx.add_action( |workspace: &mut Workspace, _: &AnchorDockBottom, cx: &mut ViewContext| { + settings::settings_file::write_setting("default_dock_anchor", "bottom".to_string(), cx); Dock::move_dock(workspace, &MoveDock(DockAnchor::Bottom), cx) }, ); cx.add_action( |workspace: &mut Workspace, _: &ExpandDock, cx: &mut ViewContext| { + settings::settings_file::write_setting( + "default_dock_anchor", + "expanded".to_string(), + cx, + ); Dock::move_dock(workspace, &MoveDock(DockAnchor::Expanded), cx) }, ); diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 705823003f..9a6bc9e6ac 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -17,6 +17,7 @@ use client::{proto, Client, PeerId, TypedEnvelope, UserStore}; use collections::{hash_map, HashMap, HashSet}; use dock::{DefaultItemFactory, Dock, ToggleDockButton}; use drag_and_drop::DragAndDrop; +use fs::{self, Fs}; use futures::{channel::oneshot, FutureExt, StreamExt}; use gpui::{ actions, @@ -32,7 +33,7 @@ use log::{error, warn}; pub use pane::*; pub use pane_group::*; use postage::prelude::Stream; -use project::{fs, Fs, Project, ProjectEntryId, ProjectPath, ProjectStore, Worktree, WorktreeId}; +use project::{Project, ProjectEntryId, ProjectPath, ProjectStore, Worktree, WorktreeId}; use searchable::SearchableItemHandle; use serde::Deserialize; use settings::{Autosave, DockAnchor, Settings}; @@ -930,7 +931,7 @@ impl AppState { let settings = Settings::test(cx); cx.set_global(settings); - let fs = project::FakeFs::new(cx.background().clone()); + let fs = fs::FakeFs::new(cx.background().clone()); let languages = Arc::new(LanguageRegistry::test()); let http_client = client::test::FakeHttpClient::with_404_response(); let client = Client::new(http_client.clone(), cx); @@ -2805,8 +2806,9 @@ mod tests { use crate::sidebar::SidebarItem; use super::*; + use fs::FakeFs; use gpui::{executor::Deterministic, ModelHandle, TestAppContext, ViewContext}; - use project::{FakeFs, Project, ProjectEntryId}; + use project::{Project, ProjectEntryId}; use serde_json::json; pub fn default_item_factory( diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index d0b41b08f1..6c92dd9bef 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -32,6 +32,7 @@ diagnostics = { path = "../diagnostics" } editor = { path = "../editor" } file_finder = { path = "../file_finder" } search = { path = "../search" } +fs = { path = "../fs" } fsevent = { path = "../fsevent" } fuzzy = { path = "../fuzzy" } go_to_line = { path = "../go_to_line" } diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index f48f8b723e..1c6a818ef3 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -14,7 +14,6 @@ use client::{ http::{self, HttpClient}, UserStore, ZED_SECRET_CLIENT_TOKEN, }; -use fs::OpenOptions; use futures::{ channel::{mpsc, oneshot}, FutureExt, SinkExt, StreamExt, @@ -26,20 +25,21 @@ use log::LevelFilter; use parking_lot::Mutex; use project::{Fs, ProjectStore}; use serde_json::json; -use settings::{self, KeymapFileContent, Settings, SettingsFileContent, WorkingDirectory}; +use settings::{ + self, settings_file::SettingsFile, KeymapFileContent, Settings, SettingsFileContent, + WorkingDirectory, +}; use smol::process::Command; -use std::{env, ffi::OsStr, fs, panic, path::PathBuf, sync::Arc, thread, time::Duration}; +use std::fs::OpenOptions; +use std::{env, ffi::OsStr, panic, path::PathBuf, sync::Arc, thread, time::Duration}; use terminal::terminal_container_view::{get_working_directory, TerminalContainer}; +use fs::RealFs; +use settings::settings_file::{watch_keymap_file, watch_settings_file, WatchedJsonFile}; use theme::ThemeRegistry; use util::{ResultExt, TryFutureExt}; use workspace::{self, AppState, ItemHandle, NewFile, OpenPaths, Workspace}; -use zed::{ - self, build_window_options, - fs::RealFs, - initialize_workspace, languages, menus, - settings_file::{watch_keymap_file, watch_settings_file, WatchedJsonFile}, -}; +use zed::{self, build_window_options, initialize_workspace, languages, menus}; fn main() { let http = http::client(); @@ -65,6 +65,7 @@ fn main() { let themes = ThemeRegistry::new(Assets, app.font_cache()); let default_settings = Settings::defaults(Assets, &app.font_cache(), &themes); + let settings_file = SettingsFile::new(&*zed::paths::SETTINGS, fs.clone()); let config_files = load_config_files(&app, fs.clone()); let login_shell_env_loaded = if stdout_is_a_pty() { @@ -97,10 +98,11 @@ fn main() { .spawn(languages::init(languages.clone(), cx.background().clone())); let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http.clone(), cx)); - let (settings_file, keymap_file) = cx.background().block(config_files).unwrap(); + let (settings_file_content, keymap_file) = cx.background().block(config_files).unwrap(); //Setup settings global before binding actions - watch_settings_file(default_settings, settings_file, themes.clone(), cx); + cx.set_global(settings_file); + watch_settings_file(default_settings, settings_file_content, themes.clone(), cx); watch_keymap_file(keymap_file, cx); context_menu::init(cx); @@ -200,23 +202,23 @@ fn main() { } fn init_paths() { - fs::create_dir_all(&*zed::paths::CONFIG_DIR).expect("could not create config path"); - fs::create_dir_all(&*zed::paths::LANGUAGES_DIR).expect("could not create languages path"); - fs::create_dir_all(&*zed::paths::DB_DIR).expect("could not create database path"); - fs::create_dir_all(&*zed::paths::LOGS_DIR).expect("could not create logs path"); + std::fs::create_dir_all(&*zed::paths::CONFIG_DIR).expect("could not create config path"); + std::fs::create_dir_all(&*zed::paths::LANGUAGES_DIR).expect("could not create languages path"); + std::fs::create_dir_all(&*zed::paths::DB_DIR).expect("could not create database path"); + std::fs::create_dir_all(&*zed::paths::LOGS_DIR).expect("could not create logs path"); // Copy setting files from legacy locations. TODO: remove this after a few releases. thread::spawn(|| { - if fs::metadata(&*zed::paths::legacy::SETTINGS).is_ok() - && fs::metadata(&*zed::paths::SETTINGS).is_err() + if std::fs::metadata(&*zed::paths::legacy::SETTINGS).is_ok() + && std::fs::metadata(&*zed::paths::SETTINGS).is_err() { - fs::copy(&*zed::paths::legacy::SETTINGS, &*zed::paths::SETTINGS).log_err(); + std::fs::copy(&*zed::paths::legacy::SETTINGS, &*zed::paths::SETTINGS).log_err(); } - if fs::metadata(&*zed::paths::legacy::KEYMAP).is_ok() - && fs::metadata(&*zed::paths::KEYMAP).is_err() + if std::fs::metadata(&*zed::paths::legacy::KEYMAP).is_ok() + && std::fs::metadata(&*zed::paths::KEYMAP).is_err() { - fs::copy(&*zed::paths::legacy::KEYMAP, &*zed::paths::KEYMAP).log_err(); + std::fs::copy(&*zed::paths::legacy::KEYMAP, &*zed::paths::KEYMAP).log_err(); } }); } @@ -231,9 +233,10 @@ fn init_logger() { const KIB: u64 = 1024; const MIB: u64 = 1024 * KIB; const MAX_LOG_BYTES: u64 = MIB; - if fs::metadata(&*zed::paths::LOG).map_or(false, |metadata| metadata.len() > MAX_LOG_BYTES) + if std::fs::metadata(&*zed::paths::LOG) + .map_or(false, |metadata| metadata.len() > MAX_LOG_BYTES) { - let _ = fs::rename(&*zed::paths::LOG, &*zed::paths::OLD_LOG); + let _ = std::fs::rename(&*zed::paths::LOG, &*zed::paths::OLD_LOG); } let log_file = OpenOptions::new() @@ -289,7 +292,7 @@ fn init_panic_hook(app_version: String, http: Arc, background: A .body(body.into())?; let response = http.send(request).await.context("error sending panic")?; if response.status().is_success() { - fs::remove_file(child_path) + std::fs::remove_file(child_path) .context("error removing panic after sending it successfully") .log_err(); } else { @@ -338,7 +341,7 @@ fn init_panic_hook(app_version: String, http: Arc, background: A }; let panic_filename = chrono::Utc::now().format("%Y_%m_%d %H_%M_%S").to_string(); - fs::write( + std::fs::write( zed::paths::LOGS_DIR.join(format!("zed-{}-{}.panic", app_version, panic_filename)), &message, ) @@ -395,7 +398,7 @@ fn stdout_is_a_pty() -> bool { fn collect_path_args() -> Vec { env::args() .skip(1) - .filter_map(|arg| match fs::canonicalize(arg) { + .filter_map(|arg| match std::fs::canonicalize(arg) { Ok(path) => Some(path), Err(error) => { log::error!("error parsing path argument: {}", error); diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index f6f3a34242..9012bc89e2 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -2,7 +2,6 @@ mod feedback; pub mod languages; pub mod menus; pub mod paths; -pub mod settings_file; #[cfg(any(test, feature = "test-support"))] pub mod test; @@ -14,6 +13,7 @@ use collab_ui::CollabTitlebarItem; use collections::VecDeque; pub use editor; use editor::{Editor, MultiBuffer}; + use gpui::{ actions, geometry::vector::vec2f, @@ -23,7 +23,7 @@ use gpui::{ }; use language::Rope; pub use lsp; -pub use project::{self, fs}; +pub use project; use project_panel::ProjectPanel; use search::{BufferSearchBar, ProjectSearchBar}; use serde::Deserialize;