Coder Social home page Coder Social logo

danipen / textmatesharp Goto Github PK

View Code? Open in Web Editor NEW
88.0 2.0 16.0 5.79 MB

A port of tm4e to bring TextMate grammars to dotnet ecosystem

License: MIT License

C# 87.26% C 12.51% PowerShell 0.23%
csharp dotnet-core textmate-grammar textmate-port cross-platform syntax-highlighting textmate

textmatesharp's Introduction

dotnet-workflow GitHub license Current stable version Downloads Size GitHub language count GitHub top language

TextMateSharp

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 around Oniguruma regex engine. Read below to learn how to build Oniguruma bindings.

TextMateSharp is used by AvaloniaEdit.

Building

Just execute dotnet build under the folder TextMateSharp

Using

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]

Demo

There is a demo project in TextMateSharp.Demo folder.

image

Build and run:

cd src/TestMateSharp.Demo
dotnet build
dotnet run -- ./testdata/samplefiles/sample.cs

Building Oniguruma wrapper

Instructions about how to build Oniguruma bindings can be found in onigwrap/README.md

textmatesharp's People

Contributors

andrew1medvedev avatar danipen avatar hez2010 avatar khitiara avatar markushaslinger avatar numpsy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

textmatesharp's Issues

Feature request - add rule name to ParsedThemeRule and language-configuration classes

Hi,

We use TextMateSharp in our new generic parser.

There are a few features that we'd like to see in the next version of TextMateSharp

Please consider adding the name of the matched token to the ParsedThemeRule, so it's possible to match the token name from the tokens (right now, we can only get colors from the token). Here's a code snippet

            foreach (var themeRule in theme.Match(token.Scopes))
            {
                name = themeRule.name;
            }

We use the name of the matched token for our lexical styles collection.

Please also consider parsing language-configuration.json into C# classes. We use language configuration to get code snippets, code folding, indentation rules, etc.

Another small issue - IStateStack does not uniquely identifies the stack object; please add RuleId (at least) to this interface.
BTW, StateStack.GetHashCode throws exceptions most of the time.

Finally, please consider signing TextMateSharp assemblies with strong names, as we're getting errors when adding the package to our strong-name signed assemblies.

We were able to work around most of these issues (except for the last one), by porting/changing some code from TextMateSharp.
Happy to send you our modifications if needed.

I'm attaching a screenshot for your reference.
image

Kind regards,
Dmitry
[email protected]

How to parse embedded languages?

I am trying to parse the vue file .
It is found that the embedded language inside cannot be parsed normally. What configuration is needed to achieve this goal?

In your sample code I see that the GetFilePath(string scopeName) method is automatically called in IRegistryOptions.
I can see that some embedded languages ​​needed by vue will find its tmlanguage files in this way. Is this related to the problem I mentioned?

Release a nuget package with the latest code changes?

Hi,

Would it be possible to get a new version released that contains #53 ?

Reason for asking: I just tried to build an application of mine that uses AvaloniaEdit / TextMateSharp as .NET 8 using the RC1 release, and it fell over at runtime due to the reflection based serializers being disabled by default - and I think that change should fix it by using the serializer context in more places.

Thanks,

Textmate thread safe

Calling "grammar.TokenizeLine(line,rulestack)" by two threads at the same time will cause thread safety problems. How do you solve them?

Cannot use Ini grammar with turkish culture

When a machine has configured to use Turkish culture, the following exception happens trying to load the Ini grammar:

System.IO.FileNotFoundException : The grammar package 'TextMateSharp.Grammars.Resources.Grammars.ıni.package.json' was not 
found.

Use [Flags] enum for FontStyle

TextMateSharp.Themes.FontStyle is currently a class with int fields representing a bitfield. This sort of bitfield is normally represented in c#/dotnet as an enum with the [Flags] attribute, so FontStyle should be updated to match.

How to correctly parse the text in the specified range?

