#!/usr/bin/wish -f # tkyap -- a TK shell for YAP # $Locker: $ # $Log: not supported by cvs2svn $ # Revision 1.1.1.1 2001/04/09 19:53:46 vsc # Imported sources # # Revision 1.1 1997/06/02 16:32:00 vsc # Initial revision # # Revision 1.1 1994/01/26 17:23:18 rvr # Luis Damas Version # # Created On : Wed Jan 26 17:21:54 1994 # Last Modified By: Nelma Moreira # Last Modified On: Sat Feb 5 20:24:04 1994 # Update Count : 39 # # HISTORY set service 8081 set YapOptions "-h1000 -s1000" # set TextFont "*7x13*" set version "97" #option add "*text*Font" $TextFont #option add "*message*Font" $TextFont #option add "*list*Font" $TextFont if {[file exists /vmlinuz]} { set TextFont "*6x10*" if {[file exists /home/luis/Yap94/linux]} { set homeyap /home/luis/Yap94/linux } else { set homeyap . } set PrologCommand "$homeyap/yap $homeyap/startup.yss -c localhost $service $YapOptions" set SolarisBug 0 } else { set PrologCommand "ny -h8000 -s1000" set SolarisBug 1 } set MaxHistory 100 ############################################################################### # Launch Prolog Proccess # create server socket -server client_connection $service proc client_connection {sock host lixo} { global from_yap to_yap set from_yap $sock set to_yap $sock puts "Got client $sock $host" fconfigure $sock -blocking 0 -buffering none fileevent $sock readable output_from_yap } # run yap in parallel set pid [eval exec $PrologCommand &] # make sure we kill Prolog when we are killed # signal trap SIGINT {ExitTkYap} proc ExitTkYap {} { global pid SaveHistory exec kill $pid exit } ############################################################################### # Create a mininal interface #### create a terminal window with a scrollbar frame .frame text .frame.text -bg white -font $TextFont \ -yscrollcommand {.frame.scrollbarv set} # insert wellcome message .frame.text insert end "Welcome to the Tcl/Tk Interface to YAP! ($version)\n" set iline {\n\n\n\n\n\n} ; # this is because of bug in solaris version # add scrollbar frame .frame.scrollframe -relief ridge -bd 2 scrollbar .frame.scrollbarv -command {.frame.text yview} pack append .frame.scrollframe .frame.scrollbarv {top expand filly} # pack text widget and scrollbar pack append .frame \ .frame.text {left frame center expand fill} \ .frame.scrollframe {right frame center filly} #### Menu #### frame .menu -relief raised -borderwidth 1 #pack .menu1 -before .frame -side top -fill x menubutton .menu.file -text "File" -menu .menu.file.m -underline 0 menu .menu.file.m .menu.file.m add command -label "Consult" -command {ConsultFile} -underline 0 .menu.file.m add command -label "Reconsult" \ -command {ReconsultFile} -underline 0 .menu.file.m add separator .menu.file.m add command -label "Exit" -command {ExitTkYap} -underline 0 menubutton .menu.exec -text "Execution" -menu .menu.exec.m -underline 0 menu .menu.exec.m .menu.exec.m add command -label "Interrupt" \ -command {global tcl_mode; set tcl_mode 0; exec kill -SIGINT $pid} .menu.exec.m add separator .menu.exec.m add command -label "Statistics" -command {YapStats} pack .menu.file .menu.exec -side left menubutton .menu.help -text "Help" -menu .menu.help.m -underline 0 menu .menu.help.m pack .menu.help -side right #### pack panes together pack append . \ .menu {top fillx frame n} \ .frame {left frame n} proc ReconsultFile {} { global to_yap set file [FileSelect "File to Reconsult" "*.yap"] if {$file!=""} { puts $to_yap "reconsult('$file')." flush $to_yap } } proc ConsultFile {} { global to_yap set file [FileSelect "File to Consult" "*.yap"] if {$file!=""} { puts $to_yap "consult('$file')." flush $to_yap } } proc YapStats {} { global to_yap from_yap puts $to_yap "statistics." flush $to_yap } ############################################################################ # Handle input from the keyboard # InputStart is index of start of input set InputStart [.frame.text index {end - 1 chars}] # create a read_only range of text .frame.text tag add rdonly 0.0 "$InputStart -0 chars" # prevent user from modifying previous text by jumping to end of text .frame.text tag bind rdonly { if {[.frame.text compare insert < $InputStart]} { .frame.text mark set insert end } } # pass ^C to yap bind .frame.text { set tcl_mode 0 .frame.text yview -pickplace end exec kill -SIGINT $pid } # add Readline/Emacs like bindings bind .frame.text { .frame.text mark set insert $InputStart } bind .frame.text { .frame.text mark set insert {insert -1 chars} } bind .frame.text { .frame.text delete insert } bind .frame.text { .frame.text mark set insert end } bind .frame.text { .frame.text mark set insert {insert +1 chars} } bind .frame.text { .frame.text delete insert "insert lineend" } bind .frame.text { if {[.frame.text compare insert > $InputStart]} { .frame.text delete "insert -1 chars" } } bind .frame.text { if {[.frame.text compare insert > $InputStart]} { .frame.text delete "insert -1 chars" } } # add history bindings set history {} set history_len 0 set history_dir [exec pwd] if {[file isfile .yap_history]} { set file [open "$history_dir/.yap_history"] while {[gets $file s]>0} { lappend history $s incr history_len } close $file } set history_ind $history_len proc SaveHistory {} { global history_len history_ind history history_dir set file [open "$history_dir/.yap_history" w] for {set i 0} {$i<$history_len} {incr i} { puts $file [lindex $history $i] } close $file } proc AddHistory {line} { global history_len history_ind history MaxHistory if {[string length $line]<3} {return} set i [lsearch -exact $history $line] if {$i>=0} { set history [lreplace $history $i $i] incr history_len -1 } if {$history_len>$MaxHistory} { set history [lreplace $history 0 0] incr history_len -1 } lappend history $line incr history_len set history_ind $history_len } bind .frame.text { if {$history_ind==$history_len} { set CurrentLine [.frame.text get $InputStart "$InputStart lineend"] } if {$history_ind>0} { incr history_ind -1 .frame.text delete $InputStart "$InputStart lineend" .frame.text insert $InputStart [lindex $history $history_ind] } } bind .frame.text { if {$history_ind<$history_len} { incr history_ind .frame.text delete $InputStart "$InputStart lineend" if {$history_ind==$history_len} { .frame.text insert $InputStart $CurrentLine } else { .frame.text insert $InputStart [lindex $history $history_ind] } } } # catch the enter key and send the input line to yap bind .frame.text {HandleInputLine} proc HandleInputLine {} { global InputStart to_yap iline set iline [.frame.text get $InputStart end] # .frame.text insert end "\n" AddHistory $iline puts "sending: '$iline'" puts -nonewline $to_yap "$iline" flush $to_yap set InputStart [.frame.text index end] .frame.text tag add rdonly 1.0 "$InputStart -0 chars" } ############################################################################## # Handle output from Yap set tcl_mode 0 set tcl_buf {} proc out_filter {s} { global tcl_mode tcl_buf InputStart iline SolarisBug while {$s!=""} { set i [string first \001 $s] set j [string first \002 $s] set xflag 0 if {$j>=0 && ($i==-1 || $j<$i) } {set xflag 1; set i $j} set new_mode $tcl_mode if {$i<0} { set ch $s set s "" } else { set ch [string range $s 0 [expr $i-1]] set s [string range $s [expr $i+1] end] if {$xflag==0} { set new_mode [expr 1-$tcl_mode] } } # puts "$i $j '$ch' '$s' $xflag" if {$tcl_mode} { append tcl_buf $ch } else { if {$SolarisBug} { # under Solaris we get echo on the fisrt line sent to # Yap. So remove it ... if {[csubstr $ch 0 [string length $iline]]=="$iline"} { set ch [string range $ch [string length $iline\r\n] end] set SolarisBug 0 puts fixed } } .frame.text insert "$InputStart" $ch set ll [string length $ch] set InputStart [.frame.text index "$InputStart +$ll chars"] .frame.text tag add rdonly 1.0 "$InputStart -0 chars" .frame.text yview -pickplace end update idletasks } if {$xflag} { puts "eval $tcl_buf" flush stdout set res [catch "eval $tcl_buf" errMsg ] puts "$res $errMsg" if {$res!=0} { tkerror $errMsg } set tcl_buf {} } set tcl_mode $new_mode } } # this is an idle task routine to handle output from yap proc idle_task {} { global from_yap set got 0 while {$got<500} { set fr [select [list $from_yap] {} {} 0.01] set fr [lindex $fr 0] #puts "fr=$fr" if {$fr != {}} { #puts "reading" set ch [read $from_yap ] incr got [string length $ch] out_filter $ch #puts "read '$ch'" } else { if {$got} { .frame.text yview -pickplace end } flush stdout break } } after 100 idle_task } proc output_from_yap {} { global from_yap set ch [read $from_yap] puts "got: '$ch'" out_filter $ch .frame.text yview -pickplace end # fileevent $from_yap readable output_from_yap update } #### File selection... proc FileSelectOk {} { global FileSelectRes set FileSelectRes ok } proc FileSelectCancel {} { global FileSelectRes set FileSelectRes cancel } proc FileSelectUpdate {} { global FileSelectFilter set wd [exec pwd] set dir [open "|ls -a"] .fileSelect.list delete 0 end while {[gets $dir f]>0} { if {[file isdirectory $f]} { .fileSelect.list insert end $f } elseif {[string match $FileSelectFilter $f]} { .fileSelect.list insert end $f } } close $dir .fileSelect.dir configure -text "Dir: $wd" } proc FileSelect {msg filter} { global FileSelectRes FileSelectFilter set FileSelectFilter $filter if {[winfo exists .fileSelect]} {destroy .fileSelect} toplevel .fileSelect message .fileSelect.msg -text $msg -width 300 frame .fileSelect.lbox -relief raised -bd 2 listbox .fileSelect.list -bd 1 \ -yscrollcommand {.fileSelect.scroll set} scrollbar .fileSelect.scroll -bd 2 -command {.fileSelect.list yview} pack append .fileSelect.lbox \ .fileSelect.list {left expand fill} \ .fileSelect.scroll {right filly} set wd [exec pwd] label .fileSelect.dir -text "Directory: $wd " frame .fileSelect.buttons button .fileSelect.buttons.ok -text "Ok" -command "FileSelectOk" button .fileSelect.buttons.cancel -text "Cancel" -command "FileSelectCancel" pack .fileSelect.buttons.ok .fileSelect.buttons.cancel -side left -padx 10 pack append .fileSelect \ .fileSelect.msg {top expand fillx } \ .fileSelect.dir {expand fillx} \ .fileSelect.lbox {expand fillx} \ .fileSelect.buttons {expand fillx pady 5} tk_listboxSingleSelect .fileSelect.list bind .fileSelect.list "FileSelectOk" set w .fileSelect wm withdraw $w update idletasks set x [expr [winfo screenwidth $w]/2 - [winfo reqwidth $w]/2 \ - [winfo vrootx [winfo parent $w]]] set y [expr [winfo screenheight $w]/2 - [winfo reqheight $w]/2 \ - [winfo vrooty [winfo parent $w]]] wm geom $w +$x+$y wm deiconify $w set oldFocus [focus] grab .fileSelect while 1 { set FileSelectRes {} FileSelectUpdate update tkwait variable FileSelectRes if {$FileSelectRes=="cancel"} {break} set file [.fileSelect.list curselection ] if {$file!=""} { set file $wd/[.fileSelect.list get $file] if {[file isdirectory $file]} { set wd $file cd $file } else {break} } } destroy .fileSelect focus $oldFocus if {$FileSelectRes=="cancel"} { set file "" cd $wd } return $file }