New approach for chat processing
Created different providers for regex, range and string matching Handling one match at a time per provider TODO: Formatters should be executed one by one in declaration order Add enitre message by default Loop until all of the providers are finished Ignore any areas returned by the providers #71
This commit is contained in:
parent
b452170ff7
commit
0a4cdd01ce
9 changed files with 214 additions and 106 deletions
|
@ -49,7 +49,6 @@ public class ChatProcessing {
|
|||
private static final Pattern CONSOLE_PING_PATTERN = Pattern.compile("(?i)" + Pattern.quote("@console"));
|
||||
private static final Pattern HASHTAG_PATTERN = Pattern.compile("#(\\w+)");
|
||||
private static final Pattern URL_PATTERN = Pattern.compile("(http[\\w:/?=$\\-_.+!*'(),&]+(?:#[\\w]+)?)");
|
||||
public static final Pattern ENTIRE_MESSAGE_PATTERN = Pattern.compile(".+");
|
||||
private static final Pattern UNDERLINED_PATTERN = Pattern.compile("__");
|
||||
private static final Pattern ITALIC_PATTERN = Pattern.compile("\\*");
|
||||
private static final Pattern ITALIC_PATTERN_2 = Pattern.compile("_");
|
||||
|
@ -64,7 +63,10 @@ public class ChatProcessing {
|
|||
private static final Pattern WORD_PATTERN = Pattern.compile("\\S+");
|
||||
private static boolean pingedconsole = false;
|
||||
|
||||
public static final ChatFormatter ESCAPE_FORMATTER = ChatFormatter.builder("escape", ESCAPE_PATTERN).build();
|
||||
/**
|
||||
* A special range formatter that removes the effect of the next formatter
|
||||
*/
|
||||
public static final ChatFormatter ESCAPE_FORMATTER = ChatFormatter.builder("escape", ESCAPE_PATTERN).type(ChatFormatter.Type.Range).build();
|
||||
|
||||
private static ArrayList<ChatFormatter> commonFormatters = Lists.newArrayList(
|
||||
ChatFormatter.builder("bold", BOLD_PATTERN).bold(true).removeCharCount((short) 2).type(ChatFormatter.Type.Range)
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package buttondevteam.chat.components.formatter.formatting;
|
||||
|
||||
import buttondevteam.chat.commands.ucmds.admin.DebugCommand;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
public final class ChatFormatUtils {
|
||||
private ChatFormatUtils() {}
|
||||
|
||||
static void sendMessageWithPointer(String str, int... pointer) {
|
||||
DebugCommand.SendDebugMessage(str);
|
||||
StringBuilder sb = new StringBuilder(str.length());
|
||||
Arrays.sort(pointer);
|
||||
for (int i = 0; i < pointer.length; i++) {
|
||||
for (int j = 0; j < pointer[i] - (i > 0 ? pointer[i - 1] + 1 : 0); j++)
|
||||
sb.append(' ');
|
||||
if (pointer[i] == (i > 0 ? pointer[i - 1] : -1))
|
||||
continue;
|
||||
sb.append('^');
|
||||
}
|
||||
DebugCommand.SendDebugMessage(sb.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given start and end position is inside any of the ranges
|
||||
*/
|
||||
static boolean isInRange(int start, int end, ArrayList<int[]> ranges) {
|
||||
return ranges.stream().anyMatch(range -> range[1] >= start && range[0] <= end - 1);
|
||||
}
|
||||
}
|
|
@ -5,14 +5,12 @@ import buttondevteam.chat.components.formatter.ChatProcessing;
|
|||
import buttondevteam.lib.architecture.ConfigData;
|
||||
import buttondevteam.lib.architecture.IHaveConfig;
|
||||
import buttondevteam.lib.chat.Color;
|
||||
import buttondevteam.lib.chat.Priority;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.val;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -28,16 +26,6 @@ import java.util.stream.Collectors;
|
|||
@Builder
|
||||
public final class ChatFormatter {
|
||||
Pattern regex;
|
||||
boolean italic;
|
||||
boolean bold;
|
||||
boolean underlined;
|
||||
boolean strikethrough;
|
||||
boolean obfuscated;
|
||||
Color color;
|
||||
TriFunc<String, ChatFormatter, FormattedSection, String> onmatch;
|
||||
String openlink;
|
||||
@Builder.Default
|
||||
Priority priority = Priority.Normal;
|
||||
@Builder.Default
|
||||
short removeCharCount = 0;
|
||||
@Builder.Default
|
||||
|
@ -64,18 +52,6 @@ public final class ChatFormatter {
|
|||
return config.getData(name + ".enabled", true);
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
Normal,
|
||||
/**
|
||||
* Matches a start and an end section which gets converted to one section (for example see italics)
|
||||
*/
|
||||
Range,
|
||||
/**
|
||||
* Exclude matching area from further processing (besides this formatter)
|
||||
*/
|
||||
Excluder
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface TriFunc<T1, T2, T3, R> {
|
||||
R apply(T1 x1, T2 x2, T3 x3);
|
||||
|
@ -101,8 +77,8 @@ public final class ChatFormatter {
|
|||
*/
|
||||
val remchars = new ArrayList<int[]>();
|
||||
|
||||
header("Range section conversion");
|
||||
sections = convertRangeSections(str, sections, remchars);
|
||||
header("Range section creation");
|
||||
sections = createRangeSections(str, sections, formatters, remchars);
|
||||
|
||||
header("Adding remove chars (RC)"); // Important to add after the range section conversion
|
||||
addRemChars(sections, remchars, str);
|
||||
|
@ -117,28 +93,6 @@ public final class ChatFormatter {
|
|||
|
||||
private static void createSections(List<ChatFormatter> formatters, String str, ArrayList<FormattedSection> sections,
|
||||
boolean excluders) {
|
||||
for (ChatFormatter formatter : formatters) {
|
||||
if (excluders == (formatter.type != Type.Excluder))
|
||||
continue; //If we're looking at excluders and this isn't one, skip - or vica-versa
|
||||
Matcher matcher = formatter.regex.matcher(str);
|
||||
while (matcher.find()) {
|
||||
DebugCommand.SendDebugMessage("Found match from " + matcher.start() + " to " + (matcher.end() - 1));
|
||||
DebugCommand.SendDebugMessage("With " + (excluders ? "excluder " : "") + "formatter: " + formatter);
|
||||
sendMessageWithPointer(str, matcher.start(), matcher.end() - 1);
|
||||
if (formatter.regex != ChatProcessing.ENTIRE_MESSAGE_PATTERN && sections.stream().anyMatch(fs -> fs.type == Type.Excluder && (fs.End >= matcher.start() && fs.Start <= matcher.end() - 1))) {
|
||||
DebugCommand.SendDebugMessage("Ignoring formatter because of an excluder");
|
||||
continue; //Exclude areas matched by excluders - Range sections are correctly handled afterwards
|
||||
}
|
||||
ArrayList<String> groups = new ArrayList<>();
|
||||
for (int i = 0; i < matcher.groupCount(); i++)
|
||||
groups.add(matcher.group(i + 1));
|
||||
if (groups.size() > 0)
|
||||
DebugCommand.SendDebugMessage("First group: " + groups.get(0));
|
||||
FormattedSection section = new FormattedSection(formatter, matcher.start(), matcher.end() - 1, groups,
|
||||
formatter.type);
|
||||
sections.add(section);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void newCombine(String str, ArrayList<FormattedSection> sections, ArrayList<int[]> remchars) {
|
||||
|
@ -154,7 +108,7 @@ public final class ChatFormatter {
|
|||
}
|
||||
}
|
||||
|
||||
private static ArrayList<FormattedSection> convertRangeSections(String str, ArrayList<FormattedSection> sections, ArrayList<int[]> remchars) {
|
||||
private static ArrayList<FormattedSection> createRangeSections(String str, List<ChatFormatter> formatters, ArrayList<int[]> remchars) {
|
||||
ArrayList<FormattedSection> combined = new ArrayList<>();
|
||||
Map<ChatFormatter, FormattedSection> nextSection = new HashMap<>();
|
||||
boolean escaped = false;
|
||||
|
@ -172,7 +126,7 @@ public final class ChatFormatter {
|
|||
combined.add(section); // The above will delete the \
|
||||
DebugCommand.SendDebugMessage("Added section: " + section);
|
||||
}
|
||||
sendMessageWithPointer(str, section.Start, section.End);
|
||||
ChatFormatUtils.sendMessageWithPointer(str, section.Start, section.End);
|
||||
continue;
|
||||
}
|
||||
if (!escaped) {
|
||||
|
@ -183,17 +137,17 @@ public final class ChatFormatter {
|
|||
*/
|
||||
if (takenByBigGuy || formatter.removeCharCount < takenEnd - takenStart) {
|
||||
DebugCommand.SendDebugMessage("Lose: " + section);
|
||||
sendMessageWithPointer(str, section.Start, section.End);
|
||||
ChatFormatUtils.sendMessageWithPointer(str, section.Start, section.End);
|
||||
DebugCommand.SendDebugMessage("And win: " + takenFormatter);
|
||||
continue; // The current section loses
|
||||
}
|
||||
nextSection.remove(takenFormatter); // The current section wins
|
||||
DebugCommand.SendDebugMessage("Win: " + section);
|
||||
sendMessageWithPointer(str, section.Start, section.End);
|
||||
ChatFormatUtils.sendMessageWithPointer(str, section.Start, section.End);
|
||||
DebugCommand.SendDebugMessage("And lose: " + takenFormatter);
|
||||
}
|
||||
boolean hasFormatter = nextSection.containsKey(formatter);
|
||||
if (!hasFormatter) {
|
||||
/*if (!hasFormatter) {
|
||||
val ff = formatter;
|
||||
val cfo = nextSection.keySet().stream().filter(f -> f.removeCharCount > ff.removeCharCount).findAny();
|
||||
if (cfo.isPresent()) {
|
||||
|
@ -205,7 +159,7 @@ public final class ChatFormatter {
|
|||
continue; //Not the formatter we're looking for - TODO: It doesn't fix the problem of italics at the end
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
takenStart = section.Start;
|
||||
takenEnd = section.Start + formatter.removeCharCount;
|
||||
takenFormatter = formatter;
|
||||
|
@ -218,19 +172,19 @@ public final class ChatFormatter {
|
|||
combined.add(s);
|
||||
takenByBigGuy = true;
|
||||
DebugCommand.SendDebugMessage("Finished section: " + s);
|
||||
sendMessageWithPointer(str, s.Start, s.End);
|
||||
ChatFormatUtils.sendMessageWithPointer(str, s.Start, s.End);
|
||||
} else {
|
||||
DebugCommand.SendDebugMessage("Adding next section: " + section);
|
||||
sendMessageWithPointer(str, section.Start, section.End);
|
||||
ChatFormatUtils.sendMessageWithPointer(str, section.Start, section.End);
|
||||
nextSection.put(formatter, section);
|
||||
takenByBigGuy = false;
|
||||
}
|
||||
DebugCommand
|
||||
.SendDebugMessage("New area taken: (" + takenStart + "-" + takenEnd + ") " + takenFormatter);
|
||||
sendMessageWithPointer(str, takenStart, takenEnd);
|
||||
ChatFormatUtils.sendMessageWithPointer(str, takenStart, takenEnd);
|
||||
} else {
|
||||
DebugCommand.SendDebugMessage("Skipping section: " + section); // This will keep the text (character)
|
||||
sendMessageWithPointer(str, section.Start, section.End);
|
||||
ChatFormatUtils.sendMessageWithPointer(str, section.Start, section.End);
|
||||
escaped = false; // Reset escaping if applied, like if we're at the '*' in '\*'
|
||||
}
|
||||
}
|
||||
|
@ -250,7 +204,7 @@ public final class ChatFormatter {
|
|||
.forEach(remchars::add);
|
||||
DebugCommand.SendDebugMessage("Added remchars:");
|
||||
DebugCommand.SendDebugMessage(remchars.stream().map(Arrays::toString).collect(Collectors.joining("; ")));
|
||||
sendMessageWithPointer(str,
|
||||
ChatFormatUtils.sendMessageWithPointer(str,
|
||||
remchars.stream().flatMapToInt(Arrays::stream).toArray());
|
||||
}
|
||||
|
||||
|
@ -271,15 +225,15 @@ public final class ChatFormatter {
|
|||
lastSection = lastSect;
|
||||
}
|
||||
DebugCommand.SendDebugMessage("Combining sections " + firstSection);
|
||||
sendMessageWithPointer(str, firstSection.Start, firstSection.End);
|
||||
ChatFormatUtils.sendMessageWithPointer(str, firstSection.Start, firstSection.End);
|
||||
DebugCommand.SendDebugMessage(" and " + lastSection);
|
||||
sendMessageWithPointer(str, lastSection.Start, lastSection.End);
|
||||
ChatFormatUtils.sendMessageWithPointer(str, lastSection.Start, lastSection.End);
|
||||
if (firstSection.Start == lastSection.Start && firstSection.End == lastSection.End) {
|
||||
firstSection.Formatters.addAll(lastSection.Formatters);
|
||||
firstSection.Matches.addAll(lastSection.Matches);
|
||||
firstSection.type = lastSection.type;
|
||||
DebugCommand.SendDebugMessage("To section " + firstSection);
|
||||
sendMessageWithPointer(str, firstSection.Start, firstSection.End);
|
||||
ChatFormatUtils.sendMessageWithPointer(str, firstSection.Start, firstSection.End);
|
||||
sections.remove(i);
|
||||
i = 0;
|
||||
sortSections(sections);
|
||||
|
@ -305,7 +259,7 @@ public final class ChatFormatter {
|
|||
Predicate<FormattedSection> removeIfNeeded = s -> {
|
||||
if (s.Start < 0 || s.End < 0 || s.Start > s.End) {
|
||||
DebugCommand.SendDebugMessage(" Removed: " + s);
|
||||
sendMessageWithPointer(str, s.Start, s.End);
|
||||
ChatFormatUtils.sendMessageWithPointer(str, s.Start, s.End);
|
||||
sections.remove(s);
|
||||
return true;
|
||||
}
|
||||
|
@ -315,15 +269,15 @@ public final class ChatFormatter {
|
|||
DebugCommand.SendDebugMessage("To sections");
|
||||
if (!removeIfNeeded.test(firstSection)) {
|
||||
DebugCommand.SendDebugMessage(" 1:" + firstSection + "");
|
||||
sendMessageWithPointer(str, firstSection.Start, firstSection.End);
|
||||
ChatFormatUtils.sendMessageWithPointer(str, firstSection.Start, firstSection.End);
|
||||
}
|
||||
if (!removeIfNeeded.test(section)) {
|
||||
DebugCommand.SendDebugMessage(" 2:" + section + "");
|
||||
sendMessageWithPointer(str, section.Start, section.End);
|
||||
ChatFormatUtils.sendMessageWithPointer(str, section.Start, section.End);
|
||||
}
|
||||
if (!removeIfNeeded.test(lastSection)) {
|
||||
DebugCommand.SendDebugMessage(" 3:" + lastSection);
|
||||
sendMessageWithPointer(str, lastSection.Start, lastSection.End);
|
||||
ChatFormatUtils.sendMessageWithPointer(str, lastSection.Start, lastSection.End);
|
||||
}
|
||||
i = 0;
|
||||
}
|
||||
|
@ -332,7 +286,7 @@ public final class ChatFormatter {
|
|||
for (int j = i - 1; j <= i + 1; j++) {
|
||||
if (j < sections.size() && sections.get(j).End < sections.get(j).Start) {
|
||||
DebugCommand.SendDebugMessage("Removing section: " + sections.get(j));
|
||||
sendMessageWithPointer(str, sections.get(j).Start, sections.get(j).End);
|
||||
ChatFormatUtils.sendMessageWithPointer(str, sections.get(j).Start, sections.get(j).End);
|
||||
sections.remove(j);
|
||||
j--;
|
||||
i = 0;
|
||||
|
@ -349,7 +303,7 @@ public final class ChatFormatter {
|
|||
String originaltext;
|
||||
int start = section.Start, end = section.End;
|
||||
DebugCommand.SendDebugMessage("Start: " + start + " - End: " + end);
|
||||
sendMessageWithPointer(str, start, end);
|
||||
ChatFormatUtils.sendMessageWithPointer(str, start, end);
|
||||
/*DebugCommand.SendDebugMessage("RCS: "+remchars.stream().filter(rc -> rc[0] <= start && start <= rc[1]).count());
|
||||
DebugCommand.SendDebugMessage("RCE: "+remchars.stream().filter(rc -> rc[0] <= end && end <= rc[1]).count());
|
||||
DebugCommand.SendDebugMessage("RCI: "+remchars.stream().filter(rc -> start < rc[0] || rc[1] < end).count());*/
|
||||
|
@ -432,20 +386,6 @@ public final class ChatFormatter {
|
|||
: Integer.compare(s1.Start, s2.Start));
|
||||
}
|
||||
|
||||
private static void sendMessageWithPointer(String str, int... pointer) {
|
||||
DebugCommand.SendDebugMessage(str);
|
||||
StringBuilder sb = new StringBuilder(str.length());
|
||||
Arrays.sort(pointer);
|
||||
for (int i = 0; i < pointer.length; i++) {
|
||||
for (int j = 0; j < pointer[i] - (i > 0 ? pointer[i - 1] + 1 : 0); j++)
|
||||
sb.append(' ');
|
||||
if (pointer[i] == (i > 0 ? pointer[i - 1] : -1))
|
||||
continue;
|
||||
sb.append('^');
|
||||
}
|
||||
DebugCommand.SendDebugMessage(sb.toString());
|
||||
}
|
||||
|
||||
private static void header(String message) {
|
||||
DebugCommand.SendDebugMessage("\n--------\n" + message + "\n--------\n");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package buttondevteam.chat.components.formatter.formatting;
|
||||
|
||||
import buttondevteam.lib.chat.Color;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
public class FormatSettings {
|
||||
boolean italic;
|
||||
boolean bold;
|
||||
boolean underlined;
|
||||
boolean strikethrough;
|
||||
boolean obfuscated;
|
||||
Color color;
|
||||
ChatFormatter.TriFunc<String, ChatFormatter, FormattedSection, String> onmatch;
|
||||
String openlink;
|
||||
}
|
|
@ -1,36 +1,17 @@
|
|||
package buttondevteam.chat.components.formatter.formatting;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
public class FormattedSection {
|
||||
public int Start;
|
||||
public int End;
|
||||
public ArrayList<ChatFormatter> Formatters = new ArrayList<ChatFormatter>();
|
||||
public FormatSettings Settings;
|
||||
public ArrayList<String> Matches = new ArrayList<String>();
|
||||
public ChatFormatter.Type type;
|
||||
|
||||
FormattedSection(ChatFormatter formatter, int start, int end, ArrayList<String> matches, ChatFormatter.Type type) {
|
||||
FormattedSection(FormatSettings settings, int start, int end, ArrayList<String> matches) {
|
||||
Start = start;
|
||||
End = end;
|
||||
Formatters.add(formatter);
|
||||
Settings = settings;
|
||||
Matches.addAll(matches);
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
FormattedSection(Collection<ChatFormatter> formatters, int start, int end, ArrayList<String> matches,
|
||||
ChatFormatter.Type type) {
|
||||
Start = start;
|
||||
End = end;
|
||||
Formatters.addAll(formatters);
|
||||
Matches.addAll(matches);
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Section(" + Start + ", " + End + ", formatters: " +
|
||||
Formatters.toString() + ", matches: " + Matches.toString() + ", " +
|
||||
type + ")";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package buttondevteam.chat.components.formatter.formatting;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public interface MatchProvider {
|
||||
@Nullable
|
||||
FormattedSection getNextSection(String message, ArrayList<int[]> ignoredAreas, ArrayList<int[]> removedCharacters);
|
||||
|
||||
boolean isFinished();
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package buttondevteam.chat.components.formatter.formatting;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class RangeMatchProvider implements MatchProvider {
|
||||
private final String pattern;
|
||||
private final FormatSettings settings;
|
||||
@Getter
|
||||
private boolean finished;
|
||||
private int nextIndex = 0;
|
||||
private FormattedSection startedSection;
|
||||
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
@Override
|
||||
public FormattedSection getNextSection(String message, ArrayList<int[]> ignoredAreas, ArrayList<int[]> removedCharacters) {
|
||||
int i, len;
|
||||
do {
|
||||
i = message.indexOf(pattern, nextIndex);
|
||||
len = pattern.length();
|
||||
nextIndex = i + len; //Set for the next loop if it's escaped or for the next method call
|
||||
} while (i > 0 && message.charAt(i - 1) == '\\');
|
||||
if (i == -1) {
|
||||
finished = true; //Won't find any more - unfinished sections will be garbage collected
|
||||
return null;
|
||||
}
|
||||
removedCharacters.add(new int[]{i, i + len - 1});
|
||||
if (startedSection == null) {
|
||||
startedSection = new FormattedSection(settings, i, i + len - 1, new ArrayList<>(0));
|
||||
return null;
|
||||
} else {
|
||||
startedSection.End = i + len - 1;
|
||||
return startedSection;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package buttondevteam.chat.components.formatter.formatting;
|
||||
|
||||
import buttondevteam.chat.commands.ucmds.admin.DebugCommand;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class RegexMatchProvider implements MatchProvider {
|
||||
private final Pattern pattern;
|
||||
private final FormatSettings settings;
|
||||
private Matcher matcher;
|
||||
@Getter
|
||||
private boolean finished;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public FormattedSection getNextSection(String message, ArrayList<int[]> ignoredAreas, ArrayList<int[]> removedCharacters) {
|
||||
if (matcher == null)
|
||||
matcher = pattern.matcher(message);
|
||||
if (!matcher.find()) {
|
||||
finished = true;
|
||||
return null;
|
||||
}
|
||||
int start = matcher.start(), end = matcher.end() - 1;
|
||||
DebugCommand.SendDebugMessage("Found regex match from " + start + " to " + end);
|
||||
DebugCommand.SendDebugMessage("With settings: " + settings);
|
||||
ChatFormatUtils.sendMessageWithPointer(message, start, end);
|
||||
if (ChatFormatUtils.isInRange(start, end, ignoredAreas)) {
|
||||
DebugCommand.SendDebugMessage("Formatter is in ignored area, skipping");
|
||||
return null; //Not setting finished to true, so it will go to the next match
|
||||
}
|
||||
ArrayList<String> groups = new ArrayList<>();
|
||||
for (int i = 0; i < matcher.groupCount(); i++)
|
||||
groups.add(matcher.group(i + 1));
|
||||
if (groups.size() > 0)
|
||||
DebugCommand.SendDebugMessage("First group: " + groups.get(0));
|
||||
return new FormattedSection(settings, matcher.start(), matcher.end() - 1, groups);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package buttondevteam.chat.components.formatter.formatting;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class StringMatchProvider implements MatchProvider {
|
||||
private final String[] strings;
|
||||
private final FormatSettings settings;
|
||||
@Getter
|
||||
private boolean finished;
|
||||
private int nextIndex = 0;
|
||||
|
||||
/**
|
||||
* Matches the given strings in the order given
|
||||
*
|
||||
* @param settings The format settings
|
||||
* @param strings The strings to match in the correct order
|
||||
*/
|
||||
public StringMatchProvider(FormatSettings settings, String... strings) {
|
||||
this.settings = settings;
|
||||
this.strings = strings;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public FormattedSection getNextSection(String message, ArrayList<int[]> ignoredAreas, ArrayList<int[]> removedCharacters) {
|
||||
int i = -1, len = 0;
|
||||
for (String string : strings) {
|
||||
i = message.indexOf(string, nextIndex);
|
||||
len = string.length();
|
||||
if (i != -1) break;
|
||||
}
|
||||
if (i == -1) {
|
||||
finished = true; //Won't find any more
|
||||
return null;
|
||||
}
|
||||
nextIndex = i + len;
|
||||
return new FormattedSection(settings, i, i + len - 1, new ArrayList<>(0));
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue