Compare commits

..

1 Commits

@ -0,0 +1,4 @@
# Extend `enumerate-ordered` (new major version!)
Modify `enumerate-ordered` to add more sort-by key options (instead of just times,) including a `printf()`-like "string format" key option.

@ -0,0 +1,78 @@
//! User-defined arbitrary format string ordering key spec & replacement.
use super::*;
use std::{
path::Path,
};
/// Used to identify and parse a token in a format string `%[OPT...]C` where `C` is the character used to idenfity the type's parser as valid for the sequence.
pub trait ParseToken {
/// The returned order-by object that can be reduced to a comparable `Cow<str>`-like slice for comparing with other tokens in a `Format` string.
type Substitute: Ord; //TODO: What trait bounds should be on this? Is it okay to just be `Ord`??? Or must it be something like... `<T: ParseToken>: PartialOrd<T>` instead? (XXX: Is `Ord` enough here? Since the list index of `ParseToken`s will be the same for every path in any given `Format` instance... How can we do this non-polymorphically??? Am I forgetting how to write Rust now...???? ehh...)
// Parsing stage (during arg-parse).
/// Attempt to check if `substring` should match this parser.
/// The layout of `substring` will be in the format `/%.*(.)/` where group 1 is the character matched (and `end_char` is the extracted codepoint of it.)
/// # Returns
/// If it does, the matched portion of `substring` should be returned. (__NOTE__: The returned string **must** be *within* `substring`.)
fn visit<'matched>(&self, substring: &'matched str, end_char: char) -> Option<&'matched str>;
/// Parse from a matched `visit()` call into the options of this instance of the parser type.
/// The options encoded in `substring` should set the state in `self` (if there is state.)
/// If parsing fails, the parser should return an error (which will be wrapped in context by the caller before reporting.)
fn parse(&mut self, substring: &str) -> eyre::Result<()>;
// Substituting state (during work for individual paths)
/// Create a substitute for this specific substring (identified in parsing stage above) for this specific path that can inserted into the `Format`'s list of reconstituted substrings to be compared with other outputs of the *same token index* for the *same substring* of a different path in the *same `Format` host*.
///
/// # Panics
/// A panic should be used to signal failure, as this method should not fail in general. Any possible failures should be reported in `parse()`
// TOOD: Should we pass more then the `path`? I think when this `OrderBy` mode is selected, we should *not* do the `statx()` of the pathname itself before the comparison, since it may be irrelevent to the operation of this specific token, so.
fn substitute(&self, path: &Path) -> Self::Substitute;
}
/// Options available for filename/path-like tokens (see below.)
///
/// # Example
/// The token `%p` and `%n` can be modified with `PathTokenOpt` as: `%[S..[-]E]n` or `%[S..[-]E]p` to slice the name.
struct PathTokenOpt {
slice: Option<(usize, Option<usize>)>,
}
impl ParseToken for PathTokenOpt {
//TODO: Impl visit, parse & substitute for `%[S..[-]E]C`
}
enum Token<'source> {
/// Part is a string literal, no replacement.
Literal(&'source str),
/// Specifically for escaped characters (e.g. `"%%"` -> `'%'`)
Escaped(char),
/// Part is `%[S..E]n`: Filename (not path, just the file *name*.)
Filename(PathTokenOpt),
/// Part is `%[S..E]p`: *Full* path.
Path(PathTokenOpt),
//TODO: Add rest...
}
impl<'source> ParseToken for Token<'source> {
//TODO: Add forwarding impl for each variant (where needed, like `Filename` & `Path`; for literals and escapes this can be handled here.)
// XXX: `visit()` can be implemented without forwarding since implementors like `PathTokenOpt` can be invariant wrt. the thing they're operating on.
//XXX: How are we going to define `Self::Substitute` here??? I think maybe having `Token` as an enum is not going to work here...
//TODO: We might need to do this with `dyn ParseToken` and have `Format::tokens: Vec<Box<dyn ParseToken + 'input>>` instead or something...
}
/// A parsed format-string whose values are replaced with that of the target file when comparing via order.
///
/// TODO: See if we can make it work as `<&[&dyn AsRef<str> + PartialOrd<str> + '_] as PartialOrd>` or something in implementation to avoid allocating where possible when substituting the parsed tokens (order each split part of the string)
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Format<'input> {
/// The parsed tokens
tokens: Vec<Token<'input>>,
//TODO: How to design this type...? See above `ParseToken` trait & its impl for `Token<'source>`...
}

@ -25,6 +25,7 @@ mod args;
mod order; mod order;
mod work; mod work;
mod walk; mod walk;
mod format;
fn init_logging() -> eyre::Result<()> fn init_logging() -> eyre::Result<()>
{ {

@ -10,7 +10,7 @@ use std::{
sync::Arc, sync::Arc,
}; };
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Copy, Default)] #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
pub enum OrderBy pub enum OrderBy
{ {
#[default] #[default]
@ -18,6 +18,9 @@ pub enum OrderBy
ChangeTime, ChangeTime,
AccessTime, AccessTime,
ModifiedTime, ModifiedTime,
/// User-provided formattable string
Arbitrary(format::Format<'static>) // XXX: This doesn't fit in the derivations of this enum... What can we do about this? Look through the codebase again and see where (and how) *exactly* this is used.
} }
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]

Loading…
Cancel
Save