NOTE: Please improve this list!

Dear (new) GRASS Developer,

When submitting TCL and TK SCRIPTS and C code to GRASS CVS repository,
please take care of following rules:

[ see SUBMITTING for C code hints ]
[ see SUBMITTING_SCRIPTS for shell script hints ]

1.  Use the directory structure to place your program appropriately into
    the source tree
        - general grass tcl/tk libraries and reusable code go into lib/gtcltk
        - user interfaces go in gui/tcltk
        - scripts go in scripts/
            Programs here must have a proper Makefile and description.html
 
2.  Add a header section to the script you submit and make sure you include
    the copyright. The purpose section is meant to contain a general
    overview of the code in the file to assist other programmers that will
    need to make changes to your code.

    Example (fictitious header for a script called r.myscript) :

############################################################################
#
# MODULE:       r.myscript
# AUTHOR(S):    Me <email AT some domain>
# PURPOSE:      Calculates univariate statistics from a GRASS raster map
# COPYRIGHT:    (C) 2005 by the GRASS Development Team
#
#               This program is free software under the GNU General Public
#               License (>=v2). Read the file COPYING that comes with GRASS
#               for details.
#
#############################################################################

    The copyright protects your rights according to GNU General Public
    License (www.gnu.org).

3.  PLEASE take the time to add comments throughout your code explaining what
    the code is doing. It will save a HUGE amount of time and frustration for
    other programmers that need to change or understand your code in the future.
    Many of the programmers working on grass are not heavily invested in tcl
    and tk, so extra documentation and explanation are greatly appreciated.

4.  Test your program with both tcl/tk 8.3 and tcl/tk 8.4.

5.  Always use the gettext macros with [G_msg "..."] for user messages.
    The string must be quoted using quotation marks, not braces, for
    xgettext to find it. The string cannot include variable ($) or
    command ([...]) substitutions. If you need substitutions use
    [format ...].

    Examples:
    button .ok -text [G_msg "Ok"]

    set statusbartext [format [G_msg "Monitor %d running"] $monitor_number]]

    Use positional parameters if substitutions might be rearranged in another language:

    format [G_msg "We produced %1\$d units in location %2\$s"] $num $city
    format [G_msg "In location %2\$s we produced %1\$d units"] $num $city

6.  Use "GRASS_TCLSH" and "GRASS_WISH" environment variables instead of
    "tclsh" and "wish" at the start of Tcl/Tk scripts. This allows users to
    override the default names, so that developers don't need worry about the
    shell names.

    Tcl script:

    	#!/bin/sh
	# the next line restarts using tclsh \
	exec $GRASS_TCLSH "$0" "$@"


    Tk script:

    	#!/bin/sh
	# the next line restarts using wish \
	exec $GRASS_WISH "$0" "$@"

7.  Do not source files that have already been sourced.

        gui.tcl sources:
            options.tcl 
            select.tcl
            gronsole.tcl

    If your code requires something to be sourced before it note so
    in a comment at the top of the file.

8.  Set tabstops in your editor to 8 spaces.
    When modifying files use the indentation style that is already present.
    Please use consistent indentation style in your new code. Whether you use
    tabs or spaces to indent please be consistent. Where tabs and spaces are
    mixed please remember that a tab is 8 spaces.

