655 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
			
		
		
	
	
			655 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
| ;;;;
 | |
| ;;;; console.stk 			-- A simple console written in STk
 | |
| ;;;;
 | |
| ;;;; Copyright © 1998-1999 Erick Gallesio - I3S-CNRS/ESSI <eg@unice.fr>
 | |
| ;;;; 
 | |
| ;;;; Permission to use, copy, modify, distribute,and license this
 | |
| ;;;; software and its documentation for any purpose is hereby granted,
 | |
| ;;;; provided that existing copyright notices are retained in all
 | |
| ;;;; copies and that this notice is included verbatim in any
 | |
| ;;;; distributions.  No written agreement, license, or royalty fee is
 | |
| ;;;; required for any of the authorized uses.
 | |
| ;;;; This software is provided ``AS IS'' without express or implied
 | |
| ;;;; warranty.
 | |
| ;;;;
 | |
| ;;;;           Author: Erick Gallesio [eg@unice.fr]
 | |
| ;;;;    Creation date: 29-Oct-1998 18:51
 | |
| ;;;; Last file update:  3-Sep-1999 19:50 (eg)
 | |
| 
 | |
| (require "font-lock")
 | |
| (require "butbar")
 | |
| (require "edit")
 | |
| 
 | |
| ;;;
 | |
| ;;; Variables which which can be overloaded by the user file ~/.stkvars
 | |
| ;;;
 | |
