Version 9 of interactive command composer

Updated 2003-11-21 18:39:04

by Theo Verelst

http://195.241.128.75/Bwise/procwindow1.jpg


LV What is this application? A tool to assist in writing tcl code? A tool to assist in generating tcl code? A tool to browse tcl code? I'm trying to figure out a high level description of this this does.


The below procedures generate the window shown here, at least they did for me on windows XP with tcl/tk 8.4.4 .

The meaning of the widget elements is as follows:

The left upper list Contains all procedures defined in tcl (in the main namespace/interpreter) without all procedures starting with tcl or tk or pkg and a few more (which are defined when tcl is started up), unless you loaded packages, then all procedures from there are also listed.

By clicking on a procedure name, its arguments are listed in the right upper list, while also the procedure definition, in correct tcl (but see below) appears in the lower edit window, and the command line contains the name of the procedure.

The Form Command line contains a prefixed call to pro_args, which takes its arguments, and produces a command from the options it is presented with, and the tcl procedures' default argument list, such that when the button is pressed, a command is formed in the shortest form possible given the default arguments, which can be executed from the Execute line by prcessing the <execute> button when satisfied with the formed commmand.

Each time an argument is double clicked from the argument list, it appears in the form command editable line, with the right braces around it, and with the cursor ready to fill in the parameter value. This can be repeated in any order until all arguments needed are filled in, and after that <Form Command> creates a well-formed tcl command with those arguments.

The lower procedure edit window contains the procedure last double clicked on in the upper left procedure list. The double-click simply overrides the contents of the window, regardless of what changes you had made, be sure to <Update Proc> regularly when you edit!

Left next to Save Procs Button, an entry can contain a file name, possibly with full path, where all procedures which have been updated with the <Update Proc> during the session will be saved when the button is pressed.

The Refresh list updates the procedure list to become up to date.

The Update Proc basically sources in (evals) the content from the text window, usually containing a single procedure definition, which at that point becomes the actual tcl procedure definition. While editing, the old procedure stays called.

A new procedure can easily be made by editing an old one, by changing name and what else needs change, and pressing <Update Proc>.

The code below assumes you loaded bwise first, command:

   destroy .f

to get rid of the old function window, unless you replace the procedure in the 0.34 source, and re-invoke the procedure to set up the procedure list window by

   procs_window

 proc procs_window { } {
           global defaultprocs
                     # The procedures which are listed in this list are not shown
           if {[info exists defaultprocs] != 1} {
              set defaultprocs {bgerror history loadvfs unknown}
           }
 #         get_procvanilla
           toplevel .f
         wm title .f "Procedure Window"

         frame .f.fu ; pack .f.fu -expand n -fill x;      # top frame with two scrollable lists

         listbox .f.fu.l -height 5 -yscroll ".f.fu.s set";   # left list
         pack .f.fu.l -expand y -fill x -side left
         scrollbar .f.fu.s -command ".f.fu.l yview"
         pack .f.fu.s -side left -expand n -fill y
         listbox .f.fu.lr -height 5 -yscroll ".f.fu.sr set";   # right list
         pack .f.fu.lr -expand y -fill x -side left
         scrollbar .f.fu.sr -command ".f.fu.lr yview"
         pack .f.fu.sr -side left -expand n -fill y

         frame .f.fe ; pack .f.fe -expand n -fill x ;             # Entries
         proc_entry fargs {set fcom [pro_args [lindex $fcom 0] $fargs]} "Form Command"
         proc_entry fcom {} Execute

         frame .f.ft ; pack .f.ft -expand y -fill both ;         # Text area
         pack .f.ft -expand y -fill both
         text .f.ft.t -width 20 -height 4 -wrap none -yscroll ".f.ft.s set";;
         pack .f.ft.t -expand y -fill both -side left
         scrollbar .f.ft.s -command ".f.ft.t yview"
         pack .f.ft.s -side right -expand n -fill y

         frame .f.f; pack .f.f -expand n -fill x
         button .f.f.b -text {Update Proc} -command {
            global procs;
            set p [.f.ft.t get 0.0 end];
            eval $p;
            set procs([lindex $p 1]) $p
         }
         pack .f.f.b -side right
         bind .f.fu.l <Double-Button-1> {
            global cf; set cf [selection get];
            .f.ft.t del 0.0 end;
            .f.ft.t insert end "proc $cf \{"
            .f.fu.lr del 0 end; 
            foreach i [info args $cf] {
               .f.fu.lr insert end $i
            }

            foreach a [info args $cf] {
           if { [info default $cf $a b] == 1} {
              .f.ft.t insert end " {$a {$b}}" } {
              .f.ft.t insert end " {$a}"
            }
         }
         .f.ft.t insert end " \} \{[info body $cf]\} "
         global fargs fcom
         set fcom $cf
         set fargs "pro_args "
        }
           button .f.f.b2 -text "Refresh List" -command {
              set o {};
                                            # Don't list certain procs
              foreach i [info procs] {
                 if {[string match {tk*} $i] == 0 && 
                 [string match {tcl*} $i] == 0 &&
                 [string match {pkg_*} $i] == 0 &&
                 [string match {auto_*} $i] == 0 &&
                 [lsearch $defaultprocs $i] == -1 } {
                    lappend o $i
                 }
              };
              .f.fu.l del 0 end;
              foreach i [lsort $o] {.f.fu.l insert end $i}
           };
           pack .f.f.b2 -side right
           entry .f.f.f -width 15 -textvar procsfile
           pack .f.f.f -side left
           button .f.f.bs -text {Save Procs} -command {
              global procsfile procs
              set o {}
              foreach i [lsort [array names procs]] {
                 eval append o { $procs($i) } \n 
              }
              set f [open $procsfile w];
              puts $f $o;
              close $f
           }
           pack .f.f.bs -side left
   bind .f.fu.lr <Double-Button-1> {
      append fargs " \{" [selection get] " \{"
      .f.fe.ffargs.e icursor end
      append fargs "\}\} "
   }

   bind .f.fu.l  <F1> [bind .f.fu.l [bind .f.fu.l ]]
   .f.f.b2 invoke
   .f.ft.t insert end "Use refresh list when you made a new procedure.\n"
   .f.ft.t insert end "Double click a procedure name to make it appear \n"
   .f.ft.t insert end "in the bottom window.\n\n"
   .f.ft.t insert end "After editing it, press Update to resource the proc.\n\n"
   .f.ft.t insert end "There is no extra storage except regular tcl procs,\n"
   .f.ft.t insert end "loading another proc destroys you edits: \nUPDATE FIRST.\n\n"
   .f.ft.t insert end "Save button saves EDITED procs, \nsee filebox entry on the left.\n"
   .f.ft.t insert end "Most Bwise regular windows can be resized."
 } 

 proc proc_entry {var {command {}} {buttontext Do}} {
         set w .f.fe.f$var
         frame $w ; pack $w -expand yes -fill x
         entry $w.e -textvar $var ; pack $w.e -side left -expand y -fill x
         if {$command == {}} {set command "eval \$$var"}
         button $w.b -command $command -text $buttontext
         pack $w.b -side right -expand n -fill none
 }

