6
6
7
7
import java .util .ArrayList ;
8
8
import java .util .List ;
9
+ import java .util .HashMap ;
10
+ import java .util .Map ;
9
11
import java .util .regex .Matcher ;
10
12
import java .util .regex .Pattern ;
11
13
12
14
public abstract class SystemTextBase extends Text {
13
- // Combined markup pattern for violet highlighting (_text_) and bronze ("text")
14
- protected static final Pattern MARKUP_PATTERN = Pattern .compile ("_(.*?)_|\" (.*?)\" " );
15
- // Markup pattern for highlighting (_text_)
16
- protected static final Pattern HIGHLIGHTER = Pattern .compile ("_(.*?)_" );
17
- // Markup pattern for bronze text ("text")
18
- protected static final Pattern BRONZE_HIGHLIGHTER = Pattern .compile ("\" (.*?)\" " );
15
+ // Combined markup pattern for violet highlighting (_text_), bronze ("text"), and generic color tags ([color:text])
16
+ protected static final Pattern MARKUP_PATTERN = Pattern .compile ("_(.*?)_|\" (.*?)\" |\\ [(#?[a-zA-Z0-9]+):(.*?)?\\ ]" );
17
+
18
+ private static final Map <String , Integer > COLOR_MAP = new HashMap <>();
19
+ static {
20
+ COLOR_MAP .put ("red" , 0xFFFF0000 );
21
+ COLOR_MAP .put ("green" , 0xFF00FF00 );
22
+ COLOR_MAP .put ("blue" , 0xFF0000FF );
23
+ COLOR_MAP .put ("yellow" , 0xFFFFFF00 );
24
+ COLOR_MAP .put ("cyan" , 0xFF00FFFF );
25
+ COLOR_MAP .put ("magenta" , 0xFFFF00FF );
26
+ COLOR_MAP .put ("white" , 0xFFFFFFFF );
27
+ COLOR_MAP .put ("black" , 0xFF000000 );
28
+ COLOR_MAP .put ("gray" , 0xFF808080 );
29
+ COLOR_MAP .put ("orange" , 0xFFFFA500 );
30
+ COLOR_MAP .put ("purple" , 0xFF800080 );
31
+ }
19
32
20
33
protected static float fontScale = Float .NaN ;
21
34
@@ -67,7 +80,7 @@ public static void updateFontScale() {
67
80
* Subclasses can override if needed
68
81
*/
69
82
protected void parseMarkup (String input ) {
70
- if (input != null && ( HIGHLIGHTER .matcher (input ).find () || BRONZE_HIGHLIGHTER . matcher ( input ). find () )) {
83
+ if (input != null && MARKUP_PATTERN .matcher (input ).find ()) {
71
84
hasMarkup = true ;
72
85
}
73
86
}
@@ -80,15 +93,17 @@ protected void parseMarkup(String input) {
80
93
protected String extractPlainText (String str ) {
81
94
if (str == null ) return "" ;
82
95
83
- // Remove both underscore markup (_text_) and quote markup ("text")
84
- return str .replaceAll ("_(.*?)_" , "$1" ).replaceAll ("\" (.*?)\" " , "$1" );
96
+ // Remove underscore, quote, and color tag markup
97
+ return str .replaceAll ("_(.*?)_" , "$1" )
98
+ .replaceAll ("\" (.*?)\" " , "$1" )
99
+ .replaceAll ("\\ [(#?[a-zA-Z0-9]+):(.*?)?\\ ]" , "$2" );
85
100
}
86
101
87
102
/**
88
103
* Set the highlight color for marked text
89
104
*/
90
105
public void highlightColor (int color ) {
91
- this . highlightColor = color ;
106
+ highlightColor = color ;
92
107
if (hasMarkup ) {
93
108
dirty = true ;
94
109
}
@@ -128,6 +143,32 @@ public void text(@NotNull String str) {
128
143
// Parse markup in the original text
129
144
parseMarkup (str );
130
145
}
146
+
147
+ /**
148
+ * Parse a color string (hex or name) into an ARGB integer.
149
+ * @param colorStr The color string (e.g., "#FF0000", "red")
150
+ * @return The integer ARGB color
151
+ */
152
+ private int parseColorString (String colorStr ) {
153
+ if (colorStr == null || colorStr .isEmpty ()) {
154
+ return defaultColor ;
155
+ }
156
+ String lowerCaseColor = colorStr .toLowerCase ();
157
+ if (COLOR_MAP .containsKey (lowerCaseColor )) {
158
+ return COLOR_MAP .get (lowerCaseColor );
159
+ }
160
+ if (colorStr .startsWith ("#" )) {
161
+ try {
162
+ long color = Long .parseLong (colorStr .substring (1 ), 16 );
163
+ if (colorStr .length () == 7 ) { // #RRGGBB
164
+ return (int ) (0xFF000000 | color );
165
+ } else if (colorStr .length () == 9 ) { // #AARRGGBB
166
+ return (int ) color ;
167
+ }
168
+ } catch (NumberFormatException ignored ) {}
169
+ }
170
+ return defaultColor ; // Fallback
171
+ }
131
172
132
173
/**
133
174
* Parse markup in the input string and convert to a list of colored segments.
@@ -149,6 +190,10 @@ protected List<ColoredSegment> parseMarkupToSegments(String input) {
149
190
segments .add (new ColoredSegment (m .group (1 ), highlightColor ));
150
191
} else if (m .group (2 ) != null ) {
151
192
segments .add (new ColoredSegment (m .group (2 ), bronzeColor ));
193
+ } else if (m .group (3 ) != null ) {
194
+ String text = m .group (4 ) != null ? m .group (4 ) : "" ;
195
+ int color = parseColorString (m .group (3 ));
196
+ segments .add (new ColoredSegment (text , color ));
152
197
}
153
198
lastEnd = m .end ();
154
199
}
@@ -216,7 +261,7 @@ protected List<List<ColoredSegment>> wrapText(List<ColoredSegment> allSegments,
216
261
/**
217
262
* Store the text lines after parsing and wrapping
218
263
*/
219
- protected final ArrayList < ArrayList <ColoredSegment >> textLines = new ArrayList <>();
264
+ protected final List < List <ColoredSegment >> textLines = new ArrayList <>();
220
265
221
266
/**
222
267
* Invalidate caches - to be implemented by subclasses
0 commit comments