| (define-module STk
 | |
|   (define *show-splash-screen* #t)
 | |
|   (define *console-font*       '(courier)))
 | |
| 
 | |
| ;;;
 | |
| ;;; The rest of the file is in the Tk module
 | |
| ;;;
 | |
| 
 | |
| (select-module Tk)
 | |
| (export make-console)
 | |
| (autoload "console-customize" console-customize console-customize-save)
 | |
| 
 | |
| 
 | |
| ;=============================================================================
 | |
| ;
 | |
| ; Globals
 | |
| ;
 | |
| ;=============================================================================
 | |
| 
 | |
| (define *console-version-message* 
 | |
|   (string-append "STk version" (version) 
 | |
| 		 "\n(Tk version is " *tk-patch-level* ")\n\n"
 | |
| 		 "Copyright © 1993-1999\nErick Gallesio - I3S-CNRS/ESSI\n"
 | |
| 		 "<eg@unice.fr>"))
 | |
| 
 | |
| ;=============================================================================
 | |
| ;
 | |
| ; Utilities
 | |
| ;
 | |
| ;=============================================================================
 | |
| 
 | |
| (define (bad-port . _)
 | |
|   (error "console is not tied to a standard input port"))
 | |
| 
 | |
| 
 | |
| (define (set-cursor console pos)
 | |
|   (let ((pos (if (console 'compare pos "==" "end") "end - 1 chars" pos)))
 | |
|     (console 'mark 'set 'insert pos)
 | |
|     (console 'tag 'remove 'sel "1.0" "end")
 | |
|     (console 'see "insert")))
 | |
| 
 | |
| ;;
 | |
| ;; console-insert --
 | |
| ;;    Insert a string into a text at the point of the insertion cursor. If
 | |
| ;;    there is a selection in the text, and it covers the point of the
 | |
| ;;    insertion cursor, then delete the selection before inserting.
 | |
| ;;    Insertion is restricted to the prompt area.  
 | |
| ;;
 | |
| (define (console-insert console s)
 | |
|   (unless (zero? (string-length s))
 | |
|     ; 1. Raise window
 | |
|     (raise (winfo 'top console))
 | |
|     ; 2. Do text insertion
 | |
|     (catch 
 | |
|         (when (and (console 'compare "sel.first" "<=" "insert")
 | |
| 		   (console 'compare "sel.last" ">=" "insert"))
 | |
| 	  (console 'tag 'remove 'sel "sel.first" "prompt-end")
 | |
| 	  (console 'delete "sel.first" "sel.last")))
 | |
|     (if (console 'compare "insert" "<" "prompt-end")
 | |
| 	(console 'mark 'set "insert" "end"))
 | |
|     (console 'insert "insert" s "input stdin")
 | |
|     (console 'see "insert")
 | |
|     ; 3. Fontify
 | |
|     (idle-fontify console)))
 | |
| 
 | |
| ;;
 | |
| ;; console-output --
 | |
| ;; 	This routine is called directly by the interpreter to cause a string
 | |
| ;; 	to be displayed in the console.
 | |
| ;;
 | |
| (define (console-output console string file-type)
 | |
|   (console 'insert "output" string file-type)
 | |
|   (console 'see "insert"))
 | |
| 
 | |
| 
 | |
| ;;
 | |
| ;; console-load
 | |
| ;;
 | |
| (define (console-load)
 | |
|   (let ((file (Tk:get-open-file :title "Load File")))
 | |
|     (and file (load file))))
 | |
| 
 | |
| ;;
 | |
| ;; console-about
 | |
| ;;
 | |
| (define (console-about)
 | |
|   (let* ((top (toplevel '.__cons_about__))
 | |
| 	 (m   (label (& top ".m") :justify "center" :foreground "IndianRed4"
 | |
| 		     :text *console-version-message*))
 | |
| 	 (img (make-image "STk-big-logo.gif"))
 | |
| 	 (lab (label (& top ".l") :image img :relief "groove" :bd 5))
 | |
| 	 (q   (button (& top ".b") :text "Close" 
 | |
| 		      :command (lambda () 
 | |
| 				 (delete-image "STk-big-logo.gif") 
 | |
| 				 (destroy top)))))
 | |
|     (wm 'title top "About STk ...")
 | |
|     (grab top)
 | |
|     (raise top)
 | |
|     (pack lab :padx 20 :pady 20)
 | |
|     (pack m :fill "both" :expand #t)
 | |
|     (pack q :ipadx 10 :pady 10)))
 | |
| 
 | |
| ;;
 | |
| ;; console-splash-screen
 | |
| ;;
 | |
| (define (console-splash-screen)
 | |
|   (let* ((width  400)
 | |
| 	 (height 300)
 | |
| 	 (top    (toplevel '.__cons_splash__ :bg "white" :relief "solid" :bd 3
 | |
| 			   :width width :height height))
 | |
| 	 (m   	 (label (& top ".m") :justify "center" :fg "IndianRed4" 
 | |
| 			:bg "white" :text *console-version-message*))
 | |
| 	 (img    (make-image "STk-big-logo.gif"))
 | |
| 	 (lab    (label (& top ".l") :image img :bd 0))
 | |
| 	 (w      (winfo 'screenwidth top))
 | |
| 	 (h      (winfo 'screenheight top))
 | |
| 	 (kill   (lambda () 
 | |
| 		   (catch (delete-image "STk-big-logo.gif"))
 | |
| 		   (destroy top))))
 | |
|     (wm 'over top #t)
 | |
|     (wm 'geometry top (format #f "+~A+~A" (quotient (- w 400) 2) 
 | |
| 			                  (quotient (- h 300) 2)))
 | |
|     (pack 'propagate top #f)
 | |
|     (pack lab m)
 | |
|     (bind top "<1>" kill) 	;; for the impatients
 | |
|     (raise top)
 | |
|     (after 2000 kill)))
 | |
| 
 | |
| ;;
 | |
| ;; console-logo
 | |
| ;;
 | |
| (define (console-logo console)
 | |
|   (let ((l0 (label (& console ".l0") :image (make-image "LineLeft.gif")     :bd 0))
 | |
| 	(l1 (label (& console ".l1") :image (make-image "STk-tiny-logo.gif"):bd 0))
 | |
| 	(l2 (label (& console ".l2") :image (make-image "LineRight.gif")    :bd 0)))
 | |
|     (console 'insert 'insert "\n")
 | |
|     (console 'window 'create "insert" :window l0 :align "baseline")
 | |
|     (console 'insert 'insert " ")
 | |
|     (console 'window 'create "insert" :window l1 :align "baseline")
 | |
|     (console 'insert 'insert " ")
 | |
|     (console 'window 'create "insert" :window l2 :align "baseline")
 | |
|     (console 'tag 'add "center" "1.0" "insert")
 | |
|     (console 'tag 'configure "center" :justify "center")
 | |
|     (console 'insert "insert" "\n\n")))
 | |
| 
 | |
| ;;
 | |
| ;; console-invoke --
 | |
| ;;
 | |
| ;; Processes the command line input.  If the command is complete it
 | |
| ;; is evaluated.  
 | |
| ;;
 | |
| 
 | |
| (define (console-invoke console module stdin stdout stderr)
 | |
|   (let* ((cmd      "")
 | |
| 	 (mod      (or module (%get-selected-module)))
 | |
| 	 (env      (module-environment mod))
 | |
| 	 (stdcons? (eq? stdin (current-input-port))))
 | |
|     
 | |
|     ;; Set cmd to be the concatenation of all ranges of text with tag "input"
 | |
|     (let ((hd (console 'tag 'ranges "input")))
 | |
|       (while (not (null? hd))
 | |
| 	 (set! cmd (string-append cmd (console 'get (car hd) (cadr hd))))
 | |
| 	 (set! hd (cddr hd))))
 | |
| 
 | |
|     (if (complete-sexpr? cmd)
 | |
| 	(begin
 | |
| 	  ;; We have a complete set of expression to evaluate
 | |
| 	  (console 'mark 'set "output" "end")
 | |
| 	  (console 'tag "delete" "input")
 | |
| 	  
 | |
| 	  (with-input-from-string cmd
 | |
| 	    (lambda ()
 | |
| 	      (do ((sexpr (read) (read)))
 | |
| 		  ((eof-object? sexpr))
 | |
| 		(add-history! console (substring cmd 0 (- (string-length cmd) 1)))
 | |
| 		(if stdcons?
 | |
| 		    ;; We are on the main console. Directly fill the std buffer 
 | |
| 		    (%fill-stdin cmd)
 | |
| 		    ;; Not the standard console. Use redirection
 | |
| 		    (dynamic-wind 
 | |
| 		       (lambda () #f)
 | |
| 		       (lambda ()
 | |
| 			 (with-input-from-port stdin 
 | |
| 			   (lambda ()
 | |
| 			     (with-output-to-port stdout
 | |
| 			       (lambda ()
 | |
| 				 (with-error-to-port stderr
 | |
| 				   (lambda ()
 | |
| 				     (let ((E (eval sexpr env)))
 | |
| 				       (repl-display-result E)))))))))
 | |
| 		       (lambda ()
 | |
| 			 (console-prompt console module stdout stderr)
 | |
| 			 (console 'yview :pickplace "insert"))))))))
 | |
| 	;; Not a complete sexpr. Indent text 
 | |
| 	(font-lock-indent console "input"))))
 | |
| 
 | |
| 
 | |
| ;=============================================================================
 | |
| ;
 | |
| ; console-prompt
 | |
| ;
 | |
| ;=============================================================================
 | |
| (define (console-prompt console module stdout stderr)
 | |
|   (let ((temp (console 'index "end -1 char"))
 | |
| 	(mod  (or module (%get-selected-module))))
 | |
|     (with-output-to-port stdout 
 | |
|       (lambda()
 | |
| 	(with-error-to-port stderr
 | |
| 	   (lambda ()
 | |
| 	     (repl-display-prompt mod)))))
 | |
|     (console 'mark 'set "output" temp)
 | |
|     (set-cursor console "end")
 | |
|     (console 'mark 'set "prompt-end" "insert")		; FIXME: obligé de mettre 
 | |
|     (console 'mark 'gravity "prompt-end" 'left)		; la gravité?
 | |
|     (console 'mark 'set "start_fontify" "insert")
 | |
|     (console 'mark 'gravity "start_fontify" 'left)))
 | |
|     
 | |
| 
 | |
| 
 | |
| (define console-display-prompt  #f)
 | |
| 
 | |
| (define (make-console-display-prompt console stdout stderr)
 | |
|   (set! console-display-prompt
 | |
| 	(lambda (module)
 | |
| 	  (console-prompt console  module stdout stderr))))
 | |
| 
 | |
| ;=============================================================================
 | |
| ;
 | |
| ; History management
 | |
| ;
 | |
| ;=============================================================================
 | |
| (define (update-history! console h index)
 | |
|   (set-widget-data! console (list :hist h :index index)))
 | |
| 
 | |
| (define (get-history console)
 | |
|   (let ((data (get-widget-data console)))
 | |
|     (if data 
 | |
| 	; we have already an history for this console
 | |
| 	(values (get-keyword :hist data) (get-keyword :index data))
 | |
| 	; make an empty history for this console
 | |
| 	(values '() 0))))
 | |
| 
 | |
| (define (add-history! console line)
 | |
|   (call-with-values (lambda ()      (get-history console))
 | |
| 		    (lambda (h idx) (update-history! console (cons line h) 0))))
 | |
| 
 | |
| (define(follow-history console oper)
 | |
|   (call-with-values 
 | |
|       (lambda () (get-history console))
 | |
|       (lambda (h idx)
 | |
| 	(if (null? h)
 | |
| 	    ""
 | |
| 	    (let ((r (list-ref h idx)))
 | |
| 	      (update-history! console h (modulo (oper idx 1) (length h)))
 | |
| 	      r)))))
 | |
|  
 | |
| (define (previous-history console)
 | |
|   (follow-history console +))
 | |
| 
 | |
| (define (next-history console)
 | |
|   (follow-history console -))
 | |
| 
 | |
| ;=============================================================================
 | |
| ;
 | |
| ; Init-console-bindings
 | |
| ;
 | |
| ;    This is quite unreadable, but who cares?
 | |
| ;
 | |
| ;=============================================================================
 | |
| 
 | |
| (define (init-console-bindings console module stdin stdout stderr)
 | |
|   ;; Ignore all Alt, Meta, and Control keypresses unless explicitly bound.
 | |
|   ;; Otherwise, if a widget binding for one of these is defined, the
 | |
|   ;; <KeyPress> class binding will also fire and insert the character,
 | |
|   ;; which is wrong.  Ditto for <Escape>.
 | |
|   (bind console "<Alt-KeyPress>"     "")
 | |
|   (bind console "<Meta-KeyPress>"    "")
 | |
|   (bind console "<Control-KeyPress>" "")
 | |
|   (bind console "<Escape>"           "")
 | |
|   (bind console "<KP_Enter>" 	     "")
 | |
| 
 | |
|   ;; Inserting characters
 | |
|   (bind console "<Tab>" (lambda ()
 | |
| 			  (console-insert console "\t")
 | |
| 			  (focus console)
 | |
| 			  'break))
 | |
|   
 | |
|   (bind console "<Return>" (lambda ()
 | |
| 			     (console 'mark 'set 'insert "end - 1c")
 | |
| 			     (console-insert console "\n")
 | |
| 			     (console-invoke console module stdin stdout stderr)
 | |
| 			     'break))
 | |
| 
 | |
|   (bind console "<KeyPress>" (lambda (|A|)
 | |
| 			       (console-insert console |A|)
 | |
| 			       'break))
 | |
| 
 | |
|   ;; Deleting characters
 | |
|   (let ((del (lambda (comparison)
 | |
| 	       (idle-fontify console)
 | |
| 	       (if (null? (console 'tag 'nextrange 'sel "1.0" 'end))
 | |
| 		   (if (console 'compare "insert" comparison "prompt-end") 'break)
 | |
| 		   (console 'tag 'remove 'sel "sel.first" "prompt-end")))))
 | |
|     (bind console "<Delete>"    (lambda () (del "<")))
 | |
|     (bind console "<Control-d>" (lambda () (del "<")))
 | |
|     (bind console "<BackSpace>" (lambda () (del "<=")))
 | |
|     (bind console "<Control-k>" (lambda ()
 | |
| 				  (idle-fontify console)
 | |
| 				  (if (console 'compare "insert" "<" "prompt-end")
 | |
| 				      (console 'mark 'set "insert" "prompt-end"))))
 | |
| 
 | |
|     (bind console "<Meta-d>" (lambda ()
 | |
| 			       (idle-fontify console)
 | |
| 			       (if (console 'compare "insert" "<" "prompt-end")
 | |
| 				   'break)))
 | |
|     (bind console "<Meta-BackSpace>" 
 | |
| 	  (lambda () 
 | |
| 	    (idle-fontify console)
 | |
| 	    (if (console 'compare "insert" "<=" "prompt-end") 'break))))
 | |
|   
 | |
|   ;; Moving around
 | |
|   (let ((start (lambda ()
 | |
| 		 (idle-fontify console)
 | |
| 		 (let ((pos (if (console 'comp "insert linestart" ">" "prompt-end")
 | |
| 				"insert linestart"
 | |
| 				"prompt-end")))
 | |
| 		 (set-cursor console pos)
 | |
| 		 'break)))
 | |
| 	(end    (lambda ()
 | |
| 		  (idle-fontify console)
 | |
| 		  (set-cursor console "insert lineend")
 | |
| 		  'break))
 | |
| 	(forw   (lambda ()
 | |
| 		  (if (console 'compare "insert" ">=" "prompt-end")
 | |
| 		      (set-cursor console "insert+1c"))
 | |
| 		  'break))
 | |
| 	(back (lambda ()
 | |
| 		(if (console 'compare "insert" ">=" "prompt-end")
 | |
| 		    (set-cursor console "insert-1c"))
 | |
| 		'break))
 | |
| 	(nop  (lambda () #f)))
 | |
|     (bind console "<Control-a>"     start)
 | |
|     (bind console "<Home>"          start)
 | |
|     (bind console "<Control-e>"     end)
 | |
|     (bind console "<End>"           end)
 | |
|     (bind console "<Control-f>"     forw)
 | |
|     (bind console "<Right>"         forw)
 | |
|     (bind console "<Control-b>"     back)
 | |
|     (bind console "<Left>"          back)
 | |
|     (bind console "<Control-Left>"  nop)
 | |
|     (bind console "<Control-Right>" nop))
 | |
| 
 | |
|   ;; History
 | |
|   (let ((prev (lambda ()
 | |
| 		(when (console 'compare "insert linestart" "<" "prompt-end")
 | |
| 		  (console 'delete "prompt-end" "end")
 | |
| 		  (console-insert console (previous-history console))
 | |
| 		  'break)))
 | |
| 	(next (lambda ()
 | |
| 		(when (console 'compare "insert linestart" "<" "prompt-end")
 | |
| 		  (console 'delete "prompt-end" "end")
 | |
| 		  (console-insert console (next-history console))
 | |
| 		  'break))))
 | |
|     (bind console "<Control-p>" prev)
 | |
|     (bind console "<Up>"	prev)
 | |
|     (bind console "<Control-n>" next)
 | |
|     (bind console "<Down>"	next))
 | |
|   
 | |
|   (bind console "<<PasteSelection>>" (lambda ()
 | |
| 				       (catch 
 | |
| 					 (console-insert console 
 | |
| 					      (selection 'get :displayof console)))
 | |
| 				       (fontify-buffer console "prompt-end")
 | |
| 				       'break))
 | |
|   (bind console "<<Cut>>" (lambda ()
 | |
| 			    (catch 
 | |
| 			       (let ((buffer (console 'get "sel.first" "sel.last")))
 | |
| 				 (clipboard 'clear :displayof console)
 | |
| 				 (clipboard 'append :displayof console buffer)
 | |
| 				 (console 'delete "sel.first" "sel.last")))
 | |
| 			    'break))
 | |
|   
 | |
|   (bind console "<<Copy>>" (lambda ()
 | |
| 			     (catch 
 | |
| 			      (let ((buffer (console 'get "sel.first" "sel.last")))
 | |
| 				(clipboard 'clear :displayof console)
 | |
| 				(clipboard 'append :displayof console buffer)))
 | |
| 			     'break))
 | |
|   (bind console "<<Paste>>" (lambda ()
 | |
| 			      (catch
 | |
| 			       (let ((clip (selection 'get 
 | |
| 						      :displayof console 
 | |
| 						      :selection "CLIPBOARD")))
 | |
| 				 (console-insert console clip)
 | |
| 				 (fontify-buffer console "prompt-end")))
 | |
| 			      'break))
 | |
|   (bind console "<Control-c>" (lambda ()
 | |
| 				(bell)
 | |
| 				(send-signal |SIGINT|)))
 | |
| 
 | |
| 
 | |
|   ;; Use fontification for the console (but call it by hand because the console
 | |
|   ;; completely manage text insertion)
 | |
|   (make-fontifiable console)
 | |
|   (bindtags console (remove  "ScmTxt" (bindtags console)))
 | |
| )
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| ;=============================================================================
 | |
| ;
 | |
| ; init-console
 | |
| ;
 | |
| ;=============================================================================
 | |
| 
 | |
| (define (init-console module std-console?)
 | |
|   (let* ((top     (toplevel (gensym "._cons_") :class "STk"))
 | |
| 	 (console (text (& top ".txt") :background "white" :setgrid #t 
 | |
| 				       :font *console-font*))
 | |
| 	 (sb	  (scrollbar (& top ".sb") :width 10))
 | |
| 	 (mb	  (console-make-menubar   top console))
 | |
| 	 (bb	  (console-make-buttonbar top console))
 | |
| 	 (stdin   (if std-console? 
 | |
| 		      (current-input-port)
 | |
| 		      (open-input-virtual bad-port bad-port bad-port bad-port)))
 | |
| 	 (stdout  (open-output-virtual 
 | |
| 		    (lambda (c p) (console-output console (string c) "stdout"))
 | |
| 		    (lambda (s p) (console-output console s "stdout")(update 'idle))
 | |
| 		    #f
 | |
| 		    #f))
 | |
| 	 (stderr  (open-output-virtual 
 | |
| 		    (lambda (c p) (console-output console (string c) "stderr"))
 | |
| 		    (lambda (s p) (console-output console s "stderr")(update 'idle))
 | |
| 		    #f
 | |
| 		    #f)))
 | |
| 
 | |
|     ;; Associate the scrollbar commands
 | |
|     (tk-set! sb :command      (lambda l (apply console 'yview l)))
 | |
|     (tk-set! console :yscroll (lambda l (apply sb 'set l)))
 | |
|     
 | |
|     ;; Pack stuff
 | |
|     (pack bb :fill "x")
 | |
| 
 | |
|     (pack console :expand #t :fill "both" :side "left")
 | |
|     (pack sb :expand #f :fill "y" :side "left")
 | |
| 
 | |
|     (wm 'title top (if module 
 | |
| 		       (format #f "Console (~A)" (module-name module))
 | |
| 		       "STk console"))
 | |
|     (if std-console?
 | |
| 	(let ((exit (lambda () (exit 0))))
 | |
| 	  (wm 'protocol top "WM_DELETE_WINDOW" exit)
 | |
| 	  (bind console "<Destroy>" 	       exit)))
 | |
| 
 | |
|     (console 'tag 'configure "stdin"  :foreground "black")
 | |
|     (console 'tag 'configure "stdout" :foreground "midnightblue")
 | |
|     (console 'tag 'configure "stderr" :foreground "#ff2e2f") ;; i.e. "DarkRed"
 | |
| 
 | |
|     (console 'mark 'set "output" (console 'index "end - 1 char"))
 | |
|     (set-cursor console "end")
 | |
|     (console 'mark 'set "prompt-end" "insert")
 | |
|     (console 'mark 'gravity "prompt-end" "left")
 | |
| 
 | |
|     (init-console-bindings console module stdin stdout stderr)
 | |
|     (if std-console?
 | |
| 	(begin
 | |
| 	  (if *show-splash-screen* (console-splash-screen))
 | |
| 	  (if *print-banner*       (console-logo console))
 | |
| 	  (%change-standard-ports stdin stdout stderr)
 | |
| 	  (make-console-display-prompt console stdout stderr))
 | |
| 	(console-prompt console module stdout stderr))
 | |
|     (focus console)
 | |
|     console))
 | |
| 
 | |
| 
 | |
| (define (console-make-buttonbar parent txt)
 | |
|   (let* ((f (frame (& parent ".butbar") :relief "ridge" :bd 1)))
 | |
|     (make-button-bar f 
 | |
|       (list 5
 | |
| 	    (list "tb_console.gif"
 | |
| 		  "Open New Console"
 | |
| 		  make-console)
 | |
| 	    (list "tb_edit.gif"
 | |
| 		  "Open New Editor"
 | |
| 		  ed)
 | |
| 	    (list "tb_customize.gif"
 | |
| 		  "Customize Environment"
 | |
| 		  (lambda () (console-customize))) ; delayed to avoid autoload
 | |
| 	    (list "tb_fileopen.gif"
 | |
| 		  "Load File"  
 | |
| 		  console-load)
 | |
| 	    20
 | |
| 	    (list "tb_copy.gif"
 | |
| 		  "Copy"
 | |
| 		  (lambda () (event 'gen txt "<<Copy>>")))
 | |
| 	    (list "tb_paste.gif"
 | |
| 		  "Paste"
 | |
| 		  (lambda () (event 'gen txt "<<Paste>>")))
 | |
| 	    (list "tb_cut.gif"
 | |
| 		  "Cut"
 | |
| 		  (lambda () (event 'gen txt "<<Cut>>")))
 | |
| 	    20
 | |
| 	    (list "tb_info.gif"
 | |
| 		  "Help on Console"
 | |
| 		  (lambda () (help "make-console")))))
 | |
|     f))
 | |
| 
 | |
| 
 | |
| (define (make-console-in)
 | |
|   (define name ".__cons_module_chooser")
 | |
| 
 | |
|   (define (create)
 | |
|     (catch 
 | |
|       (make-console :module (string->symbol (selection 'get)))
 | |
|       (after 'idle (lambda () (destroy name)))))
 | |
| 
 | |
|   ;;;;
 | |
|   ;;;; make-console-in starts here
 | |
|   ;;;;
 | |
|   (destroy name)
 | |
|   (let* ((all  (sort (map module-name (all-modules))
 | |
| 		     (lambda (x y)
 | |
| 		       (string<? (symbol->string x) (symbol->string y)))))
 | |
| 	 (top  (toplevel name))
 | |
| 	 (lab  (label (& top ".lab") :text "Choose a module for new console"))
 | |
| 	 (f0   (frame (& top ".f0")))
 | |
| 	 (lb   (listbox (& f0 ".lb") :bg "white" :fg "RoyalBlue" :width 50))
 | |
| 	 (sb   (scrollbar (& f0 ".sb") :width 10))
 | |
| 	 (f1   (frame (& top ".f1") :relief "ridge" :bd 2))
 | |
| 	 (doit (button (& f1 ".doit") :text "Create console" :command create))
 | |
| 	 (quit (button (& f1 ".quit") :text "Cancel"
 | |
| 		       :command (lambda () (destroy top)))))
 | |
|     (wm 'title top "Choose module")
 | |
|     ;; Fill in the listbox
 | |
|     (apply lb 'insert 0 all)
 | |
|     ;; Pack everybody
 | |
|     (pack lab :expand #f :pady 10 :padx 20 :anchor 'w)
 | |
|     (pack lb :fill 'both :side 'left :expand #t)
 | |
|     (pack sb :fill 'y :side 'right)
 | |
|     (pack f0 :padx 20 :pady 10 :expand #t :fill 'both)
 | |
|     (pack doit quit :side 'left :padx 3 :pady 3)
 | |
|     (pack f1 :expand #f :fill 'x)
 | |
|     ;; Add command to connect the scrollbar
 | |
|     (tk-set! lb :yscrollcom (lambda l (apply sb 'set l)))
 | |
|     (tk-set! sb :command    (lambda l (apply lb 'yview l)))
 | |
|     ;; Add binding such as double click on the list create a console
 | |
|     (bind lb "<Double-ButtonRelease-1>" create)))
 | |
| 
 | |
| 
 | |
| (define (console-make-menubar top console)
 | |
|   (let* ((f    (frame (& top ".f") :relief "ridge" :bd 1))
 | |
| 	 (b    (make-bordered-frame f))
 | |
| 	 (file (menubutton (& b ".file") :text "File"))
 | |
| 	 (edit (menubutton (& b ".edit") :text "Edit"))
 | |
| 	 (conf (menubutton (& b ".conf") :text "Customize"))
 | |
| 	 (hlp  (menubutton (& b ".help") :text "Help")))
 | |
|     
 | |
|     ;; File Menu
 | |
|     (let ((m (menu (& file ".m") :tearoff #f)))
 | |
|       (m 'add 'command :label "Load ..." :command console-load)
 | |
|       (m 'add 'separator)
 | |
|       (m 'add 'command :label "New Console" :command make-console)
 | |
|       (m 'add 'command :label "New Console in ..." :command make-console-in)
 | |
|       (m 'add 'separator)
 | |
|       (m 'add 'command :label "Hide Console" :command (lambda () (wm 'iconify top)))
 | |
|       (m 'add 'command :label "Close Console" :command (lambda () (destroy top)))
 | |
|       (m 'add 'command :label "Exit STk" :command (lambda () (exit 0)))
 | |
|       (tk-set! file :menu m)
 | |
|       (pack file :side "left"))
 | |
| 
 | |
|     ;; Edit Menu
 | |
|     (let ((m (menu (& edit ".m") :tearoff #f)))
 | |
|       (m 'add 'command :label "Cut"   :accel "Ctrl-X" 
 | |
| 	 	       :command (lambda () (event 'gen console "<<Cut>>")))
 | |
|       (m 'add 'command :label "Copy" 
 | |
| 	 	       :command (lambda () (event 'gen console "<<Copy>>")))
 | |
|       (m 'add 'command :label "Paste" :accel "Ctrl-V" 
 | |
| 	 	       :command (lambda () (event 'gen console "<<Paste>>")))
 | |
|       (m 'add 'command :label "Clear" :accel "Del"
 | |
| 	 	       :command (lambda () (event 'gen console "<<Clear>>")))
 | |
|       (m 'add 'separator)
 | |
|       (m 'add 'command :label "Flush Console"
 | |
| 	 		:command (lambda () (console 'delete "1.0" "end")))
 | |
|       (tk-set! edit :menu m)
 | |
|       (pack edit :side "left"))
 | |
|     
 | |
|     (let ((m (menu (& conf ".m") :tearoff #f)))
 | |
|       (m 'add 'command :label "Customize" 
 | |
| 	 	       :command (lambda () (console-customize)))
 | |
|       (m 'add 'command :label "Save Configuration" 
 | |
| 	 	       :command (lambda () (console-customize-save)))
 | |
|       (tk-set! conf :menu m)
 | |
|       (pack conf :side "left"))
 | |
|       
 | |
|     ;; Help Menu
 | |
|     (let ((m (menu (& hlp ".m") :tearoff #f)))
 | |
|       (m 'add 'command :label "STk"   :command (lambda ()  ; Indirect to avoid 
 | |
| 						 (help)))  ; autoloads
 | |
|       (m 'add 'command :label "Console" :command (lambda ()
 | |
| 						   (help "make-console")))
 | |
|       (m 'add 'separator)
 | |
|       (m 'add 'command :label "About" :command console-about)
 | |
|       (tk-set! hlp :menu m)
 | |
|       (pack hlp :side "right"))
 | |
| 
 | |
|     (pack f :fill "x" :side "top")))
 | |
| 
 | |
| ;=============================================================================
 | |
| ;
 | |
| ; make-console
 | |
| ;
 | |
| ;=============================================================================
 | |
| 
 | |
| (define (make-console . args)
 | |
|   (let ((module (get-keyword :module args #f)))
 | |
|     (when module
 | |
|       (if (symbol? module) (set! module (find-module module)))
 | |
|       (if (not (module? module))
 | |
| 	  (error "make-console: bad module ~S" module)))
 | |
|     (init-console module #f)))
 | |
| 	  
 | |
| (define (%make-standard-console)
 | |
|   ;; Don't use try-load because ~ can yiel an error on Windows if HOME is
 | |
|   ;; unset (and console is unproperly initialized in this case).
 | |
|   (catch (load "~/.stkvars"))
 | |
|   (init-console #f #t))
 | |
| 
 | |
| (provide "console")
 |