/** * Copyright winterwell Mathematics Ltd. * @author Daniel Winterstein * 11 Jan 2007 */ package winterwell.markdown.editors; import org.eclipse.jface.text.rules.ICharacterScanner; import org.eclipse.jface.text.rules.IToken; import org.eclipse.jface.text.rules.Token; import org.eclipse.jface.text.rules.IRule; import org.eclipse.core.runtime.Assert; /** * * * @author Amir Pakdel */ public class LinkRule implements IRule { private static char[][] fDelimiters = null; protected IToken fToken; public LinkRule(IToken token) { Assert.isNotNull(token); fToken= token; } /* * @see IPredicateRule#getSuccessToken() * @since 2.0 */ public IToken getSuccessToken() { return fToken; } // Copied from org.eclipse.jface.text.rules.PatternRule protected boolean sequenceDetected(ICharacterScanner scanner, char[] sequence, boolean eofAllowed) { for (int i= 1; i < sequence.length; i++) { int c= scanner.read(); if (c == ICharacterScanner.EOF && eofAllowed) { return true; } else if (c != sequence[i]) { // Non-matching character detected, rewind the scanner back to the start. // Do not unread the first character. scanner.unread(); for (int j= i-1; j > 0; j--) scanner.unread(); return false; } } return true; } /* * @see IRule#evaluate(ICharacterScanner) * @since 2.0 */ public IToken evaluate(ICharacterScanner scanner) { int c; if ((c = scanner.read()) != '[') { if ((c != 'h' || ( !sequenceDetected(scanner, "http://".toCharArray(), false) && !sequenceDetected(scanner, "https://".toCharArray(), false) )) && (c != 'f' || !sequenceDetected(scanner, "ftp://".toCharArray(), false)) ) { // Not even a non-standard link scanner.unread(); return Token.UNDEFINED; } //+ preventing NPE (Non-standard link should not be below as comment above suggests) by Paul Verest if (fDelimiters == null) { scanner.unread(); return Token.UNDEFINED; } // Non-standard link while ((c = scanner.read()) != ICharacterScanner.EOF && !Character.isWhitespace(c)) { for (int i = 0; i < fDelimiters.length; i++) { if (c == fDelimiters[i][0] && sequenceDetected(scanner, fDelimiters[i], true)) { return fToken; } } } return fToken; } if (fDelimiters == null) { fDelimiters = scanner.getLegalLineDelimiters(); } int readCount = 1; // Find '](' and then find ')' boolean sequenceFound = false; int delimiterFound = 0; while ((c = scanner.read()) != ICharacterScanner.EOF && delimiterFound < 2) { readCount++; if ( !sequenceFound && c == ']') { c = scanner.read(); if (c == '(') { readCount++; sequenceFound = true; } else { scanner.unread(); } } else if (c == ')') { // '](' is already found return fToken; } int i; for (i = 0; i < fDelimiters.length; i++) { if (c == fDelimiters[i][0] && sequenceDetected(scanner, fDelimiters[i], true)) { delimiterFound ++; break; } } if (i == fDelimiters.length) delimiterFound = 0; } for (; readCount > 0; readCount--) scanner.unread(); return Token.UNDEFINED; } }