TABLE OF CONTENTS


::pwtk::redirect

SYNOPSIS

proc ::pwtk::redirect {args} {

USAGE

   redirect ?stdout? ?stderr? script 
   redirect ?stderr? ?stdout? script

DESCRIPTION

Redirect printing to stdout/stderr to a return value.

Inspired by:

      https://wiki.tcl-lang.org/page/puts+workaround
      https://stackoverflow.com/questions/8531031/how-can-i-redirect-stdout-into-a-file-in-tcl

ARGUMENTS

RETURN VALUE

A return value of the script.

SOURCE

    global pwtk_redirect_channels_  pwtk_redirect_result_

    set pwtk_redirect_result_ {}    
    set pwtk_redirect_channels_ {}
    set len [llength $args]

    lassign $args arg1 arg2 arg3
    
    if { $len == 1 } {
        set pwtk_redirect_channels_ stdout
        set script $arg1
    } elseif { $len == 2 } {
        switch $arg1 {
            stdout - stderr {
                set pwtk_redirect_channels_ $arg1
            } default {
                ::pwtk::error "wrong channel '$arg1', must be stdout or stderr" 1
            }
        }
        set script $arg2
    } elseif { $len == 3 } {
        foreach arg [list $arg1 $arg2] {
            switch $arg {
                stdout - stderr {
                    lappend pwtk_redirect_channels_ $arg
                } default {
                    ::pwtk::error "wrong channel '$arg', must be stdout or stderr" 1
                }
            }
        }
        set script $arg3
    } else {
        ::pwtk::error "wrong # of args, must be redirect ?stdout? ?stderr? script" 1
    }
    
    rename puts ::tcl::orig_puts

    proc ::puts {args} {
        global pwtk_redirect_channels_ pwtk_redirect_result_
        
        set nargs [llength $args]        
        if {$nargs<1 || $nargs>3} {
            ::error "wrong # args: should be \"puts ?-nonewline? ?channelId? string\""
        }

        set nl \n
        if { [lindex $args 0] == "-nonewline" } {
            set nl {}
            set args [lrange $args 1 end]
        }

        if { [llength $args] == 1 } {
            set args [list stdout [join $args]]
        }

        set channel [lindex $args 0]
        set string  [lindex $args 1]

        if { $channel in $pwtk_redirect_channels_ } {
            append pwtk_redirect_result_ ${string}$nl
        } else {
            ::tcl::orig_puts $channel ${string}$nl
        }
    } 

    uplevel $script

    set result $pwtk_redirect_result_
    unset pwtk_redirect_result_

    rename ::puts {}
    rename ::tcl::orig_puts ::puts

    return $result
}