aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Schneppe <christian@pix-art.de>2017-11-20 20:51:04 +0100
committerChristian Schneppe <christian@pix-art.de>2017-11-20 20:51:04 +0100
commit7949c0ac2947ead64615d90cf9e7867297e53427 (patch)
treeaeccfbafa650b5f56187b61d7d0e5521e4f6a702
parent3f4baf530f36a55dbba8d5e60a103dc1577188dc (diff)
styling: introduce support for code blocks
Diffstat (limited to '')
-rw-r--r--src/main/java/de/pixart/messenger/utils/ImStyleParser.java46
-rw-r--r--src/main/java/de/pixart/messenger/utils/StylingHelper.java18
2 files changed, 47 insertions, 17 deletions
diff --git a/src/main/java/de/pixart/messenger/utils/ImStyleParser.java b/src/main/java/de/pixart/messenger/utils/ImStyleParser.java
index 0046ba464..5c41c95e2 100644
--- a/src/main/java/de/pixart/messenger/utils/ImStyleParser.java
+++ b/src/main/java/de/pixart/messenger/utils/ImStyleParser.java
@@ -34,19 +34,29 @@ import java.util.Arrays;
import java.util.List;
public class ImStyleParser {
- final static List<Character> KEYWORDS = Arrays.asList('*', '_', '~', '`');
- final static List<Character> NO_SUB_PARSING_KEYWORDS = Arrays.asList('`');
- final static boolean ALLOW_EMPTY = false;
+ private final static List<Character> KEYWORDS = Arrays.asList('*', '_', '~', '`');
+ private final static List<Character> NO_SUB_PARSING_KEYWORDS = Arrays.asList('`');
+ private final static List<Character> BLOCK_KEYWORDS = Arrays.asList('`');
+ private final static boolean ALLOW_EMPTY = false;
public static List<Style> parse(CharSequence text) {
return parse(text, 0, text.length() - 1);
}
- public static List<Style> parse(CharSequence text, int start, int end) {
+ private static List<Style> parse(CharSequence text, int start, int end) {
List<Style> styles = new ArrayList<>();
for (int i = start; i <= end; ++i) {
char c = text.charAt(i);
if (KEYWORDS.contains(c) && precededByWhiteSpace(text, i, start) && !followedByWhitespace(text, i, end)) {
+ if (BLOCK_KEYWORDS.contains(c) && isCharRepeatedTwoTimes(text, c, i + 1, end)) {
+ int to = seekEndBlock(text, c, i + 3, end);
+ if (to != -1 && (to != i + 5 || ALLOW_EMPTY)) {
+ String keyword = String.valueOf(c) + String.valueOf(c) + String.valueOf(c);
+ styles.add(new Style(keyword, i, to));
+ i = to;
+ continue;
+ }
+ }
int to = seekEnd(text, c, i + 1, end);
if (to != -1 && (to != i + 1 || ALLOW_EMPTY)) {
styles.add(new Style(c, i, to));
@@ -60,6 +70,10 @@ public class ImStyleParser {
return styles;
}
+ private static boolean isCharRepeatedTwoTimes(CharSequence text, char c, int index, int end) {
+ return index + 1 <= end && text.charAt(index) == c && text.charAt(index) == c;
+ }
+
private static boolean precededByWhiteSpace(CharSequence text, int index, int start) {
return index == start || Character.isWhitespace(text.charAt(index - 1));
}
@@ -80,20 +94,34 @@ public class ImStyleParser {
return -1;
}
+ private static int seekEndBlock(CharSequence text, char needle, int start, int end) {
+ for (int i = start; i <= end; ++i) {
+ char c = text.charAt(i);
+ if (c == needle && isCharRepeatedTwoTimes(text, needle, i + 1, end)) {
+ return i + 2;
+ }
+ }
+ return -1;
+ }
+
public static class Style {
- private final char c;
+ private final String keyword;
private final int start;
private final int end;
- public Style(char c, int start, int end) {
- this.c = c;
+ public Style(char character, int start, int end) {
+ this(String.valueOf(character), start, end);
+ }
+
+ public Style(String keyword, int start, int end) {
+ this.keyword = keyword;
this.start = start;
this.end = end;
}
- public char getCharacter() {
- return c;
+ public String getKeyword() {
+ return keyword;
}
public int getStart() {
diff --git a/src/main/java/de/pixart/messenger/utils/StylingHelper.java b/src/main/java/de/pixart/messenger/utils/StylingHelper.java
index 8d5e73ccf..b04a1f8a2 100644
--- a/src/main/java/de/pixart/messenger/utils/StylingHelper.java
+++ b/src/main/java/de/pixart/messenger/utils/StylingHelper.java
@@ -67,21 +67,23 @@ public class StylingHelper {
public static void format(final Editable editable, @ColorInt int textColor) {
for (ImStyleParser.Style style : ImStyleParser.parse(editable)) {
- editable.setSpan(createSpanForStyle(style), style.getStart() + 1, style.getEnd(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
- makeKeywordOpaque(editable, style.getStart(), style.getStart() + 1, textColor);
- makeKeywordOpaque(editable, style.getEnd(), style.getEnd() + 1, textColor);
+ final int keywordLength = style.getKeyword().length();
+ editable.setSpan(createSpanForStyle(style), style.getStart() + keywordLength, style.getEnd() - keywordLength + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ makeKeywordOpaque(editable, style.getStart(), style.getStart() + keywordLength, textColor);
+ makeKeywordOpaque(editable, style.getEnd() - keywordLength + 1, style.getEnd() + 1, textColor);
}
}
private static ParcelableSpan createSpanForStyle(ImStyleParser.Style style) {
- switch (style.getCharacter()) {
- case '*':
+ switch (style.getKeyword()) {
+ case "*":
return new StyleSpan(Typeface.BOLD);
- case '_':
+ case "_":
return new StyleSpan(Typeface.ITALIC);
- case '~':
+ case "~":
return new StrikethroughSpan();
- case '`':
+ case "`":
+ case "```":
return new TypefaceSpan("monospace");
default:
throw new AssertionError("Unknown Style");