mirror of
https://github.com/Llewellynvdm/zoxide.git
synced 2025-01-01 05:31:48 +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"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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]]
|
[[package]]
|
||||||
@ -295,15 +295,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.105"
|
version = "1.0.106"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.105"
|
version = "1.0.106"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"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)",
|
"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)",
|
"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)",
|
"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 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 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 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 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)" = "36df6ac6412072f67cf767ebbde4133a5b2e88e76dc6187fa7104cd16f783399"
|
||||||
"checksum serde_derive 1.0.105 (registry+https://github.com/rust-lang/crates.io-index)" = "ac5d00fc561ba2724df6758a17de23df5914f20e41cb00f94d5b7ae42fffaff8"
|
"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 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 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"
|
"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"
|
bincode = "1.2.1"
|
||||||
clap = "2.33.0"
|
clap = "2.33.0"
|
||||||
dirs = "2.0.2"
|
dirs = "2.0.2"
|
||||||
serde = { version = "1.0.105", features = ["derive"] }
|
serde = { version = "1.0.106", features = ["derive"] }
|
||||||
structopt = "0.3.12"
|
structopt = "0.3.12"
|
||||||
uuid = { version = "0.8.1", features = ["v4"] }
|
uuid = { version = "0.8.1", features = ["v4"] }
|
||||||
|
|
||||||
|
21
src/db.rs
21
src/db.rs
@ -121,7 +121,7 @@ impl DB {
|
|||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
let split_line = line.rsplitn(3, '|').collect::<Vec<&str>>();
|
let split_line = line.rsplitn(3, '|').collect::<Vec<_>>();
|
||||||
|
|
||||||
match split_line.as_slice() {
|
match split_line.as_slice() {
|
||||||
[epoch_str, rank_str, path_str] => {
|
[epoch_str, rank_str, path_str] => {
|
||||||
@ -215,7 +215,7 @@ impl DB {
|
|||||||
Ok(())
|
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
|
let (idx, dir, _) = self
|
||||||
.data
|
.data
|
||||||
.dirs
|
.dirs
|
||||||
@ -228,7 +228,8 @@ impl DB {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
if dir.is_dir() {
|
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 {
|
} else {
|
||||||
self.data.dirs.swap_remove(idx);
|
self.data.dirs.swap_remove(idx);
|
||||||
self.modified = true;
|
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();
|
let orig_len = self.data.dirs.len();
|
||||||
self.data.dirs.retain(Dir::is_dir);
|
self.data.dirs.retain(Dir::is_dir);
|
||||||
|
|
||||||
@ -247,15 +248,17 @@ impl DB {
|
|||||||
self.data
|
self.data
|
||||||
.dirs
|
.dirs
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|dir| dir.is_match(&keywords))
|
.filter(move |dir| dir.is_match(keywords))
|
||||||
.cloned()
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove<P: AsRef<Path>>(&mut self, path: P) -> Result<()> {
|
pub fn remove<P: AsRef<Path>>(&mut self, path: P) -> Result<()> {
|
||||||
|
let path_canonicalized;
|
||||||
let path_abs = match path.as_ref().canonicalize() {
|
let path_abs = match path.as_ref().canonicalize() {
|
||||||
Ok(path_abs) => path_abs,
|
Ok(path_abs) => {
|
||||||
Err(_) => path.as_ref().to_path_buf(),
|
path_canonicalized = path_abs;
|
||||||
|
&path_canonicalized
|
||||||
|
}
|
||||||
|
Err(_) => path.as_ref(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(idx) = self.data.dirs.iter().position(|dir| dir.path == path_abs) {
|
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 f64 as Rank;
|
||||||
pub use i64 as Epoch; // use a signed integer so subtraction can be performed on it
|
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 struct Dir {
|
||||||
pub path: PathBuf,
|
pub path: PathBuf,
|
||||||
pub rank: Rank,
|
pub rank: Rank,
|
||||||
|
@ -15,20 +15,25 @@ pub struct Add {
|
|||||||
|
|
||||||
impl Add {
|
impl Add {
|
||||||
pub fn run(&self) -> Result<()> {
|
pub fn run(&self) -> Result<()> {
|
||||||
let mut db = util::get_db()?;
|
let current_dir;
|
||||||
let now = util::get_current_time()?;
|
|
||||||
let maxage = config::zo_maxage()?;
|
|
||||||
let excluded_dirs = config::zo_exclude_dirs();
|
|
||||||
|
|
||||||
let path = match &self.path {
|
let path = match &self.path {
|
||||||
Some(path) => path.clone(),
|
Some(path) => path,
|
||||||
None => env::current_dir().context("unable to fetch current directory")?,
|
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(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut db = util::get_db()?;
|
||||||
|
|
||||||
|
let maxage = config::zo_maxage()?;
|
||||||
|
let now = util::get_current_time()?;
|
||||||
|
|
||||||
db.add(path, maxage, now)
|
db.add(path, maxage, now)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,8 +45,6 @@ impl Init {
|
|||||||
let stdout = io::stdout();
|
let stdout = io::stdout();
|
||||||
let mut handle = stdout.lock();
|
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;
|
let z = config.z;
|
||||||
writeln!(handle, "{}", z(&self.z_cmd)).unwrap();
|
writeln!(handle, "{}", z(&self.z_cmd)).unwrap();
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ pub struct Query {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Query {
|
impl Query {
|
||||||
pub fn run(mut self) -> Result<()> {
|
pub fn run(&self) -> Result<()> {
|
||||||
let path_opt = if self.interactive {
|
let path_opt = if self.interactive {
|
||||||
self.query_interactive()?
|
self.query_interactive()?
|
||||||
} else {
|
} else {
|
||||||
@ -35,7 +35,7 @@ impl Query {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn query(&mut self) -> Result<Option<Vec<u8>>> {
|
fn query(&self) -> Result<Option<Vec<u8>>> {
|
||||||
if let [path] = self.keywords.as_slice() {
|
if let [path] = self.keywords.as_slice() {
|
||||||
if Path::new(path).is_dir() {
|
if Path::new(path).is_dir() {
|
||||||
return Ok(Some(path.as_bytes().to_vec()));
|
return Ok(Some(path.as_bytes().to_vec()));
|
||||||
@ -44,11 +44,13 @@ impl Query {
|
|||||||
|
|
||||||
let now = util::get_current_time()?;
|
let now = util::get_current_time()?;
|
||||||
|
|
||||||
for keyword in &mut self.keywords {
|
let keywords = self
|
||||||
*keyword = keyword.to_lowercase();
|
.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
|
// `path_to_bytes` is guaranteed to succeed here since
|
||||||
// the path has already been queried successfully
|
// the path has already been queried successfully
|
||||||
let path_bytes = util::path_to_bytes(&dir.path).unwrap();
|
let path_bytes = util::path_to_bytes(&dir.path).unwrap();
|
||||||
@ -58,14 +60,17 @@ impl Query {
|
|||||||
Ok(path_opt)
|
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()?;
|
let now = util::get_current_time()?;
|
||||||
|
|
||||||
for keyword in &mut self.keywords {
|
let keywords = self
|
||||||
*keyword = keyword.to_lowercase();
|
.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)
|
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 anyhow::{anyhow, bail, Context, Result};
|
||||||
|
|
||||||
use std::cmp::{Ordering, PartialOrd};
|
use std::cmp::Reverse;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
@ -49,9 +49,12 @@ pub fn get_current_time() -> Result<Epoch> {
|
|||||||
Ok(current_time as 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")
|
let mut fzf = Command::new("fzf")
|
||||||
.arg("-n2..")
|
.args(&["-n2..", "--no-sort"])
|
||||||
.stdin(Stdio::piped())
|
.stdin(Stdio::piped())
|
||||||
.stdout(Stdio::piped())
|
.stdout(Stdio::piped())
|
||||||
.spawn()
|
.spawn()
|
||||||
@ -62,26 +65,20 @@ pub fn fzf_helper(now: Epoch, mut dirs: Vec<Dir>) -> Result<Option<Vec<u8>>> {
|
|||||||
.as_mut()
|
.as_mut()
|
||||||
.ok_or_else(|| anyhow!("could not connect to fzf stdin"))?;
|
.ok_or_else(|| anyhow!("could not connect to fzf stdin"))?;
|
||||||
|
|
||||||
for dir in dirs.iter_mut() {
|
let mut dir_frecencies = dirs
|
||||||
dir.rank = dir.get_frecency(now);
|
.into_iter()
|
||||||
}
|
.map(|dir| (dir, clamp(dir.get_frecency(now), 0.0, 9999.0) as i32))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
dirs.sort_unstable_by(|dir1, dir2| {
|
dir_frecencies.sort_unstable_by_key(|&(dir, frecency)| Reverse((frecency, &dir.path)));
|
||||||
dir1.rank
|
|
||||||
.partial_cmp(&dir2.rank)
|
|
||||||
.unwrap_or(Ordering::Equal)
|
|
||||||
.reverse()
|
|
||||||
});
|
|
||||||
|
|
||||||
for dir in dirs.iter() {
|
for &(dir, frecency) in dir_frecencies.iter() {
|
||||||
// ensure that frecency fits in 4 characters
|
// 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) {
|
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(path_bytes)?;
|
||||||
fzf_stdin.write_all(b"\n")
|
writeln!(fzf_stdin)
|
||||||
})()
|
})()
|
||||||
.context("could not write into 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 {
|
pub fn clamp(val: f64, min: f64, max: f64) -> f64 {
|
||||||
assert!(min <= max);
|
assert!(min <= max);
|
||||||
|
|
||||||
if val < min {
|
if val > max {
|
||||||
min
|
|
||||||
} else if val > max {
|
|
||||||
max
|
max
|
||||||
} else {
|
} else if val > min {
|
||||||
val
|
val
|
||||||
|
} else {
|
||||||
|
min
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user