TABLE OF CONTENTS


::pwtk::redirect_stdout_to

SYNOPSIS

proc ::pwtk::redirect_stdout_to {filename script} {

DESCRIPTION

Redirect stdout and stderr to a file and also print stderr to stderr.

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

An empty string, just like the Tcl puts command.

SOURCE

    global pwtk_redirect_channel_

    # 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
    
    rename puts ::tcl::orig_puts
    set pwtk_redirect_channel_ [open $filename w]

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

        set nl {}
        if { [lindex $args 0] == "-nonewline" } {
            set nl -nonewline
            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 == "stdout" } {
            set channel $pwtk_redirect_channel_
        } elseif { $channel == "stderr" } {
            # print to stderr & $pwtk_redirect_channel_
            set channel [list stderr $pwtk_redirect_channel_]
        }
        foreach ch $channel {
            eval ::tcl::orig_puts $nl $ch [list $string]
            flush $ch
        }
        return
    }    

    uplevel $script    

    close $pwtk_redirect_channel_
    rename ::puts {}
    rename ::tcl::orig_puts ::puts
}