Posted to tcl by hypnotoad at Mon Jun 03 20:28:44 GMT 2019view pretty
package require clay 0.8 package provide clay::tk::console 0.1 ### # topic: 3f0e8c2797e7bd5e470fce8f117980095ea094f0 # description: # Open a console window for direct access to the # Tcl/Tk command interface to the IRM software suite ### proc ::console:start {} { if {[info command ::CONSOLE] ne {}} { CONSOLE wake } else { set args [list -prompt {wish% } -title {Tcl/Tk Shell}] ::clay::tk::console create CONSOLE .tclconsole mixinmap {language ::clay::tk::console.tcl} {*}$args } CONSOLE redirect_stdout } # Create a console widget named $w. The prompt string is $prompt. # The title at the top of the window is $title. The database connection # object is $db # proc sqlitecon:create {w prompt title db} { if {[info commands ::clay::tk::$w] ne {}} { ::clay::tk::$w wake } else { set args [list prompt $prompt title $title db $db] destroy $w ::clay::tk::console create ::clay::tk::$w $w mixinmap {language ::clay::tk::console.sqlite} {*}$args } } namespace eval ::clay::tk {} ### # This file implements the clay event manager ### ::namespace eval ::clay::event {} ### # topic: f2853d380a732845610e40375bcdbe0f # description: Cancel a scheduled event ### proc ::clay::event::cancel {self {task *}} { variable timer_event variable timer_script foreach {id event} [array get timer_event $self:$task] { ::after cancel $event set timer_event($id) {} set timer_script($id) {} } } ### # topic: 8ec32f6b6ba78eaf980524f8dec55b49 # description: # Generate an event # Adds a subscription mechanism for objects # to see who has recieved this event and prevent # spamming or infinite recursion ### proc ::clay::event::generate {self event args} { set wholist [Notification_list $self $event] if {$wholist eq {}} return set dictargs [::oo::meta::args_to_options {*}$args] set info $dictargs set strict 0 set debug 0 set sender $self dict with dictargs {} dict set info id [::clay::event::nextid] dict set info origin $self dict set info sender $sender dict set info rcpt {} foreach who $wholist { catch {::clay::event::notify $who $self $event $info} } } ### # topic: 891289a24b8cc52b6c228f6edb169959 # title: Return a unique event handle ### proc ::clay::event::nextid {} { return "event#[format %0.8x [incr ::clay::event_count]]" } ### # topic: 1e53e8405b4631aec17f98b3e8a5d6a4 # description: # Called recursively to produce a list of # who recieves notifications ### proc ::clay::event::Notification_list {self event {stackvar {}}} { set notify_list {} foreach {obj patternlist} [array get ::clay::object_subscribe] { if {$obj eq $self} continue if {$obj in $notify_list} continue set match 0 foreach {objpat eventlist} $patternlist { if {![string match $objpat $self]} continue foreach eventpat $eventlist { if {![string match $eventpat $event]} continue set match 1 break } if {$match} { break } } if {$match} { lappend notify_list $obj } } return $notify_list } ### # topic: b4b12f6aed69f74529be10966afd81da ### proc ::clay::event::notify {rcpt sender event eventinfo} { if {[info commands $rcpt] eq {}} return if {$::clay::trace} { puts [list event notify rcpt $rcpt sender $sender event $event info $eventinfo] } $rcpt notify $event $sender $eventinfo } ### # topic: 829c89bda736aed1c16bb0c570037088 ### proc ::clay::event::process {self handle script} { variable timer_event variable timer_script array unset timer_event $self:$handle array unset timer_script $self:$handle set err [catch {uplevel #0 $script} result errdat] if $err { puts "BGError: $self $handle $script ERR: $result [dict get $errdat -errorinfo] ***" } } ### # topic: eba686cffe18cd141ac9b4accfc634bb # description: Schedule an event to occur later ### proc ::clay::event::schedule {self handle interval script} { variable timer_event variable timer_script if {$::clay::trace} { puts [list $self schedule $handle $interval] } if {[info exists timer_event($self:$handle)]} { if {$script eq $timer_script($self:$handle)} { return } ::after cancel $timer_event($self:$handle) } set timer_script($self:$handle) $script set timer_event($self:$handle) [::after $interval [list ::clay::event::process $self $handle $script]] } ### # topic: e64cff024027ee93403edddd5dd9fdde ### proc ::clay::event::subscribe {self who event} { upvar #0 ::clay::object_subscribe($self) subscriptions if {![info exists subscriptions]} { set subscriptions {} } set match 0 foreach {objpat eventlist} $subscriptions { if {![string match $objpat $who]} continue foreach eventpat $eventlist { if {[string match $eventpat $event]} { # This rule already exists return } } } dict lappend subscriptions $who $event } ### # topic: 5f74cfd01735fb1a90705a5f74f6cd8f ### proc ::clay::event::unsubscribe {self args} { upvar #0 ::clay::object_subscribe($self) subscriptions if {![info exists subscriptions]} { return } switch [llength $args] { 1 { set event [lindex $args 0] if {$event eq "*"} { # Shortcut, if the set subscriptions {} } else { set newlist {} foreach {objpat eventlist} $subscriptions { foreach eventpat $eventlist { if {[string match $event $eventpat]} continue dict lappend newlist $objpat $eventpat } } set subscriptions $newlist } } 2 { set who [lindex $args 0] set event [lindex $args 1] if {$who eq "*" && $event eq "*"} { set subscriptions {} } else { set newlist {} foreach {objpat eventlist} $subscriptions { if {[string match $who $objpat]} { foreach eventpat $eventlist { if {[string match $event $eventpat]} continue dict lappend newlist $objpat $eventpat } } } set subscriptions $newlist } } } } set ::clay::tk::winsys [tk windowingsystem] if {$::tcl_platform(platform) eq "windows"} { set ::clay::tk::platform windows catch {::ttk::style theme use xpnative} } else { if {$::tcl_platform(os) == "Darwin"} { set ::clay::tk::platform macosx } else { set ::clay::tk::platform unix } catch {::ttk::style theme use clam} } ::clay::define ::clay::tk::megawidget { constructor {tkpath args} { set hull $tkpath if {![winfo exists $tkpath]} { set toplevel $tkpath toplevel $tkpath } else { set toplevel [winfo toplevel $tkpath] destroy {*}[winfo children $tkpath] } my clay delegate hull $hull toplevel $toplevel my Config_merge $args my Hull_Populate my content } destructor { my variable ismain if { $ismain } { catch {rename ::console:puts ::puts} } my Hull_Destroy } Ensemble config::get args { return [my Config_get {*}$args] } Ensemble config::merge args { return [my Config_merge {*}$args] } Ensemble config::set args { my Config_set {*}$args } method Config_get {field args} { my variable config option_canonical option_getcmd set field [string trimleft $field -] if {[info exists option_canonical($field)]} { set field $option_canonical($field) } if {[info exists option_getcmd($field)]} { return [eval $option_getcmd($field)] } if {[dict exists $config $field]} { return [dict get $config $field] } if {[llength $args]} { return [lindex $args 0] } return [my meta cget $field] } ### # topic: dc9fba12ec23a3ad000c66aea17135a5 ### method Config_merge dictargs { my variable config option_canonical set rawlist $dictargs set dictargs {} set dat [my clay get option] foreach {field val} $rawlist { set field [string trim $field -:/] if {[info exists option_canonical($field)]} { set field $option_canonical($field) } if {$field eq "mixinmap"} { my clay mixinmap {*}$val } elseif {$field eq "delegate"} { my clay delegate {*}$val } else { dict set dictargs $field $val } } ### # Validate all inputs ### foreach {field val} $dictargs { set script [my clay get option $field validate-command] if {$script ne {}} { dict set dictargs $field [eval [string map [list %field% [list $field] %value% [list $val] %self% [namespace which my]] $script]] } } ### # Apply all inputs with special rules ### foreach {field val} $dictargs { set script [my clay get option $field set-command] dict set config $field $val if {$script ne {}} { {*}[string map [list %field% [list $field] %value% [list $val] %self% [namespace which my]] $script] } } return $dictargs } method Config_set args { set dictargs [::clay::args_to_options {*}$args] set dat [my Config_merge $dictargs] my Config_triggers $dat } ### # topic: 543c936485189593f0b9ed79b5d5f2c0 ### method Config_triggers dictargs { foreach {field val} $dictargs { set script [my clay get option $field post-command] if {$script ne {}} { {*}[string map [list %field% [list $field] %value% [list $val] %self% [namespace which my]] $script] } } } method content {} {} method event {submethod args} { ::clay::event::$submethod [self] {*}$args } method Option_Default field { set info [my meta getnull option $field] set getcmd [dict getnull $info default-command:] if {$getcmd ne {}} { return [{*}[string map [list %field% $field %self% [namespace which my]] $getcmd]] } else { return [dict getnull $info default:] } } method Hull_Bind tkpath { bind $tkpath <Destroy> [namespace code {my Hull_Destroy_From_Tk %w}] } method Hull_Destroy {} { set w [my widget hull] if {![winfo exists $w]} return bind $w <Destroy> {} $w destroy } method Hull_Destroy_From_Tk {tkpath} { set w [my widget hull] if { [string match "${tkpath}*" $w] } { bind $w <Destroy> {} my destroy } } method signal args {} # Renames the tcl command that represents the widget to # one that resides in the object's namespace. It then renames # the object to catch calls to the tk path. ### method tkalias tkname { set oldname $tkname my variable tkalias set tkalias $tkname set self [self] set hullwidget [::info object namespace $self]::tkwidget my clay delegate tkwidget $hullwidget rename ::$tkalias $hullwidget my clay delegate hullwidget $hullwidget ::clay::object_rename [self] ::$tkalias my Hull_Bind $tkname return $hullwidget } method wake {} { set hull [my clay delegate hull] if {![winfo exists $hull]} { my clay delegate toplevel $hull toplevel $hull my Hull_Populate } else { catch [list wm deiconify [my widget toplevel]] update catch [list raise [my widget toplevel]] catch [list focus [my widget hull]] } } } ### # topic: fc7ea2899bddf6a00d04dc7515fd004702d282ef # description: # By the overt act of typing this comment, the author of this code # releases it into the public domain. No claim of copyright is made. # In place of a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # # # # This file contains code use to implement a simple command-line console # for Tcl/Tk. ### ::clay::define ::clay::tk::console { superclass megawidget Variable toplevel {} Variable ismain 0 clay set option language { default tcl } clay set option title { default {} } clay set option prompt { default {tcl% } } set has_consolas [expr {"Consolas" in [font families]}] if {$has_consolas} { set font {Consolas 10} switch $::clay::tk::platform { macosx { set font {Consolas 12} } } } else { set font {fixed 10} switch $::clay::tk::platform { macosx { set font {system 10} } windows { set font {systemfixed 9} } } } clay set option font [list \ widget font \ description {Font used on console widgets} \ default $font ] clay set signal focus { follows * action {focus [my clay delegate text]} } destructor { my variable ismain if { $ismain } { catch {rename ::console:puts ::puts} } my Hull_Destroy set terminate [expr {$hull eq "."}] if {$terminate} { exit 0 } } ### # topic: 03ca79afffe63938a00a9bd124316ba6fe83443d ### method addHistory line { my variable v if {$v(historycnt)>0} { set last [lindex $v(history) [expr $v(historycnt)-1]] if {[string compare $last $line]} { lappend v(history) $line incr v(historycnt) } } else { set v(history) [list $line] set v(historycnt) 1 } set v(current) $v(historycnt) } ### # topic: 83fc9e18be0f0d1798c7e20e7ccb23d806e1474c # description: # Called whenever the mouse leaves the boundries of the widget # while button 1 is held down. ### method B1Leave {x y} { my variable v set v(y) $y set v(x) $x my motor } ### # topic: 61622cb601a30cc516a5b227c37e80444ae09911 # description: Called whenever the mouse moves while button-1 is held down. ### method B1Motion {x y} { my variable v set v(y) $y set v(x) $x my SelectTo $x $y } ### # topic: b8eb39886df4395c26e911532af6c904910c735d # description: Erase the character to the left of the cursor ### method Backspace {} { my variable v scan [my <text> index insert] %d.%d row col if {$col>$v(plength)} { my <text> delete {insert -1c} } } ### # topic: 055c60d0743072b8d18f23322164664b80fa9328 ### method build_buttons {} { my variable v set mb [my widget subwindow mb] ttk::frame $mb my clay delegate buttonframe $mb pack $mb -side top -fill x menubutton $mb.file -text File -menu $mb.file.m menubutton $mb.edit -text Edit -menu $mb.edit.m menubutton $mb.tool -text Tools -menu $mb.tool.m pack $mb.file $mb.edit $mb.tool -side left -padx 8 -pady 1 set m [menu $mb.file.m -tearoff 0] # $m add command -label {Source...} -command "console:SourceFile $w.t" # $m add command -label {Save As...} -command "console:SaveFile $w.t" # $m add separator $m add command -label {Close} -command [list destroy [my widget hull]] $m add command -label {Exit} -command exit #$m add command -label {SQLite Console} -command \ # {::sqlitecon::create .sqlitecon {sqlite> } {SQLite Console} db} set m [menu $mb.tool.m -tearoff 0] set editmenu $mb.edit.m set v(editmenu) $editmenu set m [menu $editmenu -tearoff 0] $m add command -label Cut -command [namespace code "my Cut"] $m add command -label Copy -command [namespace code "my Copy"] $m add command -label Paste -command [namespace code "my Paste"] $m add command -label {Clear Screen} -command [namespace code "my Clear"] $m add separator $m add command -label {Source...} -command [namespace code "my SourceFile"] $m add command -label {Save As...} -command [namespace code "my SaveFile"] catch {$editmenu config -postcommand [namespace code "my EnableEditMenu"]} } method SBSET {args} { set sb [my widget subwindow sb] catch {$sb set {*}$args} } ### # topic: 93a511dc8939a3f59315d2b2016946e82cc4c12c ### method build_console {} { set w [my widget hull] my variable v array set v { pressX 0 mouseMoved 0 } set sb [my widget subwindow sb] set st [my widget subwindow console] ttk::scrollbar $sb -orient vertical -command "$st yview" pack $sb -side right -fill y text $st -font [my Config_get font] -yscrollcommand [namespace code {my SBSET}] pack $st -side right -fill both -expand 1 my clay delegate text $st set prompt [my Config_get prompt] set v(text) $st set v(history) 0 set v(historycnt) 0 set v(current) -1 set v(prompt) $prompt set v(prior) {} set v(plength) [string length $v(prompt)] set v(x) 0 set v(y) 0 $st mark set insert end $st tag config ok -foreground blue $st tag config err -foreground red $st tag config grn -foreground #00a000 $st tag config purple -foreground #c000c0 $st tag config lblue -foreground #417a9b $st tag config orange -foreground #be9e4f $st insert end $v(prompt) $st mark set out 1.0 my signal focus bindtags $st [list $st . all] bind $st <1> [namespace code {my Button1 %x %y}] bind $st <B1-Motion> [namespace code {my B1Motion %x %y}] bind $st <B1-Leave> [namespace code {my B1Leave %x %y}] bind $st <B1-Enter> [namespace code {my cancelMotor}] bind $st <ButtonRelease-1> [namespace code {my cancelMotor}] bind $st <KeyPress> [namespace code {my Insert %A}] bind $st <Left> [namespace code {my Left}] bind $st <Control-b> [namespace code {my Left}] bind $st <Right> [namespace code {my Right}] bind $st <Control-f> [namespace code {my Right}] bind $st <BackSpace> [namespace code {my Backspace}] bind $st <Control-h> [namespace code {my Backspace}] bind $st <Delete> [namespace code {my Delete}] bind $st <Control-d> [namespace code {my Delete}] bind $st <Home> [namespace code {my Home}] bind $st <Control-a> [namespace code {my Home}] bind $st <End> [namespace code {my End}] bind $st <Control-e> [namespace code {my End}] bind $st <Return> [namespace code {my Enter}] bind $st <KP_Enter> [namespace code {my Enter}] bind $st <Up> [namespace code {my Prior}] bind $st <Control-p> [namespace code {my Prior}] bind $st <Down> [namespace code {my Next}] bind $st <Control-n> [namespace code {my Next}] bind $st <Control-k> [namespace code {my EraseEOL}] bind $st <<Cut>> [namespace code {my Cut}] bind $st <<Copy>> [namespace code {my Copy}] bind $st <<Paste>> [namespace code {my Paste}] bind $st <<Clear>> [namespace code {my Clear}] } ### # topic: 67ea0661809dd66ff34b45263c465789bfbb9591 # description: # Called when the mouse button is pressed at position $x,$y on # the console widget. ### method Button1 {x y} { global tkPriv set w [my clay delegate text] my variable v set v(mouseMoved) 0 set v(pressX) $x set p [my nearestBoundry $x $y] scan [my <text> index insert] %d.%d ix iy scan $p %d.%d px py if {$px==$ix} { my <text> mark set insert $p } my <text> mark set anchor $p focus $w } ### # topic: 937a1570589f78997120e0f82d9989651a462dad # description: This routine cancels the scrolling motor if it is active ### method cancelMotor {} { my event cancel motor } ### # topic: 968b14fc7c6cbd13fd8a23f3d635ae0da45c6561 # description: # Return 1 if the selection exists and is contained # entirely on the input line. Return 2 if the selection # exists but is not entirely on the input line. Return 0 # if the selection does not exist. ### method canCut {} { set r [catch { scan [my <text> index sel.first] %d.%d s1x s1y scan [my <text> index sel.last] %d.%d s2x s2y scan [my <text> index insert] %d.%d ix iy }] if {$r==1} {return 0} if {$s1x==$ix && $s2x==$ix} {return 1} return 2 } ### # topic: 4a6b17559391aff67a3b8d9e850da371c89ff5ab # description: Erase everything from the console above the insertion line. ### method Clear {} { my <text> delete 1.0 {insert linestart} } ### # topic: cca0174bee56d0c82519a22c26fa417a3d61e373 # description: Do a Copy operation on the stuff currently selected. ### method Copy {} { set w [my clay delegate text] if {![catch {set text [my <text> get sel.first sel.last]}]} { clipboard clear -displayof $w clipboard append -displayof $w $text } } ### # topic: 5600bf5544e3c2a4c7d5b2a8a8f77e3cf4fb80f1 # description: # Do a Cut operation if possible. Cuts are only allowed # if the current selection is entirely contained on the # current input line. ### method Cut {} { if {[my canCut]==1} { my Copy my <text> delete sel.first sel.last } } ### # topic: 340c92b30cf1d0ee90eac3cc9ee0ff99360bb42d # description: Erase the character to the right of the cursor ### method Delete {} { my <text> delete insert } ### # topic: a11cb7a2a3118e0f46a332542e4853543f18cf8b ### method dialog_preferences {} { set pvar [my varname prefs] set f [my widget hull] if {[winfo exists $f.prefs]} { destroy {*}[winfo children $f.prefs] wm deiconify $f.prefs raise $f.prefs $f.prefs signal build_content } else { ::clay::tk::preference_panel $f.prefs object [self] } } ### # topic: 0c0ea9da28a51f2440c58c80021e67e605d750db # description: Enable or disable entries in the Edit menu ### method EnableEditMenu {} { my variable v set m $v(editmenu) if {$m=="" || ![winfo exists $m]} return switch [my canCut] { 0 { $m entryconf Copy -state disabled $m entryconf Cut -state disabled } 1 { $m entryconf Copy -state normal $m entryconf Cut -state normal } 2 { $m entryconf Copy -state normal $m entryconf Cut -state disabled } } } ### # topic: b6157a20658fef4530840f60f8163984a8c0bd6b # description: Move the cursor to the end of the current line ### method End {} { my <text> mark set insert {insert lineend} } ### # topic: ade17f15ff8a2b984f503c9570066952844ddf4e # description: Erase to the end of the line ### method EraseEOL {} { my variable v scan [my <text> index insert] %d.%d row col if {$col>=$v(plength)} { my <text> delete insert {insert lineend} } } ### # topic: ab0549c4965bf2dabdd74d318531a3a2bc90cf85 # description: Move the cursor to the beginning of the current line ### method Home {} { my variable v scan [my <text> index insert] %d.%d row col my <text> mark set insert $row.$v(plength) } ### # topic: 04d56668301bb768d53522d5754828bf8b8e2cfa ### method Hull_Populate {} { set t [my widget toplevel] set w [my widget hull] set prompt [my Config_get prompt] set title [my Config_get title] upvar #0 $w.t v if {[info exists v]} {unset v} wm title $w $title wm iconname $w $title my clay delegate hull $t my build_buttons my build_console } ### # topic: f21c52fa306df0b911649a088f634792260f9bc3 # description: Insert a single character at the insertion cursor ### method Insert a { my <text> insert insert $a my <text> yview insert } ### # topic: a86a704912089f9f69a51608a795ca78846e1c59 ### method insert text { my insert $a my Enter } ### # topic: a893a71497eca915ca47f88a86f296a05ce1fcab # description: Move the cursor one character to the left ### method Left {} { my variable v scan [my <text> index insert] %d.%d row col if {$col>$v(plength)} { my <text> mark set insert "insert -1c" } } ### # topic: f7d39c17edaa0287b478e6e9924e1ad6c5376ddc # description: # This routine is called to automatically scroll the window when # the mouse drags offscreen. ### method motor {} { my variable v set w [my clay delegate text] if {![winfo exists $w]} return if {$v(y)>=[winfo height $w]} { $w yview scroll 1 units } elseif {$v(y)<0} { $w yview scroll -1 units } else { return } my SelectTo $v(x) $v(y) my event schedule motor 50 [namespace code {my motor}] } ### # topic: 9089b1e19d4d54d37830de5832c94ed317abfc54 # description: # Find the boundry between characters that is nearest # to $x,$y ### method nearestBoundry {x y} { my variable v set p [my <text> index @$x,$y] set bb [my <text> bbox $p] if {![string compare $bb ""]} {return $p} if {($x-[lindex $bb 0])<([lindex $bb 2]/2)} {return $p} my <text> index "$p + 1 char" } ### # topic: f2543342648de822341ab839b19fc875549c0d71 # description: Change the line to the next line ### method Next {} { my variable v if {$v(current)>=$v(historycnt)} return incr v(current) 1 set line [lindex $v(history) $v(current)] my SetLine $line } ### # topic: 1fbaa6cd76c0ba81725f87e67e30c28f13a42de4 ### method Option_set::font newvalue { my <text> configure -font $newvalue } ### # topic: c2f59206f13fc6cd17ba0cc916d4b64853545642 # description: Do a paste opeation. ### method Paste {} { my variable v if {[my canCut]==1} { my <text> delete sel.first sel.last } set w [my clay delegate text] if {[catch {selection get -displayof $w -selection CLIPBOARD} topaste] && [catch {selection get -displayof $w -selection PRIMARY} topaste]} { return } set prior 0 foreach line [split $topaste \n] { if {$prior} { my Enter update } set prior 1 my <text> insert insert $line } } ### # topic: 1bdd01f30493ccdf242fcb581c188a861bc51246 # description: Change the line to the previous line ### method Prior {} { my variable v if {$v(current)<=0} return incr v(current) -1 set line [lindex $v(history) $v(current)] my SetLine $line } ### # topic: f58b9ac700bd1dc6748c89a4d346e7cc4a068bf6 # description: # Insert test at the "out" mark. The "out" mark is always # before the input line. New text appears on the line prior # to the current input line. ### method puts {t tag} { set nc [string length $t] set endc [string index $t [expr $nc-1]] if {$endc=="\n"} { if {[my <text> index out]<[my <text> index {insert linestart}]} { my <text> insert out [string range $t 0 [expr $nc-2]] $tag my <text> mark set out {out linestart +1 lines} } else { my <text> insert out $t $tag } } else { if {[my <text> index out]<[my <text> index {insert linestart}]} { my <text> insert out $t $tag } else { my <text> insert out $t\n $tag my <text> mark set out {out -1 char} } } my <text> yview insert } ### # topic: c7a8603d316f43da21effe7223902dd2853ded43 # description: Move the cursor one character to the right ### method Right {} { my <text> mark set insert "insert +1c" } ### # topic: 0833547d2ad5522b8a54fa0d92d339e4197ab635 # description: # Prompt the user for the name of a writable file. Then write the # entire contents of the console screen to that file. ### method SaveFile {} { set types { {{Text Files} {.txt}} {{All Files} *} } set f [tk_getSaveFile -filetypes $types -title "Write Screen To..."] if {$f!=""} { if {[catch {open $f w} fd]} { ::clay::tk::dialog -type ok -icon error -message {Error writing file} -detail $fd } else { puts $fd [string trimright [my <text> get 1.0 end] \n] close $fd } } } ### # topic: 71af63e2fb369f7677c165caa724b99b2ac0ca26 # description: This routine extends the selection to the point specified by {$x,$y} ### method SelectTo {x y} { my variable v set cur [my nearestBoundry $x $y] if {[catch {my <text> index anchor}]} { my <text> mark set anchor $cur } set anchor [my <text> index anchor] if {[my <text> compare $cur != $anchor] || (abs($v(pressX) - $x) >= 3)} { if {$v(mouseMoved)==0} { my <text> tag remove sel 0.0 end } set v(mouseMoved) 1 } if {[my <text> compare $cur < anchor]} { set first $cur set last anchor } else { set first anchor set last $cur } if {$v(mouseMoved)} { my <text> tag remove sel 0.0 $first my <text> tag add sel $first $last my <text> tag remove sel $last end update idletasks } } ### # topic: d832f029f5a3c95ebbbc0c7f46b053151dbecd2e # description: Change the contents of the entry line ### method SetLine line { my variable v scan [my <text> index insert] %d.%d row col set start $row.$v(plength) my <text> delete $start end my <text> insert end $line my <text> mark set insert end my <text> yview insert } Ensemble widget::toplevel {} { return [my clay delegate toplevel] } Ensemble widget::hull {} { return [my clay delegate hull] } Ensemble widget::parent {} { return [winfo parent [my clay delegate hull]] } Ensemble widget::subwindow path { set tl [string trimleft [my widget hull] .] if { $tl eq {} } { return .[string trimleft $path .] } return .$tl.[string trimleft $path .] } } ::clay::define ::clay::tk::console.tcl { ### # topic: c3d3bed792724df80d4ee0a5b1bc486d2501fd69 # description: # Called when "Enter" is pressed. Do something with the line # of text that was entered. ### method Enter {} { my variable v set w [my clay delegate text] scan [my <text> index insert] %d.%d row col set start $row.$v(plength) set line [my <text> get $start "$start lineend"] my addHistory $line my <text> insert end \n my <text> mark set out end if {$v(prior)==""} { set cmd $line } else { set cmd $v(prior)\n$line } if {[info complete $cmd]} { set rc [catch {uplevel #0 $cmd} res] if {![winfo exists $w]} return if {$rc} { my <text> insert end $res\n err } elseif {[string length $res]>0} { my <text> insert end $res\n ok } set v(prior) {} my <text> insert end $v(prompt) } else { set v(prior) $cmd regsub -all {[^ ]} $v(prompt) . x my <text> insert end $x } my <text> mark set insert end my <text> mark set out {insert linestart} my <text> yview insert } ### # topic: adb57b892b7da0eb46ab54c904f0de9cb1e31e01 ### method redirect_stdout {} { my variable ismain if { $ismain } return set nspace [namespace current] set my [namespace which my] set newproc ::console:puts if {[info command $newproc] eq {}} { catch {rename puts $newproc} } proc ::puts args [string map [list %newproc% $newproc %nspace% $nspace %self% $my] { if {[info command %self%] eq {} } { uplevel #0 %newproc% $args ::rename ::puts {} ::rename %newproc% ::puts return } switch -glob -- "[llength $args] $args" { {1 *} { set msg [lindex $args 0]\n set tag ok } {2 stdout *} { set msg [lindex $args 1]\n set tag ok } {2 stderr *} { set msg [lindex $args 1]\n set tag err } {2 green *} { set msg [lindex $args 1]\n set tag grn } {2 purple *} { set msg [lindex $args 1]\n set tag purple } {2 lightblue *} { set msg [lindex $args 1]\n set tag lblue } {2 orange *} { set msg [lindex $args 1]\n set tag orange } {2 -nonewline *} { set msg [lindex $args 1] set tag ok } {3 -nonewline stdout *} { set msg [lindex $args 2] set tag ok } {3 -nonewline stderr *} { set msg [lindex $args 2] set tag err } default { uplevel #0 %newproc% $args return } } %self% puts $msg $tag }] set ismain 1 return {} } ### # topic: 85c1d45d5027823e4407e59dbdfadca12a15d689 # description: Prompt for the user to select an input file, the source that file. ### method SourceFile {} { set types { {{TCL Scripts} {.tcl}} {{All Files} *} } set f [tk_getOpenFile -filetypes $types -title "TCL Script To Source..."] if {$f!=""} { uplevel #0 [list source [file normalize $f]] } } } ::clay::define ::clay::tk::console.sqlite { clay set option db {class organ} clay set option prompt {default {sqlite-> }} clay set option title {default {SQLite Console}} clay set option header {datatype boolean default 1} clay set option mode {widget select default column values {line list column csv multicolumn}} ### # topic: 43e235cf3b612e95c590e5de400d4bcc39d622a4 # description: # Execute a single SQL command. Pay special attention to control # directives that begin with "." # # The return value is the text output from the command, properly # formatted. ### method DoCommand cmd { my clay delegate db [my Config_get db] my variable v set mode [my Config_get mode] set header [my Config_get header] if {[regexp {^(\.[a-z]+)} $cmd all word]} { if {$word==".tcl"} { my tcl_console return {} } elseif {$word==".mode"} { regexp {^.[a-z]+ +([a-z]+)} $cmd all newvalue my config set [list mode $newvalue] return {} } elseif {$word==".exit"} { my destroy return {} } elseif {$word==".header"} { regexp {^.[a-z]+ +([a-z]+)} $cmd all newvalue my config set [list header $newvalue] return {} } elseif {$word==".tables"} { set mode multicolumn set cmd {SELECT name FROM sqlite_master WHERE type='table' UNION ALL SELECT name FROM sqlite_temp_master WHERE type='table'} my <db> eval {PRAGMA database_list} { if {$name!="temp" && $name!="main"} { append cmd "UNION ALL SELECT name FROM $name.sqlite_master\ WHERE type='table'" } } append cmd { ORDER BY 1} } elseif {$word==".fullschema"} { set pattern % regexp {^.[a-z]+ +([^ ]+)} $cmd all pattern set mode list set header 0 set cmd "SELECT sql FROM sqlite_master WHERE tbl_name LIKE '$pattern' AND sql NOT NULL UNION ALL SELECT sql FROM sqlite_temp_master WHERE tbl_name LIKE '$pattern' AND sql NOT NULL" my <db> eval {PRAGMA database_list} { if {$name!="temp" && $name!="main"} { append cmd " UNION ALL SELECT sql FROM $name.sqlite_master\ WHERE tbl_name LIKE '$pattern' AND sql NOT NULL" } } } elseif {$word==".schema"} { set pattern % regexp {^.[a-z]+ +([^ ]+)} $cmd all pattern set mode list set header 0 set cmd "SELECT sql FROM sqlite_master WHERE name LIKE '$pattern' AND sql NOT NULL UNION ALL SELECT sql FROM sqlite_temp_master WHERE name LIKE '$pattern' AND sql NOT NULL" my <db> eval {PRAGMA database_list} { if {$name!="temp" && $name!="main"} { append cmd " UNION ALL SELECT sql FROM $name.sqlite_master\ WHERE name LIKE '$pattern' AND sql NOT NULL" } } } else { return \ ".exit\n.mode line|list|column|csv\n.schema ?TABLENAME?\n.tables\n.tcl" } } set res {} if {$mode=="list"} { my <db> eval $cmd x { set sep {} foreach col $x(*) { append res $sep$x($col) set sep | } append res \n } if {[info exists x(*)] && $header} { set sep {} set hdr {} foreach col $x(*) { append hdr $sep$col set sep | } set res $hdr\n$res } } elseif {[string range $mode 0 2]=="col"} { set y {} my <db> eval $cmd x { foreach col $x(*) { if {![info exists cw($col)] || $cw($col)<[string length $x($col)]} { set cw($col) [string length $x($col)] } lappend y $x($col) } } if {[info exists x(*)] && $header} { set hdr {} set ln {} set dash --------------------------------------------------------------- append dash ------------------------------------------------------------ foreach col $x(*) { if {![info exists cw($col)] || $cw($col)<[string length $col]} { set cw($col) [string length $col] } lappend hdr $col lappend ln [string range $dash 1 $cw($col)] } set y [concat $hdr $ln $y] } if {[info exists x(*)]} { set format {} set arglist {} set arglist2 {} set i 0 foreach col $x(*) { lappend arglist x$i append arglist2 " \$x$i" incr i append format " %-$cw($col)s" } set format [string trimleft $format]\n if {[llength $arglist]>0} { foreach $arglist $y "append res \[format [list $format] $arglist2\]" } } } elseif {$mode=="multicolumn"} { set y [my <db> eval $cmd] set max 0 foreach e $y { if {$max<[string length $e]} {set max [string length $e]} } set ncol [expr {int(80/($max+2))}] if {$ncol<1} {set ncol 1} set nelem [llength $y] set nrow [expr {($nelem+$ncol-1)/$ncol}] set format "%-${max}s" for {set i 0} {$i<$nrow} {incr i} { set j $i while 1 { append res [format $format [lindex $y $j]] incr j $nrow if {$j>=$nelem} break append res { } } append res \n } } elseif {$mode=="csv"} { my <db> eval $cmd x { set sep {} foreach col $x(*) { set val $x($col) if {$val=="" || [regexp {[\s",]} $val]} { set val \"[string map [list \" \"\"] $val]\" } append res $sep$val set sep , } append res \n } } else { my <db> eval $cmd x { foreach col $x(*) {append res "$col = $x($col)\n"} append res \n } } return [string trimright $res] } ### # topic: 93d94ab333ba8ad804eefcc8bba8afa95b1e0dcf ### method Enter {} { my variable v set w [my clay delegate text] scan [my <text> index insert] %d.%d row col set start $row.$v(plength) set line [my <text> get $start "$start lineend"] my <text> insert end \n my <text> mark set out end if {$v(prior)==""} { set cmd $line } else { set cmd $v(prior)\n$line } if {[string index $cmd 0]=="." || [my <db> complete $cmd]} { regsub -all {\n} [string trim $cmd] { } cmd2 my addHistory $cmd2 set rc [catch {my DoCommand $cmd} res] if {![winfo exists $w]} return if {$rc} { my <text> insert end $res\n err } elseif {[string length $res]>0} { my <text> insert end $res\n ok } set v(prior) {} my <text> insert end $v(prompt) } else { set v(prior) $cmd regsub -all {[^ ]} $v(prompt) . x my <text> insert end $x } my <text> mark set insert end my <text> mark set out {insert linestart} my <text> yview insert } method tcl_console {} { set w [my widget toplevel] if {$w ne "."} { console:start } else { if {[winfo exists .tclconsole]} { catch {wm deiconify .tclconsole} update catch {raise .tclconsole} } else { set args [list -prompt {wish% } -title {Tcl/Tk Shell}] taotk::console .tclconsole {*}$args } .tclconsole redirect_stdout wm title .tclconsole "TCL [my Config_get title]" .tclconsole puts "SQL Object Available as [my Config_get db]" green } } } # Start the console # # console:create {.@console} {% } {Tcl/Tk Console}