fn present_and_apply_patches()

in src/main.rs [331:398]


    fn present_and_apply_patches(
        &mut self,
        regex: &Regex,
        subst: &str,
        path: &Path,
        mut contents: String,
    ) -> Result<()> {
        // Overall flow:
        // 0) offset = 0.
        // 1) Find next patch from *current* contents of the file at
        //    given offset. If none, we are done.
        // 2) Set the offset to the start of the previous patch + 1.
        // 3) Ask the user to make a modification to the file.
        // 4) Re-read the file. (User may have made arbitrary edits!)
        let mut offset = 0;
        while offset < contents.len() {
            {
                let mat = regex.find(&contents[offset..]);
                match mat {
                    None => break,
                    Some(mat) => {
                        let mut new_contents = contents[..offset].to_string();
                        let new_trailing_contents = regex.replace(&contents[offset..], subst);
                        new_contents.push_str(&new_trailing_contents);
                        // Zero-length matches can happen with any
                        // regex that matches the empty string,
                        // such as `a?` or the empty regex.
                        let is_zero_length_match = mat.end() == mat.start();
                        let (start_line, _) = index_to_row_col(&contents, mat.start() + offset);
                        let (end_line, _) = index_to_row_col(
                            &contents,
                            // Avoid generating index of -1 when start
                            // == end == offset = 0 for a zero-length
                            // match.
                            backward_to_char_boundary(
                                &contents,
                                mat.end() + offset - if is_zero_length_match { 0 } else { 1 },
                            ),
                        );
                        let accepted = self.ask_about_patch(
                            path,
                            &contents,
                            start_line + 1,
                            end_line + 1,
                            &new_contents,
                        )?;
                        if accepted {
                            offset = to_char_boundary(
                                &contents,
                                offset
                                + mat.start()
                                + subst.len()
                                // Ensure forward progress when there
                                // is a zero-length match.
                                + if is_zero_length_match { 1 } else { 0 },
                            );
                        } else {
                            // Advance to the next character after the match.
                            offset = to_char_boundary(&contents, offset + mat.end() + 1);
                        }
                    }
                }
            }
            // re-open file in case contents changed.
            contents = read_to_string(path)?;
        }
        Ok(())
    }