This is an automated email from the ASF dual-hosted git repository.

jlahoda pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-netbeans.git


The following commit(s) were added to refs/heads/master by this push:
     new 93192ad  Support for TextMate grammars (from VS Code)
93192ad is described below

commit 93192ad1b8b586d339ebc0afa8e24712ee89e1af
Author: Jan Lahoda <[email protected]>
AuthorDate: Tue Jan 29 22:39:34 2019 +0100

    Support for TextMate grammars (from VS Code)
---
 ide/textmate.lexer/arch.xml                        | 1115 ++++++++++++++++++++
 ide/textmate.lexer/build.xml                       |   23 +
 ide/textmate.lexer/external/binaries-list          |   19 +
 .../external/jcodings-1.0.41-license.txt           |   23 +
 .../external/joni-2.1.11-license.txt               |   27 +
 ...clipse.tm4e.core_0.2.0.201809031154-license.txt |  209 ++++
 ide/textmate.lexer/manifest.mf                     |    7 +
 ide/textmate.lexer/nbproject/project.properties    |   23 +
 ide/textmate.lexer/nbproject/project.xml           |  202 ++++
 .../modules/textmate/lexer/Bundle.properties       |   17 +
 .../modules/textmate/lexer/SyntaxHighlighting.java |  862 +++++++++++++++
 .../modules/textmate/lexer/TextmateLexer.java      |  110 ++
 .../modules/textmate/lexer/TextmateTokenId.java    |  141 +++
 .../textmate/lexer/resources/Bundle.properties     |   17 +
 .../textmate/lexer/resources/fontsColors.xml       |   56 +
 .../modules/textmate/lexer/resources/layer.xml     |   40 +
 .../modules/textmate/lexer/TextmateLexerTest.java  |  171 +++
 nbbuild/cluster.properties                         |    1 +
 nbbuild/licenses/MIT-jruby                         |   21 +
 nbbuild/licenses/names.properties                  |    1 +
 20 files changed, 3085 insertions(+)

diff --git a/ide/textmate.lexer/arch.xml b/ide/textmate.lexer/arch.xml
new file mode 100644
index 0000000..9e275fe
--- /dev/null
+++ b/ide/textmate.lexer/arch.xml
@@ -0,0 +1,1115 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<!DOCTYPE api-answers PUBLIC "-//NetBeans//DTD Arch Answers//EN" 
"../../nbbuild/antsrc/org/netbeans/nbbuild/Arch.dtd" [
+  <!ENTITY api-questions SYSTEM 
"../../nbbuild/antsrc/org/netbeans/nbbuild/Arch-api-questions.xml">
+]>
+
+<api-answers
+  question-version="1.29"
+  author="[email protected]"
+>
+
+  &api-questions;
+
+
+<!--
+        <question id="arch-overall" when="init">
+            Describe the overall architecture. 
+            <hint>
+            What will be API for 
+            <a 
href="http://wiki.netbeans.org/API_Design#Separate_API_for_clients_from_support_API";>
+                clients and what support API</a>? 
+            What parts will be pluggable?
+            How will plug-ins be registered? Please use <code>&lt;api 
type="export"/&gt;</code>
+            to describe your general APIs and specify their
+            <a href="http://wiki.netbeans.org/API_Stability#Private";>
+            stability categories</a>.
+            If possible please provide simple diagrams.
+            </hint>
+        </question>
+-->
+ <answer id="arch-overall">
+  <p>
+   This is a lexer an syntax highlighting for TextMate grammars. The grammars
+   may be regitered using the system layer.
+   <api name="register-grammar" group="layer" type="export" category="devel" />
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="arch-quality" when="init">
+            How will the <a 
href="http://www.netbeans.org/community/guidelines/q-evangelism.html";>quality</a>
+            of your code be tested and 
+            how are future regressions going to be prevented?
+            <hint>
+            What kind of testing do
+            you want to use? How much functionality, in which areas,
+            should be covered by the tests? How you find out that your
+            project was successful?
+            </hint>
+        </question>
+-->
+ <answer id="arch-quality">
+  <p>
+   Unit tests for the lexer.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="arch-time" when="init">
+            What are the time estimates of the work?
+            <hint>
+            Please express your estimates of how long the design, 
implementation,
+            stabilization are likely to last. How many people will be needed to
+            implement this and what is the expected milestone by which the 
work should be 
+            ready?
+            </hint>
+        </question>
+-->
+ <answer id="arch-time">
+  <p>
+   Unclear.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="arch-usecases" when="init">
+            <hint>
+                Content of this answer will be displayed as part of page at
+                http://www.netbeans.org/download/dev/javadoc/usecases.html 
+                You can use tags &lt;usecase name="name&gt; regular html 
description &lt;/usecase&gt;
+                and if you want to use an URL you can prefix if with @TOP@ to 
begin
+                at the root of your javadoc
+            </hint>
+        
+            Describe the main <a 
href="http://wiki.netbeans.org/API_Design#The_Importance_of_Being_Use_Case_Oriented";>
+            use cases</a> of the new API. Who will use it under
+            what circumstances? What kind of code would typically need to be 
written
+            to use the module?
+        </question>
+-->
+ <answer id="arch-usecases">
+  <p>
+      <usecase id="register-grammar" name="Register grammar">
+          To register a new TextMate grammar, add it as a file into the system 
filesystem,
+          under "Editors/&lt;mime-type&gt;/", and make sure it has an 
attribute "textmate-grammar",&lt;/mime-type&gt;,
+          whose value is a string representing the TextMate top-level scope. 
For example:
+          <pre>
+    &lt;folder name="Editors"&gt;
+        &lt;folder name="text"&gt;
+            &lt;folder name="x-kotlin"&gt;
+                &lt;file name="Kotlin.tmLanguage.json" 
url="Kotlin.tmLanguage.json"&gt;
+                    &lt;attr name="textmate-grammar" 
stringvalue="source.kotlin" /&gt;
+                &lt;/file&gt;
+            &lt;/folder&gt;
+        &lt;/folder&gt;
+    &lt;/folder&gt;
+          </pre>
+      </usecase>
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="arch-what" when="init">
+            What is this project good for?
+            <hint>
+            Please provide here a few lines describing the project, 
+            what problem it should solve, provide links to documentation, 
+            specifications, etc.
+            </hint>
+        </question>
+-->
+ <answer id="arch-what">
+  <p>
+   This project to allows to easily add syntax highlighting for languages by
+   using the TextMate grammar files.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="arch-where" when="impl">
+            Where one can find sources for your module?
+            <hint>
+                Please provide link to the Hg web client at
+                http://hg.netbeans.org/
+                or just use tag defaultanswer generate='here'
+            </hint>
+        </question>
+-->
+ <answer id="arch-where">
+  <defaultanswer generate='here' />
+ </answer>
+
+
+
+<!--
+        <question id="compat-deprecation" when="init">
+            How the introduction of your project influences functionality
+            provided by previous version of the product?
+            <hint>
+            If you are planning to deprecate/remove/change any existing APIs,
+            list them here accompanied with the reason explaining why you
+            are doing so.
+            </hint>
+        </question>
+-->
+ <answer id="compat-deprecation">
+  <p>
+   No particular plan to deprecate stuff.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="compat-i18n" when="impl">
+            Is your module correctly internationalized?
+            <hint>
+            Correct internationalization means that it obeys instructions 
+            at <a 
href="http://www.netbeans.org/download/dev/javadoc/org-openide-modules/org/openide/modules/doc-files/i18n-branding.html";>
+            NetBeans I18N pages</a>.
+            </hint>
+        </question>
+-->
+ <answer id="compat-i18n">
+  <p>
+   Yes.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="compat-standards" when="init">
+            Does the module implement or define any standards? Is the 
+            implementation exact or does it deviate somehow?
+        </question>
+-->
+ <answer id="compat-standards">
+  <p>
+   Supports the TextMate grammar standard by use of an external library.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="compat-version" when="impl">
+            Can your module coexist with earlier and future
+            versions of itself? Can you correctly read all old settings? Will 
future
+            versions be able to read your current settings? Can you read
+            or politely ignore settings stored by a future version?
+            
+            <hint>
+            Very helpful for reading settings is to store version number
+            there, so future versions can decide whether how to read/convert
+            the settings and older versions can ignore the new ones.
+            </hint>
+        </question>
+-->
+ <answer id="compat-version">
+  <p>
+   No settings created or read by this module.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="dep-jre" when="final">
+            Which version of JRE do you need (1.2, 1.3, 1.4, etc.)?
+            <hint>
+            It is expected that if your module runs on 1.x that it will run 
+            on 1.x+1 if no, state that please. Also describe here cases where
+            you run different code on different versions of JRE and why.
+            </hint>
+        </question>
+-->
+ <answer id="dep-jre">
+  <p>
+   JRE 8.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="dep-jrejdk" when="final">
+            Do you require the JDK or is the JRE enough?
+        </question>
+-->
+ <answer id="dep-jrejdk">
+  <p>
+   JRE.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="dep-nb" when="init">
+            What other NetBeans projects and modules does this one depend on?
+            <hint>
+            Depending on other NetBeans projects influnces the ability of
+            users of your work to customize their own branded version of
+            NetBeans by enabling and disabling some modules. Too
+            much dependencies restrict this kind of customization. If that
+            is your case, then you may want to split your functionality into
+            pieces of autoload, eager and regular modules which can be
+            enabled independently. Usually the answer to this question
+            is generated from your <code>project.xml</code> file, but
+            if it is not guessed correctly, you can suppress it by
+            specifying &lt;defaultanswer generate="none"/&gt; and
+            write here your own. Please describe such projects as imported 
APIs using
+            the <code>&lt;api name="identification" type="import or export" 
category="stable" url="where is the description" /&gt;</code>.
+            By doing this information gets listed in the summary page of your
+            javadoc.
+            </hint>
+        </question>
+-->
+ <answer id="dep-nb">
+  <defaultanswer generate='here' />
+ </answer>
+
+
+
+<!--
+        <question id="dep-non-nb" when="init">
+            What other projects outside NetBeans does this one depend on?
+            
+            <hint>
+            Depending on 3rd party libraries is always problematic,
+            especially if they are not open source, as that complicates
+            the licensing scheme of NetBeans. Please enumerate your
+            external dependencies here, so it is correctly understood since
+            the begining what are the legal implications of your project.
+            Also please note that
+            some non-NetBeans projects are packaged as NetBeans modules
+            (see <a href="http://libs.netbeans.org/";>libraries</a>) and
+            it is preferred to use this approach when more modules may
+            depend and share such third-party libraries.
+            </hint>
+        </question>
+-->
+ <answer id="dep-non-nb">
+  <p>
+   This project uses the TextMate support for Eclipse.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="dep-platform" when="init">
+            On which platforms does your module run? Does it run in the same
+            way on each?
+            <hint>
+            If you plan any dependency on OS or any usage of native code,
+            please describe why you are doing so and describe how you envision
+            to enforce the portability of your code.
+            Please note that there is a support for <a 
href="http://www.netbeans.org/download/dev/javadoc/org-openide-modules/org/openide/modules/doc-files/api.html#how-os-specific";>OS
 conditionally
