Sarnold 2010-Mar-14 Updated 2010-Jun-15: Here is a tool to manipulate column-separated text. It can split, join, trim data. It can put strings between double-quotes for export to CSV format.
Discussion
GWL 2010-Jun-18: What is the advantages of this code over the CSV package in TclLib?
Sarnold 2010-Jun-21: It is a small GUI app, not a code library, so nothing comparable.
#!/usr/bin/env wish
package require Tcl 8.5
package require Tk 8.5
package require Ttk
set SEP tab
set DLG() ""
proc FieldList {} {list space " " tab \t , , \; \; | | - -}
proc FieldSep {} {dict get [FieldList] $::SEP}
proc SplitFilter {txt split} {lfilter [split $txt $split] ""}
proc Dialog {cmd args} {
global DLG
foreach {name title def} $args {
set fr .dlg.$name
pack [frame $fr]
set DLG($name) $def
pack [label $fr.lbl -text $title] [entry $fr.in -textvariable ::DLG($name)] -side left
}
pack [button .dlg.ok -text OK -command [list Confirm $cmd]] [button .dlg.cancel -text Cancel -command Confirm]
}
proc Confirm {{cmd ""}} {
destroy .dlg
pack [frame .dlg]
eval $cmd
array unset ::DLG *
}
proc Cons {} {
option add *frame.background #EEEEEE
pack [text .txt -width 80 -height 15 -background #FFFFFF]
pack [frame .bt]
pack [frame .dlg]
button .clr -text Clear -command Clear
button .str -text Quote -command Stringify
button .keep -text Keep -command {Dialog Keep fst "Keep first elements" 1 last "Keep last elements" 0}
button .trim -text Trim -command {Dialog Trim trim "Chars to trim" <>}
button .join -text "Join lines" -command {Dialog Joinlines}
button .joinfield -text "Join fields" -command {Dialog Joinfields fst "First element" 0 snd "Last element" 1 join "Join with" ""}
label .lbl -text "Separator:"
ttk::combobox .sep -values [dict keys [FieldList]] -textvariable ::SEP -width 8
pack .clr .str .keep .trim .lbl .sep .join .joinfield -in .bt -side left
}
proc Joinlines {} {
PutLines [list [Join [Textlines]]]
}
# stringify a string
proc Stringify-elt elt {
if {[llength [split $elt]]==1} {return $elt}
return \"[string map {\" '} $elt]\" ;# " keep emacs Happy
}
# stringify a line
proc Stringify-line line {
Join [Lmap [Split $line] Stringify-elt]
}
# stringify everything
# to use data as CSV for export to a spreadsheet like MS Excel
proc Stringify {} {
PutLines [Lmap [Textlines] Stringify-line]
}
proc Joinfields {} {
global DLG
set first $DLG(fst)
set second $DLG(snd)
set res ""
foreach line [Textlines] {
set linelst [Split $line]
lappend res [Join [lreplace $linelst $first $second [JoinSpace [lrange $linelst $first $second] $DLG(join)]]]
}
PutLines $res
}
proc JoinSpace {lst j} {
if {$j eq ""} {join $lst} else {join $lst $j}
}
proc Keep {} {
global DLG
set first $DLG(fst)
set last $DLG(last)
set res ""
foreach line [Lmap [Textlines] Split] {
lappend res [Join [concat [First $line $first] [Last $line $last]]]
}
PutLines $res
}
proc Split {line} {split $line [FieldSep]}
proc Join lst {join $lst [FieldSep]}
proc Trim {} {
global DLG
set res ""
foreach line [Textlines] {
lappend res [Join [Lmap [Split $line] [list TrimWord $DLG(trim)]]]
}
PutLines $res
}
proc TrimWord {sep word} {string trim $word $sep}
proc Lmap {lst cmd} {
set res ""
foreach elt $lst {
lappend res [{*}$cmd $elt]
}
set res
}
proc First {lst n} {
if {[llength $lst]<$n} {
return $lst
}
lrange $lst 0 [incr n -1]
}
proc Last {lst n} {
if {[llength $lst]<$n} {
return $lst
}
lrange $lst end-[incr n -1] end
}
proc Textlines {} {
SplitFilter [Gettext] \n
}
proc PutLines {lst} {
set txt [join $lst \n]
.txt delete 1.0 end; .txt delete end
.txt insert 1.0 $txt
}
proc Clear {} {
.txt delete 1.0 end; .txt delete end
}
proc Gettext {} {
set t [.txt get 1.0 end]
append t [.txt get end]
}
proc lfilter {list tofilter} {
set res ""
foreach l $list {if {$l ne $tofilter} {lappend res $l}}
set res
}
Cons
wm title . "Textjam v0.3"