Howto:Syntax highlighting for Nasal: Difference between revisions

From FlightGear wiki
Jump to navigation Jump to search
No edit summary
Line 23: Line 23:
Create a new text file - ''nasal.lang'' with the following contents.
Create a new text file - ''nasal.lang'' with the following contents.


<nowiki><syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8"?>
<!--
<!--
Line 411: Line 411:
   </definitions>
   </definitions>
</language>
</language>
</syntaxhighlight></nowiki>
</syntaxhighlight>


If you use Mac, move it into your ''Applications/gedit/Contents/Resources/share/gtksourceview-2.0/language specs'' folder.
If you use Mac, move it into your ''Applications/gedit/Contents/Resources/share/gtksourceview-2.0/language specs'' folder.

Revision as of 07:45, 16 August 2012

There's Nasal syntax-highlighting support available for some editors, which is a big advantage, as it makes Nasal coding much easier. It can often point to syntax errors and so reduce the number of tedious time-consuming and unproductive FlightGear runs.

Notepad++

http://dl.dropbox.com/u/1463693/nasal.xml

Instructions are here: http://superuser.com/questions/62474/notepad-custom-syntax-highlighting-setting-where-to-look-for-it

jEdit

There's a syntax highlighting mode for jEdit, programmer's text editor

Included are some of Nasal's internal functions and those functions currently implemented in NasalSys.cxx To use, add the content of the catalog inside your own catalog (do NOT overwrite the file) and nasal.xml in /home/USER/.jedit/modes

Restart jEdit and you can use it. Current extension is .nas, you can add your own extension and functions. This mode is heavily based on the Javascript mode.

Get it here: http://www.jedit.org/

gEdit

Philosopher on the FlightGear Forum has created a syntax highlighter for gEdit- a popular and simple Text Editor for Mac OSX and Linux.

Create a new text file - nasal.lang with the following contents.

<?xml version="1.0" encoding="UTF-8"?>
<!--

Author: Gustavo Giráldez <gustavo.giraldez@gmx.net>
Copyright (C) 2003 Gustavo Giráldez <gustavo.giraldez@gmx.net>
Copyright (C) 2004 Benoît Dejean <TaZForEver@free.fr>
Copyright (C) 2006 Steve Frécinaux <nud@apinc.org>

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.

This library 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
Library General Public License for more details.

You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.

