An interpreter for grammar files as defined by TextMate. TextMate grammars use the oniguruma dialect (https://github.com/kkos/oniguruma). Supports loading grammar files only from JSON format. Cross - grammar injections are currently not supported.
TextMateSharp is a port of microsoft/vscode-textmate that brings TextMate grammars to dotnet ecosystem. The implementation is based the Java port eclipse/tm4e.
TextMateSharp uses a wrapper via nuget packges around Oniguruma regex engine. Thanks @aikawayataro for your contribution.
TextMateSharp is used by AvaloniaEdit.
Just execute dotnet build
under the folder TextMateSharp
class Program
{
static void Main(string[] args)
{
try
{
IRegistryOptions options = new LocalRegistryOptions();
Registry.Registry registry = new Registry.Registry(options);
List<string> textLines = new List<string>();
textLines.Add("using static System; /* comment here */");
textLines.Add("namespace Example");
textLines.Add("{");
textLines.Add("}");
IGrammar grammar = registry.LoadGrammar("source.cs");
StackElement ruleStack = null;
foreach (string line in textLines)
{
Console.WriteLine(string.Format("Tokenizing line: {0}", line));
ITokenizeLineResult result = grammar.TokenizeLine(line, ruleStack);
ruleStack = result.RuleStack;
foreach (IToken token in result.GetTokens())
{
int startIndex = (token.StartIndex > line.Length) ?
line.Length : token.StartIndex;
int endIndex = (token.EndIndex > line.Length) ?
line.Length : token.EndIndex;
Console.WriteLine(string.Format(
" - token from {0} to {1} -->{2}<-- with scopes {3}",
startIndex,
endIndex,
line.SubstringAtIndexes(startIndex, endIndex),
string.Join(",", token.Scopes)));
foreach (string scopeName in token.Scopes)
{
Theme theme = registry.GetTheme();
List<ThemeTrieElementRule> themeRules =
theme.Match(scopeName);
foreach (ThemeTrieElementRule themeRule in themeRules)
{
Console.WriteLine(
" - Matched theme rule: "
"[bg: {0}, fg:{1}, fontStyle: {2}]",
theme.GetColor(themeRule.background),
theme.GetColor(themeRule.foreground),
themeRule.fontStyle);
}
}
}
}
}
catch (Exception ex)
{
Console.WriteLine("ERROR: " ex.Message);
}
}
class LocalRegistryOptions : IRegistryOptions
{
public ICollection<string> GetInjections(string scopeName)
{
return null;
}
public IRawGrammar GetGrammar(string scopeName)
{
return null;
}
public IRawTheme GetTheme(string scopeName)
{
return null;
}
public IRawTheme GetDefaultTheme()
{
string themePath = Path.GetFullPath(
@"../../../../test/themes/dark_vs.json");
using (StreamReader reader = new StreamReader(themePath))
{
return ThemeReader.ReadThemeSync(reader);
}
}
}
}
OUTPUT:
Tokenizing line: using static System; /* comment here */
- token from 0 to 5 -->using<-- with scopes source.cs,keyword.other.using.cs
- Matched theme rule: [bg: , fg:, fontStyle: -1]
- Matched theme rule: [bg: , fg:#569CD6, fontStyle: -1]
- token from 5 to 6 --> <-- with scopes source.cs
- Matched theme rule: [bg: , fg:, fontStyle: -1]
- token from 6 to 12 -->static<-- with scopes source.cs,keyword.other.static.cs
- Matched theme rule: [bg: , fg:, fontStyle: -1]
- Matched theme rule: [bg: , fg:#569CD6, fontStyle: -1]
- token from 12 to 13 --> <-- with scopes source.cs
- Matched theme rule: [bg: , fg:, fontStyle: -1]
- token from 13 to 19 -->System<-- with scopes source.cs,storage.type.cs
- Matched theme rule: [bg: , fg:, fontStyle: -1]
- Matched theme rule: [bg: , fg:#569CD6, fontStyle: -1]
- token from 19 to 20 -->;<-- with scopes source.cs,punctuation.terminator.statement.cs
- Matched theme rule: [bg: , fg:, fontStyle: -1]
- Matched theme rule: [bg: , fg:, fontStyle: -1]
- token from 20 to 21 --> <-- with scopes source.cs
- Matched theme rule: [bg: , fg:, fontStyle: -1]
- token from 21 to 23 -->/*<-- with scopes source.cs,comment.block.cs,punctuation.definition.comment.cs
- Matched theme rule: [bg: , fg:, fontStyle: -1]
- Matched theme rule: [bg: , fg:#6A9955, fontStyle: -1]
- Matched theme rule: [bg: , fg:, fontStyle: -1]
- token from 23 to 37 --> comment here <-- with scopes source.cs,comment.block.cs
- Matched theme rule: [bg: , fg:, fontStyle: -1]
- Matched theme rule: [bg: , fg:#6A9955, fontStyle: -1]
- token from 37 to 39 -->*/<-- with scopes source.cs,comment.block.cs,punctuation.definition.comment.cs
- Matched theme rule: [bg: , fg:, fontStyle: -1]
- Matched theme rule: [bg: , fg:#6A9955, fontStyle: -1]
- Matched theme rule: [bg: , fg:, fontStyle: -1]
Tokenizing line: namespace Example
- token from 0 to 9 -->namespace<-- with scopes source.cs,keyword.other.namespace.cs
- Matched theme rule: [bg: , fg:, fontStyle: -1]
- Matched theme rule: [bg: , fg:#569CD6, fontStyle: -1]
- token from 9 to 10 --> <-- with scopes source.cs
- Matched theme rule: [bg: , fg:, fontStyle: -1]
- token from 10 to 17 -->Example<-- with scopes source.cs,entity.name.type.namespace.cs
- Matched theme rule: [bg: , fg:, fontStyle: -1]
- Matched theme rule: [bg: , fg:, fontStyle: -1]
Tokenizing line: {
- token from 0 to 1 -->{<-- with scopes source.cs,punctuation.curlybrace.open.cs
- Matched theme rule: [bg: , fg:, fontStyle: -1]
- Matched theme rule: [bg: , fg:, fontStyle: -1]
Tokenizing line: }
- token from 0 to 1 -->}<-- with scopes source.cs
- Matched theme rule: [bg: , fg:, fontStyle: -1]
There is a demo project in TextMateSharp.Demo folder.
Build and run:
cd src/TestMateSharp.Demo
dotnet build
dotnet run -- ./testdata/samplefiles/sample.cs