Merge branch 'main' into polish-project-diagnostics
Co-Authored-By: Max Brunsfeld <max@zed.dev>
This commit is contained in:
commit
b2f0c78924
12 changed files with 166 additions and 107 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -5683,7 +5683,7 @@ checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zed"
|
name = "zed"
|
||||||
version = "0.9.0"
|
version = "0.11.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-recursion",
|
"async-recursion",
|
||||||
|
|
|
@ -11,7 +11,7 @@ use gpui::{
|
||||||
};
|
};
|
||||||
use language::{Bias, Buffer, Diagnostic, DiagnosticEntry, Point};
|
use language::{Bias, Buffer, Diagnostic, DiagnosticEntry, Point};
|
||||||
use postage::watch;
|
use postage::watch;
|
||||||
use project::{Project, ProjectPath};
|
use project::{Project, ProjectPath, WorktreeId};
|
||||||
use std::{cmp::Ordering, ops::Range, path::Path, sync::Arc};
|
use std::{cmp::Ordering, ops::Range, path::Path, sync::Arc};
|
||||||
use util::TryFutureExt;
|
use util::TryFutureExt;
|
||||||
use workspace::Workspace;
|
use workspace::Workspace;
|
||||||
|
@ -45,7 +45,7 @@ struct ProjectDiagnosticsEditor {
|
||||||
editor: ViewHandle<Editor>,
|
editor: ViewHandle<Editor>,
|
||||||
excerpts: ModelHandle<MultiBuffer>,
|
excerpts: ModelHandle<MultiBuffer>,
|
||||||
path_states: Vec<(Arc<Path>, Vec<DiagnosticGroupState>)>,
|
path_states: Vec<(Arc<Path>, Vec<DiagnosticGroupState>)>,
|
||||||
paths_to_update: HashMap<usize, HashSet<ProjectPath>>,
|
paths_to_update: HashMap<WorktreeId, HashSet<ProjectPath>>,
|
||||||
build_settings: BuildSettings,
|
build_settings: BuildSettings,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ use gpui::{
|
||||||
};
|
};
|
||||||
use language::{Diagnostic, File as _};
|
use language::{Diagnostic, File as _};
|
||||||
use postage::watch;
|
use postage::watch;
|
||||||
use project::{ProjectPath, Worktree};
|
use project::{File, ProjectPath, Worktree};
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use text::{Point, Selection};
|
use text::{Point, Selection};
|
||||||
|
@ -66,8 +66,8 @@ impl ItemHandle for BufferItemHandle {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn project_path(&self, cx: &AppContext) -> Option<ProjectPath> {
|
fn project_path(&self, cx: &AppContext) -> Option<ProjectPath> {
|
||||||
self.0.read(cx).file(cx).map(|f| ProjectPath {
|
File::from_dyn(self.0.read(cx).file(cx)).map(|f| ProjectPath {
|
||||||
worktree_id: f.worktree_id(),
|
worktree_id: f.worktree_id(cx),
|
||||||
path: f.path().clone(),
|
path: f.path().clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -111,8 +111,8 @@ impl ItemView for Editor {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn project_path(&self, cx: &AppContext) -> Option<ProjectPath> {
|
fn project_path(&self, cx: &AppContext) -> Option<ProjectPath> {
|
||||||
self.buffer().read(cx).file(cx).map(|file| ProjectPath {
|
File::from_dyn(self.buffer().read(cx).file(cx)).map(|file| ProjectPath {
|
||||||
worktree_id: file.worktree_id(),
|
worktree_id: file.worktree_id(cx),
|
||||||
path: file.path().clone(),
|
path: file.path().clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,7 @@ struct BufferState {
|
||||||
buffer: ModelHandle<Buffer>,
|
buffer: ModelHandle<Buffer>,
|
||||||
last_version: clock::Global,
|
last_version: clock::Global,
|
||||||
last_parse_count: usize,
|
last_parse_count: usize,
|
||||||
|
last_selections_update_count: usize,
|
||||||
last_diagnostics_update_count: usize,
|
last_diagnostics_update_count: usize,
|
||||||
excerpts: Vec<ExcerptId>,
|
excerpts: Vec<ExcerptId>,
|
||||||
_subscriptions: [gpui::Subscription; 2],
|
_subscriptions: [gpui::Subscription; 2],
|
||||||
|
@ -637,6 +638,7 @@ impl MultiBuffer {
|
||||||
.or_insert_with(|| BufferState {
|
.or_insert_with(|| BufferState {
|
||||||
last_version: buffer_snapshot.version().clone(),
|
last_version: buffer_snapshot.version().clone(),
|
||||||
last_parse_count: buffer_snapshot.parse_count(),
|
last_parse_count: buffer_snapshot.parse_count(),
|
||||||
|
last_selections_update_count: buffer_snapshot.selections_update_count(),
|
||||||
last_diagnostics_update_count: buffer_snapshot.diagnostics_update_count(),
|
last_diagnostics_update_count: buffer_snapshot.diagnostics_update_count(),
|
||||||
excerpts: Default::default(),
|
excerpts: Default::default(),
|
||||||
_subscriptions: [
|
_subscriptions: [
|
||||||
|
@ -799,15 +801,23 @@ impl MultiBuffer {
|
||||||
let buffer = buffer_state.buffer.read(cx);
|
let buffer = buffer_state.buffer.read(cx);
|
||||||
let version = buffer.version();
|
let version = buffer.version();
|
||||||
let parse_count = buffer.parse_count();
|
let parse_count = buffer.parse_count();
|
||||||
|
let selections_update_count = buffer.selections_update_count();
|
||||||
let diagnostics_update_count = buffer.diagnostics_update_count();
|
let diagnostics_update_count = buffer.diagnostics_update_count();
|
||||||
|
|
||||||
let buffer_edited = version.gt(&buffer_state.last_version);
|
let buffer_edited = version.gt(&buffer_state.last_version);
|
||||||
let buffer_reparsed = parse_count > buffer_state.last_parse_count;
|
let buffer_reparsed = parse_count > buffer_state.last_parse_count;
|
||||||
|
let buffer_selections_updated =
|
||||||
|
selections_update_count > buffer_state.last_selections_update_count;
|
||||||
let buffer_diagnostics_updated =
|
let buffer_diagnostics_updated =
|
||||||
diagnostics_update_count > buffer_state.last_diagnostics_update_count;
|
diagnostics_update_count > buffer_state.last_diagnostics_update_count;
|
||||||
if buffer_edited || buffer_reparsed || buffer_diagnostics_updated {
|
if buffer_edited
|
||||||
|
|| buffer_reparsed
|
||||||
|
|| buffer_selections_updated
|
||||||
|
|| buffer_diagnostics_updated
|
||||||
|
{
|
||||||
buffer_state.last_version = version;
|
buffer_state.last_version = version;
|
||||||
buffer_state.last_parse_count = parse_count;
|
buffer_state.last_parse_count = parse_count;
|
||||||
|
buffer_state.last_selections_update_count = selections_update_count;
|
||||||
buffer_state.last_diagnostics_update_count = diagnostics_update_count;
|
buffer_state.last_diagnostics_update_count = diagnostics_update_count;
|
||||||
excerpts_to_edit.extend(
|
excerpts_to_edit.extend(
|
||||||
buffer_state
|
buffer_state
|
||||||
|
|
|
@ -12,7 +12,7 @@ use gpui::{
|
||||||
ViewContext, ViewHandle, WeakViewHandle,
|
ViewContext, ViewHandle, WeakViewHandle,
|
||||||
};
|
};
|
||||||
use postage::watch;
|
use postage::watch;
|
||||||
use project::{Project, ProjectPath};
|
use project::{Project, ProjectPath, WorktreeId};
|
||||||
use std::{
|
use std::{
|
||||||
cmp,
|
cmp,
|
||||||
path::Path,
|
path::Path,
|
||||||
|
@ -195,7 +195,7 @@ impl FileFinder {
|
||||||
.with_style(style.container);
|
.with_style(style.container);
|
||||||
|
|
||||||
let action = Select(ProjectPath {
|
let action = Select(ProjectPath {
|
||||||
worktree_id: path_match.worktree_id,
|
worktree_id: WorktreeId::from_usize(path_match.worktree_id),
|
||||||
path: path_match.path.clone(),
|
path: path_match.path.clone(),
|
||||||
});
|
});
|
||||||
EventHandler::new(container.boxed())
|
EventHandler::new(container.boxed())
|
||||||
|
@ -370,7 +370,7 @@ impl FileFinder {
|
||||||
fn confirm(&mut self, _: &Confirm, cx: &mut ViewContext<Self>) {
|
fn confirm(&mut self, _: &Confirm, cx: &mut ViewContext<Self>) {
|
||||||
if let Some(m) = self.matches.get(self.selected_index()) {
|
if let Some(m) = self.matches.get(self.selected_index()) {
|
||||||
cx.emit(Event::Selected(ProjectPath {
|
cx.emit(Event::Selected(ProjectPath {
|
||||||
worktree_id: m.worktree_id,
|
worktree_id: WorktreeId::from_usize(m.worktree_id),
|
||||||
path: m.path.clone(),
|
path: m.path.clone(),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,6 +67,7 @@ pub struct Buffer {
|
||||||
parse_count: usize,
|
parse_count: usize,
|
||||||
remote_selections: TreeMap<ReplicaId, Arc<[Selection<Anchor>]>>,
|
remote_selections: TreeMap<ReplicaId, Arc<[Selection<Anchor>]>>,
|
||||||
diagnostics: DiagnosticSet,
|
diagnostics: DiagnosticSet,
|
||||||
|
selections_update_count: usize,
|
||||||
diagnostics_update_count: usize,
|
diagnostics_update_count: usize,
|
||||||
language_server: Option<LanguageServerState>,
|
language_server: Option<LanguageServerState>,
|
||||||
deferred_ops: OperationQueue<Operation>,
|
deferred_ops: OperationQueue<Operation>,
|
||||||
|
@ -80,6 +81,7 @@ pub struct BufferSnapshot {
|
||||||
diagnostics: DiagnosticSet,
|
diagnostics: DiagnosticSet,
|
||||||
remote_selections: TreeMap<ReplicaId, Arc<[Selection<Anchor>]>>,
|
remote_selections: TreeMap<ReplicaId, Arc<[Selection<Anchor>]>>,
|
||||||
diagnostics_update_count: usize,
|
diagnostics_update_count: usize,
|
||||||
|
selections_update_count: usize,
|
||||||
is_parsing: bool,
|
is_parsing: bool,
|
||||||
language: Option<Arc<Language>>,
|
language: Option<Arc<Language>>,
|
||||||
parse_count: usize,
|
parse_count: usize,
|
||||||
|
@ -148,10 +150,6 @@ pub enum Event {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait File {
|
pub trait File {
|
||||||
fn worktree_id(&self) -> usize;
|
|
||||||
|
|
||||||
fn entry_id(&self) -> Option<usize>;
|
|
||||||
|
|
||||||
fn mtime(&self) -> SystemTime;
|
fn mtime(&self) -> SystemTime;
|
||||||
|
|
||||||
/// Returns the path of this file relative to the worktree's root directory.
|
/// Returns the path of this file relative to the worktree's root directory.
|
||||||
|
@ -184,8 +182,6 @@ pub trait File {
|
||||||
|
|
||||||
fn buffer_removed(&self, buffer_id: u64, cx: &mut MutableAppContext);
|
fn buffer_removed(&self, buffer_id: u64, cx: &mut MutableAppContext);
|
||||||
|
|
||||||
fn boxed_clone(&self) -> Box<dyn File>;
|
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any;
|
fn as_any(&self) -> &dyn Any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,6 +362,7 @@ impl Buffer {
|
||||||
pending_autoindent: Default::default(),
|
pending_autoindent: Default::default(),
|
||||||
language: None,
|
language: None,
|
||||||
remote_selections: Default::default(),
|
remote_selections: Default::default(),
|
||||||
|
selections_update_count: 0,
|
||||||
diagnostics: Default::default(),
|
diagnostics: Default::default(),
|
||||||
diagnostics_update_count: 0,
|
diagnostics_update_count: 0,
|
||||||
language_server: None,
|
language_server: None,
|
||||||
|
@ -385,6 +382,7 @@ impl Buffer {
|
||||||
is_parsing: self.parsing_in_background,
|
is_parsing: self.parsing_in_background,
|
||||||
language: self.language.clone(),
|
language: self.language.clone(),
|
||||||
parse_count: self.parse_count,
|
parse_count: self.parse_count,
|
||||||
|
selections_update_count: self.selections_update_count,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -610,6 +608,10 @@ impl Buffer {
|
||||||
self.parse_count
|
self.parse_count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn selections_update_count(&self) -> usize {
|
||||||
|
self.selections_update_count
|
||||||
|
}
|
||||||
|
|
||||||
pub fn diagnostics_update_count(&self) -> usize {
|
pub fn diagnostics_update_count(&self) -> usize {
|
||||||
self.diagnostics_update_count
|
self.diagnostics_update_count
|
||||||
}
|
}
|
||||||
|
@ -1079,8 +1081,6 @@ impl Buffer {
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) {
|
) {
|
||||||
let lamport_timestamp = self.text.lamport_clock.tick();
|
let lamport_timestamp = self.text.lamport_clock.tick();
|
||||||
self.remote_selections
|
|
||||||
.insert(self.text.replica_id(), selections.clone());
|
|
||||||
self.send_operation(
|
self.send_operation(
|
||||||
Operation::UpdateSelections {
|
Operation::UpdateSelections {
|
||||||
replica_id: self.text.replica_id(),
|
replica_id: self.text.replica_id(),
|
||||||
|
@ -1348,6 +1348,7 @@ impl Buffer {
|
||||||
} => {
|
} => {
|
||||||
self.remote_selections.insert(replica_id, selections);
|
self.remote_selections.insert(replica_id, selections);
|
||||||
self.text.lamport_clock.observe(lamport_timestamp);
|
self.text.lamport_clock.observe(lamport_timestamp);
|
||||||
|
self.selections_update_count += 1;
|
||||||
}
|
}
|
||||||
Operation::RemoveSelections {
|
Operation::RemoveSelections {
|
||||||
replica_id,
|
replica_id,
|
||||||
|
@ -1355,6 +1356,7 @@ impl Buffer {
|
||||||
} => {
|
} => {
|
||||||
self.remote_selections.remove(&replica_id);
|
self.remote_selections.remove(&replica_id);
|
||||||
self.text.lamport_clock.observe(lamport_timestamp);
|
self.text.lamport_clock.observe(lamport_timestamp);
|
||||||
|
self.selections_update_count += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1760,6 +1762,10 @@ impl BufferSnapshot {
|
||||||
pub fn parse_count(&self) -> usize {
|
pub fn parse_count(&self) -> usize {
|
||||||
self.parse_count
|
self.parse_count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn selections_update_count(&self) -> usize {
|
||||||
|
self.selections_update_count
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for BufferSnapshot {
|
impl Clone for BufferSnapshot {
|
||||||
|
@ -1769,6 +1775,7 @@ impl Clone for BufferSnapshot {
|
||||||
tree: self.tree.clone(),
|
tree: self.tree.clone(),
|
||||||
remote_selections: self.remote_selections.clone(),
|
remote_selections: self.remote_selections.clone(),
|
||||||
diagnostics: self.diagnostics.clone(),
|
diagnostics: self.diagnostics.clone(),
|
||||||
|
selections_update_count: self.selections_update_count,
|
||||||
diagnostics_update_count: self.diagnostics_update_count,
|
diagnostics_update_count: self.diagnostics_update_count,
|
||||||
is_parsing: self.is_parsing,
|
is_parsing: self.is_parsing,
|
||||||
language: self.language.clone(),
|
language: self.language.clone(),
|
||||||
|
|
|
@ -59,14 +59,14 @@ pub struct Collaborator {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
ActiveEntryChanged(Option<ProjectEntry>),
|
ActiveEntryChanged(Option<ProjectEntry>),
|
||||||
WorktreeRemoved(usize),
|
WorktreeRemoved(WorktreeId),
|
||||||
DiskBasedDiagnosticsUpdated { worktree_id: usize },
|
DiskBasedDiagnosticsUpdated { worktree_id: WorktreeId },
|
||||||
DiagnosticsUpdated(ProjectPath),
|
DiagnosticsUpdated(ProjectPath),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
|
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
|
||||||
pub struct ProjectPath {
|
pub struct ProjectPath {
|
||||||
pub worktree_id: usize,
|
pub worktree_id: WorktreeId,
|
||||||
pub path: Arc<Path>,
|
pub path: Arc<Path>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ impl DiagnosticSummary {
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct ProjectEntry {
|
pub struct ProjectEntry {
|
||||||
pub worktree_id: usize,
|
pub worktree_id: WorktreeId,
|
||||||
pub entry_id: usize,
|
pub entry_id: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,7 +321,11 @@ impl Project {
|
||||||
&self.worktrees
|
&self.worktrees
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn worktree_for_id(&self, id: usize, cx: &AppContext) -> Option<ModelHandle<Worktree>> {
|
pub fn worktree_for_id(
|
||||||
|
&self,
|
||||||
|
id: WorktreeId,
|
||||||
|
cx: &AppContext,
|
||||||
|
) -> Option<ModelHandle<Worktree>> {
|
||||||
self.worktrees
|
self.worktrees
|
||||||
.iter()
|
.iter()
|
||||||
.find(|worktree| worktree.read(cx).id() == id)
|
.find(|worktree| worktree.read(cx).id() == id)
|
||||||
|
@ -479,13 +483,13 @@ impl Project {
|
||||||
cx.subscribe(&worktree, |_, worktree, event, cx| match event {
|
cx.subscribe(&worktree, |_, worktree, event, cx| match event {
|
||||||
worktree::Event::DiagnosticsUpdated(path) => {
|
worktree::Event::DiagnosticsUpdated(path) => {
|
||||||
cx.emit(Event::DiagnosticsUpdated(ProjectPath {
|
cx.emit(Event::DiagnosticsUpdated(ProjectPath {
|
||||||
worktree_id: worktree.id(),
|
worktree_id: worktree.read(cx).id(),
|
||||||
path: path.clone(),
|
path: path.clone(),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
worktree::Event::DiskBasedDiagnosticsUpdated => {
|
worktree::Event::DiskBasedDiagnosticsUpdated => {
|
||||||
cx.emit(Event::DiskBasedDiagnosticsUpdated {
|
cx.emit(Event::DiskBasedDiagnosticsUpdated {
|
||||||
worktree_id: worktree.id(),
|
worktree_id: worktree.read(cx).id(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -514,9 +518,9 @@ impl Project {
|
||||||
cx: &'a AppContext,
|
cx: &'a AppContext,
|
||||||
) -> impl Iterator<Item = (ProjectPath, DiagnosticSummary)> + 'a {
|
) -> impl Iterator<Item = (ProjectPath, DiagnosticSummary)> + 'a {
|
||||||
self.worktrees.iter().flat_map(move |worktree| {
|
self.worktrees.iter().flat_map(move |worktree| {
|
||||||
|
let worktree = worktree.read(cx);
|
||||||
let worktree_id = worktree.id();
|
let worktree_id = worktree.id();
|
||||||
worktree
|
worktree
|
||||||
.read(cx)
|
|
||||||
.diagnostic_summaries()
|
.diagnostic_summaries()
|
||||||
.map(move |(path, summary)| (ProjectPath { worktree_id, path }, summary))
|
.map(move |(path, summary)| (ProjectPath { worktree_id, path }, summary))
|
||||||
})
|
})
|
||||||
|
@ -634,9 +638,9 @@ impl Project {
|
||||||
_: Arc<Client>,
|
_: Arc<Client>,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
self.worktrees.retain(|worktree| {
|
let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
|
||||||
worktree.read(cx).as_remote().unwrap().remote_id() != envelope.payload.worktree_id
|
self.worktrees
|
||||||
});
|
.retain(|worktree| worktree.read(cx).as_remote().unwrap().id() != worktree_id);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -647,7 +651,8 @@ impl Project {
|
||||||
_: Arc<Client>,
|
_: Arc<Client>,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if let Some(worktree) = self.worktree_for_id(envelope.payload.worktree_id as usize, cx) {
|
let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
|
||||||
|
if let Some(worktree) = self.worktree_for_id(worktree_id, cx) {
|
||||||
worktree.update(cx, |worktree, cx| {
|
worktree.update(cx, |worktree, cx| {
|
||||||
let worktree = worktree.as_remote_mut().unwrap();
|
let worktree = worktree.as_remote_mut().unwrap();
|
||||||
worktree.update_from_remote(envelope, cx)
|
worktree.update_from_remote(envelope, cx)
|
||||||
|
@ -662,7 +667,8 @@ impl Project {
|
||||||
_: Arc<Client>,
|
_: Arc<Client>,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if let Some(worktree) = self.worktree_for_id(envelope.payload.worktree_id as usize, cx) {
|
let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
|
||||||
|
if let Some(worktree) = self.worktree_for_id(worktree_id, cx) {
|
||||||
worktree.update(cx, |worktree, cx| {
|
worktree.update(cx, |worktree, cx| {
|
||||||
worktree.handle_update_buffer(envelope, cx)
|
worktree.handle_update_buffer(envelope, cx)
|
||||||
})?;
|
})?;
|
||||||
|
@ -676,7 +682,8 @@ impl Project {
|
||||||
rpc: Arc<Client>,
|
rpc: Arc<Client>,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if let Some(worktree) = self.worktree_for_id(envelope.payload.worktree_id as usize, cx) {
|
let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
|
||||||
|
if let Some(worktree) = self.worktree_for_id(worktree_id, cx) {
|
||||||
worktree.update(cx, |worktree, cx| {
|
worktree.update(cx, |worktree, cx| {
|
||||||
worktree.handle_save_buffer(envelope, rpc, cx)
|
worktree.handle_save_buffer(envelope, rpc, cx)
|
||||||
})?;
|
})?;
|
||||||
|
@ -690,7 +697,8 @@ impl Project {
|
||||||
rpc: Arc<Client>,
|
rpc: Arc<Client>,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
if let Some(worktree) = self.worktree_for_id(envelope.payload.worktree_id as usize, cx) {
|
let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
|
||||||
|
if let Some(worktree) = self.worktree_for_id(worktree_id, cx) {
|
||||||
return worktree.update(cx, |worktree, cx| {
|
return worktree.update(cx, |worktree, cx| {
|
||||||
worktree.handle_open_buffer(envelope, rpc, cx)
|
worktree.handle_open_buffer(envelope, rpc, cx)
|
||||||
});
|
});
|
||||||
|
@ -705,7 +713,8 @@ impl Project {
|
||||||
rpc: Arc<Client>,
|
rpc: Arc<Client>,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
if let Some(worktree) = self.worktree_for_id(envelope.payload.worktree_id as usize, cx) {
|
let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
|
||||||
|
if let Some(worktree) = self.worktree_for_id(worktree_id, cx) {
|
||||||
worktree.update(cx, |worktree, cx| {
|
worktree.update(cx, |worktree, cx| {
|
||||||
worktree.handle_close_buffer(envelope, rpc, cx)
|
worktree.handle_close_buffer(envelope, rpc, cx)
|
||||||
})?;
|
})?;
|
||||||
|
@ -719,7 +728,8 @@ impl Project {
|
||||||
_: Arc<Client>,
|
_: Arc<Client>,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if let Some(worktree) = self.worktree_for_id(envelope.payload.worktree_id as usize, cx) {
|
let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
|
||||||
|
if let Some(worktree) = self.worktree_for_id(worktree_id, cx) {
|
||||||
worktree.update(cx, |worktree, cx| {
|
worktree.update(cx, |worktree, cx| {
|
||||||
worktree.handle_buffer_saved(envelope, cx)
|
worktree.handle_buffer_saved(envelope, cx)
|
||||||
})?;
|
})?;
|
||||||
|
@ -772,7 +782,7 @@ impl<'a> PathMatchCandidateSet<'a> for CandidateSet {
|
||||||
type Candidates = CandidateSetIter<'a>;
|
type Candidates = CandidateSetIter<'a>;
|
||||||
|
|
||||||
fn id(&self) -> usize {
|
fn id(&self) -> usize {
|
||||||
self.snapshot.id()
|
self.snapshot.id().to_usize()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn len(&self) -> usize {
|
fn len(&self) -> usize {
|
||||||
|
|
|
@ -59,6 +59,9 @@ enum ScanState {
|
||||||
Err(Arc<anyhow::Error>),
|
Err(Arc<anyhow::Error>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
|
||||||
|
pub struct WorktreeId(usize);
|
||||||
|
|
||||||
pub enum Worktree {
|
pub enum Worktree {
|
||||||
Local(LocalWorktree),
|
Local(LocalWorktree),
|
||||||
Remote(RemoteWorktree),
|
Remote(RemoteWorktree),
|
||||||
|
@ -170,7 +173,7 @@ impl Worktree {
|
||||||
let worktree = cx.update(|cx| {
|
let worktree = cx.update(|cx| {
|
||||||
cx.add_model(|cx: &mut ModelContext<Worktree>| {
|
cx.add_model(|cx: &mut ModelContext<Worktree>| {
|
||||||
let snapshot = Snapshot {
|
let snapshot = Snapshot {
|
||||||
id: remote_id as usize,
|
id: WorktreeId(remote_id as usize),
|
||||||
scan_id: 0,
|
scan_id: 0,
|
||||||
abs_path: Path::new("").into(),
|
abs_path: Path::new("").into(),
|
||||||
root_name,
|
root_name,
|
||||||
|
@ -213,7 +216,6 @@ impl Worktree {
|
||||||
|
|
||||||
Worktree::Remote(RemoteWorktree {
|
Worktree::Remote(RemoteWorktree {
|
||||||
project_id: project_remote_id,
|
project_id: project_remote_id,
|
||||||
remote_id,
|
|
||||||
replica_id,
|
replica_id,
|
||||||
snapshot,
|
snapshot,
|
||||||
snapshot_rx,
|
snapshot_rx,
|
||||||
|
@ -618,9 +620,9 @@ impl Worktree {
|
||||||
for (buffer_id, buffer) in open_buffers {
|
for (buffer_id, buffer) in open_buffers {
|
||||||
if let Some(buffer) = buffer.upgrade(cx) {
|
if let Some(buffer) = buffer.upgrade(cx) {
|
||||||
buffer.update(cx, |buffer, cx| {
|
buffer.update(cx, |buffer, cx| {
|
||||||
if let Some(old_file) = buffer.file() {
|
if let Some(old_file) = File::from_dyn(buffer.file()) {
|
||||||
let new_file = if let Some(entry) = old_file
|
let new_file = if let Some(entry) = old_file
|
||||||
.entry_id()
|
.entry_id
|
||||||
.and_then(|entry_id| self.entry_for_id(entry_id))
|
.and_then(|entry_id| self.entry_for_id(entry_id))
|
||||||
{
|
{
|
||||||
File {
|
File {
|
||||||
|
@ -789,16 +791,13 @@ impl Worktree {
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) {
|
) {
|
||||||
if let Some((project_id, worktree_id, rpc)) = match self {
|
if let Some((project_id, worktree_id, rpc)) = match self {
|
||||||
Worktree::Local(worktree) => worktree.share.as_ref().map(|share| {
|
Worktree::Local(worktree) => worktree
|
||||||
(
|
.share
|
||||||
share.project_id,
|
.as_ref()
|
||||||
worktree.id() as u64,
|
.map(|share| (share.project_id, worktree.id(), worktree.client.clone())),
|
||||||
worktree.client.clone(),
|
|
||||||
)
|
|
||||||
}),
|
|
||||||
Worktree::Remote(worktree) => Some((
|
Worktree::Remote(worktree) => Some((
|
||||||
worktree.project_id,
|
worktree.project_id,
|
||||||
worktree.remote_id,
|
worktree.snapshot.id(),
|
||||||
worktree.client.clone(),
|
worktree.client.clone(),
|
||||||
)),
|
)),
|
||||||
} {
|
} {
|
||||||
|
@ -806,7 +805,7 @@ impl Worktree {
|
||||||
if let Err(error) = rpc
|
if let Err(error) = rpc
|
||||||
.request(proto::UpdateBuffer {
|
.request(proto::UpdateBuffer {
|
||||||
project_id,
|
project_id,
|
||||||
worktree_id,
|
worktree_id: worktree_id.0 as u64,
|
||||||
buffer_id,
|
buffer_id,
|
||||||
operations: vec![language::proto::serialize_operation(&operation)],
|
operations: vec![language::proto::serialize_operation(&operation)],
|
||||||
})
|
})
|
||||||
|
@ -827,9 +826,33 @@ impl Worktree {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl WorktreeId {
|
||||||
|
pub fn from_usize(handle_id: usize) -> Self {
|
||||||
|
Self(handle_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn from_proto(id: u64) -> Self {
|
||||||
|
Self(id as usize)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_proto(&self) -> u64 {
|
||||||
|
self.0 as u64
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_usize(&self) -> usize {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for WorktreeId {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
self.0.fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Snapshot {
|
pub struct Snapshot {
|
||||||
id: usize,
|
id: WorktreeId,
|
||||||
scan_id: usize,
|
scan_id: usize,
|
||||||
abs_path: Arc<Path>,
|
abs_path: Arc<Path>,
|
||||||
root_name: String,
|
root_name: String,
|
||||||
|
@ -870,7 +893,6 @@ struct ShareState {
|
||||||
|
|
||||||
pub struct RemoteWorktree {
|
pub struct RemoteWorktree {
|
||||||
project_id: u64,
|
project_id: u64,
|
||||||
remote_id: u64,
|
|
||||||
snapshot: Snapshot,
|
snapshot: Snapshot,
|
||||||
snapshot_rx: watch::Receiver<Snapshot>,
|
snapshot_rx: watch::Receiver<Snapshot>,
|
||||||
client: Arc<Client>,
|
client: Arc<Client>,
|
||||||
|
@ -926,7 +948,7 @@ impl LocalWorktree {
|
||||||
let (mut last_scan_state_tx, last_scan_state_rx) = watch::channel_with(ScanState::Scanning);
|
let (mut last_scan_state_tx, last_scan_state_rx) = watch::channel_with(ScanState::Scanning);
|
||||||
let tree = cx.add_model(move |cx: &mut ModelContext<Worktree>| {
|
let tree = cx.add_model(move |cx: &mut ModelContext<Worktree>| {
|
||||||
let mut snapshot = Snapshot {
|
let mut snapshot = Snapshot {
|
||||||
id: cx.model_id(),
|
id: WorktreeId::from_usize(cx.model_id()),
|
||||||
scan_id: 0,
|
scan_id: 0,
|
||||||
abs_path,
|
abs_path,
|
||||||
root_name: root_name.clone(),
|
root_name: root_name.clone(),
|
||||||
|
@ -1114,12 +1136,12 @@ impl LocalWorktree {
|
||||||
path: &Path,
|
path: &Path,
|
||||||
cx: &mut ModelContext<Worktree>,
|
cx: &mut ModelContext<Worktree>,
|
||||||
) -> Option<ModelHandle<Buffer>> {
|
) -> Option<ModelHandle<Buffer>> {
|
||||||
let worktree_id = self.id();
|
let handle = cx.handle();
|
||||||
let mut result = None;
|
let mut result = None;
|
||||||
self.open_buffers.retain(|_buffer_id, buffer| {
|
self.open_buffers.retain(|_buffer_id, buffer| {
|
||||||
if let Some(buffer) = buffer.upgrade(cx.as_ref()) {
|
if let Some(buffer) = buffer.upgrade(cx) {
|
||||||
if let Some(file) = buffer.read(cx.as_ref()).file() {
|
if let Some(file) = File::from_dyn(buffer.read(cx).file()) {
|
||||||
if file.worktree_id() == worktree_id && file.path().as_ref() == path {
|
if file.worktree == handle && file.path().as_ref() == path {
|
||||||
result = Some(buffer);
|
result = Some(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1422,6 +1444,14 @@ impl Deref for LocalWorktree {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Deref for RemoteWorktree {
|
||||||
|
type Target = Snapshot;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.snapshot
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Debug for LocalWorktree {
|
impl fmt::Debug for LocalWorktree {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
self.snapshot.fmt(f)
|
self.snapshot.fmt(f)
|
||||||
|
@ -1429,10 +1459,6 @@ impl fmt::Debug for LocalWorktree {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RemoteWorktree {
|
impl RemoteWorktree {
|
||||||
pub fn remote_id(&self) -> u64 {
|
|
||||||
self.remote_id
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_open_buffer(
|
fn get_open_buffer(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &Path,
|
path: &Path,
|
||||||
|
@ -1442,8 +1468,8 @@ impl RemoteWorktree {
|
||||||
let mut existing_buffer = None;
|
let mut existing_buffer = None;
|
||||||
self.open_buffers.retain(|_buffer_id, buffer| {
|
self.open_buffers.retain(|_buffer_id, buffer| {
|
||||||
if let Some(buffer) = buffer.upgrade(cx.as_ref()) {
|
if let Some(buffer) = buffer.upgrade(cx.as_ref()) {
|
||||||
if let Some(file) = buffer.read(cx.as_ref()).file() {
|
if let Some(file) = File::from_dyn(buffer.read(cx).file()) {
|
||||||
if file.worktree_id() == handle.id() && file.path().as_ref() == path {
|
if file.worktree == handle && file.path().as_ref() == path {
|
||||||
existing_buffer = Some(buffer);
|
existing_buffer = Some(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1463,7 +1489,7 @@ impl RemoteWorktree {
|
||||||
let rpc = self.client.clone();
|
let rpc = self.client.clone();
|
||||||
let replica_id = self.replica_id;
|
let replica_id = self.replica_id;
|
||||||
let project_id = self.project_id;
|
let project_id = self.project_id;
|
||||||
let remote_worktree_id = self.remote_id;
|
let remote_worktree_id = self.id();
|
||||||
let root_path = self.snapshot.abs_path.clone();
|
let root_path = self.snapshot.abs_path.clone();
|
||||||
let path: Arc<Path> = Arc::from(path);
|
let path: Arc<Path> = Arc::from(path);
|
||||||
let path_string = path.to_string_lossy().to_string();
|
let path_string = path.to_string_lossy().to_string();
|
||||||
|
@ -1476,7 +1502,7 @@ impl RemoteWorktree {
|
||||||
let response = rpc
|
let response = rpc
|
||||||
.request(proto::OpenBuffer {
|
.request(proto::OpenBuffer {
|
||||||
project_id,
|
project_id,
|
||||||
worktree_id: remote_worktree_id as u64,
|
worktree_id: remote_worktree_id.to_proto(),
|
||||||
path: path_string,
|
path: path_string,
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -1571,14 +1597,14 @@ impl RemoteBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Snapshot {
|
impl Snapshot {
|
||||||
pub fn id(&self) -> usize {
|
pub fn id(&self) -> WorktreeId {
|
||||||
self.id
|
self.id
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_proto(&self) -> proto::Worktree {
|
pub fn to_proto(&self) -> proto::Worktree {
|
||||||
let root_name = self.root_name.clone();
|
let root_name = self.root_name.clone();
|
||||||
proto::Worktree {
|
proto::Worktree {
|
||||||
id: self.id as u64,
|
id: self.id.0 as u64,
|
||||||
root_name,
|
root_name,
|
||||||
entries: self
|
entries: self
|
||||||
.entries_by_path
|
.entries_by_path
|
||||||
|
@ -1954,14 +1980,6 @@ pub struct File {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl language::File for File {
|
impl language::File for File {
|
||||||
fn worktree_id(&self) -> usize {
|
|
||||||
self.worktree.id()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn entry_id(&self) -> Option<usize> {
|
|
||||||
self.entry_id
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mtime(&self) -> SystemTime {
|
fn mtime(&self) -> SystemTime {
|
||||||
self.mtime
|
self.mtime
|
||||||
}
|
}
|
||||||
|
@ -2007,7 +2025,7 @@ impl language::File for File {
|
||||||
version: clock::Global,
|
version: clock::Global,
|
||||||
cx: &mut MutableAppContext,
|
cx: &mut MutableAppContext,
|
||||||
) -> Task<Result<(clock::Global, SystemTime)>> {
|
) -> Task<Result<(clock::Global, SystemTime)>> {
|
||||||
let worktree_id = self.worktree.read(cx).id() as u64;
|
let worktree_id = self.worktree.read(cx).id().to_proto();
|
||||||
self.worktree.update(cx, |worktree, cx| match worktree {
|
self.worktree.update(cx, |worktree, cx| match worktree {
|
||||||
Worktree::Local(worktree) => {
|
Worktree::Local(worktree) => {
|
||||||
let rpc = worktree.client.clone();
|
let rpc = worktree.client.clone();
|
||||||
|
@ -2070,7 +2088,7 @@ impl language::File for File {
|
||||||
self.worktree.update(cx, |worktree, cx| {
|
self.worktree.update(cx, |worktree, cx| {
|
||||||
if let Worktree::Remote(worktree) = worktree {
|
if let Worktree::Remote(worktree) = worktree {
|
||||||
let project_id = worktree.project_id;
|
let project_id = worktree.project_id;
|
||||||
let worktree_id = worktree.remote_id;
|
let worktree_id = worktree.id().to_proto();
|
||||||
let rpc = worktree.client.clone();
|
let rpc = worktree.client.clone();
|
||||||
cx.background()
|
cx.background()
|
||||||
.spawn(async move {
|
.spawn(async move {
|
||||||
|
@ -2090,15 +2108,21 @@ impl language::File for File {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn boxed_clone(&self) -> Box<dyn language::File> {
|
|
||||||
Box::new(self.clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl File {
|
||||||
|
pub fn from_dyn(file: Option<&dyn language::File>) -> Option<&Self> {
|
||||||
|
file.and_then(|f| f.as_any().downcast_ref())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn worktree_id(&self, cx: &AppContext) -> WorktreeId {
|
||||||
|
self.worktree.read(cx).id()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Entry {
|
pub struct Entry {
|
||||||
pub id: usize,
|
pub id: usize,
|
||||||
|
@ -4031,7 +4055,7 @@ mod tests {
|
||||||
let fs = Arc::new(RealFs);
|
let fs = Arc::new(RealFs);
|
||||||
let next_entry_id = Arc::new(AtomicUsize::new(0));
|
let next_entry_id = Arc::new(AtomicUsize::new(0));
|
||||||
let mut initial_snapshot = Snapshot {
|
let mut initial_snapshot = Snapshot {
|
||||||
id: 0,
|
id: WorktreeId::from_usize(0),
|
||||||
scan_id: 0,
|
scan_id: 0,
|
||||||
abs_path: root_dir.path().into(),
|
abs_path: root_dir.path().into(),
|
||||||
entries_by_path: Default::default(),
|
entries_by_path: Default::default(),
|
||||||
|
|
|
@ -14,7 +14,7 @@ use gpui::{
|
||||||
ViewContext, ViewHandle, WeakViewHandle,
|
ViewContext, ViewHandle, WeakViewHandle,
|
||||||
};
|
};
|
||||||
use postage::watch;
|
use postage::watch;
|
||||||
use project::{Project, ProjectEntry, ProjectPath, Worktree};
|
use project::{Project, ProjectEntry, ProjectPath, Worktree, WorktreeId};
|
||||||
use std::{
|
use std::{
|
||||||
collections::{hash_map, HashMap},
|
collections::{hash_map, HashMap},
|
||||||
ffi::OsStr,
|
ffi::OsStr,
|
||||||
|
@ -26,7 +26,7 @@ pub struct ProjectPanel {
|
||||||
project: ModelHandle<Project>,
|
project: ModelHandle<Project>,
|
||||||
list: UniformListState,
|
list: UniformListState,
|
||||||
visible_entries: Vec<Vec<usize>>,
|
visible_entries: Vec<Vec<usize>>,
|
||||||
expanded_dir_ids: HashMap<usize, Vec<usize>>,
|
expanded_dir_ids: HashMap<WorktreeId, Vec<usize>>,
|
||||||
selection: Option<Selection>,
|
selection: Option<Selection>,
|
||||||
settings: watch::Receiver<Settings>,
|
settings: watch::Receiver<Settings>,
|
||||||
handle: WeakViewHandle<Self>,
|
handle: WeakViewHandle<Self>,
|
||||||
|
@ -34,7 +34,7 @@ pub struct ProjectPanel {
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
struct Selection {
|
struct Selection {
|
||||||
worktree_id: usize,
|
worktree_id: WorktreeId,
|
||||||
entry_id: usize,
|
entry_id: usize,
|
||||||
index: usize,
|
index: usize,
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,10 @@ pub fn init(cx: &mut MutableAppContext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
OpenedEntry { worktree_id: usize, entry_id: usize },
|
OpenedEntry {
|
||||||
|
worktree_id: WorktreeId,
|
||||||
|
entry_id: usize,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProjectPanel {
|
impl ProjectPanel {
|
||||||
|
@ -114,16 +117,16 @@ impl ProjectPanel {
|
||||||
this
|
this
|
||||||
});
|
});
|
||||||
cx.subscribe(&project_panel, move |workspace, _, event, cx| match event {
|
cx.subscribe(&project_panel, move |workspace, _, event, cx| match event {
|
||||||
Event::OpenedEntry {
|
&Event::OpenedEntry {
|
||||||
worktree_id,
|
worktree_id,
|
||||||
entry_id,
|
entry_id,
|
||||||
} => {
|
} => {
|
||||||
if let Some(worktree) = project.read(cx).worktree_for_id(*worktree_id, cx) {
|
if let Some(worktree) = project.read(cx).worktree_for_id(worktree_id, cx) {
|
||||||
if let Some(entry) = worktree.read(cx).entry_for_id(*entry_id) {
|
if let Some(entry) = worktree.read(cx).entry_for_id(entry_id) {
|
||||||
workspace
|
workspace
|
||||||
.open_entry(
|
.open_entry(
|
||||||
ProjectPath {
|
ProjectPath {
|
||||||
worktree_id: worktree.id(),
|
worktree_id,
|
||||||
path: entry.path.clone(),
|
path: entry.path.clone(),
|
||||||
},
|
},
|
||||||
cx,
|
cx,
|
||||||
|
@ -259,8 +262,8 @@ impl ProjectPanel {
|
||||||
|
|
||||||
fn select_first(&mut self, cx: &mut ViewContext<Self>) {
|
fn select_first(&mut self, cx: &mut ViewContext<Self>) {
|
||||||
if let Some(worktree) = self.project.read(cx).worktrees().first() {
|
if let Some(worktree) = self.project.read(cx).worktrees().first() {
|
||||||
let worktree_id = worktree.id();
|
|
||||||
let worktree = worktree.read(cx);
|
let worktree = worktree.read(cx);
|
||||||
|
let worktree_id = worktree.id();
|
||||||
if let Some(root_entry) = worktree.root_entry() {
|
if let Some(root_entry) = worktree.root_entry() {
|
||||||
self.selection = Some(Selection {
|
self.selection = Some(Selection {
|
||||||
worktree_id,
|
worktree_id,
|
||||||
|
@ -313,7 +316,7 @@ impl ProjectPanel {
|
||||||
|
|
||||||
fn update_visible_entries(
|
fn update_visible_entries(
|
||||||
&mut self,
|
&mut self,
|
||||||
new_selected_entry: Option<(usize, usize)>,
|
new_selected_entry: Option<(WorktreeId, usize)>,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) {
|
) {
|
||||||
let worktrees = self.project.read(cx).worktrees();
|
let worktrees = self.project.read(cx).worktrees();
|
||||||
|
@ -322,7 +325,7 @@ impl ProjectPanel {
|
||||||
let mut entry_ix = 0;
|
let mut entry_ix = 0;
|
||||||
for worktree in worktrees {
|
for worktree in worktrees {
|
||||||
let snapshot = worktree.read(cx).snapshot();
|
let snapshot = worktree.read(cx).snapshot();
|
||||||
let worktree_id = worktree.id();
|
let worktree_id = snapshot.id();
|
||||||
|
|
||||||
let expanded_dir_ids = match self.expanded_dir_ids.entry(worktree_id) {
|
let expanded_dir_ids = match self.expanded_dir_ids.entry(worktree_id) {
|
||||||
hash_map::Entry::Occupied(e) => e.into_mut(),
|
hash_map::Entry::Occupied(e) => e.into_mut(),
|
||||||
|
@ -342,7 +345,7 @@ impl ProjectPanel {
|
||||||
while let Some(item) = entry_iter.entry() {
|
while let Some(item) = entry_iter.entry() {
|
||||||
visible_worktree_entries.push(entry_iter.offset());
|
visible_worktree_entries.push(entry_iter.offset());
|
||||||
if let Some(new_selected_entry) = new_selected_entry {
|
if let Some(new_selected_entry) = new_selected_entry {
|
||||||
if new_selected_entry == (worktree.id(), item.id) {
|
if new_selected_entry == (worktree_id, item.id) {
|
||||||
self.selection = Some(Selection {
|
self.selection = Some(Selection {
|
||||||
worktree_id,
|
worktree_id,
|
||||||
entry_id: item.id,
|
entry_id: item.id,
|
||||||
|
@ -371,7 +374,12 @@ impl ProjectPanel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expand_entry(&mut self, worktree_id: usize, entry_id: usize, cx: &mut ViewContext<Self>) {
|
fn expand_entry(
|
||||||
|
&mut self,
|
||||||
|
worktree_id: WorktreeId,
|
||||||
|
entry_id: usize,
|
||||||
|
cx: &mut ViewContext<Self>,
|
||||||
|
) {
|
||||||
let project = self.project.read(cx);
|
let project = self.project.read(cx);
|
||||||
if let Some((worktree, expanded_dir_ids)) = project
|
if let Some((worktree, expanded_dir_ids)) = project
|
||||||
.worktree_for_id(worktree_id, cx)
|
.worktree_for_id(worktree_id, cx)
|
||||||
|
@ -417,12 +425,12 @@ impl ProjectPanel {
|
||||||
|
|
||||||
let end_ix = range.end.min(ix + visible_worktree_entries.len());
|
let end_ix = range.end.min(ix + visible_worktree_entries.len());
|
||||||
let worktree = &worktrees[worktree_ix];
|
let worktree = &worktrees[worktree_ix];
|
||||||
|
let snapshot = worktree.read(cx).snapshot();
|
||||||
let expanded_entry_ids = self
|
let expanded_entry_ids = self
|
||||||
.expanded_dir_ids
|
.expanded_dir_ids
|
||||||
.get(&worktree.id())
|
.get(&snapshot.id())
|
||||||
.map(Vec::as_slice)
|
.map(Vec::as_slice)
|
||||||
.unwrap_or(&[]);
|
.unwrap_or(&[]);
|
||||||
let snapshot = worktree.read(cx).snapshot();
|
|
||||||
let root_name = OsStr::new(snapshot.root_name());
|
let root_name = OsStr::new(snapshot.root_name());
|
||||||
let mut cursor = snapshot.entries(false);
|
let mut cursor = snapshot.entries(false);
|
||||||
|
|
||||||
|
@ -439,11 +447,11 @@ impl ProjectPanel {
|
||||||
is_dir: entry.is_dir(),
|
is_dir: entry.is_dir(),
|
||||||
is_expanded: expanded_entry_ids.binary_search(&entry.id).is_ok(),
|
is_expanded: expanded_entry_ids.binary_search(&entry.id).is_ok(),
|
||||||
is_selected: self.selection.map_or(false, |e| {
|
is_selected: self.selection.map_or(false, |e| {
|
||||||
e.worktree_id == worktree.id() && e.entry_id == entry.id
|
e.worktree_id == snapshot.id() && e.entry_id == entry.id
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
let entry = ProjectEntry {
|
let entry = ProjectEntry {
|
||||||
worktree_id: worktree.id(),
|
worktree_id: snapshot.id(),
|
||||||
entry_id: entry.id,
|
entry_id: entry.id,
|
||||||
};
|
};
|
||||||
callback(entry, details, cx);
|
callback(entry, details, cx);
|
||||||
|
@ -461,7 +469,7 @@ impl ProjectPanel {
|
||||||
) -> ElementBox {
|
) -> ElementBox {
|
||||||
let is_dir = details.is_dir;
|
let is_dir = details.is_dir;
|
||||||
MouseEventHandler::new::<Self, _, _, _>(
|
MouseEventHandler::new::<Self, _, _, _>(
|
||||||
(entry.worktree_id, entry.entry_id),
|
(entry.worktree_id.to_usize(), entry.entry_id),
|
||||||
cx,
|
cx,
|
||||||
|state, _| {
|
|state, _| {
|
||||||
let style = match (details.is_selected, state.hovered) {
|
let style = match (details.is_selected, state.hovered) {
|
||||||
|
@ -516,7 +524,7 @@ impl ProjectPanel {
|
||||||
if is_dir {
|
if is_dir {
|
||||||
cx.dispatch_action(ToggleExpanded(entry))
|
cx.dispatch_action(ToggleExpanded(entry))
|
||||||
} else {
|
} else {
|
||||||
cx.dispatch_action(Open(entry))
|
cx.dispatch_action(Open(dbg!(entry)))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
|
|
|
@ -619,10 +619,10 @@ impl Workspace {
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) -> Task<Result<ProjectPath>> {
|
) -> Task<Result<ProjectPath>> {
|
||||||
let entry = self.worktree_for_abs_path(abs_path, cx);
|
let entry = self.worktree_for_abs_path(abs_path, cx);
|
||||||
cx.spawn(|_, _| async move {
|
cx.spawn(|_, cx| async move {
|
||||||
let (worktree, path) = entry.await?;
|
let (worktree, path) = entry.await?;
|
||||||
Ok(ProjectPath {
|
Ok(ProjectPath {
|
||||||
worktree_id: worktree.id(),
|
worktree_id: worktree.read_with(&cx, |t, _| t.id()),
|
||||||
path: path.into(),
|
path: path.into(),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1252,7 +1252,7 @@ impl WorkspaceHandle for ViewHandle<Workspace> {
|
||||||
.worktrees(cx)
|
.worktrees(cx)
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|worktree| {
|
.flat_map(|worktree| {
|
||||||
let worktree_id = worktree.id();
|
let worktree_id = worktree.read(cx).id();
|
||||||
worktree.read(cx).files(true, 0).map(move |f| ProjectPath {
|
worktree.read(cx).files(true, 0).map(move |f| ProjectPath {
|
||||||
worktree_id,
|
worktree_id,
|
||||||
path: f.path.clone(),
|
path: f.path.clone(),
|
||||||
|
|
|
@ -3,7 +3,7 @@ authors = ["Nathan Sobo <nathansobo@gmail.com>"]
|
||||||
description = "The fast, collaborative code editor."
|
description = "The fast, collaborative code editor."
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
name = "zed"
|
name = "zed"
|
||||||
version = "0.9.0"
|
version = "0.11.0"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "zed"
|
name = "zed"
|
||||||
|
|
|
@ -556,7 +556,7 @@ mod tests {
|
||||||
workspace
|
workspace
|
||||||
.open_entry(
|
.open_entry(
|
||||||
ProjectPath {
|
ProjectPath {
|
||||||
worktree_id: worktree.id(),
|
worktree_id: worktree.read(cx).id(),
|
||||||
path: Path::new("the-new-name.rs").into(),
|
path: Path::new("the-new-name.rs").into(),
|
||||||
},
|
},
|
||||||
cx,
|
cx,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue