Version 6 of Reformatting Tcl code indentation

Updated 2008-04-05 17:55:06 by nem

Sarnold introduces here a script that provides this feature.

It works either as a command-line tool :

 tclsh reformat.tcl ?-indent number? myfile.tcl

and as a Tcl proc :

 source reformat.tcl
 set out [reformat $code]

Sarnold on 2008-04-05 : I fixed a bug that caused duplicating newlines. The -unixnl option was removed because of that bug. I added the -indent option to specify the number of blanks of the indentation.

NEM Could you describe what it does, exactly? Is it a pretty-printer for Tcl source code?


reformat.tcl

proc reformat {tclcode {pad 4}} {
    set lines [split $tclcode \n]
    set out ""
    set continued no
    set oddquotes 0
    set line [lindex $lines 0]
    set indent [expr {([string length $line]-[string length [string trimleft $line \ \t]])/$pad}]
    set pad [string repeat " " $pad]
    
    foreach orig $lines {
        set newline [string trim $orig \ \t]
        set line [string repeat $pad $indent]$newline
        if {[string index $line end] eq "\\"} {
            if {!$continued} {
                incr indent 2
                set continued yes
            }
        } elseif {$continued} {
            incr indent -2
            set continued no
        }
        # oddquotes contains : 0 when quotes are balanced
        # and 1 when they are not
        set oddquotes [expr {([count $line \"] + $oddquotes) % 2}]
        if {! $oddquotes} {
            set  nbbraces  [count $line \{]
            incr nbbraces -[count $line \}]
            set brace   [string equal [string index $newline end] \{]
            set unbrace [string equal [string index $newline 0] \}]
            if {$nbbraces>0 || $brace} {
                incr indent
            }
            if {$nbbraces<0 || $unbrace} {
                incr indent -1
                if {$indent<0} {
                    error "unbalanced braces"
                }
                set line [string range $line [string length $pad] end]
            }
        } else {
            # unbalanced quotes, preserve original indentation
            set line $orig
        }
        append out $line\n
    }
    return $out
}

proc eol {} {
    switch -- $::tcl_platform(platform) {
        windows {return \r\n}
        unix {return \n}
        macintosh {return \r}
        default {error "no such platform: $::tc_platform(platform)"}
    }
}

proc count {string char} {
    set count 0
    while {[set idx [string first $char $string]]>=0} {
        set backslashes 0
        set nidx $idx
        while {[string equal [string index $string [incr nidx -1]] \\]} {
            incr backslashes
        }
        if {$backslashes % 2 == 0} {
            incr count
        }
        set string [string range $string [incr idx] end]
    }
    return $count
}

set usage "reformat.tcl ?-indent number? filename"

if {[llength $argv]!=0} {
    if {[lindex $argv 0] eq "-indent"} {
        set indent [lindex $argv 1]
        set argv [lrange $argv 2 end]
    } else  {
        set indent 4
    }
    if {[llength $argv]>1} {
        error $usage
    }
    set f [open $argv r]
    set data [read $f]
    close $f
    set f [open $argv w]
    puts -nonewline $f [reformat [string map [list [eol] \n] $data] $indent]
    close $f
}

Category Dev. Tools