I try to use this tool to parse Json grammar。
When I parse the complete Json text, I can get the correct result, but I want to parse the grammar of a certain line alone and cannot get the correct result.
I guess it should be StackElement in IGrammar.TokenizeLine(string lineText, StackElement prevState) can be used to contact context analysis.

How to deal with such problems?
Thanks a lot!

Add Luau grammar

Is your feature request related to a problem? Please describe.
Luau is a superset of Lua with types, used by ROBLOX.

Describe the solution you'd like
I'd love to have Luau added to TextMateSharp.Grammars. https://github.com/JohnnyMorganz/Luau.tmLanguage

Describe alternatives you've considered
I have tried lua grammar but it isn't as good as I wanted it to be.

Custom Grammars - Where to Start

I'm using AvaloniaEdit and am using it as a replacement for a WPF RichTextBox I was using in a custom control.

Look at the AE docs it says I need to implement IRegistryOptions but I can't find any examples of what any of the requirements are for doing so. This is all pretty complex stuff and I can't find anything to give me a nudge in the right direction.

I found a message saying to look at the implementation for AvaloniaEdit but the link is now a 404 and looking over all the branches it seems to have vanished.

My requirements are really simple.

I just have a handful of key words to be green and a handful of keywords to be Red but I just cannot figure out what to do with the interface. It all seems geared up for a much more complex use case and I'm left struggling a bit to be honest.

Are there any docs I'm missing or examples?

Switch to System.Text.Json?

System.Text.Json is compatible still with .NET Standard via NuGet package. Also, they've added source generator support for even better performance and reducing of reflection.

Was wondering if there's any plans/thoughts on migrating to the new infrastructure from Newtonsoft.Json?

System.Threading.Thread.Start not supported on webassembly

Unhandled exception rendering component: Operation is not supported on this platform.
System.PlatformNotSupportedException: Operation is not supported on this platform.
   at System.Threading.Thread.Start()
   at TextMateSharp.Model.TMModel.TokenizerThread.Run() in /_/src/TextMateSharp/Model/TMModel.cs:line 63
   at TextMateSharp.Model.TMModel.Start() in /_/src/TextMateSharp/Model/TMModel.cs:line 334
   at TextMateSharp.Model.TMModel.SetGrammar(IGrammar grammar) in /_/src/TextMateSharp/Model/TMModel.cs:line 282
   at AvaloniaEdit.TextMate.TextMateColoringTransformer.SetGrammar(IGrammar grammar)
   at AvaloniaEdit.TextMate.TextMate.Installation.SetGrammar(String scopeName)

Found while trying AvaloniaEdit running on the webassembly.

AvaloniaUI/AvaloniaEdit#201

Include packages for x86/x64 onigwrap.dll, and dynamic binding between them

We use TextMateSharp in our projects; on our tests, projects compiled with AnyCPU platform either do not copy onigwrap.dll to the bin folder (in case of packages.config), or copy x86 version of onigrwrap.dll (in case of sdk-style projects/package references). On the x64 platform, the project cannot load this dll and fails to run.

Please consider providing additional packages like TextMateShar.onigwrap.dll.Native.win-x64/TextMateShar.onigwrap.dll.Native.win-x86,

and implementing run-time binding to the correct version of onigwrap.dll depending on the platform.

Please take a look at ClearScript project which does it this way:
https://www.nuget.org/packages/Microsoft.ClearScript

(different platforms are handled inside V8SplitProxyNative.Generated.cs)

TextMateSharp with Wasm not working?

I saw the package TextmateSharp.Wasm.
Is it possible to run with AvaloniaEdit?
For me AvaloniaEdit alone works in Wasm. As soon as I add some highlighting it breaks, with or without the TextMateSharp.Wasm package.
Maybe I am not doing it right, since I didn't see any demo project for this

Support for XML Plist grammars?

Firstly - thank you for this project!

