Files
nomina/crates/nomina-core/src/rules/swap.rs
lashman 6f5b862234 pipeline cards, context menus, presets, settings overhaul
rewrote pipeline as draggable card strip with per-rule config popovers,
added right-click menus to pipeline cards, sidebar tree, and file list,
preset import/export with BRU format support, new rules (hash, swap,
truncate, sanitize, padding, randomize, text editor, folder name,
transliterate), settings dialog with all sections, overlay collision
containment, tooltips on icon buttons, empty pipeline default
2026-03-14 19:04:35 +02:00

117 lines
2.7 KiB
Rust

use serde::{Deserialize, Serialize};
use crate::{RenameContext, RenameRule};
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
pub enum SwapOccurrence {
#[default]
First,
Last,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SwapRule {
pub delimiter: String,
pub occurrence: SwapOccurrence,
#[serde(default)]
pub new_delimiter: Option<String>,
pub enabled: bool,
}
impl SwapRule {
pub fn new() -> Self {
Self {
delimiter: ", ".into(),
occurrence: SwapOccurrence::First,
new_delimiter: None,
enabled: true,
}
}
}
impl RenameRule for SwapRule {
fn apply(&self, filename: &str, _context: &RenameContext) -> String {
if self.delimiter.is_empty() {
return filename.to_string();
}
let pos = match self.occurrence {
SwapOccurrence::First => filename.find(&self.delimiter),
SwapOccurrence::Last => filename.rfind(&self.delimiter),
};
let pos = match pos {
Some(p) => p,
None => return filename.to_string(),
};
let left = &filename[..pos];
let right = &filename[pos + self.delimiter.len()..];
let joiner = self.new_delimiter.as_deref().unwrap_or(&self.delimiter);
format!("{}{}{}", right, joiner, left)
}
fn display_name(&self) -> &str {
"Swap"
}
fn rule_type(&self) -> &str {
"swap"
}
fn is_enabled(&self) -> bool {
self.enabled
}
}
#[cfg(test)]
mod tests {
use super::*;
fn ctx() -> RenameContext {
RenameContext::dummy(0)
}
#[test]
fn swap_comma_space() {
let rule = SwapRule::new();
assert_eq!(rule.apply("LastName, FirstName", &ctx()), "FirstName, LastName");
}
#[test]
fn swap_with_new_delimiter() {
let rule = SwapRule {
new_delimiter: Some(" ".into()),
..SwapRule::new()
};
assert_eq!(rule.apply("LastName, FirstName", &ctx()), "FirstName LastName");
}
#[test]
fn swap_first_occurrence() {
let rule = SwapRule {
delimiter: "-".into(),
occurrence: SwapOccurrence::First,
..SwapRule::new()
};
assert_eq!(rule.apply("a-b-c", &ctx()), "b-c-a");
}
#[test]
fn swap_last_occurrence() {
let rule = SwapRule {
delimiter: "-".into(),
occurrence: SwapOccurrence::Last,
..SwapRule::new()
};
assert_eq!(rule.apply("a-b-c", &ctx()), "c-a-b");
}
#[test]
fn no_delimiter_found() {
let rule = SwapRule::new();
assert_eq!(rule.apply("nodelimiter", &ctx()), "nodelimiter");
}
}