| What | '''tcl-augeas''' | | Where | https://github.com/dbohdan/tcl-augeas | | Description | A binary Tcl [extension] that provides bindings for the [Augeas] configuration editing tool. | | Platforms | Linux, FreeBSD, OpenBSD. | | Prerequisites | Tcl 8.5 or newer, Augeas 0.10 or newer. | | Updated | 2015-04-10 | | License | MIT | Includes a [https://github.com/dbohdan/tcl-augeas/blob/master/build.tcl%|%build script] that uses values from [tcl::pkgconfig] to build and install the extension in a way that works on across several different Linux distributions as well as on FreeBSD and OpenBSD. ** Sample code ** ====== package require augeas set id [::augeas::init /] foreach x [::augeas::match $id {/files/etc/hosts/*}] { set ipaddr [::augeas::get $id $x/ipaddr] set hostname [::augeas::get $id $x/canonical] puts [format %-30s%s $hostname $ipaddr] } ::augeas::close $id ====== On the default installation of [Fedora] 21 with no extra hosts added this produces the output of ====== localhost.localdomain 127.0.0.1 localhost6.localdomain6 ::1 ====== ** Dung Fork ** [chw] 2016-07-11: verrry versatile! Couldn't resist to make a little regedit like read-only toy and call it "Dung Fork" in memory of King Augeias, maybe an acronym for "All Useful Garbage Extracted Is A String". Warning however: on my CentOS 6 system opening /files/etc/services takes centuries but this certainly isn't Tcl's fault. [dbohdan] 2016-07-12: Cool stuff! You could grow a configuration management GUI tool on top of it if you let the user edit the values, record his actions and spit out Augeas or Tcl + tcl-augeas scripts. domcleal 2016-07-12: @chw, the /etc/services performance ought to be a lot better in Augeas 1.5.0 which contains some optimisations for iterating and calling aug_get on every entry. [chw] 2016-07-12: @domcleal, yes that's exactly my observation, too. CentOS 6 is at Augeas 1.0, but Ubuntu 16.04 is at 1.2.0 which is an order of magnitude faster. @dbohdan: thanks for this useful invention. Please review my somewhat changed tcl-augeas variant which I gladly integrated into [undroidwish], the source code is in http://www.androwish.org/index.html/dir?name=undroid/tcl-augeas *** Screenshot *** [Dung Fork.png] *** Code *** ====== # Dung Fork -- use augeas to browse system info from /etc etc # 0.1.0 package require augeas set ::AUG [augeas::init /] set ::ABORT 0 array set ::AUGCACHE {} proc treeview_focus {w} { if {![::tk::FocusOK $w]} return set item [$w focus] if {$item eq ""} { catch { set item [lindex [$w children {}] 0] $w focus $item $w see $item ttk::treeview::select.choose.browse $w $item } } } ttk::style configure Treeview -rowheight \ [expr {[font metrics TkDefaultFont -linespace] + 4}] bind Treeview {treeview_focus %W} proc augeas_match pat { if {[info exists ::AUGCACHE($pat)]} { return $::AUGCACHE($pat) } set ::AUGCACHE($pat) [augeas::match $::AUG $pat] } proc fill_roots {tree} { set ::ABORT 0 foreach dir [lsort -dictionary [augeas::match $::AUG /*]] { fill_tree $tree [$tree insert {} end -text $dir \ -values [list $dir {} "directory"]] } } proc fill_tree {tree node {open 0} {dobusy 1}} { if {![string match "*irectory" [$tree set $node type]]} return if {$open < 0} { $tree item $node -open 0 return } # already processed? if {[$tree set $node type] ne "directory"} return if {$dobusy} { set count0 0 set ::ABORT 0 catch {tk busy hold .} update set oldfocus [focus] catch { focus ._Busy bind ._Busy {set ::ABORT 1} bind ._Busy break } upvar 0 count0 count } else { upvar 1 count0 count } set path [$tree set $node fullpath] $tree delete [$tree children $node] set list {} set toopen {} set list [lsort -dictionary [augeas_match "$path/*"]] foreach f $list { if {[catch {augeas::get $::AUG $f} data]} continue set sublist [augeas_match $f/*] if {[llength $sublist]} { set id [$tree insert $node end -text [file tail $f] \ -values [list $f $data "directory"]] # make this node openable $tree insert $id 0 -text dummy ;# a dummy if {$open > 0} { lappend toopen $id } } else { set id [$tree insert $node end -text [file tail $f] \ -values [list $f $data "file"]] } incr count if {$count > 100} { set count 0 update } if {$::ABORT} break } if {!$::ABORT} { # stop from rerunning on the current node $tree set $node type "processedDirectory" } if {($open > 0) && [llength $list]} { $tree item $node -open 1 } foreach id $toopen { fill_tree $tree $id $open 0 } if {$dobusy} { focus $oldfocus catch {tk busy forget .} set ::ABORT 0 } } proc dung_fork {} { wm title . "Dung Fork" ttk::treeview .tree -columns {fullpath value type} -displaycolumns value \ -yscroll [list .scroll set] -selectmode browse -show {headings tree} ttk::scrollbar .scroll -orient vertical -command [list .tree yview] .tree heading \#0 -text Path .tree heading value -text Value bind .tree <> {fill_tree %W [%W focus]} bind .tree <> {fill_tree %W [%W focus] -1} grid .tree -row 0 -column 0 -sticky nsew grid .scroll -row 0 -column 1 -sticky ns grid columnconfigure . 0 -weight 1 grid rowconfigure . 0 -weight 1 fill_roots .tree } dung_fork ====== <>Package