Created
September 11, 2021 15:23
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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