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:
Swarnim Arun 2023-05-12 02:34:52 +05:30
parent 153e060043
commit 73596971bf
No known key found for this signature in database
GPG Key ID: F1EEE523F3F007BE
4 changed files with 28 additions and 18 deletions

View File

@ -64,11 +64,11 @@ pub struct Edit {
#[derive(Clone, Debug, Subcommand)]
pub enum EditCommand {
#[clap(hide = true)]
Decrement { path: String },
Decrement { path: PathBuf },
#[clap(hide = true)]
Delete { path: String },
Delete { path: PathBuf },
#[clap(hide = true)]
Increment { path: String },
Increment { path: PathBuf },
#[clap(hide = true)]
Reload,
}

View File

@ -1,5 +1,6 @@
use std::borrow::Cow;
use std::fmt::{self, Display, Formatter};
use std::path::Path;
use serde::{Deserialize, Serialize};
@ -8,7 +9,7 @@ use crate::util::{DAY, HOUR, WEEK};
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Dir<'a> {
#[serde(borrow)]
pub path: Cow<'a, str>,
pub path: Cow<'a, Path>,
pub rank: Rank,
pub last_accessed: Epoch,
}
@ -61,7 +62,7 @@ impl Display for DirDisplay<'_> {
let score = self.dir.score(now).clamp(0.0, 9999.0);
write!(f, "{score:>6.1}{}", self.separator)?;
}
write!(f, "{}", self.dir.path)
write!(f, "{}", self.dir.path.display())
}
}

View File

@ -64,11 +64,11 @@ impl Database {
}
/// 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()) {
Some(dir) => dir.rank = (dir.rank + by).max(0.0),
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);
@ -77,23 +77,23 @@ impl Database {
/// 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
/// 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| {
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);
}
/// Increments the rank and updates the last_accessed of a directory, or
/// 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()) {
Some(dir) => {
dir.rank = (dir.rank + by).max(0.0);
dir.last_accessed = now;
}
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);
@ -101,7 +101,7 @@ impl Database {
/// Removes the directory with `path` from the store. This does not preserve
/// 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()) {
Some(idx) => {
self.swap_remove(idx);
@ -256,7 +256,7 @@ mod tests {
assert_eq!(db.dirs().len(), 1);
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_eq!(dir.last_accessed, now);
}

View File

@ -1,5 +1,6 @@
use std::iter::Rev;
use std::ops::Range;
use std::path::Path;
use std::{fs, path};
use crate::db::{Database, Dir, Epoch};
@ -71,7 +72,13 @@ impl<'a> Stream<'a> {
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;
continue;
}
@ -87,7 +94,7 @@ impl<'a> Stream<'a> {
self.did_exclude
}
fn matches_exists(&self, path: &str) -> bool {
fn matches_exists(&self, path: &Path) -> bool {
if !self.check_exists {
return true;
}
@ -95,12 +102,14 @@ impl<'a> Stream<'a> {
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() {
Some(split) => split,
None => return true,
};
let Some(path) = path.to_str() else {
return false;
};
let path = util::to_lowercase(path);
let mut path = path.as_str();
match path.rfind(keywords_last) {
@ -155,6 +164,6 @@ mod tests {
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 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)));
}
}