-->
<language id="nasal" _name="Nasal" version="2.0" _section="Scripts">
  <metadata>
    <property name="mimetypes">text/nasal;application/nasal</property>
    <property name="globs">*.nas</property>
    <property name="line-comment-start">#</property>
  </metadata>

  <styles>
    <style id="module-handler"    _name="Module Handler"        map-to="def:preprocessor"/>
    <style id="keyword"           _name="Keyword"               map-to="def:keyword"/>
    <!--<style id="multiline-string"  _name="Multiline string"      map-to="def:string"/>-->
    <style id="string"            _name="String"                map-to="def:string"/>
    <style id="escaped-char"      _name="Escaped Character"     map-to="def:special-char"/>
    <style id="format"            _name="Format"                map-to="def:character"/>
    <style id="string-conversion" _name="string-conversion"/>
    <style id="special-variable"  _name="Special Variable"      map-to="def:identifier"/>
    <style id="boolean"           _name="Boolean"               map-to="def:boolean"/>
    <style id="floating-point"    _name="Floating point number" map-to="def:floating-point"/>
    <style id="decimal"           _name="Decimal number"        map-to="def:decimal"/>
    <style id="base-n-integer"    _name="Base-N number"         map-to="def:base-n-integer"/>
    <style id="complex"           _name="Complex number"        map-to="def:complex"/>
    <style id="builtin-constant"  _name="Builtin Constant"      map-to="def:special-constant"/>
    <style id="builtin-object"    _name="Builtin Object"        map-to="def:type"/>
    <style id="builtin-function"  _name="Builtin Function"      map-to="def:builtin"/>
    <style id="path"              _name="Path"                  map-to="def:string"/>
  </styles>

  <definitions>
    <define-regex id="identifier">[_a-zA-Z][_a-zA-Z0-9]*</define-regex>
    <define-regex id="number">[1-9][0-9]*</define-regex>

    <!-- http://docs.python.org/lib/typesseq-strings.html -->
    <context id="format" style-ref="format" extend-parent="false">
      <match extended="true">
        %                       # leading % sign
        \(\%{identifier}\)?     # mapping key
        [#0\-\ \+]*             # conversion flags
        (\-?\%{number}|\*)?     # minimum field width
        (\.(\-?\%{number}|\*))? # precision
        (hlL)?                  # lentgh modifier
        [diouxXeEfFgGcrs%]      # conversion type
      </match>
    </context>

    <!-- http://docs.python.org/ref/strings.html -->
    <context id="escaped-char" style-ref="escaped-char" extend-parent="true">
      <match extended="true">
        \\(                 # leading backslash
        [\\'"abfnrtv]     | # single escaped char
        N\{[A-Z\ ]+\}     | # named unicode character
        u[0-9A-Fa-f]{4}   | # xxxx - character with 16-bit hex value xxxx
        U[0-9A-Fa-f]{8}   | # xxxxxxxx - character with 32-bit hex value xxxxxxxx
        x[0-9A-Fa-f]{1,2} | # \xhh - character with hex value hh
        [0-7]{1,3}          # \ooo - character with octal value ooo
        )
      </match>
    </context>

    <define-regex id="string-prefix">(u|U)?</define-regex>
    <define-regex id="raw-string-prefix">(r|ur|R|UR|Ur|uR)</define-regex>

    <!--<context id="multiline-double-quoted-string" style-ref="multiline-string" class="string" class-disabled="no-spell-check">
      <start>\%{string-prefix}"""</start>
      <end>"""</end>
      <include>
        <context ref="format"/>
        <context ref="escaped-char"/>
      </include>
    </context>

    <context id="multiline-single-quoted-string" style-ref="multiline-string" class="string" class-disabled="no-spell-check">
      <start>\%{string-prefix}'''</start>
      <end>'''</end>
      <include>
        <context ref="format"/>
        <context ref="escaped-char"/>
      </include>
    </context>-->

    <context id="double-quoted-string" style-ref="string" end-at-line-end="true" class="string" class-disabled="no-spell-check">
      <start>\%{string-prefix}"</start>
      <end>"</end>
      <include>
        <context ref="format"/>
        <context ref="escaped-char"/>
        <context ref="def:line-continue"/>
      </include>
    </context>

    <context id="single-quoted-string" style-ref="string" end-at-line-end="true" class="string" class-disabled="no-spell-check">
      <start>\%{string-prefix}'</start>
      <end>'</end>
      <include>
        <context ref="format"/>
        <context ref="escaped-char"/>
        <context ref="def:line-continue"/>
      </include>
    </context>

    <!--<context id="multiline-double-quoted-raw-string" style-ref="multiline-string" class="string" class-disabled="no-spell-check">
      <start>\%{raw-string-prefix}"""</start>
      <end>"""</end>
      <include>
        <context ref="format"/>
      </include>
    </context>

    <context id="multiline-single-quoted-raw-string" style-ref="multiline-string" class="string" class-disabled="no-spell-check">
      <start>\%{raw-string-prefix}'''</start>
      <end>'''</end>
      <include>
        <context ref="format"/>
      </include>
    </context>-->

    <context id="double-quoted-raw-string" style-ref="string" end-at-line-end="true" class="string" class-disabled="no-spell-check">
      <start>\%{raw-string-prefix}"</start>
      <end>"</end>
      <include>
        <context ref="format"/>
        <context ref="def:line-continue"/>
      </include>
    </context>

    <context id="single-quoted-raw-string" style-ref="string" end-at-line-end="true" class="string" class-disabled="no-spell-check">
      <start>\%{raw-string-prefix}'</start>
      <end>'</end>
      <include>
        <context ref="format"/>
        <context ref="def:line-continue"/>
      </include>
    </context>

    <context id="nasal" class="no-spell-check">
      <include>
        <context ref="def:shebang"/>
        <context ref="def:shell-like-comment"/>

        <!--<context ref="multiline-double-quoted-string"/>
        <context ref="multiline-single-quoted-string"/>-->
        <context ref="double-quoted-string"/>
        <context ref="single-quoted-string"/>

        <!--<context ref="multiline-double-quoted-raw-string"/>
        <context ref="multiline-single-quoted-raw-string"/>-->
        <context ref="double-quoted-raw-string"/>
        <context ref="single-quoted-raw-string"/>

        <context id="string-conversion" style-ref="string-conversion" end-at-line-end="true">
          <start>`</start>
          <end>`</end>
          <include>
            <context ref="nasal"/>
          </include>
        </context>

        <!--<context id="special-variables" style-ref="special-variable">
          <prefix>(?&lt;![\w\.])</prefix>
          <keyword>self</keyword>
          <keyword>__name__</keyword>
          <keyword>__debug__</keyword>
        </context>-->

        <context id="boolean" style-ref="boolean">
          <prefix>(?&lt;![\w\.])</prefix>
          <keyword>false</keyword>
          <keyword>true</keyword>
        </context>

        <define-regex id="path" extended="true"><!-- matches a path inside of a string like "/path[0]/node" or "path[1]/node_now" -->
          "[/\[]\w]{0,1000}"
        </define-regex>

        <define-regex id="float" extended="true">
          ( (\d+)?\.\d+ | \d+\. ) |
          ( (\d+|(\d+)?\.\d+|\d+\.)[eE][+-]?\d+ )
        </define-regex>

        <context id="complex" style-ref="complex">
          <match>(?&lt;![\w\.])(\%{float}|\d+)[jJ]\b</match>
        </context>

        <context id="float" style-ref="floating-point">
          <match>(?&lt;![\w\.])\%{float}(?![\w\.])</match>
        </context>

        <context id="decimal" style-ref="decimal">
          <match>(?&lt;![\w\.])([1-9][0-9]*|0)[lL]?(?![\w\.])</match>
        </context>

        <context id="octal" style-ref="base-n-integer">
          <match>(?&lt;![\w\.])0[0-7]+[lL]?(?![\w\.])</match>
        </context>

        <context id="hex" style-ref="base-n-integer">
          <match>(?&lt;![\w\.])0[xX][0-9A-Fa-f]+[lL]?(?![\w\.])</match>
        </context>

        <context id="module-handler" style-ref="module-handler">
          <keyword>import</keyword>
          <keyword>from</keyword>
          <keyword>as</keyword>
        </context>

        <context id="keyword" style-ref="keyword">
          <keyword>and</keyword>
          <keyword>or</keyword>
          <keyword>var</keyword>
          <keyword>for</keyword>
          <keyword>foreach</keyword>
          <keyword>forindex</keyword>
          <keyword>elsif</keyword>
          <keyword>else</keyword>
          <keyword>if</keyword>
          <keyword>while</keyword>
          <keyword>func</keyword>
          <keyword>print</keyword>
          <keyword>return</keyword>
        </context>

        <context id="builtin-constants" style-ref="builtin-constant">
          <prefix>(?&lt;![\w\.])</prefix>
          <keyword>math.sin</keyword>
          <keyword>math.cos</keyword>
          <keyword>math.exp</keyword>
          <keyword>math.ln</keyword>
          <keyword>math.sqrt</keyword>
          <keyword>math.atan2</keyword>
          <keyword>nil</keyword>
        </context>

        <!--<context id="builtin-objects" style-ref="builtin-object">
          <prefix>(?&lt;![\w\.])</prefix>
          <keyword>ArithmeticError</keyword>
          <keyword>AssertionError</keyword>
          <keyword>AttributeError</keyword>
          <keyword>EnvironmentError</keyword>
          <keyword>EOFError</keyword>
          <keyword>Exception</keyword>
          <keyword>FloatingPointError</keyword>
          <keyword>ImportError</keyword>
          <keyword>IndentationError</keyword>
          <keyword>IndexError</keyword>
          <keyword>IOError</keyword>
          <keyword>KeyboardInterrupt</keyword>
          <keyword>KeyError</keyword>
          <keyword>LookupError</keyword>
          <keyword>MemoryError</keyword>
          <keyword>NameError</keyword>
          <keyword>NotImplementedError</keyword>
          <keyword>OSError</keyword>
          <keyword>OverflowError</keyword>
          <keyword>ReferenceError</keyword>
          <keyword>RuntimeError</keyword>
          <keyword>StandardError</keyword>
          <keyword>StopIteration</keyword>
          <keyword>SyntaxError</keyword>
          <keyword>SystemError</keyword>
          <keyword>SystemExit</keyword>
          <keyword>TabError</keyword>
          <keyword>TypeError</keyword>
          <keyword>UnboundLocalError</keyword>
          <keyword>UnicodeDecodeError</keyword>
          <keyword>UnicodeEncodeError</keyword>
          <keyword>UnicodeError</keyword>
          <keyword>UnicodeTranslateError</keyword>
          <keyword>ValueError</keyword>
          <keyword>WindowsError</keyword>
          <keyword>ZeroDivisionError</keyword>
          <keyword>Warning</keyword>
          <keyword>UserWarning</keyword>
          <keyword>DeprecationWarning</keyword>
          <keyword>PendingDeprecationWarning</keyword>
          <keyword>SyntaxWarning</keyword>
          <keyword>OverflowWarning</keyword>
          <keyword>RuntimeWarning</keyword>
          <keyword>FutureWarning</keyword>
        </context>-->

        <context id="builtin-function" style-ref="builtin-function">
          <prefix>(?&lt;![\w\.])</prefix> <!-- look behind for anything but a word or period as a prefix, e.g. a space or tab -->
          <!--<keyword>setattr</keyword>
          <keyword>getattr</keyword>-->
          <keyword>setlistener</keyword>
          <keyword>setprop</keyword>
          <keyword>getprop</keyword>
          <keyword>settimer</keyword>
          <keyword>append</keyword>
          <keyword>setsize</keyword>
          <keyword>subvec</keyword>
          <keyword>contains</keyword>
          <keyword>delete</keyword>
          <keyword>num</keyword>
          <keyword>keys</keyword>
          <keyword>pop</keyword>
          <keyword>size</keyword>
          <keyword>streq</keyword>
          <keyword>cmp</keyword>
          <keyword>sort</keyword>
          <keyword>substr</keyword>
          <keyword>sprintf</keyword>
          <keyword>find</keyword>
          <keyword>split</keyword>
          <keyword>rand</keyword>
          <keyword>typeof</keyword>
          <keyword>die</keyword>
          <keyword>call</keyword>
          <keyword>compile</keyword>
          <keyword>closure</keyword>
          <keyword>bind</keyword>
          <keyword>print</keyword>
          <keyword>fgcommand</keyword>
          <keyword>interpolate</keyword>
          <keyword>gui.Dialog.new</keyword>
          <keyword>props.Node.new</keyword>
          <keyword>props.globals</keyword>
          <keyword>props.globals.getNode</keyword>
          <keyword>props.dump</keyword>
          <keyword>bits.fld</keyword>
          <keyword>bits.sfld</keyword>
          <keyword>bits.setfld</keyword>
          <keyword>bits.buf</keyword>
          <keyword>io.open</keyword>
          <keyword>io.close</keyword>
          <keyword>io.read</keyword>
          <keyword>io.write</keyword>
          <keyword>io.seek</keyword>
          <keyword>io.tell</keyword>
          <keyword>io.readln</keyword>
          <keyword>io.stat</keyword>
          <keyword>thread.newthread</keyword>
          <keyword>thread.newlock</keyword>
          <keyword>thread.lock</keyword>
          <keyword>thread.unlock</keyword>
          <keyword>thread.newsem</keyword>
          <keyword>thread.semdown</keyword>
          <keyword>thread.semup</keyword>
          <keyword>regex.comp</keyword>
          <keyword>regex.exec</keyword>
          <keyword>readline</keyword>
        </context>

        <context id="node-object" style-ref="builtin-function">
          <prefix>(?&lt;=getNode\({path}\)\.)</prefix> <!-- look behind for getNode("[path]"). as a prefix-->
          <keyword>getType</keyword>
          <keyword>getName</keyword>
          <keyword>getIndex</keyword>
          <keyword>getValue</keyword>
          <keyword>getParent</keyword>
          <keyword>getChild</keyword>
          <keyword>getChildren</keyword>
          <keyword>removeChild</keyword>
          <keyword>setValues</keyword>
          <keyword>setDoubleValue</keyword>
          <keyword>setIntValue</keyword>
          <keyword>setBoolValue</keyword>
          <keyword>setValue</keyword>
          <keyword>setValues</keyword>
        </context>
      </include>
    </context>
  </definitions>
</language>

If you use Mac, move it into your Applications/gedit/Contents/Resources/share/gtksourceview-2.0/language specs folder. And for linux, move it into your /usr/share/gtksourceview-X.0/language specs folder.

Vim

It also makes understanding other people's code easier. One such editor is the free vim or its gui variant gvim.

It's not for everyone but it's free, and testing it doesn't hurt: http://www.vim.org/.

The syntax definition file comes with the FlightGear code (http://gitorious.org/fg/flightgear/blobs/next/scripts/syntax/nasal.vim). Highlighting works even for Nasal embedded in XML files (type ":set ft=nasal", where ft stands for file-type)

Here's an example, which demonstrates a short code segment with three syntax errors as well as the highlighting of a matching pair of parentheses (yellow) and trailing spaces (blue x). (The leading blue dots aren't on by default. They help to spot tab crimes.)

Screen shot illustrating syntax highlighting in Vim

Other editors

Nasal being syntactically very close to other programming languages like C, Php or JavaScript, you can get some usable highlighting even without real Nasal support:

  • TextMate [1]
  • SciTe [2]
  • gEdit (Linux) : Using the 'Octave' highlighting mode, most of the nasal functions work.

FlightGear Wiki

A common approach in code examples on the wiki is to use php syntax highlighting beween <syntaxhighlight>:

<syntaxhighlight lang="php">
# hello.nas
print('Hello World!');
</syntaxhighlight>

Which renders into:

# hello.nas
print('Hello World!');

Related