typos_git_commit/
thashmap.rs1use crate::cli::Cli;
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 THashMap {
21 fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
22 where
23 P: AsRef<Path>,
24 {
25 let file = File::open(filename)?;
26 Ok(io::BufReader::new(file).lines())
27 }
28
29 pub fn new() -> Self {
30 let hashmap: HashMap<Key, Vec<Value>> = HashMap::new();
31 THashMap {
32 hashmap,
33 }
34 }
35
36 pub fn insert(&mut self, typojson: TyposJsonLine, cli: &Cli) {
39 if !typojson.is_excluded(cli) {
40 let typo = typojson.typo;
41 let corrections = typojson.corrections;
42 let key = Key {
43 typo,
44 corrections,
45 };
46
47 match self.hashmap.get_mut(&key) {
48 Some(v) => {
49 let value = Value {
52 path: typojson.path,
53 line_num: typojson.line_num,
54 byte_offset: typojson.byte_offset,
55 };
56 v.push(value);
57 }
58 None => {
59 let mut v: Vec<Value> = Vec::new();
62 let value = Value {
63 path: typojson.path,
64 line_num: typojson.line_num,
65 byte_offset: typojson.byte_offset,
66 };
67 v.push(value);
68 self.hashmap.insert(key, v);
69 }
70 }
71 } else if cli.debug {
72 if typojson.is_file_excluded(cli) {
75 eprintln!("{}", t!("thashmap-file-excluded", {"file" => typojson.path}));
76 } else if typojson.is_typo_excluded(cli) {
77 eprintln!("{}", t!("thashmap-typo-excluded", {"typo" => typojson.typo}));
78 } else if typojson.is_correction_excluded(cli) {
79 eprintln!(
80 "{}",
81 t!("thashmap-correction-excluded", { "correction" => format!("{:?}", typojson.corrections), "typo" => typojson.typo})
82 );
83 }
84 }
85 }
86
87 pub fn read_typos_file(mut self, cli: &Cli) -> Result<Self, Box<dyn Error>> {
89 match THashMap::read_lines(&cli.filename) {
90 Ok(lines) => {
91 for line in lines.map_while(Result::ok) {
93 let typojson = serde_json::from_str::<TyposJsonLine>(&line)?;
94 if typojson.type_id == "typo" {
95 self.insert(typojson, cli);
96 }
97 }
98 }
99 Err(e) => {
100 eprintln!("{}", t!("thashmap-error-file", {"e" => e.to_string()}));
101 exit(1);
102 }
103 }
104 Ok(self)
105 }
106
107 pub fn list_typos(&self, cli: &Cli) {
109 for (key, values) in &self.hashmap {
110 let values_len = values.len();
111 let files_string = t!("thashmap-file-count", {"count" => values_len }).to_string();
112
113 if key.is_typo_correctable(cli) {
117 println!("'{}' -> {:?}) {}", key.typo, key.corrections, files_string);
118 } else {
119 println!(
120 "\t{}",
121 t!("thashmap-wont-correct", {"typo" => key.typo, "correction" => format!("{:?}",key.corrections), "files" => files_string})
122 );
123 }
124
125 if cli.details {
126 for v in values {
127 println!(
128 "\t{}",
129 t!("thashmap-typo-details", {"path" => v.path, "line" => v.line_num, "offset" => v.byte_offset})
130 );
131 }
132 println!();
133 }
134 }
135 }
136
137 pub fn correct_typos(&self, cli: &Cli) {
139 for (key, values) in &self.hashmap {
140 if key.is_typo_correctable(cli) {
144 let mut files: Vec<String> = Vec::new();
145 for v in values {
146 files.push(v.path.clone());
147 }
148
149 key.run_sed(&files, cli);
150 key.run_git_commit(cli);
151 } else if cli.details {
152 println!();
153 println!(
154 "{}\n{}",
155 t!("thashmap-typo-not-corrected", {"typo" => key.typo, "correction" => format!("{:?}",key.corrections)}),
156 t!("thashmap-typo-look-carefully")
157 );
158 for v in values {
159 println!(
160 "{}",
161 t!("thashmap-typo-details", {"path" => v.path, "line" => v.line_num, "offset" => v.byte_offset})
162 );
163 }
164 println!();
165 }
166 }
167 }
168}