📄 exec.tcl
字号:
proc cvs_usercmd {args} {
#
# Run a cvs command from the user menu and view its output.
# called for cvsmenu() entries.
#
global cvs
gen_log:log T "ENTER ($args)"
#gen_log:log C "$cvs $args"
set my_viewer [viewer::new "CVS $args"]
$my_viewer\::do "$cvs $args"
gen_log:log T "LEAVE"
}
proc cvs_execcmd {args} {
#
# Run any command from the user menu without
# a viewer to capture its output and without
# the ability to abort it.
# called for execmenu() entries.
#
gen_log:log T "ENTER ($args)"
gen_log:log C "$args"
eval "exec $args &"
gen_log:log T "LEAVE"
}
proc cvs_catchcmd {args} {
#
# Run any command from the user menu and view its output.
# You can abort it too.
# called for usermenu() entries.
#
gen_log:log T "ENTER ($args)"
#gen_log:log C "$args"
set my_viewer [viewer::new "$args"]
$my_viewer\::do "$args"
gen_log:log T "LEAVE"
}
namespace eval ::exec {
variable instance 0
proc new {command {viewer {}} {show_stderr {1}} {filter {}}} {
variable instance
set my_idx $instance
incr instance
gen_log:log T "ENTER (\"$command\" \"$show_stderr\" \"$filter\")"
namespace eval $my_idx {
set my_idx [uplevel {concat $my_idx}]
variable command [uplevel {concat $command}]
variable viewer [uplevel {concat $viewer}]
variable filter [uplevel {concat $filter}]
variable show_stderr [uplevel {concat $show_stderr}]
global cvscfg
global errorCode
variable data {}
variable errmsg {}
variable procout ""
variable procerr ""
variable errpos 0
variable ExecDone 0
variable v_w
if {$viewer != ""} {
set v_w [namespace inscope $viewer {set w}]
}
proc out_handler { {viewer {}} {filter {}} } {
variable procout
variable procerr
variable ExecDone
variable errmsg
variable data
variable v_w
variable my_idx
variable show_stderr
global errorCode
# Blocking read -- returns -1 on EOF. Then you get the process return
# from errorCode
if {[gets $procout line] < 0} {
# [close] blocks until child process completes
if {[catch {close $procout} res]} {
gen_log:log E " Close Failed - errorCode $errorCode"
set ExecDone [list 1 $res $errorCode]
gen_log:log E " ExecDone $ExecDone"
if {$errmsg == ""} { set errmsg $res }
[namespace current]::err_handler
if {! [info exists command]} {set command ""}
if {! [info exists status]} {set status ""}
if {$errmsg == ""} {set errmsg "$command exited status $status"}
if {[string length $errmsg] < 512} {
cvsfail $errmsg .
}
# If we don't pop up an error dialog, let's at least try to show
# what happened in the viewer window, if there is one
if {$viewer != {}} {
$v_w.text insert end "\n$res" stderr
if {[tell $procerr]} {
seek $procerr 0
while {[gets $procerr erline] != -1} {
$v_w.text insert end "$erline\n" stderr
}
}
}
::exec::$my_idx\::abort
} else {
gen_log:log D " Close OK"
# Many CVS commands write stderr without err exit
if {[tell $procerr]} {
seek $procerr 0
while {[gets $procerr erline] != -1} {
gen_log:log E "$erline"
#if {$show_stderr && $viewer != {}} {
#$v_w.text insert end "$erline\n" stderr
#}
}
}
set ExecDone [list 0]
gen_log:log D " ExecDone $ExecDone"
}
catch {close $procerr}
if {$viewer != {}} {
pack forget $v_w.stop
pack $v_w.close -in $v_w.bottom -side right -ipadx 15
$v_w.close configure -state normal
}
return
}
if {$filter != ""} {
set filtered_line [$filter [namespace current] $line]
set texttag [lindex $filtered_line 0]
set line [lindex $filtered_line 1]
}
append data "$line\n"
if {$viewer != ""} {
if {$filter != ""} {
if {$texttag != "noshow"} {
$v_w.text insert end "$line\n" $texttag
}
} else {
$v_w.text insert end "$line\n"
}
$v_w.text yview end
}
gen_log:log D "STDOUT: $line"
}
proc err_handler {} {
variable errpos
variable procerr
variable errmsg
variable viewer
variable filter
variable show_stderr
variable v_w
# When new stuff appears in the error output file, get it. There may
# be more than one line.
set errmsg ""
if {[tell $procerr] != $errpos} {
seek $procerr $errpos start
while {[gets $procerr erline] != -1} {
append errmsg "\n$erline"
set errpos [tell $procerr]
}
gen_log:log E "$errmsg"
if {$viewer != "" && $show_stderr == 1} {
$v_w.text insert end "\n$errmsg" stderr
}
}
}
proc abort {} {
variable procout
variable procerr
variable procid
variable viewer
variable v_w
global tcl_platform
gen_log:log T "ENTER"
# This does the trick but it wont work on windows
if {![info exists procid]} {
gen_log:log D "procid is not defined"
return
}
catch "exec kill $procid" kres
unset procid
err_handler
if {$viewer != {}} {
pack forget $v_w.stop
pack $v_w.close -in $v_w.bottom -side right -ipadx 15
$v_w.close configure -state normal
}
catch {close $procout} cres
catch {close $procerr} cres
gen_log:log D "$kres"
gen_log:log T "LEAVE"
}
proc wait {} {
variable ExecDone
gen_log:log T "ENTER"
if {!$ExecDone} {
vwait [namespace current]::ExecDone
}
gen_log:log T "LEAVE"
}
proc output {} {
variable data
variable ExecDone
gen_log:log T "ENTER"
if {!$ExecDone} {
[namespace current]::wait
}
gen_log:log T "LEAVE"
return $data
}
proc run_exec {} {
global cvscfg
variable my_idx
variable procout
variable procerr
variable procid
variable errmsg
variable command
variable viewer
variable filter
variable v_w
variable w
fconfigure stderr -blocking false -buffering line
fconfigure stdout -blocking false -buffering line
# Set up the file we send the proc's stderr to
set errordir [file join $cvscfg(tmpdir) "cvstmpdir.[pid]"]
file mkdir $errordir
set errorfile [file join $errordir "exec$my_idx"]
set procerr [open $errorfile w+]
# Here's where we do it
gen_log:log C "$command"
set procout [open "| $command 2>@$procerr" r]
set procid [pid $procout]
# Dont ever do this. The whole thing depends on procout blocking
#fconfigure $procout -blocking false -buffering line
fileevent $procout readable [list [namespace current]::out_handler $viewer $filter]
flush $procerr
fileevent $procerr readable [list [namespace current]::err_handler]
# set buffering back to normal
fconfigure stdout -blocking true -buffering line
catch {fileevent $procerr readable {} }
}
after 0 [list [namespace current]::run_exec]
return [namespace current]
}
}
}
namespace eval ::viewer {
variable instance 0
#
# Set up a dialog containing a text box to view
# the report of the command during execution.
#
proc new {title} {
variable instance
set my_idx $instance
incr instance
namespace eval $my_idx {
global cvscfg
variable my_idx [uplevel {concat $my_idx}]
variable title [uplevel {concat $title}]
variable w ".view$my_idx"
variable log {}
variable searchstr {}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -