Skip to content

Commit

Permalink
api: Fix handling of first replacements in child components
Browse files Browse the repository at this point in the history
Fixes #197
  • Loading branch information
zml2008 committed Nov 15, 2020
1 parent ae2005b commit ce6ca40
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ private TextReplacementRenderer() {
@Override
public @NonNull Component render(final @NonNull Component component, final @NonNull State state) {
if(!state.running) return component;
final boolean prevFirstMatch = state.firstMatch;
state.firstMatch = true;

final List<Component> oldChildren = component.children();
final int oldChildrenSize = oldChildren.size();
Expand Down Expand Up @@ -90,7 +92,7 @@ private TextReplacementRenderer() {
if(children == null) {
children = new ArrayList<>(oldChildrenSize + 2);
}
if(state.replaceCount == 0) {
if(state.firstMatch) {
// truncate parent to content before match
modified = ((TextComponent) component).content(content.substring(0, matcher.start()));
} else if(replacedUntil < matcher.start()) {
Expand All @@ -102,6 +104,7 @@ private TextReplacementRenderer() {
}
}
state.replaceCount++;
state.firstMatch = false;
replacedUntil = matcher.end();
}
if(replacedUntil < content.length()) {
Expand Down Expand Up @@ -175,6 +178,7 @@ private TextReplacementRenderer() {
if(children != null) {
return modified.children(children);
}
state.firstMatch = prevFirstMatch;
return modified;
}

Expand All @@ -185,6 +189,7 @@ static final class State {
boolean running = true;
int matchCount = 0;
int replaceCount = 0;
boolean firstMatch = true;

State(final @NonNull Pattern pattern, final @NonNull BiFunction<MatchResult, TextComponent.Builder, @Nullable ComponentLike> replacement, final @NonNull IntFunction2<PatternReplacementResult> continuer) {
this.pattern = pattern;
Expand Down
29 changes: 29 additions & 0 deletions api/src/test/java/net/kyori/adventure/text/TextComponentTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import com.google.common.collect.ImmutableSet;
import java.util.Collections;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.IntStream;
import net.kyori.adventure.text.event.HoverEvent;
Expand Down Expand Up @@ -272,7 +273,35 @@ void testPartialReplaceHasIsolatedStyle() {
});

assertEquals(expectedReplacement, component.replaceText(Pattern.compile("Hello"), builder -> builder.content("Goodbye").color(NamedTextColor.LIGHT_PURPLE)));
}

// https://github.com/KyoriPowered/adventure/issues/197
@Test
void testReplaceSameInComponentAndEvent() {
final Component original = Component.text("/{0}", NamedTextColor.RED)
.hoverEvent(Component.text()
.append(Component.text("Click to run"))
.append(Component.space())
.append(Component.text("/{0}", NamedTextColor.RED)).build());

final Component expected = Component.text("/", NamedTextColor.RED)
.append(Component.text("mycommand"))
.hoverEvent(Component.text()
.append(Component.text("Click to run"))
.append(Component.space())
.append(Component.text("/", NamedTextColor.RED).append(Component.text("mycommand"))).build());

final Pattern replaceWith = Pattern.compile("\\{(\\d+)}");

final Component replaced = original.replaceText(replaceWith, b -> {
final Matcher matcher = replaceWith.matcher(b.content());
assertTrue(matcher.find());
assertEquals(0, Integer.parseInt(matcher.group(1))); // only one index in our test case

return Component.text("mycommand");
});

assertEquals(expected, replaced);
}

@Test
Expand Down

0 comments on commit ce6ca40

Please sign in to comment.