parsing Mac OS X preferences using the 'defaults' command

On Mac OS X, you can easily read and write to the preference .plist files using the 'defaults' command. I didn't find anything on parsing the results in Tcl, so I quickly wrote up a script to parse an array of filenames like you'd use to store a "Recent Files" list.

set domain "recentfilestext"
set key "recentfiles"

catch {exec defaults write $domain $key -array patch.pd another.pd "file with spaces.txt" "file, with,commas.pd" oneword.txt anotherpatch.pd}

if {![catch {exec -- defaults read $domain $key} arr]} {
    puts "arr $arr"
    set filelist $arr
    regsub -all -- {",\s+"} $filelist {" "} filelist
    regsub -all -- {\n} $filelist {} filelist
    regsub -all -- {^\(} $filelist {} filelist 
    regsub -all -- {\)$} $filelist {} filelist
    puts "filelist: $filelist"
    foreach file $filelist {                                                                                           
        puts "file: $file"                                                                                             
    }                                                                                                                  
}

Or something more like a library:

#!/usr/bin/tclsh

proc defaults_delete {domain key} {
    if {[catch {exec defaults delete $domain $key} errorMsg]} {
        puts stderr $errorMsg
    }
}

proc defaults_write {domain key value} {
    if {[catch {exec defaults write $domain $key $value} errorMsg]} {
        puts stderr $errorMsg
    }
}

proc defaults_write_array_add {domain key arrayElement} {
    if {[regexp -- {[\(\)\{\}]} $arrayElement match]} {
        set arrayElement '$arrayElement'
    }
    if {[catch {exec defaults write $domain $key -array-add "$arrayElement"} errorMsg]} {
        puts stderr "ERROR: defaults_write_array_add $domain $key: $errorMsg"
    }
}

proc defaults_read {domain key} {
    if {![catch {exec -- defaults read $domain $key} arr]} {
        set filelist $arr
        regsub -all -- {",\s+"} $filelist {" "} filelist
        regsub -all -- {\n} $filelist {} filelist
        regsub -all -- {^\(} $filelist {} filelist 
        regsub -all -- {\)$} $filelist {} filelist
        regsub -all -- {^\s+} $filelist {} filelist
        regsub -all -- {\s+$} $filelist {} filelist
        return $filelist
    }
}

proc create_test_data {domain key} {
    set filenames {patch.pd another.pd "file with spaces.txt" "file, with,commas.pd" \
                  oneword.txt anotherpatch.pd "file with (parens).mov"}
    foreach filename $filenames {
        defaults_write_array_add $domain $key $filename
    }
}

set domain "testy"
defaults_delete $domain recentfiles
defaults_read $domain recentfiles
create_test_data $domain recentfiles
defaults_write $domain singlekey "single value"
puts "singlekey = [defaults_read $domain singlekey]"
puts "recentfiles = [defaults_read $domain recentfiles]"
foreach filename [defaults_read $domain recentfiles] {
    puts "\tfile: $filename"
}