1use std::io::Cursor;
2
3use crate::{
4 line_reader::BufReadExt,
5 replace::replacement_if_match,
6 search::{FileSearcher, ParsedDirConfig, ParsedSearchConfig},
7 validation::{
8 DirConfig, SearchConfig, SimpleErrorHandler, ValidationResult,
9 validate_search_configuration,
10 },
11};
12
13pub fn find_and_replace(
15 search_config: SearchConfig<'_>,
16 dir_config: DirConfig<'_>,
17) -> anyhow::Result<String> {
18 let (parsed_search_config, parsed_dir_config) = parse_config(search_config, Some(dir_config))?;
19 let searcher = FileSearcher::new(
20 parsed_search_config,
21 parsed_dir_config.expect("Found None dir_config when search_type is Files"),
22 );
23 let num_files_replaced = searcher.walk_files_and_replace(None);
24
25 Ok(format!(
26 "Success: {num_files_replaced} file{prefix} updated",
27 prefix = if num_files_replaced != 1 { "s" } else { "" },
28 ))
29}
30
31pub fn find_and_replace_text(
33 content: &str,
34 search_config: SearchConfig<'_>,
35) -> anyhow::Result<String> {
36 let (parsed_search_config, _) = parse_config(search_config, None)?;
37 let mut result = String::with_capacity(content.len());
38
39 let cursor = Cursor::new(content);
40
41 for line_result in cursor.lines_with_endings() {
42 let (line_bytes, line_ending) = line_result?;
43
44 let line = String::from_utf8(line_bytes)?;
45
46 if let Some(replaced_line) = replacement_if_match(
47 &line,
48 &parsed_search_config.search,
49 &parsed_search_config.replace,
50 ) {
51 result.push_str(&replaced_line);
52 } else {
53 result.push_str(&line);
54 }
55
56 result.push_str(line_ending.as_str());
57 }
58
59 Ok(result)
60}
61
62fn parse_config(
63 search_config: SearchConfig<'_>,
64 dir_config: Option<DirConfig<'_>>,
65) -> anyhow::Result<(ParsedSearchConfig, Option<ParsedDirConfig>)> {
66 let mut error_handler = SimpleErrorHandler::new();
67
68 match validate_search_configuration(search_config, dir_config, &mut error_handler)? {
69 ValidationResult::Success(parsed) => Ok(parsed),
70 ValidationResult::ValidationErrors => Err(anyhow::anyhow!(
71 "{}",
72 error_handler
73 .errors_str()
74 .unwrap_or_else(|| "Unknown validation error".to_string())
75 )),
76 }
77}