Compare commits

..

1 Commits

Author SHA1 Message Date
Antonio Scandurra
2442bf89f0 WIP: Optimistically produce a frame at the end of an effect cycle
Co-Authored-By: Thorsten Ball <thorsten@zed.dev>
2024-01-31 08:27:51 -08:00
73 changed files with 266 additions and 959 deletions

View File

@@ -81,7 +81,6 @@ jobs:
MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }}
APPLE_NOTARIZATION_USERNAME: ${{ secrets.APPLE_NOTARIZATION_USERNAME }}
APPLE_NOTARIZATION_PASSWORD: ${{ secrets.APPLE_NOTARIZATION_PASSWORD }}
ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
steps:
- name: Install Node
uses: actions/setup-node@v3

View File

@@ -3,53 +3,15 @@ name: Publish Collab Server Image
on:
push:
tags:
- collab-production
- collab-staging
branches:
- test-collab-deploy
- collab-v*
env:
DOCKER_BUILDKIT: 1
DIGITALOCEAN_ACCESS_TOKEN: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}
jobs:
style:
name: Check formatting and Clippy lints
runs-on:
- self-hosted
- test
steps:
- name: Checkout repo
uses: actions/checkout@v4
with:
clean: false
submodules: "recursive"
fetch-depth: 0
- name: Run style checks
uses: ./.github/actions/check_style
tests:
name: Run tests
runs-on:
- self-hosted
- test
needs: style
steps:
- name: Checkout repo
uses: actions/checkout@v4
with:
clean: false
submodules: "recursive"
- name: Run tests
uses: ./.github/actions/run_test
publish:
name: Publish collab server image
needs:
- style
- tests
runs-on:
- self-hosted
- deploy
@@ -67,44 +29,21 @@ jobs:
uses: actions/checkout@v4
with:
clean: false
submodules: "recursive"
submodules: 'recursive'
- name: Build docker image
run: docker build . --tag registry.digitalocean.com/zed/collab:${GITHUB_SHA}
- name: Publish docker image
run: docker push registry.digitalocean.com/zed/collab:${GITHUB_SHA}
deploy:
name: Deploy new server image
needs:
- publish
runs-on:
- self-hosted
- deploy
- name: Sign into Kubernetes
run: doctl kubernetes cluster kubeconfig save --expiry-seconds 600 ${{ secrets.CLUSTER_NAME }}
- name: Determine namepsace
- name: Determine version
run: |
set -eu
if [[ $GITHUB_REF_NAME = "collab-production" ]]; then
echo "Deploying collab:${GITHUB_SHA} to production"
echo "KUBE_NAMESPACE=production" >> $GITHUB_ENV
elif [[ $GITHUB_REF_NAME = "collab-staging" ]]; then
echo "Deploying collab:${GITHUB_SHA} to staging"
echo "KUBE_NAMESPACE=staging" >> $GITHUB_ENV
elif [[ $GITHUB_REF_NAME = "test-collab-deploy" ]]; then
echo "Deploying collab:${GITHUB_SHA} to staging"
echo "KUBE_NAMESPACE=staging" >> $GITHUB_ENV
else
version=$(script/get-crate-version collab)
if [[ $GITHUB_REF_NAME != "collab-v${version}" ]]; then
echo "release tag ${GITHUB_REF_NAME} does not match version ${version}"
exit 1
fi
echo "Publishing collab version: ${version}"
echo "COLLAB_VERSION=${version}" >> $GITHUB_ENV
- name: Start rollout
run: echo kubectl -n "$KUBE_NAMESPACE" set image deployment/collab collab=registry.digitalocean.com/zed/collab:${GITHUB_SHA}
- name: Build docker image
run: docker build . --tag registry.digitalocean.com/zed/collab:v${COLLAB_VERSION}
- name: Wait for rollout to finish
run: kubectl -n "$KUBE_NAMESPACE" rollout status deployment/collab
- name: Publish docker image
run: docker push registry.digitalocean.com/zed/collab:v${COLLAB_VERSION}

View File

@@ -1,6 +1,6 @@
{
"JSON": {
"tab_size": 4
},
"formatter": "auto"
"JSON": {
"tab_size": 4
},
"formatter": "auto"
}

52
Cargo.lock generated
View File