From what I can see thus far, the grammar needs to be the JSON format only, is that right? Do you have any plans to implement support for the XML Plist grammar similar to what exists in tm4e?

I realize there is a workaround to convert those XML grammars to JSON, so this is a good-to-have feature, albeit lower priority.

Once again, thanks!

Unicode text is not correctly parsed

Wen trying to parse the following line using the csharp grammar:

string s = "chars: 安定させる";

The IToken::StartIndex and IToken::EndIndex for the string token are not correct.

Unexpected behavior in indexes and length.

Hello,

I am confused about the StartIndex, EndIndex and Length of IToken.
I was programming a demo file to parse proto (ProtoBuf) messages.
While parsing a comment line, the string had 26 chars.
The EndIndex and Length value were both resulting in 27 chars.

This is the snippet of the textmate json:

    "comments": {
      "patterns": [
        {
          "name": "comment.block.proto",
          "begin": "/\\*",
          "end": "\\*/"
        },
        {
          "name": "comment.line.double-slash.proto",
          "begin": "//",
          "end": "$\\n?"
        }
      ]
    }

For me, this looks like a bug, however in the example of the readme, there is also code, fixing the length values.

int startIndex = (token.StartIndex > line.Length) ? line.Length : token.StartIndex;
int endIndex = (token.EndIndex > line.Length) ? line.Length : token.EndIndex;

Is this a nasty fix, or is it intended behavior? Why do I need this behavior?
I would like to use the length values to detect possible parsing errors, but without knowing the behavior, this is not possible.

Operations that change non-concurrent collections must have exclusive access

https://forum.plasticscm.com/topic/23292-operations-that-change-non-concurrent-collections-must-have-exclusive-access/#comment-45776

This suddenly popped up when I alt-tabbed back to plastic. I'd changed a source file that I think was visible in the diff view.
I could continue working after forcibly killing plastic. What exactly has been corrupted and should I be concerned?

image

DEBUG ExceptionHandler - Stack trace:    at System.Collections.Generic.Dictionary`2.FindValue(TKey key)
   at TextMateSharp.Themes.Theme.Match(IList`1 scopeNames) in /_/src/TextMateSharp/Themes/Theme.cs:line 42
   at AvaloniaEdit.TextMate.TextMateColoringTransformer.ProcessTokens(Int32 lineNumber, List`1 tokens)
   at AvaloniaEdit.TextMate.TextMateColoringTransformer.TransformLine(DocumentLine line, ITextRunConstructionContext context)

Yaml highlighting issue with nested multi line strings

Describe the bug
Syntax Highlighting appears to be broken after nested multi line strings

one: |-
  this is fine
two:
  two: |-
    this is fine
  shouldnt-be-highlighted:
    test:

one: |
  this is fine
two:
  two: |
    this is fine
  shouldnt-be-highlighted:
    test:
 
one: >
  this is fine
two:
  two: >
    this is fine
  shouldnt-be-highlighted:
    test:
  
one: >-
  this is fine
two:
  two: >-
    this is fine
  shouldnt-be-highlighted:
    test:

To Reproduce
Steps to reproduce the behavior:

  1. Load the Yaml above

Expected behavior
Lines following a nested multi line string should be highlighted correctly

Screenshots
Left is VS Code, right is AvaloniaEdit
image

Desktop (please complete the following information):

  • OS: Windows 11
  • TextMateSharp Version="1.0.56"
  • Avalonia.AvaloniaEdit Version="11.0.6"
  • AvaloniaEdit.TextMate Version="11.0.6"

Support for arm32 and arm64

Hello,

First, thanks for this project!

I am using TextMateSharp through AvaloniaEdit.TextMate project and I would like to have support for arm and arm64.

I do not have an arm machine to test it, but the onigwrap.dll seem to be missing when I compile for win-arm64, although it appears for win-x64.

I would like support for the following .NET target runtimes:

linux-arm64
osx-x64
osx-arm64
win-arm
win-arm64

Does it work on arm machines?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.