@Override public Token getLastPaintableToken() { Token t = this; while (t.isPaintable()) { Token next = t.getNextToken(); if (next==null || !next.isPaintable()) { return t; } t = next; } return null; }
private void loadTokenListForCurLine() { token = doc.getTokenListForLine(curLine); if (token!=null && !token.isPaintable()) { // Common end of document scenario token = null; } }
@Override public Token getLastNonCommentNonWhitespaceToken() { Token last = null; for (Token t=this; t!=null && t.isPaintable(); t=t.getNextToken()) { switch (t.getType()) { case COMMENT_DOCUMENTATION: case COMMENT_EOL: case COMMENT_MULTILINE: case COMMENT_KEYWORD: case COMMENT_MARKUP: case WHITESPACE: break; default: last = t; break; } } return last; }
/** * Determines the width of the given token list taking tabs * into consideration. This is implemented in a 1.1 style coordinate * system where ints are used and 72dpi is assumed.<p> * * @param tokenList The token list list representing the text. * @param textArea The text area in which this token list resides. * @param e The tab expander. This value cannot be <code>null</code>. * @param x0 The x-pixel coordinate of the start of the token list. * @return The width of the token list, in pixels. * @see #getTokenListWidthUpTo */ public static float getTokenListWidth(final Token tokenList, RSyntaxTextArea textArea, TabExpander e, float x0) { float width = x0; for (Token t=tokenList; t!=null&&t.isPaintable(); t=t.getNextToken()) { width += t.getWidth(textArea, e, width); } return width - x0; }
/** * Returns the token at the specified index, or <code>null</code> if * the given offset isn't in this token list's range.<br> * Note that this method does NOT check to see if <code>tokenList</code> * is null; callers should check for themselves. * * @param tokenList The list of tokens in which to search. * @param offset The offset at which to get the token. * @return The token at <code>offset</code>, or <code>null</code> if * none of the tokens are at that offset. * @see #getTokenAtOffset(RSyntaxTextArea, int) * @see #getTokenAtOffset(RSyntaxDocument, int) */ public static Token getTokenAtOffset(Token tokenList, int offset) { for (Token t=tokenList; t!=null && t.isPaintable(); t=t.getNextToken()){ if (t.containsPosition(offset)) { return t; } } return null; }
public static String getTextAsHtml(RSyntaxTextArea textArea, int start, int end) { // Create the selection as HTML StringBuilder sb = new StringBuilder("<pre style='") .append("font-family: \"").append(textArea.getFont().getFamily()).append("\", courier;"); if (textArea.getBackground() != null) { // May be null if it is an image sb.append(" background: ") .append(HtmlUtil.getHexString(textArea.getBackground())) .append("'>"); } Token token = textArea.getTokenListFor(start, end); for (Token t = token; t != null; t = t.getNextToken()) { if (t.isPaintable()) { if (t.isSingleChar('\n')) { sb.append("<br>"); } else { sb.append(TokenUtils.tokenToHtml(textArea, t)); } } } sb.append("</pre>"); return sb.toString(); } }
/** * Constructor. * * @param doc The document whose tokens we should iterate over. */ TokenIterator(RSyntaxDocument doc) { this.doc = doc; loadTokenListForCurLine(); int lineCount = getLineCount(); while ((token==null || !token.isPaintable()) && curLine<lineCount-1) { curLine++; loadTokenListForCurLine(); } }
/** * Returns the next non-whitespace, non-comment token in a text area. * * @param t The next token in this line's token list. * @param textArea The text area. * @param line The current line index (the line index of <code>t</code>). * @return The next non-whitespace, non-comment token, or <code>null</code> * if there isn't one. * @see #getPreviousImportantToken(RSyntaxDocument, int) * @see #getPreviousImportantTokenFromOffs(RSyntaxDocument, int) */ public static Token getNextImportantToken(Token t, RSyntaxTextArea textArea, int line) { while (t!=null && t.isPaintable() && t.isCommentOrWhitespace()) { t = t.getNextToken(); } if ((t==null || !t.isPaintable()) && line<textArea.getLineCount()-1) { t = textArea.getTokenListForLine(++line); return getNextImportantToken(t, textArea, line); } return t; }
boolean paintBG = host.getPaintTokenBackgrounds(line, y); while (token!=null && token.isPaintable() && nextX<clipEnd) { nextX = painter.paint(token, g, nextX,y, host, this, clipStart, paintBG);
/** * Returns the set of expected paintable tokens from a document. * * @param doc The document. * @return The list of tokens, in the order in which they appear. */ private static final List<Token> getTokens(RSyntaxDocument doc) { Element root = doc.getDefaultRootElement(); int lineCount = root.getElementCount(); List<Token> list = new ArrayList<Token>(); for (int i=0; i<lineCount; i++) { Token t = doc.getTokenListForLine(i); while (t!=null && t.isPaintable()) { list.add(new TokenImpl(t)); // Copy since Tokens are pooled t = t.getNextToken(); } } return list; }
/** * Returns the last non-whitespace, non-comment token, before the * specified offset. * * @param doc The document. * @param offs The ending offset for the search. * @return The last non-whitespace, non-comment token, or <code>null</code> * if there isn't one. * @see #getPreviousImportantToken(RSyntaxDocument, int) * @see #getNextImportantToken(Token, RSyntaxTextArea, int) */ public static Token getPreviousImportantTokenFromOffs( RSyntaxDocument doc, int offs) { Element root = doc.getDefaultRootElement(); int line = root.getElementIndex(offs); Token t = doc.getTokenListForLine(line); // Check line containing offs Token target = null; while (t!=null && t.isPaintable() && !t.containsPosition(offs)) { if (!t.isCommentOrWhitespace()) { target = t; } t = t.getNextToken(); } // Check previous line(s) if (target==null) { target = RSyntaxUtilities.getPreviousImportantToken(doc, line-1); } return target; }
/** * Highlights all instances of tokens identical to <code>t</code> in the * specified document. * * @param doc The document. * @param t The document whose relevant occurrences should be marked. * @param h The highlighter to add the highlights to. * @param p The painter for the highlights. */ public static final void markOccurrencesOfToken(RSyntaxDocument doc, Token t, RSyntaxTextAreaHighlighter h, SmartHighlightPainter p) { char[] lexeme = t.getLexeme().toCharArray(); int type = t.getType(); int lineCount = doc.getDefaultRootElement().getElementCount(); for (int i=0; i<lineCount; i++) { Token temp = doc.getTokenListForLine(i); while (temp!=null && temp.isPaintable()) { if (temp.is(type, lexeme)) { try { int end = temp.getEndOffset(); h.addMarkedOccurrenceHighlight(temp.getOffset(),end,p); } catch (BadLocationException ble) { ble.printStackTrace(); // Never happens } } temp = temp.getNextToken(); } } }
private byte[] getTextAsRtf(int start, int end) { // Create the RTF selection. RtfGenerator gen = new RtfGenerator(getBackground()); Token tokenList = getTokenListFor(start, end); for (Token t = tokenList; t != null; t = t.getNextToken()) { if (t.isPaintable()) { if (t.length() == 1 && t.charAt(0) == '\n') { gen.appendNewline(); } else { Font font = getFontForTokenType(t.getType()); Color bg = getBackgroundForToken(t); boolean underline = getUnderlineForToken(t); // Small optimization - don't print fg color if this // is a whitespace color. Saves on RTF size. if (t.isWhitespace()) { gen.appendToDocNoFG(t.getLexeme(), font, bg, underline); } else { Color fg = getForegroundForToken(t); gen.appendToDoc(t.getLexeme(), font, fg, bg, underline); } } } } // RTF text is 7-bit ASCII so this should cover us return gen.getRtf().getBytes(StandardCharsets.UTF_8); }
@Test public void testWhitespace() { String code = " foo bar\t\tbas\t \tbaz "; PlainTextTokenMaker tm = new PlainTextTokenMaker(); Segment segment = createSegment(code); Token token = tm.getTokenList(segment, TokenTypes.NULL, 0); Assert.assertTrue(token.isWhitespace()); token = token.getNextToken(); while (token != null && token.isPaintable()) { Assert.assertEquals("Not an identifier: " + token, TokenTypes.IDENTIFIER, token.getType()); token = token.getNextToken(); Assert.assertTrue(token.isWhitespace()); token = token.getNextToken(); } }
@Test public void testIdentifiers() { String code = " foo bar\t\tbas\t \tbaz "; PlainTextTokenMaker tm = new PlainTextTokenMaker(); Segment segment = createSegment(code); Token token = tm.getTokenList(segment, TokenTypes.NULL, 0); Assert.assertTrue(token.isWhitespace()); token = token.getNextToken(); while (token != null && token.isPaintable()) { Assert.assertEquals("Not an identifier: " + token, TokenTypes.IDENTIFIER, token.getType()); token = token.getNextToken(); Assert.assertTrue(token.isWhitespace()); token = token.getNextToken(); } }
@Test public void testJS_EolComments_URL() { String[] eolCommentLiterals = { // Note: The 0-length token at the end of the first example is a // minor bug/performance thing "// Hello world http://www.sas.com", "// Hello world http://www.sas.com extra", }; for (String code : eolCommentLiterals) { Segment segment = createSegment(code); TokenMaker tm = createTokenMaker(); Token token = tm.getTokenList(segment, TokenTypes.NULL, 0); Assert.assertEquals(TokenTypes.COMMENT_EOL, token.getType()); token = token.getNextToken(); Assert.assertTrue(token.isHyperlink()); Assert.assertEquals(TokenTypes.COMMENT_EOL, token.getType()); Assert.assertEquals("http://www.sas.com", token.getLexeme()); token = token.getNextToken(); // Note: The 0-length token at the end of the first example is a // minor bug/performance thing if (token != null && token.isPaintable() && token.length() > 0) { Assert.assertFalse(token.isHyperlink()); Assert.assertTrue(token.is(TokenTypes.COMMENT_EOL, " extra")); } } }
@Test public void testJS_EolComments_URL() { String[] eolCommentLiterals = { // Note: The 0-length token at the end of the first example is a // minor bug/performance thing "// Hello world http://www.sas.com", "// Hello world http://www.sas.com extra", }; for (String code : eolCommentLiterals) { Segment segment = createSegment(code); TokenMaker tm = createTokenMaker(); Token token = tm.getTokenList(segment, HTMLTokenMaker.INTERNAL_IN_JS, 0); Assert.assertEquals("nope - " + token, TokenTypes.COMMENT_EOL, token.getType()); token = token.getNextToken(); Assert.assertTrue(token.isHyperlink()); Assert.assertEquals(TokenTypes.COMMENT_EOL, token.getType()); Assert.assertEquals("http://www.sas.com", token.getLexeme()); token = token.getNextToken(); // Note: The 0-length token at the end of the first example is a // minor bug/performance thing if (token != null && token.isPaintable() && token.length() > 0) { Assert.assertFalse(token.isHyperlink()); Assert.assertTrue(token.is(TokenTypes.COMMENT_EOL, " extra")); } } }
@Test public void testJS_EolComments_URL() { String[] eolCommentLiterals = { // Note: The 0-length token at the end of the first example is a // minor bug/performance thing "// Hello world http://www.sas.com", "// Hello world http://www.sas.com extra", }; for (String code : eolCommentLiterals) { Segment segment = createSegment(code); TokenMaker tm = createTokenMaker(); Token token = tm.getTokenList(segment, JS_PREV_TOKEN_TYPE, 0); Assert.assertEquals(TokenTypes.COMMENT_EOL, token.getType()); token = token.getNextToken(); Assert.assertTrue(token.isHyperlink()); Assert.assertEquals(TokenTypes.COMMENT_EOL, token.getType()); Assert.assertEquals("http://www.sas.com", token.getLexeme()); token = token.getNextToken(); // Note: The 0-length token at the end of the first example is a // minor bug/performance thing if (token != null && token.isPaintable() && token.length() > 0) { Assert.assertFalse(token.isHyperlink()); Assert.assertTrue(token.is(TokenTypes.COMMENT_EOL, " extra")); } } }
@Test public void testTS_EolComments_URL() { String[] eolCommentLiterals = { // Note: The 0-length token at the end of the first example is a // minor bug/performance thing "// Hello world http://www.sas.com", "// Hello world http://www.sas.com extra", }; for (String code : eolCommentLiterals) { Segment segment = createSegment(code); TokenMaker tm = createTokenMaker(); Token token = tm.getTokenList(segment, TS_PREV_TOKEN_TYPE, 0); Assert.assertEquals(TokenTypes.COMMENT_EOL, token.getType()); token = token.getNextToken(); Assert.assertTrue(token.isHyperlink()); Assert.assertEquals(TokenTypes.COMMENT_EOL, token.getType()); Assert.assertEquals("http://www.sas.com", token.getLexeme()); token = token.getNextToken(); // Note: The 0-length token at the end of the first example is a // minor bug/performance thing if (token != null && token.isPaintable() && token.length() > 0) { Assert.assertFalse(token.isHyperlink()); Assert.assertTrue(token.is(TokenTypes.COMMENT_EOL, " extra")); } } }
@Test public void testJS_EolComments_URL() { String[] eolCommentLiterals = { // Note: The 0-length token at the end of the first example is a // minor bug/performance thing "// Hello world http://www.sas.com", "// Hello world http://www.sas.com extra", }; for (String code : eolCommentLiterals) { Segment segment = createSegment(code); TokenMaker tm = createTokenMaker(); Token token = tm.getTokenList(segment, JS_PREV_TOKEN_TYPE, 0); Assert.assertEquals(TokenTypes.COMMENT_EOL, token.getType()); token = token.getNextToken(); Assert.assertTrue(token.isHyperlink()); Assert.assertEquals(TokenTypes.COMMENT_EOL, token.getType()); Assert.assertEquals("http://www.sas.com", token.getLexeme()); token = token.getNextToken(); // Note: The 0-length token at the end of the first example is a // minor bug/performance thing if (token != null && token.isPaintable() && token.length() > 0) { Assert.assertFalse(token.isHyperlink()); Assert.assertTrue(token.is(TokenTypes.COMMENT_EOL, " extra")); } } }