this repo has no description

Use Vec<char> instead of &str to correctly parse Chinese character.

Signed-off-by: Jamie Moriarty <jamiemoriarty@qq.com>

+31 -23
+7
src/tests.rs
··· 73 73 } 74 74 75 75 #[test] 76 + fn test_cn_chars() { 77 + let tex = r"\text{中文}"; 78 + let result = tex2typst(tex).unwrap(); 79 + assert_eq!(result, "\"中文\""); 80 + } 81 + 82 + #[test] 76 83 fn test_readme() { 77 84 let tex = r"\widehat{f}(\xi)=\int_{-\infty}^{\infty} f(x) e^{-i 2 \pi \xi x} d x, \quad \forall \xi \in \mathbb{R}"; 78 85 println!("{}", tex2typst(tex).unwrap());
+24 -23
src/tex_parser.rs
··· 91 91 pos - start 92 92 } 93 93 94 - fn eat_command_name(latex: &str, start: usize) -> &str { 94 + fn eat_command_name(latex:&Vec<char>, start: usize) -> String { 95 95 let mut pos = start; 96 - while pos < latex.len() && latex[pos..].chars().next().unwrap().is_alphabetic() { 96 + while pos < latex.len() && latex[pos].is_alphabetic() { 97 97 pos += 1; 98 98 } 99 - &latex[start..pos] 99 + latex[start..pos].iter().collect::<String>() 100 100 } 101 101 102 102 fn find_closing_match(tokens: &[TexToken], start: usize, left_token: &TexToken, right_token: &TexToken) -> isize { ··· 135 135 find_closing_match(tokens, start, &BEGIN_COMMAND, &END_COMMAND) 136 136 } 137 137 138 - fn find_closing_curly_bracket_char(latex: &str, start: usize) -> Result<usize, &'static str> { 139 - assert_eq!(latex[start..].chars().next().unwrap(), '{'); 138 + fn find_closing_curly_bracket_char(latex: &Vec<char>, start: usize) -> Result<usize, &'static str> { 139 + assert_eq!(latex[start], '{'); 140 140 let mut count = 1; 141 141 let mut pos = start + 1; 142 142 ··· 144 144 if pos >= latex.len() { 145 145 return Err("Unmatched curly brackets"); 146 146 } 147 - if pos + 1 < latex.len() && ["\\{", "\\}"].contains(&&latex[pos..pos + 2]) { 147 + if pos + 1 < latex.len() && ["\\{", "\\}"].contains(&latex[pos..pos + 2].iter().collect::<String>().as_str()) { 148 148 pos += 2; 149 149 continue; 150 150 } 151 - match latex[pos..].chars().next().unwrap() { 151 + match latex[pos] { 152 152 '{' => count += 1, 153 153 '}' => count -= 1, 154 154 _ => {} ··· 160 160 } 161 161 162 162 pub fn tokenize(latex: &str) -> Result<Vec<TexToken>, String> { 163 + let latex: Vec<char> = latex.chars().collect(); 163 164 let mut tokens: Vec<TexToken> = Vec::new(); 164 165 let mut pos = 0; 165 166 166 167 while pos < latex.len() { 167 - let first_char = latex[pos..].chars().next().unwrap(); 168 + let first_char = latex[pos]; 168 169 let token: TexToken; 169 170 match first_char { 170 171 '%' => { 171 172 let mut new_pos = pos + 1; 172 - while new_pos < latex.len() && latex[new_pos..].chars().next().unwrap() != '\n' { 173 + while new_pos < latex.len() && latex[new_pos] != '\n' { 173 174 new_pos += 1; 174 175 } 175 - token = TexToken::new(TexTokenType::Comment, latex[pos + 1..new_pos].to_string()); 176 + token = TexToken::new(TexTokenType::Comment, latex[pos + 1..new_pos].iter().collect()); 176 177 pos = new_pos; 177 178 } 178 179 '{' | '}' | '_' | '^' | '&' => { ··· 184 185 pos += 1; 185 186 } 186 187 '\r' => { 187 - if pos + 1 < latex.len() && latex[pos + 1..].chars().next().unwrap() == '\n' { 188 + if pos + 1 < latex.len() && latex[pos + 1] == '\n' { 188 189 token = TexToken::new(TexTokenType::Newline, "\n".to_string()); 189 190 pos += 2; 190 191 } else { ··· 194 195 } 195 196 ' ' => { 196 197 let mut new_pos = pos; 197 - while new_pos < latex.len() && latex[new_pos..].chars().next().unwrap() == ' ' { 198 + while new_pos < latex.len() && latex[new_pos] == ' ' { 198 199 new_pos += 1; 199 200 } 200 - token = TexToken::new(TexTokenType::Space, latex[pos..new_pos].to_string()); 201 + token = TexToken::new(TexTokenType::Space, latex[pos..new_pos].iter().collect()); 201 202 pos = new_pos; 202 203 } 203 204 '\\' => { 204 205 if pos + 1 >= latex.len() { 205 206 return Err("Expecting command name after '\\'".to_string()); 206 207 } 207 - let first_two_chars = &latex[pos..pos + 2]; 208 - if ["\\\\", "\\,"].contains(&first_two_chars) { 208 + let first_two_chars = latex[pos..pos + 2].iter().collect::<String>(); 209 + if ["\\\\", "\\,"].contains(&&*first_two_chars) { 209 210 token = TexToken::new(TexTokenType::Control, first_two_chars.to_string()); 210 - } else if ["\\{", "\\}", "\\%", "\\$", "\\&", "\\#", "\\_", "\\|"].contains(&first_two_chars) { 211 + } else if ["\\{", "\\}", "\\%", "\\$", "\\&", "\\#", "\\_", "\\|"].contains(&&*first_two_chars) { 211 212 token = TexToken::new(TexTokenType::Element, first_two_chars.to_string()); 212 213 } else { 213 - let command = eat_command_name(latex, pos + 1); 214 + let command = eat_command_name(&latex, pos + 1); 214 215 token = TexToken::new(TexTokenType::Command, format!("\\{}", command)); 215 216 } 216 217 pos += token.value.len(); ··· 218 219 _ => { 219 220 if first_char.is_digit(10) { 220 221 let mut new_pos = pos; 221 - while new_pos < latex.len() && latex[new_pos..].chars().next().unwrap().is_digit(10) { 222 + while new_pos < latex.len() && latex[new_pos].is_digit(10) { 222 223 new_pos += 1; 223 224 } 224 - token = TexToken::new(TexTokenType::Element, latex[pos..new_pos].to_string()); 225 + token = TexToken::new(TexTokenType::Element, latex[pos..new_pos].iter().collect()); 225 226 } else if first_char.is_alphabetic() { 226 227 token = TexToken::new(TexTokenType::Element, first_char.to_string()); 227 228 } else if "+-*/='<>!.,;:?()[]|".contains(first_char) { ··· 240 241 if token.token_type == TexTokenType::Command 241 242 && ["\\text", "\\operatorname", "\\begin", "\\end"].contains(&token.value.as_str()) 242 243 { 243 - if pos >= latex.len() || latex[pos..].chars().next().unwrap() != '{' { 244 - if let Some(nn) = latex[pos..].find('{') { 244 + if pos >= latex.len() || latex[pos] != '{' { 245 + if let Some(nn) = latex[pos..].iter().position(|&c| c=='{') { 245 246 pos += nn; 246 247 } else { 247 248 return Err(format!("No content for {} command", token.value)); 248 249 } 249 250 } 250 251 tokens.push(TexToken::new(TexTokenType::Control, "{".to_string())); 251 - let pos_closing_bracket = find_closing_curly_bracket_char(latex, pos)?; 252 + let pos_closing_bracket = find_closing_curly_bracket_char(&latex, pos)?; 252 253 pos += 1; 253 - let mut text_inside = latex[pos..pos_closing_bracket].to_string(); 254 + let mut text_inside: String = latex[pos..pos_closing_bracket].iter().collect(); 254 255 let chars = ['{', '}', '\\', '$', '&', '#', '_', '%']; 255 256 for &char in &chars { 256 257 text_inside = text_inside.replace(&format!("\\{}", char), &char.to_string());