From cba41a78e5366b875fcdbb5d43ca1aef8f3650c0 Mon Sep 17 00:00:00 2001 From: iff Date: Thu, 3 Aug 2023 22:13:23 +0200 Subject: [PATCH] format: extract replaces to functions --- rule_parser/src/lib.rs | 152 +++--------------------------------- rule_parser/src/replaces.rs | 151 +++++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+), 142 deletions(-) create mode 100644 rule_parser/src/replaces.rs diff --git a/rule_parser/src/lib.rs b/rule_parser/src/lib.rs index ee0d2e6..47dee97 100644 --- a/rule_parser/src/lib.rs +++ b/rule_parser/src/lib.rs @@ -4,6 +4,8 @@ use proc_macro::TokenStream; use proc_macro2::TokenStream as TokenStream2; use quote::quote; +mod replaces; + #[proc_macro] pub fn parse_rules(input: TokenStream) -> TokenStream { let directory = input.to_string().trim_matches('"').to_owned(); @@ -182,155 +184,21 @@ fn eval_condition(condition: &str, arg: &str) -> TokenStream2 { fn eval_suggest(suggest: &str) -> TokenStream2 { let mut suggest = suggest.to_owned(); - let rtag = |x: i32, y: String| { - let tag = format!("tag{} = {}", x, y); - let tag: TokenStream2 = tag.parse().unwrap(); - tag - }; - - let tag = |x: i32| { - let tag = format!("{{tag{}}}", x); - let tag = tag.as_str(); - let tag = tag.to_owned(); - tag - }; - let mut replace_tag = 0; - let mut replace_list = Vec::new(); - if suggest.contains("{{command}}") { - let command = "last_command".to_string(); - - replace_list.push(rtag(replace_tag, command)); - suggest = suggest.replace("{{command}}", &tag(replace_tag)); - replace_tag += 1; + suggest = suggest.replace("{{command}}", "{last_command}"); } - let mut opt_lists = Vec::new(); - while suggest.contains("{{opt::") { - let placeholder_start = "{{opt::"; - let placeholder_end = "}}"; + let mut replace_list = Vec::new(); + let mut opt_list = Vec::new(); - let start_index = suggest.find(placeholder_start).unwrap(); - let end_index = suggest[start_index..].find(placeholder_end).unwrap() - + start_index - + placeholder_end.len(); - - let placeholder = start_index..end_index; - - let args = start_index + placeholder_start.len()..end_index - placeholder_end.len(); - let opt = &suggest[args.to_owned()]; - let regex = opt.trim(); - let current_tag = tag(replace_tag); - let token_tag: TokenStream2 = format!("tag{}", replace_tag).parse().unwrap(); - let command = quote! { - let #token_tag = opt_regex(#regex, &mut last_command); - }; - opt_lists.push(command); - - replace_list.push(rtag(replace_tag, current_tag.to_owned())); - suggest.replace_range(placeholder, ¤t_tag); - replace_tag += 1; - } - - while suggest.contains("{{command") { - let placeholder_start = "{{command"; - let placeholder_end = "}}"; - - let start_index = suggest.find(placeholder_start).unwrap(); - let end_index = suggest[start_index..].find(placeholder_end).unwrap() - + start_index - + placeholder_end.len(); - - let placeholder = start_index..end_index; - - let args = start_index + placeholder_start.len()..end_index - placeholder_end.len(); - let range = suggest[args.to_owned()].trim_matches(|c| c == '[' || c == ']'); - if let Some((start, end)) = range.split_once(':') { - let mut start_string = start.to_string(); - let start = start.parse::().unwrap_or(0); - if start < 0 { - start_string = format!("split_command.len() {}", start); - }; - let end_string; - let parsed_end = end.parse::(); - if parsed_end.is_err() { - end_string = String::from("split_command.len()"); - } else { - let end = parsed_end.clone().unwrap(); - if end < 0 { - end_string = format!("split_command.len() {}", end + 1); - } else { - end_string = (end + 1).to_string(); - } - }; - - let command = format!{r#"split_command[{}..{}].join(" ")"#, start_string, end_string}; - - replace_list.push(rtag(replace_tag, command)); - suggest.replace_range(placeholder, &tag(replace_tag)); - replace_tag += 1; - } else { - let range = range.parse::().unwrap_or(0); - let command = format!("split_command[{}]", range); - - replace_list.push(rtag(replace_tag, command)); - suggest.replace_range(placeholder, &tag(replace_tag)); - replace_tag += 1; - } - } - - while suggest.contains("{{typo") { - let placeholder_start = "{{typo"; - let placeholder_end = "}}"; - - let start_index = suggest.find(placeholder_start).unwrap(); - let end_index = suggest[start_index..].find(placeholder_end).unwrap() - + start_index - + placeholder_end.len(); - - let placeholder = start_index..end_index; - let args = start_index + placeholder_start.len()..end_index - placeholder_end.len(); - - let string_index; - if suggest.contains('[') { - let split = suggest[args.to_owned()] - .split(&['[', ']']) - .collect::>(); - let command_index = split[1].parse::().unwrap(); - if command_index < 0 { - // command_index += split_command.len() as i32; - string_index = format!("split_command.len() {}", command_index); - } else { - string_index = command_index.to_string(); - } - } else { - unreachable!("Typo suggestion must have a command index"); - } - let mut match_list = Vec::new(); - if suggest.contains('(') { - let split = suggest[args.to_owned()] - .split(&['(', ')']) - .collect::>(); - match_list = split[1].trim().split(',').collect::>(); - } - - let match_list = match_list - .iter() - .map(|s| s.trim().to_string()) - .collect::>(); - let string_match_list = match_list.join(r#"".to_string(), ""#); - let string_match_list = format!(r#""{}".to_string()"#, string_match_list); - - let command = format!("suggest_typo(&split_command[{}], vec![{}])", string_index, string_match_list); - - replace_list.push(rtag(replace_tag, command)); - suggest.replace_range(placeholder, &tag(replace_tag)); - replace_tag += 1; - } + replaces::opts(&mut suggest, &mut replace_list, &mut opt_list); + replaces::command(&mut suggest, &mut replace_list); + replaces::typo(&mut suggest, &mut replace_list); quote! { - #(#opt_lists)* + #(#opt_list)* let split_command = split_command(&last_command); return Some(format!{#suggest, #(#replace_list),*}); } } + diff --git a/rule_parser/src/replaces.rs b/rule_parser/src/replaces.rs new file mode 100644 index 0000000..ae85a5e --- /dev/null +++ b/rule_parser/src/replaces.rs @@ -0,0 +1,151 @@ +use proc_macro2::TokenStream as TokenStream2; +use quote::quote; + +fn rtag (name: &str, x: i32, y: String) -> TokenStream2 { + let tag = format!("{}{} = {}", name, x, y); + let tag: TokenStream2 = tag.parse().unwrap(); + tag +} + +fn tag (name: &str, x: i32) -> String { + let tag = format!("{{{}{}}}", name, x); + let tag = tag.as_str(); + let tag = tag.to_owned(); + tag +} + +pub fn opts(suggest: &mut String, replace_list: &mut Vec, opt_list: &mut Vec) { + let mut replace_tag = 0; + let tag_name = "opts"; + while suggest.contains("{{opt::") { + let placeholder_start = "{{opt::"; + let placeholder_end = "}}"; + + let start_index = suggest.find(placeholder_start).unwrap(); + let end_index = suggest[start_index..].find(placeholder_end).unwrap() + + start_index + + placeholder_end.len(); + + let placeholder = start_index..end_index; + + let args = start_index + placeholder_start.len()..end_index - placeholder_end.len(); + let opt = &suggest[args.to_owned()]; + let regex = opt.trim(); + let current_tag = tag(tag_name, replace_tag); + let token_tag: TokenStream2 = format!("{}{}", tag_name, replace_tag).parse().unwrap(); + let command = quote! { + let #token_tag = opt_regex(#regex, &mut last_command); + }; + opt_list.push(command); + + replace_list.push(rtag(tag_name, replace_tag, current_tag.to_owned())); + suggest.replace_range(placeholder, ¤t_tag); + replace_tag += 1; + } +} + +pub fn command(suggest: &mut String, replace_list: &mut Vec) { + let mut replace_tag = 0; + let tag_name = "command"; + while suggest.contains("{{command") { + let placeholder_start = "{{command"; + let placeholder_end = "}}"; + + let start_index = suggest.find(placeholder_start).unwrap(); + let end_index = suggest[start_index..].find(placeholder_end).unwrap() + + start_index + + placeholder_end.len(); + + let placeholder = start_index..end_index; + + let args = start_index + placeholder_start.len()..end_index - placeholder_end.len(); + let range = suggest[args.to_owned()].trim_matches(|c| c == '[' || c == ']'); + if let Some((start, end)) = range.split_once(':') { + let mut start_string = start.to_string(); + let start = start.parse::().unwrap_or(0); + if start < 0 { + start_string = format!("split_command.len() {}", start); + }; + let end_string; + let parsed_end = end.parse::(); + if parsed_end.is_err() { + end_string = String::from("split_command.len()"); + } else { + let end = parsed_end.clone().unwrap(); + if end < 0 { + end_string = format!("split_command.len() {}", end + 1); + } else { + end_string = (end + 1).to_string(); + } + }; + + let command = format!{r#"split_command[{}..{}].join(" ")"#, start_string, end_string}; + + replace_list.push(rtag(tag_name, replace_tag, command)); + suggest.replace_range(placeholder, &tag(tag_name, replace_tag)); + replace_tag += 1; + } else { + let range = range.parse::().unwrap_or(0); + let command = format!("split_command[{}]", range); + + replace_list.push(rtag(tag_name, replace_tag, command)); + suggest.replace_range(placeholder, &tag(tag_name, replace_tag)); + replace_tag += 1; + } + } +} + +pub fn typo(suggest: &mut String, replace_list: &mut Vec) { + let mut replace_tag = 0; + let tag_name = "typo"; + + while suggest.contains("{{typo") { + let placeholder_start = "{{typo"; + let placeholder_end = "}}"; + + let start_index = suggest.find(placeholder_start).unwrap(); + let end_index = suggest[start_index..].find(placeholder_end).unwrap() + + start_index + + placeholder_end.len(); + + let placeholder = start_index..end_index; + let args = start_index + placeholder_start.len()..end_index - placeholder_end.len(); + + let string_index; + if suggest.contains('[') { + let split = suggest[args.to_owned()] + .split(&['[', ']']) + .collect::>(); + let command_index = split[1].parse::().unwrap(); + if command_index < 0 { + // command_index += split_command.len() as i32; + string_index = format!("split_command.len() {}", command_index); + } else { + string_index = command_index.to_string(); + } + } else { + unreachable!("Typo suggestion must have a command index"); + } + let mut match_list = Vec::new(); + if suggest.contains('(') { + let split = suggest[args.to_owned()] + .split(&['(', ')']) + .collect::>(); + match_list = split[1].trim().split(',').collect::>(); + } + + let match_list = match_list + .iter() + .map(|s| s.trim().to_string()) + .collect::>(); + let string_match_list = match_list.join(r#"".to_string(), ""#); + let string_match_list = format!(r#""{}".to_string()"#, string_match_list); + + let command = format!("suggest_typo(&split_command[{}], vec![{}])", string_index, string_match_list); + + replace_list.push(rtag(tag_name, replace_tag, command)); + suggest.replace_range(placeholder, &tag(tag_name, replace_tag)); + replace_tag += 1; + } + +}