Skip to content

[feature] Stateful streaming replacement: appendReplacement / appendTail equivalent #46

@jbachorik

Description

@jbachorik

Summary

Reggie has no equivalent for JDK's stateful appendReplacement / appendTail pattern, which is used for streaming find-and-replace loops where replacement logic is computed per-match. The existing replaceAll(String, Function<MatchResult, String>) covers the common case, but not all usages.

JDK API being replaced

// JDK pattern: loop with per-match replacement and custom StringBuilder accumulation
Matcher m = pattern.matcher(content);
StringBuilder sb = new StringBuilder();
while (m.find()) {
    m.appendReplacement(sb, placeholder);
}
m.appendTail(sb);
return sb.toString();

This is a stateful API: the matcher tracks the last append position across appendReplacement calls, and appendTail flushes the remainder.

Proposed solution

Option A — add appendReplacement / appendTail to ReggieMatcher with internal position state (stateful, mirrors JDK):

public ReggieMatcher reset(String input);
public boolean findNext();              // advances internal position
public ReggieMatcher appendReplacement(StringBuilder sb, String replacement);
public StringBuilder appendTail(StringBuilder sb);

Option B — expose a stateful iterator/cursor object:

public MatchCursor cursor(String input);  // new stateful object
// cursor.findNext() -> MatchResult or null
// cursor.appendReplacement(sb, repl)
// cursor.appendTail(sb)

Option B is preferable as it keeps ReggieMatcher stateless (thread-safe) and avoids re-entrancy issues.

Notes

The functional replaceAll(String, Function<MatchResult, String>) already on ReggieMatcher handles the majority of cases. The gap is specifically the incremental StringBuilder accumulation pattern where the caller interleaves custom logic between matches (e.g., conditional replacement, side effects per match).

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions