Remove separator! macro and make path! handle relative paths (#32527)

Release Notes:

- N/A
This commit is contained in:
Michael Sloan 2025-06-13 00:32:29 -06:00 committed by GitHub
parent babf846ef9
commit 9cc82212b5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 302 additions and 343 deletions

View file

@ -1066,7 +1066,7 @@ mod tests {
use serde_json::json;
use settings::SettingsStore;
use std::{ops::Deref, rc::Rc};
use util::{path, separator};
use util::path;
use workspace::{AppState, Item};
#[test]
@ -1217,14 +1217,14 @@ mod tests {
let mut cx = VisualTestContext::from_window(*window.deref(), cx);
let paths = vec![
separator!("a/one.txt"),
separator!("a/two.txt"),
separator!("a/three.txt"),
separator!("a/four.txt"),
separator!("b/five.txt"),
separator!("b/six.txt"),
separator!("b/seven.txt"),
separator!("b/eight.txt"),
path!("a/one.txt"),
path!("a/two.txt"),
path!("a/three.txt"),
path!("a/four.txt"),
path!("b/five.txt"),
path!("b/six.txt"),
path!("b/seven.txt"),
path!("b/eight.txt"),
];
let mut opened_editors = Vec::new();

View file

@ -582,7 +582,7 @@ mod test {
use serde_json::json;
use settings::SettingsStore;
use smol::stream::StreamExt;
use util::{path, separator};
use util::path;
use super::collect_files;
@ -627,7 +627,7 @@ mod test {
.await
.unwrap();
assert!(result_1.text.starts_with(separator!("root/dir")));
assert!(result_1.text.starts_with(path!("root/dir")));
// 4 files + 2 directories
assert_eq!(result_1.sections.len(), 6);
@ -643,7 +643,7 @@ mod test {
cx.update(|cx| collect_files(project.clone(), &["root/dir*".to_string()], cx).boxed());
let result = SlashCommandOutput::from_event_stream(result).await.unwrap();
assert!(result.text.starts_with(separator!("root/dir")));
assert!(result.text.starts_with(path!("root/dir")));
// 5 files + 2 directories
assert_eq!(result.sections.len(), 7);
@ -691,24 +691,20 @@ mod test {
.unwrap();
// Sanity check
assert!(result.text.starts_with(separator!("zed/assets/themes\n")));
assert!(result.text.starts_with(path!("zed/assets/themes\n")));
assert_eq!(result.sections.len(), 7);
// Ensure that full file paths are included in the real output
assert!(
result
.text
.contains(separator!("zed/assets/themes/andromeda/LICENSE"))
.contains(path!("zed/assets/themes/andromeda/LICENSE"))
);
assert!(result.text.contains(path!("zed/assets/themes/ayu/LICENSE")));
assert!(
result
.text
.contains(separator!("zed/assets/themes/ayu/LICENSE"))
);
assert!(
result
.text
.contains(separator!("zed/assets/themes/summercamp/LICENSE"))
.contains(path!("zed/assets/themes/summercamp/LICENSE"))
);
assert_eq!(result.sections[5].label, "summercamp");
@ -716,17 +712,17 @@ mod test {
// Ensure that things are in descending order, with properly relativized paths
assert_eq!(
result.sections[0].label,
separator!("zed/assets/themes/andromeda/LICENSE")
path!("zed/assets/themes/andromeda/LICENSE")
);
assert_eq!(result.sections[1].label, "andromeda");
assert_eq!(
result.sections[2].label,
separator!("zed/assets/themes/ayu/LICENSE")
path!("zed/assets/themes/ayu/LICENSE")
);
assert_eq!(result.sections[3].label, "ayu");
assert_eq!(
result.sections[4].label,
separator!("zed/assets/themes/summercamp/LICENSE")
path!("zed/assets/themes/summercamp/LICENSE")
);
// Ensure that the project lasts until after the last await
@ -767,31 +763,28 @@ mod test {
.await
.unwrap();
assert!(result.text.starts_with(separator!("zed/assets/themes\n")));
assert_eq!(
result.sections[0].label,
separator!("zed/assets/themes/LICENSE")
);
assert!(result.text.starts_with(path!("zed/assets/themes\n")));
assert_eq!(result.sections[0].label, path!("zed/assets/themes/LICENSE"));
assert_eq!(
result.sections[1].label,
separator!("zed/assets/themes/summercamp/LICENSE")
path!("zed/assets/themes/summercamp/LICENSE")
);
assert_eq!(
result.sections[2].label,
separator!("zed/assets/themes/summercamp/subdir/LICENSE")
path!("zed/assets/themes/summercamp/subdir/LICENSE")
);
assert_eq!(
result.sections[3].label,
separator!("zed/assets/themes/summercamp/subdir/subsubdir/LICENSE")
path!("zed/assets/themes/summercamp/subdir/subsubdir/LICENSE")
);
assert_eq!(result.sections[4].label, "subsubdir");
assert_eq!(result.sections[5].label, "subdir");
assert_eq!(result.sections[6].label, "summercamp");
assert_eq!(result.sections[7].label, separator!("zed/assets/themes"));
assert_eq!(result.sections[7].label, path!("zed/assets/themes"));
assert_eq!(
result.text,
separator!(
path!(
"zed/assets/themes\n```zed/assets/themes/LICENSE\n1\n```\n\nsummercamp\n```zed/assets/themes/summercamp/LICENSE\n1\n```\n\nsubdir\n```zed/assets/themes/summercamp/subdir/LICENSE\n1\n```\n\nsubsubdir\n```zed/assets/themes/summercamp/subdir/subsubdir/LICENSE\n3\n```\n\n"
)
);

View file

@ -51,7 +51,7 @@ use std::{
time::Duration,
};
use unindent::Unindent as _;
use util::{path, separator, uri};
use util::{path, uri};
use workspace::Pane;
#[ctor::ctor]
@ -1676,13 +1676,13 @@ async fn test_project_reconnect(
.map(|p| p.to_str().unwrap())
.collect::<Vec<_>>(),
vec![
separator!("a.txt"),
separator!("b.txt"),
separator!("subdir2"),
separator!("subdir2/f.txt"),
separator!("subdir2/g.txt"),
separator!("subdir2/h.txt"),
separator!("subdir2/i.txt")
path!("a.txt"),
path!("b.txt"),
path!("subdir2"),
path!("subdir2/f.txt"),
path!("subdir2/g.txt"),
path!("subdir2/h.txt"),
path!("subdir2/i.txt")
]
);
assert!(worktree_a3.read(cx).has_update_observer());
@ -1709,13 +1709,13 @@ async fn test_project_reconnect(
.map(|p| p.to_str().unwrap())
.collect::<Vec<_>>(),
vec![
separator!("a.txt"),
separator!("b.txt"),
separator!("subdir2"),
separator!("subdir2/f.txt"),
separator!("subdir2/g.txt"),
separator!("subdir2/h.txt"),
separator!("subdir2/i.txt")
path!("a.txt"),
path!("b.txt"),
path!("subdir2"),
path!("subdir2/f.txt"),
path!("subdir2/g.txt"),
path!("subdir2/h.txt"),
path!("subdir2/i.txt")
]
);
assert!(project.worktree_for_id(worktree2_id, cx).is_none());
@ -1806,13 +1806,13 @@ async fn test_project_reconnect(
.map(|p| p.to_str().unwrap())
.collect::<Vec<_>>(),
vec![
separator!("a.txt"),
separator!("b.txt"),
separator!("subdir2"),
separator!("subdir2/f.txt"),
separator!("subdir2/g.txt"),
separator!("subdir2/h.txt"),
separator!("subdir2/j.txt")
path!("a.txt"),
path!("b.txt"),
path!("subdir2"),
path!("subdir2/f.txt"),
path!("subdir2/g.txt"),
path!("subdir2/h.txt"),
path!("subdir2/j.txt")
]
);
assert!(project.worktree_for_id(worktree2_id, cx).is_none());
@ -3315,13 +3315,13 @@ async fn test_fs_operations(
.map(|p| p.to_string_lossy())
.collect::<Vec<_>>(),
[
separator!("DIR"),
separator!("DIR/SUBDIR"),
separator!("DIR/SUBDIR/f.txt"),
separator!("DIR/e.txt"),
separator!("a.txt"),
separator!("b.txt"),
separator!("d.txt")
path!("DIR"),
path!("DIR/SUBDIR"),
path!("DIR/SUBDIR/f.txt"),
path!("DIR/e.txt"),
path!("a.txt"),
path!("b.txt"),
path!("d.txt")
]
);
});
@ -3333,13 +3333,13 @@ async fn test_fs_operations(
.map(|p| p.to_string_lossy())
.collect::<Vec<_>>(),
[
separator!("DIR"),
separator!("DIR/SUBDIR"),
separator!("DIR/SUBDIR/f.txt"),
separator!("DIR/e.txt"),
separator!("a.txt"),
separator!("b.txt"),
separator!("d.txt")
path!("DIR"),
path!("DIR/SUBDIR"),
path!("DIR/SUBDIR/f.txt"),
path!("DIR/e.txt"),
path!("a.txt"),
path!("b.txt"),
path!("d.txt")
]
);
});
@ -3359,14 +3359,14 @@ async fn test_fs_operations(
.map(|p| p.to_string_lossy())
.collect::<Vec<_>>(),
[
separator!("DIR"),
separator!("DIR/SUBDIR"),
separator!("DIR/SUBDIR/f.txt"),
separator!("DIR/e.txt"),
separator!("a.txt"),
separator!("b.txt"),
separator!("d.txt"),
separator!("f.txt")
path!("DIR"),
path!("DIR/SUBDIR"),
path!("DIR/SUBDIR/f.txt"),
path!("DIR/e.txt"),
path!("a.txt"),
path!("b.txt"),
path!("d.txt"),
path!("f.txt")
]
);
});
@ -3378,14 +3378,14 @@ async fn test_fs_operations(
.map(|p| p.to_string_lossy())
.collect::<Vec<_>>(),
[
separator!("DIR"),
separator!("DIR/SUBDIR"),
separator!("DIR/SUBDIR/f.txt"),
separator!("DIR/e.txt"),
separator!("a.txt"),
separator!("b.txt"),
separator!("d.txt"),
separator!("f.txt")
path!("DIR"),
path!("DIR/SUBDIR"),
path!("DIR/SUBDIR/f.txt"),
path!("DIR/e.txt"),
path!("a.txt"),
path!("b.txt"),
path!("d.txt"),
path!("f.txt")
]
);
});

View file

@ -30,7 +30,7 @@ use rpc::proto;
use serde_json::json;
use settings::SettingsStore;
use std::{path::Path, sync::Arc};
use util::{path, separator};
use util::path;
#[gpui::test(iterations = 10)]
async fn test_sharing_an_ssh_remote_project(
@ -198,7 +198,7 @@ async fn test_sharing_an_ssh_remote_project(
.path()
.to_string_lossy()
.to_string(),
separator!("src/renamed.rs").to_string()
path!("src/renamed.rs").to_string()
);
});
}

