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).
Summary
Reggie has no equivalent for JDK's stateful
appendReplacement/appendTailpattern, which is used for streaming find-and-replace loops where replacement logic is computed per-match. The existingreplaceAll(String, Function<MatchResult, String>)covers the common case, but not all usages.JDK API being replaced
This is a stateful API: the matcher tracks the last append position across
appendReplacementcalls, andappendTailflushes the remainder.Proposed solution
Option A — add
appendReplacement/appendTailtoReggieMatcherwith internal position state (stateful, mirrors JDK):Option B — expose a stateful iterator/cursor object:
Option B is preferable as it keeps
ReggieMatcherstateless (thread-safe) and avoids re-entrancy issues.Notes
The functional
replaceAll(String, Function<MatchResult, String>)already onReggieMatcherhandles the majority of cases. The gap is specifically the incrementalStringBuilderaccumulation pattern where the caller interleaves custom logic between matches (e.g., conditional replacement, side effects per match).