Jun 14 2008
GEdit with 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 :

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"><!--</property> <property name="block-comment-end">--></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><!--</start> <end>--\s*></end> <include> <context ref="def:in-comment"/> </include> </context> <context id="dtd" style-ref="dtd"> <start><!</start> <end>></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>(?=>|\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><\s*script\%]</start> <end><\s*/\s*script\s*></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>></start> <include> <context sub-pattern="0" where="start" style-ref="tag"/> <context ref="js:js"/> </include> </context> </include> </context> <context id="tag"> <start><\s*/?\s*[a-z0-9_-]+</start> <end>/?\s*></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><g:\s*/?\s*[a-z0-9_-]+</start> <end>/?\s*></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
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.
Hello Ryan,
Indeed it did.
Credit goes to you for that.
Thanks for passing by,
- Kefah.
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
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.
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.