2 * Copyright winterwell Mathematics Ltd.
3 * @author Daniel Winterstein
6 package winterwell.markdown.editors;
8 import org.eclipse.jface.text.rules.ICharacterScanner;
9 import org.eclipse.jface.text.rules.IToken;
10 import org.eclipse.jface.text.rules.Token;
11 import org.eclipse.jface.text.rules.IRule;
12 import org.eclipse.core.runtime.Assert;
19 public class LinkRule implements IRule {
20 private static char[][] fDelimiters = null;
21 protected IToken fToken;
23 public LinkRule(IToken token) {
24 Assert.isNotNull(token);
29 * @see IPredicateRule#getSuccessToken()
32 public IToken getSuccessToken() {
37 // Copied from org.eclipse.jface.text.rules.PatternRule
38 protected boolean sequenceDetected(ICharacterScanner scanner, char[] sequence, boolean eofAllowed) {
39 for (int i= 1; i < sequence.length; i++) {
40 int c= scanner.read();
41 if (c == ICharacterScanner.EOF && eofAllowed) {
43 } else if (c != sequence[i]) {
44 // Non-matching character detected, rewind the scanner back to the start.
45 // Do not unread the first character.
47 for (int j= i-1; j > 0; j--)
56 * @see IRule#evaluate(ICharacterScanner)
59 public IToken evaluate(ICharacterScanner scanner) {
61 if ((c = scanner.read()) != '[') {
62 if ((c != 'h' || ( !sequenceDetected(scanner, "http://".toCharArray(), false) && !sequenceDetected(scanner, "https://".toCharArray(), false) ))
63 && (c != 'f' || !sequenceDetected(scanner, "ftp://".toCharArray(), false)) ) {
64 // Not even a non-standard link
66 return Token.UNDEFINED;
69 //+ preventing NPE (Non-standard link should not be below as comment above suggests) by Paul Verest
70 if (fDelimiters == null) {
72 return Token.UNDEFINED;
76 while ((c = scanner.read()) != ICharacterScanner.EOF && !Character.isWhitespace(c)) {
77 for (int i = 0; i < fDelimiters.length; i++) {
78 if (c == fDelimiters[i][0] && sequenceDetected(scanner, fDelimiters[i], true)) {
85 if (fDelimiters == null) {
86 fDelimiters = scanner.getLegalLineDelimiters();
90 // Find '](' and then find ')'
91 boolean sequenceFound = false;
92 int delimiterFound = 0;
93 while ((c = scanner.read()) != ICharacterScanner.EOF && delimiterFound < 2) {
95 if ( !sequenceFound && c == ']') {
103 } else if (c == ')') { // '](' is already found
108 for (i = 0; i < fDelimiters.length; i++) {
109 if (c == fDelimiters[i][0] && sequenceDetected(scanner, fDelimiters[i], true)) {
114 if (i == fDelimiters.length)
118 for (; readCount > 0; readCount--)
120 return Token.UNDEFINED;