+            enabled modules</a> which together with autoload/eager modules
+            can allow you to enable to provide the best OS aware support
+            on certain OSes while providing compatibility bridge on the not
+            supported ones.
+            Also please list the supported
+            OSes/HW platforms and mentioned the lovest version of JDK required
+            for your project to run on. Also state whether JRE is enough or
+            you really need JDK.
+            </hint>
+        </question>
+-->
+ <answer id="dep-platform">
+  <p>
+   Any platform.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="deploy-dependencies" when="final">
+            What do other modules need to do to declare a dependency on this 
one,
+            in addition to or instead of the normal module dependency 
declaration
+            (e.g. tokens to require)?
+            <hint>
+                Provide a sample of the actual lines you would add to a module 
manifest
+                to declare a dependency, for example OpenIDE-Module-Requires: 
some.token.
+                If other modules should not depend on this module, or should 
just use a
+                simple regular module dependency, you can just answer 
"nothing". If you
+                intentionally expose a semistable API to clients using 
implementation
+                dependencies, you should mention that here (but there is no 
need to give
+                an example of usage).
+            </hint>
+        </question>
+-->
+ <answer id="deploy-dependencies">
+  <p>
+   No real dependencies needed currently.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="deploy-jar" when="impl">
+            Do you deploy just module JAR file(s) or other files as well?
+            <hint>
+            Usually a module consist of one JAR file (perhaps with Class-Path
+            extensions) and also a configuration file that enables it. If you
+            have any other files, use
+            &lt;api group="java.io.File" name="yourname" type="export" 
category="friend"&gt;...&lt;/api&gt;
+            to define the location, name and stability of your files (of course
+            changing "yourname" and "friend" to suit your needs).
+            
+            If it uses more than one JAR, describe where they are located, how
+            they refer to each other. 
+            If it consist of module JAR(s) and other files, please describe
+            what is their purpose, why other files are necessary. Please 
+            make sure that installation/uninstallation leaves the system 
+            in state as it was before installation.
+            </hint>
+        </question>
+-->
+ <answer id="deploy-jar">
+  <p>
+   Uses the core jar from TextMate for Eclipse.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="deploy-nbm" when="impl">
+            Can you deploy an NBM via the Update Center?
+            <hint>
+            If not why?
+            </hint>
+        </question>
+-->
+ <answer id="deploy-nbm">
+  <p>
+   Yes.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="deploy-packages" when="init">
+            Are packages of your module made inaccessible by not declaring them
+            public?
+            
+            <hint>
+            By default NetBeans build harness treats all packages are private.
+            If you export some of them - either as public or friend packages,
+            you should have a reason. If the reason is described elsewhere
+            in this document, you can ignore this question.
+            </hint>
+        </question>
+-->
+ <answer id="deploy-packages">
+  <p>
+   Yes.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="deploy-shared" when="final">
+            Do you need to be installed in the shared location only, or in the 
user directory only,
+            or can your module be installed anywhere?
+            <hint>
+            Installation location shall not matter, if it does explain why.
+            Consider also whether <code>InstalledFileLocator</code> can help.
+            </hint>
+        </question>
+-->
+ <answer id="deploy-shared">
+  <p>
+   Anywhere.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="exec-ant-tasks" when="impl">
+            Do you define or register any ant tasks that other can use?
+            
+            <hint>
+            If you provide an ant task that users can use, you need to be very
+            careful about its syntax and behaviour, as it most likely forms an
+                 API for end users and as there is a lot of end users, their 
reaction
+            when such API gets broken can be pretty strong.
+            </hint>
+        </question>
+-->
+ <answer id="exec-ant-tasks">
+  <p>
+   No.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="exec-classloader" when="impl">
+            Does your code create its own class loader(s)?
+            <hint>
+            A bit unusual. Please explain why and what for.
+            </hint>
+        </question>
+-->
+ <answer id="exec-classloader">
+  <p>
+   None known.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="exec-component" when="impl">
+            Is execution of your code influenced by any (string) property
+            of any of your components?
+            
+            <hint>
+            Often <code>JComponent.getClientProperty</code>, 
<code>Action.getValue</code>
+            or <code>PropertyDescriptor.getValue</code>, etc. are used to 
influence
+            a behavior of some code. This of course forms an interface that 
should
+            be documented. Also if one depends on some interface that an object
+            implements (<code>component instanceof Runnable</code>) that forms 
an
+            API as well.
+            </hint>
+        </question>
+-->
+ <answer id="exec-component">
+  <p>
+   None known.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="exec-introspection" when="impl">
+            Does your module use any kind of runtime type information 
(<code>instanceof</code>,
+            work with <code>java.lang.Class</code>, etc.)?
+            <hint>
+            Check for cases when you have an object of type A and you also
+            expect it to (possibly) be of type B and do some special action. 
That
+            should be documented. The same applies on operations in meta-level
+            (Class.isInstance(...), Class.isAssignableFrom(...), etc.).
+            </hint>
+        </question>
+-->
+ <answer id="exec-introspection">
+  <p>
+   None known.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="exec-privateaccess" when="final">
+            Are you aware of any other parts of the system calling some of 
+            your methods by reflection?
+            <hint>
+            If so, describe the "contract" as an API. Likely private or friend 
one, but
+            still API and consider rewrite of it.
+            </hint>
+        </question>
+-->
+ <answer id="exec-privateaccess">
+  <p>
+   None known.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="exec-process" when="impl">
+            Do you execute an external process from your module? How do you 
ensure
+            that the result is the same on different platforms? Do you parse 
output?
+            Do you depend on result code?
+            <hint>
+            If you feed an input, parse the output please declare that as an 
API.
+            </hint>
+        </question>
+-->
+ <answer id="exec-process">
+  <p>
+   None known.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="exec-property" when="impl">
+            Is execution of your code influenced by any environment or
+            Java system (<code>System.getProperty</code>) property?
+            On a similar note, is there something interesting that you
+            pass to <code>java.util.logging.Logger</code>? Or do you observe
+            what others log?
+            <hint>
+            If there is a property that can change the behavior of your 
+            code, somebody will likely use it. You should describe what it 
does 
+            and the <a href="http://wiki.netbeans.org/API_Stability";>stability 
category</a>
+            of this API. You may use
+            <pre>
+                &lt;api type="export" group="property" name="id" 
category="private" url="http://..."&gt;
+                    description of the property, where it is used, what it 
influence, etc.
+                &lt;/api&gt;            
+            </pre>
+            </hint>
+        </question>
+-->
+ <answer id="exec-property">
+  <p>
+   None known.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="exec-reflection" when="impl">
+            Does your code use Java Reflection to execute other code?
+            <hint>
+            This usually indicates a missing or insufficient API in the other
+            part of the system. If the other side is not aware of your 
dependency
+            this contract can be easily broken.
+            </hint>
+        </question>
+-->
+ <answer id="exec-reflection">
+  <p>
+   None known.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="exec-threading" when="init">
+            What threading models, if any, does your module adhere to? How the
+            project behaves with respect to threading?
+            <hint>
+                Is your API threadsafe? Can it be accessed from any threads or
+                just from some dedicated ones? Any special relation to AWT and
+                its Event Dispatch thread? Also
+                if your module calls foreign APIs which have a specific 
threading model,
+                indicate how you comply with the requirements for 
multithreaded access
+                (synchronization, mutexes, etc.) applicable to those APIs.
+                If your module defines any APIs, or has complex internal 
structures
+                that might be used from multiple threads, declare how you 
protect
+                data against concurrent access, race conditions, deadlocks, 
etc.,
+                and whether such rules are enforced by runtime warnings, 
errors, assertions, etc.
+                Examples: a class might be non-thread-safe (like Java 
Collections); might
+                be fully thread-safe (internal locking); might require access 
through a mutex
+                (and may or may not automatically acquire that mutex on behalf 
of a client method);
+                might be able to run only in the event queue; etc.
+                Also describe when any events are fired: synchronously, 
asynchronously, etc.
+                Ideas: <a 
href="http://core.netbeans.org/proposals/threading/index.html#recommendations";>Threading
 Recommendations</a> (in progress)
