Merge branch 'main' into theme-variables
This commit is contained in:
commit
85a076312a
7 changed files with 181 additions and 174 deletions
|
@ -23,7 +23,7 @@ use core_graphics::{
|
||||||
use core_text::{line::CTLine, string_attributes::kCTFontAttributeName};
|
use core_text::{line::CTLine, string_attributes::kCTFontAttributeName};
|
||||||
use font_kit::{canvas::RasterizationOptions, hinting::HintingOptions, source::SystemSource};
|
use font_kit::{canvas::RasterizationOptions, hinting::HintingOptions, source::SystemSource};
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use std::{cell::RefCell, char, convert::TryFrom, ffi::c_void};
|
use std::{cell::RefCell, char, cmp, convert::TryFrom, ffi::c_void};
|
||||||
|
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
const kCGImageAlphaOnly: u32 = 7;
|
const kCGImageAlphaOnly: u32 = 7;
|
||||||
|
@ -199,6 +199,7 @@ impl FontSystemState {
|
||||||
let mut string = CFMutableAttributedString::new();
|
let mut string = CFMutableAttributedString::new();
|
||||||
{
|
{
|
||||||
string.replace_str(&CFString::new(text), CFRange::init(0, 0));
|
string.replace_str(&CFString::new(text), CFRange::init(0, 0));
|
||||||
|
let utf16_line_len = string.char_len() as usize;
|
||||||
|
|
||||||
let last_run: RefCell<Option<(usize, FontId)>> = Default::default();
|
let last_run: RefCell<Option<(usize, FontId)>> = Default::default();
|
||||||
let font_runs = runs
|
let font_runs = runs
|
||||||
|
@ -226,12 +227,16 @@ impl FontSystemState {
|
||||||
for (run_len, font_id) in font_runs {
|
for (run_len, font_id) in font_runs {
|
||||||
let utf8_end = ix_converter.utf8_ix + run_len;
|
let utf8_end = ix_converter.utf8_ix + run_len;
|
||||||
let utf16_start = ix_converter.utf16_ix;
|
let utf16_start = ix_converter.utf16_ix;
|
||||||
ix_converter.advance_to_utf8_ix(utf8_end);
|
|
||||||
|
|
||||||
let cf_range = CFRange::init(
|
if utf16_start >= utf16_line_len {
|
||||||
utf16_start as isize,
|
break;
|
||||||
(ix_converter.utf16_ix - utf16_start) as isize,
|
}
|
||||||
);
|
|
||||||
|
ix_converter.advance_to_utf8_ix(utf8_end);
|
||||||
|
let utf16_end = cmp::min(ix_converter.utf16_ix, utf16_line_len);
|
||||||
|
|
||||||
|
let cf_range =
|
||||||
|
CFRange::init(utf16_start as isize, (utf16_end - utf16_start) as isize);
|
||||||
let font = &self.fonts[font_id.0];
|
let font = &self.fonts[font_id.0];
|
||||||
unsafe {
|
unsafe {
|
||||||
string.set_attribute(
|
string.set_attribute(
|
||||||
|
@ -245,6 +250,10 @@ impl FontSystemState {
|
||||||
&CFNumber::from(font_id.0 as i64),
|
&CFNumber::from(font_id.0 as i64),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if utf16_end == utf16_line_len {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,7 +492,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_layout_line() {
|
fn test_wrap_line() {
|
||||||
let fonts = FontSystem::new();
|
let fonts = FontSystem::new();
|
||||||
let font_ids = fonts.load_family("Helvetica").unwrap();
|
let font_ids = fonts.load_family("Helvetica").unwrap();
|
||||||
let font_id = fonts.select_font(&font_ids, &Default::default()).unwrap();
|
let font_id = fonts.select_font(&font_ids, &Default::default()).unwrap();
|
||||||
|
@ -499,4 +508,25 @@ mod tests {
|
||||||
&["aaa ααα ".len(), "aaa ααα ✋✋✋ ".len(),]
|
&["aaa ααα ".len(), "aaa ααα ✋✋✋ ".len(),]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_layout_line_bom_char() {
|
||||||
|
let fonts = FontSystem::new();
|
||||||
|
let font_ids = fonts.load_family("Helvetica").unwrap();
|
||||||
|
let font_id = fonts.select_font(&font_ids, &Default::default()).unwrap();
|
||||||
|
|
||||||
|
let line = "\u{feff}";
|
||||||
|
let layout = fonts.layout_line(line, 16., &[(line.len(), font_id, Default::default())]);
|
||||||
|
assert_eq!(layout.len, line.len());
|
||||||
|
assert!(layout.runs.is_empty());
|
||||||
|
|
||||||
|
let line = "a\u{feff}b";
|
||||||
|
let layout = fonts.layout_line(line, 16., &[(line.len(), font_id, Default::default())]);
|
||||||
|
assert_eq!(layout.len, line.len());
|
||||||
|
assert_eq!(layout.runs.len(), 1);
|
||||||
|
assert_eq!(layout.runs[0].glyphs.len(), 2);
|
||||||
|
assert_eq!(layout.runs[0].glyphs[0].id, 68); // a
|
||||||
|
// There's no glyph for \u{feff}
|
||||||
|
assert_eq!(layout.runs[0].glyphs[1].id, 69); // b
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
BIN
zed/app-icon.png
BIN
zed/app-icon.png
Binary file not shown.
Before Width: | Height: | Size: 158 KiB After Width: | Height: | Size: 4.4 KiB |
Binary file not shown.
Before Width: | Height: | Size: 579 KiB After Width: | Height: | Size: 8.7 KiB |
|
@ -3,7 +3,7 @@ use crate::{
|
||||||
settings::Settings,
|
settings::Settings,
|
||||||
util,
|
util,
|
||||||
workspace::Workspace,
|
workspace::Workspace,
|
||||||
worktree::{match_paths, PathMatch, Worktree},
|
worktree::{match_paths, PathMatch},
|
||||||
};
|
};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
elements::*,
|
elements::*,
|
||||||
|
@ -124,9 +124,12 @@ impl FileFinder {
|
||||||
let finder = finder.read(cx);
|
let finder = finder.read(cx);
|
||||||
let start = range.start;
|
let start = range.start;
|
||||||
range.end = cmp::min(range.end, finder.matches.len());
|
range.end = cmp::min(range.end, finder.matches.len());
|
||||||
items.extend(finder.matches[range].iter().enumerate().filter_map(
|
items.extend(
|
||||||
move |(i, path_match)| finder.render_match(path_match, start + i, cx),
|
finder.matches[range]
|
||||||
));
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(move |(i, path_match)| finder.render_match(path_match, start + i)),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -135,12 +138,7 @@ impl FileFinder {
|
||||||
.named("matches")
|
.named("matches")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_match(
|
fn render_match(&self, path_match: &PathMatch, index: usize) -> ElementBox {
|
||||||
&self,
|
|
||||||
path_match: &PathMatch,
|
|
||||||
index: usize,
|
|
||||||
cx: &AppContext,
|
|
||||||
) -> Option<ElementBox> {
|
|
||||||
let selected_index = self.selected_index();
|
let selected_index = self.selected_index();
|
||||||
let settings = self.settings.borrow();
|
let settings = self.settings.borrow();
|
||||||
let style = if index == selected_index {
|
let style = if index == selected_index {
|
||||||
|
@ -148,8 +146,8 @@ impl FileFinder {
|
||||||
} else {
|
} else {
|
||||||
&settings.theme.ui.selector.item
|
&settings.theme.ui.selector.item
|
||||||
};
|
};
|
||||||
self.labels_for_match(path_match, cx).map(
|
let (file_name, file_name_positions, full_path, full_path_positions) =
|
||||||
|(file_name, file_name_positions, full_path, full_path_positions)| {
|
self.labels_for_match(path_match);
|
||||||
let container = Container::new(
|
let container = Container::new(
|
||||||
Flex::row()
|
Flex::row()
|
||||||
.with_child(
|
.with_child(
|
||||||
|
@ -205,32 +203,19 @@ impl FileFinder {
|
||||||
true
|
true
|
||||||
})
|
})
|
||||||
.named("match")
|
.named("match")
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn labels_for_match(
|
fn labels_for_match(&self, path_match: &PathMatch) -> (String, Vec<usize>, String, Vec<usize>) {
|
||||||
&self,
|
|
||||||
path_match: &PathMatch,
|
|
||||||
cx: &AppContext,
|
|
||||||
) -> Option<(String, Vec<usize>, String, Vec<usize>)> {
|
|
||||||
self.worktree(path_match.tree_id, cx).map(|tree| {
|
|
||||||
let prefix = if path_match.include_root_name {
|
|
||||||
tree.root_name()
|
|
||||||
} else {
|
|
||||||
""
|
|
||||||
};
|
|
||||||
|
|
||||||
let path_string = path_match.path.to_string_lossy();
|
let path_string = path_match.path.to_string_lossy();
|
||||||
let full_path = [prefix, path_string.as_ref()].join("");
|
let full_path = [path_match.path_prefix.as_ref(), path_string.as_ref()].join("");
|
||||||
let path_positions = path_match.positions.clone();
|
let path_positions = path_match.positions.clone();
|
||||||
|
|
||||||
let file_name = path_match.path.file_name().map_or_else(
|
let file_name = path_match.path.file_name().map_or_else(
|
||||||
|| prefix.to_string(),
|
|| path_match.path_prefix.to_string(),
|
||||||
|file_name| file_name.to_string_lossy().to_string(),
|
|file_name| file_name.to_string_lossy().to_string(),
|
||||||
);
|
);
|
||||||
let file_name_start =
|
let file_name_start = path_match.path_prefix.chars().count() + path_string.chars().count()
|
||||||
prefix.chars().count() + path_string.chars().count() - file_name.chars().count();
|
- file_name.chars().count();
|
||||||
let file_name_positions = path_positions
|
let file_name_positions = path_positions
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|pos| {
|
.filter_map(|pos| {
|
||||||
|
@ -243,7 +228,6 @@ impl FileFinder {
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
(file_name, file_name_positions, full_path, path_positions)
|
(file_name, file_name_positions, full_path, path_positions)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toggle(workspace: &mut Workspace, _: &(), cx: &mut ViewContext<Workspace>) {
|
fn toggle(workspace: &mut Workspace, _: &(), cx: &mut ViewContext<Workspace>) {
|
||||||
|
@ -392,11 +376,9 @@ impl FileFinder {
|
||||||
self.cancel_flag = Arc::new(AtomicBool::new(false));
|
self.cancel_flag = Arc::new(AtomicBool::new(false));
|
||||||
let cancel_flag = self.cancel_flag.clone();
|
let cancel_flag = self.cancel_flag.clone();
|
||||||
Some(cx.spawn(|this, mut cx| async move {
|
Some(cx.spawn(|this, mut cx| async move {
|
||||||
let include_root_name = snapshots.len() > 1;
|
|
||||||
let matches = match_paths(
|
let matches = match_paths(
|
||||||
snapshots.iter(),
|
&snapshots,
|
||||||
&query,
|
&query,
|
||||||
include_root_name,
|
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
100,
|
100,
|
||||||
|
@ -429,15 +411,6 @@ impl FileFinder {
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn worktree<'a>(&'a self, tree_id: usize, cx: &'a AppContext) -> Option<&'a Worktree> {
|
|
||||||
self.workspace
|
|
||||||
.upgrade(cx)?
|
|
||||||
.read(cx)
|
|
||||||
.worktrees()
|
|
||||||
.get(&tree_id)
|
|
||||||
.map(|worktree| worktree.read(cx))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -625,7 +598,7 @@ mod tests {
|
||||||
assert_eq!(finder.matches.len(), 1);
|
assert_eq!(finder.matches.len(), 1);
|
||||||
|
|
||||||
let (file_name, file_name_positions, full_path, full_path_positions) =
|
let (file_name, file_name_positions, full_path, full_path_positions) =
|
||||||
finder.labels_for_match(&finder.matches[0], cx).unwrap();
|
finder.labels_for_match(&finder.matches[0]);
|
||||||
assert_eq!(file_name, "the-file");
|
assert_eq!(file_name, "the-file");
|
||||||
assert_eq!(file_name_positions, &[0, 1, 4]);
|
assert_eq!(file_name_positions, &[0, 1, 4]);
|
||||||
assert_eq!(full_path, "the-file");
|
assert_eq!(full_path, "the-file");
|
||||||
|
|
|
@ -1322,14 +1322,31 @@ mod tests {
|
||||||
cx.dispatch_global_action("workspace:new_file", app_state);
|
cx.dispatch_global_action("workspace:new_file", app_state);
|
||||||
let window_id = *cx.window_ids().first().unwrap();
|
let window_id = *cx.window_ids().first().unwrap();
|
||||||
let workspace = cx.root_view::<Workspace>(window_id).unwrap();
|
let workspace = cx.root_view::<Workspace>(window_id).unwrap();
|
||||||
workspace.update(&mut cx, |workspace, cx| {
|
let editor = workspace.update(&mut cx, |workspace, cx| {
|
||||||
let editor = workspace
|
workspace
|
||||||
.active_item(cx)
|
.active_item(cx)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_any()
|
.to_any()
|
||||||
.downcast::<Editor>()
|
.downcast::<Editor>()
|
||||||
.unwrap();
|
.unwrap()
|
||||||
assert!(editor.update(cx, |editor, cx| editor.text(cx).is_empty()));
|
});
|
||||||
|
|
||||||
|
editor.update(&mut cx, |editor, cx| {
|
||||||
|
assert!(editor.text(cx).is_empty());
|
||||||
|
});
|
||||||
|
|
||||||
|
workspace.update(&mut cx, |workspace, cx| workspace.save_active_item(&(), cx));
|
||||||
|
|
||||||
|
let dir = TempDir::new("test-new-empty-workspace").unwrap();
|
||||||
|
cx.simulate_new_path_selection(|_| {
|
||||||
|
Some(dir.path().canonicalize().unwrap().join("the-new-name"))
|
||||||
|
});
|
||||||
|
|
||||||
|
editor
|
||||||
|
.condition(&cx, |editor, cx| editor.title(cx) == "the-new-name")
|
||||||
|
.await;
|
||||||
|
editor.update(&mut cx, |editor, cx| {
|
||||||
|
assert!(!editor.is_dirty(cx));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -586,17 +586,11 @@ impl LocalWorktree {
|
||||||
|
|
||||||
// After determining whether the root entry is a file or a directory, populate the
|
// After determining whether the root entry is a file or a directory, populate the
|
||||||
// snapshot's "root name", which will be used for the purpose of fuzzy matching.
|
// snapshot's "root name", which will be used for the purpose of fuzzy matching.
|
||||||
let mut root_name = abs_path
|
let root_name = abs_path
|
||||||
.file_name()
|
.file_name()
|
||||||
.map_or(String::new(), |f| f.to_string_lossy().to_string());
|
.map_or(String::new(), |f| f.to_string_lossy().to_string());
|
||||||
let root_char_bag = root_name.chars().map(|c| c.to_ascii_lowercase()).collect();
|
let root_char_bag = root_name.chars().map(|c| c.to_ascii_lowercase()).collect();
|
||||||
let metadata = fs
|
let metadata = fs.metadata(&abs_path).await?;
|
||||||
.metadata(&abs_path)
|
|
||||||
.await?
|
|
||||||
.ok_or_else(|| anyhow!("root entry does not exist"))?;
|
|
||||||
if metadata.is_dir {
|
|
||||||
root_name.push('/');
|
|
||||||
}
|
|
||||||
|
|
||||||
let (scan_states_tx, scan_states_rx) = smol::channel::unbounded();
|
let (scan_states_tx, scan_states_rx) = smol::channel::unbounded();
|
||||||
let (mut last_scan_state_tx, last_scan_state_rx) = watch::channel_with(ScanState::Scanning);
|
let (mut last_scan_state_tx, last_scan_state_rx) = watch::channel_with(ScanState::Scanning);
|
||||||
|
@ -613,12 +607,14 @@ impl LocalWorktree {
|
||||||
removed_entry_ids: Default::default(),
|
removed_entry_ids: Default::default(),
|
||||||
next_entry_id: Arc::new(next_entry_id),
|
next_entry_id: Arc::new(next_entry_id),
|
||||||
};
|
};
|
||||||
|
if let Some(metadata) = metadata {
|
||||||
snapshot.insert_entry(Entry::new(
|
snapshot.insert_entry(Entry::new(
|
||||||
path.into(),
|
path.into(),
|
||||||
&metadata,
|
&metadata,
|
||||||
&snapshot.next_entry_id,
|
&snapshot.next_entry_id,
|
||||||
snapshot.root_char_bag,
|
snapshot.root_char_bag,
|
||||||
));
|
));
|
||||||
|
}
|
||||||
|
|
||||||
let tree = Self {
|
let tree = Self {
|
||||||
snapshot: snapshot.clone(),
|
snapshot: snapshot.clone(),
|
||||||
|
@ -1229,12 +1225,10 @@ impl Snapshot {
|
||||||
ChildEntriesIter::new(path, self)
|
ChildEntriesIter::new(path, self)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn root_entry(&self) -> &Entry {
|
pub fn root_entry(&self) -> Option<&Entry> {
|
||||||
self.entry_for_path("").unwrap()
|
self.entry_for_path("")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the filename of the snapshot's root, plus a trailing slash if the snapshot's root is
|
|
||||||
/// a directory.
|
|
||||||
pub fn root_name(&self) -> &str {
|
pub fn root_name(&self) -> &str {
|
||||||
&self.root_name
|
&self.root_name
|
||||||
}
|
}
|
||||||
|
@ -1856,8 +1850,8 @@ impl BackgroundScanner {
|
||||||
let snapshot = self.snapshot.lock();
|
let snapshot = self.snapshot.lock();
|
||||||
root_char_bag = snapshot.root_char_bag;
|
root_char_bag = snapshot.root_char_bag;
|
||||||
next_entry_id = snapshot.next_entry_id.clone();
|
next_entry_id = snapshot.next_entry_id.clone();
|
||||||
is_dir = snapshot.root_entry().is_dir();
|
is_dir = snapshot.root_entry().map_or(false, |e| e.is_dir())
|
||||||
}
|
};
|
||||||
|
|
||||||
if is_dir {
|
if is_dir {
|
||||||
let path: Arc<Path> = Arc::from(Path::new(""));
|
let path: Arc<Path> = Arc::from(Path::new(""));
|
||||||
|
@ -2605,25 +2599,23 @@ mod tests {
|
||||||
|
|
||||||
cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete())
|
cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete())
|
||||||
.await;
|
.await;
|
||||||
let snapshot = cx.read(|cx| {
|
let snapshots = [cx.read(|cx| {
|
||||||
let tree = tree.read(cx);
|
let tree = tree.read(cx);
|
||||||
assert_eq!(tree.file_count(), 5);
|
assert_eq!(tree.file_count(), 5);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tree.inode_for_path("fennel/grape"),
|
tree.inode_for_path("fennel/grape"),
|
||||||
tree.inode_for_path("finnochio/grape")
|
tree.inode_for_path("finnochio/grape")
|
||||||
);
|
);
|
||||||
|
|
||||||
tree.snapshot()
|
tree.snapshot()
|
||||||
});
|
})];
|
||||||
let cancel_flag = Default::default();
|
let cancel_flag = Default::default();
|
||||||
let results = cx
|
let results = cx
|
||||||
.read(|cx| {
|
.read(|cx| {
|
||||||
match_paths(
|
match_paths(
|
||||||
Some(&snapshot).into_iter(),
|
&snapshots,
|
||||||
"bna",
|
"bna",
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
|
||||||
10,
|
10,
|
||||||
&cancel_flag,
|
&cancel_flag,
|
||||||
cx.background().clone(),
|
cx.background().clone(),
|
||||||
|
@ -2663,20 +2655,19 @@ mod tests {
|
||||||
|
|
||||||
cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete())
|
cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete())
|
||||||
.await;
|
.await;
|
||||||
let snapshot = cx.read(|cx| {
|
let snapshots = [cx.read(|cx| {
|
||||||
let tree = tree.read(cx);
|
let tree = tree.read(cx);
|
||||||
assert_eq!(tree.file_count(), 0);
|
assert_eq!(tree.file_count(), 0);
|
||||||
tree.snapshot()
|
tree.snapshot()
|
||||||
});
|
})];
|
||||||
let cancel_flag = Default::default();
|
let cancel_flag = Default::default();
|
||||||
let results = cx
|
let results = cx
|
||||||
.read(|cx| {
|
.read(|cx| {
|
||||||
match_paths(
|
match_paths(
|
||||||
Some(&snapshot).into_iter(),
|
&snapshots,
|
||||||
"dir",
|
"dir",
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
|
||||||
10,
|
10,
|
||||||
&cancel_flag,
|
&cancel_flag,
|
||||||
cx.background().clone(),
|
cx.background().clone(),
|
||||||
|
|
|
@ -48,7 +48,7 @@ pub struct PathMatch {
|
||||||
pub positions: Vec<usize>,
|
pub positions: Vec<usize>,
|
||||||
pub tree_id: usize,
|
pub tree_id: usize,
|
||||||
pub path: Arc<Path>,
|
pub path: Arc<Path>,
|
||||||
pub include_root_name: bool,
|
pub path_prefix: Arc<str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -207,23 +207,19 @@ pub async fn match_strings(
|
||||||
results
|
results
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn match_paths<'a, T>(
|
pub async fn match_paths(
|
||||||
snapshots: T,
|
snapshots: &[Snapshot],
|
||||||
query: &str,
|
query: &str,
|
||||||
include_root_name: bool,
|
|
||||||
include_ignored: bool,
|
include_ignored: bool,
|
||||||
smart_case: bool,
|
smart_case: bool,
|
||||||
max_results: usize,
|
max_results: usize,
|
||||||
cancel_flag: &AtomicBool,
|
cancel_flag: &AtomicBool,
|
||||||
background: Arc<executor::Background>,
|
background: Arc<executor::Background>,
|
||||||
) -> Vec<PathMatch>
|
) -> Vec<PathMatch> {
|
||||||
where
|
|
||||||
T: Clone + Send + Iterator<Item = &'a Snapshot> + 'a,
|
|
||||||
{
|
|
||||||
let path_count: usize = if include_ignored {
|
let path_count: usize = if include_ignored {
|
||||||
snapshots.clone().map(Snapshot::file_count).sum()
|
snapshots.iter().map(Snapshot::file_count).sum()
|
||||||
} else {
|
} else {
|
||||||
snapshots.clone().map(Snapshot::visible_file_count).sum()
|
snapshots.iter().map(Snapshot::visible_file_count).sum()
|
||||||
};
|
};
|
||||||
if path_count == 0 {
|
if path_count == 0 {
|
||||||
return Vec::new();
|
return Vec::new();
|
||||||
|
@ -245,7 +241,6 @@ where
|
||||||
background
|
background
|
||||||
.scoped(|scope| {
|
.scoped(|scope| {
|
||||||
for (segment_idx, results) in segment_results.iter_mut().enumerate() {
|
for (segment_idx, results) in segment_results.iter_mut().enumerate() {
|
||||||
let snapshots = snapshots.clone();
|
|
||||||
scope.spawn(async move {
|
scope.spawn(async move {
|
||||||
let segment_start = segment_idx * segment_size;
|
let segment_start = segment_idx * segment_size;
|
||||||
let segment_end = segment_start + segment_size;
|
let segment_end = segment_start + segment_size;
|
||||||
|
@ -265,9 +260,16 @@ where
|
||||||
tree_start + snapshot.visible_file_count()
|
tree_start + snapshot.visible_file_count()
|
||||||
};
|
};
|
||||||
|
|
||||||
let include_root_name =
|
|
||||||
include_root_name || snapshot.root_entry().is_file();
|
|
||||||
if tree_start < segment_end && segment_start < tree_end {
|
if tree_start < segment_end && segment_start < tree_end {
|
||||||
|
let path_prefix: Arc<str> =
|
||||||
|
if snapshot.root_entry().map_or(false, |e| e.is_file()) {
|
||||||
|
snapshot.root_name().into()
|
||||||
|
} else if snapshots.len() > 1 {
|
||||||
|
format!("{}/", snapshot.root_name()).into()
|
||||||
|
} else {
|
||||||
|
"".into()
|
||||||
|
};
|
||||||
|
|
||||||
let start = max(tree_start, segment_start) - tree_start;
|
let start = max(tree_start, segment_start) - tree_start;
|
||||||
let end = min(tree_end, segment_end) - tree_start;
|
let end = min(tree_end, segment_end) - tree_start;
|
||||||
let entries = if include_ignored {
|
let entries = if include_ignored {
|
||||||
|
@ -288,7 +290,7 @@ where
|
||||||
|
|
||||||
matcher.match_paths(
|
matcher.match_paths(
|
||||||
snapshot,
|
snapshot,
|
||||||
include_root_name,
|
path_prefix,
|
||||||
paths,
|
paths,
|
||||||
results,
|
results,
|
||||||
&cancel_flag,
|
&cancel_flag,
|
||||||
|
@ -360,19 +362,13 @@ impl<'a> Matcher<'a> {
|
||||||
fn match_paths(
|
fn match_paths(
|
||||||
&mut self,
|
&mut self,
|
||||||
snapshot: &Snapshot,
|
snapshot: &Snapshot,
|
||||||
include_root_name: bool,
|
path_prefix: Arc<str>,
|
||||||
path_entries: impl Iterator<Item = PathMatchCandidate<'a>>,
|
path_entries: impl Iterator<Item = PathMatchCandidate<'a>>,
|
||||||
results: &mut Vec<PathMatch>,
|
results: &mut Vec<PathMatch>,
|
||||||
cancel_flag: &AtomicBool,
|
cancel_flag: &AtomicBool,
|
||||||
) {
|
) {
|
||||||
let tree_id = snapshot.id;
|
let tree_id = snapshot.id;
|
||||||
let prefix = if include_root_name {
|
let prefix = path_prefix.chars().collect::<Vec<_>>();
|
||||||
snapshot.root_name()
|
|
||||||
} else {
|
|
||||||
""
|
|
||||||
}
|
|
||||||
.chars()
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let lowercase_prefix = prefix
|
let lowercase_prefix = prefix
|
||||||
.iter()
|
.iter()
|
||||||
.map(|c| c.to_ascii_lowercase())
|
.map(|c| c.to_ascii_lowercase())
|
||||||
|
@ -388,7 +384,7 @@ impl<'a> Matcher<'a> {
|
||||||
tree_id,
|
tree_id,
|
||||||
positions: Vec::new(),
|
positions: Vec::new(),
|
||||||
path: candidate.path.clone(),
|
path: candidate.path.clone(),
|
||||||
include_root_name,
|
path_prefix: path_prefix.clone(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -772,7 +768,7 @@ mod tests {
|
||||||
root_char_bag: Default::default(),
|
root_char_bag: Default::default(),
|
||||||
next_entry_id: Default::default(),
|
next_entry_id: Default::default(),
|
||||||
},
|
},
|
||||||
false,
|
"".into(),
|
||||||
path_entries.into_iter(),
|
path_entries.into_iter(),
|
||||||
&mut results,
|
&mut results,
|
||||||
&cancel_flag,
|
&cancel_flag,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue