Repository: typst/typst
File: crates/typst-library/src/foundations/str.rs (Rust)

Code before:
                .map(match_to_dict)
                .map(Value::Dict)
                .collect(),
            StrPattern::Regex(re) => re
                .captures_iter(self)
                .map(captures_to_dict)
                .map(Value::Dict)
                .collect(),
        }
    }

    /// Replace at most `count` occurrences of the given pattern with a
    /// replacement string or function (beginning from the start). If no count
    /// is given, all occurrences are replaced.
    #[func]
    pub fn replace(
        &self,
        engine: &mut Engine,
        context: Tracked<Context>,
        /// The pattern to search for.
        pattern: StrPattern,
        /// The string to replace the matches with or a function that gets a
        /// dictionary for each match and can return individual replacement
        /// strings.
        ///
        /// The dictionary would be the same as the returned dictionary of
        /// [`match`]($str.match).
        replacement: Replacement,
        ///  If given, only the first `count` matches of the pattern are placed.
        #[named]
        count: Option<usize>,
    ) -> SourceResult<Str> {
        // Heuristic: Assume the new string is about the same length as
        // the current string.
        let mut output = EcoString::with_capacity(self.as_str().len());

        // Replace one match of a pattern with the replacement.
        let mut last_match = 0;
        let mut handle_match = |range: Range<usize>, dict: Dict| -> SourceResult<()> {
            // Push everything until the match.
            output.push_str(&self[last_match..range.start]);
            last_match = range.end;

            // Determine and push the replacement.
            match &replacement {
                Replacement::Str(s) => output.push_str(s),
                Replacement::Func(func) => {
                    let piece = func
                        .call(engine, context, [dict])?
                        .cast::<Str>()
                        .at(func.span())?;

Review comment (suggestion):
How about:

```
The dictionary passed to the function has the same shape as the dictionary returned by [`match`]($str.match).
```

Code after:
                .captures_iter(self)
                .map(captures_to_dict)
                .map(Value::Dict)
                .collect(),
        }
    }

    /// Replace at most `count` occurrences of the given pattern with a
    /// replacement string or function (beginning from the start). If no count
    /// is given, all occurrences are replaced.
    #[func]
    pub fn replace(
        &self,
        engine: &mut Engine,
        context: Tracked<Context>,
        /// The pattern to search for.
        pattern: StrPattern,
        /// The string to replace the matches with or a function that gets a
        /// dictionary for each match and can return individual replacement
        /// strings.
        ///
        /// The dictionary passed to the function has the same shape as the
        /// dictionary returned by [`match`]($str.match).
        replacement: Replacement,
        ///  If given, only the first `count` matches of the pattern are placed.
        #[named]
        count: Option<usize>,
    ) -> SourceResult<Str> {
        // Heuristic: Assume the new string is about the same length as
        // the current string.
        let mut output = EcoString::with_capacity(self.as_str().len());

        // Replace one match of a pattern with the replacement.
        let mut last_match = 0;
        let mut handle_match = |range: Range<usize>, dict: Dict| -> SourceResult<()> {
            // Push everything until the match.
            output.push_str(&self[last_match..range.start]);
            last_match = range.end;

            // Determine and push the replacement.
            match &replacement {
                Replacement::Str(s) => output.push_str(s),
                Replacement::Func(func) => {
                    let piece = func
                        .call(engine, context, [dict])?
                        .cast::<Str>()
                        .at(func.span())?;
                    output.push_str(&piece);
                }
            }