Detailed changes
@@ -121,7 +121,7 @@ use text::{Anchor, BufferId, OffsetRangeExt, Point, Rope};
use toolchain_store::EmptyToolchainStore;
use util::{
ResultExt as _, maybe,
- paths::{PathStyle, SanitizedPath, compare_paths, is_absolute},
+ paths::{PathStyle, SanitizedPath, compare_paths, compare_rel_paths, is_absolute},
rel_path::RelPath,
};
use worktree::{CreatedEntry, Snapshot, Traversal};
@@ -4041,10 +4041,7 @@ impl Project {
(None, None) => a.read(cx).remote_id().cmp(&b.read(cx).remote_id()),
(None, Some(_)) => std::cmp::Ordering::Less,
(Some(_), None) => std::cmp::Ordering::Greater,
- (Some(a), Some(b)) => compare_paths(
- (a.path().as_std_path(), true),
- (b.path().as_std_path(), true),
- ),
+ (Some(a), Some(b)) => compare_rel_paths((&a.path(), true), (&b.path(), true)),
});
for buffer in buffers {
tx.send_blocking(buffer.clone()).unwrap()
@@ -59,7 +59,11 @@ use ui::{
ScrollAxes, ScrollableHandle, Scrollbars, StickyCandidate, Tooltip, WithScrollbar, prelude::*,
v_flex,
};
-use util::{ResultExt, TakeUntilExt, TryFutureExt, maybe, paths::compare_paths, rel_path::RelPath};
+use util::{
+ ResultExt, TakeUntilExt, TryFutureExt, maybe,
+ paths::{compare_paths, compare_rel_paths},
+ rel_path::RelPath,
+};
use workspace::{
DraggedSelection, OpenInTerminal, OpenOptions, OpenVisible, PreviewTabsSettings, SelectedEntry,
SplitDirection, Workspace,
@@ -1998,10 +2002,9 @@ impl ProjectPanel {
worktree.entry_for_id(a.entry_id),
worktree.entry_for_id(b.entry_id),
) {
- (Some(a), Some(b)) => compare_paths(
- (a.path.as_std_path(), a.is_file()),
- (b.path.as_std_path(), b.is_file()),
- ),
+ (Some(a), Some(b)) => {
+ compare_rel_paths((&a.path, a.is_file()), (&b.path, b.is_file()))
+ }
_ => cmp::Ordering::Equal,
}
})
@@ -5889,9 +5892,9 @@ impl ClipboardEntry {
fn cmp<T: AsRef<Entry>>(lhs: T, rhs: T) -> cmp::Ordering {
let entry_a = lhs.as_ref();
let entry_b = rhs.as_ref();
- compare_paths(
- (entry_a.path.as_std_path(), entry_a.is_file()),
- (entry_b.path.as_std_path(), entry_b.is_file()),
+ compare_rel_paths(
+ (&entry_a.path, entry_a.is_file()),
+ (&entry_b.path, entry_b.is_file()),
)
}
@@ -14,6 +14,8 @@ use std::{
sync::LazyLock,
};
+use crate::rel_path::RelPath;
+
static HOME_DIR: OnceLock<PathBuf> = OnceLock::new();
/// Returns the path to the user's home directory.
@@ -850,6 +852,65 @@ pub fn compare_paths(
}
}
+pub fn compare_rel_paths(
+ (path_a, a_is_file): (&RelPath, bool),
+ (path_b, b_is_file): (&RelPath, bool),
+) -> Ordering {
+ let mut components_a = path_a.components().peekable();
+ let mut components_b = path_b.components().peekable();
+
+ loop {
+ match (components_a.next(), components_b.next()) {
+ (Some(component_a), Some(component_b)) => {
+ let a_is_file = components_a.peek().is_none() && a_is_file;
+ let b_is_file = components_b.peek().is_none() && b_is_file;
+
+ let ordering = a_is_file.cmp(&b_is_file).then_with(|| {
+ let path_a = Path::new(component_a);
+ let path_string_a = if a_is_file {
+ path_a.file_stem()
+ } else {
+ path_a.file_name()
+ }
+ .map(|s| s.to_string_lossy());
+
+ let path_b = Path::new(component_b);
+ let path_string_b = if b_is_file {
+ path_b.file_stem()
+ } else {
+ path_b.file_name()
+ }
+ .map(|s| s.to_string_lossy());
+
+ let compare_components = match (path_string_a, path_string_b) {
+ (Some(a), Some(b)) => natural_sort(&a, &b),
+ (Some(_), None) => Ordering::Greater,
+ (None, Some(_)) => Ordering::Less,
+ (None, None) => Ordering::Equal,
+ };
+
+ compare_components.then_with(|| {
+ if a_is_file && b_is_file {
+ let ext_a = path_a.extension().unwrap_or_default();
+ let ext_b = path_b.extension().unwrap_or_default();
+ ext_a.cmp(ext_b)
+ } else {
+ Ordering::Equal
+ }
+ })
+ });
+
+ if !ordering.is_eq() {
+ return ordering;
+ }
+ }
+ (Some(_), None) => break Ordering::Greater,
+ (None, Some(_)) => break Ordering::Less,
+ (None, None) => break Ordering::Equal,
+ }
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;