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, NetBSD, OpenBSD, macOS, Illumos |
Prerequisites | Tcl 8.5 or newer, Augeas 0.10 or newer. |
Updated | 2024-05-13 (v0.5.0) |
License | MIT |
Contact | dbohdan |
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
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 ancient 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 . However, to make a full scale editor from it is a Herculean task requiring a hero, two rivers, root, and a better name for the tool.
dbohdan 2016-07-13: chw, I haven't tried compiling it but at a glace the Autoconf port looks reasonable. As for storing augeas objects in a Tcl_HashTable, I like that! I've integrated your changes into the master branch on GitHub.
# 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 <FocusIn> {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 <Escape> {set ::ABORT 1} bind ._Busy <Any-Key> 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 <<TreeviewOpen>> {fill_tree %W [%W focus]} bind .tree <<TreeviewClose>> {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