9.  Use the tk options database to control the appearance of your user interface.
    In general do not set options on tk widgets unless that option is truly
    specific to that widget. It makes them harder to customize.

    Example: Don't set options like -foreground or -background or -font
    when creating widgets, unless there's a really _really_ specific reason to
    have it that color (like it's demonstrating that color).

    If you want something like a label to look different than everything else
    of that class (other labels) give it a distinctive name, like
    .moduletitlelabel . If you have a bunch of them give them all the same 
    distinctive name. This allows them to have their options controlled by the 
    options database.

    You can put your options at the start of your script (before creating any
    widgets) like this:
    option add *modultitlelabel.background red
    More examples are in lib/gtcltk/options.tcl

    Many common options, like font, background and foreground colors,
    highlighting, scrollbar colors, and help bubble appearance are controlled
    by options.tcl. You can include it at the start of your script with:
    source $env(GISBASE)/etc/gtcltk/options.tcl

10. Avoid using global variables. Thay are a frequent source of bugs, make code
    harder to understand, and make your program difficult to reuse. Additionally,
    putting code into procs usually makes it run faster (it gets compiled).

11. For consistency, use README rather than README.txt for any README files.

12. Use of GRASS commands in shell wrapper.

    Any GRASS program run in an xterm (those which do interactive query) needs
    to use grass-run.sh, e.g.:

    exec -- $env(GISBASE)/etc/grass-xterm-wrapper -e $env(GISBASE)/etc/grass-run.sh g.proj ...

    You should probably also use "-T g.proj -n g.proj" to set the title
    back (otherwise it will be "grass-run.sh", which isn't particularly
    informative).

    The xterm will close as soon as the command completes (whether it
    succeeds or fails). You can use the -hold switch to retain the xterm
    window after the command completes, but you should only do that for
    debugging; having to manually close the xterm window each time would
    be annoying in normal use. Alternatively, redirect stdout/stderr to a
    file, to catch any error messages.

13. Be sure to develop on top of the LATEST GRASS code (which is in CVS).
    You can re-check before submission with 'cvs diff':

    Be sure to create unified ("diff -u") format. "Plain"
    diffs (the default format) are risky, because they will apply without
    warning to code which has been substantially changed; they are also
    harder to read than unified.

    Such diffs should be made from the top-level directory, e.g.
    "cvs diff -u display/d.vect/main.c"; that way, the diff will
    include the pathname rather than just "main.c".

14. Tell the other developers about the new code using the following e-mail:
    grass-dev@grass.itc.it
 
    To subscribe to this mailing list, see
    http://grass.itc.it/devel/index.php

15. In case of questions feel free to contact the developers at the above
    mailing list.
    http://grass.itc.it/devel/index.php#submission

16. Try to evaluate things only once. Tcl compiles the program to bytecode which
    can be interpreted fairly quickly. If there are strings that must still be
    evaluated tcl must parse and either compile or interpret them
    each time they are encountered. In general this means put braces around
    expressions and especially regular expressions (Tcl also compiles regular
    expressions). Multiple evaluation can also lead to bugs.

    Expressions via expr command:
    Slow:
        set y [expr $a * $x + $b]
    Fast:
        set y [expr {$a * $x + $b}]

    Expressions in conditions:
    Slow:
        if [...] {...
    Fast:
        if {[...]} {...

    Regular expressions:
    Very slow:
        regex "x(\[0-9\]+).*not" $string trash number
    Fast:
        regex {x([0-9]+).*not} $string trash number

    If you really want speed:
    If a regular expression needs to be constructed from variables but used
    multiple times store it in a variable that will not be destroyed or
    changed between reuse. Tcl stores the compiled regex with the variable.

17. You might want to decompose lists in a somewhat easy way:

    Difficult and slow:
    # Make x1 y1 x2 y2 the first four things in the list
    set list [commandMakesList]
    set x1 [lindex $list 0]
    set y1 [lindex $list 1]
    set x2 [lindex $list 2]
    set y2 [lindex $list 3]

    Easier and faster:
    # Make x1 y1 x2 y2 the first four things in the list
    foreach {x1 y1 x2 y2} [commandMakesList] {break}

    Be sure to include a comment as to what you are doing.

18. Use the Tcl list functions (list, lappend etc) for manipulating lists.

    For example, use:

        set vals [list $foo $bar]

    rather than:

        set vals "$foo $bar"

    The former will always create a list with two elements, adding braces
    if necessary, while the latter will split $foo and $bar into multiple
    elements if they contain spaces. Additionally the first is faster
    because tcl is not internally converting between strings and lists.

    A related issue is to remember that command lines (as used by exec and
    open "|...") are lists. exec behaves like execl(), spawnl() etc, and
    not like system().

    Overlooking either of these points is likely to result in code which
    fails when a command argument contains a space.

19. Tcl C library:
    Memory allocated with Tcl_Alloc (such as the result of Tcl_Merge)
    must be freed with Tcl_Free. This means that the ->freeProc of
    an interpreter when returning a string using Tcl_Merge should be
    TCL_DYNAMIC. Incorrectly freeing memory with glibc free will
    cause segfaults in Tcl 8.4 and later.

...
[please add further hints if required]
