Merge pull request #1769 from zed-industries/breadcrumbs
Fix breadcrumbs
This commit is contained in:
commit
4ef69c8361
18 changed files with 105 additions and 40 deletions
|
@ -8,7 +8,7 @@ use collections::{BTreeMap, HashSet};
|
|||
use futures::StreamExt;
|
||||
use gpui::{AsyncAppContext, Entity, ModelContext, ModelHandle, MutableAppContext, Task};
|
||||
use project::Project;
|
||||
use std::sync::Arc;
|
||||
use std::{os::unix::prelude::OsStrExt, sync::Arc};
|
||||
use util::ResultExt;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
|
@ -389,6 +389,7 @@ impl Room {
|
|||
id: worktree.id().to_proto(),
|
||||
root_name: worktree.root_name().into(),
|
||||
visible: worktree.is_visible(),
|
||||
abs_path: worktree.abs_path().as_os_str().as_bytes().to_vec(),
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
|
|
|
@ -15,7 +15,7 @@ use editor::{
|
|||
self, ConfirmCodeAction, ConfirmCompletion, ConfirmRename, Editor, Redo, Rename, ToOffset,
|
||||
ToggleCodeActions, Undo,
|
||||
};
|
||||
use fs::{FakeFs, Fs as _, LineEnding};
|
||||
use fs::{FakeFs, Fs as _, HomeDir, LineEnding};
|
||||
use futures::{channel::mpsc, Future, StreamExt as _};
|
||||
use gpui::{
|
||||
executor::{self, Deterministic},
|
||||
|
@ -3038,7 +3038,7 @@ async fn test_references(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) {
|
|||
assert_eq!(references[1].buffer, references[0].buffer);
|
||||
assert_eq!(
|
||||
three_buffer.file().unwrap().full_path(cx),
|
||||
Path::new("three.rs")
|
||||
Path::new("/root/dir-2/three.rs")
|
||||
);
|
||||
|
||||
assert_eq!(references[0].range.to_offset(two_buffer), 24..27);
|
||||
|
@ -6130,6 +6130,8 @@ impl TestServer {
|
|||
|
||||
async fn create_client(&mut self, cx: &mut TestAppContext, name: &str) -> TestClient {
|
||||
cx.update(|cx| {
|
||||
cx.set_global(HomeDir(Path::new("/tmp/").to_path_buf()));
|
||||
|
||||
let mut settings = Settings::test(cx);
|
||||
settings.projects_online_by_default = false;
|
||||
cx.set_global(settings);
|
||||
|
|
|
@ -42,6 +42,7 @@ use std::{
|
|||
marker::PhantomData,
|
||||
net::SocketAddr,
|
||||
ops::{Deref, DerefMut},
|
||||
os::unix::prelude::OsStrExt,
|
||||
rc::Rc,
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering::SeqCst},
|
||||
|
@ -941,6 +942,7 @@ impl Server {
|
|||
id: *id,
|
||||
root_name: worktree.root_name.clone(),
|
||||
visible: worktree.visible,
|
||||
abs_path: worktree.abs_path.as_os_str().as_bytes().to_vec(),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
|
@ -989,6 +991,7 @@ impl Server {
|
|||
let message = proto::UpdateWorktree {
|
||||
project_id: project_id.to_proto(),
|
||||
worktree_id: *worktree_id,
|
||||
abs_path: worktree.abs_path.as_os_str().as_bytes().to_vec(),
|
||||
root_name: worktree.root_name.clone(),
|
||||
updated_entries: worktree.entries.values().cloned().collect(),
|
||||
removed_entries: Default::default(),
|
||||
|
|
|
@ -66,6 +66,7 @@ pub struct Collaborator {
|
|||
|
||||
#[derive(Default, Serialize)]
|
||||
pub struct Worktree {
|
||||
pub abs_path: PathBuf,
|
||||
pub root_name: String,
|
||||
pub visible: bool,
|
||||
#[serde(skip)]
|
||||
|
|
|
@ -1324,6 +1324,7 @@ impl EditorElement {
|
|||
line_height: f32,
|
||||
style: &EditorStyle,
|
||||
line_layouts: &[text_layout::Line],
|
||||
include_root: bool,
|
||||
cx: &mut LayoutContext,
|
||||
) -> (f32, Vec<BlockLayout>) {
|
||||
let editor = if let Some(editor) = self.view.upgrade(cx) {
|
||||
|
@ -1427,10 +1428,11 @@ impl EditorElement {
|
|||
let font_size =
|
||||
(style.text_scale_factor * self.style.text.font_size).round();
|
||||
|
||||
let path = buffer.resolve_file_path(cx, include_root);
|
||||
let mut filename = None;
|
||||
let mut parent_path = None;
|
||||
if let Some(file) = buffer.file() {
|
||||
let path = file.path();
|
||||
// Can't use .and_then() because `.file_name()` and `.parent()` return references :(
|
||||
if let Some(path) = path {
|
||||
filename = path.file_name().map(|f| f.to_string_lossy().to_string());
|
||||
parent_path =
|
||||
path.parent().map(|p| p.to_string_lossy().to_string() + "/");
|
||||
|
@ -1634,6 +1636,7 @@ impl Element for EditorElement {
|
|||
let mut highlighted_rows = None;
|
||||
let mut highlighted_ranges = Vec::new();
|
||||
let mut show_scrollbars = false;
|
||||
let mut include_root = false;
|
||||
self.update_view(cx.app, |view, cx| {
|
||||
let display_map = view.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
|
||||
|
@ -1706,6 +1709,11 @@ impl Element for EditorElement {
|
|||
}
|
||||
|
||||
show_scrollbars = view.show_scrollbars();
|
||||
include_root = view
|
||||
.project
|
||||
.as_ref()
|
||||
.map(|project| project.read(cx).visible_worktrees(cx).count() > 1)
|
||||
.unwrap_or_default()
|
||||
});
|
||||
|
||||
let line_number_layouts =
|
||||
|
@ -1745,6 +1753,7 @@ impl Element for EditorElement {
|
|||
line_height,
|
||||
&style,
|
||||
&line_layouts,
|
||||
include_root,
|
||||
cx,
|
||||
);
|
||||
|
||||
|
|
|
@ -532,21 +532,17 @@ impl Item for Editor {
|
|||
let buffer = multibuffer.buffer(buffer_id)?;
|
||||
|
||||
let buffer = buffer.read(cx);
|
||||
let filename = if let Some(file) = buffer.file() {
|
||||
if file.path().file_name().is_none()
|
||||
|| self
|
||||
.project
|
||||
let filename = buffer
|
||||
.snapshot()
|
||||
.resolve_file_path(
|
||||
cx,
|
||||
self.project
|
||||
.as_ref()
|
||||
.map(|project| project.read(cx).visible_worktrees(cx).count() > 1)
|
||||
.unwrap_or_default()
|
||||
{
|
||||
file.full_path(cx).to_string_lossy().to_string()
|
||||
} else {
|
||||
file.path().to_string_lossy().to_string()
|
||||
}
|
||||
} else {
|
||||
"untitled".to_string()
|
||||
};
|
||||
.unwrap_or_default(),
|
||||
)
|
||||
.map(|path| path.to_string_lossy().to_string())
|
||||
.unwrap_or_else(|| "untitled".to_string());
|
||||
|
||||
let mut breadcrumbs = vec![Label::new(filename, theme.breadcrumbs.text.clone()).boxed()];
|
||||
breadcrumbs.extend(symbols.into_iter().map(|symbol| {
|
||||
|
|
|
@ -13,6 +13,7 @@ use smol::io::{AsyncReadExt, AsyncWriteExt};
|
|||
use std::borrow::Cow;
|
||||
use std::cmp;
|
||||
use std::io::Write;
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
use std::{
|
||||
io,
|
||||
|
@ -92,6 +93,17 @@ impl LineEnding {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct HomeDir(pub PathBuf);
|
||||
|
||||
impl Deref for HomeDir {
|
||||
type Target = PathBuf;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
pub trait Fs: Send + Sync {
|
||||
async fn create_dir(&self, path: &Path) -> Result<()>;
|
||||
|
|
|
@ -2334,6 +2334,18 @@ impl BufferSnapshot {
|
|||
self.file.as_deref()
|
||||
}
|
||||
|
||||
pub fn resolve_file_path(&self, cx: &AppContext, include_root: bool) -> Option<PathBuf> {
|
||||
if let Some(file) = self.file() {
|
||||
if file.path().file_name().is_none() || include_root {
|
||||
Some(file.full_path(cx))
|
||||
} else {
|
||||
Some(file.path().to_path_buf())
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn file_update_count(&self) -> usize {
|
||||
self.file_update_count
|
||||
}
|
||||
|
|
|
@ -583,7 +583,10 @@ impl Project {
|
|||
cx: &mut gpui::TestAppContext,
|
||||
) -> ModelHandle<Project> {
|
||||
if !cx.read(|cx| cx.has_global::<Settings>()) {
|
||||
cx.update(|cx| cx.set_global(Settings::test(cx)));
|
||||
cx.update(|cx| {
|
||||
cx.set_global(Settings::test(cx));
|
||||
cx.set_global(HomeDir(Path::new("/tmp/").to_path_buf()))
|
||||
});
|
||||
}
|
||||
|
||||
let languages = Arc::new(LanguageRegistry::test());
|
||||
|
|
|
@ -2164,6 +2164,7 @@ async fn test_rescan_and_remote_updates(
|
|||
proto::WorktreeMetadata {
|
||||
id: initial_snapshot.id().to_proto(),
|
||||
root_name: initial_snapshot.root_name().into(),
|
||||
abs_path: initial_snapshot.abs_path().as_os_str().as_bytes().to_vec(),
|
||||
visible: true,
|
||||
},
|
||||
rpc.clone(),
|
||||
|
|
|
@ -5,8 +5,8 @@ use anyhow::{anyhow, Context, Result};
|
|||
use client::{proto, Client};
|
||||
use clock::ReplicaId;
|
||||
use collections::{HashMap, VecDeque};
|
||||
use fs::LineEnding;
|
||||
use fs::{repository::GitRepository, Fs};
|
||||
use fs::{HomeDir, LineEnding};
|
||||
use futures::{
|
||||
channel::{
|
||||
mpsc::{self, UnboundedSender},
|
||||
|
@ -87,6 +87,7 @@ pub struct RemoteWorktree {
|
|||
#[derive(Clone)]
|
||||
pub struct Snapshot {
|
||||
id: WorktreeId,
|
||||
abs_path: Arc<Path>,
|
||||
root_name: String,
|
||||
root_char_bag: CharBag,
|
||||
entries_by_path: SumTree<Entry>,
|
||||
|
@ -118,7 +119,6 @@ impl std::fmt::Debug for GitRepositoryEntry {
|
|||
}
|
||||
|
||||
pub struct LocalSnapshot {
|
||||
abs_path: Arc<Path>,
|
||||
ignores_by_parent_abs_path: HashMap<Arc<Path>, (Arc<Gitignore>, usize)>,
|
||||
git_repositories: Vec<GitRepositoryEntry>,
|
||||
removed_entry_ids: HashMap<u64, ProjectEntryId>,
|
||||
|
@ -130,7 +130,6 @@ pub struct LocalSnapshot {
|
|||
impl Clone for LocalSnapshot {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
abs_path: self.abs_path.clone(),
|
||||
ignores_by_parent_abs_path: self.ignores_by_parent_abs_path.clone(),
|
||||
git_repositories: self.git_repositories.iter().cloned().collect(),
|
||||
removed_entry_ids: self.removed_entry_ids.clone(),
|
||||
|
@ -221,8 +220,11 @@ impl Worktree {
|
|||
.collect();
|
||||
let root_name = worktree.root_name.clone();
|
||||
let visible = worktree.visible;
|
||||
|
||||
let abs_path = PathBuf::from(OsString::from_vec(worktree.abs_path));
|
||||
let snapshot = Snapshot {
|
||||
id: WorktreeId(remote_id as usize),
|
||||
abs_path: Arc::from(abs_path.deref()),
|
||||
root_name,
|
||||
root_char_bag,
|
||||
entries_by_path: Default::default(),
|
||||
|
@ -372,6 +374,13 @@ impl Worktree {
|
|||
Self::Remote(worktree) => worktree.poll_snapshot(cx),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn abs_path(&self) -> Arc<Path> {
|
||||
match self {
|
||||
Worktree::Local(worktree) => worktree.abs_path.clone(),
|
||||
Worktree::Remote(worktree) => worktree.abs_path.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LocalWorktree {
|
||||
|
@ -402,13 +411,13 @@ impl LocalWorktree {
|
|||
watch::channel_with(ScanState::Initializing);
|
||||
let tree = cx.add_model(move |cx: &mut ModelContext<Worktree>| {
|
||||
let mut snapshot = LocalSnapshot {
|
||||
abs_path,
|
||||
ignores_by_parent_abs_path: Default::default(),
|
||||
git_repositories: Default::default(),
|
||||
removed_entry_ids: Default::default(),
|
||||
next_entry_id,
|
||||
snapshot: Snapshot {
|
||||
id: WorktreeId::from_usize(cx.model_id()),
|
||||
abs_path,
|
||||
root_name: root_name.clone(),
|
||||
root_char_bag,
|
||||
entries_by_path: Default::default(),
|
||||
|
@ -647,6 +656,7 @@ impl LocalWorktree {
|
|||
id: self.id().to_proto(),
|
||||
root_name: self.root_name().to_string(),
|
||||
visible: self.visible,
|
||||
abs_path: self.abs_path().as_os_str().as_bytes().to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -980,6 +990,7 @@ impl LocalWorktree {
|
|||
let update = proto::UpdateWorktree {
|
||||
project_id,
|
||||
worktree_id,
|
||||
abs_path: snapshot.abs_path().as_os_str().as_bytes().to_vec(),
|
||||
root_name: snapshot.root_name().to_string(),
|
||||
updated_entries: snapshot
|
||||
.entries_by_path
|
||||
|
@ -1389,6 +1400,7 @@ impl LocalSnapshot {
|
|||
proto::UpdateWorktree {
|
||||
project_id,
|
||||
worktree_id: self.id().to_proto(),
|
||||
abs_path: self.abs_path().as_os_str().as_bytes().to_vec(),
|
||||
root_name,
|
||||
updated_entries: self.entries_by_path.iter().map(Into::into).collect(),
|
||||
removed_entries: Default::default(),
|
||||
|
@ -1456,6 +1468,7 @@ impl LocalSnapshot {
|
|||
proto::UpdateWorktree {
|
||||
project_id,
|
||||
worktree_id,
|
||||
abs_path: self.abs_path().as_os_str().as_bytes().to_vec(),
|
||||
root_name: self.root_name().to_string(),
|
||||
updated_entries,
|
||||
removed_entries,
|
||||
|
@ -1839,10 +1852,25 @@ impl language::File for File {
|
|||
|
||||
fn full_path(&self, cx: &AppContext) -> PathBuf {
|
||||
let mut full_path = PathBuf::new();
|
||||
full_path.push(self.worktree.read(cx).root_name());
|
||||
let worktree = self.worktree.read(cx);
|
||||
|
||||
if worktree.is_visible() {
|
||||
full_path.push(worktree.root_name());
|
||||
} else {
|
||||
let path = worktree.abs_path();
|
||||
|
||||
if worktree.is_local() && path.starts_with(cx.global::<HomeDir>().as_path()) {
|
||||
full_path.push("~");
|
||||
full_path.push(path.strip_prefix(cx.global::<HomeDir>().as_path()).unwrap());
|
||||
} else {
|
||||
full_path.push(path)
|
||||
}
|
||||
}
|
||||
|
||||
if self.path.components().next().is_some() {
|
||||
full_path.push(&self.path);
|
||||
}
|
||||
|
||||
full_path
|
||||
}
|
||||
|
||||
|
@ -3455,7 +3483,6 @@ mod tests {
|
|||
let fs = Arc::new(RealFs);
|
||||
let next_entry_id = Arc::new(AtomicUsize::new(0));
|
||||
let mut initial_snapshot = LocalSnapshot {
|
||||
abs_path: root_dir.path().into(),
|
||||
removed_entry_ids: Default::default(),
|
||||
ignores_by_parent_abs_path: Default::default(),
|
||||
git_repositories: Default::default(),
|
||||
|
@ -3464,6 +3491,7 @@ mod tests {
|
|||
id: WorktreeId::from_usize(0),
|
||||
entries_by_path: Default::default(),
|
||||
entries_by_id: Default::default(),
|
||||
abs_path: root_dir.path().into(),
|
||||
root_name: Default::default(),
|
||||
root_char_bag: Default::default(),
|
||||
scan_id: 0,
|
||||
|
|
|
@ -266,6 +266,7 @@ message UpdateWorktree {
|
|||
repeated uint64 removed_entries = 5;
|
||||
uint64 scan_id = 6;
|
||||
bool is_last_update = 7;
|
||||
bytes abs_path = 8;
|
||||
}
|
||||
|
||||
message UpdateWorktreeExtensions {
|
||||
|
@ -1061,6 +1062,7 @@ message WorktreeMetadata {
|
|||
uint64 id = 1;
|
||||
string root_name = 2;
|
||||
bool visible = 3;
|
||||
bytes abs_path = 4;
|
||||
}
|
||||
|
||||
message UpdateDiffBase {
|
||||
|
|
|
@ -435,6 +435,7 @@ pub fn split_worktree_update(
|
|||
project_id: message.project_id,
|
||||
worktree_id: message.worktree_id,
|
||||
root_name: message.root_name.clone(),
|
||||
abs_path: message.abs_path.clone(),
|
||||
updated_entries,
|
||||
removed_entries: mem::take(&mut message.removed_entries),
|
||||
scan_id: message.scan_id,
|
||||
|
|
|
@ -6,4 +6,4 @@ pub use conn::Connection;
|
|||
pub use peer::*;
|
||||
mod macros;
|
||||
|
||||
pub const PROTOCOL_VERSION: u32 = 36;
|
||||
pub const PROTOCOL_VERSION: u32 = 37;
|
|
@ -38,18 +38,7 @@ pub struct SendKeystroke(String);
|
|||
|
||||
actions!(
|
||||
terminal,
|
||||
[
|
||||
Up,
|
||||
Down,
|
||||
CtrlC,
|
||||
Escape,
|
||||
Enter,
|
||||
Clear,
|
||||
Copy,
|
||||
Paste,
|
||||
ShowCharacterPalette,
|
||||
SearchTest
|
||||
]
|
||||
[Clear, Copy, Paste, ShowCharacterPalette, SearchTest]
|
||||
);
|
||||
|
||||
impl_actions!(terminal, [SendText, SendKeystroke]);
|
||||
|
|
|
@ -927,6 +927,9 @@ impl From<&dyn NotificationHandle> for AnyViewHandle {
|
|||
impl AppState {
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub fn test(cx: &mut MutableAppContext) -> Arc<Self> {
|
||||
use fs::HomeDir;
|
||||
|
||||
cx.set_global(HomeDir(Path::new("/tmp/").to_path_buf()));
|
||||
let settings = Settings::test(cx);
|
||||
cx.set_global(settings);
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ use isahc::{config::Configurable, Request};
|
|||
use language::LanguageRegistry;
|
||||
use log::LevelFilter;
|
||||
use parking_lot::Mutex;
|
||||
use project::{Fs, ProjectStore};
|
||||
use project::{Fs, HomeDir, ProjectStore};
|
||||
use serde_json::json;
|
||||
use settings::{
|
||||
self, settings_file::SettingsFile, KeymapFileContent, Settings, SettingsFileContent,
|
||||
|
@ -99,6 +99,8 @@ fn main() {
|
|||
|
||||
let (settings_file_content, keymap_file) = cx.background().block(config_files).unwrap();
|
||||
|
||||
cx.set_global(HomeDir(zed::paths::HOME.to_path_buf()));
|
||||
|
||||
//Setup settings global before binding actions
|
||||
cx.set_global(SettingsFile::new(
|
||||
&*zed::paths::SETTINGS,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref HOME: PathBuf = dirs::home_dir().expect("failed to determine home directory");
|
||||
pub static ref HOME: PathBuf = dirs::home_dir().expect("failed to determine home directory");
|
||||
pub static ref CONFIG_DIR: PathBuf = HOME.join(".config").join("zed");
|
||||
pub static ref LOGS_DIR: PathBuf = HOME.join("Library/Logs/Zed");
|
||||
pub static ref LANGUAGES_DIR: PathBuf = HOME.join("Library/Application Support/Zed/languages");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue