mirror of
https://github.com/Llewellynvdm/zoxide.git
synced 2024-12-29 12:32:40 +00:00
Performance improvements
This commit is contained in:
parent
4414898a06
commit
342954cda0
14
Cargo.lock
generated
14
Cargo.lock
generated
@ -49,7 +49,7 @@ version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.105 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -295,15 +295,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.105"
|
||||
version = "1.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"serde_derive 1.0.105 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.105"
|
||||
version = "1.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -432,7 +432,7 @@ dependencies = [
|
||||
"bstr 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.105 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"structopt 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -475,8 +475,8 @@ dependencies = [
|
||||
"checksum redox_users 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "09b23093265f8d200fa7b4c2c76297f47e681c655f6f1285a8780d6a022f7431"
|
||||
"checksum regex-automata 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4"
|
||||
"checksum rust-argon2 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2bc8af4bda8e1ff4932523b94d3dd20ee30a87232323eda55903ffd71d2fb017"
|
||||
"checksum serde 1.0.105 (registry+https://github.com/rust-lang/crates.io-index)" = "e707fbbf255b8fc8c3b99abb91e7257a622caeb20a9818cbadbeeede4e0932ff"
|
||||
"checksum serde_derive 1.0.105 (registry+https://github.com/rust-lang/crates.io-index)" = "ac5d00fc561ba2724df6758a17de23df5914f20e41cb00f94d5b7ae42fffaff8"
|
||||
"checksum serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)" = "36df6ac6412072f67cf767ebbde4133a5b2e88e76dc6187fa7104cd16f783399"
|
||||
"checksum serde_derive 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)" = "9e549e3abf4fb8621bd1609f11dfc9f5e50320802273b12f3811a67e6716ea6c"
|
||||
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||
"checksum structopt 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "c8faa2719539bbe9d77869bfb15d4ee769f99525e707931452c97b693b3f159d"
|
||||
"checksum structopt-derive 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f88b8e18c69496aad6f9ddf4630dd7d585bcaf765786cb415b9aec2fe5a0430"
|
||||
|
@ -17,7 +17,7 @@ anyhow = "1.0.28"
|
||||
bincode = "1.2.1"
|
||||
clap = "2.33.0"
|
||||
dirs = "2.0.2"
|
||||
serde = { version = "1.0.105", features = ["derive"] }
|
||||
serde = { version = "1.0.106", features = ["derive"] }
|
||||
structopt = "0.3.12"
|
||||
uuid = { version = "0.8.1", features = ["v4"] }
|
||||
|
||||
|
21
src/db.rs
21
src/db.rs
@ -121,7 +121,7 @@ impl DB {
|
||||
continue;
|
||||
};
|
||||
|
||||
let split_line = line.rsplitn(3, '|').collect::<Vec<&str>>();
|
||||
let split_line = line.rsplitn(3, '|').collect::<Vec<_>>();
|
||||
|
||||
match split_line.as_slice() {
|
||||
[epoch_str, rank_str, path_str] => {
|
||||
@ -215,7 +215,7 @@ impl DB {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn query(&mut self, keywords: &[String], now: Epoch) -> Option<Dir> {
|
||||
pub fn query(&mut self, keywords: &[String], now: Epoch) -> Option<&Dir> {
|
||||
let (idx, dir, _) = self
|
||||
.data
|
||||
.dirs
|
||||
@ -228,7 +228,8 @@ impl DB {
|
||||
})?;
|
||||
|
||||
if dir.is_dir() {
|
||||
Some(dir.to_owned())
|
||||
// FIXME: change this to Some(dir) once the MIR borrow checker comes to stable Rust
|
||||
Some(&self.data.dirs[idx])
|
||||
} else {
|
||||
self.data.dirs.swap_remove(idx);
|
||||
self.modified = true;
|
||||
@ -236,7 +237,7 @@ impl DB {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn query_all(&mut self, keywords: &[String]) -> Vec<Dir> {
|
||||
pub fn query_all<'a>(&'a mut self, keywords: &'a [String]) -> impl Iterator<Item = &'a Dir> {
|
||||
let orig_len = self.data.dirs.len();
|
||||
self.data.dirs.retain(Dir::is_dir);
|
||||
|
||||
@ -247,15 +248,17 @@ impl DB {
|
||||
self.data
|
||||
.dirs
|
||||
.iter()
|
||||
.filter(|dir| dir.is_match(&keywords))
|
||||
.cloned()
|
||||
.collect()
|
||||
.filter(move |dir| dir.is_match(keywords))
|
||||
}
|
||||
|
||||
pub fn remove<P: AsRef<Path>>(&mut self, path: P) -> Result<()> {
|
||||
let path_canonicalized;
|
||||
let path_abs = match path.as_ref().canonicalize() {
|
||||
Ok(path_abs) => path_abs,
|
||||
Err(_) => path.as_ref().to_path_buf(),
|
||||
Ok(path_abs) => {
|
||||
path_canonicalized = path_abs;
|
||||
&path_canonicalized
|
||||
}
|
||||
Err(_) => path.as_ref(),
|
||||
};
|
||||
|
||||
if let Some(idx) = self.data.dirs.iter().position(|dir| dir.path == path_abs) {
|
||||
|
@ -5,7 +5,7 @@ use std::path::{Path, PathBuf};
|
||||
pub use f64 as Rank;
|
||||
pub use i64 as Epoch; // use a signed integer so subtraction can be performed on it
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
||||
#[derive(Debug, Default, Deserialize, Serialize)]
|
||||
pub struct Dir {
|
||||
pub path: PathBuf,
|
||||
pub rank: Rank,
|
||||
|
@ -15,20 +15,25 @@ pub struct Add {
|
||||
|
||||
impl Add {
|
||||
pub fn run(&self) -> Result<()> {
|
||||
let mut db = util::get_db()?;
|
||||
let now = util::get_current_time()?;
|
||||
let maxage = config::zo_maxage()?;
|
||||
let excluded_dirs = config::zo_exclude_dirs();
|
||||
|
||||
let current_dir;
|
||||
let path = match &self.path {
|
||||
Some(path) => path.clone(),
|
||||
None => env::current_dir().context("unable to fetch current directory")?,
|
||||
Some(path) => path,
|
||||
None => {
|
||||
current_dir = env::current_dir().context("unable to fetch current directory")?;
|
||||
¤t_dir
|
||||
}
|
||||
};
|
||||
|
||||
if excluded_dirs.contains(&path) {
|
||||
let excluded_dirs = config::zo_exclude_dirs();
|
||||
if excluded_dirs.contains(path) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut db = util::get_db()?;
|
||||
|
||||
let maxage = config::zo_maxage()?;
|
||||
let now = util::get_current_time()?;
|
||||
|
||||
db.add(path, maxage, now)
|
||||
}
|
||||
}
|
||||
|
@ -45,8 +45,6 @@ impl Init {
|
||||
let stdout = io::stdout();
|
||||
let mut handle = stdout.lock();
|
||||
|
||||
// If any `writeln!` call fails to write to stdout, we assume the user's
|
||||
// computer is on fire and panic.
|
||||
let z = config.z;
|
||||
writeln!(handle, "{}", z(&self.z_cmd)).unwrap();
|
||||
|
||||
|
@ -15,7 +15,7 @@ pub struct Query {
|
||||
}
|
||||
|
||||
impl Query {
|
||||
pub fn run(mut self) -> Result<()> {
|
||||
pub fn run(&self) -> Result<()> {
|
||||
let path_opt = if self.interactive {
|
||||
self.query_interactive()?
|
||||
} else {
|
||||
@ -35,7 +35,7 @@ impl Query {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn query(&mut self) -> Result<Option<Vec<u8>>> {
|
||||
fn query(&self) -> Result<Option<Vec<u8>>> {
|
||||
if let [path] = self.keywords.as_slice() {
|
||||
if Path::new(path).is_dir() {
|
||||
return Ok(Some(path.as_bytes().to_vec()));
|
||||
@ -44,11 +44,13 @@ impl Query {
|
||||
|
||||
let now = util::get_current_time()?;
|
||||
|
||||
for keyword in &mut self.keywords {
|
||||
*keyword = keyword.to_lowercase();
|
||||
}
|
||||
let keywords = self
|
||||
.keywords
|
||||
.iter()
|
||||
.map(|keyword| keyword.to_lowercase())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let path_opt = util::get_db()?.query(&self.keywords, now).map(|dir| {
|
||||
let path_opt = util::get_db()?.query(&keywords, now).map(|dir| {
|
||||
// `path_to_bytes` is guaranteed to succeed here since
|
||||
// the path has already been queried successfully
|
||||
let path_bytes = util::path_to_bytes(&dir.path).unwrap();
|
||||
@ -58,14 +60,17 @@ impl Query {
|
||||
Ok(path_opt)
|
||||
}
|
||||
|
||||
fn query_interactive(&mut self) -> Result<Option<Vec<u8>>> {
|
||||
fn query_interactive(&self) -> Result<Option<Vec<u8>>> {
|
||||
let now = util::get_current_time()?;
|
||||
|
||||
for keyword in &mut self.keywords {
|
||||
*keyword = keyword.to_lowercase();
|
||||
}
|
||||
let keywords = self
|
||||
.keywords
|
||||
.iter()
|
||||
.map(|keyword| keyword.to_lowercase())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let dirs = util::get_db()?.query_all(&self.keywords);
|
||||
let mut db = util::get_db()?;
|
||||
let dirs = db.query_all(&keywords);
|
||||
util::fzf_helper(now, dirs)
|
||||
}
|
||||
}
|
||||
|
39
src/util.rs
39
src/util.rs
@ -4,7 +4,7 @@ use crate::dir::{Dir, Epoch};
|
||||
|
||||
use anyhow::{anyhow, bail, Context, Result};
|
||||
|
||||
use std::cmp::{Ordering, PartialOrd};
|
||||
use std::cmp::Reverse;
|
||||
use std::io::{Read, Write};
|
||||
use std::path::Path;
|
||||
use std::process::{Command, Stdio};
|
||||
@ -49,9 +49,12 @@ pub fn get_current_time() -> Result<Epoch> {
|
||||
Ok(current_time as Epoch)
|
||||
}
|
||||
|
||||
pub fn fzf_helper(now: Epoch, mut dirs: Vec<Dir>) -> Result<Option<Vec<u8>>> {
|
||||
pub fn fzf_helper<'a, I>(now: Epoch, dirs: I) -> Result<Option<Vec<u8>>>
|
||||
where
|
||||
I: IntoIterator<Item = &'a Dir>,
|
||||
{
|
||||
let mut fzf = Command::new("fzf")
|
||||
.arg("-n2..")
|
||||
.args(&["-n2..", "--no-sort"])
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
@ -62,26 +65,20 @@ pub fn fzf_helper(now: Epoch, mut dirs: Vec<Dir>) -> Result<Option<Vec<u8>>> {
|
||||
.as_mut()
|
||||
.ok_or_else(|| anyhow!("could not connect to fzf stdin"))?;
|
||||
|
||||
for dir in dirs.iter_mut() {
|
||||
dir.rank = dir.get_frecency(now);
|
||||
}
|
||||
let mut dir_frecencies = dirs
|
||||
.into_iter()
|
||||
.map(|dir| (dir, clamp(dir.get_frecency(now), 0.0, 9999.0) as i32))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
dirs.sort_unstable_by(|dir1, dir2| {
|
||||
dir1.rank
|
||||
.partial_cmp(&dir2.rank)
|
||||
.unwrap_or(Ordering::Equal)
|
||||
.reverse()
|
||||
});
|
||||
dir_frecencies.sort_unstable_by_key(|&(dir, frecency)| Reverse((frecency, &dir.path)));
|
||||
|
||||
for dir in dirs.iter() {
|
||||
for &(dir, frecency) in dir_frecencies.iter() {
|
||||
// ensure that frecency fits in 4 characters
|
||||
let frecency = clamp(dir.rank, 0.0, 9999.0);
|
||||
|
||||
if let Some(path_bytes) = path_to_bytes(&dir.path) {
|
||||
(|| {
|
||||
write!(fzf_stdin, "{:>4.0} ", frecency)?;
|
||||
write!(fzf_stdin, "{:>4} ", frecency)?;
|
||||
fzf_stdin.write_all(path_bytes)?;
|
||||
fzf_stdin.write_all(b"\n")
|
||||
writeln!(fzf_stdin)
|
||||
})()
|
||||
.context("could not write into fzf stdin")?;
|
||||
}
|
||||
@ -125,11 +122,11 @@ pub fn fzf_helper(now: Epoch, mut dirs: Vec<Dir>) -> Result<Option<Vec<u8>>> {
|
||||
pub fn clamp(val: f64, min: f64, max: f64) -> f64 {
|
||||
assert!(min <= max);
|
||||
|
||||
if val < min {
|
||||
min
|
||||
} else if val > max {
|
||||
if val > max {
|
||||
max
|
||||
} else {
|
||||
} else if val > min {
|
||||
val
|
||||
} else {
|
||||
min
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user