Updated 2011-01-25 02:45:48 by RLE

* Purpose: Progress meter for Tcl scripts

I am creating this page because I don't find one like it but certainly there should be an interest. While the below example works somewhat, I am sure that the more experienced coders can come up with better.

The "spinner" component spins upon each loop providing an indication that the program is working, while the percent meter indicates the entire progress of work being done.

MT Ok, below is what I feel is a workable solution to my original idea but I'd like to see more.
 proc dummy {args} {
   # your code here instead of a delay
   if {$args != "dummyargs"} {
     puts "\nFailed"
     exit
   }
   after 100
   return
 }
 # Tcl progressMeter by Mike Tuxford
 proc progressMeter {i args} {
   set c 0
   set spincnt 0
   array set spinner {0 "/" 1 "-" 2 "\\" 3 "|"}
   while {$c < $i} {
     [lindex $args 0] [lrange $args 1 end]
     if {$spincnt == 3} {
       set spincnt 0
     } else {
       incr spincnt
     }
     incr c
     set p [expr int(($c / $i.0) * 100)]
     puts -nonewline stdout "  $spinner($spincnt)\[$p%\][string repeat \b 8]"
     flush stdout
   }
   puts "\bDone!    "
   return
 }
 # Syntax: progressMeter <number of loops> <proc> ?args?
 progressMeter 123 dummy dummyargs

SC Here's another one which is used as a callback, more like the various tk callback widgets. The original author is Kris Raney I believe.
 # text_progress --
 #
 #    progress callback for a download or other piece of work
 #
 # Arguments:
 #   total      expected total size/duration
 #   current    current size/duration
 # Results:
 #   Displays progress information in some way to the user.
 #
 #   this version culled from Kris Raney's text_progress
 #
 proc text_progress {totalsize current} {

    puts -nonewline "\r  |"

    if {$totalsize == 0} {
        set totalsize $current
    }

    set portion [expr 1.0 * $current/$totalsize * 40]

    for {set x 0} {$x <= $portion} {incr x} {
        puts -nonewline "="
    }

    for {} {$x <= 40} {incr x} {
        puts -nonewline " "
    }
    puts -nonewline "| [format "%3d" [expr int(100.0 * $current/$totalsize)]] %"
    flush stdout
    if {$totalsize == $current} {
        puts "\ndone"
    }
 }

 ## test code

 for {set i 0} {$i < 100} {incr i} {
   text_progress 100 $i
   after 100
 }

MT That's an interesting one although for values less than or greater than 100 it leaves the final percentage as less than 100% but certainly usable as is.