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

View file

@ -582,7 +582,7 @@ mod test {
use serde_json::json; use serde_json::json;
use settings::SettingsStore; use settings::SettingsStore;
use smol::stream::StreamExt; use smol::stream::StreamExt;
use util::{path, separator}; use util::path;
use super::collect_files; use super::collect_files;
@ -627,7 +627,7 @@ mod test {
.await .await
.unwrap(); .unwrap();
assert!(result_1.text.starts_with(separator!("root/dir"))); assert!(result_1.text.starts_with(path!("root/dir")));
// 4 files + 2 directories // 4 files + 2 directories
assert_eq!(result_1.sections.len(), 6); 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()); cx.update(|cx| collect_files(project.clone(), &["root/dir*".to_string()], cx).boxed());
let result = SlashCommandOutput::from_event_stream(result).await.unwrap(); 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 // 5 files + 2 directories
assert_eq!(result.sections.len(), 7); assert_eq!(result.sections.len(), 7);
@ -691,24 +691,20 @@ mod test {
.unwrap(); .unwrap();
// Sanity check // 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); assert_eq!(result.sections.len(), 7);
// Ensure that full file paths are included in the real output // Ensure that full file paths are included in the real output
assert!( assert!(
result result
.text .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!( assert!(
result result
.text .text
.contains(separator!("zed/assets/themes/ayu/LICENSE")) .contains(path!("zed/assets/themes/summercamp/LICENSE"))
);
assert!(
result
.text
.contains(separator!("zed/assets/themes/summercamp/LICENSE"))
); );
assert_eq!(result.sections[5].label, "summercamp"); assert_eq!(result.sections[5].label, "summercamp");
@ -716,17 +712,17 @@ mod test {
// Ensure that things are in descending order, with properly relativized paths // Ensure that things are in descending order, with properly relativized paths
assert_eq!( assert_eq!(
result.sections[0].label, 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[1].label, "andromeda");
assert_eq!( assert_eq!(
result.sections[2].label, 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[3].label, "ayu");
assert_eq!( assert_eq!(
result.sections[4].label, 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 // Ensure that the project lasts until after the last await
@ -767,31 +763,28 @@ mod test {
.await .await
.unwrap(); .unwrap();
assert!(result.text.starts_with(separator!("zed/assets/themes\n"))); assert!(result.text.starts_with(path!("zed/assets/themes\n")));
assert_eq!( assert_eq!(result.sections[0].label, path!("zed/assets/themes/LICENSE"));
result.sections[0].label,
separator!("zed/assets/themes/LICENSE")
);
assert_eq!( assert_eq!(
result.sections[1].label, result.sections[1].label,
separator!("zed/assets/themes/summercamp/LICENSE") path!("zed/assets/themes/summercamp/LICENSE")
); );
assert_eq!( assert_eq!(
result.sections[2].label, result.sections[2].label,
separator!("zed/assets/themes/summercamp/subdir/LICENSE") path!("zed/assets/themes/summercamp/subdir/LICENSE")
); );
assert_eq!( assert_eq!(
result.sections[3].label, 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[4].label, "subsubdir");
assert_eq!(result.sections[5].label, "subdir"); assert_eq!(result.sections[5].label, "subdir");
assert_eq!(result.sections[6].label, "summercamp"); 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!( assert_eq!(
result.text, 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" "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, time::Duration,
}; };
use unindent::Unindent as _; use unindent::Unindent as _;
use util::{path, separator, uri}; use util::{path, uri};
use workspace::Pane; use workspace::Pane;
#[ctor::ctor] #[ctor::ctor]
@ -1676,13 +1676,13 @@ async fn test_project_reconnect(
.map(|p| p.to_str().unwrap()) .map(|p| p.to_str().unwrap())
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
vec![ vec![
separator!("a.txt"), path!("a.txt"),
separator!("b.txt"), path!("b.txt"),
separator!("subdir2"), path!("subdir2"),
separator!("subdir2/f.txt"), path!("subdir2/f.txt"),
separator!("subdir2/g.txt"), path!("subdir2/g.txt"),
separator!("subdir2/h.txt"), path!("subdir2/h.txt"),
separator!("subdir2/i.txt") path!("subdir2/i.txt")
] ]
); );
assert!(worktree_a3.read(cx).has_update_observer()); assert!(worktree_a3.read(cx).has_update_observer());
@ -1709,13 +1709,13 @@ async fn test_project_reconnect(
.map(|p| p.to_str().unwrap()) .map(|p| p.to_str().unwrap())
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
vec![ vec![
separator!("a.txt"), path!("a.txt"),
separator!("b.txt"), path!("b.txt"),
separator!("subdir2"), path!("subdir2"),
separator!("subdir2/f.txt"), path!("subdir2/f.txt"),
separator!("subdir2/g.txt"), path!("subdir2/g.txt"),
separator!("subdir2/h.txt"), path!("subdir2/h.txt"),
separator!("subdir2/i.txt") path!("subdir2/i.txt")
] ]
); );
assert!(project.worktree_for_id(worktree2_id, cx).is_none()); 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()) .map(|p| p.to_str().unwrap())
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
vec![ vec![
separator!("a.txt"), path!("a.txt"),
separator!("b.txt"), path!("b.txt"),
separator!("subdir2"), path!("subdir2"),
separator!("subdir2/f.txt"), path!("subdir2/f.txt"),
separator!("subdir2/g.txt"), path!("subdir2/g.txt"),
separator!("subdir2/h.txt"), path!("subdir2/h.txt"),
separator!("subdir2/j.txt") path!("subdir2/j.txt")
] ]
); );
assert!(project.worktree_for_id(worktree2_id, cx).is_none()); 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()) .map(|p| p.to_string_lossy())
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
[ [
separator!("DIR"), path!("DIR"),
separator!("DIR/SUBDIR"), path!("DIR/SUBDIR"),
separator!("DIR/SUBDIR/f.txt"), path!("DIR/SUBDIR/f.txt"),
separator!("DIR/e.txt"), path!("DIR/e.txt"),
separator!("a.txt"), path!("a.txt"),
separator!("b.txt"), path!("b.txt"),
separator!("d.txt") path!("d.txt")
] ]
); );
}); });
@ -3333,13 +3333,13 @@ async fn test_fs_operations(
.map(|p| p.to_string_lossy()) .map(|p| p.to_string_lossy())
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
[ [
separator!("DIR"), path!("DIR"),
separator!("DIR/SUBDIR"), path!("DIR/SUBDIR"),
separator!("DIR/SUBDIR/f.txt"), path!("DIR/SUBDIR/f.txt"),
separator!("DIR/e.txt"), path!("DIR/e.txt"),
separator!("a.txt"), path!("a.txt"),
separator!("b.txt"), path!("b.txt"),
separator!("d.txt") path!("d.txt")
] ]
); );
}); });
@ -3359,14 +3359,14 @@ async fn test_fs_operations(
.map(|p| p.to_string_lossy()) .map(|p| p.to_string_lossy())
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
[ [
separator!("DIR"), path!("DIR"),
separator!("DIR/SUBDIR"), path!("DIR/SUBDIR"),
separator!("DIR/SUBDIR/f.txt"), path!("DIR/SUBDIR/f.txt"),
separator!("DIR/e.txt"), path!("DIR/e.txt"),
separator!("a.txt"), path!("a.txt"),
separator!("b.txt"), path!("b.txt"),
separator!("d.txt"), path!("d.txt"),
separator!("f.txt") path!("f.txt")
] ]
); );
}); });
@ -3378,14 +3378,14 @@ async fn test_fs_operations(
.map(|p| p.to_string_lossy()) .map(|p| p.to_string_lossy())
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
[ [
separator!("DIR"), path!("DIR"),
separator!("DIR/SUBDIR"), path!("DIR/SUBDIR"),
separator!("DIR/SUBDIR/f.txt"), path!("DIR/SUBDIR/f.txt"),
separator!("DIR/e.txt"), path!("DIR/e.txt"),
separator!("a.txt"), path!("a.txt"),
separator!("b.txt"), path!("b.txt"),
separator!("d.txt"), path!("d.txt"),
separator!("f.txt") path!("f.txt")
] ]
); );
}); });