@@ -1367,7 +1367,6 @@ dependencies = [
"image",
"lazy_static",
"log",
"once_cell",
"parking_lot 0.11.2",
"postage",
"rand 0.8.5",
@@ -1378,7 +1377,6 @@ dependencies = [
"serde_derive",
"serde_json",
"settings",
"sha2 0.10.7",
"smol",
"sum_tree",
"sysinfo",
@@ -3257,6 +3255,7 @@ dependencies = [
"serde",
"serde_derive",
"serde_json",
"signpost",
"simplelog",
"slotmap",
"smallvec",
@@ -4095,16 +4094,6 @@ version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4"
[[package]]
name = "libmimalloc-sys"
version = "0.1.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3979b5c37ece694f1f5e51e7ecc871fdb0f517ed04ee45f88d15d6d553cb9664"
dependencies = [
"cc",
"libc",
]
[[package]]
name = "libsqlite3-sys"
version = "0.26.0"
@@ -4434,15 +4423,6 @@ dependencies = [
"objc",
]
[[package]]
name = "mimalloc"
version = "0.1.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa01922b5ea280a911e323e4d2fd24b7fe5cc4042e0d2cda3c40775cdc4bdc9c"
dependencies = [
"libmimalloc-sys",
]
[[package]]
name = "mime"
version = "0.3.17"
@@ -7333,6 +7313,12 @@ dependencies = [
"rand_core 0.6.4",
]
[[package]]
name = "signpost"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acde4ef7ee97ad3bac7c4f73ee22ddb71067aa1d427a22efa76284de48eada41"
[[package]]
name = "simdutf8"
version = "0.1.4"
@@ -8204,7 +8190,6 @@ dependencies = [
"serde",
"serde_derive",
"serde_json",
"serde_json_lenient",
"serde_repr",
"settings",
"story",
@@ -8785,15 +8770,6 @@ dependencies = [
"tree-sitter",
]
[[package]]
name = "tree-sitter-gitcommit"
version = "0.3.3"
source = "git+https://github.com/gbprod/tree-sitter-gitcommit#e8d9eda4e5ea0b08aa39d48dab0f6553058fbe0f"
dependencies = [
"cc",
"tree-sitter",
]
[[package]]
name = "tree-sitter-gleam"
version = "0.34.0"
@@ -8830,15 +8806,6 @@ dependencies = [
"tree-sitter",
]
[[package]]
name = "tree-sitter-gowork"
version = "0.0.1"
source = "git+https://github.com/d1y/tree-sitter-go-work#a2a4b99b53b3740855ff33f0b54cab0bb4ce6f45"
dependencies = [
"cc",
"tree-sitter",
]
[[package]]
name = "tree-sitter-haskell"
version = "0.14.0"
@@ -10263,7 +10230,7 @@ dependencies = [
[[package]]
name = "zed"
version = "0.122.0"
version = "0.121.0"
dependencies = [
"activity_indicator",
"ai",
@@ -10315,7 +10282,6 @@ dependencies = [
"log",
"lsp",
"menu",
"mimalloc",
"node_runtime",
"notifications",
"num_cpus",
@@ -10363,12 +10329,10 @@ dependencies = [
"tree-sitter-elixir",
"tree-sitter-elm",
"tree-sitter-embedded-template",
"tree-sitter-gitcommit",
"tree-sitter-gleam",
"tree-sitter-glsl",
"tree-sitter-go",
"tree-sitter-gomod",
"tree-sitter-gowork",
"tree-sitter-haskell",
"tree-sitter-heex",
"tree-sitter-html",

View File

@@ -120,7 +120,6 @@ schemars = "0.8"
serde = { version = "1.0", features = ["derive", "rc"] }
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
serde_json = { version = "1.0", features = ["preserve_order", "raw_value"] }
serde_json_lenient = { version = "0.1", features = ["preserve_order", "raw_value"] }
serde_repr = "0.1"
smallvec = { version = "1.6", features = ["union"] }
smol = "1.2"
@@ -140,12 +139,10 @@ tree-sitter-css = { git = "https://github.com/tree-sitter/tree-sitter-css", rev
tree-sitter-elixir = { git = "https://github.com/elixir-lang/tree-sitter-elixir", rev = "a2861e88a730287a60c11ea9299c033c7d076e30" }
tree-sitter-elm = { git = "https://github.com/elm-tooling/tree-sitter-elm", rev = "692c50c0b961364c40299e73c1306aecb5d20f40" }
tree-sitter-embedded-template = "0.20.0"
tree-sitter-gitcommit = { git = "https://github.com/gbprod/tree-sitter-gitcommit" }
tree-sitter-gleam = { git = "https://github.com/gleam-lang/tree-sitter-gleam", rev = "58b7cac8fc14c92b0677c542610d8738c373fa81" }
tree-sitter-glsl = { git = "https://github.com/theHamsta/tree-sitter-glsl", rev = "2a56fb7bc8bb03a1892b4741279dd0a8758b7fb3" }
tree-sitter-go = { git = "https://github.com/tree-sitter/tree-sitter-go", rev = "aeb2f33b366fd78d5789ff104956ce23508b85db" }
tree-sitter-gomod = { git = "https://github.com/camdencheek/tree-sitter-go-mod" }
tree-sitter-gowork = { git = "https://github.com/d1y/tree-sitter-go-work" }
tree-sitter-haskell = { git = "https://github.com/tree-sitter/tree-sitter-haskell", rev = "cf98de23e4285b8e6bcb57b050ef2326e2cc284b" }
tree-sitter-heex = { git = "https://github.com/phoenixframework/tree-sitter-heex", rev = "2e1348c3cf2c9323e87c2744796cf3f3868aa82a" }
tree-sitter-html = "0.19.0"

View File

@@ -74,7 +74,7 @@
"ogg": "video",
"pdb": "storage",
"pdf": "document",
"php": "php",
"php": "code",
"png": "image",
"ppt": "document",
"pptx": "document",
@@ -171,9 +171,6 @@
"phoenix": {
"icon": "icons/file_icons/phoenix.svg"
},
"php": {
"icon": "icons/file_icons/php.svg"
},
"prettier": {
"icon": "icons/file_icons/prettier.svg"
},

View File

@@ -1 +0,0 @@
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="512" height="512"><path d="M170.322 349.808c-2.4-15.66-9-28.38-25.020-34.531-6.27-2.4-11.7-6.78-17.88-9.54-7.020-3.15-14.16-6.15-21.57-8.1-5.61-1.5-10.83 1.020-14.16 5.94-3.15 4.62-0.87 8.97 1.77 12.84 2.97 4.35 6.27 8.49 9.6 12.57 5.52 6.78 11.37 13.29 16.74 20.161 5.13 6.57 9.51 13.86 8.76 22.56-1.65 19.080-10.29 34.891-24.21 47.76-1.53 1.38-4.23 2.37-6.21 2.19-8.88-0.96-16.95-4.32-23.46-10.53-7.47-7.11-6.33-15.48 2.61-20.67 2.13-1.23 4.35-2.37 6.3-3.87 5.46-4.11 7.29-11.13 4.32-17.22-1.41-2.94-3-6.12-5.34-8.25-11.43-10.41-22.651-21.151-34.891-30.63-29.671-23.041-44.91-53.52-47.251-90.421-2.64-40.981 6.87-79.231 28.5-114.242 8.19-13.29 17.73-25.951 32.37-32.52 9.96-4.47 20.88-6.99 31.531-9.78 29.311-7.71 58.89-13.5 89.401-8.34 26.28 4.41 45.511 17.94 54.331 43.77 5.79 16.89 7.17 34.35 5.37 52.231-3.54 35.131-29.49 66.541-63.331 75.841-14.67 4.020-22.68 1.77-31.5-10.44-6.33-8.79-11.58-18.36-17.25-27.631-0.84-1.38-1.44-2.97-2.16-4.44-0.69-1.47-1.44-2.88-2.16-4.35 2.13 15.24 5.67 29.911 13.98 42.99 4.5 7.11 10.5 12.36 19.29 13.14 32.34 2.91 59.641-7.71 79.021-33.721 21.69-29.101 26.461-62.581 20.19-97.831-1.23-6.96-3.3-13.77-4.77-20.7-0.99-4.47 0.78-7.77 5.19-9.33 2.040-0.69 4.14-1.26 6.18-1.68 26.461-5.7 53.221-7.59 80.191-4.86 30.601 3.060 59.551 11.46 85.441 28.471 40.531 26.67 65.641 64.621 79.291 110.522 1.98 6.66 2.28 13.95 2.46 20.971 0.12 4.68-2.88 5.91-6.45 2.97-3.93-3.21-7.53-6.87-10.92-10.65-3.15-3.57-5.67-7.65-8.73-11.4-2.37-2.94-4.44-2.49-5.58 1.17-0.72 2.22-1.35 4.41-1.98 6.63-7.080 25.26-18.24 48.3-36.33 67.711-2.52 2.73-4.77 6.78-5.070 10.38-0.78 9.96-1.35 20.13-0.39 30.060 1.98 21.331 5.070 42.57 7.47 63.871 1.35 12.030-2.52 19.11-13.83 23.281-7.95 2.91-16.47 5.040-24.87 5.64-13.38 0.93-26.88 0.27-40.32 0.27-0.36-15 0.93-29.731-13.17-37.771 2.73-11.13 5.88-21.69 7.77-32.49 1.56-8.97 0.24-17.79-6.060-25.14-5.91-6.93-13.32-8.82-20.101-4.86-20.43 11.91-41.671 11.97-63.301 4.17-9.93-3.6-16.86-1.56-22.351 7.5-5.91 9.75-8.4 20.7-7.74 31.771 0.84 13.95 3.27 27.75 5.13 41.64 1.020 7.77 0.15 9.78-7.56 11.76-17.13 4.35-34.56 4.83-52.081 3.42-0.93-0.090-1.86-0.48-2.46-0.63-0.87-14.55 0.66-29.671-16.68-37.411 7.68-16.29 6.63-33.18 3.99-50.070l-0.060-0.15zM66.761 292.718c2.55-2.4 4.59-6.15 5.31-9.6 1.8-8.64-4.68-20.22-12.18-23.43-3.99-1.74-7.47-1.11-10.29 2.070-6.87 7.77-13.65 15.63-20.401 23.521-1.14 1.35-2.16 2.94-2.97 4.53-2.7 5.19-1.11 8.97 4.65 10.38 3.48 0.87 7.080 1.050 10.65 1.56 9.3-0.9 18.3-2.46 25.23-9v-0.030zM67.541 206.347c-0.030-6.18-5.19-11.34-11.28-11.37-6.27-0.030-11.67 5.58-11.46 11.76 0.27 6.21 5.43 11.19 11.61 11.070 6.24-0.090 11.22-5.19 11.16-11.43l-0.030-0.030z"></path></svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -207,9 +207,6 @@
"displayLines": true
}
],
"shift-h": "vim::WindowTop",
"shift-m": "vim::WindowMiddle",
"shift-l": "vim::WindowBottom",
// z commands
"z t": "editor::ScrollCursorTop",
"z z": "editor::ScrollCursorCenter",
@@ -340,6 +337,9 @@
"shift-s": "vim::SubstituteLine",
"> >": "editor::Indent",
"< <": "editor::Outdent",
"shift-h": "vim::WindowTop",
"shift-m": "vim::WindowMiddle",
"shift-l": "vim::WindowBottom",
"ctrl-pagedown": "pane::ActivateNextItem",
"ctrl-pageup": "pane::ActivatePrevItem"
}

View File

@@ -72,17 +72,6 @@
"show_wrap_guides": true,
// Character counts at which to show wrap guides in the editor.
"wrap_guides": [],
// Hide the values of in variables from visual display in private files
"redact_private_values": false,
// Globs to match against file paths to determine if a file is private.
"private_files": [
"**/.env*",
"**/*.pem",
"**/*.key",
"**/*.cert",
"**/*.crt",
"**/secrets.yml"
],
// Whether to use additional LSP queries to format (and amend) the code after
// every "trigger" symbol input, defined by LSP server capabilities.
"use_on_type_format": true,

View File

@@ -32,7 +32,6 @@ futures.workspace = true
image = "0.23"
lazy_static.workspace = true
log.workspace = true
once_cell = "1.19.0"
parking_lot.workspace = true
postage.workspace = true
rand.workspace = true
@@ -40,7 +39,6 @@ schemars.workspace = true
serde.workspace = true
serde_derive.workspace = true
serde_json.workspace = true
sha2 = "0.10"
smol.workspace = true
sysinfo.workspace = true
tempfile.workspace = true

View File

@@ -4,19 +4,16 @@ use crate::TelemetrySettings;
use chrono::{DateTime, Utc};
use futures::Future;
use gpui::{AppContext, AppMetadata, BackgroundExecutor, Task};
use once_cell::sync::Lazy;
use parking_lot::Mutex;
use release_channel::ReleaseChannel;
use serde::Serialize;
use settings::{Settings, SettingsStore};
use sha2::{Digest, Sha256};
use std::io::Write;
use std::{env, mem, path::PathBuf, sync::Arc, time::Duration};
use std::{env, io::Write, mem, path::PathBuf, sync::Arc, time::Duration};
use sysinfo::{
CpuRefreshKind, Pid, PidExt, ProcessExt, ProcessRefreshKind, RefreshKind, System, SystemExt,
};
use tempfile::NamedTempFile;
use util::http::{self, HttpClient, Method, ZedHttpClient};
use util::http::{HttpClient, ZedHttpClient};
#[cfg(not(debug_assertions))]
use util::ResultExt;
use util::TryFutureExt;
@@ -145,13 +142,6 @@ const FLUSH_INTERVAL: Duration = Duration::from_secs(1);
#[cfg(not(debug_assertions))]
const FLUSH_INTERVAL: Duration = Duration::from_secs(60 * 5);
static ZED_CLIENT_CHECKSUM_SEED: Lazy<Vec<u8>> = Lazy::new(|| {
option_env!("ZED_CLIENT_CHECKSUM_SEED")
.unwrap_or("development-checksum-seed")
.as_bytes()
.into()
});
impl Telemetry {
pub fn new(client: Arc<ZedHttpClient>, cx: &mut AppContext) -> Arc<Self> {
let release_channel =
@@ -550,27 +540,9 @@ impl Telemetry {
serde_json::to_writer(&mut json_bytes, &request_body)?;
}
let mut summer = Sha256::new();
summer.update(&*ZED_CLIENT_CHECKSUM_SEED);
summer.update(&json_bytes);
summer.update(&*ZED_CLIENT_CHECKSUM_SEED);
let mut checksum = String::new();
for byte in summer.finalize().as_slice() {
use std::fmt::Write;
write!(&mut checksum, "{:02x}", byte).unwrap();
}
let request = http::Request::builder()
.method(Method::POST)
.uri(&this.http_client.zed_url("/api/events"))
.header("Content-Type", "text/plain")
.header("x-zed-checksum", checksum)
.body(json_bytes.into());
let response = this.http_client.send(request?).await?;
if response.status() != 200 {
log::error!("Failed to send events: HTTP {:?}", response.status());
}
this.http_client
.post_json(&this.http_client.zed_url("/api/events"), json_bytes.into())
.await?;
anyhow::Ok(())
}
.log_err(),

View File

@@ -28,9 +28,6 @@ async fn main() -> Result<()> {
Some("version") => {
println!("collab v{VERSION}");
}
Some("migrate") => {
run_migrations().await?;
}
Some("serve") => {
let config = envy::from_env::<Config>().expect("error loading config");
init_tracing(&config);

View File

@@ -137,7 +137,7 @@ impl Clone for Command {
/// Hit count for each command in the palette.
/// We only account for commands triggered directly via command palette and not by e.g. keystrokes because
/// if a user already knows a keystroke for a command, they are unlikely to use a command palette to look for it.
/// if an user already knows a keystroke for a command, they are unlikely to use a command palette to look for it.
#[derive(Default)]
struct HitCounts(HashMap<String, usize>);

View File

@@ -1251,10 +1251,6 @@ mod tests {
fn worktree_id(&self) -> usize {
0
}
fn is_private(&self) -> bool {
false
}
}
impl language::LocalFile for File {

View File

@@ -225,9 +225,8 @@ impl CopilotButton {
let file = snapshot.file_at(suggestion_anchor).cloned();
self.editor_enabled = Some(
file.as_ref().map(|file| !file.is_private()).unwrap_or(true)
&& all_language_settings(self.file.as_ref(), cx)
.copilot_enabled(language, file.as_ref().map(|file| file.path().as_ref())),
all_language_settings(self.file.as_ref(), cx)
.copilot_enabled(language, file.as_ref().map(|file| file.path().as_ref())),
);
self.language = language.cloned();
self.file = file;

View File

@@ -2310,7 +2310,7 @@ impl Editor {
let mut bracket_pair = None;
let mut is_bracket_pair_start = false;
if !text.is_empty() {
// `text` can be empty when a user is using IME (e.g. Chinese Wubi Simplified)
// `text` can be empty when an user is using IME (e.g. Chinese Wubi Simplified)
// and they are removing the character that triggered IME popup.
for (pair, enabled) in scope.brackets() {
if enabled && pair.close && pair.start.ends_with(text.as_ref()) {
@@ -8493,31 +8493,6 @@ impl Editor {
results
}
/// Get the text ranges corresponding to the redaction query
pub fn redacted_ranges(
&self,
search_range: Range<Anchor>,
display_snapshot: &DisplaySnapshot,
cx: &mut ViewContext<Self>,
) -> Vec<Range<DisplayPoint>> {
display_snapshot
.buffer_snapshot
.redacted_ranges(search_range, |file| {
if let Some(file) = file {
file.is_private()
&& EditorSettings::get(Some((file.worktree_id(), file.path())), cx)
.redact_private_values
} else {
false
}
})
.map(|range| {
range.start.to_display_point(display_snapshot)
..range.end.to_display_point(display_snapshot)
})
.collect()
}
pub fn highlight_text<T: 'static>(
&mut self,
ranges: Vec<Range<Anchor>>,

View File

@@ -13,7 +13,6 @@ pub struct EditorSettings {
pub scrollbar: Scrollbar,
pub relative_line_numbers: bool,
pub seed_search_query_from_cursor: SeedQuerySetting,
pub redact_private_values: bool,
}
/// When to populate a new search's query based on the text under the cursor.
@@ -94,13 +93,6 @@ pub struct EditorSettingsContent {
///
/// Default: always
pub seed_search_query_from_cursor: Option<SeedQuerySetting>,
/// Hide the values of variables in `private` files, as defined by the
/// private_files setting. This only changes the visual representation,
/// the values are still present in the file and can be selected / copied / pasted
///
/// Default: false
pub redact_private_values: Option<bool>,
}
/// Scrollbar related settings

View File

@@ -1153,9 +1153,7 @@ impl EditorElement {
)
}
cx.with_z_index(0, |cx| self.paint_redactions(text_bounds, &layout, cx));
cx.with_z_index(1, |cx| {
cx.with_z_index(0, |cx| {
for cursor in cursors {
cursor.paint(content_origin, cx);
}
@@ -1164,32 +1162,6 @@ impl EditorElement {
)
}
fn paint_redactions(
&mut self,
text_bounds: Bounds<Pixels>,
layout: &LayoutState,
cx: &mut ElementContext,
) {
let content_origin = text_bounds.origin + point(layout.gutter_margin, Pixels::ZERO);
let line_end_overshoot = layout.line_end_overshoot();
// A softer than perfect black
let redaction_color = gpui::rgb(0x0e1111);
for range in layout.redacted_ranges.iter() {
self.paint_highlighted_range(
range.clone(),
redaction_color.into(),
Pixels::ZERO,
line_end_overshoot,
layout,
content_origin,
text_bounds,
cx,
);
}
}
fn paint_overlays(
&mut self,
text_bounds: Bounds<Pixels>,
@@ -1985,8 +1957,6 @@ impl EditorElement {
cx.theme().colors(),
);
let redacted_ranges = editor.redacted_ranges(start_anchor..end_anchor, &snapshot.display_snapshot, cx);
let mut newest_selection_head = None;
if editor.show_local_selections {
@@ -2328,7 +2298,6 @@ impl EditorElement {
active_rows,
highlighted_rows,
highlighted_ranges,
redacted_ranges,
line_numbers,
display_hunks,
blocks,
@@ -3113,7 +3082,6 @@ pub struct LayoutState {
display_hunks: Vec<DisplayDiffHunk>,
blocks: Vec<BlockLayout>,
highlighted_ranges: Vec<(Range<DisplayPoint>, Hsla)>,
redacted_ranges: Vec<Range<DisplayPoint>>,
selections: Vec<(PlayerColor, Vec<SelectionLayout>)>,
scrollbar_row_range: Range<f32>,
show_scrollbars: bool,
@@ -3127,12 +3095,6 @@ pub struct LayoutState {
space_invisible: ShapedLine,
}
impl LayoutState {
fn line_end_overshoot(&self) -> Pixels {
0.15 * self.position_map.line_height
}
}
struct CodeActionsIndicator {
row: u32,
button: IconButton,

View File

@@ -73,16 +73,18 @@ impl FollowableItem for Editor {
.iter()
.map(|excerpt| excerpt.buffer_id)
.collect::<HashSet<_>>();
let buffers = project.update(cx, |project, cx| {
buffer_ids
.iter()
.map(|id| BufferId::new(*id).map(|id| project.open_buffer_by_id(id, cx)))
.collect::<Result<Vec<_>>>()
});
let buffers = project
.update(cx, |project, cx| {
buffer_ids
.iter()
.map(|id| BufferId::new(*id).map(|id| project.open_buffer_by_id(id, cx)))
.collect::<Result<Vec<_>>>()
})
.ok()?;
let pane = pane.downgrade();
Some(cx.spawn(|mut cx| async move {
let mut buffers = futures::future::try_join_all(buffers?)
let mut buffers = futures::future::try_join_all(buffers)
.await
.debug_assert_ok("leaders don't share views for unshared buffers")?;
let editor = pane.update(&mut cx, |pane, cx| {
@@ -185,14 +187,6 @@ impl FollowableItem for Editor {
fn to_state_proto(&self, cx: &WindowContext) -> Option<proto::view::Variant> {
let buffer = self.buffer.read(cx);
if buffer
.as_singleton()
.and_then(|buffer| buffer.read(cx).file())
.map_or(false, |file| file.is_private())
{
return None;
}
let scroll_anchor = self.scroll_manager.anchor();
let excerpts = buffer
.read(cx)
@@ -1372,9 +1366,5 @@ mod tests {
fn to_proto(&self) -> rpc::proto::File {
unimplemented!()
}
fn is_private(&self) -> bool {
false
}
}
}

View File

@@ -666,7 +666,6 @@ impl PickerDelegate for FileFinderDelegate {
raw_query: String,
cx: &mut ViewContext<Picker<Self>>,
) -> Task<()> {
let raw_query = raw_query.replace(" ", "");
let raw_query = raw_query.trim();
if raw_query.is_empty() {
let project = self.project.read(cx);

View File

@@ -53,7 +53,6 @@ async fn test_matching_paths(cx: &mut TestAppContext) {
" bandana ",
" ndan ",
" band ",
"a bandana",
] {
picker
.update(cx, |picker, cx| {

View File

@@ -8,14 +8,7 @@ publish = false
license = "Apache-2.0"
[features]
test-support = [
"backtrace",
"dhat",
"env_logger",
"collections/test-support",
"util/test-support",
]
runtime_shaders = []
test-support = ["backtrace", "dhat", "env_logger", "collections/test-support", "util/test-support"]
[lib]
path = "src/gpui.rs"
@@ -54,6 +47,7 @@ seahash = "4.1"
serde.workspace = true
serde_derive.workspace = true
serde_json.workspace = true
signpost = "0.1"
slotmap = "1.0.6"
smallvec.workspace = true
smol.workspace = true

View File

@@ -1,6 +1,7 @@
use std::{
env,
path::{Path, PathBuf},
process::{self, Command},
};
use cbindgen::Config;
@@ -8,9 +9,6 @@ use cbindgen::Config;
fn main() {
generate_dispatch_bindings();
let header_path = generate_shader_bindings();
#[cfg(feature = "runtime_shaders")]
emit_stitched_shaders(&header_path);
#[cfg(not(feature = "runtime_shaders"))]
compile_metal_shaders(&header_path);
}
@@ -97,30 +95,11 @@ fn generate_shader_bindings() -> PathBuf {
output_path
}
/// To enable runtime compilation, we need to "stitch" the shaders file with the generated header
/// so that it is self-contained.
#[cfg(feature = "runtime_shaders")]
fn emit_stitched_shaders(header_path: &Path) {
use std::str::FromStr;
fn stitch_header(header: &Path, shader_path: &Path) -> std::io::Result<PathBuf> {
let header_contents = std::fs::read_to_string(header)?;
let shader_contents = std::fs::read_to_string(shader_path)?;
let stitched_contents = format!("{header_contents}\n{shader_contents}");
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()).join("stitched_shaders.metal");
let _ = std::fs::write(&out_path, stitched_contents)?;
Ok(out_path)
}
let shader_source_path = "./src/platform/mac/shaders.metal";
let shader_path = PathBuf::from_str(shader_source_path).unwrap();
stitch_header(header_path, &shader_path).unwrap();
println!("cargo:rerun-if-changed={}", &shader_source_path);
}
#[cfg(not(feature = "runtime_shaders"))]
fn compile_metal_shaders(header_path: &Path) {
use std::process::{self, Command};
let shader_path = "./src/platform/mac/shaders.metal";
let air_output_path = PathBuf::from(env::var("OUT_DIR").unwrap()).join("shaders.air");
let metallib_output_path = PathBuf::from(env::var("OUT_DIR").unwrap()).join("shaders.metallib");
println!("cargo:rerun-if-changed={}", shader_path);
let output = Command::new("xcrun")

View File

@@ -652,25 +652,19 @@ impl AppContext {
}
}
} else {
for window in self.windows.values() {
if let Some(window) = window.as_ref() {
if window.dirty {
window.platform_window.invalidate();
}
}
}
#[cfg(any(test, feature = "test-support"))]
for window in self
.windows
.values()
.filter_map(|window| {
let window = window.as_ref()?;
(window.dirty || window.focus_invalidated).then_some(window.handle)
window.dirty.then_some(window.handle)
})
.collect::<Vec<_>>()
{
self.update_window(window, |_, cx| cx.draw()).unwrap();
self.update_window(window, |_, cx| {
cx.draw();
})
.unwrap();
}
if self.pending_effects.is_empty() {

View File

@@ -17,11 +17,7 @@ use objc::{self, msg_send, sel, sel_impl};
use smallvec::SmallVec;
use std::{ffi::c_void, mem, ptr, sync::Arc};
#[cfg(not(feature = "runtime_shaders"))]
const SHADERS_METALLIB: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/shaders.metallib"));
#[cfg(feature = "runtime_shaders")]
const SHADERS_SOURCE_FILE: &'static str =
include_str!(concat!(env!("OUT_DIR"), "/stitched_shaders.metal"));
const INSTANCE_BUFFER_SIZE: usize = 32 * 1024 * 1024; // This is an arbitrary decision. There's probably a more optimal value (maybe even we could adjust dynamically...)
pub(crate) struct MetalRenderer {
@@ -64,11 +60,7 @@ impl MetalRenderer {
| AutoresizingMask::HEIGHT_SIZABLE
];
}
#[cfg(feature = "runtime_shaders")]
let library = device
.new_library_with_source(&SHADERS_SOURCE_FILE, &metal::CompileOptions::new())
.expect("error building metal library");
#[cfg(not(feature = "runtime_shaders"))]
let library = device
.new_library_with_data(SHADERS_METALLIB)
.expect("error building metal library");

View File

@@ -341,8 +341,16 @@ impl Window {
platform_window.on_request_frame(Box::new({
let mut cx = cx.to_async();
move || {
measure("frame duration", || {
handle.update(&mut cx, |_, cx| cx.draw()).log_err();
signpost::trace_function(42, &[0; 4], || {
measure("frame duration", || {
handle
.update(&mut cx, |_, cx| {
cx.window
.platform_window
.draw(&cx.window.rendered_frame.scene);
})
.log_err();
})
})
}
}));
@@ -380,10 +388,12 @@ impl Window {
platform_window.on_input({
let mut cx = cx.to_async();
Box::new(move |event| {
handle
.update(&mut cx, |_, cx| cx.dispatch_event(event))
.log_err()
.unwrap_or(false)
signpost::trace_function(41, &[0; 4], || {
handle
.update(&mut cx, |_, cx| cx.dispatch_event(event))
.log_err()
.unwrap_or(false)
})
})
});
@@ -1071,9 +1081,7 @@ impl<'a> WindowContext<'a> {
.retain(&(), |listener| listener(&event, self));
}
self.window
.platform_window
.draw(&self.window.rendered_frame.scene);
self.window.platform_window.invalidate();
self.window.refreshing = false;
self.window.drawing = false;
}

View File

@@ -383,9 +383,6 @@ pub trait File: Send + Sync {
/// Converts this file into a protobuf message.
fn to_proto(&self) -> rpc::proto::File;
/// Return whether Zed considers this to be a private file.
fn is_private(&self) -> bool;
}
/// The file associated with a buffer, in the case where the file is on the local disk.
@@ -406,11 +403,6 @@ pub trait LocalFile: File {
mtime: SystemTime,
cx: &mut AppContext,
);
/// Returns true if the file should not be shared with collaborators.
fn is_private(&self, _: &AppContext) -> bool {
false
}
}
/// The auto-indent behavior associated with an editing operation.
@@ -2885,43 +2877,6 @@ impl BufferSnapshot {
})
}
/// Returns anchor ranges for any matches of the redaction query.
/// The buffer can be associated with multiple languages, and the redaction query associated with each
/// will be run on the relevant section of the buffer.
pub fn redacted_ranges<'a, T: ToOffset>(
&'a self,
range: Range<T>,
) -> impl Iterator<Item = Range<usize>> + 'a {
let offset_range = range.start.to_offset(self)..range.end.to_offset(self);
let mut syntax_matches = self.syntax.matches(offset_range, self, |grammar| {
grammar
.redactions_config
.as_ref()
.map(|config| &config.query)
});
let configs = syntax_matches
.grammars()
.iter()
.map(|grammar| grammar.redactions_config.as_ref())
.collect::<Vec<_>>();
iter::from_fn(move || {
let redacted_range = syntax_matches
.peek()
.and_then(|mat| {
configs[mat.grammar_index].and_then(|config| {
mat.captures
.iter()
.find(|capture| capture.index == config.redaction_capture_ix)
})
})
.map(|mat| mat.node.byte_range());
syntax_matches.advance();
redacted_range
})
}
/// Returns selections for remote peers intersecting the given range.
#[allow(clippy::type_complexity)]
pub fn remote_selections_in_range(

View File

@@ -453,7 +453,6 @@ pub struct LanguageQueries {
pub embedding: Option<Cow<'static, str>>,
pub injections: Option<Cow<'static, str>>,
pub overrides: Option<Cow<'static, str>>,
pub redactions: Option<Cow<'static, str>>,
}
/// Represents a language for the given range. Some languages (e.g. HTML)
@@ -624,7 +623,6 @@ pub struct Grammar {
pub(crate) error_query: Query,
pub(crate) highlights_query: Option<Query>,
pub(crate) brackets_config: Option<BracketConfig>,
pub(crate) redactions_config: Option<RedactionConfig>,
pub(crate) indents_config: Option<IndentConfig>,
pub outline_config: Option<OutlineConfig>,
pub embedding_config: Option<EmbeddingConfig>,
@@ -666,11 +664,6 @@ struct InjectionConfig {
patterns: Vec<InjectionPatternConfig>,
}
struct RedactionConfig {
pub query: Query,
pub redaction_capture_ix: u32,
}
struct OverrideConfig {
query: Query,
values: HashMap<u32, (String, LanguageConfigOverride)>,
@@ -1310,7 +1303,6 @@ impl Language {
indents_config: None,
injection_config: None,
override_config: None,
redactions_config: None,
error_query: Query::new(&ts_language, "(ERROR) @error").unwrap(),
ts_language,
highlight_map: Default::default(),
@@ -1367,11 +1359,6 @@ impl Language {
.with_override_query(query.as_ref())
.context("Error loading override query")?;
}
if let Some(query) = queries.redactions {
self = self
.with_redaction_query(query.as_ref())
.context("Error loading redaction query")?;
}
Ok(self)
}
@@ -1602,22 +1589,6 @@ impl Language {
Ok(self)
}
pub fn with_redaction_query(mut self, source: &str) -> anyhow::Result<Self> {
let grammar = self.grammar_mut();
let query = Query::new(&grammar.ts_language, source)?;
let mut redaction_capture_ix = None;
get_capture_indices(&query, &mut [("redact", &mut redaction_capture_ix)]);
if let Some(redaction_capture_ix) = redaction_capture_ix {
grammar.redactions_config = Some(RedactionConfig {
query,
redaction_capture_ix,
});
}
Ok(self)
}
fn grammar_mut(&mut self) -> &mut Grammar {
Arc::get_mut(self.grammar.as_mut().unwrap()).unwrap()
}

View File

@@ -1059,7 +1059,7 @@ impl<'a> SyntaxMapMatches<'a> {
.position(|later_layer| key < later_layer.sort_key())
.unwrap_or(self.active_layer_count - 1);
self.layers[0..i].rotate_left(1);
} else if self.active_layer_count != 0 {
} else {
self.layers[0..self.active_layer_count].rotate_left(1);
self.active_layer_count -= 1;
}

View File

@@ -36,7 +36,6 @@ use text::{
BufferId, Edit, TextSummary,
};
use theme::SyntaxTheme;
use util::post_inc;
#[cfg(any(test, feature = "test-support"))]
@@ -2785,26 +2784,6 @@ impl MultiBufferSnapshot {
.map(|excerpt| (excerpt.id, &excerpt.buffer, excerpt.range.clone()))
}
fn excerpts_for_range<'a, T: ToOffset>(
&'a self,
range: Range<T>,
) -> impl Iterator<Item = (&'a Excerpt, usize)> + 'a {
let range = range.start.to_offset(self)..range.end.to_offset(self);
let mut cursor = self.excerpts.cursor::<usize>();
cursor.seek(&range.start, Bias::Right, &());
cursor.prev(&());
iter::from_fn(move || {
cursor.next(&());
if cursor.start() < &range.end {
cursor.item().map(|item| (item, *cursor.start()))
} else {
None
}
})
}
pub fn excerpt_boundaries_in_range<R, T>(
&self,
range: R,
@@ -2963,37 +2942,6 @@ impl MultiBufferSnapshot {
})
}
pub fn redacted_ranges<'a, T: ToOffset>(
&'a self,
range: Range<T>,
redaction_enabled: impl Fn(Option<&Arc<dyn File>>) -> bool + 'a,
) -> impl Iterator<Item = Range<usize>> + 'a {
let range = range.start.to_offset(self)..range.end.to_offset(self);
self.excerpts_for_range(range.clone())
.filter_map(move |(excerpt, excerpt_offset)| {
redaction_enabled(excerpt.buffer.file()).then(move || {
let excerpt_buffer_start =
excerpt.range.context.start.to_offset(&excerpt.buffer);
excerpt
.buffer
.redacted_ranges(excerpt.range.context.clone())
.map(move |mut redacted_range| {
// Re-base onto the excerpts coordinates in the multibuffer
redacted_range.start =
excerpt_offset + (redacted_range.start - excerpt_buffer_start);
redacted_range.end =
excerpt_offset + (redacted_range.end - excerpt_buffer_start);
redacted_range
})
.skip_while(move |redacted_range| redacted_range.end < range.start)
.take_while(move |redacted_range| redacted_range.start < range.end)
})
})
.flatten()
}
pub fn diagnostics_update_count(&self) -> usize {
self.diagnostics_update_count
}

View File

@@ -56,7 +56,6 @@ use postage::watch;
use prettier_support::{DefaultPrettier, PrettierInstance};
use project_settings::{LspSettings, ProjectSettings};
use rand::prelude::*;
use rpc::{ErrorCode, ErrorExt};
use search::SearchQuery;
use serde::Serialize;
use settings::{Settings, SettingsStore};
@@ -1761,7 +1760,7 @@ impl Project {
cx.background_executor().spawn(async move {
wait_for_loading_buffer(loading_watch)
.await
.map_err(|e| e.cloned())
.map_err(|error| anyhow!("{project_path:?} opening failure: {error:#}"))
})
}
@@ -6471,7 +6470,6 @@ impl Project {
path: entry.path.clone(),
worktree: worktree_handle.clone(),
is_deleted: false,
is_private: entry.is_private,
}
} else if let Some(entry) = snapshot.entry_for_path(old_file.path().as_ref()) {
File {
@@ -6481,7 +6479,6 @@ impl Project {
path: entry.path.clone(),
worktree: worktree_handle.clone(),
is_deleted: false,
is_private: entry.is_private,
}
} else {
File {
@@ -6491,7 +6488,6 @@ impl Project {
mtime: old_file.mtime(),
worktree: worktree_handle.clone(),
is_deleted: true,
is_private: old_file.is_private,
}
};
@@ -8012,20 +8008,11 @@ impl Project {
.update(&mut cx, |this, cx| this.open_buffer_for_symbol(&symbol, cx))?
.await?;
this.update(&mut cx, |this, cx| {
let is_private = buffer
.read(cx)
.file()
.map(|f| f.is_private())
.unwrap_or_default();
if is_private {
Err(anyhow!(ErrorCode::UnsharedItem))
} else {
Ok(proto::OpenBufferForSymbolResponse {
buffer_id: this.create_buffer_for_peer(&buffer, peer_id, cx).into(),
})
}
})?
Ok(proto::OpenBufferForSymbolResponse {
buffer_id: this.update(&mut cx, |this, cx| {
this.create_buffer_for_peer(&buffer, peer_id, cx).into()
})?,
})
}
fn symbol_signature(&self, project_path: &ProjectPath) -> [u8; 32] {
@@ -8047,7 +8034,11 @@ impl Project {
let buffer = this
.update(&mut cx, |this, cx| this.open_buffer_by_id(buffer_id, cx))?
.await?;
Project::respond_to_open_buffer_request(this, buffer, peer_id, &mut cx)
this.update(&mut cx, |this, cx| {
Ok(proto::OpenBufferResponse {
buffer_id: this.create_buffer_for_peer(&buffer, peer_id, cx).into(),
})
})?
}
async fn handle_open_buffer_by_path(
@@ -8069,28 +8060,10 @@ impl Project {
})?;
let buffer = open_buffer.await?;
Project::respond_to_open_buffer_request(this, buffer, peer_id, &mut cx)
}
fn respond_to_open_buffer_request(
this: Model<Self>,
buffer: Model<Buffer>,
peer_id: proto::PeerId,
cx: &mut AsyncAppContext,
) -> Result<proto::OpenBufferResponse> {
this.update(cx, |this, cx| {
let is_private = buffer
.read(cx)
.file()
.map(|f| f.is_private())
.unwrap_or_default();
if is_private {
Err(anyhow!(ErrorCode::UnsharedItem))
} else {
Ok(proto::OpenBufferResponse {
buffer_id: this.create_buffer_for_peer(&buffer, peer_id, cx).into(),
})
}
this.update(&mut cx, |this, cx| {
Ok(proto::OpenBufferResponse {
buffer_id: this.create_buffer_for_peer(&buffer, peer_id, cx).into(),
})
})?
}

View File

@@ -20,7 +20,6 @@ pub struct ProjectSettings {
/// Configuration for Git-related features
#[serde(default)]
pub git: GitSettings,
/// Completely ignore files matching globs from `file_scan_exclusions`
///
/// Default: [
@@ -35,10 +34,6 @@ pub struct ProjectSettings {
/// ]
#[serde(default)]
pub file_scan_exclusions: Option<Vec<String>>,
/// Treat the files matching these globs as `.env` files.
/// Default: [ "**/.env*" ]
pub private_files: Option<Vec<String>>,
}
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, JsonSchema)]

View File

@@ -230,7 +230,6 @@ pub struct LocalSnapshot {
/// id of their parent directory.
git_repositories: TreeMap<ProjectEntryId, LocalRepositoryEntry>,
file_scan_exclusions: Vec<PathMatcher>,
private_files: Vec<PathMatcher>,
}
struct BackgroundScannerState {
@@ -320,34 +319,16 @@ impl Worktree {
cx.new_model(move |cx: &mut ModelContext<Worktree>| {
cx.observe_global::<SettingsStore>(move |this, cx| {
if let Self::Local(this) = this {
let new_file_scan_exclusions = path_matchers(
ProjectSettings::get_global(cx)
.file_scan_exclusions
.as_deref(),
"file_scan_exclusions",
);
let new_private_files = path_matchers(
ProjectSettings::get(Some((cx.handle().entity_id().as_u64() as usize, &Path::new(""))), cx).private_files.as_deref(),
"private_files",
);
if new_file_scan_exclusions != this.snapshot.file_scan_exclusions
|| new_private_files != this.snapshot.private_files
{
let new_file_scan_exclusions =
file_scan_exclusions(ProjectSettings::get_global(cx));
if new_file_scan_exclusions != this.snapshot.file_scan_exclusions {
this.snapshot.file_scan_exclusions = new_file_scan_exclusions;
this.snapshot.private_files = new_private_files;
log::info!(
"Re-scanning directories, new scan exclude files: {:?}, new dotenv files: {:?}",
"Re-scanning directories, new scan exclude files: {:?}",
this.snapshot
.file_scan_exclusions
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>(),
this.snapshot
.private_files
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
);
@@ -376,16 +357,7 @@ impl Worktree {
.map_or(String::new(), |f| f.to_string_lossy().to_string());
let mut snapshot = LocalSnapshot {
file_scan_exclusions: path_matchers(
ProjectSettings::get_global(cx)
.file_scan_exclusions
.as_deref(),
"file_scan_exclusions",
),
private_files: path_matchers(
ProjectSettings::get(Some((cx.handle().entity_id().as_u64() as usize, &Path::new(""))), cx).private_files.as_deref(),
"private_files",
),
file_scan_exclusions: file_scan_exclusions(ProjectSettings::get_global(cx)),
ignores_by_parent_abs_path: Default::default(),
git_repositories: Default::default(),
snapshot: Snapshot {
@@ -678,22 +650,20 @@ fn start_background_scan_tasks(
vec![background_scanner, scan_state_updater]
}
fn path_matchers(values: Option<&[String]>, context: &'static str) -> Vec<PathMatcher> {
values
.unwrap_or(&[])
.iter()
.sorted()
.filter_map(|pattern| {
PathMatcher::new(pattern)
.map(Some)
.unwrap_or_else(|e| {
log::error!(
"Skipping pattern {pattern} in `{}` project settings due to parsing error: {e:#}", context
);
None
})
})
.collect()
fn file_scan_exclusions(project_settings: &ProjectSettings) -> Vec<PathMatcher> {
project_settings.file_scan_exclusions.as_deref().unwrap_or(&[]).iter()
.sorted()
.filter_map(|pattern| {
PathMatcher::new(pattern)
.map(Some)
.unwrap_or_else(|e| {
log::error!(
"Skipping pattern {pattern} in `file_scan_exclusions` project settings due to parsing error: {e:#}"
);
None
})
})
.collect()
}
impl LocalWorktree {
@@ -1033,7 +1003,6 @@ impl LocalWorktree {
mtime: entry.mtime,
is_local: true,
is_deleted: false,
is_private: entry.is_private,
},
text,
diff_base,
@@ -1048,7 +1017,6 @@ impl LocalWorktree {
.with_context(|| {
format!("Excluded file {abs_path:?} got removed during loading")
})?;
let is_private = snapshot.is_path_private(path.as_ref());
Ok((
File {
entry_id: None,
@@ -1057,7 +1025,6 @@ impl LocalWorktree {
mtime: metadata.mtime,
is_local: true,
is_deleted: false,
is_private,
},
text,
diff_base,
@@ -1086,15 +1053,14 @@ impl LocalWorktree {
let save = self.write_file(path.as_ref(), text, buffer.line_ending(), cx);
let fs = Arc::clone(&self.fs);
let abs_path = self.absolutize(&path);
let is_private = self.snapshot.is_path_private(&path);
cx.spawn(move |this, mut cx| async move {
let entry = save.await?;
let abs_path = abs_path?;
let this = this.upgrade().context("worktree dropped")?;
let (entry_id, mtime, path, is_dotenv) = match entry {
Some(entry) => (Some(entry.id), entry.mtime, entry.path, entry.is_private),
let (entry_id, mtime, path) = match entry {
Some(entry) => (Some(entry.id), entry.mtime, entry.path),
None => {
let metadata = fs
.metadata(&abs_path)
@@ -1107,7 +1073,7 @@ impl LocalWorktree {
.with_context(|| {
format!("Excluded buffer {path:?} got removed during saving")
})?;
(None, metadata.mtime, path, is_private)
(None, metadata.mtime, path)
}
};
@@ -1119,7 +1085,6 @@ impl LocalWorktree {
mtime,
is_local: true,
is_deleted: false,
is_private: is_dotenv,
});
if let Some(project_id) = project_id {
@@ -2330,14 +2295,6 @@ impl LocalSnapshot {
paths
}
pub fn is_path_private(&self, path: &Path) -> bool {
path.ancestors().any(|ancestor| {
self.private_files
.iter()
.any(|exclude_matcher| exclude_matcher.is_match(&ancestor))
})
}
pub fn is_path_excluded(&self, mut path: PathBuf) -> bool {
loop {
if self
@@ -2790,7 +2747,6 @@ pub struct File {
pub(crate) entry_id: Option<ProjectEntryId>,
pub(crate) is_local: bool,
pub(crate) is_deleted: bool,
pub(crate) is_private: bool,
}
impl language::File for File {
@@ -2863,10 +2819,6 @@ impl language::File for File {
is_deleted: self.is_deleted,
}
}
fn is_private(&self) -> bool {
self.is_private
}
}
impl language::LocalFile for File {
@@ -2922,7 +2874,6 @@ impl File {
entry_id: Some(entry.id),
is_local: true,
is_deleted: false,
is_private: entry.is_private,
})
}
@@ -2948,7 +2899,6 @@ impl File {
entry_id: proto.entry_id.map(ProjectEntryId::from_proto),
is_local: false,
is_deleted: proto.is_deleted,
is_private: false,
})
}
@@ -2993,8 +2943,6 @@ pub struct Entry {
/// entries in that they are not included in searches.
pub is_external: bool,
pub git_status: Option<GitFileStatus>,
/// Whether this entry is considered to be a `.env` file.
pub is_private: bool,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
@@ -3049,7 +2997,6 @@ impl Entry {
is_symlink: metadata.is_symlink,
is_ignored: false,
is_external: false,
is_private: false,
git_status: None,
}
}
@@ -3785,7 +3732,7 @@ impl BackgroundScanner {
ancestor_inodes.insert(child_entry.inode);
new_jobs.push(Some(ScanJob {
abs_path: child_abs_path.clone(),
abs_path: child_abs_path,
path: child_path,
is_external: child_entry.is_external,
ignore_stack: if child_entry.is_ignored {
@@ -3819,16 +3766,6 @@ impl BackgroundScanner {
}
}
{
let relative_path = job.path.join(child_name);
let state = self.state.lock();
if state.snapshot.is_path_private(&relative_path) {
log::debug!("detected private file: {relative_path:?}");
child_entry.is_private = true;
}
drop(state)
}
new_entries.push(child_entry);
}
@@ -3929,7 +3866,6 @@ impl BackgroundScanner {
let is_dir = fs_entry.is_dir();
fs_entry.is_ignored = ignore_stack.is_abs_path_ignored(&abs_path, is_dir);
fs_entry.is_external = !canonical_path.starts_with(&root_canonical_path);
fs_entry.is_private = state.snapshot.is_path_private(path);
if !is_dir && !fs_entry.is_ignored && !fs_entry.is_external {
if let Some((work_dir, repo)) = state.snapshot.local_repo_for_path(path) {
@@ -4612,7 +4548,6 @@ impl<'a> TryFrom<(&'a CharBag, proto::Entry)> for Entry {
is_ignored: entry.is_ignored,
is_external: entry.is_external,
git_status: git_status_from_proto(entry.git_status),
is_private: false,
})
} else {
Err(anyhow!(

View File

@@ -31,7 +31,6 @@ theme = { path = "../theme" }
ui = { path = "../ui" }
unicase = "2.6"
util = { path = "../util" }
client = { path = "../client" }
workspace = { path = "../workspace", package = "workspace" }
[dev-dependencies]

View File

@@ -1,6 +1,5 @@
pub mod file_associations;
mod project_panel_settings;
use client::{ErrorCode, ErrorExt};
use settings::Settings;
use db::kvp::KEY_VALUE_STORE;
@@ -36,7 +35,6 @@ use unicase::UniCase;
use util::{maybe, ResultExt, TryFutureExt};
use workspace::{
dock::{DockPosition, Panel, PanelEvent},
notifications::DetachAndPromptErr,
Workspace,
};
@@ -103,7 +101,6 @@ pub struct EntryDetails {
is_processing: bool,
is_cut: bool,
git_status: Option<GitFileStatus>,
is_dotenv: bool,
}
actions!(
@@ -261,7 +258,6 @@ impl ProjectPanel {
} => {
if let Some(worktree) = project.read(cx).worktree_for_entry(entry_id, cx) {
if let Some(entry) = worktree.read(cx).entry_for_id(entry_id) {
let file_path = entry.path.clone();
workspace
.open_path(
ProjectPath {
@@ -272,15 +268,7 @@ impl ProjectPanel {
focus_opened_item,
cx,
)
.detach_and_prompt_err("Failed to open file", cx, move |e, _| {
match e.error_code() {
ErrorCode::UnsharedItem => Some(format!(
"{} is not shared by the host. This could be because it has been marked as `private`",
file_path.display()
)),
_ => None,
}
});
.detach_and_log_err(cx);
if !focus_opened_item {
if let Some(project_panel) = project_panel.upgrade() {
let focus_handle = project_panel.read(cx).focus_handle.clone();
@@ -1149,7 +1137,6 @@ impl ProjectPanel {
is_symlink: false,
is_ignored: false,
is_external: false,
is_private: false,
git_status: entry.git_status,
});
}
@@ -1311,7 +1298,6 @@ impl ProjectPanel {
.clipboard_entry
.map_or(false, |e| e.is_cut() && e.entry_id() == entry.id),
git_status: status,
is_dotenv: entry.is_private,
};
if let Some(edit_state) = &self.edit_state {

View File

@@ -216,7 +216,6 @@ enum ErrorCode {
BadPublicNesting = 9;
CircularNesting = 10;
WrongMoveTarget = 11;
UnsharedItem = 12;
}
message Test {

View File

@@ -80,8 +80,6 @@ pub trait ErrorExt {
fn error_tag(&self, k: &str) -> Option<&str>;
/// to_proto() converts the error into a proto::Error
fn to_proto(&self) -> proto::Error;
///
fn cloned(&self) -> anyhow::Error;
}
impl ErrorExt for anyhow::Error {
@@ -108,14 +106,6 @@ impl ErrorExt for anyhow::Error {
ErrorCode::Internal.message(format!("{}", self)).to_proto()
}
}
fn cloned(&self) -> anyhow::Error {
if let Some(rpc_error) = self.downcast_ref::<RpcError>() {
rpc_error.cloned()
} else {
anyhow::anyhow!("{}", self)
}
}
}
impl From<proto::ErrorCode> for anyhow::Error {
@@ -199,10 +189,6 @@ impl ErrorExt for RpcError {
tags: self.tags.clone(),
}
}
fn cloned(&self) -> anyhow::Error {
self.clone().into()
}
}
impl std::error::Error for RpcError {

View File

@@ -27,7 +27,7 @@ schemars.workspace = true
serde.workspace = true
serde_derive.workspace = true
serde_json.workspace = true
serde_json_lenient.workspace = true
serde_json_lenient = {version = "0.1", features = ["preserve_order", "raw_value"] }
smallvec.workspace = true
toml.workspace = true
tree-sitter-json = "*"

View File

@@ -86,7 +86,6 @@ pub trait Settings: 'static + Send + Sync {
});
}
/// path is a (worktree ID, Path)
#[track_caller]
fn get<'a>(path: Option<(usize, &Path)>, cx: &'a AppContext) -> &'a Self
where

View File

@@ -34,7 +34,6 @@ schemars = { workspace = true, features = ["indexmap"] }
serde.workspace = true
serde_derive.workspace = true
serde_json.workspace = true
serde_json_lenient.workspace = true
serde_repr.workspace = true
settings = { path = "../settings" }
story = { path = "../story", optional = true }

View File

@@ -259,7 +259,7 @@ impl ThemeRegistry {
continue;
};
let Some(theme) = serde_json_lenient::from_reader(reader).log_err() else {
let Some(theme) = serde_json::from_reader(reader).log_err() else {
continue;
};

View File

@@ -513,9 +513,9 @@ impl Motion {
StartOfLineDownward => (next_line_start(map, point, times - 1), SelectionGoal::None),
EndOfLineDownward => (next_line_end(map, point, times), SelectionGoal::None),
GoToColumn => (go_to_column(map, point, times), SelectionGoal::None),
WindowTop => window_top(map, point, &text_layout_details, times - 1),
WindowTop => window_top(map, point, &text_layout_details),
WindowMiddle => window_middle(map, point, &text_layout_details),
WindowBottom => window_bottom(map, point, &text_layout_details, times - 1),
WindowBottom => window_bottom(map, point, &text_layout_details),
};
(new_point != point || infallible).then_some((new_point, goal))
@@ -1044,24 +1044,11 @@ fn window_top(
map: &DisplaySnapshot,
point: DisplayPoint,
text_layout_details: &TextLayoutDetails,
times: usize,
) -> (DisplayPoint, SelectionGoal) {
let first_visible_line = text_layout_details.anchor.to_display_point(map);
if let Some(visible_rows) = text_layout_details.visible_rows {
let bottom_row = first_visible_line.row() + visible_rows as u32;
let new_row = (first_visible_line.row() + (times as u32)).min(bottom_row);
let new_col = point.column().min(map.line_len(first_visible_line.row()));
let new_point = DisplayPoint::new(new_row, new_col);
(map.clip_point(new_point, Bias::Left), SelectionGoal::None)
} else {
let new_row = first_visible_line.row() + (times as u32);
let new_col = point.column().min(map.line_len(first_visible_line.row()));
let new_point = DisplayPoint::new(new_row, new_col);
(map.clip_point(new_point, Bias::Left), SelectionGoal::None)
}
let new_col = point.column().min(map.line_len(first_visible_line.row()));
let new_point = DisplayPoint::new(first_visible_line.row(), new_col);
(map.clip_point(new_point, Bias::Left), SelectionGoal::None)
}
fn window_middle(
@@ -1085,19 +1072,13 @@ fn window_bottom(
map: &DisplaySnapshot,
point: DisplayPoint,
text_layout_details: &TextLayoutDetails,
times: usize,
) -> (DisplayPoint, SelectionGoal) {
if let Some(visible_rows) = text_layout_details.visible_rows {
let first_visible_line = text_layout_details.anchor.to_display_point(map);
let bottom_row = first_visible_line.row() + (visible_rows) as u32;
let bottom_row_capped = bottom_row.min(map.max_buffer_row());
let new_row = if bottom_row_capped.saturating_sub(times as u32) < first_visible_line.row() {
first_visible_line.row()
} else {
bottom_row_capped.saturating_sub(times as u32)
};
let new_col = point.column().min(map.line_len(new_row));
let new_point = DisplayPoint::new(new_row, new_col);
let new_col = point.column().min(map.line_len(bottom_row_capped));
let new_point = DisplayPoint::new(bottom_row_capped, new_col);
(map.clip_point(new_point, Bias::Left), SelectionGoal::None)
} else {
(point, SelectionGoal::None)
@@ -1321,18 +1302,6 @@ mod test {
7 8 9
"})
.await;
cx.set_shared_state(indoc! {r"
1 2 3
4 5 ˇ6
7 8 9"})
.await;
cx.simulate_shared_keystrokes(["9", "shift-h"]).await;
cx.assert_shared_state(indoc! {r"
1 2 3
4 5 6
7 8 ˇ9"})
.await;
}
#[gpui::test]
@@ -1497,19 +1466,5 @@ mod test {
7 8 9
ˇ"})
.await;
cx.set_shared_state(indoc! {r"
1 2 3
4 5 ˇ6
7 8 9
"})
.await;
cx.simulate_shared_keystrokes(["9", "shift-l"]).await;
cx.assert_shared_state(indoc! {r"
1 2 ˇ3
4 5 6
7 8 9
"})
.await;
}
}

View File

@@ -13,7 +13,3 @@
{"Put":{"state":"ˇ1 2 3\n4 5 6\n7 8 9\n"}}
{"Key":"shift-l"}
{"Get":{"state":"1 2 3\n4 5 6\n7 8 9\nˇ","mode":"Normal"}}
{"Put":{"state":"1 2 3\n4 5 ˇ6\n7 8 9\n"}}
{"Key":"9"}
{"Key":"shift-l"}
{"Get":{"state":"1 2 ˇ3\n4 5 6\n7 8 9\n","mode":"Normal"}}

View File

@@ -7,7 +7,3 @@
{"Put":{"state":"1 2 3\n4 5 6\nˇ7 8 9\n"}}
{"Key":"shift-h"}
{"Get":{"state":"ˇ1 2 3\n4 5 6\n7 8 9\n","mode":"Normal"}}
{"Put":{"state":"1 2 3\n4 5 ˇ6\n7 8 9"}}
{"Key":"9"}
{"Key":"shift-h"}
{"Get":{"state":"1 2 3\n4 5 6\n7 8 ˇ9","mode":"Normal"}}

View File

@@ -176,19 +176,11 @@ impl Member {
return div().into_any();
}
let follower_state = follower_states.get(pane);
let leader = follower_state.and_then(|state| {
let leader = follower_states.get(pane).and_then(|state| {
let room = active_call?.read(cx).room()?.read(cx);
room.remote_participant_for_peer_id(state.leader_id)
});
let is_in_unshared_view = follower_state.map_or(false, |state| {
state.active_view_id.is_some_and(|view_id| {
!state.items_by_leader_view_id.contains_key(&view_id)
})
});
let mut leader_border = None;
let mut leader_status_box = None;
let mut leader_join_data = None;
@@ -206,14 +198,7 @@ impl Member {
project_id: leader_project_id,
} => {
if Some(leader_project_id) == project.read(cx).remote_id() {
if is_in_unshared_view {
Some(Label::new(format!(
"{} is in an unshared pane",
leader.user.github_login
)))
} else {
None
}
None
} else {
leader_join_data = Some((leader_project_id, leader.user.id));
Some(Label::new(format!(

View File

@@ -2784,10 +2784,8 @@ impl Workspace {
item_tasks.push(task);
leader_view_ids.push(id);
break;
} else if variant.is_none() {
Err(anyhow!(
"failed to construct view from leader (maybe from a different version of zed?)"
))?;
} else {
assert!(variant.is_some());
}
}
}

View File

@@ -2,7 +2,7 @@
description = "The fast, collaborative code editor."
edition = "2021"
name = "zed"
version = "0.122.0"
version = "0.121.0"
publish = false
license = "GPL-3.0-or-later"
@@ -66,7 +66,6 @@ libc = "0.2"
log.workspace = true
lsp = { path = "../lsp" }
menu = { path = "../menu" }
mimalloc = "0.1"
node_runtime = { path = "../node_runtime" }
notifications = { path = "../notifications" }
num_cpus = "1.13.0"
@@ -113,12 +112,10 @@ tree-sitter-css.workspace = true
tree-sitter-elixir.workspace = true
tree-sitter-elm.workspace = true
tree-sitter-embedded-template.workspace = true
tree-sitter-gitcommit.workspace = true
tree-sitter-gleam.workspace = true
tree-sitter-glsl.workspace = true
tree-sitter-go.workspace = true
tree-sitter-gomod.workspace = true
tree-sitter-gowork.workspace = true
tree-sitter-haskell.workspace = true
tree-sitter-heex.workspace = true
tree-sitter-html.workspace = true

View File

@@ -112,7 +112,7 @@ pub fn init(
})],
),
}
language("gitcommit", tree_sitter_gitcommit::language(), vec![]);
language(
"gleam",
tree_sitter_gleam::language(),
@@ -124,7 +124,6 @@ pub fn init(
vec![Arc::new(go::GoLspAdapter)],
);
language("gomod", tree_sitter_gomod::language(), vec![]);
language("gowork", tree_sitter_gowork::language(), vec![]);
language(
"zig",
tree_sitter_zig::language(),
@@ -357,7 +356,6 @@ const QUERY_FILENAME_PREFIXES: &[(
("embedding", |q| &mut q.embedding),
("injections", |q| &mut q.injections),
("overrides", |q| &mut q.overrides),
("redactions", |q| &mut q.redactions),
];
fn load_queries(name: &str) -> LanguageQueries {

View File

@@ -1,5 +1,5 @@
name = "Shell Script"
path_suffixes = ["sh", "bash", "bashrc", "bash_profile", "bash_aliases", "bash_logout", "profile", "zsh", "zshrc", "zshenv", "zsh_profile", "zsh_aliases", "zsh_histfile", "zlogin", "zprofile", ".env"]
path_suffixes = ["sh", "bash", "bashrc", "bash_profile", "bash_aliases", "bash_logout", "profile", "zsh", "zshrc", "zshenv", "zsh_profile", "zsh_aliases", "zsh_histfile", "zlogin", "zprofile"]
line_comments = ["# "]
first_line_pattern = "^#!.*\\b(?:ba|z)?sh\\b"
brackets = [

View File

@@ -1,2 +0,0 @@
(variable_assignment
value: (_) @redact)

View File

@@ -1,11 +0,0 @@
name = "Git commit"
path_suffixes = [
# Refer to https://github.com/neovim/neovim/blob/master/runtime/lua/vim/filetype.lua#L1286-L1290
"TAG_EDITMSG",
"MERGE_MSG",
"COMMIT_EDITMSG",
"NOTES_EDITMSG",
"EDIT_DESCRIPTION",
]
line_comments = ["#"]
brackets = []

View File

@@ -1,34 +0,0 @@
(comment) @comment
(generated_comment) @comment
(title) @text.title
(text) @text
(branch) @text.reference
(change) @keyword
(filepath) @text.uri
(arrow) @punctuation.delimiter
(subject) @text.title
(subject (overflow) @text)
(prefix (type) @keyword)
(prefix (scope) @parameter)
(prefix [
"("
")"
":"
] @punctuation.delimiter)
(prefix [
"!"
] @punctuation.special)
(message) @text
(trailer (token) @keyword)
(trailer (value) @text)
(breaking_change (token) @text.warning)
(breaking_change (value) @text)
(scissor) @comment
(subject_prefix) @keyword
(ERROR) @error

View File

@@ -1,8 +0,0 @@
((diff) @injection.content
(#set! injection.combined)
(#set! injection.language "diff"))
((rebase_command) @injection.content
(#set! injection.combined)
(#set! injection.language "git_rebase"))

View File

@@ -1,7 +0,0 @@
name = "Go Work"
path_suffixes = ["work"]
line_comments = ["//"]
autoclose_before = ")"
brackets = [
{ start = "(", end = ")", close = true, newline = true}
]

View File

@@ -1,14 +0,0 @@
[
"replace"
"go"
"use"
] @keyword
"=>" @operator
(comment) @comment
[
(version)
(go_version)
] @string

View File

@@ -1,4 +0,0 @@
(pair value: (number) @redact)
(pair value: (string) @redact)
(array (number) @redact)
(array (string) @redact)

View File

@@ -1 +0,0 @@
(pair (bare_key) "=" (_) @redact)

View File

@@ -1 +0,0 @@
(block_mapping_pair value: (flow_node) @redact)

View File

@@ -18,7 +18,6 @@ use language::LanguageRegistry;
use log::LevelFilter;
use assets::Assets;
use mimalloc::MiMalloc;
use node_runtime::RealNodeRuntime;
use parking_lot::Mutex;
use release_channel::{parse_zed_link, AppCommitSha, ReleaseChannel, RELEASE_CHANNEL};
@@ -58,9 +57,6 @@ use zed::{
OpenRequest,
};
#[global_allocator]
static GLOBAL: MiMalloc = MiMalloc;
fn main() {
menu::init();
zed_actions::init();

View File

@@ -17,23 +17,23 @@ diverse, inclusive, and healthy community.
Examples of behavior that contributes to a positive environment for our
community include:
- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes,
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
- Focusing on what is best not just for us as individuals, but for the
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
- The use of sexualized language or imagery, and sexual attention or
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
- Other conduct which could reasonably be considered inappropriate in a
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
@@ -106,7 +106,7 @@ Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within

View File

@@ -2,7 +2,7 @@
## Folder-specific settings
Folder-specific settings are used to override Zed's global settings for files within a specific directory in the project panel. To get started, create a `.zed` subdirectory and add a `settings.json` within it. It should be noted that folder-specific settings don't need to live only a project's root, but can be defined at multiple levels in the project hierarchy. In setups like this, Zed will find the configuration nearest to the file you are working in and apply those settings to it. In most cases, this level of flexibility won't be needed and a single configuration for all files in a project is all that is required; the `Zed > Settings > Open Local Settings` menu action is built for this case. Running this action will look for a `.zed/settings.json` file at the root of the first top-level directory in your project panel. If it does not exist, it will create it.
Folder-specific settings are used to override Zed's global settings for files within a specific directory in the project panel. To get started, create a `.zed` subdirectory and add a `settings.json` within it. It should be noted that folder-specific settings don't need to live only a project's root, but can be defined at multiple levels in the project hierarchy. In setups like this, Zed will find the configuration nearest to the file you are working in and apply those settings to it. In most cases, this level of flexibility won't be needed and a single configuration for all files in a project is all that is required; the `Zed > Settings > Open Local Settings` menu action is built for this case. Running this action will look for a `.zed/settings.json` file at the root of the first top-level directory in your project panel. If it does not exist, it will create it.
The following global settings can be overridden with a folder-specific configuration:
@@ -20,7 +20,7 @@ The following global settings can be overridden with a folder-specific configura
- `show_copilot_suggestions`
- `show_whitespaces`
_See the Global settings section for details about these settings_
*See the Global settings section for details about these settings*
## Global settings
@@ -110,7 +110,7 @@ The name of any font family installed on the user's system
**Options**
Zed supports a subset of OpenType features that can be enabled or disabled for a given buffer or terminal font. The following [OpenType features](https://en.wikipedia.org/wiki/List_of_typographic_features) can be enabled or disabled too: `calt`, `case`, `cpsp`, `frac`, `liga`, `onum`, `ordn`, `pnum`, `ss01`, `ss02`, `ss03`, `ss04`, `ss05`, `ss06`, `ss07`, `ss08`, `ss09`, `ss10`, `ss11`, `ss12`, `ss13`, `ss14`, `ss15`, `ss16`, `ss17`, `ss18`, `ss19`, `ss20`, `subs`, `sups`, `swsh`, `titl`, `tnum`, `zero`.
Zed supports a subset of OpenType features that can be enabled or disabled for a given buffer or terminal font. The following [OpenType features](https://en.wikipedia.org/wiki/List_of_typographic_features) can be enabled or disabled too: `calt`, `case`, `cpsp`, `frac`, `liga`, `onum`, `ordn`, `pnum`, `ss01`, `ss02`, `ss03`, `ss04`, `ss05`, `ss06`, `ss07`, `ss08`, `ss09`, `ss10`, `ss11`, `ss12`, `ss13`, `ss14`, `ss15`, `ss16`, `ss17`, `ss18`, `ss19`, `ss20`, `subs`, `sups`, `swsh`, `titl`, `tnum`, `zero`.
For example, to disable ligatures for a given font you can add the following to your settings:
@@ -1005,7 +1005,6 @@ Run the `theme selector: toggle` action in the command palette to see a current
```
### Default Width
- Description: Customise default width taken by project panel
- Setting: `default_width`
- Default: N/A width in pixels (eg: 420)

View File

@@ -2,18 +2,15 @@
Zed includes a vim emulation layer known as “vim mode”. This document aims to describe how it works, and how to make the most out of it.
## Philosophy
### Philosophy
Vim mode in Zed is supposed to primarily "do what you expect": it mostly tries to copy vim exactly, but will use Zed-specific functionality when available to make things smoother.
This means Zed will never be 100% vim compatible, but should be 100% vim familiar! We expect that our vim mode already copes with 90% of your workflow, and we'd like to keep improving it. If you find things that you cant yet do in vim mode, but which you rely on in your current workflow, please leave feedback in the editor itself (`:feedback`), or [file an issue](https://github.com/zed-industries/zed/issues).
## Zed-specific features
### Zed-specific features
Zed is built on a modern foundation that (among other things) uses tree-sitter to understand the content of the file you're editing, and supports multiple cursors out of the box.
Vim mode has several "core Zed" key bindings, that will help you make the most of Zed's specific feature set.
```
# Normal mode
g d Go to definition
@@ -48,9 +45,8 @@ Vim mode emulates visual block mode using Zed's multiple cursor support. This ag
Finally, Vim mode's search and replace functionality is backed by Zed's. This means that the pattern syntax is slightly different, see the section on [Regex differences](#regex-differences) for details.
## Custom key bindings
Zed does not yet have an equivalent to vims `map` command to convert one set of keystrokes into another, however you can bind any sequence of keys to fire any Action documented in the [Key bindings documentation](https://docs.zed.dev/configuration/key-bindings).
### Custom key bindings
Zed does not yet have an equivalent to vims `map` command to convert one set of keystrokes into another, however you can bind any sequence of keys to fire any Action documented in the [Key bindings documentation](https://docs.zed.dev/configuration/key-bindings).
You can edit your personal key bindings with `:keymap`.
For vim-specific shortcuts, you may find the following template a good place to start:
@@ -88,7 +84,7 @@ You can see the bindings that are enabled by default in vim mode [here](https://
The details of the context are a little out of scope for this doc, but suffice to say that `menu` is true when a menu is open (e.g. the completions menu), `VimWaiting` is true after you type `f` or `t` when were waiting for a new key (and you probably dont want bindings to happen). Please reach out on [GitHub](https://github.com/zed-industries/zed) if you want help making a key bindings work.
## Command palette
### Command palette
Vim mode allows you to enable Zeds command palette with `:`. This means that you can use vim's command palette to run any action that Zed supports.
@@ -99,7 +95,6 @@ We do not (yet) emulate the full power of vims command line, in particular we
As mentioned above, one thing to be aware of is that the regex engine is slightly different from vim's in `:%s/a/b`.
Currently supported vim-specific commands (as of Zed 0.106):
```
# window management
:w[rite][!], :wq[!], :q[uit][!], :wa[ll][!], :wqa[ll][!], :qa[ll][!], :[e]x[it][!], :up[date]
@@ -144,10 +139,9 @@ Currently supported vim-specific commands (as of Zed 0.106):
to sort the current selection (with i, case-insensitively)
```
## Related settings
### Related settings
There are a few Zed settings that you may also enjoy if you use vim mode:
```json
{
// disable cursor blink
@@ -155,22 +149,21 @@ There are a few Zed settings that you may also enjoy if you use vim mode:
// use relative line numbers
"relative_line_numbers": true,
// hide the scroll bar
"scrollbar": { "show": "never" }
"scrollbar": {"show": "never"}
}
```
## Regex differences
### Regex differences
Zed uses a different regular expression engine from Vim. This means that you will have to use a different syntax for some things.
Notably:
- Vim uses `\(` and `\)` to represent capture groups, in Zed these are `(` and `)`.
- On the flip side, `(` and `)` represent literal parentheses, but in Zed these must be escaped to `\(` and `\)`.
- When replacing, Vim uses `\0` to represent the entire match, in Zed this is `$0`, same for numbered capture groups `\1` -> `$1`.
- Vim uses `\<` and `\>` to represent word boundaries, in Zed these are both handled by `\b`
- Vim uses `/g` to indicate "all matches on one line", in Zed this is implied
- Vim uses `/i` to indicate "case-insensitive", in Zed you can either use `(?i)` at the start of the pattern or toggle case-sensitivity with `cmd-option-c`.
* Vim uses `\(` and `\)` to represent capture groups, in Zed these are `(` and `)`.
* On the flip side, `(` and `)` represent literal parentheses, but in Zed these must be escaped to `\(` and `\)`.
* When replacing, Vim uses `\0` to represent the entire match, in Zed this is `$0`, same for numbered capture groups `\1` -> `$1`.
* Vim uses `\<` and `\>` to represent word boundaries, in Zed these are both handled by `\b`
* Vim uses `/g` to indicate "all matches on one line", in Zed this is implied
* Vim uses `/i` to indicate "case-insensitive", in Zed you can either use `(?i)` at the start of the pattern or toggle case-sensitivity with `cmd-option-c`.
To help with the transition, the command palette will fix parentheses and replace groups for you when you run `:%s//`. So `%s:/\(a\)(b)/\1/` will be converted into a search for "(a)\(b\)" and a replacement of "$1".

View File

@@ -1,16 +1,16 @@
Zed can be configured via a simple JSON file located at `~/.config/zed/keymap.json`.
## Predefined keymaps
### Predefined keymaps
We have a growing collection of pre-defined keymaps in [zed repository's keymaps folder](https://github.com/zed-industries/zed/tree/main/assets/keymaps).
## Custom key bindings
### Custom key bindings
### Accessing custom key bindings
#### Accessing custom key bindings
You can open `keymap.json` via `⌘` + `K`, `⌘` + `S`, the command palette, or the `Zed > Settings > Open Key Bindings` application menu item.
### Adding a custom key binding
#### Adding a custom key binding
To customize key bindings, specify a context and the list of bindings to set. Re-mapping an existing binding will clobber the existing binding in favor of the custom one.
@@ -33,9 +33,9 @@ You can see more examples in Zed's [`default.json`](https://zed.dev/ref/default.
_There are some key bindings that can't be overridden; we are working on an issue surrounding this._
## All key bindings
### All key bindings
### Global
#### Global
| **Command** | **Target** | **Default Shortcut** |
| -------------------------------- | -------------- | ----------------------------- |
@@ -97,7 +97,7 @@ _There are some key bindings that can't be overridden; we are working on an issu
| Reset buffer font size | Zed | `` + `0` |
| Toggle full screen | Zed | `Control` + `` + `F` |
### Editor
#### Editor
| **Command** | **Target** | **Default Shortcut** |
| -------------------------------- | ---------- | ------------------------------------- |
@@ -240,7 +240,7 @@ _There are some key bindings that can't be overridden; we are working on an issu
| Undo selection | Editor | `` + `U` |
| Unfold lines | Editor | `Alt` + `` + `]` |
### Editor (Full Only)
#### Editor (Full Only)
| **Command** | **Target** | **Default Shortcut** |
| ------------------- | ------------- | ----------------------- |
@@ -258,14 +258,14 @@ _There are some key bindings that can't be overridden; we are working on an issu
| Toggle | Go To Line | `Control` + `G` |
| Toggle | Outline | `⌘` + `Shift` + `O` |
### Editor (Auto Height Only)
#### Editor (Auto Height Only)
| **Command** | **Target** | **Default Shortcut** |
| ------------- | ---------- | ----------------------------- |
| Newline | Editor | `Control` + `Enter` |
| Newline below | Editor | `Control` + `Shift` + `Enter` |
### Pane
#### Pane
| **Command** | **Target** | **Default Shortcut** |
| ---------------------- | -------------- | -------------------- |
@@ -300,7 +300,7 @@ _There are some key bindings that can't be overridden; we are working on an issu
| Toggle replace | Search | `⌘` + `Shift` + `H` |
| Toggle whole word | Search | `Alt` + `⌘` + `W` |
### Buffer Search Bar
#### Buffer Search Bar
| **Command** | **Target** | **Default Shortcut** |
| ---------------------- | ------------- | -------------------- |
@@ -315,7 +315,7 @@ _There are some key bindings that can't be overridden; we are working on an issu
| Select next match | Search | `Enter` |
| Select prev match | Search | `Shift` + `Enter` |
### Workspace
#### Workspace
| **Command** | **Target** | **Default Shortcut** |
| ------------------ | ----------------- | -------------------- |
@@ -344,7 +344,7 @@ _There are some key bindings that can't be overridden; we are working on an issu
| Toggle right dock | Workspace | `⌘` + `R` |
| Open keymap | Zed | `⌘` + `K`, `⌘` + `S` |
### Project Panel
#### Project Panel
| **Command** | **Target** | **Default Shortcut** |
| ----------------------- | ------------- | --------------------------- |
@@ -364,7 +364,7 @@ _There are some key bindings that can't be overridden; we are working on an issu
| Rename | Project Panel | `F2` |
| Reveal in finder | Project Panel | `Alt` + `⌘` + `R` |
### Project Search Bar
#### Project Search Bar
| **Command** | **Target** | **Default Shortcut** |
| ---------------------- | -------------- | -------------------- |
@@ -380,7 +380,7 @@ _There are some key bindings that can't be overridden; we are working on an issu
| Replace next | Search | `Enter` |
| Toggle replace | Search | `⌘` + `Shift` + `H` |
### Terminal
#### Terminal
| **Command** | **Target** | **Default Shortcut** |
| --------------------------- | ---------- | ------------------------- |
@@ -394,7 +394,7 @@ _There are some key bindings that can't be overridden; we are working on an issu
| Paste | Terminal | `⌘` + `V` |
| Show character palette | Terminal | `Control` + `⌘` + `Space` |
### Assistant Editor
#### Assistant Editor
| **Command** | **Target** | **Default Shortcut** |
| ------------------ | ---------- | -------------------- |

View File

@@ -18,10 +18,10 @@ We use tree-sitter queries to match certain properties to highlight.
```ts
const font: FontFamily = {
weight: "normal",
underline: false,
italic: false,
};
weight: "normal",
underline: false,
italic: false,
}
```
Match a property identifier and highlight it using the identifier `@property`. In the above example, `weight`, `underline`, and `italic` would be highlighted.
@@ -40,7 +40,7 @@ Match a property identifier and highlight it using the identifier `@property`. I
```ts
function buildDefaultSyntax(colorScheme: Theme): Partial<Syntax> {
// ...
// ...
}
```

View File

@@ -15,21 +15,21 @@ git submodule update --init --recursive
- Install [Xcode command line tools](https://developer.apple.com/xcode/resources/)
```bash
xcode-select --install
```
```bash
xcode-select --install
```
- Ensure that the Xcode command line tools are using your newly installed copy of Xcode:
```
sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
```
```
sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
```
* Install the Rust wasm toolchain:
```bash
rustup target add wasm32-wasi
```
```bash
rustup target add wasm32-wasi
```
## Backend Dependencies
@@ -38,9 +38,9 @@ If you are developing collaborative features of Zed, you'll need to install the
- Install [Postgres](https://postgresapp.com)
- Install [Livekit](https://formulae.brew.sh/formula/livekit) and [Foreman](https://formulae.brew.sh/formula/foreman)
```bash
brew install livekit foreman
```
```bash
brew install livekit foreman
```
## Building Zed from Source

View File

@@ -12,7 +12,7 @@ script/bootstrap
This script will set up the `zed` Postgres database, and populate it with some users. It requires internet access, because it fetches some users from the GitHub API.
The script will create several _admin_ users, who you'll sign in as by default when developing locally. The GitHub logins for these default admin users are specified in this file:
The script will create several *admin* users, who you'll sign in as by default when developing locally. The GitHub logins for these default admin users are specified in this file:
```
cat crates/collab/.admins.default.json

View File

@@ -1,29 +1,29 @@
# Giving feedback
## Zed repository
### Zed repository
We track our issues at [`zed-industries/zed`](https://github.com/zed-industries/zed/issues).
### Feature requests
#### Feature requests
Try to focus on the things that are most critical to you rather than exhaustively listing all features another editor you have used has.
Command palette: `request feature`
### Bug reports
#### Bug reports
Try to add as much detail as possible, if it is not obvious to reproduce. Let us know how severe the problem is for you; is the issue more of a minor inconvenience or something that would prevent you from using Zed?
Command palette: `file bug report`
## In-app feedback
### In-app feedback
Anonymous feedback can be submitted from within Zed via the feedback editor (command palette: `give feedback`).
## Zed forum
### Zed forum
Use the [Zed forum](https://github.com/zed-industries/zed/discussions) to ask questions and learn from one another. We will be present in the forum and answering questions as well.
## Email
### Email
If you prefer to write up your thoughts as an email, you can send them to [hi@zed.dev](mailto:hi@zed.dev).

View File

@@ -2,14 +2,14 @@
Welcome to Zed! We are excited to have you. Here is a jumping-off point to getting started.
## Download Zed
### Download Zed
You can obtain the release build via the [download page](https://zed.dev/download). After the first manual installation, Zed will periodically check for and install updates automatically for you.
## Configure Zed
### Configure Zed
Use `⌘` + `,` to open your custom settings to set things like fonts, formatting settings, per-language settings and more. You can access the default configuration using the `Zed > Settings > Open Default Settings` menu item. See Configuring Zed for all available settings.
## Set up your key bindings
### Set up your key bindings
You can access the default key binding set using the `Zed > Settings > Open Default Key Bindings` menu item. Use `⌘` + `K`, `⌘` + `S` to open your custom keymap to add your own key bindings. See Key Bindings for more info.

View File

@@ -20,12 +20,12 @@ brew install elixir-ls
3. Restart Zed
{% hint style="warning" %}
If `elixir-ls` is not running in an elixir project, check the error log via the command palette action `zed: open log`. If you find an error message mentioning: `invalid LSP message header "Shall I install Hex? (if running non-interactively, use \"mix local.hex --force\") [Yn]`, you might need to install [`Hex`](https://hex.pm). You run `elixir-ls` from the command line and accept the prompt to install `Hex`.
If `elixir-ls` is not running in an elixir project, check the error log via the command palette action `zed: open log`. If you find an error message mentioning: `invalid LSP message header "Shall I install Hex? (if running non-interactively, use \"mix local.hex --force\") [Yn]`, you might need to install [`Hex`](https://hex.pm). You run `elixir-ls` from the command line and accept the prompt to install `Hex`.
{% endhint %}
### Formatting with Mix
If you prefer to format your code with [Mix](https://hexdocs.pm/mix/Mix.html), use the following snippet in your `settings.json` file to configure it as an external formatter. Formatting will occur on file save.
If you prefer to format your code with [Mix](https://hexdocs.pm/mix/Mix.html), use the following snippet in your `settings.json` file to configure it as an external formatter. Formatting will occur on file save.
```json
{

View File

@@ -17,8 +17,8 @@ By default, the Pyright language server will look for Python packages in the def
To do this, create a JSON file called `pyrightconfig.json` at the root of your project. This file must include two keys:
- `venvPath`: a relative path from your project directory to any directory that _contains_ one or more virtual environment directories
- `venv`: the name of a virtual environment directory
* `venvPath`: a relative path from your project directory to any directory that _contains_ one or more virtual environment directories
* `venv`: the name of a virtual environment directory
For example, a common approach is to create a virtual environment directory called `.venv` at the root of your project directory with the following commands:
@@ -40,7 +40,7 @@ Having done that, you would create a `pyrightconfig.json` with the following con
### Code formatting
The Pyright language server does not provide code formatting. If you want to automatically reformat your Python code when saving, you'll need to specify an \_external_code formatter in your settings. See the [configuration](../configuration/configuring-zed.md) documentation for more information.
The Pyright language server does not provide code formatting. If you want to automatically reformat your Python code when saving, you'll need to specify an _external_code formatter in your settings. See the [configuration](../configuration/configuring-zed.md) documentation for more information.
A common tool for formatting python code is [Black](https://black.readthedocs.io/en/stable/). If you have Black installed globally, you can use it to format Python files by adding the following to your `settings.json`:

View File

@@ -23,14 +23,14 @@ Solargraph has formatting and diagnostics disabled by default. We can tell Zed t
```json
{
"lsp": {
"solargraph": {
"initialization_options": {
"diagnostics": true,
"formatting": true
"lsp": {
"solargraph": {
"initialization_options": {
"diagnostics": true,
"formatting": true
}
}
}
}
}
}
```

View File

@@ -1,4 +1,5 @@
# TOML
- Tree Sitter: [tree-sitter-toml](https://github.com/tree-sitter/tree-sitter-toml)
- Language Server: [taplo](https://taplo.tamasfe.dev)

View File

@@ -30,14 +30,14 @@ When a panic occurs, the following data is sent:
- `thread`: The name of the thread that panicked
- `payload`: The panic message
- `location_data`: The location of the panic
- `file`
- `line`
- `file`
- `line`
- `backtrace`: The backtrace of the panic
- `app_version`: Zed's app version
- `release_channel`: Zed's release channel
- `stable`
- `preview`
- `dev`
- `stable`
- `preview`
- `dev`
- `os_name`: The name of your operating system
- `os_version`: The version of your operating system
- `architecture`: The architecture of your CPU
@@ -62,9 +62,9 @@ The following data is sent:
- `os_version`: The version of your operating system
- `architecture`: The architecture of your CPU
- `release_channel`: Zed's release channel
- `stable`
- `preview`
- `dev`
- `stable`
- `preview`
- `dev`
- `events`: A vector of `ClickhouseEventWrapper`s
#### ClickhouseEventWrapper
@@ -75,57 +75,57 @@ The following data is sent:
#### ClickhouseEvent
- `editor`
- `operation`: The editor operation that was performed
- `open`
- `save`
- `file_extension`: The extension of the file that was opened or saved
- `vim_mode`: A boolean that indicates whether the user is in vim mode or not
- `copilot_enabled`: A boolean that indicates whether the user has copilot enabled or not
- `copilot_enabled_for_language`: A boolean that indicates whether the user has copilot enabled for the language of the file that was opened or saved
- `milliseconds_since_first_event`: Duration of time between this event's timestamp and the timestamp of the first event in the current batch
- `operation`: The editor operation that was performed
- `open`
- `save`
- `file_extension`: The extension of the file that was opened or saved
- `vim_mode`: A boolean that indicates whether the user is in vim mode or not
- `copilot_enabled`: A boolean that indicates whether the user has copilot enabled or not
- `copilot_enabled_for_language`: A boolean that indicates whether the user has copilot enabled for the language of the file that was opened or saved
- `milliseconds_since_first_event`: Duration of time between this event's timestamp and the timestamp of the first event in the current batch
- `copilot`
- `suggestion_id`: The ID of the suggestion
- `suggestion_accepted`: A boolean that indicates whether the suggestion was accepted or not
- `file_extension`: The file extension of the file that was opened or saved
- `milliseconds_since_first_event`: Same as above
- `suggestion_id`: The ID of the suggestion
- `suggestion_accepted`: A boolean that indicates whether the suggestion was accepted or not
- `file_extension`: The file extension of the file that was opened or saved
- `milliseconds_since_first_event`: Same as above
- `call`
- `operation`: The call operation that was performed
- `accept incoming`
- `decline incoming`
- `disable microphone`
- `disable screen share`
- `enable microphone`
- `enable screen share`
- `hang up`
- `invite`
- `join channel`
- `open channel notes`
- `share project`
- `unshare project`
- `room_id`: The ID of the room
- `channel_id`: The ID of the channel
- `milliseconds_since_first_event`: Same as above
- `operation`: The call operation that was performed
- `accept incoming`
- `decline incoming`
- `disable microphone`
- `disable screen share`
- `enable microphone`
- `enable screen share`
- `hang up`
- `invite`
- `join channel`
- `open channel notes`
- `share project`
- `unshare project`
- `room_id`: The ID of the room
- `channel_id`: The ID of the channel
- `milliseconds_since_first_event`: Same as above
- `assistant`
- `conversation_id`: The ID of the conversation (for panel events only)
- `kind`: An enum with the following variants:
- `panel`
- `inline`
- `model`: The model that was used
- `milliseconds_since_first_event`: Same as above
- `conversation_id`: The ID of the conversation (for panel events only)
- `kind`: An enum with the following variants:
- `panel`
- `inline`
- `model`: The model that was used
- `milliseconds_since_first_event`: Same as above
- `cpu`
- `usage_as_percentage`: The CPU usage
- `core_count`: The number of cores on the CPU
- `milliseconds_since_first_event`: Same as above
- `usage_as_percentage`: The CPU usage
- `core_count`: The number of cores on the CPU
- `milliseconds_since_first_event`: Same as above
- `memory`
- `memory_in_bytes`: The amount of memory used in bytes
- `virtual_memory_in_bytes`: The amount of virtual memory used in bytes
- `milliseconds_since_first_event`: Same as above
- `memory_in_bytes`: The amount of memory used in bytes
- `virtual_memory_in_bytes`: The amount of virtual memory used in bytes
- `milliseconds_since_first_event`: Same as above
- `app`
- `operation`: The app operation that was performed
- `first open`
- `open`
- `close`
- `milliseconds_since_first_event`: Same as above
- `operation`: The app operation that was performed
- `first open`
- `open`
- `close`
- `milliseconds_since_first_event`: Same as above
You can audit the metrics data that Zed has reported by running the command `zed: open telemetry log` from the command palette, or clicking `Help > View Telemetry Log` in the application menu.