proc pipedata {data args} { #puts stderr "'$args'" set r $data for {set i 0} {$i < [llength $args]} {incr i} { set e [lindex $args $i] if {[catch {llength $e} seglen]} { #not a list - assume script and run anyway set r [apply [list {data} $e] $r] } else { if {[llength $e] == 1} { if {$e eq {>}} { #output to calling context. only pipedata return value and '> varname' should affect caller. incr i uplevel 1 [list set [lindex $args $i] $r] } elseif {$e in {% pipematch ispipematch}} { incr i set e2 [lindex $args $i] #set body [list $e {*}$e2] #append body { $data} set body [list $e {*}$e2] append body { {*}$data} set applylist [list {data} $body] #puts stderr $applylist set r [apply $applylist $r] } elseif {$e in [list pipeswitch pipeswitchc]} { #pipeswitch takes a script not a list. incr i set e2 [lindex $args $i] set body [list $e $e2] #pipeswitch takes 'args' - so expand $data when in pipedata context append body { {*}$data} #use applylist instead of uplevel when in pipedata context! #can use either switchdata/data but not vars in calling context of 'pipedata' command. #this is consistent with pipeswitch running in a % / .= pipeline which can only access vars in immediate calling context. set applylist [list {data} $body] #puts stderr $applylist set r [apply $applylist $r] } else { #puts "other single arg: [list $e $r]" append e { $data} set r [apply [list {data} $e] $r] } } else { set r [apply [list {data} $e] $r] } } } return $r } set s " supercalifragilistichespiralitoso " pipedata $s {string trim $data} {split $data {}} {lsort -unique $data} {join $data {}} > s \ {string length $data} > l puts $s puts $l #test running of patternmatching pipelines within pipe* set x [list a b blah etc] puts "-1" pipedata $x {,'a'@0/0= |@0> {puts $data; set data} <| $data} {val $data} puts "-2" pipedata $x {,'a'@0/0= |@0> { puts $data set data } <| $data} {val $data} pipeset pipe1 ,'a'@0/0= |/0-1> {puts $data; set data} |> string toupper <| puts "-3" pipedata $x pipematch $pipe1