[gtksourceview] Add a language file for Groovy



commit b22eb9da513cc5e58298c670ed7995e9be4e5907
Author: Роман Донченко <dpb corrigendum ru>
Date:   Sun Dec 10 00:05:58 2017 +0300

    Add a language file for Groovy
    
    This was originally based on java.lang (hence the extra copyright lines),
    although Groovy is sufficiently different from Java that only the overall
    structure and keyword lists have survived from the original file.
    
    Add a test file, as well.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=553894

 data/language-specs/Makefile.am       |    1 +
 data/language-specs/groovy.lang       |  337 +++++++++++++++++++++++++++++++++
 po/POTFILES.skip                      |    1 +
 tests/syntax-highlighting/file.groovy |   55 ++++++
 4 files changed, 394 insertions(+), 0 deletions(-)
---
diff --git a/data/language-specs/Makefile.am b/data/language-specs/Makefile.am
index 7d62ed3..98c8371 100644
--- a/data/language-specs/Makefile.am
+++ b/data/language-specs/Makefile.am
@@ -45,6 +45,7 @@ LANGUAGES =                   \
        genie.lang              \
        glsl.lang               \
        go.lang                 \
+       groovy.lang             \
        gtk-doc.lang            \
        gtkrc.lang              \
        haddock.lang            \