View file

@ -209,7 +209,7 @@ async fn test_matching_paths(cx: &mut TestAppContext) {
"bandana",
"./bandana",
".\\bandana",
util::separator!("a/bandana"),
util::path!("a/bandana"),
"b/bandana",
"b\\bandana",
" bandana",
@ -230,7 +230,7 @@ async fn test_matching_paths(cx: &mut TestAppContext) {
assert_eq!(
picker.delegate.matches.len(),
// existence of CreateNew option depends on whether path already exists
if bandana_query == util::separator!("a/bandana") {
if bandana_query == util::path!("a/bandana") {
1
} else {
2

View file

@ -42,7 +42,6 @@ use unindent::Unindent as _;
use util::{
TryFutureExt as _, assert_set_eq, maybe, path,
paths::PathMatcher,
separator,
test::{TempTree, marked_text_offsets},
uri,
};
@ -375,7 +374,7 @@ async fn test_managing_project_specific_settings(cx: &mut gpui::TestAppContext)
(
TaskSourceKind::Worktree {
id: worktree_id,
directory_in_worktree: PathBuf::from(separator!("b/.zed")),
directory_in_worktree: PathBuf::from(path!("b/.zed")),
id_base: if cfg!(windows) {
"local worktree tasks from directory \"b\\\\.zed\"".into()
} else {
@ -460,7 +459,7 @@ async fn test_managing_project_specific_settings(cx: &mut gpui::TestAppContext)
(
TaskSourceKind::Worktree {
id: worktree_id,
directory_in_worktree: PathBuf::from(separator!("b/.zed")),
directory_in_worktree: PathBuf::from(path!("b/.zed")),
id_base: if cfg!(windows) {
"local worktree tasks from directory \"b\\\\.zed\"".into()
} else {
@ -575,7 +574,7 @@ async fn test_fallback_to_single_worktree_tasks(cx: &mut gpui::TestAppContext) {
vec![(
TaskSourceKind::Worktree {
id: worktree_id,
directory_in_worktree: PathBuf::from(separator!(".zed")),
directory_in_worktree: PathBuf::from(path!(".zed")),
id_base: if cfg!(windows) {
"local worktree tasks from directory \".zed\"".into()
} else {
@ -3987,12 +3986,12 @@ async fn test_rescan_and_remote_updates(cx: &mut gpui::TestAppContext) {
.collect::<Vec<_>>(),
vec![
"a",
separator!("a/file1"),
separator!("a/file2.new"),
path!("a/file1"),
path!("a/file2.new"),
"b",
"d",
separator!("d/file3"),
separator!("d/file4"),
path!("d/file3"),
path!("d/file4"),
]
);
});
@ -4055,12 +4054,12 @@ async fn test_rescan_and_remote_updates(cx: &mut gpui::TestAppContext) {
.collect::<Vec<_>>(),
vec![
"a",
separator!("a/file1"),
separator!("a/file2.new"),
path!("a/file1"),
path!("a/file2.new"),
"b",
"d",
separator!("d/file3"),
separator!("d/file4"),
path!("d/file3"),
path!("d/file4"),
]
);
});
@ -5055,8 +5054,8 @@ async fn test_search(cx: &mut gpui::TestAppContext) {
.await
.unwrap(),
HashMap::from_iter([
(separator!("dir/two.rs").to_string(), vec![6..9]),
(separator!("dir/three.rs").to_string(), vec![37..40])
(path!("dir/two.rs").to_string(), vec![6..9]),
(path!("dir/three.rs").to_string(), vec![37..40])
])
);
@ -5090,9 +5089,9 @@ async fn test_search(cx: &mut gpui::TestAppContext) {
.await
.unwrap(),
HashMap::from_iter([
(separator!("dir/two.rs").to_string(), vec![6..9]),
(separator!("dir/three.rs").to_string(), vec![37..40]),
(separator!("dir/four.rs").to_string(), vec![25..28, 36..39])
(path!("dir/two.rs").to_string(), vec![6..9]),
(path!("dir/three.rs").to_string(), vec![37..40]),
(path!("dir/four.rs").to_string(), vec![25..28, 36..39])
])
);
}
@ -5157,8 +5156,8 @@ async fn test_search_with_inclusions(cx: &mut gpui::TestAppContext) {
.await
.unwrap(),
HashMap::from_iter([
(separator!("dir/one.rs").to_string(), vec![8..12]),
(separator!("dir/two.rs").to_string(), vec![8..12]),
(path!("dir/one.rs").to_string(), vec![8..12]),
(path!("dir/two.rs").to_string(), vec![8..12]),
]),
"Rust only search should give only Rust files"
);
@ -5182,8 +5181,8 @@ async fn test_search_with_inclusions(cx: &mut gpui::TestAppContext) {
.await
.unwrap(),
HashMap::from_iter([
(separator!("dir/one.ts").to_string(), vec![14..18]),
(separator!("dir/two.ts").to_string(), vec![14..18]),
(path!("dir/one.ts").to_string(), vec![14..18]),
(path!("dir/two.ts").to_string(), vec![14..18]),
]),
"TypeScript only search should give only TypeScript files, even if other inclusions don't match anything"
);
@ -5208,10 +5207,10 @@ async fn test_search_with_inclusions(cx: &mut gpui::TestAppContext) {
.await
.unwrap(),
HashMap::from_iter([
(separator!("dir/two.ts").to_string(), vec![14..18]),
(separator!("dir/one.rs").to_string(), vec![8..12]),
(separator!("dir/one.ts").to_string(), vec![14..18]),
(separator!("dir/two.rs").to_string(), vec![8..12]),
(path!("dir/two.ts").to_string(), vec![14..18]),
(path!("dir/one.rs").to_string(), vec![8..12]),
(path!("dir/one.ts").to_string(), vec![14..18]),
(path!("dir/two.rs").to_string(), vec![8..12]),
]),
"Rust and typescript search should give both Rust and TypeScript files, even if other inclusions don't match anything"
);
@ -5255,10 +5254,10 @@ async fn test_search_with_exclusions(cx: &mut gpui::TestAppContext) {
.await
.unwrap(),
HashMap::from_iter([
(separator!("dir/one.rs").to_string(), vec![8..12]),
(separator!("dir/one.ts").to_string(), vec![14..18]),
(separator!("dir/two.rs").to_string(), vec![8..12]),
(separator!("dir/two.ts").to_string(), vec![14..18]),
(path!("dir/one.rs").to_string(), vec![8..12]),
(path!("dir/one.ts").to_string(), vec![14..18]),
(path!("dir/two.rs").to_string(), vec![8..12]),
(path!("dir/two.ts").to_string(), vec![14..18]),
]),
"If no exclusions match, all files should be returned"
);
@ -5282,8 +5281,8 @@ async fn test_search_with_exclusions(cx: &mut gpui::TestAppContext) {
.await
.unwrap(),
HashMap::from_iter([
(separator!("dir/one.ts").to_string(), vec![14..18]),
(separator!("dir/two.ts").to_string(), vec![14..18]),
(path!("dir/one.ts").to_string(), vec![14..18]),
(path!("dir/two.ts").to_string(), vec![14..18]),
]),
"Rust exclusion search should give only TypeScript files"
);
@ -5307,8 +5306,8 @@ async fn test_search_with_exclusions(cx: &mut gpui::TestAppContext) {
.await
.unwrap(),
HashMap::from_iter([
(separator!("dir/one.rs").to_string(), vec![8..12]),
(separator!("dir/two.rs").to_string(), vec![8..12]),
(path!("dir/one.rs").to_string(), vec![8..12]),
(path!("dir/two.rs").to_string(), vec![8..12]),
]),
"TypeScript exclusion search should give only Rust files, even if other exclusions don't match anything"
);
@ -5441,8 +5440,8 @@ async fn test_search_with_exclusions_and_inclusions(cx: &mut gpui::TestAppContex
.await
.unwrap(),
HashMap::from_iter([
(separator!("dir/one.ts").to_string(), vec![14..18]),
(separator!("dir/two.ts").to_string(), vec![14..18]),
(path!("dir/one.ts").to_string(), vec![14..18]),
(path!("dir/two.ts").to_string(), vec![14..18]),
]),
"Non-intersecting TypeScript inclusions and Rust exclusions should return TypeScript files"
);
@ -5495,7 +5494,7 @@ async fn test_search_multiple_worktrees_with_inclusions(cx: &mut gpui::TestAppCo
)
.await
.unwrap(),
HashMap::from_iter([(separator!("worktree-a/haystack.rs").to_string(), vec![3..9])]),
HashMap::from_iter([(path!("worktree-a/haystack.rs").to_string(), vec![3..9])]),
"should only return results from included worktree"
);
assert_eq!(
@ -5516,7 +5515,7 @@ async fn test_search_multiple_worktrees_with_inclusions(cx: &mut gpui::TestAppCo
)
.await
.unwrap(),
HashMap::from_iter([(separator!("worktree-b/haystack.rs").to_string(), vec![3..9])]),
HashMap::from_iter([(path!("worktree-b/haystack.rs").to_string(), vec![3..9])]),
"should only return results from included worktree"
);
@ -5539,8 +5538,8 @@ async fn test_search_multiple_worktrees_with_inclusions(cx: &mut gpui::TestAppCo
.await
.unwrap(),
HashMap::from_iter([
(separator!("worktree-a/haystack.ts").to_string(), vec![3..9]),
(separator!("worktree-b/haystack.ts").to_string(), vec![3..9])
(path!("worktree-a/haystack.ts").to_string(), vec![3..9]),
(path!("worktree-b/haystack.ts").to_string(), vec![3..9])
]),
"should return results from both worktrees"
);
@ -5594,7 +5593,7 @@ async fn test_search_in_gitignored_dirs(cx: &mut gpui::TestAppContext) {
)
.await
.unwrap(),
HashMap::from_iter([(separator!("dir/package.json").to_string(), vec![8..11])]),
HashMap::from_iter([(path!("dir/package.json").to_string(), vec![8..11])]),
"Only one non-ignored file should have the query"
);
@ -5618,22 +5617,22 @@ async fn test_search_in_gitignored_dirs(cx: &mut gpui::TestAppContext) {
.await
.unwrap(),
HashMap::from_iter([
(separator!("dir/package.json").to_string(), vec![8..11]),
(separator!("dir/target/index.txt").to_string(), vec![6..9]),
(path!("dir/package.json").to_string(), vec![8..11]),
(path!("dir/target/index.txt").to_string(), vec![6..9]),
(
separator!("dir/node_modules/prettier/package.json").to_string(),
path!("dir/node_modules/prettier/package.json").to_string(),
vec![9..12]
),
(
separator!("dir/node_modules/prettier/index.ts").to_string(),
path!("dir/node_modules/prettier/index.ts").to_string(),
vec![15..18]
),
(
separator!("dir/node_modules/eslint/index.ts").to_string(),
path!("dir/node_modules/eslint/index.ts").to_string(),
vec![13..16]
),
(
separator!("dir/node_modules/eslint/package.json").to_string(),
path!("dir/node_modules/eslint/package.json").to_string(),
vec![8..11]
),
]),
@ -5662,7 +5661,7 @@ async fn test_search_in_gitignored_dirs(cx: &mut gpui::TestAppContext) {
.await
.unwrap(),
HashMap::from_iter([(
separator!("dir/node_modules/prettier/package.json").to_string(),
path!("dir/node_modules/prettier/package.json").to_string(),
vec![9..12]
)]),
"With search including ignored prettier directory and excluding TS files, only one file should be found"
@ -5701,8 +5700,8 @@ async fn test_search_with_unicode(cx: &mut gpui::TestAppContext) {
.await
.unwrap(),
HashMap::from_iter([
(separator!("dir/one.rs").to_string(), vec![17..29]),
(separator!("dir/three.rs").to_string(), vec![3..15]),
(path!("dir/one.rs").to_string(), vec![17..29]),
(path!("dir/three.rs").to_string(), vec![3..15]),
])
);
@ -5725,9 +5724,9 @@ async fn test_search_with_unicode(cx: &mut gpui::TestAppContext) {
.await
.unwrap(),
HashMap::from_iter([
(separator!("dir/one.rs").to_string(), vec![3..15, 17..29]),
(separator!("dir/two.rs").to_string(), vec![3..15]),
(separator!("dir/three.rs").to_string(), vec![3..15]),
(path!("dir/one.rs").to_string(), vec![3..15, 17..29]),
(path!("dir/two.rs").to_string(), vec![3..15]),
(path!("dir/three.rs").to_string(), vec![3..15]),
])
);
@ -5749,7 +5748,7 @@ async fn test_search_with_unicode(cx: &mut gpui::TestAppContext) {
)
.await
.unwrap(),
HashMap::from_iter([(separator!("dir/two.rs").to_string(), vec![3..16]),])
HashMap::from_iter([(path!("dir/two.rs").to_string(), vec![3..16]),])
);
}

View file

@ -6,7 +6,7 @@ use project::{FakeFs, WorktreeSettings};
use serde_json::json;
use settings::SettingsStore;
use std::path::{Path, PathBuf};
use util::{path, separator};
use util::path;
use workspace::{
AppState, Pane,
item::{Item, ProjectItem},
@ -332,10 +332,10 @@ async fn test_auto_collapse_dir_paths(cx: &mut gpui::TestAppContext) {
assert_eq!(
visible_entries_as_strings(&panel, 0..10, cx),
&[
separator!("v root1"),
separator!(" > dir_1/nested_dir_1/nested_dir_2/nested_dir_3"),
separator!("v root2"),
separator!(" > dir_2"),
"v root1",
" > dir_1/nested_dir_1/nested_dir_2/nested_dir_3",
"v root2",
" > dir_2",
]
);
@ -347,14 +347,14 @@ async fn test_auto_collapse_dir_paths(cx: &mut gpui::TestAppContext) {
assert_eq!(
visible_entries_as_strings(&panel, 0..10, cx),
&[
separator!("v root1"),
separator!(" v dir_1/nested_dir_1/nested_dir_2/nested_dir_3 <== selected"),
separator!(" > nested_dir_4/nested_dir_5"),
separator!(" file_a.java"),
separator!(" file_b.java"),
separator!(" file_c.java"),
separator!("v root2"),
separator!(" > dir_2"),
"v root1",
" v dir_1/nested_dir_1/nested_dir_2/nested_dir_3 <== selected",
" > nested_dir_4/nested_dir_5",
" file_a.java",
" file_b.java",
" file_c.java",
"v root2",
" > dir_2",
]
);
@ -366,31 +366,31 @@ async fn test_auto_collapse_dir_paths(cx: &mut gpui::TestAppContext) {
assert_eq!(
visible_entries_as_strings(&panel, 0..10, cx),
&[
separator!("v root1"),
separator!(" v dir_1/nested_dir_1/nested_dir_2/nested_dir_3"),
separator!(" v nested_dir_4/nested_dir_5 <== selected"),
separator!(" file_d.java"),
separator!(" file_a.java"),
separator!(" file_b.java"),
separator!(" file_c.java"),
separator!("v root2"),
separator!(" > dir_2"),
"v root1",
" v dir_1/nested_dir_1/nested_dir_2/nested_dir_3",
" v nested_dir_4/nested_dir_5 <== selected",
" file_d.java",
" file_a.java",
" file_b.java",
" file_c.java",
"v root2",
" > dir_2",
]
);
toggle_expand_dir(&panel, "root2/dir_2", cx);
assert_eq!(
visible_entries_as_strings(&panel, 0..10, cx),
&[
separator!("v root1"),
separator!(" v dir_1/nested_dir_1/nested_dir_2/nested_dir_3"),
separator!(" v nested_dir_4/nested_dir_5"),
separator!(" file_d.java"),
separator!(" file_a.java"),
separator!(" file_b.java"),
separator!(" file_c.java"),
separator!("v root2"),
separator!(" v dir_2 <== selected"),
separator!(" file_1.java"),
"v root1",
" v dir_1/nested_dir_1/nested_dir_2/nested_dir_3",
" v nested_dir_4/nested_dir_5",
" file_d.java",
" file_a.java",
" file_b.java",
" file_c.java",
"v root2",
" v dir_2 <== selected",
" file_1.java",
]
);
@ -414,7 +414,7 @@ async fn test_auto_collapse_dir_paths(cx: &mut gpui::TestAppContext) {
let panel = workspace.update(cx, ProjectPanel::new).unwrap();
assert_eq!(
visible_entries_as_strings(&panel, 0..10, cx),
&[separator!("> dir_1/nested_dir_1/nested_dir_2/nested_dir_3")],
&["> dir_1/nested_dir_1/nested_dir_2/nested_dir_3"],
"Single worktree with hide_root=true should hide root and show auto-folded paths"
);
@ -426,11 +426,11 @@ async fn test_auto_collapse_dir_paths(cx: &mut gpui::TestAppContext) {
assert_eq!(
visible_entries_as_strings(&panel, 0..10, cx),
&[
separator!("v dir_1/nested_dir_1/nested_dir_2/nested_dir_3 <== selected"),
separator!(" > nested_dir_4/nested_dir_5"),
separator!(" file_a.java"),
separator!(" file_b.java"),
separator!(" file_c.java"),
"v dir_1/nested_dir_1/nested_dir_2/nested_dir_3 <== selected",
" > nested_dir_4/nested_dir_5",
" file_a.java",
" file_b.java",
" file_c.java",
],
"Expanded auto-folded path with hidden root should show contents without root prefix"
);
@ -443,12 +443,12 @@ async fn test_auto_collapse_dir_paths(cx: &mut gpui::TestAppContext) {
assert_eq!(
visible_entries_as_strings(&panel, 0..10, cx),
&[
separator!("v dir_1/nested_dir_1/nested_dir_2/nested_dir_3"),
separator!(" v nested_dir_4/nested_dir_5 <== selected"),
separator!(" file_d.java"),
separator!(" file_a.java"),
separator!(" file_b.java"),
separator!(" file_c.java"),
"v dir_1/nested_dir_1/nested_dir_2/nested_dir_3",
" v nested_dir_4/nested_dir_5 <== selected",
" file_d.java",
" file_a.java",
" file_b.java",
" file_c.java",
],
"Nested expansion with hidden root should maintain proper indentation"
);
@ -4917,12 +4917,12 @@ async fn test_expand_all_for_entry(cx: &mut gpui::TestAppContext) {
assert_eq!(
visible_entries_as_strings(&panel, 0..20, cx),
&[
separator!("v root"),
separator!(" v dir1 <== selected"),
separator!(" > empty1/empty2/empty3"),
separator!(" > ignored_dir"),
separator!(" > subdir1"),
separator!(" .gitignore"),
"v root",
" v dir1 <== selected",
" > empty1/empty2/empty3",
" > ignored_dir",
" > subdir1",
" .gitignore",
],
"Should show first level with auto-folded dirs and ignored dir visible"
);
@ -4939,18 +4939,18 @@ async fn test_expand_all_for_entry(cx: &mut gpui::TestAppContext) {
assert_eq!(
visible_entries_as_strings(&panel, 0..20, cx),
&[
separator!("v root"),
separator!(" v dir1 <== selected"),
separator!(" v empty1"),
separator!(" v empty2"),
separator!(" v empty3"),
separator!(" file.txt"),
separator!(" > ignored_dir"),
separator!(" v subdir1"),
separator!(" > ignored_nested"),
separator!(" file1.txt"),
separator!(" file2.txt"),
separator!(" .gitignore"),
"v root",
" v dir1 <== selected",
" v empty1",
" v empty2",
" v empty3",
" file.txt",
" > ignored_dir",
" v subdir1",
" > ignored_nested",
" file1.txt",
" file2.txt",
" .gitignore",
],
"After expand_all with auto-fold: should not expand ignored_dir, should expand folded dirs, and should not expand ignored_nested"
);
@ -4975,12 +4975,12 @@ async fn test_expand_all_for_entry(cx: &mut gpui::TestAppContext) {
assert_eq!(
visible_entries_as_strings(&panel, 0..20, cx),
&[
separator!("v root"),
separator!(" v dir1 <== selected"),
separator!(" > empty1"),
separator!(" > ignored_dir"),
separator!(" > subdir1"),
separator!(" .gitignore"),
"v root",
" v dir1 <== selected",
" > empty1",
" > ignored_dir",
" > subdir1",
" .gitignore",
],
"With auto-fold disabled: should show all directories separately"
);
@ -4997,18 +4997,18 @@ async fn test_expand_all_for_entry(cx: &mut gpui::TestAppContext) {
assert_eq!(
visible_entries_as_strings(&panel, 0..20, cx),
&[
separator!("v root"),
separator!(" v dir1 <== selected"),
separator!(" v empty1"),
separator!(" v empty2"),
separator!(" v empty3"),
separator!(" file.txt"),
separator!(" > ignored_dir"),
separator!(" v subdir1"),
separator!(" > ignored_nested"),
separator!(" file1.txt"),
separator!(" file2.txt"),
separator!(" .gitignore"),
"v root",
" v dir1 <== selected",
" v empty1",
" v empty2",
" v empty3",
" file.txt",
" > ignored_dir",
" v subdir1",
" > ignored_nested",
" file1.txt",
" file2.txt",
" .gitignore",
],
"After expand_all without auto-fold: should expand all dirs normally, \
expand ignored_dir itself but not its subdirs, and not expand ignored_nested"
@ -5027,20 +5027,20 @@ async fn test_expand_all_for_entry(cx: &mut gpui::TestAppContext) {
assert_eq!(
visible_entries_as_strings(&panel, 0..20, cx),
&[
separator!("v root"),
separator!(" v dir1 <== selected"),
separator!(" v empty1"),
separator!(" v empty2"),
separator!(" v empty3"),
separator!(" file.txt"),
separator!(" v ignored_dir"),
separator!(" v subdir"),
separator!(" deep_file.txt"),
separator!(" v subdir1"),
separator!(" > ignored_nested"),
separator!(" file1.txt"),
separator!(" file2.txt"),
separator!(" .gitignore"),
"v root",
" v dir1 <== selected",
" v empty1",
" v empty2",
" v empty3",
" file.txt",
" v ignored_dir",
" v subdir",
" deep_file.txt",
" v subdir1",
" > ignored_nested",
" file1.txt",
" file2.txt",
" .gitignore",
],
"After expand_all on ignored_dir: should expand all contents of the ignored directory"
);
@ -5090,15 +5090,15 @@ async fn test_collapse_all_for_entry(cx: &mut gpui::TestAppContext) {
assert_eq!(
visible_entries_as_strings(&panel, 0..20, cx),
&[
separator!("v root"),
separator!(" v dir1"),
separator!(" v subdir1"),
separator!(" v nested1"),
separator!(" file1.txt"),
separator!(" file2.txt"),
separator!(" v subdir2 <== selected"),
separator!(" file4.txt"),
separator!(" > dir2"),
"v root",
" v dir1",
" v subdir1",
" v nested1",
" file1.txt",
" file2.txt",
" v subdir2 <== selected",
" file4.txt",
" > dir2",
],
"Initial state with everything expanded"
);
@ -5140,13 +5140,13 @@ async fn test_collapse_all_for_entry(cx: &mut gpui::TestAppContext) {
assert_eq!(
visible_entries_as_strings(&panel, 0..20, cx),
&[
separator!("v root"),
separator!(" v dir1"),
separator!(" v subdir1/nested1 <== selected"),
separator!(" file1.txt"),
separator!(" file2.txt"),
separator!(" > subdir2"),
separator!(" > dir2/single_file"),
"v root",
" v dir1",
" v subdir1/nested1 <== selected",
" file1.txt",
" file2.txt",
" > subdir2",
" > dir2/single_file",
],
"Initial state with some dirs expanded"
);
@ -5163,11 +5163,11 @@ async fn test_collapse_all_for_entry(cx: &mut gpui::TestAppContext) {
assert_eq!(
visible_entries_as_strings(&panel, 0..20, cx),
&[
separator!("v root"),
separator!(" v dir1 <== selected"),
separator!(" > subdir1/nested1"),
separator!(" > subdir2"),
separator!(" > dir2/single_file"),
"v root",
" v dir1 <== selected",
" > subdir1/nested1",
" > subdir2",
" > dir2/single_file",
],
"Subdirs should be collapsed and folded with auto-fold enabled"
);
@ -5195,14 +5195,14 @@ async fn test_collapse_all_for_entry(cx: &mut gpui::TestAppContext) {
assert_eq!(
visible_entries_as_strings(&panel, 0..20, cx),
&[
separator!("v root"),
separator!(" v dir1"),
separator!(" v subdir1"),
separator!(" v nested1 <== selected"),
separator!(" file1.txt"),
separator!(" file2.txt"),
separator!(" > subdir2"),
separator!(" > dir2"),
"v root",
" v dir1",
" v subdir1",
" v nested1 <== selected",
" file1.txt",
" file2.txt",
" > subdir2",
" > dir2",
],
"Initial state with some dirs expanded and auto-fold disabled"
);
@ -5219,11 +5219,11 @@ async fn test_collapse_all_for_entry(cx: &mut gpui::TestAppContext) {
assert_eq!(
visible_entries_as_strings(&panel, 0..20, cx),
&[
separator!("v root"),
separator!(" v dir1 <== selected"),
separator!(" > subdir1"),
separator!(" > subdir2"),
separator!(" > dir2"),
"v root",
" v dir1 <== selected",
" > subdir1",
" > subdir2",
" > dir2",
],
"Subdirs should be collapsed but not folded with auto-fold disabled"
);
@ -5261,8 +5261,8 @@ async fn test_create_entries_without_selection(cx: &mut gpui::TestAppContext) {
assert_eq!(
visible_entries_as_strings(&panel, 0..20, cx),
&[
separator!("v root"),
separator!(" > dir1"),
"v root",
" > dir1",
],
"Initial state with nothing selected"
);
@ -5287,9 +5287,9 @@ async fn test_create_entries_without_selection(cx: &mut gpui::TestAppContext) {
assert_eq!(
visible_entries_as_strings(&panel, 0..20, cx),
&[
separator!("v root"),
separator!(" > dir1"),
separator!(" hello_from_no_selections <== selected <== marked"),
"v root",
" > dir1",
" hello_from_no_selections <== selected <== marked",
],
"A new file is created under the root directory"
);
@ -5911,12 +5911,16 @@ fn visible_entries_as_strings(
} else {
" "
};
#[cfg(windows)]
let filename = details.filename.replace("\\", "/");
#[cfg(not(windows))]
let filename = details.filename;
let name = if details.is_editing {
format!("[EDITOR: '{}']", details.filename)
format!("[EDITOR: '{}']", filename)
} else if details.is_processing {
format!("[PROCESSING: '{}']", details.filename)
format!("[PROCESSING: '{}']", filename)
} else {
details.filename.clone()
filename
};
let selected = if details.is_selected {
" <== selected"

View file

@ -33,7 +33,7 @@ use std::{
};
#[cfg(not(windows))]
use unindent::Unindent as _;
use util::{path, separator};
use util::path;
#[gpui::test]
async fn test_basic_remote_editing(cx: &mut TestAppContext, server_cx: &mut TestAppContext) {
@ -218,7 +218,7 @@ async fn test_remote_project_search(cx: &mut TestAppContext, server_cx: &mut Tes
buffer.update(&mut cx, |buffer, cx| {
assert_eq!(
buffer.file().unwrap().full_path(cx).to_string_lossy(),
separator!("project1/README.md")
path!("project1/README.md")
)
});

View file

@ -277,7 +277,7 @@ mod tests {
use settings::SettingsStore;
use smol::channel;
use std::{future, path::Path, sync::Arc};
use util::separator;
use util::path;
fn init_test(cx: &mut TestAppContext) {
zlog::init_test();
@ -422,7 +422,7 @@ mod tests {
assert_eq!(
search_result.path.to_string_lossy(),
separator!("fixture/needle.md")
path!("fixture/needle.md")
);
let content = cx

View file

@ -400,7 +400,7 @@ mod tests {
use serde_json::json;
use task::{TaskContext, TaskVariables, VariableName};
use ui::VisualContext;
use util::{path, separator};
use util::path;
use workspace::{AppState, Workspace};
use crate::task_contexts;
@ -524,7 +524,7 @@ mod tests {
task_variables: TaskVariables::from_iter([
(VariableName::File, path!("/dir/rust/b.rs").into()),
(VariableName::Filename, "b.rs".into()),
(VariableName::RelativeFile, separator!("rust/b.rs").into()),
(VariableName::RelativeFile, path!("rust/b.rs").into()),
(VariableName::RelativeDir, "rust".into()),
(VariableName::Dirname, path!("/dir/rust").into()),
(VariableName::Stem, "b".into()),
@ -556,7 +556,7 @@ mod tests {
task_variables: TaskVariables::from_iter([
(VariableName::File, path!("/dir/rust/b.rs").into()),
(VariableName::Filename, "b.rs".into()),
(VariableName::RelativeFile, separator!("rust/b.rs").into()),
(VariableName::RelativeFile, path!("rust/b.rs").into()),
(VariableName::RelativeDir, "rust".into()),
(VariableName::Dirname, path!("/dir/rust").into()),
(VariableName::Stem, "b".into()),

View file

@ -30,7 +30,7 @@ use unicase::UniCase;
pub use take_until::*;
#[cfg(any(test, feature = "test-support"))]
pub use util_macros::{line_endings, separator, uri};
pub use util_macros::{line_endings, path, uri};
#[macro_export]
macro_rules! debug_panic {
@ -44,50 +44,6 @@ macro_rules! debug_panic {
};
}
/// A macro to add "C:" to the beginning of a path literal on Windows, and replace all
/// the separator from `/` to `\`.
/// But on non-Windows platforms, it will return the path literal as is.
///
/// # Examples
/// ```rust
/// use util::path;
///
/// let path = path!("/Users/user/file.txt");
/// #[cfg(target_os = "windows")]
/// assert_eq!(path, "C:\\Users\\user\\file.txt");
/// #[cfg(not(target_os = "windows"))]
/// assert_eq!(path, "/Users/user/file.txt");
/// ```
#[cfg(all(any(test, feature = "test-support"), target_os = "windows"))]
#[macro_export]
macro_rules! path {
($path:literal) => {
concat!("C:", util::separator!($path))
};
}
/// A macro to add "C:" to the beginning of a path literal on Windows, and replace all
/// the separator from `/` to `\`.
/// But on non-Windows platforms, it will return the path literal as is.
///
/// # Examples
/// ```rust
/// use util::path;
///
/// let path = path!("/Users/user/file.txt");
/// #[cfg(target_os = "windows")]
/// assert_eq!(path, "C:\\Users\\user\\file.txt");
/// #[cfg(not(target_os = "windows"))]
/// assert_eq!(path, "/Users/user/file.txt");
/// ```
#[cfg(all(any(test, feature = "test-support"), not(target_os = "windows")))]
#[macro_export]
macro_rules! path {
($path:literal) => {
$path
};
}
pub fn truncate(s: &str, max_chars: usize) -> &str {
match s.char_indices().nth(max_chars) {
None => s,

View file

@ -4,25 +4,32 @@ use proc_macro::TokenStream;
use quote::quote;
use syn::{LitStr, parse_macro_input};
/// This macro replaces the path separator `/` with `\` for Windows.
/// But if the target OS is not Windows, the path is returned as is.
/// A macro used in tests for cross-platform path string literals in tests. On Windows it replaces
/// `/` with `\\` and adds `C:` to the beginning of absolute paths. On other platforms, the path is
/// returned unmodified.
///
/// # Example
/// ```rust
/// # use util_macros::separator;
/// let path = separator!("path/to/file");
/// use util_macros::path;
///
/// let path = path!("/Users/user/file.txt");
/// #[cfg(target_os = "windows")]
/// assert_eq!(path, "path\\to\\file");
/// assert_eq!(path, "C:\\Users\\user\\file.txt");
/// #[cfg(not(target_os = "windows"))]
/// assert_eq!(path, "path/to/file");
/// assert_eq!(path, "/Users/user/file.txt");
/// ```
#[proc_macro]
pub fn separator(input: TokenStream) -> TokenStream {
pub fn path(input: TokenStream) -> TokenStream {
let path = parse_macro_input!(input as LitStr);
let path = path.value();
let mut path = path.value();
#[cfg(target_os = "windows")]
let path = path.replace("/", "\\");
{
path = path.replace("/", "\\");
if path.starts_with("\\") {
path = format!("C:{}", path);
}
}
TokenStream::from(quote! {
#path

View file

@ -1760,7 +1760,7 @@ mod tests {
time::Duration,
};
use theme::{ThemeRegistry, ThemeSettings};
use util::{path, separator};
use util::path;
use workspace::{
NewFile, OpenOptions, OpenVisible, SERIALIZATION_THROTTLE_TIME, SaveIntent, SplitDirection,
WorkspaceHandle,
@ -2864,8 +2864,8 @@ mod tests {
opened_paths,
vec![
None,
Some(separator!(".git/HEAD").to_string()),
Some(separator!("excluded_dir/file").to_string()),
Some(path!(".git/HEAD").to_string()),
Some(path!("excluded_dir/file").to_string()),
],
"Excluded files should get opened, excluded dir should not get opened"
);
@ -2891,7 +2891,7 @@ mod tests {
opened_buffer_paths.sort();
assert_eq!(
opened_buffer_paths,
vec![separator!(".git/HEAD").to_string(), separator!("excluded_dir/file").to_string()],
vec![path!(".git/HEAD").to_string(), path!("excluded_dir/file").to_string()],
"Despite not being present in the worktrees, buffers for excluded files are opened and added to the pane"
);
});