typos_git_commit/
thashmap.rs1use crate::cli::{Cli, TypoType};
2use crate::keyvalue::{Key, Value};
3use crate::typosjsonline::TyposJsonLine;
4use fluent_i18n::t;
5use std::collections::HashMap;
6use std::error::Error;
7use std::fs::File;
8use std::io::{self, BufRead};
9use std::path::Path;
10use std::process::exit;
11
12#[derive(Debug)]
16pub struct THashMap {
17 hashmap: HashMap<Key, Vec<Value>>,
18}
19
20impl Default for THashMap {
21 fn default() -> Self {
22 Self::new()
23 }
24}
25
26impl THashMap {
27 fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
28 where
29 P: AsRef<Path>,
30 {
31 let file = File::open(filename)?;
32 Ok(io::BufReader::new(file).lines())
33 }
34
35 #[must_use]
36 pub fn new() -> Self {
37 let hashmap: HashMap<Key, Vec<Value>> = HashMap::new();
38 THashMap {
39 hashmap,
40 }
41 }
42
43 pub fn insert(&mut self, typojson: TyposJsonLine, cli: &Cli) {
46 if !typojson.is_excluded(cli) {
47 let typo = typojson.typo;
48 let corrections = typojson.corrections;
49 let key = Key {
50 typo,
51 corrections,
52 };
53
54 if let Some(v) = self.hashmap.get_mut(&key) {
55 let value = Value {
58 path: typojson.path,
59 line_num: typojson.line_num,
60 byte_offset: typojson.byte_offset,
61 };
62 v.push(value);
63 } else {
64 let mut v: Vec<Value> = Vec::new();
67 let value = Value {
68 path: typojson.path,
69 line_num: typojson.line_num,
70 byte_offset: typojson.byte_offset,
71 };
72 v.push(value);
73 self.hashmap.insert(key, v);
74 }
75 } else if cli.debug {
76 if typojson.is_file_excluded(cli) {
79 eprintln!("{}", t!("thashmap-file-excluded", {"file" => typojson.path}));
80 } else if typojson.is_typo_excluded(cli) {
81 eprintln!("{}", t!("thashmap-typo-excluded", {"typo" => typojson.typo}));
82 } else if typojson.is_correction_excluded(cli) {
83 eprintln!(
84 "{}",
85 t!("thashmap-correction-excluded", { "correction" => format!("{:?}", typojson.corrections), "typo" => typojson.typo})
86 );
87 }
88 }
89 }
90
91 pub fn read_typos_file(mut self, cli: &Cli) -> Result<Self, Box<dyn Error>> {
97 match THashMap::read_lines(&cli.filename) {
98 Ok(lines) => {
99 for line in lines.map_while(Result::ok) {
101 let typojson = serde_json::from_str::<TyposJsonLine>(&line)?;
102 if typojson.type_id == "typo" {
103 self.insert(typojson, cli);
104 }
105 }
106 }
107 Err(e) => {
108 eprintln!("{}", t!("thashmap-error-file", {"e" => e.to_string()}));
109 exit(1);
110 }
111 }
112 Ok(self)
113 }
114
115 pub fn list_typos(&self, cli: &Cli) {
117 if let Some(only_list_typos) = &cli.only_list_typos {
118 for (key, values) in &self.hashmap {
119 let values_len = values.len();
120 let files_string = t!("thashmap-file-count", {"count" => values_len }).to_string();
121 let mut printed = true;
122
123 if key.is_typo_correctable(cli) {
127 match only_list_typos {
128 TypoType::All | TypoType::Corrected => {
129 println!("'{}' -> {:?}) {}", key.typo, key.corrections, files_string);
130 }
131 TypoType::NotCorrected => printed = false,
132 }
133 } else {
134 match only_list_typos {
135 TypoType::All | TypoType::NotCorrected => {
136 println!(
137 "\t{}",
138 t!("thashmap-wont-correct", {"typo" => key.typo, "correction" => format!("{:?}",key.corrections), "files" => files_string})
139 );
140 }
141 TypoType::Corrected => printed = false,
142 }
143 }
144
145 if cli.details && printed {
146 for v in values {
147 println!(
148 "\t{}",
149 t!("thashmap-typo-details", {"path" => v.path, "line" => v.line_num, "offset" => v.byte_offset})
150 );
151 }
152 println!();
153 }
154 }
155 }
156 }
157
158 pub fn correct_typos(&self, cli: &Cli) {
160 for (key, values) in &self.hashmap {
161 if key.is_typo_correctable(cli) {
165 let mut files: Vec<String> = Vec::new();
166 for v in values {
167 files.push(v.path.clone());
168 }
169
170 key.run_sed(&files, cli);
171 key.run_git_commit(cli);
172 } else if cli.details {
173 println!();
174 println!(
175 "{}\n{}",
176 t!("thashmap-typo-not-corrected", {"typo" => key.typo, "correction" => format!("{:?}",key.corrections)}),
177 t!("thashmap-typo-look-carefully")
178 );
179 for v in values {
180 println!(
181 "{}",
182 t!("thashmap-typo-details", {"path" => v.path, "line" => v.line_num, "offset" => v.byte_offset})
183 );
184 }
185 println!();
186 }
187 }
188 }
189}