diff --git a/data/language-specs/groovy.lang b/data/language-specs/groovy.lang
new file mode 100644
index 0000000..a91ae7a
--- /dev/null
+++ b/data/language-specs/groovy.lang
@@ -0,0 +1,337 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ This file is part of GtkSourceView
+
+ Copyright (C) 2003 Gustavo Giráldez <gustavo giraldez gmx net>
+ Copyright (C) 2006 Jeff Walden <jwalden mit edu>
+ Copyright (C) 2017 Roman Donchenko
+
+ GtkSourceView is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ GtkSourceView is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, see <http://www.gnu.org/licenses/>.
+
+-->
+<language id="groovy" name="Groovy" version="2.0" _section="Source">
+  <metadata>
+    <property name="globs">*.groovy</property>
+    <property name="line-comment-start">//</property>
+    <property name="block-comment-start">/*</property>
+    <property name="block-comment-end">*/</property>
+  </metadata>
+
+  <styles>
+    <style id="comment"           name="Comment"                   map-to="def:comment"/>
+    <style id="escaped-character" name="Escaped Character"         map-to="def:special-char"/>
+    <style id="interpolation"     name="Interpolation Syntax"      map-to="def:special-char"/>
+    <style id="interpolated"      name="Interpolated Expression"   map-to="def:identifier"/>
+    <style id="string"            name="String"                    map-to="def:string"/>
+    <style id="external"          name="External"                  map-to="def:preprocessor"/>
+    <style id="declaration"       name="Declaration"               map-to="def:type"/>
+    <style id="storage-class"     name="Storage Class"             map-to="def:type"/>
+    <style id="scope-declaration" name="Scope Declaration"         map-to="def:type"/>
+    <style id="operator"          name="Operator"                  map-to="def:operator"/>
+    <style id="keyword"           name="Keyword"                   map-to="def:keyword"/>
+    <style id="null-value"        name="Null Value"                map-to="def:special-constant"/>
+    <style id="boolean"           name="Boolean value"             map-to="def:boolean"/>
+    <style id="number"            name="Number"                    map-to="def:number"/>
+    <style id="type"              name="Data Type"                 map-to="def:type"/>
+  </styles>
+
+  <definitions>
+    <define-regex id="escaped-character" extended="true">
+      \\(
+        # character escape
+        [nrtbf"'\\$] |
+        # unicode escape
+        u[0-9A-Fa-f]{4} |
+        # octal escape
+        [0-3] ([0-7] [0-7]?)? | [4-7] [0-7]?
+      )
+    </define-regex>
+
+    <define-regex id="letter" extended="true">
+      [a-zA-Z\x{c0}-\x{d6}\x{d8}-\x{f6}\x{f8}-\x{ff}\x{100}-\x{fffe}_]
+    </define-regex>
+
+    <context id="escaped-character">
+      <include>
+        <context style-ref="escaped-character">
+          <match>\%{escaped-character}</match>
+        </context>
+        <context ref="def:line-continue"/>
+        <context style-ref="def:error">
+          <!-- backslashes not part of a valid escape sequence are erroneous -->
+          <match>\\</match>
+        </context>
+      </include>
+    </context>
+
+    <context id="placeholder">
+      <include>
+        <context style-ref="interpolated">
+          <match extended="true">
+            (\$)
+            # one or more dollarless identifiers separated by dots
+            \%{letter} (\%{letter} | \d)*
+            (\. \%{letter} (\%{letter} | \d)*)*
+          </match>
+          <include>
+            <context sub-pattern="1" style-ref="interpolation"/>
+          </include>
+        </context>
+        <context style-ref="interpolated">
+          <start>\$\{</start>
+          <end>\}</end>
+          <include>
+            <context sub-pattern="0" where="start" style-ref="interpolation"/>
+            <context sub-pattern="0" where="end" style-ref="interpolation"/>
+            <context ref="groovy"/>
+          </include>
+        </context>
+      </include>
+    </context>
+
+    <!-- a dollar that isn't part of a placeholder is erroneous in some instances -->
+    <context id="bad-placeholder" style-ref="def:error">
+      <match>\$</match>
+    </context>
+
+    <context id="triple-single-quoted-string" style-ref="string" class="string" 
class-disabled="no-spell-check">
+      <start>'''</start>
+      <end>'''</end>
+      <include>
+        <context ref="escaped-character"/>
+      </include>
+    </context>
+
+    <context id="single-quoted-string" end-at-line-end="true" style-ref="string" class="string" 
class-disabled="no-spell-check">
+      <start>'</start>
+      <end>'</end>
+      <include>
+        <context ref="escaped-character"/>
+      </include>
+    </context>
+
+    <context id="triple-double-quoted-string" style-ref="string" class="string" 
class-disabled="no-spell-check">
+      <start>"""</start>
+      <end>"""</end>
+      <include>
+        <context ref="escaped-character"/>
+        <context ref="placeholder"/>
+        <context ref="bad-placeholder"/>
+      </include>
+    </context>
+
+    <context id="double-quoted-string" end-at-line-end="true" style-ref="string" class="string" 
class-disabled="no-spell-check">
+      <start>"</start>
+      <end>"</end>
+      <include>
+        <context ref="escaped-character"/>
+        <context ref="placeholder"/>
+        <context ref="bad-placeholder"/>
+      </include>
+    </context>
+
+    <context id="slashy-string" style-ref="string" class="string">
+      <start extended="true">
+        # The initial slash must not be preceded by a token that can end an expression.
+        # Otherwise, it's interpreted as a division operator, not the start of a slashy string.
+        # It'd be complicated to verify whole tokens with a regex, but the last non-space
+        # character is a good indicator by itself. We can use a negative lookbehind assertion
+        # to verify that it's not a character that an expression-ending token can end with.
+
+        # Trouble is, a lookbehind assertion has to consist of fixed-length alternatives, so
+        # we can't have it match an arbitrary amount of whitespace. Thus, we do an approximate
+        # check, only trying zero and one spaces.
+
+        (?&lt;! \+\+   | --   | [])}"\d]   | \%{letter} |
+                \+\+\s | --\s | [])}"\d]\s | \%{letter}\s )
+
+        /
+      </start>
+      <end>/</end>
+      <include>
+        <context style-ref="escaped-character">
+          <match>\\/</match>
+        </context>
+        <context ref="def:line-continue"/>
+        <context ref="placeholder"/>
+        <!-- standalone dollars and backslashes are interpreted literally -->
+      </include>
+    </context>
+
+    <context id="dollar-slashy-string" style-ref="string" class="string">
+      <start extended="true">
+        # Strictly speaking, a dollar slashy string has the same requirements on the
+        # preceding token as a plain slashy string, but if those requirements aren't
+        # met, it's parsed as a dollar followed by a division operator, which isn't
+        # legal. So we don't bother with accounting for that case.
+
+        \$/
+
+        # We will, however, account for the case when there's a slash right after
+        # the initial $/. In that case, the construct is actually parsed as a dollar
+        # followed by a single-line comment. Which is still illegal... but as least
+        # this check is easy to implement.
+        (?=[^/])
+      </start>
+      <end>/\$</end>
+      <include>
+        <context style-ref="escaped-character">
+          <match>\$[$/]</match>
+        </context>
+        <context ref="def:line-continue"/>
+        <context ref="placeholder"/>
+      </include>
+    </context>
+
+    <context id="numeric" style-ref="number">
+      <match extended="true">
+        \b (
+          # floating-point
+          \d ([\d_]* \d)? (
+            \. \d ([\d_]* \d)? ([eE] [+-]? [\d_]* \d)? [dDfFgG]? |
+            [eE] [+-]? [\d_]* \d [dDfFgG]? |
+            [dDfF]
+          ) |
+          # integer
+          (
+            0 | # decimal zero
+            0[bB] [01] ([01_]* [01])? | # binary
+            0 [0-7] ([0-7_]* [0-7])? | # octal
+            [1-9] ([\d_]* \d)? | # decimal
+            0[xX] [\da-fA-F] ([\da-fA-F_]* [\da-fA-F])? # hexadecimal
+          ) [iIlLgG]?
+        ) \b
+      </match>
+    </context>
+
+    <!--
+      Some of the Java keywords are reserved in Groovy. We don't mark them
+      with a special style, though, because in some instances keywords can
+      be used as identifiers (e.g. when used as a member name), and even
+      reserved keywords are valid when used like that.
+    -->
+
+    <context id="externals" style-ref="external">
+      <keyword>import</keyword>
+      <keyword>package</keyword>
+    </context>
+
+    <context id="declarations" style-ref="declaration">
+      <keyword>class</keyword>
+      <keyword>enum</keyword>
+      <keyword>extends</keyword>
+      <keyword>implements</keyword>
+      <keyword>interface</keyword>
+      <keyword>native</keyword>
+      <keyword>throws</keyword>
+      <keyword>trait</keyword>
+    </context>
+
+    <context id="primitive-types" style-ref="type">
+      <keyword>boolean</keyword>
+      <keyword>byte</keyword>
+      <keyword>char</keyword>
+      <keyword>def</keyword>
+      <keyword>double</keyword>
+      <keyword>float</keyword>
+      <keyword>int</keyword>
+      <keyword>long</keyword>
+      <keyword>short</keyword>
+      <keyword>void</keyword>
+    </context>
+
+    <context id="storage-class" style-ref="storage-class">
+      <keyword>abstract</keyword>
+      <keyword>const</keyword>
+      <keyword>final</keyword>
+      <keyword>static</keyword>
+      <keyword>strictfp</keyword>
+      <keyword>synchronized</keyword>
+      <keyword>transient</keyword>
+      <keyword>volatile</keyword>
+    </context>
+
+    <context id="scope-declarations" style-ref="scope-declaration">
+      <keyword>private</keyword>
+      <keyword>protected</keyword>
+      <keyword>public</keyword>
+    </context>
+
+    <context id="flow" style-ref="keyword">
+      <keyword>assert</keyword>
+      <keyword>break</keyword>
+      <keyword>case</keyword>
+      <keyword>catch</keyword>
+      <keyword>continue</keyword>
+      <keyword>default</keyword>
+      <keyword>do</keyword>
+      <keyword>else</keyword>
+      <keyword>finally</keyword>
+      <keyword>for</keyword>
+      <keyword>goto</keyword>
+      <keyword>if</keyword>
+      <keyword>return</keyword>
+      <keyword>throw</keyword>
+      <keyword>switch</keyword>
+      <keyword>try</keyword>
+      <keyword>while</keyword>
+    </context>
+
+    <context id="operator" style-ref="operator">
+      <keyword>as</keyword>
+      <keyword>in</keyword>
+      <keyword>instanceof</keyword>
+      <keyword>new</keyword>
+      <keyword>super</keyword>
+      <keyword>this</keyword>
+    </context>
+
+    <context id="null-value" style-ref="null-value">
+      <keyword>null</keyword>
+    </context>
+
+    <context id="boolean" style-ref="boolean">
+      <keyword>false</keyword>
+      <keyword>true</keyword>
+    </context>
+
+    <context id="groovy" class="no-spell-check">
+      <include>
+        <context ref="def:shebang" style-ref="comment"/>
+        <context ref="def:c-like-comment" style-ref="comment"/>
+        <context ref="def:c-like-comment-multiline" style-ref="comment"/>
+        <context ref="def:line-continue"/>
+
+        <context ref="triple-single-quoted-string"/>
+        <context ref="single-quoted-string"/>
+        <context ref="triple-double-quoted-string"/>
+        <context ref="double-quoted-string"/>
+        <context ref="slashy-string"/>
+        <context ref="dollar-slashy-string"/>
+        <context ref="numeric"/>
+
+        <context ref="externals"/>
+        <context ref="declarations"/>
+        <context ref="primitive-types"/>
+        <context ref="storage-class"/>
+        <context ref="scope-declarations"/>
+        <context ref="flow"/>
+        <context ref="operator"/>
+        <context ref="null-value"/>
+        <context ref="boolean"/>
+      </include>
+    </context>
+  </definitions>
+</language>
diff --git a/po/POTFILES.skip b/po/POTFILES.skip
index 375e96c..3927763 100644
--- a/po/POTFILES.skip
+++ b/po/POTFILES.skip
@@ -48,6 +48,7 @@ data/language-specs/gdb-log.lang
 data/language-specs/genie.lang
 data/language-specs/glsl.lang
 data/language-specs/go.lang
+data/language-specs/groovy.lang
 data/language-specs/gtk-doc.lang
 data/language-specs/gtkrc.lang
 data/language-specs/haddock.lang
diff --git a/tests/syntax-highlighting/file.groovy b/tests/syntax-highlighting/file.groovy
new file mode 100644
index 0000000..82f01a0
--- /dev/null
+++ b/tests/syntax-highlighting/file.groovy
@@ -0,0 +1,55 @@
+#!/usr/bin/env groovy
+
+// Single-line comment. TODO markers work.
+/* Multi-line comment.
+   TODO markers work. */
+
+'line' \
+    + 'continuation'
+
+def tsq = '''Triple single-quoted string.
+
+    Escapes work: \' \n \123 \u12ab \
+    Interpolation doesn't work: $x ${x}
+'''
+
+def sq = 'Single-quoted string. Escapes work: \' \r \45 \u45CD \
+    Interpolation does not: $x ${x}'
+
+def tdq = """Triple double-quoted string.
+
+    Escapes work: \" \f \6 \uABCD \
+    Interpolation works: $x._y.z0 ${x + 5}
+"""
+
+def dq = "Double-quoted string. Escapes work: \" \b \7 \u5678 \
+    So does interpolation: $_abc1 ${x + "abc"}"
+
+def slashy = /Slashy string.
+
+    There are only two escape sequences: \/ \
+    Interpolation works: $X ${-> X}
+    Dollars $ and backslashes \ on their own are interpreted literally./
+
+def notSlashy = 1 /2/ 3 // not a slashy string; just two division operators
+
+def dollarSlashy = $/Dollar slashy string.
+
+    There are three escape sequences: $$ $/ \
+    Interpolation works: $_ ${true}
+    Dollars $ and backslashes \ on their own are interpreted literally./$
+
+0b10i + 0b0110_1011 // binary numbers
+0 + 123L + 456_789 // decimal numbers
+0xab + 0xcd_efG // hexadecimal numbers
+
+01_23.45_67g + 1e-23f + 2d + 08.80 // floating-point numbers
+
+trait Test {
+    void foo(List list) {
+        def sum = 0
+        for (n in list) sum += n as int
+        println sum
+    }
+}
+


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]