Version 9 of pdict: Pretty print a dict

Updated 2010-07-14 22:21:06 by tomk

I couldn't find a quick way to print a dict item when I was debugging some code so I wrote this pretty printer. Enjoy...tjk


# -- pdict
#
# Pretty print a dict similar to parray.
#
# USAGE:
#
#   pdict d [i [p [s]]]
#
# WHERE:
#  d - dict to be printed
#  i - indent level
#  p - prefix string for one level of indent
#  s - separator string between key and value
#
# EXAMPLE:
# % set d [dict create a {1 i 2 j 3 k} b {x y z} c {i m j {q w e r} k o}]
# a {1 i 2 j 3 k} b {x y z} c {i m j {q w e r} k o}
# % pdict $d
# a ->
#   1 -> 'i'
#   2 -> 'j'
#   3 -> 'k'
# b -> 'x y z'
# c ->
#   i -> 'm'
#   j ->
#     q -> 'w'
#     e -> 'r'
#   k -> 'o'
#
proc pdict { d {i 0} {p "  "} {s " -> "} } {
    if { [catch {dict keys ${d}}] } {
        error "error: pdict - argument is not a dict"
    }
    set prefix [string repeat ${p} ${i}]
    set max 0
    foreach key [dict keys ${d}] {
        if { [string length ${key}] > ${max} } {
            set max [string length ${key}]
        }
    }
    dict for {key val} ${d} {
        puts -nonewline "${prefix}[format "%-${max}s" ${key}]${s}"
        if { [catch {dict keys ${val}}] } {
            puts "'${val}'"
        } else {
            puts ""
            pdict ${val} [expr ${i}+1] ${p} ${s}
        }
    }
}

LV I wonder if something like this should be included in the same place that parray is located in the Tcl distribution...

Lars H, 2010-06-01: That reminds me… two years ago (I think it was) I wrote a package to a similar end that I was going to put in tcllib, but I got sidetracked somewhere late in the wrapping up process (probably something about the tests). Anyway, since the issue is up, I might as well put it on the wiki: exhibit.


kpv this fails for me when the value has a space in it. Try

  pdict [dict create name "keith vetter"]

TK the result is

name -> 
  keith -> 'vetter'

which feels like an error but isn't. The problem here is that there isn't any way to distinguish between a value that is a dict and a value that is an even number of tcl words. In your example you provided an even number of tcl words as the value to name and the print code descend into any value that looks like a dict.