From afff0af5167361873b5e1a04c8069ed8c530f361 Mon Sep 17 00:00:00 2001 From: sxyazi Date: Sat, 9 May 2026 22:26:10 +0800 Subject: [PATCH] Refactor --- yazi-shared/src/condition.rs | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/yazi-shared/src/condition.rs b/yazi-shared/src/condition.rs index 3a803d4a..9f608924 100644 --- a/yazi-shared/src/condition.rs +++ b/yazi-shared/src/condition.rs @@ -1,4 +1,4 @@ -use std::str::FromStr; +use std::{cmp::Ordering, str::FromStr}; use anyhow::bail; use serde_with::DeserializeFromStr; @@ -33,8 +33,7 @@ impl ConditionOp { } } - #[inline] - pub fn prec(&self) -> u8 { + fn prec(&self) -> u8 { match self { Self::Or => 1, Self::And => 2, @@ -44,6 +43,18 @@ impl ConditionOp { } } +impl PartialOrd for ConditionOp { + fn partial_cmp(&self, other: &Self) -> Option { + use Ordering::*; + + match self.prec().cmp(&other.prec()) { + // Keep repeated `!` right-associative by making `! >= !` false. + Equal if matches!((self, other), (Self::Not, Self::Not)) => None, + ordering => Some(ordering), + } + } +} + #[derive(Debug, DeserializeFromStr)] pub struct Condition { ops: Vec, @@ -72,10 +83,7 @@ impl Condition { let op = ConditionOp::new(token); match op { ConditionOp::Or | ConditionOp::And | ConditionOp::Not => { - while matches!( - stack.last(), - Some(last) if last.prec() > op.prec() || (op != ConditionOp::Not && last.prec() == op.prec()) - ) { + while matches!(stack.last(), Some(last) if last >= &op) { output.push(stack.pop().unwrap()); } stack.push(op); @@ -139,14 +147,14 @@ mod tests { #[test] fn test_condition_not() -> anyhow::Result<()> { + let cond: Condition = "!dir".parse()?; + assert!(!cond.eval(|s| s == "dir").unwrap()); + assert!(cond.eval(|_| false).unwrap()); + let cond: Condition = "!!dir".parse()?; assert!(cond.eval(|s| s == "dir").unwrap()); assert!(!cond.eval(|_| false).unwrap()); - let cond: Condition = "!!!dir".parse()?; - assert!(!cond.eval(|s| s == "dir").unwrap()); - assert!(cond.eval(|_| false).unwrap()); - Ok(()) } }