+            </hint>
+        </question>
+-->
+ <answer id="exec-threading">
+  <p>
+   The threading model is inherited from the lexing infrastructure.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="format-clipboard" when="impl">
+            Which data flavors (if any) does your code read from or insert to
+            the clipboard (by access to clipboard on means calling methods on 
<code>java.awt.datatransfer.Transferable</code>?
+            
+            <hint>
+            Often Node's deal with clipboard by usage of 
<code>Node.clipboardCopy, Node.clipboardCut and Node.pasteTypes</code>.
+            Check your code for overriding these methods.
+            </hint>
+        </question>
+-->
+ <answer id="format-clipboard">
+  <p>
+   None known.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="format-dnd" when="impl">
+            Which protocols (if any) does your code understand during Drag 
&amp; Drop?
+            <hint>
+            Often Node's deal with clipboard by usage of <code>Node.drag, 
Node.getDropType</code>. 
+            Check your code for overriding these methods. Btw. if they are not 
overridden, they
+            by default delegate to <code>Node.clipboardCopy, Node.clipboardCut 
and Node.pasteTypes</code>.
+            </hint>
+        </question>
+-->
+ <answer id="format-dnd">
+  <p>
+   None known.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="format-types" when="impl">
+            Which protocols and file formats (if any) does your module read or 
write on disk,
+            or transmit or receive over the network? Do you generate an ant 
build script?
+            Can it be edited and modified? 
+            
+            <hint>
+            <p>
+            Files can be read and written by other programs, modules and 
users. If they influence
+            your behaviour, make sure you either document the format or claim 
that it is a private
+            api (using the &lt;api&gt; tag). 
+            </p>
+            
+            <p>
+            If you generate an ant build file, this is very likely going to be 
seen by end users and
+            they will be attempted to edit it. You should be ready for that 
and provide here a link
+            to documentation that you have for such purposes and also describe 
how you are going to
+            understand such files during next release, when you (very likely) 
slightly change the 
+            format.
+            </p>
+            </hint>
+        </question>
+-->
+ <answer id="format-types">
+  <p>
+   The TextMate grammar files are read by the TextMate support for Eclipse 
library.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="lookup-lookup" when="init">
+            Does your module use <code>org.openide.util.Lookup</code>
+            or any similar technology to find any components to communicate 
with? Which ones?
+            
+            <hint>
+            NetBeans is build around a generic registry of services called
+            lookup. It is preferable to use it for registration and discovery
+            if possible. See
+            <a 
href="http://www.netbeans.org/download/dev/javadoc/org-openide-util/org/openide/util/lookup/doc-files/index.html";>
+            The Solution to Comunication Between Components
+            </a>. If you do not plan to use lookup and insist usage
+            of other solution, then please describe why it is not working for
+            you.
+            <br/>
+            When filling the final version of your arch document, please
+            describe the interfaces you are searching for, where 
+            are defined, whether you are searching for just one or more of 
them,
+            if the order is important, etc. Also classify the stability of such
+            API contract. Use &lt;api group=&amp;lookup&amp; /&gt; tag, so
+            your information gets listed in the summary page of your javadoc.
+            </hint>
+        </question>
+-->
+ <answer id="lookup-lookup">
+  <p>
+   Grammar files are looked up on the system filesystem.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="lookup-register" when="final">
+            Do you register anything into lookup for other code to find?
+            <hint>
+            Do you register using layer file or using a declarative annotation 
such as <code>@ServiceProvider</code>?
+            Who is supposed to find your component?
+            </hint>
+        </question>
+-->
+ <answer id="lookup-register">
+  <p>
+   Languages are dynamically added into the MimeLookup.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="lookup-remove" when="final">
+            Do you remove entries of other modules from lookup?
+            <hint>
+            Why? Of course, that is possible, but it can be dangerous. Is the 
module
+            your are masking resource from aware of what you are doing?
+            </hint>
+        </question>
+-->
+ <answer id="lookup-remove">
+  <p>
+   No.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="perf-exit" when="final">
+            Does your module run any code on exit?
+        </question>
+-->
+ <answer id="perf-exit">
+  <p>
+   None known.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="perf-huge_dialogs" when="final">
+            Does your module contain any dialogs or wizards with a large 
number of
+            GUI controls such as combo boxes, lists, trees, or text areas?
+        </question>
+-->
+ <answer id="perf-huge_dialogs">
+  <p>
+   None known.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="perf-limit" when="init">
+            Are there any hard-coded or practical limits in the number or size 
of
+            elements your code can handle?
+            <hint>
+                Most of algorithms have increasing memory and speed complexity
+                with respect to size of data they operate on. What is the 
critical
+                part of your project that can be seen as a bottleneck with
+                respect to speed or required memory? What are the practical
+                sizes of data you tested your project with? What is your 
estimate
+                of potential size of data that would cause visible performance
+                problems? Is there some kind of check to detect such situation
+                and prevent "hard" crashes - for example the 
CloneableEditorSupport
+                checks for size of a file to be opened in editor
+                and if it is larger than 1Mb it shows a dialog giving the
+                user the right to decide - e.g. to cancel or commit suicide.
+            </hint>
+        </question>
+-->
+ <answer id="perf-limit">
+  <p>
+   None known.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="perf-mem" when="final">
+            How much memory does your component consume? Estimate
+            with a relation to the number of windows, etc.
+        </question>
+-->
+ <answer id="perf-mem">
+  <p>
+   Not known.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="perf-menus" when="final">
+            Does your module use dynamically updated context menus, or
+            context-sensitive actions with complicated and slow enablement 
logic?
+            <hint>
+                If you do a lot of tricks when adding actions to regular or 
context menus, you can significantly
+                slow down display of the menu, even when the user is not using 
your action. Pay attention to
+                actions you add to the main menu bar, and to context menus of 
foreign nodes or components. If
+                the action is conditionally enabled, or changes its display 
dynamically, you need to check the
+                impact on performance. In some cases it may be more 
appropriate to make a simple action that is
+                always enabled but does more detailed checks in a dialog if it 
is actually run.
+            </hint>
+        </question>
+-->
+ <answer id="perf-menus">
+  <p>
+   None known.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="perf-progress" when="final">
+            Does your module execute any long-running tasks?
+            
+            <hint>Long running tasks should never block 
+            AWT thread as it badly hurts the UI
+            <a 
href="http://performance.netbeans.org/responsiveness/issues.html";>
+            responsiveness</a>.
+            Tasks like connecting over
+            network, computing huge amount of data, compilation
+            be done asynchronously (for example
+            using <code>RequestProcessor</code>), definitively it should 
+            not block AWT thread.
+            </hint>
+        </question>
+-->
+ <answer id="perf-progress">
+  <p>
+   None known.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="perf-scale" when="init">
+            Which external criteria influence the performance of your
+            program (size of file in editor, number of files in menu, 
+            in source directory, etc.) and how well your code scales?
+            <hint>
+            Please include some estimates, there are other more detailed 
+            questions to answer in later phases of implementation. 
+            </hint>
+        </question>
+-->
+ <answer id="perf-scale">
+  <p>
+   The size of the grammar files and the size of the edited file affect the 
performance.
+   Due to the format of the TextMate grammars, long lines may negativelly 
affect performance.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="perf-spi" when="init">
+            How the performance of the plugged in code will be enforced?
+            <hint>
+            If you allow foreign code to be plugged into your own module, how
+            do you enforce that it will behave correctly and quickly and will 
not
+            negatively influence the performance of your own module?
+            </hint>
+        </question>
+-->
+ <answer id="perf-spi">
+  <p>
+   Not enforced.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="perf-startup" when="final">
+            Does your module run any code on startup?
+        </question>
+-->
+ <answer id="perf-startup">
+  <p>
+   None known.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="perf-wakeup" when="final">
+            Does any piece of your code wake up periodically and do something
+            even when the system is otherwise idle (no user interaction)?
+        </question>
+-->
+ <answer id="perf-wakeup">
+  <p>
+   None known.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="resources-file" when="final">
+            Does your module use <code>java.io.File</code> directly?
+            
+            <hint>
+            NetBeans provide a logical wrapper over plain files called 
+            <code>org.openide.filesystems.FileObject</code> that
+            provides uniform access to such resources and is the preferred
+            way that should be used. But of course there can be situations when
+            this is not suitable.
+            </hint>
+        </question>
+-->
+ <answer id="resources-file">
+  <p>
+   The TextMate support for Eclipse is using Files directly.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="resources-layer" when="final">
+            Does your module provide own layer? Does it create any files or
+            folders in it? What it is trying to communicate by that and with 
which 
+            components?
+            
+            <hint>
+            NetBeans allows automatic and declarative installation of 
resources 
+            by module layers. Module register files into appropriate places
+            and other components use that information to perform their task
+            (build menu, toolbar, window layout, list of templates, set of
+            options, etc.). 
+            </hint>
+        </question>
+-->
+ <answer id="resources-layer">
+  <p>
+   Fonts&amp;Colors are registered in the layer.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="resources-mask" when="final">
+            Does your module mask/hide/override any resources provided by 
other modules in
+            their layers?
+            
+            <hint>
+            If you mask a file provided by another module, you probably depend
+            on that and do not want the other module to (for example) change
+            the file's name. That module shall thus make that file available 
as an API
+            of some stability category.
+            </hint>
+        </question>
+-->
+ <answer id="resources-mask">
+  <p>
+   None known.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="resources-preferences" when="final">
+            Does your module uses preferences via Preferences API? Does your 
module use NbPreferences or
+            or regular JDK Preferences ? Does it read, write or both ? 
+            Does it share preferences with other modules ? If so, then why ?
+            <hint>
+                You may use
+                    &lt;api type="export" group="preferences"
+                    name="preference node name" category="private"&gt;
+                    description of individual keys, where it is used, what it
+                    influences, whether the module reads/write it, etc.
+                    &lt;/api&gt;
+                Due to XML ID restrictions, rather than 
/org/netbeans/modules/foo give the "name" as org.netbeans.modules.foo.
+                Note that if you use NbPreferences this name will then be the 
same as the code name base of the module.
+            </hint>
+        </question>
+-->
+ <answer id="resources-preferences">
+  <p>
+   None known.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="resources-read" when="final">
+            Does your module read any resources from layers? For what purpose?
+            
+            <hint>
+            As this is some kind of intermodule dependency, it is a kind of 
API.
+            Please describe it and classify according to 
+            <a href="http://wiki.netbeans.org/API_Design#What_is_an_API.3F";>
+            common stability categories</a>.
+            </hint>
+        </question>
+-->
+ <answer id="resources-read">
+  <p>
+   The grammar files are read from the system filesystem.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="security-grant" when="final">
+            Does your code grant additional rights to some other code?
+            <hint>Avoid using a class loader that adds extra
+            permissions to loaded code unless really necessary.
+            Also note that your API implementation
+            can also expose unneeded permissions to enemy code by
+            calling AccessController.doPrivileged().</hint>
+        </question>
+-->
+ <answer id="security-grant">
+  <p>
+   None known.
+  </p>
+ </answer>
+
+
+
+<!--
+        <question id="security-policy" when="final">
+            Does your functionality require modifications to the standard 
policy file?
+            <hint>Your code might pass control to third-party code not
+            coming from trusted domains. This could be code downloaded over the
+            network or code coming from libraries that are not bundled
+            with NetBeans. Which permissions need to be granted to which 
domains?</hint>
+        </question>
+-->
+ <answer id="security-policy">
+  <p>
+   None known.
+  </p>
+ </answer>
+
+</api-answers>
diff --git a/ide/textmate.lexer/build.xml b/ide/textmate.lexer/build.xml
new file mode 100644
index 0000000..d563ec0
--- /dev/null
+++ b/ide/textmate.lexer/build.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  - Licensed to the Apache Software Foundation (ASF) under one
+  - or more contributor license agreements.  See the NOTICE file
+  - distributed with this work for additional information
+  - regarding copyright ownership.  The ASF licenses this file
+  - to you under the Apache License, Version 2.0 (the
+  - "License"); you may not use this file except in compliance
+  - with the License.  You may obtain a copy of the License at
+  -
+  -   http://www.apache.org/licenses/LICENSE-2.0
+  -
+  - Unless required by applicable law or agreed to in writing,
+  - software distributed under the License is distributed on an
+  - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  - KIND, either express or implied.  See the License for the
+  - specific language governing permissions and limitations
+  - under the License.
+-->
+<project basedir="." default="netbeans" name="ide/textmate.lexer">
+    <description>Builds, tests, and runs the project 
org.netbeans.modules.textmate.lexer</description>
+    <import file="../../nbbuild/templates/projectized.xml"/>
+</project>
diff --git a/ide/textmate.lexer/external/binaries-list 
b/ide/textmate.lexer/external/binaries-list
new file mode 100644
index 0000000..8e77a43
--- /dev/null
+++ b/ide/textmate.lexer/external/binaries-list
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+7CDFC30451010E4D6C65AF5A3A4F357563289245 org.jruby.jcodings:jcodings:1.0.41
+655CC3ABA1BC9DBDD653F28937BEC16F3E9C4CEC org.jruby.joni:joni:2.1.11
+041CFB536DA85BCB9DBDF2E465BC952D40704863 
org.eclipse.tm4e.core_0.2.0.201809031154.jar
diff --git a/ide/textmate.lexer/external/jcodings-1.0.41-license.txt 
b/ide/textmate.lexer/external/jcodings-1.0.41-license.txt
new file mode 100644
index 0000000..3bec304
--- /dev/null
+++ b/ide/textmate.lexer/external/jcodings-1.0.41-license.txt
@@ -0,0 +1,23 @@
+Name: jcodings
+Version: 1.0.41
+License: MIT-nocopyright
+Description: Needed by TextMate support for Eclipse
+Origin: https://github.com/jruby/jcodings
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/ide/textmate.lexer/external/joni-2.1.11-license.txt 
b/ide/textmate.lexer/external/joni-2.1.11-license.txt
new file mode 100644
index 0000000..0ab411d
--- /dev/null
+++ b/ide/textmate.lexer/external/joni-2.1.11-license.txt
@@ -0,0 +1,27 @@
+Name: jcodings
+Version: 2.1.11
+License: MIT-jruby
+Description: Needed by TextMate support for Eclipse
+Origin: https://github.com/jruby/joni
+
+MIT License
+
+Copyright (c) 2017 JRuby Team
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git 
a/ide/textmate.lexer/external/org.eclipse.tm4e.core_0.2.0.201809031154-license.txt
 
b/ide/textmate.lexer/external/org.eclipse.tm4e.core_0.2.0.201809031154-license.txt
new file mode 100644
index 0000000..9274432
--- /dev/null
+++ 
b/ide/textmate.lexer/external/org.eclipse.tm4e.core_0.2.0.201809031154-license.txt
@@ -0,0 +1,209 @@
+Name: TextMate support for Eclipse
+Version: 0.2.0.201809031154
+License: EPL-v10
+Description: Used to interpret TextMate grammars
+Origin: https://github.com/eclipse/tm4e
+
+Eclipse Public License - v 1.0
+
+THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
+LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
+CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+1. DEFINITIONS
+
+"Contribution" means:
+
+a) in the case of the initial Contributor, the initial code and documentation
+   distributed under this Agreement, and
+b) in the case of each subsequent Contributor:
+    i) changes to the Program, and
+   ii) additions to the Program;
+
+   where such changes and/or additions to the Program originate from and are
+   distributed by that particular Contributor. A Contribution 'originates'
+   from a Contributor if it was added to the Program by such Contributor
+   itself or anyone acting on such Contributor's behalf. Contributions do not
+   include additions to the Program which: (i) are separate modules of
+   software distributed in conjunction with the Program under their own
+   license agreement, and (ii) are not derivative works of the Program.
+
+"Contributor" means any person or entity that distributes the Program.
+
+"Licensed Patents" mean patent claims licensable by a Contributor which are
+necessarily infringed by the use or sale of its Contribution alone or when
+combined with the Program.
+
+"Program" means the Contributions distributed in accordance with this
+Agreement.
+
+"Recipient" means anyone who receives the Program under this Agreement,
+including all Contributors.
+
+2. GRANT OF RIGHTS
+  a) Subject to the terms of this Agreement, each Contributor hereby grants
+     Recipient a non-exclusive, worldwide, royalty-free copyright license to
+     reproduce, prepare derivative works of, publicly display, publicly
+     perform, distribute and sublicense the Contribution of such Contributor,
+     if any, and such derivative works, in source code and object code form.
+  b) Subject to the terms of this Agreement, each Contributor hereby grants
+     Recipient a non-exclusive, worldwide, royalty-free patent license under
+     Licensed Patents to make, use, sell, offer to sell, import and otherwise
+     transfer the Contribution of such Contributor, if any, in source code and
+     object code form. This patent license shall apply to the combination of
+     the Contribution and the Program if, at the time the Contribution is
+     added by the Contributor, such addition of the Contribution causes such
+     combination to be covered by the Licensed Patents. The patent license
+     shall not apply to any other combinations which include the Contribution.
+     No hardware per se is licensed hereunder.
+  c) Recipient understands that although each Contributor grants the licenses
+     to its Contributions set forth herein, no assurances are provided by any
+     Contributor that the Program does not infringe the patent or other
+     intellectual property rights of any other entity. Each Contributor
+     disclaims any liability to Recipient for claims brought by any other
+     entity based on infringement of intellectual property rights or
+     otherwise. As a condition to exercising the rights and licenses granted
+     hereunder, each Recipient hereby assumes sole responsibility to secure
+     any other intellectual property rights needed, if any. For example, if a
+     third party patent license is required to allow Recipient to distribute
+     the Program, it is Recipient's responsibility to acquire that license
+     before distributing the Program.
+  d) Each Contributor represents that to its knowledge it has sufficient
+     copyright rights in its Contribution, if any, to grant the copyright
+     license set forth in this Agreement.
+
+3. REQUIREMENTS
+
+A Contributor may choose to distribute the Program in object code form under
+its own license agreement, provided that:
+
+  a) it complies with the terms and conditions of this Agreement; and
+  b) its license agreement:
+      i) effectively disclaims on behalf of all Contributors all warranties
+         and conditions, express and implied, including warranties or
+         conditions of title and non-infringement, and implied warranties or
+         conditions of merchantability and fitness for a particular purpose;
+     ii) effectively excludes on behalf of all Contributors all liability for
+         damages, including direct, indirect, special, incidental and
+         consequential damages, such as lost profits;
+    iii) states that any provisions which differ from this Agreement are
+         offered by that Contributor alone and not by any other party; and
+     iv) states that source code for the Program is available from such
+         Contributor, and informs licensees how to obtain it in a reasonable
+         manner on or through a medium customarily used for software exchange.
+
+When the Program is made available in source code form:
+
+  a) it must be made available under this Agreement; and
+  b) a copy of this Agreement must be included with each copy of the Program.
+     Contributors may not remove or alter any copyright notices contained
+     within the Program.
+
+Each Contributor must identify itself as the originator of its Contribution,
+if
+any, in a manner that reasonably allows subsequent Recipients to identify the
+originator of the Contribution.
+
+4. COMMERCIAL DISTRIBUTION
+
+Commercial distributors of software may accept certain responsibilities with
+respect to end users, business partners and the like. While this license is
+intended to facilitate the commercial use of the Program, the Contributor who
+includes the Program in a commercial product offering should do so in a manner
+which does not create potential liability for other Contributors. Therefore,
+if a Contributor includes the Program in a commercial product offering, such
+Contributor ("Commercial Contributor") hereby agrees to defend and indemnify
+every other Contributor ("Indemnified Contributor") against any losses,
+damages and costs (collectively "Losses") arising from claims, lawsuits and
+other legal actions brought by a third party against the Indemnified
+Contributor to the extent caused by the acts or omissions of such Commercial
+Contributor in connection with its distribution of the Program in a commercial
+product offering. The obligations in this section do not apply to any claims
+or Losses relating to any actual or alleged intellectual property
+infringement. In order to qualify, an Indemnified Contributor must:
+a) promptly notify the Commercial Contributor in writing of such claim, and
+b) allow the Commercial Contributor to control, and cooperate with the
+Commercial Contributor in, the defense and any related settlement
+negotiations. The Indemnified Contributor may participate in any such claim at
+its own expense.
+
+For example, a Contributor might include the Program in a commercial product
+offering, Product X. That Contributor is then a Commercial Contributor. If
+that Commercial Contributor then makes performance claims, or offers
+warranties related to Product X, those performance claims and warranties are
+such Commercial Contributor's responsibility alone. Under this section, the
+Commercial Contributor would have to defend claims against the other
+Contributors related to those performance claims and warranties, and if a
+court requires any other Contributor to pay any damages as a result, the
+Commercial Contributor must pay those damages.
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
+IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each
+Recipient is solely responsible for determining the appropriateness of using
+and distributing the Program and assumes all risks associated with its
+exercise of rights under this Agreement , including but not limited to the
+risks and costs of program errors, compliance with applicable laws, damage to
+or loss of data, programs or equipment, and unavailability or interruption of
+operations.
+
+6. DISCLAIMER OF LIABILITY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
+CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION
+LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
+EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY
+OF SUCH DAMAGES.
+
+7. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under
+applicable law, it shall not affect the validity or enforceability of the
+remainder of the terms of this Agreement, and without further action by the
+parties hereto, such provision shall be reformed to the minimum extent
+necessary to make such provision valid and enforceable.
+
+If Recipient institutes patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Program itself
+(excluding combinations of the Program with other software or hardware)
+infringes such Recipient's patent(s), then such Recipient's rights granted
+under Section 2(b) shall terminate as of the date such litigation is filed.
+
+All Recipient's rights under this Agreement shall terminate if it fails to
+comply with any of the material terms or conditions of this Agreement and does
+not cure such failure in a reasonable period of time after becoming aware of
+such noncompliance. If all Recipient's rights under this Agreement terminate,
+Recipient agrees to cease use and distribution of the Program as soon as
+reasonably practicable. However, Recipient's obligations under this Agreement
+and any licenses granted by Recipient relating to the Program shall continue
+and survive.
+
+Everyone is permitted to copy and distribute copies of this Agreement, but in
+order to avoid inconsistency the Agreement is copyrighted and may only be
+modified in the following manner. The Agreement Steward reserves the right to
+publish new versions (including revisions) of this Agreement from time to
+time. No one other than the Agreement Steward has the right to modify this
+Agreement. The Eclipse Foundation is the initial Agreement Steward. The
+Eclipse Foundation may assign the responsibility to serve as the Agreement
+Steward to a suitable separate entity. Each new version of the Agreement will
+be given a distinguishing version number. The Program (including
+Contributions) may always be distributed subject to the version of the
+Agreement under which it was received. In addition, after a new version of the
+Agreement is published, Contributor may elect to distribute the Program
+(including its Contributions) under the new version. Except as expressly
+stated in Sections 2(a) and 2(b) above, Recipient receives no rights or
+licenses to the intellectual property of any Contributor under this Agreement,
+whether expressly, by implication, estoppel or otherwise. All rights in the
+Program not expressly granted under this Agreement are reserved.
+
+This Agreement is governed by the laws of the State of New York and the
+intellectual property laws of the United States of America. No party to this
+Agreement will bring a legal action under this Agreement more than one year
+after the cause of action arose. Each party waives its rights to a jury trial 
in
+any resulting litigation.
diff --git a/ide/textmate.lexer/manifest.mf b/ide/textmate.lexer/manifest.mf
new file mode 100644
index 0000000..9c0eeb0
--- /dev/null
+++ b/ide/textmate.lexer/manifest.mf
@@ -0,0 +1,7 @@
+Manifest-Version: 1.0
+AutoUpdate-Show-In-Client: false
+OpenIDE-Module: org.netbeans.modules.textmate.lexer/0
+OpenIDE-Module-Layer: org/netbeans/modules/textmate/lexer/resources/layer.xml
+OpenIDE-Module-Localizing-Bundle: 
org/netbeans/modules/textmate/lexer/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
diff --git a/ide/textmate.lexer/nbproject/project.properties 
b/ide/textmate.lexer/nbproject/project.properties
new file mode 100644
index 0000000..3576ad1
--- /dev/null
+++ b/ide/textmate.lexer/nbproject/project.properties
@@ -0,0 +1,23 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+is.autoload=true
+javac.source=1.8
+javac.compilerargs=-Xlint -Xlint:-serial
+javadoc.arch=${basedir}/arch.xml
+release.external/joni-2.1.11.jar=modules/ext/joni-2.1.11.jar
+release.external/jcodings-1.0.41.jar=modules/ext/jcodings-1.0.41.jar
+release.external/org.eclipse.tm4e.core_0.2.0.201809031154.jar=modules/ext/org.eclipse.tm4e.core_0.2.0.201809031154.jar
diff --git a/ide/textmate.lexer/nbproject/project.xml 
b/ide/textmate.lexer/nbproject/project.xml
new file mode 100644
index 0000000..cac8085
--- /dev/null
+++ b/ide/textmate.lexer/nbproject/project.xml
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  - Licensed to the Apache Software Foundation (ASF) under one
+  - or more contributor license agreements.  See the NOTICE file
+  - distributed with this work for additional information
+  - regarding copyright ownership.  The ASF licenses this file
+  - to you under the Apache License, Version 2.0 (the
+  - "License"); you may not use this file except in compliance
+  - with the License.  You may obtain a copy of the License at
+  -
+  -   http://www.apache.org/licenses/LICENSE-2.0
+  -
+  - Unless required by applicable law or agreed to in writing,
+  - software distributed under the License is distributed on an
+  - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  - KIND, either express or implied.  See the License for the
+  - specific language governing permissions and limitations
+  - under the License.
+-->
+<project xmlns="http://www.netbeans.org/ns/project/1";>
+    <type>org.netbeans.modules.apisupport.project</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3";>
+            
<code-name-base>org.netbeans.modules.textmate.lexer</code-name-base>
+            <module-dependencies>
+                <dependency>
+                    <code-name-base>com.google.gson</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>2.7.0</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.api.templates</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.12</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    
<code-name-base>org.netbeans.modules.editor.lib2</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>2.22</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    
<code-name-base>org.netbeans.modules.editor.mimelookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.44</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    
<code-name-base>org.netbeans.modules.editor.settings</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.61</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    
<code-name-base>org.netbeans.modules.editor.util</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.69</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.lexer</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>2</release-version>
+                        <specification-version>1.67.0.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.awt</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.72</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.dialogs</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.46</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.filesystems</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.14</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.loaders</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.71</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.nodes</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.49</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.text</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>6.71</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.11</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.lookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.37</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.ui</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.12</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.windows</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>6.80</specification-version>
+                    </run-dependency>
+                </dependency>
+            </module-dependencies>
+            <test-dependencies>
+                <test-type>
+                    <name>unit</name>
+                    <test-dependency>
+                        
<code-name-base>org.netbeans.libs.junit4</code-name-base>
+                        <compile-dependency/>
+                    </test-dependency>
+                    <test-dependency>
+                        
<code-name-base>org.netbeans.modules.lexer</code-name-base>
+                        <compile-dependency/>
+                        <test/>
+                    </test-dependency>
+                    <test-dependency>
+                        
<code-name-base>org.netbeans.modules.nbjunit</code-name-base>
+                        <recursive/>
+                        <compile-dependency/>
+                    </test-dependency>
+                </test-type>
+            </test-dependencies>
+            <public-packages/>
+            <class-path-extension>
+                
<runtime-relative-path>ext/joni-2.1.11.jar</runtime-relative-path>
+                <binary-origin>external/joni-2.1.11.jar</binary-origin>
+            </class-path-extension>
+            <class-path-extension>
+                
<runtime-relative-path>ext/jcodings-1.0.41.jar</runtime-relative-path>
+                <binary-origin>external/jcodings-1.0.41.jar</binary-origin>
+            </class-path-extension>
+            <class-path-extension>
+                
<runtime-relative-path>ext/org.eclipse.tm4e.core_0.2.0.201809031154.jar</runtime-relative-path>
+                
<binary-origin>external/org.eclipse.tm4e.core_0.2.0.201809031154.jar</binary-origin>
+            </class-path-extension>
+        </data>
+    </configuration>
+</project>
diff --git 
a/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/Bundle.properties 
b/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/Bundle.properties
new file mode 100644
index 0000000..33d008c
--- /dev/null
+++ 
b/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/Bundle.properties
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+OpenIDE-Module-Name=TextMate Lexer
diff --git 
a/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/SyntaxHighlighting.java
 
