mirror of
https://github.com/Llewellynvdm/zoxide.git
synced 2024-11-29 07:53:55 +00:00
Performance improvements for queries (#185)
This commit is contained in:
parent
1828414f21
commit
5cb091d30a
@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Manpages for each subcommand.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- `cd -` on fish shells.
|
- `cd -` on fish shells.
|
||||||
|
@ -3,7 +3,7 @@ name = "zoxide"
|
|||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
authors = ["Ajeet D'Souza <98ajeet@gmail.com>"]
|
authors = ["Ajeet D'Souza <98ajeet@gmail.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
description = "A faster way to navigate your filesystem"
|
description = "A smarter cd command"
|
||||||
repository = "https://github.com/ajeetdsouza/zoxide/"
|
repository = "https://github.com/ajeetdsouza/zoxide/"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
keywords = ["cli"]
|
keywords = ["cli"]
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
[![crates.io][crates.io-badge]][crates.io]
|
[![crates.io][crates.io-badge]][crates.io]
|
||||||
|
|
||||||
> A faster way to navigate your filesystem
|
> A smarter cd command
|
||||||
|
|
||||||
`zoxide` is a blazing fast replacement for your `cd` command, inspired by
|
`zoxide` is a blazing fast replacement for your `cd` command, inspired by
|
||||||
[`z`][z] and [`z.lua`][z.lua]. It keeps track of the directories you use most
|
[`z`][z] and [`z.lua`][z.lua]. It keeps track of the directories you use most
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
.TH "zoxide" "1" "2021-04-12" "zoxide" "zoxide"
|
.TH "zoxide" "1" "2021-04-12" "zoxide" "zoxide"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
zoxide - a faster way to navigate your filesystem
|
zoxide - a smarter cd command
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B zoxide \fISUBCOMMAND [OPTIONS]\fR
|
.B zoxide \fISUBCOMMAND [OPTIONS]\fR
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
|
@ -8,7 +8,7 @@ use crate::util;
|
|||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use clap::Clap;
|
use clap::Clap;
|
||||||
|
|
||||||
use std::io::{self, Write};
|
use std::io::{self, BufWriter, Write};
|
||||||
|
|
||||||
/// Search for a directory in the database
|
/// Search for a directory in the database
|
||||||
#[derive(Clap, Debug)]
|
#[derive(Clap, Debug)]
|
||||||
@ -52,6 +52,7 @@ impl Cmd for Query {
|
|||||||
for dir in matches {
|
for dir in matches {
|
||||||
writeln!(handle, "{}", dir.display_score(now)).handle_err("fzf")?;
|
writeln!(handle, "{}", dir.display_score(now)).handle_err("fzf")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let selection = fzf.wait_select()?;
|
let selection = fzf.wait_select()?;
|
||||||
if self.score {
|
if self.score {
|
||||||
print!("{}", selection);
|
print!("{}", selection);
|
||||||
@ -62,8 +63,13 @@ impl Cmd for Query {
|
|||||||
print!("{}", path)
|
print!("{}", path)
|
||||||
}
|
}
|
||||||
} else if self.list {
|
} else if self.list {
|
||||||
|
// Rust does line-buffering by default, i.e. it flushes stdout
|
||||||
|
// after every newline. This is not ideal when printing a large
|
||||||
|
// number of lines, so we put stdout in a BufWriter.
|
||||||
let stdout = io::stdout();
|
let stdout = io::stdout();
|
||||||
let handle = &mut stdout.lock();
|
let stdout = stdout.lock();
|
||||||
|
let mut handle = BufWriter::new(stdout);
|
||||||
|
|
||||||
for dir in matches {
|
for dir in matches {
|
||||||
if self.score {
|
if self.score {
|
||||||
writeln!(handle, "{}", dir.display_score(now))
|
writeln!(handle, "{}", dir.display_score(now))
|
||||||
@ -72,6 +78,7 @@ impl Cmd for Query {
|
|||||||
}
|
}
|
||||||
.handle_err("stdout")?;
|
.handle_err("stdout")?;
|
||||||
}
|
}
|
||||||
|
handle.flush().handle_err("stdout")?;
|
||||||
} else {
|
} else {
|
||||||
let dir = matches.next().context("no match found")?;
|
let dir = matches.next().context("no match found")?;
|
||||||
if self.score {
|
if self.score {
|
||||||
|
@ -8,36 +8,25 @@ impl Query {
|
|||||||
I: IntoIterator<Item = S>,
|
I: IntoIterator<Item = S>,
|
||||||
S: AsRef<str>,
|
S: AsRef<str>,
|
||||||
{
|
{
|
||||||
Query(
|
Query(keywords.into_iter().map(|s: S| to_lowercase(s)).collect())
|
||||||
keywords
|
|
||||||
.into_iter()
|
|
||||||
.map(|s: S| s.as_ref().to_lowercase())
|
|
||||||
.collect(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn keywords(&self) -> &[String] {
|
|
||||||
&self.0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn matches<S: AsRef<str>>(&self, path: S) -> bool {
|
pub fn matches<S: AsRef<str>>(&self, path: S) -> bool {
|
||||||
let path = path.as_ref().to_lowercase();
|
let keywords = &self.0;
|
||||||
let keywords = self.keywords();
|
let keywords_last = match keywords.last() {
|
||||||
|
Some(keyword) => keyword,
|
||||||
let get_filenames = || {
|
None => return true,
|
||||||
let query_name = Path::new(keywords.last()?).file_name()?.to_str().unwrap();
|
|
||||||
let dir_name = Path::new(&path).file_name()?.to_str().unwrap();
|
|
||||||
Some((query_name, dir_name))
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some((query_name, dir_name)) = get_filenames() {
|
let path = to_lowercase(path);
|
||||||
if !dir_name.contains(query_name) {
|
|
||||||
return false;
|
let query_name = get_filename(keywords_last);
|
||||||
}
|
let dir_name = get_filename(&path);
|
||||||
|
if !dir_name.contains(query_name) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut subpath = path.as_str();
|
let mut subpath = path.as_str();
|
||||||
|
|
||||||
for keyword in keywords.iter() {
|
for keyword in keywords.iter() {
|
||||||
match subpath.find(keyword) {
|
match subpath.find(keyword) {
|
||||||
Some(idx) => subpath = &subpath[idx + keyword.len()..],
|
Some(idx) => subpath = &subpath[idx + keyword.len()..],
|
||||||
@ -49,6 +38,33 @@ impl Query {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_filename(mut path: &str) -> &str {
|
||||||
|
if cfg!(windows) {
|
||||||
|
Path::new(path)
|
||||||
|
.file_name()
|
||||||
|
.unwrap_or_default()
|
||||||
|
.to_str()
|
||||||
|
.unwrap_or_default()
|
||||||
|
} else {
|
||||||
|
if path.ends_with('/') {
|
||||||
|
path = &path[..path.len() - 1];
|
||||||
|
}
|
||||||
|
match path.rfind('/') {
|
||||||
|
Some(idx) => &path[idx + 1..],
|
||||||
|
None => path,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_lowercase<S: AsRef<str>>(s: S) -> String {
|
||||||
|
let s = s.as_ref();
|
||||||
|
if s.is_ascii() {
|
||||||
|
s.to_ascii_lowercase()
|
||||||
|
} else {
|
||||||
|
s.to_lowercase()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::Query;
|
use super::Query;
|
||||||
|
Loading…
Reference in New Issue
Block a user