So I was looking at reddit and was wondering how they managed to do the formatting thing with the bold and the italic via asterisks encapsulating text, so I tried replicating that effect in java. I tried a lot of things and the following code is a scramble/mix/mashup of everything I tried
public static ArrayList<String> redditReformat(String message) {
ArrayList<String> single = new ArrayList<>();
ArrayList<String> doubl = new ArrayList<>();
ArrayList<String> fin = new ArrayList<>();
if (message.contains("*") && !message.contains("**")) {
ArrayList<Integer> asterisks = new ArrayList<>();
for (int index = message.indexOf("*"); index >= 0; index = message.indexOf("*", index + 1)) {
asterisks.add(index);
}
HashMap<Integer, Integer> patterns = new HashMap<>();
for (int start : asterisks) {
for (int end : asterisks) {
if (start < end) {
if ((start + 1) != end) {
if (!patterns.containsKey(start) && !patterns.containsValue(end)) {
single.add(message.substring(start, end));
patterns.put(start, end);
}
} else {
if (message.charAt(start + 1) == message.charAt(start)) {
if (message.charAt(end + 1) == message.charAt(end)) {
ArrayList<Integer> doubleasterisks = new ArrayList<>();
if (!patterns.containsKey(start) && !patterns.containsValue(end)) {
doubl.add(message.substring(start + 2, end - 1));
if (doubleasterisks.size() < 2) {
doubleasterisks.add(start + end);
} else {
patterns.put(doubleasterisks.get(1), doubleasterisks.get(2));
doubleasterisks.clear();
}
}
}
}
}
}
}
}
}
for (String s : single) {
fin.add(s);
}
for (String d : doubl) {
fin.add(d);
}
return fin;
}
Yes it's messy and probably horrible, I've tried simple and complex things but this isn't going well. The method is supposed to return the asterisks between the a message as well, so like "haha *lol* potato" (stackoverflow formats the asterisks)
It currently returns "*lol" instead of "*lol*" and it just doesn't work when done with **
It also fails when there's more than one encapsulation.
You can use a regular expression pattern to find occurrences:
String s = "blah *lol* blah";
Pattern pattern = Pattern.compile("\\*([^\\*]*)\\*");
Matcher matcher = pattern.matcher(s);
while (matcher.find()) {
System.out.println(matcher.group(1));
}
Prints:
lol
If you haven't come across regular expressions before, I strongly recommend you learn about them. They are useful in lots of text-extraction / text-munging situations.
The expression:
\\*([^\\*]*)\\*
Breaks down as follows:
\\* match an asterisk (it's escaped with a backslash
because * is a meaningful character in a regular
expression. It has to be double escaped because
backslash is a meaningful character in a Java
string.
( start a capturing group
[^\\*]* match zero or more characters that are not asterisk
) end the capturing group
\\* match another asterisk
(Actually, regular expressions may not handle every case perfectly here, as they don't handle nesting, eg *italic **bold***
, but are probably good enough. A "proper" solution would be to write some lexing/parsing code that takes each character at a time, and maintains state. For this situation you may even need backtracking, as it's not clear whether a ***
starts an italic or bold section until you have parsed further.)
If you want this functionality, there are lots of pre-written Markdown parsers.
Updated to use Bukkit's ChatColor
constants 更新为使用Bukkit的ChatColor
常量
As people in the comments are saying you should probably use regular expressions for this task.
Reading a bit about Minecraft chat formatting it seems that in order to make
text
bold you need to surround it like this:
§ltext§r
.
For underline it is similar:
§ntext§r
.
In order to include the special character in the Java code you can use the unicode
\§
.
Here is some example code using regular expressions to replace single asterisks as underline and double asterisks as bold:
public static String applyFormatting(String message) {
// BOLD: replace all occurrences of "**text**" with BOLD+"text"+RESET
message = message.replaceAll("\\*\\*([^\\*]*)\\*\\*", ChatColor.BOLD + "$1" + ChatColor.RESET);
// UNDERLINE: replace all occurrences of "*text*" with ITALIC+"text"+RESET
message = message.replaceAll("\\*([^\\*]*)\\*", ChatColor.ITALIC + "$1" + ChatColor.RESET);
return message;
}
This will not work with nested formatting like **This *is* a test**
though.
It has not been tested with Minecraft.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.