In fact, the above 2 procedures can also be used without bwise, by themselves, as long as this one is added:


 proc pro_args { {p } {ar }  } {
   set o {}
   set c 0; set maxc -1
   foreach a [info args $p] {
      set m {};
      foreach j $ar {
         if [string match $a [lindex $j 0]] { 
            set m 1 
            set arr [lindex $j 1]
            set maxc $c
         }
      }
      if {$m == {}} {
         if { [info default $p $a b] == 1} {
              append o " [list $b]" } {
              append o  " {}"
         }
      } {
         append o " [list $arr]"
      }
      incr c
   }
   set o "$p [lrange $o 0 $maxc]"
   return $o
 }

When Bwise is not loaded, the number of visible procedures which are shown are limited to these 3 procedures themselves, and any other procedures you add, so that it is like a fresh session, where all procedures you make, for instance by clearing the bottom window, writing a new procedure in it, and pressing <Update Proc> to create it. After that press <Refresh List> to get a list including the new procedure.

It seems that the example in Quoting and function arguments works when the procedure is double clicked and executed, though the procedure editor doesn't deal with the first argument right.

Putting the the default argument in position for editing is of course on the to-do list, or as an exercise to the reader.

More importantly, integration with bwise blocks is on the agenda (DV), and certainly a history, maybe integration with console, and a database of argument values.

Manual pages and search possibilities would be nice, and of course I want to make a direct link with bwise blocks, preferaly both ways, from tcl function to block decomposition, and vice versa.


KPV nice little tool. One suggestion: how about marking all new procedures say in red. By new I mean procedures loaded or altered after running procs_window.


TV Thanks.

In combination with bwise, I wanted to be able to make a procedure, preferably any procedure into a bwise-block, that is one of those yellow rectangles with short blue lines as pins and a name on a tk canvas, which are held together by tag naming conventions, and can be moved around and connected through wires.

I made a function, which takes a procedure as argument, which makes a block of that procedure, with an 'out' pin for the result, and for each argument, a corresponding input pin, named after the arguments:


 proc proc_toblock {procname} {

   set c "$procname"
   foreach i [info args $procname] {
      append c " \$\{$procname.[list $i]\}"
   }
   set ret  [eval pro_args newproc "{{f {set $procname.out \[$c\] }}  \
      {in {[info args $procname]}}  {out {out}}  \
      {x {300}}  {y {200}}  {name $procname} \
   } " ]
 puts $ret
   eval $ret
   foreach i [info args $procname] {
      uplevel #0 "info default $procname $i $procname.$i"
   }

   return $procname
 } 

That looks short...

After having started bwise, source the procudure, and call it with a self defined (non-tcl builtin) procedure namem for instance

   proc_toblock newproc

A bwise block is created with the name of the proc as name, and with block pin variables (made of blockname.pinname) for each argument of the procedure, where the pin variables are initialized with the proc's default argument values.

for the example, using the right or middle mouse pop-up menu on the generated block, and selecting 'date' the following list of block variables is automatically shown by bwise, showing this:

http://195.241.128.75/Bwise/procwindow2.jpg http://195.241.128.75/Bwise/procwindow3.jpg

I'm making a seperate page on Automatically generate Bwise blocks from procedures.


Category Application