fix: path input consistency & minor code cleanup
this should fix and improve cross platform experience of the application without breaking compatibility with anything, but needs more testing so if anyone wants to try it out they are welcome
This commit is contained in:
parent
153e060043
commit
73596971bf
|
|
@ -64,11 +64,11 @@ pub struct Edit {
|
||||||
#[derive(Clone, Debug, Subcommand)]
|
#[derive(Clone, Debug, Subcommand)]
|
||||||
pub enum EditCommand {
|
pub enum EditCommand {
|
||||||
#[clap(hide = true)]
|
#[clap(hide = true)]
|
||||||
Decrement { path: String },
|
Decrement { path: PathBuf },
|
||||||
#[clap(hide = true)]
|
#[clap(hide = true)]
|
||||||
Delete { path: String },
|
Delete { path: PathBuf },
|
||||||
#[clap(hide = true)]
|
#[clap(hide = true)]
|
||||||
Increment { path: String },
|
Increment { path: PathBuf },
|
||||||
#[clap(hide = true)]
|
#[clap(hide = true)]
|
||||||
Reload,
|
Reload,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::fmt::{self, Display, Formatter};
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
|
@ -8,7 +9,7 @@ use crate::util::{DAY, HOUR, WEEK};
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
pub struct Dir<'a> {
|
pub struct Dir<'a> {
|
||||||
#[serde(borrow)]
|
#[serde(borrow)]
|
||||||
pub path: Cow<'a, str>,
|
pub path: Cow<'a, Path>,
|
||||||
pub rank: Rank,
|
pub rank: Rank,
|
||||||
pub last_accessed: Epoch,
|
pub last_accessed: Epoch,
|
||||||
}
|
}
|
||||||
|
|
@ -61,7 +62,7 @@ impl Display for DirDisplay<'_> {
|
||||||
let score = self.dir.score(now).clamp(0.0, 9999.0);
|
let score = self.dir.score(now).clamp(0.0, 9999.0);
|
||||||
write!(f, "{score:>6.1}{}", self.separator)?;
|
write!(f, "{score:>6.1}{}", self.separator)?;
|
||||||
}
|
}
|
||||||
write!(f, "{}", self.dir.path)
|
write!(f, "{}", self.dir.path.display())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,11 +64,11 @@ impl Database {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Increments the rank of a directory, or creates it if it does not exist.
|
/// Increments the rank of a directory, or creates it if it does not exist.
|
||||||
pub fn add(&mut self, path: impl AsRef<str> + Into<String>, by: Rank, now: Epoch) {
|
pub fn add(&mut self, path: impl AsRef<Path>, by: Rank, now: Epoch) {
|
||||||
self.with_dirs_mut(|dirs| match dirs.iter_mut().find(|dir| dir.path == path.as_ref()) {
|
self.with_dirs_mut(|dirs| match dirs.iter_mut().find(|dir| dir.path == path.as_ref()) {
|
||||||
Some(dir) => dir.rank = (dir.rank + by).max(0.0),
|
Some(dir) => dir.rank = (dir.rank + by).max(0.0),
|
||||||
None => {
|
None => {
|
||||||
dirs.push(Dir { path: path.into().into(), rank: by.max(0.0), last_accessed: now })
|
dirs.push(Dir { path: path.as_ref().to_owned().into(), rank: by.max(0.0), last_accessed: now })
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
self.with_dirty_mut(|dirty| *dirty = true);
|
self.with_dirty_mut(|dirty| *dirty = true);
|
||||||
|
|
@ -77,23 +77,23 @@ impl Database {
|
||||||
/// Creates a new directory. This will create a duplicate entry if this
|
/// Creates a new directory. This will create a duplicate entry if this
|
||||||
/// directory is always in the database, it is expected that the user either
|
/// directory is always in the database, it is expected that the user either
|
||||||
/// does a check before calling this, or calls `dedup()` afterward.
|
/// does a check before calling this, or calls `dedup()` afterward.
|
||||||
pub fn add_unchecked(&mut self, path: impl AsRef<str> + Into<String>, rank: Rank, now: Epoch) {
|
pub fn add_unchecked(&mut self, path: impl AsRef<Path>, rank: Rank, now: Epoch) {
|
||||||
self.with_dirs_mut(|dirs| {
|
self.with_dirs_mut(|dirs| {
|
||||||
dirs.push(Dir { path: path.into().into(), rank, last_accessed: now })
|
dirs.push(Dir { path: path.as_ref().to_owned().into(), rank, last_accessed: now })
|
||||||
});
|
});
|
||||||
self.with_dirty_mut(|dirty| *dirty = true);
|
self.with_dirty_mut(|dirty| *dirty = true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Increments the rank and updates the last_accessed of a directory, or
|
/// Increments the rank and updates the last_accessed of a directory, or
|
||||||
/// creates it if it does not exist.
|
/// creates it if it does not exist.
|
||||||
pub fn add_update(&mut self, path: impl AsRef<str> + Into<String>, by: Rank, now: Epoch) {
|
pub fn add_update(&mut self, path: impl AsRef<Path>, by: Rank, now: Epoch) {
|
||||||
self.with_dirs_mut(|dirs| match dirs.iter_mut().find(|dir| dir.path == path.as_ref()) {
|
self.with_dirs_mut(|dirs| match dirs.iter_mut().find(|dir| dir.path == path.as_ref()) {
|
||||||
Some(dir) => {
|
Some(dir) => {
|
||||||
dir.rank = (dir.rank + by).max(0.0);
|
dir.rank = (dir.rank + by).max(0.0);
|
||||||
dir.last_accessed = now;
|
dir.last_accessed = now;
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
dirs.push(Dir { path: path.into().into(), rank: by.max(0.0), last_accessed: now })
|
dirs.push(Dir { path: path.as_ref().to_owned().into(), rank: by.max(0.0), last_accessed: now })
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
self.with_dirty_mut(|dirty| *dirty = true);
|
self.with_dirty_mut(|dirty| *dirty = true);
|
||||||
|
|
@ -101,7 +101,7 @@ impl Database {
|
||||||
|
|
||||||
/// Removes the directory with `path` from the store. This does not preserve
|
/// Removes the directory with `path` from the store. This does not preserve
|
||||||
/// ordering, but is O(1).
|
/// ordering, but is O(1).
|
||||||
pub fn remove(&mut self, path: impl AsRef<str>) -> bool {
|
pub fn remove(&mut self, path: impl AsRef<Path>) -> bool {
|
||||||
match self.dirs().iter().position(|dir| dir.path == path.as_ref()) {
|
match self.dirs().iter().position(|dir| dir.path == path.as_ref()) {
|
||||||
Some(idx) => {
|
Some(idx) => {
|
||||||
self.swap_remove(idx);
|
self.swap_remove(idx);
|
||||||
|
|
@ -256,7 +256,7 @@ mod tests {
|
||||||
assert_eq!(db.dirs().len(), 1);
|
assert_eq!(db.dirs().len(), 1);
|
||||||
|
|
||||||
let dir = &db.dirs()[0];
|
let dir = &db.dirs()[0];
|
||||||
assert_eq!(dir.path, path);
|
assert_eq!(dir.path, Path::new(path));
|
||||||
assert!((dir.rank - 2.0).abs() < 0.01);
|
assert!((dir.rank - 2.0).abs() < 0.01);
|
||||||
assert_eq!(dir.last_accessed, now);
|
assert_eq!(dir.last_accessed, now);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use std::iter::Rev;
|
use std::iter::Rev;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
use std::path::Path;
|
||||||
use std::{fs, path};
|
use std::{fs, path};
|
||||||
|
|
||||||
use crate::db::{Database, Dir, Epoch};
|
use crate::db::{Database, Dir, Epoch};
|
||||||
|
|
@ -71,7 +72,13 @@ impl<'a> Stream<'a> {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if Some(dir.path.as_ref()) == self.exclude_path.as_deref() {
|
if self
|
||||||
|
.exclude_path
|
||||||
|
.as_deref()
|
||||||
|
.map(|a| dir.path.to_str().map(|x| x == a))
|
||||||
|
.flatten()
|
||||||
|
.unwrap_or_default()
|
||||||
|
{
|
||||||
self.did_exclude = true;
|
self.did_exclude = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -87,7 +94,7 @@ impl<'a> Stream<'a> {
|
||||||
self.did_exclude
|
self.did_exclude
|
||||||
}
|
}
|
||||||
|
|
||||||
fn matches_exists(&self, path: &str) -> bool {
|
fn matches_exists(&self, path: &Path) -> bool {
|
||||||
if !self.check_exists {
|
if !self.check_exists {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -95,12 +102,14 @@ impl<'a> Stream<'a> {
|
||||||
resolver(path).map(|m| m.is_dir()).unwrap_or_default()
|
resolver(path).map(|m| m.is_dir()).unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn matches_keywords(&self, path: &str) -> bool {
|
fn matches_keywords(&self, path: &Path) -> bool {
|
||||||
let (keywords_last, keywords) = match self.keywords.split_last() {
|
let (keywords_last, keywords) = match self.keywords.split_last() {
|
||||||
Some(split) => split,
|
Some(split) => split,
|
||||||
None => return true,
|
None => return true,
|
||||||
};
|
};
|
||||||
|
let Some(path) = path.to_str() else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
let path = util::to_lowercase(path);
|
let path = util::to_lowercase(path);
|
||||||
let mut path = path.as_str();
|
let mut path = path.as_str();
|
||||||
match path.rfind(keywords_last) {
|
match path.rfind(keywords_last) {
|
||||||
|
|
@ -155,6 +164,6 @@ mod tests {
|
||||||
fn query(#[case] keywords: &[&str], #[case] path: &str, #[case] is_match: bool) {
|
fn query(#[case] keywords: &[&str], #[case] path: &str, #[case] is_match: bool) {
|
||||||
let db = &mut Database::new(PathBuf::new(), Vec::new(), |_| Vec::new(), false);
|
let db = &mut Database::new(PathBuf::new(), Vec::new(), |_| Vec::new(), false);
|
||||||
let stream = Stream::new(db, 0).with_keywords(keywords);
|
let stream = Stream::new(db, 0).with_keywords(keywords);
|
||||||
assert_eq!(is_match, stream.matches_keywords(path));
|
assert_eq!(is_match, stream.matches_keywords(Path::new(path)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue