Jun 14 2008

GEdit with Groovy

Published by Kefah Issa at 10:22 am under Fedora 9, Grails, Groovlet, groovy

Need a cool development setup for Groovy and Grails on Linux?

No I don’t mean Eclipse nor IntelliJ, and Yes, I’m smart enough for that I’m dumping the autocompletion and autoerror detection; at least I know i’m smarter than the current plugins for those two. :)

Searching for a good development setup for my groovy and grails projects, i tried IntelliJ and Eclipse along with their groovy and grails plugins. I wasn’t impressed, more so because they fail to properly understand things and give you errors where there are none.

So, I eneded up using GEdit which is a very nice piece of software. I whished Geany had groovy syntax highlight support, but it doesn’t, further more, Geany doesn’t do a good job when dealing with Arabic text inside the code; while GEdit has a fairly good support for arabic.

GEdit doesn’t come with groovy support out of the box, after a short search I found this article :
http://www.sudovi.com/blog/show/teach_gedit_grails
That worked for me.

Here is how it looks like :

Grails and GEdit
I then compiled all the steps needed to enable groovy on gedit in one handy bashscript file for Fedora 9:

 
cat > groovy-gsp-mime.xml << EOF
<?xml version="1.0" encoding="UTF-8"?>
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
 
	<mime-type type="text/x-groovy">
		<sub-class-of type="text/x-java"/>
		<comment>Groovy Source File</comment>
		<glob pattern="*.groovy"/>
	</mime-type>
 
	<mime-type type="text/x-gsp">
		<sub-class-of type="text/html"/>
		<comment>Grails GSP File</comment>
		<glob pattern="*.gsp"/>
	</mime-type>
 
</mime-info>
EOF
 
cat > groovy.lang << EOF
<?xml version="1.0" encoding="UTF-8"?>
<language id="groovy" _name="Groovy" version="2.0" _section="Sources">
  <metadata>
    <property name="mimetypes">text/x-groovy</property>
    <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="error" _name="Error" map-to="def:error"/>
    <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="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:decimal"/>
    <style id="reserved" _name="Future Reserved Keywords" map-to="def:error"/>
    <style id="type" _name="Data Type" map-to="def:type"/>
  </styles>
 
  <definitions>
 
    <context id="string" style-ref="string" end-at-line-end="true">
      <start>"</start>
      <end>"</end>
    </context>
 
    <context id="string-2" style-ref="string" end-at-line-end="true">
      <start>'</start>
      <end>'</end>
    </context>
 
    <context id="line-comment" style-ref="comment" end-at-line-end="true">
      <start>//</start>
      <include>
        <context ref="def:in-line-comment"/>
      </include>
    </context>
 
    <context id="block-comment" style-ref="comment">
      <start>/\*</start>
      <end>\*/</end>
      <include>
        <context ref="def:in-comment"/>
      </include>
    </context>
 
    <context id="close-comment-outside-comment" style-ref="error">
      <match>\*/(?!\*)</match>
    </context>
 
    <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>instanceof</keyword>
      <keyword>interface</keyword>
      <keyword>native</keyword>
      <keyword>throws</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>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>each</keyword>
      <keyword>else</keyword>
      <keyword>finally</keyword>
      <keyword>for</keyword>
      <keyword>if</keyword>
      <keyword>render</keyword>
      <keyword>return</keyword>
      <keyword>throw</keyword>
      <keyword>switch</keyword>
      <keyword>try</keyword>
      <keyword>while</keyword>
      <keyword>with</keyword>
    </context>
 
    <context id="memory" style-ref="keyword">
      <keyword>new</keyword>
      <keyword>super</keyword>
      <keyword>this</keyword>
    </context>
 
    <context id="future-reserved-words" style-ref="reserved">
      <keyword>const</keyword>
      <keyword>goto</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="numeric" style-ref="number">
      <match extended="true">
        (\b([0-9]+|0[xX][0-9a-fA-F]+)[Ll]?\b|
         \b(([0-9]+[Ee][-]?[0-9]+|
            ([0-9]*\.[0-9]+|[0-9]+\.)([Ee][-]?[0-9]+)?)[fFdD]?|
            [0-9]+[FfDd]))
      </match>
    </context>
 
    <context id="groovy">
      <include>
        <context ref="string"/>
        <context ref="string-2"/>
        <context ref="line-comment"/>
        <context ref="block-comment"/>
        <context ref="close-comment-outside-comment"/>
        <context ref="externals"/>
        <context ref="declarations"/>
        <context ref="primitive-types"/>
        <context ref="storage-class"/>
        <context ref="scope-declarations"/>
        <context ref="flow"/>
        <context ref="memory"/>
        <context ref="future-reserved-words"/>
        <context ref="null-value"/>
        <context ref="boolean"/>
        <context ref="numeric"/>
      </include>
    </context>
 
  </definitions>
</language>
EOF
 
cat > gsp.lang << EOF
<?xml version="1.0" encoding="UTF-8"?>
<language id="gsp" _name="GSP" version="2.0" _section="Markup">
    <metadata>
      <property name="mimetypes">text/x-gsp</property>
      <property name="globs">*.gsp</property>
      <property name="block-comment-start">&lt;!--</property>
      <property name="block-comment-end">--&gt;</property>
    </metadata>
 
    <styles>
        <style id="comment" _name="Comment" map-to="xml:comment"/>
        <style id="tag" _name="Tag" map-to="xml:element-name"/>
        <style id="attrib-name" _name="Attribute Name" map-to="xml:attribute-name"/>
        <style id="attrib-value" _name="Attribute Value" map-to="xml:attribute-value"/>
        <style id="dtd" _name="DTD" map-to="xml:doctype"/>
        <style id="error" _name="Error" map-to="xml:error"/>
    </styles>
 
    <default-regex-options case-sensitive="false"/>
 
    <definitions>
        <!-- Html comments are more permissive than xml comments -->
        <context id="comment" style-ref="comment">
            <start>&lt;!--</start>
            <end>--\s*&gt;</end>
            <include>
                <context ref="def:in-comment"/>
            </include>
        </context>
 
        <context id="dtd" style-ref="dtd">
            <start>&lt;!</start>
            <end>&gt;</end>
        </context>
 
        <!-- This is a placeholder context intended to be <replace>d
             in languages like php that need to embedd contexts inside
             html tags and attributes.
        -->
        <context id="embedded-lang-hook">
            <start>\%{def:never-match}</start>
            <end></end>
        </context>
 
        <context id="generic-tag">
            <include>
 
                <!-- Attribute in the form: name="value" -->
                <context id="attrib-quoted" style-ref="attrib-name">
                    <start extended="true">
                        [A-Za-z0-9:_-]+ # attribute name
                        \s*=\s*         # "="
                        (\")            # string beginning
                    </start>
                    <end>\"</end>
                    <include>
                        <context sub-pattern="1" where="start" style-ref="attrib-value"/>
                        <context sub-pattern="0" where="end" style-ref="attrib-value"/>
                        <context id="string" extend-parent="false" end-at-line-end="true" style-ref="attrib-value">
                            <start>\%{def:always-match}</start>
                            <include>
                                <context ref="xml:entity"/>
                                <context ref="xml:character-reference"/>
                                <context ref="embedded-lang-hook"/>
                            </include>
                        </context>
                    </include>
                </context>
 
                <!-- Attribute in the form: name=value -->
                <context id="attrib-unquoted" style-ref="attrib-value">
                    <start extended="true">
                        [a-z0-9:_-]+ # attribute name
                        \s*=\s*      # "="
                    </start>
                    <end>(?=&gt;|\s)</end>
                    <include>
                        <context sub-pattern="0" where="start" style-ref="attrib-name"/>
                        <context ref="xml:entity"/>
                        <context ref="xml:character-reference"/>
                    </include>
                </context>
 
                <!-- Attribute in the form: name -->
                <context id="attrib-no-value" style-ref="attrib-name">
                    <match extended="true">
                        [a-z0-9:_-]+  # attribute name
                    </match>
                </context>
 
                <context ref="embedded-lang-hook"/>
 
            </include>
        </context>
 
        <context id="script">
            <start>&lt;\s*script\%]</start>
            <end>&lt;\s*/\s*script\s*&gt;</end>
 
            <include>
                <context sub-pattern="0" where="start" style-ref="tag"/>
                <context sub-pattern="0" where="end" style-ref="tag"/>
                <context ref="generic-tag"/>
                <context id="js-code" extend-parent="false">
                    <start>&gt;</start>
                    <include>
                        <context sub-pattern="0" where="start" style-ref="tag"/>
                        <context ref="js:js"/>
                    </include>
                </context>
            </include>
        </context>
 
        <context id="tag">
            <start>&lt;\s*/?\s*[a-z0-9_-]+</start>
            <end>/?\s*&gt;</end>
            <include>
                <context sub-pattern="0" where="start" style-ref="tag"/>
                <context sub-pattern="0" where="end" style-ref="tag"/>
                <context ref="generic-tag"/>
            </include>
        </context>
 
	<context id="gtag">
		<start>&lt;g:\s*/?\s*[a-z0-9_-]+</start>
                <end>/?\s*&gt;</end>
            	<include>
                	<context sub-pattern="0" where="start" style-ref="tag"/>
                	<context sub-pattern="0" where="end" style-ref="tag"/>
                	<context ref="generic-tag"/>
		</include>
	</context>
 
        <context id="gsp">
            <include>
                <context ref="xml:doctype"/>
                <context ref="xml:entity"/>
                <context ref="xml:character-reference"/>
                <context ref="xml:cdata"/>
                <context ref="comment"/>
                <context ref="dtd"/>
                <context ref="script"/>
                <context ref="tag"/>
                <context ref="gtag"/>
            </include>
        </context>
 
    </definitions>
</language>
 
EOF
 
 
# Copy the mime
sudo cp groovy-gsp-mime.xml /usr/share/mime/packages/groovy.xml
 
# Copy the language spec's
sudo cp groovy.lang gsp.lang /usr/share/gtksourceview-2.0/language-specs/
 
sudo update-mime-database /usr/share/mime
 
# Create an empty groovy file
touch foo.groovy
 
# Check if the mime is properly defined
gnomevfs-info foo.groovy

5 Responses to “GEdit with Groovy”

  1. lifewithryanon 30 Jul 2008 at 12:57 am

    Hey man, nice to see that you built a script out of it. That’ll save some folks some work!

    I’m glad my initial frustrations served up a good solution for you. :)

  2. Kefah Issaon 30 Jul 2008 at 3:52 am

    Hello Ryan,

    Indeed it did.

    Credit goes to you for that.

    Thanks for passing by,
    - Kefah.

  3. Aaronon 03 Sep 2008 at 11:38 pm

    Is there any reason you know of this bash script wouldn’t work in ubuntu? I already have it all installed otherwise I would just try it

  4. Kefah Issaon 04 Sep 2008 at 8:19 am

    Hello Aaron,

    Not that I can think of, no. If someone can try it and confirm, I’ll make sure to mention the fact.
    Thanks,
    - Kefah.

  5. oliveron 26 Sep 2008 at 1:16 am

    If you add a bug report about “Groovy support for Gedit” at bugs.gnome.org or bugs.launchpad.net, the devs might be able to help with proper integration of Groovy highlighting and all that stuff.

Trackback URI | Comments RSS

Leave a Reply