aboutsummaryrefslogtreecommitdiff
path: root/helix-term/src/ui/mod.rs
diff options
context:
space:
mode:
authorBlaž Hrastnik2022-02-28 09:15:34 +0000
committerBlaž Hrastnik2022-03-03 07:52:41 +0000
commit78fba8683bdce31ad2d8e710cb70fb9f05b21e8c (patch)
tree760e5743c3f6c378164cd90cb2723036b3072e1e /helix-term/src/ui/mod.rs
parent0ff3e3ea38120474772052ca649d9989405b4ce5 (diff)
Picker performance improvements
Diffstat (limited to 'helix-term/src/ui/mod.rs')
-rw-r--r--helix-term/src/ui/mod.rs44
1 files changed, 17 insertions, 27 deletions
diff --git a/helix-term/src/ui/mod.rs b/helix-term/src/ui/mod.rs
index 011ad9ba..d46de2d3 100644
--- a/helix-term/src/ui/mod.rs
+++ b/helix-term/src/ui/mod.rs
@@ -98,7 +98,9 @@ pub fn regex_prompt(
pub fn file_picker(root: PathBuf, config: &helix_view::editor::Config) -> FilePicker<PathBuf> {
use ignore::{types::TypesBuilder, WalkBuilder};
- use std::time;
+ use std::time::Instant;
+
+ let now = Instant::now();
let mut walk_builder = WalkBuilder::new(&root);
walk_builder
@@ -116,56 +118,44 @@ pub fn file_picker(root: PathBuf, config: &helix_view::editor::Config) -> FilePi
// We want to exclude files that the editor can't handle yet
let mut type_builder = TypesBuilder::new();
-
type_builder
.add(
"compressed",
"*.{zip,gz,bz2,zst,lzo,sz,tgz,tbz2,lz,lz4,lzma,lzo,z,Z,xz,7z,rar,cab}",
)
- // This shouldn't panic as the above is static, but if it ever
- // is changed and becomes invalid it will catch here rather than
- // being unnoticed.
.expect("Invalid type definition");
type_builder.negate("all");
-
- if let Ok(excluded_types) = type_builder.build() {
- walk_builder.types(excluded_types);
- }
+ let excluded_types = type_builder
+ .build()
+ .expect("failed to build excluded_types");
+ walk_builder.types(excluded_types);
// We want files along with their modification date for sorting
let files = walk_builder.build().filter_map(|entry| {
let entry = entry.ok()?;
- // Path::is_dir() traverses symlinks, so we use it over DirEntry::is_dir
- if entry.path().is_dir() {
+
+ // This is faster than entry.path().is_dir() since it uses cached fs::Metadata fetched by ignore/walkdir
+ let is_dir = entry.file_type().map(|ft| ft.is_dir()).unwrap_or(false);
+
+ if is_dir {
// Will give a false positive if metadata cannot be read (eg. permission error)
return None;
}
- let time = entry.metadata().map_or(time::UNIX_EPOCH, |metadata| {
- metadata
- .accessed()
- .or_else(|_| metadata.modified())
- .or_else(|_| metadata.created())
- .unwrap_or(time::UNIX_EPOCH)
- });
-
- Some((entry.into_path(), time))
+ Some(entry.into_path())
});
// Cap the number of files if we aren't in a git project, preventing
// hangs when using the picker in your home directory
- let mut files: Vec<_> = if root.join(".git").is_dir() {
+ let files: Vec<_> = if root.join(".git").is_dir() {
files.collect()
} else {
- const MAX: usize = 8192;
+ // const MAX: usize = 8192;
+ const MAX: usize = 100_000;
files.take(MAX).collect()
};
- // Most recently modified first
- files.sort_by_key(|file| std::cmp::Reverse(file.1));
-
- // Strip the time data so we can send just the paths to the FilePicker
- let files = files.into_iter().map(|(path, _)| path).collect();
+ log::debug!("file_picker init {:?}", Instant::now().duration_since(now));
FilePicker::new(
files,