Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement sha generator #46

Merged
merged 3 commits into from
Jan 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ kamadak-exif = "*"
# string wrangling
heck = "*"
chrono-tz = "0.10.0"
strum = "0.26.3"
strum_macros = "0.26.4"
#unicode-segmentation = "*"

# output
Expand Down
3 changes: 3 additions & 0 deletions src/ocd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,9 @@ impl Plan {
}

fn present_long(&self) {
println!(
"--------------------------------------------------------------------------------"
);
println!("Result:");
for (src, action) in &self.actions {
match action {
Expand Down
38 changes: 12 additions & 26 deletions src/ocd/mrn/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ use crate::ocd::Plan;
use crate::ocd::Speaker;
use crate::ocd::Verbosity;
use clap::Args;
use clap::ValueEnum;
use heck::ToKebabCase;
use heck::ToSnakeCase;
use heck::ToTitleCase;
use heck::ToUpperCamelCase;
use regex::Regex;
use std::error::Error;
use std::fs;
use std::path::Path;
use std::path::PathBuf;
use std::sync::LazyLock;
use walkdir::WalkDir;
Expand Down Expand Up @@ -72,11 +72,6 @@ Default is low, one medium, two high, three or more debug."#)]
#[arg(long)]
mode: Mode,

#[arg(default_value = "lalrpop")]
#[arg(help = "Specifies with parser to use.")]
#[arg(long)]
parser: crate::ocd::mrn::MassRenameParser,

#[arg(help = "Recurse directories.")]
#[arg(long)]
#[arg(short = 'r')]
Expand Down Expand Up @@ -135,24 +130,15 @@ impl Speaker for MassRenameArgs {
}
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
enum MassRenameParser {
Handwritten,
Lalrpop,
}

pub(crate) fn run(config: &MassRenameArgs) -> Result<(), Box<dyn Error + '_>> {
if config.verbosity() >= Verbosity::Silent {
println!("Verbosity: {:?}", config.verbosity())
}

// Parse instructions
let program = match config.parser {
MassRenameParser::Handwritten => parse_with_handwritten(config)?,
MassRenameParser::Lalrpop => parse_with_lalrpop(config)?,
};
let program = parse_with_lalrpop(config)?;
if config.verbosity() >= Verbosity::Debug {
println!("Program: \n{:#?}", &program);
println!("{:#?}", &program);
}

// Initialize plan
Expand All @@ -179,10 +165,6 @@ pub(crate) fn run(config: &MassRenameArgs) -> Result<(), Box<dyn Error + '_>> {
Ok(())
}

fn parse_with_handwritten(_config: &MassRenameArgs) -> Result<Program, Box<dyn Error + '_>> {
todo!("Parsing with the handwritten parser is not implemented yet!")
}

fn parse_with_lalrpop(config: &MassRenameArgs) -> Result<Program, Box<dyn Error + '_>> {
let lexer = crate::ocd::mrn::lalrpop::mrn_lexer::Lexer::new(&config.input);
let parser = crate::ocd::mrn::lalrpop::mrn_parser::ProgramParser::new();
Expand Down Expand Up @@ -340,13 +322,16 @@ fn apply_program(
for instruction in program.instructions() {
for (index, (src, action)) in plan.actions.iter_mut().enumerate() {
if config.verbosity() == Verbosity::Debug {
println!(
"--------------------------------------------------------------------------------"
);
println!("Applying");
println!(" instruction: {:?}", instruction);
println!(" index: {:?}", index);
println!(" index: {}", index);
println!(" src: {:?}", src);
println!(" action: {:?}", action);
println!(" action: {}", action);
println!(" instruction: {}", instruction);
}
apply_instruction(config, index, instruction, action);
apply_instruction(config, index, src.as_path(), instruction, action);
}
}
plan.clean();
Expand All @@ -356,6 +341,7 @@ fn apply_program(
fn apply_instruction(
config: &MassRenameArgs,
index: usize,
src: &Path,
instruction: &Instruction,
action: &mut Action,
) {
Expand Down Expand Up @@ -423,7 +409,7 @@ fn apply_instruction(
match_pattern: pattern,
replace_pattern: replace,
} => {
let filename = pattern_match::apply(config, index, filename, pattern, replace);
let filename = pattern_match::apply(config, index, src, filename, pattern, replace);
crate::ocd::rename_file(path, filename);
}
Instruction::ExtensionAdd(extension) => {
Expand Down
46 changes: 33 additions & 13 deletions src/ocd/mrn/pattern_match/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use crate::ocd::Verbosity;
use rand::distributions::Distribution;
use rand::distributions::Uniform;
use regex::Regex;
use std::path::Path;
use std::process::Command;

pub mod replace_pattern_lexer;
pub mod replace_pattern_tokens;
Expand Down Expand Up @@ -55,32 +57,42 @@ pub fn process_replace(
pub fn apply(
config: &MassRenameArgs,
index: usize,
src: &Path,
filename: &str,
match_pattern: &str,
replace_pattern: &ReplacePattern,
) -> String {
let florb_matches = extract_florb_matches(filename, match_pattern);
if config.verbosity() == Verbosity::Debug {
println!("Pattern match instruction");
println!(" index: {index:?}");
println!(" filename: {filename:?}");
println!(" input match pattern: {match_pattern:?}");
println!(" input replace pattern: {replace_pattern:?}");
println!(" florb matches: {florb_matches:?}");
println!(" Pattern match instruction debug information:");
println!(" filename: {filename:?}");
println!(" match_pattern: {match_pattern:?}");
println!(" replace_pattern: {replace_pattern:?}");
println!(" florb matches: {florb_matches:?}");
}

let mut filename = String::new();
let mut new_filename = String::new();
for rpc in &replace_pattern.components {
match rpc {
ReplacePatternComponent::Florb(ref index) => {
// TODO error/warning message if the else happens, and in general check florb indexes
// if a florb index was not there, perhaps it should cancel the entire apply and just return the input
if let Some(florb_match) = florb_matches.get(*index - 1) {
filename.push_str(florb_match.as_str())
new_filename.push_str(florb_match.as_str())
}
}
ReplacePatternComponent::Literal(literal) => {
filename.push_str(literal.as_str());
new_filename.push_str(literal.as_str());
}
ReplacePatternComponent::ShaGenerator => {
let output = Command::new("sha256sum")
.args([src.as_os_str()])
.output()
.expect("Error invoking sha256sum.");
if output.status.success() {
let sha = String::from_utf8(output.stdout[0..64].to_vec()).unwrap();
new_filename.push_str(&sha);
}
}
ReplacePatternComponent::RandomNumberGenerator {
start,
Expand All @@ -91,19 +103,19 @@ pub fn apply(
let mut rng = rand::thread_rng();
let n: usize = between.sample(&mut rng);
let num = format!("{:0padding$}", n);
filename.push_str(num.as_str());
new_filename.push_str(num.as_str());
}
ReplacePatternComponent::SequentialNumberGenerator {
start,
step,
padding,
} => {
let num = format!("{:0padding$}", start + (index * step));
filename.push_str(num.as_str());
new_filename.push_str(num.as_str());
}
}
}
filename
new_filename
}

/// Extract data from filename using the match pattern
Expand Down Expand Up @@ -150,6 +162,7 @@ mod test {
use crate::ocd::mrn::program::ReplacePatternComponent;
use crate::ocd::Cli;
use crate::ocd::OcdCommand;
use std::path::Path;

fn test_pattern(
index: usize,
Expand All @@ -163,7 +176,14 @@ mod test {
let match_pattern = super::process_match(String::from(match_pattern_str));
let replace_pattern =
super::process_replace(String::from(replace_pattern_str)).unwrap();
let result = super::apply(&config, index, filename, &match_pattern, &replace_pattern);
let result = super::apply(
&config,
index,
Path::new(filename),
filename,
&match_pattern,
&replace_pattern,
);
assert_eq!(expected, result);
} else {
panic!()
Expand Down
3 changes: 2 additions & 1 deletion src/ocd/mrn/pattern_match/replace_pattern_parser.lalrpop
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ extern {
"dash" => Token::Dash,
"obrace" => Token::OpeningBrace,
"cbrace" => Token::ClosingBrace,
"date" => Token::DateGenerator,
"sha" => Token::ShaGenerator,
"sng" => Token::SequentialNumberGenerator,
"rng" => Token::RandomNumberGenerator,
"florb" => Token::Florb(<usize>),
Expand All @@ -40,6 +40,7 @@ RPC: ReplacePatternComponent = {
"dash" => ReplacePatternComponent::Literal(String::from("-")),
"obrace" => ReplacePatternComponent::Literal(String::from("{")),
"cbrace" => ReplacePatternComponent::Literal(String::from("}")),
"sha" => ReplacePatternComponent::ShaGenerator,
"sng" <sng:SNG> => sng,
"rng" <rng:RNG> => rng,
<t:"florb"> => ReplacePatternComponent::Florb(t),
Expand Down
4 changes: 2 additions & 2 deletions src/ocd/mrn/pattern_match/replace_pattern_tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ pub enum Token {
OpeningBrace,
#[token("}", priority = 3)]
ClosingBrace,
#[token("{date}")]
DateGenerator,
#[token("{sha}")]
ShaGenerator,
#[token("{sng")]
SequentialNumberGenerator,
#[token("{rng")]
Expand Down
3 changes: 2 additions & 1 deletion src/ocd/mrn/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ impl Program {
}
}

#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, strum_macros::Display)]
pub enum Instruction {
Sanitize,
CaseLower,
Expand Down Expand Up @@ -88,6 +88,7 @@ pub struct ReplacePattern {
pub enum ReplacePatternComponent {
Literal(String),
Florb(usize),
ShaGenerator,
RandomNumberGenerator {
start: usize,
end: usize,
Expand Down
Loading