Skip to content

Instantly share code, notes, and snippets.

@bluelhf
Created September 11, 2021 15:23
Show Gist options
  • Save bluelhf/f407a4c3ef76088d07e810096f0872f5 to your computer and use it in GitHub Desktop.
Save bluelhf/f407a4c3ef76088d07e810096f0872f5 to your computer and use it in GitHub Desktop.
Handles replacing printf-style format strings and named format strings in Adventure text components
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.TextReplacementConfig;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ComponentUtils {
/**
* Handles replacing printf-style format strings and named format strings in components.
* Stuff like <code>%prefix%</code> or <code>%s</code>
*/
public static class Format {
private final Map<String, TextComponent> named = new HashMap<>();
private final List<TextComponent> unnamed = new ArrayList<>();
public Format named(String name, TextComponent value) {
named.put(name, value);
return this;
}
public Format unnamed(TextComponent value) {
unnamed.add(value);
return this;
}
public Component apply(TextComponent component) {
AtomicInteger unnamedCounter = new AtomicInteger(1);
StringBuilder patternBuilder = new StringBuilder("(");
String[] quoteNamed = new String[named.size()];
int i = 0;
for (String key : named.keySet()) {
quoteNamed[i] = Pattern.quote("%" + key + "%");
i++;
}
patternBuilder.append(String.join("|", quoteNamed));
patternBuilder.append("|%s");
for (int j = 1; j < unnamed.size() + 1; j++) {
patternBuilder.append("|").append("%").append(j).append("$s");
}
patternBuilder.append(")");
Pattern anyPattern = Pattern.compile(patternBuilder.toString());
Pattern namedPattern = Pattern.compile("%(.*?)%");
Pattern indexedPattern = Pattern.compile("%\\$(\\D)s");
Pattern unindexedPattern = Pattern.compile("%s", Pattern.LITERAL);
return component.replaceText(TextReplacementConfig.builder()
.match(anyPattern)
.replacement((MatchResult result, TextComponent.Builder builder) -> {
Matcher namedMatcher = namedPattern.matcher(result.group(0));
Matcher indexedMatcher = indexedPattern.matcher(result.group(0));
Matcher unindexedMatcher = unindexedPattern.matcher(result.group(0));
if (namedMatcher.matches() && named.containsKey(namedMatcher.group(1))) {
return named.get(namedMatcher.group(1));
} else {
int idx;
if (indexedMatcher.matches() && (idx = Integer.parseUnsignedInt(indexedMatcher.group(1))) <= unnamed.size()) {
return unnamed.get(idx);
} else if (unindexedMatcher.matches()) {
return unnamed.get(unnamedCounter.getAndIncrement());
}
}
return Component.empty();
}).build());
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment