/* Function: SetSyntaxHighlightingTypeBetween * Changes the <SyntaxHighlightingType> of all the tokens between the two passed iterators. The * token at the ending iterator will not be changed. */ public void SetSyntaxHighlightingTypeBetween(TokenIterator startingIterator, TokenIterator endingIterator, SyntaxHighlightingType type) { if (startingIterator.Tokenizer != this || endingIterator.Tokenizer != this) { throw new InvalidOperationException(); } SetSyntaxHighlightingTypeBetween(startingIterator.TokenIndex, endingIterator.TokenIndex, type); }
/* Function: SetSyntaxHighlightingTypeAt * Changes the <SyntaxHighlightingType> at the passed token index. */ public void SetSyntaxHighlightingTypeAt(int tokenIndex, SyntaxHighlightingType type) { if (syntaxHighlightingTypes == null) { syntaxHighlightingTypes = new SyntaxHighlightingType[tokenLengths.Count]; } if (tokenIndex < 0 || tokenIndex >= syntaxHighlightingTypes.Length) { throw new ArgumentOutOfRangeException(); } syntaxHighlightingTypes[tokenIndex] = type; }
/* Function: SetSyntaxHighlightingTypeBetween * Changes the <SyntaxHighlightingType> of all the tokens between the two passed indexes. The * token at the ending index will not be changed. */ public void SetSyntaxHighlightingTypeBetween(int startingIndex, int endingIndex, SyntaxHighlightingType type) { if (syntaxHighlightingTypes == null) { syntaxHighlightingTypes = new SyntaxHighlightingType[tokenLengths.Count]; } if (startingIndex < 0 || endingIndex > syntaxHighlightingTypes.Length) { throw new ArgumentOutOfRangeException(); } if (startingIndex > endingIndex) { throw new InvalidOperationException(); } for (int i = startingIndex; i < endingIndex; i++) { syntaxHighlightingTypes[i] = type; } }
/* Function: SetSyntaxHighlightingTypeByCharacters * * Changes the <SyntaxHighlightingType> of the tokens encompassed by the passed number of characters. * * This throws an exception if the number of characters does not evenly fall on a token boundary. It * is assumed that this function will primarily be used after a positive result from <MatchesAcrossTokens()> * or <TokensInCharacters()> which would cause this to not be an issue. */ public void SetSyntaxHighlightingTypeByCharacters(SyntaxHighlightingType newType, int characters) { int tokenCount = TokensInCharacters(characters); if (tokenCount == -1) { throw new InvalidOperationException(); } else if (tokenCount == 1) { SyntaxHighlightingType = newType; } else { TokenIterator iterator = this; while (tokenCount > 0) { iterator.SyntaxHighlightingType = newType; iterator.Next(); tokenCount--; } } }
/* Function: AppendSyntaxHighlightedText * * Appends the text between the two iterators to the passed StringBuilder as HTML with syntax highlighting applied. The * syntax highlighting is based on the set <Tokenization.SyntaxHighlightingTypes>. * * If excludeKeywords is set, it will ignore any <SyntaxHighlightingType.Keyword> sections. This is useful in situations where * you know the text is an identifier but it may be accidentally marked as a keyword by basic language support highlighting. */ public void AppendSyntaxHighlightedText(TokenIterator start, TokenIterator end, StringBuilder output, bool excludeKeywords = false) { TokenIterator iterator = start; while (iterator < end) { if (iterator.FundamentalType == FundamentalType.LineBreak) { output.Append("<br />"); iterator.Next(); } else { TokenIterator startStretch = iterator; TokenIterator endStretch = iterator; endStretch.Next(); SyntaxHighlightingType stretchType = startStretch.SyntaxHighlightingType; for (;;) { if (endStretch == end || endStretch.FundamentalType == FundamentalType.LineBreak) { break; } else if (endStretch.SyntaxHighlightingType == stretchType) { endStretch.Next(); } // We can include unhighlighted whitespace if there's content of the same type beyond it. This prevents // unnecessary span tags. else if (stretchType != SyntaxHighlightingType.Null && endStretch.SyntaxHighlightingType == SyntaxHighlightingType.Null && endStretch.FundamentalType == FundamentalType.Whitespace) { TokenIterator lookahead = endStretch; do { lookahead.Next(); }while (lookahead.SyntaxHighlightingType == SyntaxHighlightingType.Null && lookahead.FundamentalType == FundamentalType.Whitespace && lookahead < end); if (lookahead < end && lookahead.SyntaxHighlightingType == stretchType) { endStretch = lookahead; endStretch.Next(); } else { break; } } else { break; } } switch (stretchType) { case SyntaxHighlightingType.Comment: output.Append("<span class=\"SHComment\">"); break; case SyntaxHighlightingType.Keyword: if (!excludeKeywords) { output.Append("<span class=\"SHKeyword\">"); } break; case SyntaxHighlightingType.Number: output.Append("<span class=\"SHNumber\">"); break; case SyntaxHighlightingType.String: output.Append("<span class=\"SHString\">"); break; case SyntaxHighlightingType.PreprocessingDirective: output.Append("<span class=\"SHPreprocessingDirective\">"); break; case SyntaxHighlightingType.Metadata: output.Append("<span class=\"SHMetadata\">"); break; case SyntaxHighlightingType.Null: break; default: // Add this just in case there's an unaccounted for type in the future. This prevents the spans from // being unbalanced until we handle it. output.Append("<span>"); break; } output.EntityEncodeAndAppend(startStretch.TextBetween(endStretch)); if (stretchType != SyntaxHighlightingType.Null && !(stretchType == SyntaxHighlightingType.Keyword && excludeKeywords)) { output.Append("</span>"); } iterator = endStretch; } } }
/* Function: SetSyntaxHighlightingTypeBetween * Changes the <SyntaxHighlightingType> of all the tokens between the current position and the passed iterator. * The token the ending iterator is on will not be changed. */ public void SetSyntaxHighlightingTypeBetween(TokenIterator end, SyntaxHighlightingType type) { Tokenizer.SetSyntaxHighlightingTypeBetween(this, end, type); }