diff options
author | Christian Schneppe <christian@pix-art.de> | 2017-11-20 20:51:04 +0100 |
---|---|---|
committer | Christian Schneppe <christian@pix-art.de> | 2017-11-20 20:51:04 +0100 |
commit | 7949c0ac2947ead64615d90cf9e7867297e53427 (patch) | |
tree | aeccfbafa650b5f56187b61d7d0e5521e4f6a702 /src/main/java | |
parent | 3f4baf530f36a55dbba8d5e60a103dc1577188dc (diff) |
styling: introduce support for code blocks
Diffstat (limited to 'src/main/java')
-rw-r--r-- | src/main/java/de/pixart/messenger/utils/ImStyleParser.java | 46 | ||||
-rw-r--r-- | src/main/java/de/pixart/messenger/utils/StylingHelper.java | 18 |
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"); |