b/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/SyntaxHighlighting.java
new file mode 100644
index 0000000..6cdfd9a
--- /dev/null
+++ 
b/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/SyntaxHighlighting.java
@@ -0,0 +1,862 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.netbeans.modules.textmate.lexer;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.Document;
+import javax.swing.text.SimpleAttributeSet;
+import org.netbeans.api.editor.mimelookup.MimeLookup;
+import org.netbeans.api.editor.mimelookup.MimePath;
+import org.netbeans.api.editor.mimelookup.MimeRegistration;
+import org.netbeans.api.editor.settings.AttributesUtilities;
+import org.netbeans.api.editor.settings.EditorStyleConstants;
+import org.netbeans.api.editor.settings.FontColorSettings;
+import org.netbeans.api.lexer.Language;
+import org.netbeans.api.lexer.LanguagePath;
+import org.netbeans.api.lexer.Token;
+import org.netbeans.api.lexer.TokenHierarchy;
+import org.netbeans.api.lexer.TokenHierarchyEvent;
+import org.netbeans.api.lexer.TokenHierarchyEventType;
+import org.netbeans.api.lexer.TokenHierarchyListener;
+import org.netbeans.api.lexer.TokenId;
+import org.netbeans.api.lexer.TokenSequence;
+import org.netbeans.lib.editor.util.ListenerList;
+import org.netbeans.lib.editor.util.swing.DocumentUtilities;
+import org.netbeans.spi.editor.highlighting.HighlightsLayer;
+import org.netbeans.spi.editor.highlighting.HighlightsLayerFactory;
+import org.netbeans.spi.editor.highlighting.HighlightsSequence;
+import org.netbeans.spi.editor.highlighting.ZOrder;
+import 
org.netbeans.spi.editor.highlighting.support.AbstractHighlightsContainer;
+import org.openide.util.Lookup;
+import org.openide.util.LookupEvent;
+import org.openide.util.LookupListener;
+import org.openide.util.WeakListeners;
+
+/**Copied from editor.lib2, converts the tokens to AttributeSet in a way that
+ * works for TextmateToken.
+ * The syntax coloring layer.
+ * <br>
+ * It excludes newline chars from any colorings so that if e.g. a whitespace 
highlighting is set
+ * the rest of line after newline is not colored.
+ * 
+ * @author Vita Stejskal
+ * @author Miloslav Metelka
+ */
+public final class SyntaxHighlighting extends AbstractHighlightsContainer
+implements TokenHierarchyListener, ChangeListener {
+    
+    // 
-J-Dorg.netbeans.modules.editor.lib2.highlighting.SyntaxHighlighting.level=FINEST
+    private static final Logger LOG = 
Logger.getLogger(SyntaxHighlighting.class.getName());
+    
+    public static final String LAYER_TYPE_ID = 
"org.netbeans.modules.editor.lib2.highlighting.SyntaxHighlighting"; //NOI18N
+    
+    /**
+     * Static cache for colorings mapping mime-path to coloring info.
+     */
+    private static final HashMap<String, FCSInfo<?>> globalFCSCache = new 
HashMap<String, FCSInfo<?>>();
+
+    /**
+     * Local cache of items from globalFCSCache.
+     */
+    private final HashMap<String, FCSInfo<?>> fcsCache = new HashMap<String, 
FCSInfo<?>>();
+    
+    private final Document document;
+
+    /**
+     * Either null or a mime-type that starts with "test" and it's used
+     * for preview in Tools/Options/Fonts-and-Colors.
+     */
+    private final String mimeTypeForOptions;
+
+    private final TokenHierarchy<? extends Document> hierarchy;
+
+    private long version = 0;
+    
+    /** Creates a new instance of SyntaxHighlighting */
+    public SyntaxHighlighting(Document document) {
+        this.document = document;
+        String mimeType = (String) document.getProperty("mimeType"); //NOI18N
+        if (mimeType != null && mimeType.startsWith("test")) { //NOI18N
+            this.mimeTypeForOptions = mimeType;
+        } else {
+            this.mimeTypeForOptions = null;
+        }
+        
+        // Start listening on changes in global colorings since they may 
affect colorings for target language
+        findFCSInfo("", null);
+
+        hierarchy = TokenHierarchy.get(document);
+        
hierarchy.addTokenHierarchyListener(WeakListeners.create(TokenHierarchyListener.class,
 this, hierarchy));
+    }
+
+    public @Override HighlightsSequence getHighlights(int startOffset, int 
endOffset) {
+        long lVersion = getVersion();
+        if (hierarchy.isActive()) {
+            return new HSImpl(lVersion, hierarchy, startOffset, endOffset);
+        } else {
+            return HighlightsSequence.EMPTY;
+        }
+    }
+
+    // ----------------------------------------------------------------------
+    //  TokenHierarchyListener implementation
+    // ----------------------------------------------------------------------
+
+    public @Override void tokenHierarchyChanged(TokenHierarchyEvent evt) {
+        if (evt.type() == TokenHierarchyEventType.LANGUAGE_PATHS) {
+            // ignore
+            return;
+        }
+        
+        synchronized (this) {
+            version++;
+        }
+
+        if (LOG.isLoggable(Level.FINEST)) {
+            StringBuilder sb = new StringBuilder();
+            TokenSequence<?> ts = hierarchy.tokenSequence();
+            
+            sb.append("\n"); //NOI18N
+            sb.append("Tokens after change: 
<").append(evt.affectedStartOffset()).append(", 
").append(evt.affectedEndOffset()).append(">\n"); //NOI18N
+            dumpSequence(ts, sb);
+            sb.append("--------------------------------------------\n\n"); 
//NOI18N
+            
+            LOG.finest(sb.toString());
+        }
+        
+        fireHighlightsChange(evt.affectedStartOffset(), 
evt.affectedEndOffset());
+//        fireHighlightsChange(0, Integer.MAX_VALUE);
+    }
+
+    // ----------------------------------------------------------------------
+    //  Private implementation
+    // ----------------------------------------------------------------------
+
+    // XXX: This hack is here to make sure that preview panels in Tools-Options
+    // work. Currently there is no way how to force a particular JTextComponent
+    // to use a particular MimeLookup. They all use MimeLookup common for all 
components
+    // and for the mime path of things displayed in that component. The 
preview panels
+    // however need special MimeLookup that loads colorings from a special 
profile
+    // (i.e. not the currently active coloring profile, which is used normally 
by
+    // all the other components).
+    //
+    // The hack is that Tools-Options modifies mime type of the document loaded
+    // in the preview panel and prepend 'textXXXX_' at the beginning. The 
normal
+    // MimeLookup for this mime type and any mime path derived from this mime 
type
+    // is empty. The editor/settings/storage however provides a special 
handling
+    // for these 'test' mime paths and bridge them to the MimeLookup that you 
would
+    // normally get for the mime path without the 'testXXXX_' at the 
beginning, plus
+    // they supply special colorings from the profile called 'testXXXX'. This 
way
+    // the preview panels can have different colorings from the rest of the 
IDE.
+    //
+    // This is obviously very fragile and not fully transparent for clients as
+    // you can see here. We need a better solution for that. Generally it 
should
+    // be posible to ask somewhere for a component-specific MimeLookup. This 
would
+    // normally be a standard MimeLookup as you know it, but in special cases 
it
+    // could be modified by the client code that created the component - e.g. 
Tools-Options
+    // panel.
+    private String languagePathToMimePathOptions(LanguagePath languagePath) {
+        if (languagePath.size() == 1) {
+            return mimeTypeForOptions;
+        } else if (languagePath.size() > 1) {
+            return mimeTypeForOptions + "/" + 
languagePath.subPath(1).mimePath(); //NOI18N
+        } else {
+            throw new IllegalStateException("LanguagePath should not be 
empty."); //NOI18N
+        }
+    }
+
+    @Override
+    public void stateChanged(ChangeEvent e) {
+        fireHighlightsChange(0, Integer.MAX_VALUE); // Recompute highlights 
for whole document
+    }
+
+    synchronized long getVersion() {
+        return version;
+    }
+    
+    private <T extends TokenId> FCSInfo<T> findFCSInfo(String mimePath, 
Language<T> language) {
+        @SuppressWarnings("unchecked")
+        FCSInfo<T> fcsInfo = (FCSInfo<T>) fcsCache.get(mimePath); // Search 
local cache
+        if (fcsInfo == null) { // Search in global cache
+            synchronized (globalFCSCache) {
+                @SuppressWarnings("unchecked")
+                FCSInfo<T> fcsI = (FCSInfo<T>) globalFCSCache.get(mimePath);
+                fcsInfo = fcsI;
+                if (fcsInfo == null) {
+                    fcsInfo = new FCSInfo<T>(mimePath, language);
+                    if (mimeTypeForOptions == null) { // Only cache non-test 
ones globally
+                        globalFCSCache.put(mimePath, fcsInfo);
+                    }
+                }
+            }
+            fcsInfo.addChangeListener(WeakListeners.change(this, fcsInfo));
+            fcsCache.put(mimePath, fcsInfo);
+        }
+        return fcsInfo;
+    }
+
+    private static void dumpSequence(TokenSequence<?> seq, StringBuilder sb) {
+        if (seq == null) {
+            sb.append("Inactive TokenHierarchy"); //NOI18N
+        } else {
+            for(seq.moveStart(); seq.moveNext(); ) {
+                TokenSequence<?> emSeq = seq.embedded();
+                if (emSeq != null) {
+                    dumpSequence(emSeq, sb);
+                } else {
+                    Token<?> token = seq.token();
+                    sb.append("<"); //NOI18N
+                    sb.append(String.format("%3s", seq.offset())).append(", 
"); //NOI18N
+                    sb.append(String.format("%3s", seq.offset() + 
token.length())).append(", "); //NOI18N
+                    sb.append(String.format("%+3d", token.length())).append("> 
: "); //NOI18N
+                    sb.append(tokenId(token.id(), true)).append(" : '"); 
//NOI18N
+                    sb.append(tokenText(token));
+                    sb.append("'\n"); //NOI18N
+                }
+            }
+        }
+    }
+    
+    private static String tokenId(TokenId tokenId, boolean format) {
+        if (format) {
+            return String.format("%20s.%-15s", 
tokenId.getClass().getSimpleName(), tokenId.name()); //NOI18N
+        } else {
+            return tokenId.getClass().getSimpleName() + "." + tokenId.name(); 
//NOI18N
+        }
+    }
+    
+    private static String tokenText(Token<?> token) {
+        CharSequence text = token.text();
+        StringBuilder sb = new StringBuilder(text.length());
+        
+        for(int i = 0; i < text.length(); i++) {
+            char ch = text.charAt(i);
+            if (Character.isISOControl(ch)) {
+                switch (ch) {
+                case '\n' : sb.append("\\n"); break; //NOI18N
+                case '\t' : sb.append("\\t"); break; //NOI18N
+                case '\r' : sb.append("\\r"); break; //NOI18N
+                default : sb.append("\\").append(Integer.toOctalString(ch)); 
break; //NOI18N
+                }
+            } else {
+                sb.append(ch);
+            }
+        }
+        
+        return sb.toString();
+    }
+
+    private static String attributeSet(AttributeSet as) {
+        if (as == null) {
+            return "AttributeSet is null"; //NOI18N
+        }
+        
+        StringBuilder sb = new StringBuilder();
+        
+        for(Enumeration<? extends Object> keys = as.getAttributeNames(); 
keys.hasMoreElements(); ) {
+            Object key = keys.nextElement();
+            Object value = as.getAttribute(key);
+
+            if (key == null) {
+                sb.append("null"); //NOI18N
+            } else {
+                sb.append("'").append(key.toString()).append("'"); //NOI18N
+            }
+
+            sb.append(" = "); //NOI18N
+
+            if (value == null) {
+                sb.append("null"); //NOI18N
+            } else {
+                sb.append("'").append(value.toString()).append("'"); //NOI18N
+            }
+
+            if (keys.hasMoreElements()) {
+                sb.append(", "); //NOI18N
+            }
+        }
+        
+        return sb.toString();
+    }
+    
+    /**
+     * Checks if the token should be treated as a block. Returns true if the 
token
+     * does NOT representa a block. Blocks are highlighted as a whole, 
including
+     * free space after the trailing whitespaces on the line.
+     * 
+     * @param t token to check
+     * @return true, if token is normal text; false if block.
+     */
+    private static boolean noBlock(Token t) {
+        return t.getProperty("highlight.block") != Boolean.TRUE; // NOI18N
+    }
+    
+    private final class HSImpl implements HighlightsSequence {
+        
+        private static final int S_INIT = 0;
+        private static final int S_TOKEN = 1; // Attempt to branch current 
token
+        private static final int S_NEXT_TOKEN = 2; // Fetch next token
+        private static final int S_EMBEDDED_HEAD = 3; // On head of an 
embedding (in front of its first token)
+        private static final int S_EMBEDDED_TAIL = 4; // Just above last token 
of the embedding
+        private static final int S_DONE = 5;
+
+        private final long version;
+        private final TokenHierarchy<? extends Document> scanner;
+        private final int startOffset;
+        private final int endOffset;
+        private final CharSequence docText;
+        private int newlineOffset;
+        private int partsEndOffset; // In case '\n' is in the middle of token 
this is end offset of the whole token
+
+        // Last found highlight's startOffset, endOffset and attributes
+        private int hiStartOffset;
+        private int hiEndOffset;
+        private AttributeSet hiAttrs;
+        
+        private List<TSInfo<?>> sequences;
+        private int state = S_INIT;
+        private LogHelper logHelper;
+        
+        public HSImpl(long version, TokenHierarchy<? extends Document> 
scanner, int startOffset, int endOffset) {
+            this.version = version;
+            this.scanner = scanner;
+            startOffset = Math.max(startOffset, 0); // Tests may request 
Integer.MIN_VALUE for startOffset
+            this.startOffset = startOffset;
+            this.sequences = new ArrayList<TSInfo<?>>(4);
+            this.hiStartOffset = startOffset;
+            this.hiEndOffset = startOffset;
+            Document doc = scanner.inputSource();
+            this.docText = DocumentUtilities.getText(doc);
+            endOffset = Math.min(endOffset, docText.length());
+            this.endOffset = endOffset;
+            newlineOffset = -1;
+            updateNewlineOffset(startOffset);
+            @SuppressWarnings("unchecked")
+            TokenSequence<TokenId> seq = (TokenSequence<TokenId>) 
scanner.tokenSequence();
+            if (seq != null) {
+                seq.move(startOffset);
+                TSInfo<TokenId> tsInfo = new TSInfo<TokenId>(seq);
+                sequences.add(tsInfo);
+                state = S_NEXT_TOKEN;
+            } else {
+                state = S_DONE;
+            }
+            if (LOG.isLoggable(Level.FINE)) {
+                logHelper = new LogHelper();
+                logHelper.startTime = System.currentTimeMillis();
+                LOG.fine("SyntaxHighlighting.HSImpl <" + startOffset + "," + 
endOffset + ">\n"); // NOI18N
+                if (LOG.isLoggable(Level.FINEST)) {
+                    LOG.log(Level.FINEST, "Highlighting caller", new 
Exception()); // NOI18N
+                }
+            }
+        }
+        
+        public @Override boolean moveNext() {
+            if (state == S_DONE) {
+                return false;
+            }
+
+            if (SyntaxHighlighting.this.getVersion() != this.version) {
+                finish();
+                if (LOG.isLoggable(Level.FINE)) {
+                    LOG.fine("SyntaxHighlighting: Version changed => HSImpl 
finished at offset=" + hiEndOffset); // NOI18N
+                }
+                return false;
+            }
+
+            // Check whether processing multiple parts into that token was 
split due to presence of '\n' char(s)
+            if (partsEndOffset != 0) { // Fetch next part
+                while (hiEndOffset == newlineOffset) { // Newline at highlight 
start
+                    hiEndOffset++; // Skip newline
+                    if (updateNewlineOffset(hiEndOffset)) { // Reached 
endOffset
+                        finish();
+                        return false;
+                    }
+                    if (hiEndOffset >= partsEndOffset) { // Reached end of 
parts only by newlines
+                        finishParts();
+                        return moveTheSequence();
+                    }
+                }
+                hiStartOffset = hiEndOffset;
+                if (newlineOffset < partsEndOffset) {
+                    hiEndOffset = newlineOffset;
+                } else {
+                    hiEndOffset = partsEndOffset;
+                    finishParts();
+                }
+                if (LOG.isLoggable(Level.FINE)) {
+                    LOG.fine("  SH.moveNext(): part-Highlight: <" + 
hiStartOffset + "," + // NOI18N
+                            hiEndOffset + "> attrs=" + hiAttrs + " " + 
stateToString() + // NOI18N
+                            ", pEOffset=" + partsEndOffset + ", seq#=" + 
sequences.size() + "\n"); // NOI18N
+                }
+                return true;
+            } else if (hiEndOffset >= newlineOffset) {
+                updateNewlineOffset(hiEndOffset);
+            }
+
+            return moveTheSequence();
+        }
+
+        public @Override int getStartOffset() {
+            return hiStartOffset;
+        }
+
+        public @Override int getEndOffset() {
+            return hiEndOffset;
+        }
+
+        public @Override AttributeSet getAttributes() {
+            return hiAttrs;
+        }
+        
+        private boolean moveTheSequence() {
+            boolean done = false;
+            boolean log = LOG.isLoggable(Level.FINE);
+            do {
+                TSInfo<?> tsInfo = sequences.get(sequences.size() - 1);
+                switch (state) {
+                    case S_TOKEN:
+                        TokenSequence<?> embeddedSeq = tsInfo.ts.embedded();
+                        if (embeddedSeq != null) {
+                            @SuppressWarnings("unchecked")
+                            TSInfo<TokenId> embeddedTSInfo = new 
TSInfo<TokenId>((TokenSequence<TokenId>) embeddedSeq);
+                            sequences.add(embeddedTSInfo);
+                            if (embeddedTSInfo.moveNextToken(startOffset, 
endOffset)) { // Embedded token sequence has at least one token
+                                int headLen = embeddedTSInfo.tokenOffset - 
hiEndOffset;
+                                if (headLen > 0) {
+                                    state = S_EMBEDDED_HEAD;
+                                    done = 
assignHighlightOrPart(embeddedTSInfo.tokenOffset, tsInfo.tokenAttrs, 
noBlock(tsInfo.ts.token()));
+                                    if (log) {
+                                        LOG.fine(" S_TOKEN -> S_EMBEDDED_HEAD, 
token<" + tsInfo.tokenOffset + // NOI18N
+                                                "," + tsInfo.tokenEndOffset + 
"> headLen=" + headLen + "\n"); // NOI18N
+                                    }
+                                } // else: No head -> attempt further nested 
embedding on current emb.token
+                            } else { // No tokens in embedded sequence
+                                state = S_EMBEDDED_TAIL;
+                                done = assignHighlightOrPart(tsInfo);
+                                if (log) {
+                                    LOG.fine(" S_TOKEN -> S_EMBEDDED_TAIL\n");
+                                }
+                            }
+                        } else { // embeddedSeq == null
+                            state = S_NEXT_TOKEN;
+                            done = assignHighlightOrPart(tsInfo);
+                        }
+                        break;
+
+                    case S_NEXT_TOKEN:
+                        if (tsInfo.moveNextToken(startOffset, endOffset)) {
+                            state = S_TOKEN;
+                            if (log) {
+                                logHelper.tokenCount++;
+                            }
+                        } else { // No more tokens
+                            if (sequences.size() > 1) {
+                                TSInfo<?> outerTSInfo = 
sequences.get(sequences.size() - 2);
+                                state = S_EMBEDDED_TAIL;
+                                if (tsInfo.tokenEndOffset < 
outerTSInfo.tokenEndOffset) {
+                                    done = assignHighlightOrPart(outerTSInfo);
+                                }
+                            } else { // Outer sequence => stop processing
+                                sequences.clear();
+                                finish();
+                                if (log) {
+                                    LOG.fine("SyntaxHighlighting: " + 
scanner.inputSource() + //NOI18N
+                                            ":\n-> returned " + 
logHelper.tokenCount + " token highlights for <" + //NOI18N
+                                            startOffset + "," + endOffset + 
//NOI18N
+                                            "> in " + //NOI18N
+                                            (System.currentTimeMillis() - 
logHelper.startTime) + " ms.\n"); //NOI18N
+                                    LOG.finer(tsInfo.ts.toString());
+                                    LOG.fine("\n");
+                                }
+                                return false;
+                            }
+                        }
+                        break;
+
+                    case S_EMBEDDED_HEAD:
+                        // Current token contains embedded language and we 
have processed its head
+                        // First token is fetched already so just use it.
+                        state = S_TOKEN;
+                        break;
+
+                    case S_EMBEDDED_TAIL:
+                        // The current token contains embedded language and we 
have processed it's tail
+                        state = S_NEXT_TOKEN;
+                        sequences.remove(sequences.size() - 1);
+                        if (log) {
+                            LOG.fine("S_EMBEDDED_TAIL -> S_NEXT_TOKEN; 
sequences.size()=" + sequences.size() + "\n"); // NOI18N
+                        }
+                        break;
+
+                    default: // Includes S_INIT and S_DONE
+                        throw new IllegalStateException("Invalid state: " + 
state); //NOI18N
+                }
+            } while (!done);
+
+            if (log) {
+                LOG.fine("SH.moveTheSequence(): Highlight: <" + hiStartOffset 
+ "," + hiEndOffset + // NOI18N
+                        "> attrs=" + hiAttrs + " " + stateToString() + ", 
seq#=" + sequences.size() + "\n"); // NOI18N
+            }
+            return true; // Highlight assigned
+        }
+        
+        private boolean assignHighlightOrPart(TSInfo<?> tsInfo) {
+            return assignHighlightOrPart(tsInfo.tokenEndOffset, 
tsInfo.tokenAttrs, noBlock(tsInfo.ts.token()));
+        }
+
+        /**
+         * Assign full token or its initial part as a next highlight.
+         *
+         * @param tokenEndOffset
+         * @param attrs
+         * @return true if highlight was assigned successfully or false if it 
could not be assigned
+         *  due to token consisting of all newlines.
+         */
+        private boolean assignHighlightOrPart(int tokenEndOffset, AttributeSet 
attrs, boolean noBlock) {
+            if (noBlock) {
+                while (hiEndOffset == newlineOffset) { // Newline at highlight 
start
+                    hiEndOffset++; // Skip newline
+                    if (updateNewlineOffset(hiEndOffset) || hiEndOffset >= 
tokenEndOffset) { // Reached endOffset
+                        hiStartOffset = hiEndOffset;
+                        return false;
+                    }
+                }
+            } 
+            hiStartOffset = hiEndOffset;
+            if (hiEndOffset >= tokenEndOffset) {
+                hiStartOffset = hiEndOffset;
+                return false;
+            }
+            if (noBlock && newlineOffset >= hiStartOffset && newlineOffset < 
tokenEndOffset) {
+                hiEndOffset = newlineOffset;
+                partsEndOffset = tokenEndOffset;
+            } else {
+                hiEndOffset = tokenEndOffset;
+            }
+            hiAttrs = attrs;
+            return true;
+        }
+        
+        /**
+         * Update newlineOffset.
+         *
+         * @param offset scan start offset. If '\n' right at offset then
+         *  newlineOffset will be == offset.
+         */
+        private boolean updateNewlineOffset(int offset) {
+            while (offset < endOffset) {
+                if (docText.charAt(offset) == '\n') {
+                    newlineOffset = offset;
+                    return false;
+                }
+                offset++;
+            }
+            newlineOffset = endOffset;
+            return true;
+        }
+        
+        private void finishParts() {
+            partsEndOffset = 0;
+        }
+
+        private void finish() {
+            state = S_DONE;
+            hiStartOffset = endOffset;
+            hiEndOffset = endOffset;
+            hiAttrs = null;
+        }
+
+        private String stateToString() {
+            switch (state) {
+                case S_INIT:
+                    return "S_INIT"; // NOI18N
+                case S_TOKEN:
+                    return "S_TOKEN"; // NOI18N
+                case S_NEXT_TOKEN:
+                    return "S_NEXT_TOKEN"; // NOI18N
+                case S_EMBEDDED_HEAD:
+                    return "S_EMBEDDED_HEAD"; // NOI18N
+                case S_EMBEDDED_TAIL:
+                    return "S_EMBEDDED_TAIL"; // NOI18N
+                case S_DONE:
+                    return "S_DONE"; // NOI18N
+                default:
+                    throw new IllegalStateException("Unknown state=" + state); 
// NOI18N
+            }
+        }
+
+    } // End of HSImpl class
+
+    private static final class LogHelper {
+
+        int tokenCount;
+        long startTime;
+    }
+
+    //for tests:
+    static AttributeSet TEST_FALLBACK_COLORING;
+
+    private static final class FCSInfo<T extends TokenId> implements 
LookupListener {
+        
+        private volatile ChangeEvent changeEvent;
+        
+        private final Language<T> innerLanguage;
+        
+        private final String mimePath; // Can start with mimeTypeForOptions
+    
+        private final ListenerList<ChangeListener> listeners;
+
+        private final Lookup.Result<FontColorSettings> result;
+        
+        private AttributeSet[] tokenId2attrs;
+        
+        FontColorSettings fcs;
+        
+        /**
+         * @param innerLanguage
+         * @param mimePath note it may start with mimeTypeForOptions
+         */
+        public FCSInfo(String mimePath, Language<T> innerLanguage) {
+            this.innerLanguage = innerLanguage;
+            this.mimePath = mimePath;
+            this.listeners = new ListenerList<ChangeListener>();
+            Lookup lookup = MimeLookup.getLookup("text/textmate");
+            result = lookup.lookupResult(FontColorSettings.class);
+            // Do not listen on font color settings changes in tests
+            // since "random" lookup events translate into highlight change 
events
+            // that are monitored by tests and so the tests may then fail
+            if (TEST_FALLBACK_COLORING == null) {
+                
result.addLookupListener(WeakListeners.create(LookupListener.class, this, 
result));
+            }
+            updateFCS();
+        }
+        
+        private static final Map<String, AttributeSet> scopeName2Coloring = 
new HashMap<>();
+
+        /**
+         * @param token non-null token.
+         * @return attributes for tokenId or null if none found.
+         */
+        synchronized AttributeSet findAttrs(Token token) {
+            if (token.id() != TextmateTokenId.TEXTMATE) {
+                return null;
+            }
+            
+            List<AttributeSet> attrs = new ArrayList<>();
+            List<String> categories = (List<String>) 
token.getProperty("categories");
+            
+            for (String category : categories) {
+                attrs.add(scopeName2Coloring.computeIfAbsent(category, c -> {
+                    String cat = category;
+
+                    while (true) {
+                        AttributeSet currentAttrs = 
fcs.getTokenFontColors(cat);
+
+                        if (currentAttrs != null) {
+                            return currentAttrs;
+                        }
+
+                        int dot = cat.lastIndexOf('.');
+
+                        if (dot == (-1))
+                            break;
+
+                        cat = cat.substring(0, dot);
+                    }
+
+                    return SimpleAttributeSet.EMPTY;
+                }));
+            }
+
+            return AttributesUtilities.createComposite(attrs.toArray(new 
AttributeSet[0]));
+        }
+
+        public void addChangeListener(ChangeListener l) {
+            listeners.add(l);
+        }
+        
+        public void removeChangeListener(ChangeListener l) {
+            listeners.remove(l);
+        }
+        
+        private void updateFCS() {
+            FontColorSettings newFCS = result.allInstances().iterator().next();
+            if (newFCS == null && LOG.isLoggable(Level.WARNING)) {
+                // Should not normally happen; see #106337
+                LOG.warning("No FontColorSettings for '" + mimePath + "' mime 
path."); //NOI18N
+            }
+            synchronized (this) {
+                fcs = newFCS;
+                if (innerLanguage != null) {
+                    tokenId2attrs = new 
AttributeSet[innerLanguage.maxOrdinal() + 1];
+                }
+            }
+        }
+        
+        private ChangeEvent createChangeEvent() {
+            if (changeEvent == null) {
+                changeEvent = new ChangeEvent(this);
+            }
+            return changeEvent;
+        }
+
+        @Override
+        public void resultChanged(LookupEvent ev) {
+            updateFCS();
+            ChangeEvent e = createChangeEvent();
+            for (ChangeListener l : listeners.getListeners()) {
+                l.stateChanged(e);
+            }
+        }
+   
+    }
+    
+    private final class TSInfo<T extends TokenId> {
+        
+        final TokenSequence<T> ts;
+        
+        final FCSInfo<T> fcsInfo;
+        
+        int tokenOffset;
+        
+        int tokenEndOffset;
+        
+        AttributeSet tokenAttrs;
+        
+        /**
+         * @param ts
+         */
+        public TSInfo(TokenSequence<T> ts) {
+            this.ts = ts;
+            LanguagePath languagePath = ts.languagePath();
+            @SuppressWarnings("unchecked")
+            Language<T> innerLanguage = 
(Language<T>)languagePath.innerLanguage();
+            String mimePathExt;
+            if (mimeTypeForOptions != null) {
+                // First mime-type in mimePath starts with "test"
+                mimePathExt = languagePathToMimePathOptions(languagePath);
+            } else {
+                mimePathExt = languagePath.mimePath();
+            }
+
+            fcsInfo = findFCSInfo(mimePathExt, innerLanguage);
+        }
+        
+        boolean moveNextToken(int limitStartOffset, int limitEndOffset) {
+            if (ts.moveNext()) {
+                Token<T> token = ts.token();
+                int nextTokenOffset = ts.offset();
+                if (nextTokenOffset < 0) {
+                    if (LOG.isLoggable(Level.FINE)) {
+                        LOG.fine("Invalid token offset=" + nextTokenOffset + " 
< 0. TokenSequence:\n" + ts); // NOI18N
+                    }
+                    return false;
+                }
+                int nextTokenLength = token.length();
+                if (nextTokenOffset < 0) {
+                    if (LOG.isLoggable(Level.FINE)) {
+                        LOG.fine("Invalid token length=" + nextTokenLength + " 
< 0. TokenSequence:\n" + ts); // NOI18N
+                    }
+                    return false;
+                }
+                if (nextTokenOffset >= tokenEndOffset || nextTokenLength >= 0) 
{
+                    tokenOffset = nextTokenOffset;
+                    tokenEndOffset = tokenOffset + nextTokenLength;
+                } else {
+                    // Become robust against an invalid lexer's output by 
returning "no more tokens" here
+                    return false;
+                }
+                if (tokenEndOffset <= limitStartOffset) {
+                    // Must move the sequence forward by bin-search
+                    ts.move(limitStartOffset);
+                    if (!ts.moveNext()) { // limitStartOffset above tokens (in 
tail section)
+                        return false;
+                    }
+                    token = ts.token();
+                    tokenOffset = ts.offset();
+                    tokenEndOffset = tokenOffset + token.length();
+                }
+                tokenOffset = Math.max(tokenOffset, limitStartOffset);
+                T id = token.id();
+                if (tokenEndOffset > limitEndOffset) {
+                    if (tokenOffset >= limitEndOffset) {
+                        return false;
+                    } else {
+                        tokenEndOffset = limitEndOffset;
+                    }
+                }
+                tokenAttrs = fcsInfo.findAttrs(token);
+
+                if (LOG.isLoggable(Level.FINE)) {
+                    // Add token info to the tooltip
+                    tokenAttrs = AttributesUtilities.createComposite(
+                            
AttributesUtilities.createImmutable(EditorStyleConstants.Tooltip,
+                            "<html>" //NOI18N
+                            + "<b>Token:</b> " + token.text() //NOI18N
+                            + "<br><b>Id:</b> " + id.name() //NOI18N
+                            + "<br><b>Category:</b> " + id.primaryCategory() 
//NOI18N
+                            + "<br><b>Ordinal:</b> " + id.ordinal() //NOI18N
+                            + "<br><b>Mimepath:</b> " + 
ts.languagePath().mimePath() //NOI18N
+                            ),
+                            tokenAttrs);
+                }
+                return true;
+            } else {
+                tokenOffset = tokenEndOffset;
+                return false;
+            }
+        }
+
+    }
+
+    @MimeRegistration(service=HighlightsLayerFactory.class, mimeType="")
+    public static class FactoryImpl implements HighlightsLayerFactory {
+
+        @Override
+        public HighlightsLayer[] createLayers(Context ctx) {
+            Document doc = ctx.getDocument();
+            TokenHierarchy<Document> th = TokenHierarchy.get(doc);
+
+            if (th == null) {
+                return new HighlightsLayer[0];
+            }
+            //check the token hierarchy produces the TextmateTokens
+            return new HighlightsLayer[] {
+                HighlightsLayer.create(SyntaxHighlighting.class.getName(),
+                                       ZOrder.SYNTAX_RACK,
+                                       true,
+                                       new SyntaxHighlighting(doc))
+            };
+        }
+        
+    }
+}
diff --git 
a/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/TextmateLexer.java 
b/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/TextmateLexer.java
new file mode 100644
index 0000000..168c459
--- /dev/null
+++ 
b/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/TextmateLexer.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.textmate.lexer;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.eclipse.tm4e.core.grammar.IGrammar;
+import org.eclipse.tm4e.core.grammar.IToken;
+import org.eclipse.tm4e.core.grammar.ITokenizeLineResult;
+import org.eclipse.tm4e.core.grammar.StackElement;
+import org.netbeans.api.lexer.Token;
+import org.netbeans.spi.lexer.Lexer;
+import org.netbeans.spi.lexer.LexerInput;
+import org.netbeans.spi.lexer.TokenFactory;
+
+public class TextmateLexer implements Lexer<TextmateTokenId>{
+
+    private static final Object DO_NOT_RESUME_HERE = new Object();
+
+    private final LexerInput li;
+    private final TokenFactory<TextmateTokenId> factory;
+    private final IGrammar grammar;
+    private int lineLen;
+    private int currentOffset;
+    private List<IToken> lineTokens;
+    private int currentIdx;
+    private StackElement state;
+
+    public TextmateLexer(LexerInput li, Object state, 
TokenFactory<TextmateTokenId> factory, IGrammar grammar) {
+        if (state == DO_NOT_RESUME_HERE) {
+            throw new IllegalStateException("Invalid resume state!");
+        }
+        this.li = li;
+        this.state = (StackElement) state;
+        this.factory = factory;
+        this.grammar = grammar;
+    }
+
+    @Override
+    public Token<TextmateTokenId> nextToken() {
+        if (currentOffset >= lineLen) {
+            //read next line:
+            int read;
+            while ((read = li.read()) != LexerInput.EOF && read != '\n');
+            if (li.readLength() != 0) {
+                System.err.println(li.readText().toString());
+                lineLen = li.readText().length();
+                currentOffset = 0;
+                ITokenizeLineResult tokenized = 
grammar.tokenizeLine(li.readText().toString(), state);
+                lineTokens = new 
ArrayList<>(Arrays.asList(tokenized.getTokens()));
+                currentIdx = 0;
+                state = tokenized.getRuleStack();
+            }
+        }
+        if (lineTokens != null && currentIdx < lineTokens.size()) {
+            IToken current = lineTokens.get(currentIdx);
+            if (currentOffset < current.getStartIndex()) {
+                int len = current.getStartIndex() - currentOffset;
+                currentOffset += len;
+                return factory.createToken(TextmateTokenId.UNTOKENIZED, 
lineLen - currentOffset);
+            } else if (currentOffset == current.getStartIndex()) {
+                currentIdx++;
+                int len = current.getEndIndex() - current.getStartIndex();
+                len = Math.min(len, lineLen -  currentOffset); //XXX: 
untested, unclear when this happens (Rust)
+                currentOffset += len;
+                List<String> categories = Collections.unmodifiableList(new 
ArrayList<>(current.getScopes()));
+                return factory.createPropertyToken(TextmateTokenId.TEXTMATE, 
len, (token, key) -> {
+                    if ("categories".equals(key)) {
+                        return categories;
+                    } else {
+                        return null;
+                    }
+                });
+            }
+        }
+        if (currentOffset < lineLen) {
+            int len = lineLen - currentOffset;
+            currentOffset += len;
+            return factory.createToken(TextmateTokenId.UNTOKENIZED, len);
+        }
+        return null;
+    }
+    
+    @Override
+    public Object state() {
+        return lineLen != currentOffset ? DO_NOT_RESUME_HERE : this.state;
+    }
+
+    @Override
+    public void release() {}
+    
+}
diff --git 
a/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/TextmateTokenId.java
 
b/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/TextmateTokenId.java
new file mode 100644
index 0000000..152ffba
--- /dev/null
+++ 
b/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/TextmateTokenId.java
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.textmate.lexer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.eclipse.tm4e.core.grammar.IGrammar;
+import org.eclipse.tm4e.core.registry.IRegistryOptions;
+import org.eclipse.tm4e.core.registry.Registry;
+import org.netbeans.api.editor.mimelookup.MimePath;
+import org.netbeans.api.lexer.TokenId;
+import org.netbeans.spi.editor.mimelookup.MimeDataProvider;
+import org.netbeans.spi.lexer.LanguageHierarchy;
+import org.netbeans.spi.lexer.Lexer;
+import org.netbeans.spi.lexer.LexerRestartInfo;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.util.Lookup;
+import org.openide.util.lookup.Lookups;
+import org.openide.util.lookup.ServiceProvider;
+
+public enum TextmateTokenId implements TokenId {
+
+    TEXTMATE,
+    UNTOKENIZED;
+
+    @Override
+    public String primaryCategory() {
+        return "textmate";
+    }
+
+    public static class LanguageHierarchyImpl extends 
LanguageHierarchy<TextmateTokenId> {
+
+        public static final String GRAMMAR_MARK = "textmate-grammar";
+        private static final Map<String, FileObject> scope2File;
+        private static final Map<String, String> mimeType2Scope;
+        
+        static {
+            scope2File = new HashMap<>();
+            mimeType2Scope = new HashMap<>();
+            FileObject editors = 
FileUtil.getSystemConfigRoot().getFileObject("Editors");
+            if (editors != null) {
+                Enumeration<? extends FileObject> en = 
editors.getChildren(true);
+                while (en.hasMoreElements()) {
+                    FileObject candidate = en.nextElement();
+                    Object attr = candidate.getAttribute(GRAMMAR_MARK);
+                    if (attr != null && attr instanceof String) {
+                        String scope = (String) attr;
+                        scope2File.put(scope, candidate);
+                        mimeType2Scope.put(FileUtil.getRelativePath(editors, 
candidate.getParent()), scope);
+                    }
+                }
+            }
+        }
+
+        private final String mimeType;
+        private final IGrammar grammar;
+
+        public LanguageHierarchyImpl(String mimeType, String scope) throws 
Exception {
+            this.mimeType = mimeType;
+            IRegistryOptions opts = new IRegistryOptions() {
+                @Override
+                public String getFilePath(String scopeName) {
+                    FileObject file = scope2File.get(scopeName);
+                    return file != null ? file.getNameExt() : null;
+                }
+                @Override
+                public InputStream getInputStream(String scopeName) throws 
IOException {
+                    FileObject file = scope2File.get(scopeName);
+                    return file != null ? file.getInputStream(): null;
+                }
+                @Override
+                public Collection<String> getInjections(String scopeName) {
+                    return null;
+                }
+            };
+            this.grammar = new Registry(opts).loadGrammar(scope);
+        }
+
+        @Override
+        protected Collection<TextmateTokenId> createTokenIds() {
+            return Arrays.asList(TextmateTokenId.values());
+        }
+
+        @Override
+        protected Lexer<TextmateTokenId> 
createLexer(LexerRestartInfo<TextmateTokenId> lri) {
+            return new TextmateLexer(lri.input(), lri.state(), 
lri.tokenFactory(), grammar);
+        }
+
+        @Override
+        protected String mimeType() {
+            return mimeType;
+        }
+
+    }
+    
+    @ServiceProvider(service=MimeDataProvider.class, 
position=Integer.MAX_VALUE)
+    public static final class MimeDataProviderImpl implements MimeDataProvider 
{
+
+        private static final Logger LOG = 
Logger.getLogger(MimeDataProviderImpl.class.getName());
+
+        @Override
+        public Lookup getLookup(MimePath arg0) {
+            String scope = 
LanguageHierarchyImpl.mimeType2Scope.get(arg0.getPath());
+            
+            if (scope != null) {
+                try {
+                    return Lookups.singleton(new 
LanguageHierarchyImpl(arg0.getPath(), scope).language());
+                } catch (Exception ex) {
+                    LOG.log(Level.FINE, null, ex);
+                }
+            }
+
+            return null;
+        }
+        
+    }
+}
diff --git 
a/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/resources/Bundle.properties
 
b/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/resources/Bundle.properties
new file mode 100644
index 0000000..b0c3230
--- /dev/null
+++ 
b/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/resources/Bundle.properties
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+text/textmate=TextMate Languages
diff --git 
a/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/resources/fontsColors.xml
 
b/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/resources/fontsColors.xml
new file mode 100644
index 0000000..be6e632
--- /dev/null
+++ 
b/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/resources/fontsColors.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License") /> you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<!DOCTYPE fontscolors PUBLIC "-//NetBeans//DTD Editor Fonts and Colors 
settings 1.1//EN" "http://www.netbeans.org/dtds/EditorFontsColors-1_1.dtd";>
+
+<fontscolors>
+
+    <fontcolor name="comment" default="comment" />
+    <fontcolor name="constant.numeric" default="number" />
+    <fontcolor name="constant.character" default="char" />
+    <fontcolor name="constant.character.escape" default="char">
+        <font style="bold" />
+    </fontcolor>
+    <fontcolor name="constant.language" default="keyword" />
+    <fontcolor name="constant.other" default="identifier" /> <!--???-->
+    <fontcolor name="entity.name.function" default="method">
+        <font style="bold" />
+    </fontcolor>
+    <fontcolor name="invalid" default="error" />
+    <fontcolor name="keyword" default="keyword" />
+    <fontcolor name="keyword.operator" default="operator" />
+    <fontcolor name="markup.underline" underline="000000"/>
+    <fontcolor name="markup.bold" default="identifier">
+        <font style="bold" />
+    </fontcolor>
+    <fontcolor name="markup.heading" default="identifier">
+        <font style="bold" />
+    </fontcolor>
+    <fontcolor name="markup.italic" default="identifier">
+        <font style="italic" />
+    </fontcolor>
+    <fontcolor name="storage" default="keyword" />
+    <fontcolor name="string" default="string" />
+    <fontcolor name="support.function" default="method" />
+    <fontcolor name="support.constant" default="keyword" />
+    <fontcolor name="variable.language" default="keyword" />
+
+</fontscolors>
diff --git 
a/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/resources/layer.xml
 
b/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/resources/layer.xml
new file mode 100644
index 0000000..a24c4c0
--- /dev/null
+++ 
b/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/resources/layer.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License") /> you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" 
"http://www.netbeans.org/dtds/filesystem-1_2.dtd";>
+<filesystem>
+    <folder name="Editors">
+        <folder name="text">
+            <folder name="textmate">
+                <attr name="SystemFileSystem.localizingBundle" 
stringvalue="org.netbeans.modules.textmate.lexer.resources.Bundle"/>
+                <folder name="FontsColors">
+                    <folder name="NetBeans">
+                        <folder name="Defaults">
+                            <file name="fontsColors.xml" url="fontsColors.xml">
+                            </file>
+                        </folder>
+                    </folder>
+                </folder>
+            </folder>
+        </folder>
+    </folder>
+</filesystem>
+
diff --git 
a/ide/textmate.lexer/test/unit/src/org/netbeans/modules/textmate/lexer/TextmateLexerTest.java
 
b/ide/textmate.lexer/test/unit/src/org/netbeans/modules/textmate/lexer/TextmateLexerTest.java
new file mode 100644
index 0000000..a448cfc
--- /dev/null
+++ 
b/ide/textmate.lexer/test/unit/src/org/netbeans/modules/textmate/lexer/TextmateLexerTest.java
@@ -0,0 +1,171 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.textmate.lexer;
+
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.Arrays;
+import javax.swing.text.Document;
+import javax.swing.text.PlainDocument;
+import org.netbeans.api.lexer.Language;
+import org.netbeans.api.lexer.TokenHierarchy;
+import org.netbeans.api.lexer.TokenSequence;
+import org.netbeans.junit.NbTestCase;
+import org.netbeans.lib.lexer.test.LexerTestUtilities;
+import 
org.netbeans.modules.textmate.lexer.TextmateTokenId.LanguageHierarchyImpl;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+
+public class TextmateLexerTest extends NbTestCase {
+    
+    public TextmateLexerTest(String name) {
+        super(name);
+    }
+    
+    public void testRestart() throws Exception {
+        clearWorkDir();
+
+        FileObject grammar = FileUtil.createData(FileUtil.getConfigRoot(), 
"Editors/text/test/grammar.json");
+        try (OutputStream out = grammar.getOutputStream();
+             Writer w = new OutputStreamWriter(out)) {
+            w.write("{ \"scopeName\": \"test\", " +
+                    " \"patterns\": [\n" +
+                    "  { \"name\": \"string.test\",\n" +
+                    "    \"begin\": \"x([^x]+)x\",\n" +
+                    "    \"end\": \"x\\\\1x\"\n" +
+                    "   },\n" +
+                    "  { \"name\": \"whitespace.test\",\n" +
+                    "    \"match\": \" +\"\n" +
+                    "   }\n" +
+                    "]}\n");
+        }
+        grammar.setAttribute(LanguageHierarchyImpl.GRAMMAR_MARK, "test");
+        Document doc = new PlainDocument();
+        doc.insertString(0, " xaax xbbx\nxccx xaax ", null);
+        doc.putProperty(Language.class, new LanguageHierarchyImpl("text/test", 
"test").language());
+        TokenHierarchy<Document> hi = TokenHierarchy.get(doc);
+        TokenSequence<?> ts = hi.tokenSequence();
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
" ");
+        assertTokenProperties(ts, "test", "whitespace.test");
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
"xaax");
+        assertTokenProperties(ts, "test", "string.test");
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
" xbbx\n");
+        assertTokenProperties(ts, "test", "string.test");
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
"xccx ");
+        assertTokenProperties(ts, "test", "string.test");
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
"xaax");
+        assertTokenProperties(ts, "test", "string.test");
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
" ");
+        assertTokenProperties(ts, "test", "whitespace.test");
+        LexerTestUtilities.assertNextTokenEquals(ts, 
TextmateTokenId.UNTOKENIZED, "\n");
+        assertFalse(ts.moveNext());
+        doc.insertString(8, "b", null);
+        ts = hi.tokenSequence();
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
" ");
+        assertTokenProperties(ts, "test", "whitespace.test");
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
"xaax");
+        assertTokenProperties(ts, "test", "string.test");
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
" xbbbx\n");
+        assertTokenProperties(ts, "test", "string.test");
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
"xccx ");
+        assertTokenProperties(ts, "test", "string.test");
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
"xaax");
+        assertTokenProperties(ts, "test", "string.test");
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
" ");
+        assertTokenProperties(ts, "test", "whitespace.test");
+        LexerTestUtilities.assertNextTokenEquals(ts, 
TextmateTokenId.UNTOKENIZED, "\n");
+        assertFalse(ts.moveNext());
+        doc.insertString(14, "c", null);
+        ts = hi.tokenSequence();
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
" ");
+        assertTokenProperties(ts, "test", "whitespace.test");
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
"xaax");
+        assertTokenProperties(ts, "test", "string.test");
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
" xbbbx\n");
+        assertTokenProperties(ts, "test", "string.test");
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
"xcccx ");
+        assertTokenProperties(ts, "test", "string.test");
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
"xaax");
+        assertTokenProperties(ts, "test", "string.test");
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
" ");
+        assertTokenProperties(ts, "test", "whitespace.test");
+        LexerTestUtilities.assertNextTokenEquals(ts, 
TextmateTokenId.UNTOKENIZED, "\n");
+        assertFalse(ts.moveNext());
+        doc.insertString(3, "a", null);
+        ts = hi.tokenSequence();
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
" ");
+        assertTokenProperties(ts, "test", "whitespace.test");
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
"xaaax");
+        assertTokenProperties(ts, "test", "string.test");
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
" xbbbx\n");
+        assertTokenProperties(ts, "test", "string.test");
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
"xcccx ");
+        assertTokenProperties(ts, "test", "string.test");
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
"xaax");
+        assertTokenProperties(ts, "test", "string.test");
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
" ");
+        assertTokenProperties(ts, "test", "whitespace.test");
+        LexerTestUtilities.assertNextTokenEquals(ts, 
TextmateTokenId.UNTOKENIZED, "\n");
+        assertFalse(ts.moveNext());
+    }
+
+    public void testUTF8() throws Exception {
+        clearWorkDir();
+
+        FileObject grammar = FileUtil.createData(FileUtil.getConfigRoot(), 
"Editors/text/test/grammar.json");
+        try (OutputStream out = grammar.getOutputStream();
+             Writer w = new OutputStreamWriter(out)) {
+            w.write("{ \"scopeName\": \"test\", " +
+                    " \"patterns\": [\n" + 
+                    "  { \"name\": \"ident.test\",\n" +
+                    "    \"match\": \"[^ ]+\"\n" +
+                    "   }\n" +
+                    "]}\n");
+        }
+        grammar.setAttribute(LanguageHierarchyImpl.GRAMMAR_MARK, "test");
+        Document doc = new PlainDocument();
+        doc.insertString(0, " večerníček večerníček  \n", null);
+        doc.putProperty(Language.class, new LanguageHierarchyImpl("text/test", 
"test").language());
+        TokenHierarchy<Document> hi = TokenHierarchy.get(doc);
+        TokenSequence<?> ts = hi.tokenSequence();
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
" ");
+        assertTokenProperties(ts, "test");
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
"večerníček");
+        assertTokenProperties(ts, "test", "ident.test");
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
" ");
+        assertTokenProperties(ts, "test");
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
"večerníček");
+        assertTokenProperties(ts, "test", "ident.test");
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
"  ");
+        assertTokenProperties(ts, "test");
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
" ");
+        assertTokenProperties(ts, "test", "whitespace.test");
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
"večerníček");
+        assertTokenProperties(ts, "test", "ident.test");
+        LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE, 
" ");
+        assertTokenProperties(ts, "test", "whitespace.test");
+        assertFalse(ts.moveNext());
+    }
+
+    private void assertTokenProperties(TokenSequence<?> ts, String... 
properties) {
+        assertEquals(ts.token().getProperty("categories"), 
Arrays.asList(properties));
+    }
+
+}
diff --git a/nbbuild/cluster.properties b/nbbuild/cluster.properties
index a557c71..088374a 100644
--- a/nbbuild/cluster.properties
+++ b/nbbuild/cluster.properties
@@ -514,6 +514,7 @@ nb.cluster.ide=\
         team.ide,\
         terminal,\
         terminal.nb,\
+        textmate.lexer,\
         usersguide,\
         utilities,\
         utilities.project,\
diff --git a/nbbuild/licenses/MIT-jruby b/nbbuild/licenses/MIT-jruby
new file mode 100644
index 0000000..9341f05
--- /dev/null
+++ b/nbbuild/licenses/MIT-jruby
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017 JRuby Team
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/nbbuild/licenses/names.properties 
b/nbbuild/licenses/names.properties
index 31ee59a..b323e0a 100644
--- a/nbbuild/licenses/names.properties
+++ b/nbbuild/licenses/names.properties
@@ -57,6 +57,7 @@ MIT-icu4j=MIT license icu4j variant
 MIT-isorelax=MIT license isorelax variant
 MIT-sim=MIT license ios-sim variant, with license for code from contributors.
 MIT-jquery=MIT license JQuery variant
+MIT-jruby=MIT license JRuby variant
 MIT-nodejs=MIT license NodeJS variant plus node external libraries licenses
 MIT-phpstan=MIT license PHPStan variant
 MIT-validator=MIT license validator variant


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists

Reply via email to