tkcon.tcl

来自「算断裂的」· TCL 代码 · 共 2,077 行 · 第 1/5 页

TCL
2,077
字号
#!/bin/sh# \exec wish "$0" ${1+"$@"}### tkcon.tcl## Enhanced Tk Console, part of the VerTcl system#### Originally based off Brent Welch's Tcl Shell Widget## (from "Practical Programming in Tcl and Tk")#### Thanks to the following (among many) for early bug reports & code ideas:## Steven Wahl <steven@indra.com>, Jan Nijtmans <nijtmans@nici.kun.nl>## Crimmins <markcrim@umich.edu>, Wart <wart@ugcs.caltech.edu>#### Copyright 1995-1999 Jeffrey Hobbs## Initiated: Thu Aug 17 15:36:47 PDT 1995#### jeff.hobbs@acm.org#### source standard_disclaimer.tcl## source bourbon_ware.tcl#### FIX NOTES - ideas on the block:## can tkConSplitCmd be used for debugging?## can return/error be overridden for debugging?if {$tcl_version>=8.0} {    package require -exact Tk $tcl_version} elseif {[catch {package require -exact Tk [expr {$tcl_version-3.4}]}]} {    return -code error "TkCon requires at least Tcl7.6/Tk4.2"}catch {package require bogus-package-name}foreach pkg [info loaded {}] {    set file [lindex $pkg 0]    set name [lindex $pkg 1]    if {![catch {set version [package require $name]}]} {	if {[string match {} [package ifneeded $name $version]]} {	    package ifneeded $name $version [list load $file $name]	}    }}catch {unset pkg file name version}set TKCON(WWW) [info exists embed_args]## tkConInit - inits tkCon## Calls:	tkConInitUI# Outputs:	errors found in tkCon resource file##;proc tkConInit {} {    global auto_path tcl_platform env tcl_pkgPath \	    TKCON argc argv tcl_interactive errorInfo    if {![info exists argv]} {	set argv {}	set argc 0    }    set tcl_interactive 1    if {[info exists TKCON(name)]} {	set title $TKCON(name)    } else {	tkConMainInit	set title Main    }    # get bg color from the main toplevel    array set TKCON {	color,bg	{}	color,blink	\#FFFF00	color,cursor	\#000000	color,disabled	\#4D4D4D	color,proc	\#008800	color,var	\#FFC0D0	color,prompt	\#8F4433	color,stdin	\#000000	color,stdout	\#0000FF	color,stderr	\#FF0000	autoload	{}	blinktime	500	blinkrange	1	buffer		512	calcmode	0	cols		80	debugPrompt	{(level \#$level) debug [history nextid] > }	dead		{}	expandorder	{Pathname Variable Procname}	font		{}	history		48	hoterrors	1	library		{}	lightbrace	1	lightcmd	1	maineval	{}	maxmenu		15	nontcl		0	rows		20	scrollypos	right	showmenu	1	showmultiple	1	slaveeval	{}	slaveexit	close	subhistory	1	exec		slave	app		{}	appname		{}	apptype		slave	namesp		::	cmd		{}	cmdbuf		{}	cmdsave		{}	event		1	deadapp		0	deadsock	0	debugging	0	gc-delay	60000	histid		0	find		{}	find,case	0	find,reg	0	errorInfo	{}	slavealias	{ edit more less tkcon }	slaveprocs	{	    alias clear dir dump echo idebug lremove	    tkcon_puts tclindex observe observe_var unalias which what	}	version		1.6	release		{31 March 1999}	docs		"http://www.purl.org/net/hobbs/tcl/script/tkcon/\nhttp://www.hobbs.wservice.com/tcl/script/tkcon/"	email		{jeff.hobbs@acm.org}	root		.    }    ## NOTES FOR STAYING IN PRIMARY INTERPRETER:    ## If you set TKCON(exec) to {}, then instead of a multiple interpreter    ## model, you get TkCon operating in the main interp by default.    ## This can be useful when attaching to programs that like to operate    ## in the main interpter (for example, based on special wish'es).    ## You can set this from the command line with -exec ""    ## A side effect is that all tkcon command line args will be used    ## by the first console only.    #set TKCON(exec) {}    if {$TKCON(WWW)} {	lappend TKCON(slavealias) history	set TKCON(prompt1) {[history nextid] % }    } else {	lappend TKCON(slaveprocs) tcl_unknown unknown	set TKCON(prompt1) {([file tail [pwd]]) [history nextid] % }    }    ## If there appear to be children of '.', then make sure we use    ## a disassociated toplevel.    if {[llength [winfo children .]]} {	set TKCON(root) .tkcon    }    ## Do platform specific configuration here    ### Use tkcon.cfg filename for resource filename on non-unix systems    ### Determine what directory the resource file should be in    ### Windows could possibly use env(WINDIR)    switch $tcl_platform(platform) {	macintosh	{	    set envHome PREF_FOLDER	    cd [file dirname [info script]]	    set TKCON(rcfile) tkcon.cfg	}	windows		{	    set envHome HOME	    set TKCON(rcfile) tkcon.cfg	}	unix		{	    set envHome HOME	    set TKCON(rcfile) .tkconrc	}    }    if {[info exists env($envHome)]} {	set TKCON(rcfile) [file join $env($envHome) $TKCON(rcfile)]    }    ## Handle command line arguments before sourcing resource file to    ## find if resource file is being specified (let other args pass).    if {[set i [lsearch -exact $argv -rcfile]] != -1} {	set TKCON(rcfile) [lindex $argv [incr i]]    }    if {!$TKCON(WWW) && [file exists $TKCON(rcfile)]} {	set code [catch [list uplevel \#0 source $TKCON(rcfile)] err]    }    if {[info exists env(TK_CON_LIBRARY)]} {	uplevel \#0 lappend auto_path $env(TK_CON_LIBRARY)    } else {	uplevel \#0 lappend auto_path $TKCON(library)    }    if {![info exists tcl_pkgPath]} {	set dir [file join [file dirname [info nameofexec]] lib]	if {[llength [info commands @scope]]} {	    set dir [file join $dir itcl]	}	catch {source [file join $dir pkgIndex.tcl]}    }    catch {tclPkgUnknown dummy-name dummy-version}    ## Handle rest of command line arguments after sourcing resource file    ## and slave is created, but before initializing UI or setting packages.    set slaveargs {}    set slavefiles {}    set truth {^(1|yes|true|on)$}    for {set i 0} {$i < $argc} {incr i} {	set arg [lindex $argv $i]	if {[string match {-*} $arg]} {	    set val [lindex $argv [incr i]]	    ## Handle arg based options	    switch -glob -- $arg {		-- - -argv	{		    set argv [concat -- [lrange $argv $i end]]		    set argc [llength $argv]		    break		}		-color,*	{ set TKCON([string range $arg 1 end]) $val }		-exec	{ set TKCON(exec) $val }		-main - -e - -eval	{ append TKCON(maineval) \n$val\n }		-package - -load	{ lappend TKCON(autoload) $val }		-slave	{ append TKCON(slaveeval) \n$val\n }		-nontcl	{ set TKCON(nontcl) [regexp -nocase $truth $val] }		-root	{ set TKCON(root) $val }		-font	{ set TKCON(font) $val }		-rcfile	{}		default	{ lappend slaveargs $arg; incr i -1 }	    }	} elseif {[file isfile $arg]} {	    lappend slavefiles $arg	} else {	    lappend slaveargs $arg	}    }    ## Create slave executable    if {[string compare {} $TKCON(exec)]} {	uplevel \#0 tkConInitSlave $TKCON(exec) $slaveargs    } else {	set argc [llength $slaveargs]	set argv $slaveargs	uplevel \#0 $slaveargs    }    history keep $TKCON(history)    ## Attach to the slave, tkConEvalAttached will then be effective    tkConAttach $TKCON(appname) $TKCON(apptype)    tkConInitUI $title    ## swap puts and gets with the tkcon versions to make sure all    ## input and output is handled by tkcon    if {![catch {rename puts tkcon_tcl_puts}]} {	interp alias {} puts {} tkcon_puts    }    #if {![catch {rename gets tkcon_tcl_gets}]} {	#interp alias {} gets {} tkcon_gets    #}    ## Autoload specified packages in slave    set pkgs [tkConEvalSlave package names]    foreach pkg $TKCON(autoload) {	puts -nonewline "autoloading package \"$pkg\" ... "	if {[lsearch -exact $pkgs $pkg]>-1} {	    if {[catch {tkConEvalSlave package require [list $pkg]} pkgerr]} {		puts stderr "error:\n$pkgerr"		append TKCON(errorInfo) $errorInfo\n	    } else { puts "OK" }	} else {	    puts stderr "error: package does not exist"	}    }    ## Evaluate maineval in slave    if {[string compare {} $TKCON(maineval)] && \	    [catch {uplevel \#0 $TKCON(maineval)} merr]} {	puts stderr "error in eval:\n$merr"	append TKCON(errorInfo) $errorInfo\n    }    ## Source extra command line argument files into slave executable    foreach fn $slavefiles {	puts -nonewline "slave sourcing \"$fn\" ... "	if {[catch {tkConEvalSlave source [list $fn]} fnerr]} {	    puts stderr "error:\n$fnerr"	    append TKCON(errorInfo) $errorInfo\n	} else { puts "OK" }    }    ## Evaluate slaveeval in slave    if {[string compare {} $TKCON(slaveeval)] && \	    [catch {interp eval $TKCON(exec) $TKCON(slaveeval)} serr]} {	puts stderr "error in slave eval:\n$serr"	append TKCON(errorInfo) $errorInfo\n    }    ## Output any error/output that may have been returned from rcfile    if {[info exists code] && $code && [string compare {} $err]} {	puts stderr "error in $TKCON(rcfile):\n$err"	append TKCON(errorInfo) $errorInfo    }    if {[string compare {} $TKCON(exec)]} {	tkConStateCheckpoint [concat $TKCON(name) $TKCON(exec)] slave    }    tkConStateCheckpoint $TKCON(name) slave}## tkConInitSlave - inits the slave by placing key procs and aliases in it## It's arg[cv] are based on passed in options, while argv0 is the same as## the master.  tcl_interactive is the same as the master as well.# ARGS:	slave	- name of slave to init.  If it does not exist, it is created.#	args	- args to pass to a slave as argv/argc##;proc tkConInitSlave {slave args} {    global TKCON argv0 tcl_interactive tcl_library env    if {[string match {} $slave]} {	return -code error "Don't init the master interpreter, goofball"    }    if {![interp exists $slave]} { interp create $slave }    if {[interp eval $slave info command source] == ""} {	$slave alias source tkConSafeSource $slave	$slave alias load tkConSafeLoad $slave	$slave alias open tkConSafeOpen $slave	$slave alias file file	interp eval $slave [dump var -nocomplain tcl_library env]	interp eval $slave { catch {source [file join $tcl_library init.tcl]} }	interp eval $slave { catch unknown }    }    $slave alias exit exit    interp eval $slave {	catch {rename puts tkcon_tcl_puts}	#catch {rename gets tkcon_tcl_gets}	catch {package require bogus-package-name}    }    foreach cmd $TKCON(slaveprocs) { $slave eval [dump proc $cmd] }    foreach cmd $TKCON(slavealias) { $slave alias $cmd $cmd }    interp alias $slave ls $slave dir -full    interp alias $slave puts $slave tkcon_puts    #interp alias $slave gets $slave tkcon_gets    if {[info exists argv0]} {interp eval $slave [list set argv0 $argv0]}    interp eval $slave set tcl_interactive $tcl_interactive \; \	    set argc [llength $args] \; \	    set argv  [list $args] \; history keep $TKCON(history) \; {	if {![llength [info command bgerror]]} {	    ;proc bgerror err {		global errorInfo		set body [info body bgerror]		rename bgerror {}		if {[auto_load bgerror]} { return [bgerror $err] }		;proc bgerror err $body		tkcon bgerror $err $errorInfo	    }	}    }    foreach pkg [lremove [package names] Tcl] {	foreach v [package versions $pkg] {	    interp eval $slave [list package ifneeded $pkg $v \		    [package ifneeded $pkg $v]]	}    }}## tkConInitInterp - inits an interpreter by placing key## procs and aliases in it.# ARGS: name	- interp name#	type	- interp type (slave|interp)##;proc tkConInitInterp {name type} {    global TKCON    ## Don't allow messing up a local master interpreter    if {[string match namespace $type] || ([string match slave $type] && \	    [regexp {^([Mm]ain|Slave[0-9]+)$} $name])} return    set old [tkConAttach]    if {$TKCON(A:version) >= 8.0} { set oldname $TKCON(namesp) }    catch {	tkConAttach $name $type	tkConEvalAttached {	    catch {rename puts tkcon_tcl_puts}	    #catch {rename gets tkcon_tcl_gets}	}	foreach cmd $TKCON(slaveprocs) { tkConEvalAttached [dump proc $cmd] }	switch -exact $type {	    slave {		foreach cmd $TKCON(slavealias) {		    tkConMain interp alias $name $cmd $TKCON(name) $cmd		}	    }	    interp {		set thistkcon [tk appname]		foreach cmd $TKCON(slavealias) {		    tkConEvalAttached "proc $cmd args { send [list $thistkcon] $cmd \$args }"		}	    }	}	## Catch in case it's a 7.4 (no 'interp alias') interp	tkConEvalAttached {	    catch {interp alias {} ls {} dir -full}	    if {[catch {interp alias {} puts {} tkcon_puts}]} {		catch {rename tkcon_puts puts}	    }	    #if {[catch {interp alias {} gets {} tkcon_gets}]} {		#catch {rename tkcon_gets gets}	    #}	}	return    } {err}    eval tkConAttach $old

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?