Posted to tcl by Stu at Sat May 10 03:02:34 GMT 2008view pretty

# herring
#
# May 2008
# Stuart Cassoff
#
# Use at your own risk
# (many have died)
#

namespace eval herring {
	variable HookUserInfoDialog 0
	variable InfoRaw 0
	variable TwigRun 0

	variable cfg

	set cfg(version) 0.1
	
	set cfg(tclsh) /usr/local/bin/tclsh8.5
	set cfg(wish) /usr/local/bin/wish8.5
	set cfg(twig) ~/tcl/twig/twig.tcl
	set cfg(run) $cfg(wish)

	set cfg(myTwigListFile) ~/twiglist.twig

	set cfg(twigs) {}

	# Chat Text Window
	set cfg(ctw) .txt

	set cfg(aliasMap) [list \
		wikiref	::herring::wikiref \
		twig	::herring::twig    \
	]

	set cfg(floodcount) 0
	set cfg(floodmax) 15


}

proc herring::wikisearch {what {max -1}} {
	set z {}
	set c 0
	set h [http::geturl http://wiki.tcl.tk/_search?S=$what]
	if {[http::status $h] eq {ok}} {
		foreach {. p n} [regexp -inline -all {<li>.*?\. \. \. <a href="/(.*?)">(.*?)</a>} [http::data $h]] {
			lappend z http://wiki.tcl.tk/$p\ \t$n   
			if {$max == -1} { continue }
			if {[incr c] >= $max} {	break }
		}
	}
	http::cleanup $h
	return $z
}

proc herring::wikiref {msg} {
	global Options

	if {[llength $msg] == 2} {
		set user [lindex $msg 0]
		set msg [lindex $msg 1]
		if {$user eq {me}} {
			set user $Options(Nickname)
		}
	} else  {
		set user {}
	}
	set srchres [wikisearch $msg 10]
	if {[llength $srchres] > 0} {
		send [join $srchres \n] $user
	}
}

proc herring::loadTwigs {{fn {}}} {
	variable cfg

	if {$fn eq {}} {
		set fn $cfg(myTwigListFile)
	} elseif {$fn eq {?}} {
		set fn [tk_getOpenFile -defaultextension .twig -filetypes {{{TWiG Files} .twig} {{All Files} *}}]
		if {$fn eq {}} {
			return {}
		}
	}

	set cfg(twigs) {}

	set f [open $fn r]
	set cfg(twigs) [split [read -nonewline $f] \n]
	close $f

	return "$fn loaded ok"
}

proc herring::prettyTwigs {twigs {raw 0}} {
	if {[llength $twigs] == 0} {
		return {no twigs}
	}

	set t {}
	set n 0

	foreach l $twigs {
		if {$raw} {
			set l [linsert $l 0 [incr n].]
		} else {
			set l "[incr n]. [lindex $l 4]"
		}
		lappend t $l
	}
	
	return [join $t \n]
}

proc herring::twiggit {page {blocks 0}} {
	variable cfg
	return [exec $cfg(tclsh) $cfg(twig) $page $blocks]
}

proc herring::runTwig  {page {blocks 0} {name {}}} {
	variable cfg
#	exec $cfg(wish) <<[twiggit $page $blocks] &
	exec $cfg(tclsh) $cfg(twig) $page $blocks | $cfg(run) &
}

proc herring::viewTwig  {page {blocks 0} {name {}}} {
	view [twiggit $page $blocks] $name
}

proc herring::twig {msg} {
	variable cfg

	if {[catch {llength $msg}]} { return }

	switch -exact -- [lindex $msg 0] {
	load {
		set fn {}
		set tag {}
		if {[llength $msg] == 2} { set fn [lindex $msg 1] }
		if {[catch {loadTwigs $fn} e]} { set tag ERROR }
		if {$e eq {}} { return }
		print $e $tag
	}
	list {
		set start 1
		set raw [expr {[lindex $msg $start] eq {-raw}}]
		if {$raw} { incr start }
		set user [lindex $msg $start]
		if {$user ne {}} {
			variable HookUserInfoDialog 1
			variable TwigInfoRaw $raw
			::tkjabber::userinfo $user
			return
		}
		if {[llength $cfg(twigs)] == 0} {
			print {no twigs}
			return
		}
		print Loaded\ TWiGs:[expr {$raw?" (raw)":""}]\n[prettyTwigs $cfg(twigs) $raw] 
	}
	view -
	run {
		if {[lindex $msg 0] eq {view}} {
			if {[llength $msg] == 1} {
				view
			} else {
				set tag {}
				if {[catch {viewFile [lindex $msg 1]} e]} { set tag ERROR }
				if {$e eq {}} { return }
				print $e $tag
			}
			return
		}
		if {[regexp {^(.+)\.$} [lindex $msg end] -> num]} {
			if {[llength $msg] > 2} {
				variable HookUserInfoDialog 1
				variable TwigRun $num
				::tkjabber::userinfo [lindex $msg 1]
				return
			}
			if {[llength $cfg(twigs)] == 0} {
				print {no twigs}
				return
			}
			if {$num < 1 || $num >= [llength $cfg(twigs)]} {
				print {TWiG not found} ERROR
				return
			}
			incr num -1
			set twig [lindex $cfg(twigs) $num]
			set page [lindex $twig 0]
			set blocks [lindex $twig 1]
			set name [lindex $twig 4]
		} elseif {[llength $msg] > 1} {
			set page [lindex $msg 1]
			set blocks [lindex $msg 2]
			set name {}
		} else {
			print "run|view usage:\nrun|view ?user? #.\nrun|view page ?blocks?\nview" SYSTEM
			return
		}
		if {[catch [list [lindex $msg 0]Twig $page $blocks $name] e]} {
			print $e ERROR
		}
	}
	? {
		set m {}
		lappend m "TWiG $cfg(version) Commands:"
		lappend m "list ?-raw? ?user?"
		lappend m "run|view ?user? #."
		lappend m "run|view page ?blocks?"
		lappend m "view ?filename?"
		lappend m "view ? (ask for file to view)"
		lappend m "view {} (view your .twig file)"
		lappend m "load ?filename?"
		print [join $m \n]
	}
	default {
		print "TWiG $cfg(version)\n/twig ? for help" SYSTEM
	}
	}
}

proc herring::send {msg {user {me}}} {
	global Options
	variable floodcount
	variable floodmax

	incr floodcount

	if {$floodcount > $floodmax} {return}

	if {$floodcount == $floodmax} {
		::tkjabber::msgSend "/nolog stubot: outgoing msg count exceeded $floodmax msgs" -user $Options(Nickname) -attrs [list nolog 1]
		return
	}

	if {[set c [string index $msg 0]] ne { } && $c ne {/}} {
		set msg " $msg"
	}
	if {$user eq {me}} {
		set user $Options(Nickname)
	}

	set max 300
	if {[string length $msg] <= $max} {
		::tkjabber::msgSend "/nolog$msg" -user $user -attrs [list nolog 1]
	} else {
		::tkjabber::msgSend "/nolog stubot: outgoing msg exceeded $max chars" -user $Options(Nickname) -attrs [list nolog 1]
	}
}

proc herring::print {msg {tag MSG}} {
	variable cfg
	global Options

	if {$tag eq {}} {
		info default [lindex [info level 0] 0] tag tag
	}

	$cfg(ctw) configure -state normal

	set stuff [split $msg \n]
	$cfg(ctw) insert end TWiG\t[lindex $stuff 0]\n $tag
	foreach l [lrange $stuff 1 end] {
		$cfg(ctw) insert end \t$l\n $tag
	}

	$cfg(ctw) configure -state disabled
	if {$Options(AutoScroll)} {
		$cfg(ctw) see end
	}
}

proc herring::run {code} {
	variable cfg
	exec $cfg(run) <<$code &	
}

proc herring::save {what {name {}}} {
	if {$name eq {}} {
		set name [tk_getSaveFile]
		if {$name eq {}} {
			return
		}
	}
	if {[catch {
		set f [open $name w]
		puts -nonewline $f $what
		close $f
	} e]} {
		print $e ERROR
	} else {
		print "$name saved ok"
	}
}

proc herring::viewFile {{fn {}}} {
	variable cfg
	if {$fn eq {}} {
		set fn $cfg(myTwigListFile)
	} elseif {$fn eq {?}} {
		set fn [tk_getOpenFile]
		if {$fn eq {}} {
			return {}
		}
	}

	set f [open $fn r]
	set d [read -nonewline $f]
	close $f

	view $d $fn

	return {}
}

proc herring::view {{what {}} {title {}}} {
	variable ::tkchat::NS
    catch {destroy .view}
    set dlg [::tkchat::Dialog .view]
    set w [${NS}::frame $dlg.f]
    wm withdraw $dlg
    wm title $dlg $title
    if {[llength [info command ::tkchat::img::Tkchat]] != 0} {
	catch {wm iconphoto $dlg ::tkchat::img::Tkchat}
    }
    ${NS}::button $w.b -text Dismiss -width -12 -command [list wm withdraw $dlg] -default active
    ::tkchat::ScrolledWidget text $w.text 0 1 -height 23 -width 80 \
        -borderwidth 0 -padx 2 -pady 2 -font FNT
    grid $w.text -sticky news
	${NS}::button $w.bs -text Save -width -12 -command "::herring::save \[$w.text get 1.0 end\]" -default active
	${NS}::button $w.br -text Run -width -12 -command "::herring::run \[$w.text get 1.0 end\]" -default active
	grid $w.bs            -sticky se
	grid    ^  $w.br      -sticky se -padx 4
	grid    ^     ^  $w.b -sticky se
	grid configure $w.text -columnspan 3

    grid rowconfigure $w 0 -weight 1
    grid columnconfigure $w 0 -weight 1

    $w.text insert end $what

    grid $w -sticky news
    grid rowconfigure $dlg 0 -weight 1
    grid columnconfigure $dlg 0 -weight 1

#    $w.text configure -state disabled
#    bind $dlg <Return> [list $w.b invoke]
#    bind $dlg <Escape> [list $w.b invoke]
	bind $dlg <Control-q> [list $w.b invoke]
	bind $dlg <Control-Q> [list $w.b invoke]
    catch {::tk::PlaceWindow $dlg widget .}
    wm deiconify $dlg
# This was originally TkChat's [About]
}


# Here starts the evil section

proc herring::incomingUserInfo {jid desc} {
	variable TwigInfoRaw
	variable TwigRun

	set delim {-*- TWiGs -*-}
	set delimmatch {-\*-*TWiGs*-\*-}
	set twigs {}
	set inTwigs 0

	foreach l [split $desc \n] {
		set l [string trim $l]
		if {$inTwigs} {
			if {[string match -nocase $delimmatch $l]} {
				set inTwigs 0
			} else {
				if {![catch {llength $l} len] && $len == 5} {
					lappend twigs $l
				}
			}
		} elseif {[string match -nocase $delimmatch $l]} {
			set inTwigs 1
		}
	}

	if {$TwigRun > 0} {
		set i $TwigRun
		set TwigRun 0
		if {$i < 1 || $i >= [llength $twigs]} {
			print No\ TWiGs\ for\ $jid
			return
		}
		incr i -1
		set twig [lindex $twigs $i]
		set page [lindex $twig 0]
		set blocks [lindex $twig 1]
		if {[catch {runTwig $page $blocks} e]} {
			send $e
		}
	} else {
		print TWiGs\ for\ $jid:\n[prettyTwigs $twigs $TwigInfoRaw]
	}
}

proc herring::pimple {n1 n2 op} {
	uplevel 1 {trace remove variable UI(id) write ::herring::pimple}
	variable TwigInfo [uplevel 1 { set UI(DESC) }]
	rename ::tkchat::Dialog ::herring::_Dialog
	proc ::tkchat::Dialog {id} {
		rename ::tkchat::Dialog {}
		rename ::herring::_Dialog ::tkchat::Dialog
		::tkchat::addStatus 0 "Getting [uplevel 1 { set jid }]'s TWiGs ..."
		after idle [list ::herring::incomingUserInfo [uplevel 1 { set jid }] [uplevel 1 { set UI(DESC) }]]
		uplevel 1 { unset -nocomplain [namespace current]::$id UI }
		uplevel 1 { return -level 2 }
	}
}

proc ::herring::cow {n1 n2 op} {
	trace remove variable ::tkchat::UserInfoWin write ::herring::cow
	uplevel 1 {trace add variable UI(id) write ::herring::pimple}
}


if {[info command ::tkchat::_UserInfoDialog] eq {}} {
	rename ::tkchat::UserInfoDialog ::tkchat::_UserInfoDialog
}
proc ::tkchat::UserInfoDialog {{jid {}}} {
#	upvar #0 ::herring::HookUserInfoDialog HookUserInfoDialog
	variable ::herring::HookUserInfoDialog

	if {!$HookUserInfoDialog} {
		::tkchat::_UserInfoDialog $jid
		return
	}

	set HookUserInfoDialog 0

	trace remove variable ::tkchat::UserInfoWin write ::herring::cow
	variable UserInfoWin
	unset -nocomplain UserInfoWin
	trace add variable ::tkchat::UserInfoWin write ::herring::cow

	::tkchat::_UserInfoDialog $jid

	trace remove variable ::tkchat::UserInfoWin write ::herring::cow
}

# End of evil section


proc ::herring::init {} {
	variable cfg


	foreach {alias proc} $cfg(aliasMap) {
		::tkchat::processAliasCommand "/alias $alias proc $proc"
	}
}

namespace eval herring {
	init
}


# EOF