diff --git a/src/format/fixed.rs b/src/format/fixed.rs index 0ab1baa..ede2686 100644 --- a/src/format/fixed.rs +++ b/src/format/fixed.rs @@ -1,36 +1,79 @@ +use crate::types::*; use unicode_segmentation::UnicodeSegmentation; +const SPACE_STR_LIST: [&str; 2] = [" ", " "]; + pub struct FixedFormatter { length: usize, keep_original: bool, + typ: Option, } impl FixedFormatter { - pub fn new(length: usize, keep_original: bool) -> Self { + pub fn new(length: usize, keep_original: bool, typ: Option) -> Self { FixedFormatter { length, keep_original, + typ, } } + fn is_circus(&self) -> bool { + matches!(self.typ, Some(ScriptType::Circus)) + } + pub fn format(&self, message: &str) -> String { let mut result = String::new(); let vec: Vec<_> = UnicodeSegmentation::graphemes(message, true).collect(); let mut current_length = 0; + let mut is_command = false; + let mut pre_is_lf = false; + let mut is_ruby = false; + let mut is_ruby_rt = false; for grapheme in vec { if grapheme == "\n" { if self.keep_original { result.push('\n'); current_length = 0; } + pre_is_lf = true; continue; } if current_length >= self.length { result.push('\n'); current_length = 0; } + if (current_length == 0 || pre_is_lf) && SPACE_STR_LIST.contains(&grapheme) { + continue; + } result.push_str(grapheme); - current_length += 1; + if self.is_circus() { + if grapheme == "@" { + is_command = true; + } else if is_command && grapheme.len() != 1 + || !grapheme + .chars() + .next() + .unwrap_or(' ') + .is_ascii_alphanumeric() + { + is_command = false; + } + if grapheme == "{" { + is_ruby = true; + is_ruby_rt = true; + } else if is_ruby && grapheme == "/" { + is_ruby_rt = false; + continue; + } else if is_ruby && grapheme == "}" { + is_ruby = false; + continue; + } + } + if !is_command && !is_ruby_rt { + current_length += 1; + } + pre_is_lf = false; } return result; } @@ -38,17 +81,31 @@ impl FixedFormatter { #[test] fn test_format() { - let formatter = FixedFormatter::new(10, false); + let formatter = FixedFormatter::new(10, false, None); let message = "This is a test message.\nThis is another line."; let formatted_message = formatter.format(message); assert_eq!( formatted_message, - "This is a \ntest messa\nge.This is\n another l\nine." + "This is a \ntest messa\nge.This is\nanother li\nne." ); assert_eq!(formatter.format("● This is a test."), "● This is \na test."); - let fommater2 = FixedFormatter::new(10, true); assert_eq!( - fommater2.format("● Th\nis is a test."), + formatter.format("● This is  a test."), + "● This is \na test." + ); + let fommater2 = FixedFormatter::new(10, true, None); + assert_eq!( + fommater2.format("● Th\n is is a te st."), "● Th\nis is a te\nst." ); + let circus_formatter = FixedFormatter::new(10, false, Some(ScriptType::Circus)); + assert_eq!( + circus_formatter.format("● @cmd1@cmd2@cmd3中文字数是一\n 二三 四五六七八九十"), + "● @cmd1@cmd2@cmd3中文字数是一二三\n四五六七八九十" + ); + assert_eq!( + circus_formatter + .format("● @cmd1@cmd2@cmd3{rubyText/中文}字数是一\n 二三 四五六七八九十"), + "● @cmd1@cmd2@cmd3{rubyText/中文}字数是一二三\n四五六七八九十" + ); } diff --git a/src/format/mod.rs b/src/format/mod.rs index ccae528..5171c89 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -2,13 +2,13 @@ mod fixed; use crate::types::*; -pub fn fmt_message(mes: &mut Vec, opt: FormatOptions) { +pub fn fmt_message(mes: &mut Vec, opt: FormatOptions, typ: ScriptType) { match opt { FormatOptions::Fixed { length, keep_original, } => { - let formatter = fixed::FixedFormatter::new(length, keep_original); + let formatter = fixed::FixedFormatter::new(length, keep_original, Some(typ)); for message in mes.iter_mut() { message.message = formatter.format(&message.message); } diff --git a/src/main.rs b/src/main.rs index ab7dff3..b671f10 100644 --- a/src/main.rs +++ b/src/main.rs @@ -252,7 +252,7 @@ pub fn import_script( } None => {} } - format::fmt_message(&mut mes, fmt); + format::fmt_message(&mut mes, fmt, *builder.script_type()); script.import_messages(mes, &patched_f, encoding)?; Ok(types::ScriptResult::Ok) }