- determine the whitespace prefix of the current line
- insert the prefix on the next line
- if the current line ended in "{", indents one layer more
- and creates the matching "}" line after the insert point.
proc e'indent {w {extra " "}} { set lineno [expr {int([$w index insert])}] set line [$w get $lineno.0 $lineno.end] regexp {^(\s*)} $line -> prefix after 1 [list $w insert insert $prefix] if {[string index $line end] eq "\{"} { after 2 [list $w insert insert $extra] after 3 [list $w insert insert+1c $prefix\}\n] } }#-- Testing demo:
pack [text .t] .t insert end \n ;#-- see below bind .t <Return> {e'indent %W} focus -force .t bind . <Escape> {exec wish $argv0 &; exit} bind . <F1> {console show}if 0 {Known problem: if the insert cursor is at the very end of the text, "insert+1c" delivers the same position as "insert", leading to wrong indentation on open-brace. I haven't found a good solution for that. But it rarely happens when editing existing text, and in an empty text widget, just type one newline and <Up> to avoid this problem.2006-03-20 HE I would use this version;-)
proc e'indent {w {extra " "}} { set lineno [expr {int([$w index insert])}] set line [$w get $lineno.0 $lineno.end] regexp {^(\s*)} $line -> prefix tk::TextInsert $w "\n$prefix" if {[string index $line end] eq "\{"} { tk::TextInsert $w "$extra" } }Or considering the close braces:
proc e'indent {w {extra " "}} { set lineno [expr {int([$w index insert])}] set line [$w get $lineno.0 $lineno.end] regexp {^(\s*)} $line -> prefix if {[string index $line end] eq "\{"} { tk::TextInsert $w "\n$prefix$extra" } elseif {[string index $line end] eq "\}"} { if {[regexp {^\s+\}} $line]} { $w delete insert-[expr [string length $extra]+1]c insert-1c tk::TextInsert $w "\n[string range $prefix 0 end-[string length $extra]]" } else { tk::TextInsert $w "\n$prefix" } } else { tk::TextInsert $w "\n$prefix" } }The corresponding binding is:
bind .t <Return> {e'indent %W;break}We don't need the row '.t insert end \n' anymore.
See also Maintaining indentation in a text widget when go to a new line
}