View file

@ -30,7 +30,7 @@ use rpc::proto;
use serde_json::json; use serde_json::json;
use settings::SettingsStore; use settings::SettingsStore;
use std::{path::Path, sync::Arc}; use std::{path::Path, sync::Arc};
use util::{path, separator}; use util::path;
#[gpui::test(iterations = 10)] #[gpui::test(iterations = 10)]
async fn test_sharing_an_ssh_remote_project( async fn test_sharing_an_ssh_remote_project(
@ -198,7 +198,7 @@ async fn test_sharing_an_ssh_remote_project(
.path() .path()
.to_string_lossy() .to_string_lossy()
.to_string(), .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", "./bandana",
".\\bandana", ".\\bandana",
util::separator!("a/bandana"), util::path!("a/bandana"),
"b/bandana", "b/bandana",
"b\\bandana", "b\\bandana",
" bandana", " bandana",
@ -230,7 +230,7 @@ async fn test_matching_paths(cx: &mut TestAppContext) {
assert_eq!( assert_eq!(
picker.delegate.matches.len(), picker.delegate.matches.len(),
// existence of CreateNew option depends on whether path already exists // 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 1
} else { } else {
2 2

View file

@ -42,7 +42,6 @@ use unindent::Unindent as _;
use util::{ use util::{
TryFutureExt as _, assert_set_eq, maybe, path, TryFutureExt as _, assert_set_eq, maybe, path,
paths::PathMatcher, paths::PathMatcher,
separator,
test::{TempTree, marked_text_offsets}, test::{TempTree, marked_text_offsets},
uri, uri,
}; };
@ -375,7 +374,7 @@ async fn test_managing_project_specific_settings(cx: &mut gpui::TestAppContext)
( (
TaskSourceKind::Worktree { TaskSourceKind::Worktree {
id: worktree_id, id: worktree_id,
directory_in_worktree: PathBuf::from(separator!("b/.zed")), directory_in_worktree: PathBuf::from(path!("b/.zed")),
id_base: if cfg!(windows) { id_base: if cfg!(windows) {
"local worktree tasks from directory \"b\\\\.zed\"".into() "local worktree tasks from directory \"b\\\\.zed\"".into()
} else { } else {
@ -460,7 +459,7 @@ async fn test_managing_project_specific_settings(cx: &mut gpui::TestAppContext)
( (
TaskSourceKind::Worktree { TaskSourceKind::Worktree {
id: worktree_id, id: worktree_id,
directory_in_worktree: PathBuf::from(separator!("b/.zed")), directory_in_worktree: PathBuf::from(path!("b/.zed")),
id_base: if cfg!(windows) { id_base: if cfg!(windows) {
"local worktree tasks from directory \"b\\\\.zed\"".into() "local worktree tasks from directory \"b\\\\.zed\"".into()
} else { } else {
@ -575,7 +574,7 @@ async fn test_fallback_to_single_worktree_tasks(cx: &mut gpui::TestAppContext) {
vec![( vec![(
TaskSourceKind::Worktree { TaskSourceKind::Worktree {
id: worktree_id, id: worktree_id,
directory_in_worktree: PathBuf::from(separator!(".zed")), directory_in_worktree: PathBuf::from(path!(".zed")),
id_base: if cfg!(windows) { id_base: if cfg!(windows) {
"local worktree tasks from directory \".zed\"".into() "local worktree tasks from directory \".zed\"".into()
} else { } else {
@ -3987,12 +3986,12 @@ async fn test_rescan_and_remote_updates(cx: &mut gpui::TestAppContext) {
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
vec![ vec![
"a", "a",
separator!("a/file1"), path!("a/file1"),
separator!("a/file2.new"), path!("a/file2.new"),
"b", "b",
"d", "d",
separator!("d/file3"), path!("d/file3"),
separator!("d/file4"), path!("d/file4"),
] ]
); );
}); });
@ -4055,12 +4054,12 @@ async fn test_rescan_and_remote_updates(cx: &mut gpui::TestAppContext) {
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
vec![ vec![
"a", "a",
separator!("a/file1"), path!("a/file1"),
separator!("a/file2.new"), path!("a/file2.new"),
"b", "b",
"d", "d",
separator!("d/file3"), path!("d/file3"),
separator!("d/file4"), path!("d/file4"),
] ]
); );
}); });
@ -5055,8 +5054,8 @@ async fn test_search(cx: &mut gpui::TestAppContext) {
.await .await
.unwrap(), .unwrap(),
HashMap::from_iter([ HashMap::from_iter([
(separator!("dir/two.rs").to_string(), vec![6..9]), (path!("dir/two.rs").to_string(), vec![6..9]),
(separator!("dir/three.rs").to_string(), vec![37..40]) (path!("dir/three.rs").to_string(), vec![37..40])
]) ])
); );
@ -5090,9 +5089,9 @@ async fn test_search(cx: &mut gpui::TestAppContext) {
.await .await
.unwrap(), .unwrap(),
HashMap::from_iter([ HashMap::from_iter([
(separator!("dir/two.rs").to_string(), vec![6..9]), (path!("dir/two.rs").to_string(), vec![6..9]),
(separator!("dir/three.rs").to_string(), vec![37..40]), (path!("dir/three.rs").to_string(), vec![37..40]),
(separator!("dir/four.rs").to_string(), vec![25..28, 36..39]) (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 .await
.unwrap(), .unwrap(),
HashMap::from_iter([ HashMap::from_iter([
(separator!("dir/one.rs").to_string(), vec![8..12]), (path!("dir/one.rs").to_string(), vec![8..12]),
(separator!("dir/two.rs").to_string(), vec![8..12]), (path!("dir/two.rs").to_string(), vec![8..12]),
]), ]),
"Rust only search should give only Rust files" "Rust only search should give only Rust files"
); );
@ -5182,8 +5181,8 @@ async fn test_search_with_inclusions(cx: &mut gpui::TestAppContext) {
.await .await
.unwrap(), .unwrap(),
HashMap::from_iter([ HashMap::from_iter([
(separator!("dir/one.ts").to_string(), vec![14..18]), (path!("dir/one.ts").to_string(), vec![14..18]),
(separator!("dir/two.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" "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 .await
.unwrap(), .unwrap(),
HashMap::from_iter([ HashMap::from_iter([
(separator!("dir/two.ts").to_string(), vec![14..18]), (path!("dir/two.ts").to_string(), vec![14..18]),
(separator!("dir/one.rs").to_string(), vec![8..12]), (path!("dir/one.rs").to_string(), vec![8..12]),
(separator!("dir/one.ts").to_string(), vec![14..18]), (path!("dir/one.ts").to_string(), vec![14..18]),
(separator!("dir/two.rs").to_string(), vec![8..12]), (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" "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 .await
.unwrap(), .unwrap(),
HashMap::from_iter([ HashMap::from_iter([
(separator!("dir/one.rs").to_string(), vec![8..12]), (path!("dir/one.rs").to_string(), vec![8..12]),
(separator!("dir/one.ts").to_string(), vec![14..18]), (path!("dir/one.ts").to_string(), vec![14..18]),
(separator!("dir/two.rs").to_string(), vec![8..12]), (path!("dir/two.rs").to_string(), vec![8..12]),
(separator!("dir/two.ts").to_string(), vec![14..18]), (path!("dir/two.ts").to_string(), vec![14..18]),
]), ]),
"If no exclusions match, all files should be returned" "If no exclusions match, all files should be returned"
); );
@ -5282,8 +5281,8 @@ async fn test_search_with_exclusions(cx: &mut gpui::TestAppContext) {
.await .await
.unwrap(), .unwrap(),
HashMap::from_iter([ HashMap::from_iter([
(separator!("dir/one.ts").to_string(), vec![14..18]), (path!("dir/one.ts").to_string(), vec![14..18]),
(separator!("dir/two.ts").to_string(), vec![14..18]), (path!("dir/two.ts").to_string(), vec![14..18]),
]), ]),
"Rust exclusion search should give only TypeScript files" "Rust exclusion search should give only TypeScript files"
); );
@ -5307,8 +5306,8 @@ async fn test_search_with_exclusions(cx: &mut gpui::TestAppContext) {
.await .await
.unwrap(), .unwrap(),
HashMap::from_iter([ HashMap::from_iter([
(separator!("dir/one.rs").to_string(), vec![8..12]), (path!("dir/one.rs").to_string(), vec![8..12]),
(separator!("dir/two.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" "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 .await
.unwrap(), .unwrap(),
HashMap::from_iter([ HashMap::from_iter([
(separator!("dir/one.ts").to_string(), vec![14..18]), (path!("dir/one.ts").to_string(), vec![14..18]),
(separator!("dir/two.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" "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 .await
.unwrap(), .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" "should only return results from included worktree"
); );
assert_eq!( assert_eq!(
@ -5516,7 +5515,7 @@ async fn test_search_multiple_worktrees_with_inclusions(cx: &mut gpui::TestAppCo
) )
.await .await
.unwrap(), .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" "should only return results from included worktree"
); );
@ -5539,8 +5538,8 @@ async fn test_search_multiple_worktrees_with_inclusions(cx: &mut gpui::TestAppCo
.await .await
.unwrap(), .unwrap(),
HashMap::from_iter([ HashMap::from_iter([
(separator!("worktree-a/haystack.ts").to_string(), vec![3..9]), (path!("worktree-a/haystack.ts").to_string(), vec![3..9]),
(separator!("worktree-b/haystack.ts").to_string(), vec![3..9]) (path!("worktree-b/haystack.ts").to_string(), vec![3..9])
]), ]),
"should return results from both worktrees" "should return results from both worktrees"
); );
@ -5594,7 +5593,7 @@ async fn test_search_in_gitignored_dirs(cx: &mut gpui::TestAppContext) {
) )
.await .await
.unwrap(), .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" "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 .await
.unwrap(), .unwrap(),
HashMap::from_iter([ HashMap::from_iter([
(separator!("dir/package.json").to_string(), vec![8..11]), (path!("dir/package.json").to_string(), vec![8..11]),
(separator!("dir/target/index.txt").to_string(), vec![6..9]), (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] vec![9..12]
), ),
( (
separator!("dir/node_modules/prettier/index.ts").to_string(), path!("dir/node_modules/prettier/index.ts").to_string(),
vec![15..18] vec![15..18]
), ),
( (
separator!("dir/node_modules/eslint/index.ts").to_string(), path!("dir/node_modules/eslint/index.ts").to_string(),
vec![13..16] vec![13..16]
), ),
( (
separator!("dir/node_modules/eslint/package.json").to_string(), path!("dir/node_modules/eslint/package.json").to_string(),
vec![8..11] vec![8..11]
), ),
]), ]),
@ -5662,7 +5661,7 @@ async fn test_search_in_gitignored_dirs(cx: &mut gpui::TestAppContext) {
.await .await
.unwrap(), .unwrap(),
HashMap::from_iter([( HashMap::from_iter([(
separator!("dir/node_modules/prettier/package.json").to_string(), path!("dir/node_modules/prettier/package.json").to_string(),
vec![9..12] vec![9..12]
)]), )]),
"With search including ignored prettier directory and excluding TS files, only one file should be found" "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 .await
.unwrap(), .unwrap(),
HashMap::from_iter([ HashMap::from_iter([
(separator!("dir/one.rs").to_string(), vec![17..29]), (path!("dir/one.rs").to_string(), vec![17..29]),
(separator!("dir/three.rs").to_string(), vec![3..15]), (path!("dir/three.rs").to_string(), vec![3..15]),
]) ])
); );
@ -5725,9 +5724,9 @@ async fn test_search_with_unicode(cx: &mut gpui::TestAppContext) {
.await .await
.unwrap(), .unwrap(),
HashMap::from_iter([ HashMap::from_iter([
(separator!("dir/one.rs").to_string(), vec![3..15, 17..29]), (path!("dir/one.rs").to_string(), vec![3..15, 17..29]),
(separator!("dir/two.rs").to_string(), vec![3..15]), (path!("dir/two.rs").to_string(), vec![3..15]),
(separator!("dir/three.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 .await
.unwrap(), .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 serde_json::json;
use settings::SettingsStore; use settings::SettingsStore;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use util::{path, separator}; use util::path;
use workspace::{ use workspace::{
AppState, Pane, AppState, Pane,
item::{Item, ProjectItem}, item::{Item, ProjectItem},
@ -332,10 +332,10 @@ async fn test_auto_collapse_dir_paths(cx: &mut gpui::TestAppContext) {
assert_eq!( assert_eq!(
visible_entries_as_strings(&panel, 0..10, cx), visible_entries_as_strings(&panel, 0..10, cx),
&[ &[
separator!("v root1"), "v root1",
separator!(" > dir_1/nested_dir_1/nested_dir_2/nested_dir_3"), " > dir_1/nested_dir_1/nested_dir_2/nested_dir_3",
separator!("v root2"), "v root2",
separator!(" > dir_2"), " > dir_2",
] ]
); );
@ -347,14 +347,14 @@ async fn test_auto_collapse_dir_paths(cx: &mut gpui::TestAppContext) {
assert_eq!( assert_eq!(
visible_entries_as_strings(&panel, 0..10, cx), visible_entries_as_strings(&panel, 0..10, cx),
&[ &[
separator!("v root1"), "v root1",
separator!(" v dir_1/nested_dir_1/nested_dir_2/nested_dir_3 <== selected"), " v dir_1/nested_dir_1/nested_dir_2/nested_dir_3 <== selected",
separator!(" > nested_dir_4/nested_dir_5"), " > nested_dir_4/nested_dir_5",
separator!(" file_a.java"), " file_a.java",
separator!(" file_b.java"), " file_b.java",
separator!(" file_c.java"), " file_c.java",
separator!("v root2"), "v root2",
separator!(" > dir_2"), " > dir_2",
] ]
); );
@ -366,31 +366,31 @@ async fn test_auto_collapse_dir_paths(cx: &mut gpui::TestAppContext) {
assert_eq!( assert_eq!(
visible_entries_as_strings(&panel, 0..10, cx), visible_entries_as_strings(&panel, 0..10, cx),
&[ &[
separator!("v root1"), "v root1",
separator!(" v dir_1/nested_dir_1/nested_dir_2/nested_dir_3"), " v dir_1/nested_dir_1/nested_dir_2/nested_dir_3",
separator!(" v nested_dir_4/nested_dir_5 <== selected"), " v nested_dir_4/nested_dir_5 <== selected",
separator!(" file_d.java"), " file_d.java",
separator!(" file_a.java"), " file_a.java",
separator!(" file_b.java"), " file_b.java",
separator!(" file_c.java"), " file_c.java",
separator!("v root2"), "v root2",
separator!(" > dir_2"), " > dir_2",
] ]
); );
toggle_expand_dir(&panel, "root2/dir_2", cx); toggle_expand_dir(&panel, "root2/dir_2", cx);
assert_eq!( assert_eq!(
visible_entries_as_strings(&panel, 0..10, cx), visible_entries_as_strings(&panel, 0..10, cx),
&[ &[
separator!("v root1"), "v root1",
separator!(" v dir_1/nested_dir_1/nested_dir_2/nested_dir_3"), " v dir_1/nested_dir_1/nested_dir_2/nested_dir_3",
separator!(" v nested_dir_4/nested_dir_5"), " v nested_dir_4/nested_dir_5",
separator!(" file_d.java"), " file_d.java",
separator!(" file_a.java"), " file_a.java",
separator!(" file_b.java"), " file_b.java",
separator!(" file_c.java"), " file_c.java",
separator!("v root2"), "v root2",
separator!(" v dir_2 <== selected"), " v dir_2 <== selected",
separator!(" file_1.java"), " 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(); let panel = workspace.update(cx, ProjectPanel::new).unwrap();
assert_eq!( assert_eq!(
visible_entries_as_strings(&panel, 0..10, cx), 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" "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!( assert_eq!(
visible_entries_as_strings(&panel, 0..10, cx), visible_entries_as_strings(&panel, 0..10, cx),
&[ &[
separator!("v dir_1/nested_dir_1/nested_dir_2/nested_dir_3 <== selected"), "v dir_1/nested_dir_1/nested_dir_2/nested_dir_3 <== selected",
separator!(" > nested_dir_4/nested_dir_5"), " > nested_dir_4/nested_dir_5",
separator!(" file_a.java"), " file_a.java",
separator!(" file_b.java"), " file_b.java",
separator!(" file_c.java"), " file_c.java",
], ],
"Expanded auto-folded path with hidden root should show contents without root prefix" "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!( assert_eq!(
visible_entries_as_strings(&panel, 0..10, cx), visible_entries_as_strings(&panel, 0..10, cx),
&[ &[
separator!("v dir_1/nested_dir_1/nested_dir_2/nested_dir_3"), "v dir_1/nested_dir_1/nested_dir_2/nested_dir_3",
separator!(" v nested_dir_4/nested_dir_5 <== selected"), " v nested_dir_4/nested_dir_5 <== selected",
separator!(" file_d.java"), " file_d.java",
separator!(" file_a.java"), " file_a.java",
separator!(" file_b.java"), " file_b.java",
separator!(" file_c.java"), " file_c.java",
], ],
"Nested expansion with hidden root should maintain proper indentation" "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!( assert_eq!(
visible_entries_as_strings(&panel, 0..20, cx), visible_entries_as_strings(&panel, 0..20, cx),
&[ &[
separator!("v root"), "v root",
separator!(" v dir1 <== selected"), " v dir1 <== selected",
separator!(" > empty1/empty2/empty3"), " > empty1/empty2/empty3",
separator!(" > ignored_dir"), " > ignored_dir",
separator!(" > subdir1"), " > subdir1",
separator!(" .gitignore"), " .gitignore",
], ],
"Should show first level with auto-folded dirs and ignored dir visible" "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!( assert_eq!(
visible_entries_as_strings(&panel, 0..20, cx), visible_entries_as_strings(&panel, 0..20, cx),
&[ &[
separator!("v root"), "v root",
separator!(" v dir1 <== selected"), " v dir1 <== selected",
separator!(" v empty1"), " v empty1",
separator!(" v empty2"), " v empty2",
separator!(" v empty3"), " v empty3",
separator!(" file.txt"), " file.txt",
separator!(" > ignored_dir"), " > ignored_dir",
separator!(" v subdir1"), " v subdir1",
separator!(" > ignored_nested"), " > ignored_nested",
separator!(" file1.txt"), " file1.txt",
separator!(" file2.txt"), " file2.txt",
separator!(" .gitignore"), " .gitignore",
], ],
"After expand_all with auto-fold: should not expand ignored_dir, should expand folded dirs, and should not expand ignored_nested" "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!( assert_eq!(
visible_entries_as_strings(&panel, 0..20, cx), visible_entries_as_strings(&panel, 0..20, cx),
&[ &[
separator!("v root"), "v root",
separator!(" v dir1 <== selected"), " v dir1 <== selected",
separator!(" > empty1"), " > empty1",
separator!(" > ignored_dir"), " > ignored_dir",
separator!(" > subdir1"), " > subdir1",
separator!(" .gitignore"), " .gitignore",
], ],
"With auto-fold disabled: should show all directories separately" "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!( assert_eq!(
visible_entries_as_strings(&panel, 0..20, cx), visible_entries_as_strings(&panel, 0..20, cx),
&[ &[
separator!("v root"), "v root",
separator!(" v dir1 <== selected"), " v dir1 <== selected",
separator!(" v empty1"), " v empty1",
separator!(" v empty2"), " v empty2",
separator!(" v empty3"), " v empty3",
separator!(" file.txt"), " file.txt",
separator!(" > ignored_dir"), " > ignored_dir",
separator!(" v subdir1"), " v subdir1",
separator!(" > ignored_nested"), " > ignored_nested",
separator!(" file1.txt"), " file1.txt",
separator!(" file2.txt"), " file2.txt",
separator!(" .gitignore"), " .gitignore",
], ],
"After expand_all without auto-fold: should expand all dirs normally, \ "After expand_all without auto-fold: should expand all dirs normally, \
expand ignored_dir itself but not its subdirs, and not expand ignored_nested" 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!( assert_eq!(
visible_entries_as_strings(&panel, 0..20, cx), visible_entries_as_strings(&panel, 0..20, cx),
&[ &[
separator!("v root"), "v root",
separator!(" v dir1 <== selected"), " v dir1 <== selected",
separator!(" v empty1"), " v empty1",
separator!(" v empty2"), " v empty2",
separator!(" v empty3"), " v empty3",
separator!(" file.txt"), " file.txt",
separator!(" v ignored_dir"), " v ignored_dir",
separator!(" v subdir"), " v subdir",
separator!(" deep_file.txt"), " deep_file.txt",
separator!(" v subdir1"), " v subdir1",
separator!(" > ignored_nested"), " > ignored_nested",
separator!(" file1.txt"), " file1.txt",
separator!(" file2.txt"), " file2.txt",
separator!(" .gitignore"), " .gitignore",
], ],
"After expand_all on ignored_dir: should expand all contents of the ignored directory" "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!( assert_eq!(
visible_entries_as_strings(&panel, 0..20, cx), visible_entries_as_strings(&panel, 0..20, cx),
&[ &[
separator!("v root"), "v root",
separator!(" v dir1"), " v dir1",
separator!(" v subdir1"), " v subdir1",
separator!(" v nested1"), " v nested1",
separator!(" file1.txt"), " file1.txt",
separator!(" file2.txt"), " file2.txt",
separator!(" v subdir2 <== selected"), " v subdir2 <== selected",
separator!(" file4.txt"), " file4.txt",
separator!(" > dir2"), " > dir2",
], ],
"Initial state with everything expanded" "Initial state with everything expanded"
); );
@ -5140,13 +5140,13 @@ async fn test_collapse_all_for_entry(cx: &mut gpui::TestAppContext) {
assert_eq!( assert_eq!(
visible_entries_as_strings(&panel, 0..20, cx), visible_entries_as_strings(&panel, 0..20, cx),
&[ &[
separator!("v root"), "v root",
separator!(" v dir1"), " v dir1",
separator!(" v subdir1/nested1 <== selected"), " v subdir1/nested1 <== selected",
separator!(" file1.txt"), " file1.txt",
separator!(" file2.txt"), " file2.txt",
separator!(" > subdir2"), " > subdir2",
separator!(" > dir2/single_file"), " > dir2/single_file",
], ],
"Initial state with some dirs expanded" "Initial state with some dirs expanded"
); );
@ -5163,11 +5163,11 @@ async fn test_collapse_all_for_entry(cx: &mut gpui::TestAppContext) {
assert_eq!( assert_eq!(
visible_entries_as_strings(&panel, 0..20, cx), visible_entries_as_strings(&panel, 0..20, cx),
&[ &[
separator!("v root"), "v root",
separator!(" v dir1 <== selected"), " v dir1 <== selected",
separator!(" > subdir1/nested1"), " > subdir1/nested1",
separator!(" > subdir2"), " > subdir2",
separator!(" > dir2/single_file"), " > dir2/single_file",
], ],
"Subdirs should be collapsed and folded with auto-fold enabled" "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!( assert_eq!(
visible_entries_as_strings(&panel, 0..20, cx), visible_entries_as_strings(&panel, 0..20, cx),
&[ &[
separator!("v root"), "v root",
separator!(" v dir1"), " v dir1",
separator!(" v subdir1"), " v subdir1",
separator!(" v nested1 <== selected"), " v nested1 <== selected",
separator!(" file1.txt"), " file1.txt",
separator!(" file2.txt"), " file2.txt",
separator!(" > subdir2"), " > subdir2",
separator!(" > dir2"), " > dir2",
], ],
"Initial state with some dirs expanded and auto-fold disabled" "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!( assert_eq!(
visible_entries_as_strings(&panel, 0..20, cx), visible_entries_as_strings(&panel, 0..20, cx),
&[ &[
separator!("v root"), "v root",
separator!(" v dir1 <== selected"), " v dir1 <== selected",
separator!(" > subdir1"), " > subdir1",
separator!(" > subdir2"), " > subdir2",
separator!(" > dir2"), " > dir2",
], ],
"Subdirs should be collapsed but not folded with auto-fold disabled" "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!( assert_eq!(
visible_entries_as_strings(&panel, 0..20, cx), visible_entries_as_strings(&panel, 0..20, cx),
&[ &[
separator!("v root"), "v root",
separator!(" > dir1"), " > dir1",
], ],
"Initial state with nothing selected" "Initial state with nothing selected"
); );
@ -5287,9 +5287,9 @@ async fn test_create_entries_without_selection(cx: &mut gpui::TestAppContext) {
assert_eq!( assert_eq!(
visible_entries_as_strings(&panel, 0..20, cx), visible_entries_as_strings(&panel, 0..20, cx),
&[ &[
separator!("v root"), "v root",
separator!(" > dir1"), " > dir1",
separator!(" hello_from_no_selections <== selected <== marked"), " hello_from_no_selections <== selected <== marked",
], ],
"A new file is created under the root directory" "A new file is created under the root directory"
); );
@ -5911,12 +5911,16 @@ fn visible_entries_as_strings(
} else { } else {
" " " "
}; };
#[cfg(windows)]
let filename = details.filename.replace("\\", "/");
#[cfg(not(windows))]
let filename = details.filename;
let name = if details.is_editing { let name = if details.is_editing {
format!("[EDITOR: '{}']", details.filename) format!("[EDITOR: '{}']", filename)
} else if details.is_processing { } else if details.is_processing {
format!("[PROCESSING: '{}']", details.filename) format!("[PROCESSING: '{}']", filename)
} else { } else {
details.filename.clone() filename
}; };
let selected = if details.is_selected { let selected = if details.is_selected {
" <== selected" " <== selected"

View file

@ -33,7 +33,7 @@ use std::{
}; };
#[cfg(not(windows))] #[cfg(not(windows))]
use unindent::Unindent as _; use unindent::Unindent as _;
use util::{path, separator}; use util::path;
#[gpui::test] #[gpui::test]
async fn test_basic_remote_editing(cx: &mut TestAppContext, server_cx: &mut TestAppContext) { 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| { buffer.update(&mut cx, |buffer, cx| {
assert_eq!( assert_eq!(
buffer.file().unwrap().full_path(cx).to_string_lossy(), 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 settings::SettingsStore;
use smol::channel; use smol::channel;
use std::{future, path::Path, sync::Arc}; use std::{future, path::Path, sync::Arc};
use util::separator; use util::path;
fn init_test(cx: &mut TestAppContext) { fn init_test(cx: &mut TestAppContext) {
zlog::init_test(); zlog::init_test();
@ -422,7 +422,7 @@ mod tests {
assert_eq!( assert_eq!(
search_result.path.to_string_lossy(), search_result.path.to_string_lossy(),
separator!("fixture/needle.md") path!("fixture/needle.md")
); );
let content = cx let content = cx

View file

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

View file

@ -30,7 +30,7 @@ use unicase::UniCase;
pub use take_until::*; pub use take_until::*;
#[cfg(any(test, feature = "test-support"))] #[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_export]
macro_rules! debug_panic { 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 { pub fn truncate(s: &str, max_chars: usize) -> &str {
match s.char_indices().nth(max_chars) { match s.char_indices().nth(max_chars) {
None => s, None => s,

View file

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

View file

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