Arjen Markus (30 may 2008) Below are the very first steps towards a tutorial for Plotchart.
My first idea was to write it as a man page with pictures in it, but currently the doctools do not yet support pictures in a convenient way. Then I thought it might be nice to have some interactive features ...
And then the idea was born to create a small library that would either convert the text of the tutorial to man page format or convert it into a GUI - after all, we have the text widget to take care of almost all details of displaying text and embedded windows.
So, below is that particular library, incomplete, poor in features but getting 80% of the job done already.
Note:
Right now this is limited to running Tcl code samples, but nothing prevents me or anybody else to expand this to running other applications for which you must edit some input for instance.
# tutorial_code.tcl -- # Procedures to create an interactive tutorial or a man page # in doctools format # # manpageOnly -- # Text to be written to the man page file only # # Arguments: # text Text to be written # # Result: # None # # Side effects: # The text is copied verbatim # proc manpageOnly {text} { global outfile global mode if { $mode == "manpage" } { puts $outfile $text } } # plain -- # Text to be written in plain form to the text widget or to the file # # Arguments: # text Text to be written # # Result: # None # # Side effects: # The text is copied verbatim or displayed in the text widget # proc plain {text} { global outfile global mode if { $mode == "manpage" } { puts $outfile $text } else { .textw.t insert end [string map {\n\n \n\n \n " "} $text] plain } } # title -- # Text to be written as a title # # Arguments: # text Text to be written # # Result: # None # # Side effects: # The text is copied to the file or the text widget # proc title {text} { global outfile global mode if { $mode == "manpage" } { puts $outfile "\[section \{$text\}\]" } else { .textw.t insert end $text title } } # fixed -- # Text to be written in non-proportional font # # Arguments: # text Text to be written # # Result: # None # # Side effects: # The text is copied as an example or displayed in Courier # proc fixed {text} { global outfile global mode if { $mode == "manpage" } { puts $outfile "\[example \{$text\n\}\]" } else { .textw.t insert end $text fixed } } # bullets -- # Text to be written in the form of a bullet list # # Arguments: # text Text to be written # # Result: # None # # Side effects: # The text is copied to the output file or displayed in the text # widget with the correct formatting for a bullet list # proc bullets {text} { global outfile global mode if { $mode == "manpage" } { puts $outfile $text } else { .textw.t insert end $text bullets } } # hiddenCode -- # Code to be run once, not visible in the text widget or otherwise # # Arguments: # code Code to be run immediately # # Result: # None # # Side effects: # The code is run in the global namespace # proc hiddenCode {code} { uplevel #0 $code } # runnableCode -- # Code to be written to the output file as an example or shown in a # embedded text widget. Can be edited and run by pressing the # associated push button # # Arguments: # code Code to be written or run # # Result: # None # # Side effects: # The code is copied to the output file or displayed in an # embedded text widget. A push button is added to run the code # proc runnableCode {code} { global outfile global count global mode if { $mode == "manpage" } { puts $outfile "\example \{$text\n\}\]" } else { incr count set frame [frame .textw.t.frame$count] set tcode [text $frame.t -background lightblue \ -wrap none \ -xscrollcommand [list $frame.xscroll set] \ -yscrollcommand [list $frame.yscroll set]] set brun [button .textw.b$count -text "Run" -command $code -font "Helvetica, 12"] set xbar [scrollbar $frame.xscroll -orient horizontal -command [list $tcode xview]] set ybar [scrollbar $frame.yscroll -orient vertical -command [list $tcode yview]] grid $tcode $ybar -sticky news grid $xbar - -sticky news grid columnconfigure $frame 0 -weight 1 grid columnconfigure $frame 1 -weight 0 grid rowconfigure $frame 0 -weight 1 grid rowconfigure $frame 1 -weight 0 .textw.t window create end -window $frame .textw.t insert end \n .textw.t window create end -window $brun $tcode tag configure code -font "Courier 12" $tcode insert end $code code } } # preparation -- # Create the text widget, open the file and set a few global parameters # set count 0 set mode "" if { $mode == "manpage" } { # TODO } else { toplevel .textw text .textw.t -yscrollcommand {.textw.yscroll set} -wrap word scrollbar .textw.yscroll -orient vertical -command {.textw.t yview} grid .textw.t .textw.yscroll -sticky news grid columnconfigure .textw 0 -weight 1 grid columnconfigure .textw 1 -weight 0 grid rowconfigure .textw 0 -weight 1 .textw.t tag configure plain -font "Times 12" .textw.t tag configure fixed -font "Courier 12" .textw.t tag configure bullets -font "Times 12" .textw.t tag configure title -font "Helvetica 14 bold" # TODO: wm protocol WM_DELETE ... }
And of course, the humble beginnings of the tutorial, illustrating the use of this library:
# pl_tutorial.tcl -- # Interactive tutorial for Plotchart # source "tutorial_code.tcl" manpageOnly { [comment {-*- tcl -*- doctools manpage}] [manpage_begin Plotchart n 1.5] [copyright {2008 Arjen Markus <[email protected]>}] [moddesc Plotchart] [titledesc {Tutorial to the Plotchart package}] } title { Tutorial for the Plotchart package } plain { Plotchart is Tcl-only package to create xy-plots, barcharts, piecharts and many other types of graphical presentations. This tutorial is intended to help you get started using it. It does not describe every feature of Plotchart, you should consult the manual for that. Rather, this tutorial will show: } bullets { * How to use Plotchart to create several of the plots and charts mentioned above * How to customise various aspects * Some of the gory details } plain { Throughout this tutorial we will use a fixed set of data: } fixed { chart 2008-05-18 17:25 1440 1081 27 94 axis 2008-05-18 17:26 940 712 20 86 pack 2008-02-24 08:22 378 258 7 37 priv 2008-05-18 17:18 1837 1238 40 167 annot 2008-02-22 13:03 376 275 7 22 config 2008-02-22 11:25 162 123 2 12 scaling 2008-02-22 10:23 148 109 4 15 plot3d 2007-09-07 11:47 300 203 5 34 contour 2005-04-15 13:42 1697 1131 19 151 gantt 2005-06-15 11:12 333 209 7 25 business 2007-09-07 12:15 382 246 7 30 } hiddenCode { set data { {chart 2008-05-18 17:25 1440 1081 27 94} {axis 2008-05-18 17:26 940 712 20 86} {pack 2008-02-24 08:22 378 258 7 37} {priv 2008-05-18 17:18 1837 1238 40 167} {annot 2008-02-22 13:03 376 275 7 22} {config 2008-02-22 11:25 162 123 2 12} {scaling 2008-02-22 10:23 148 109 4 15} {plot3d 2007-09-07 11:47 300 203 5 34} {contour 2005-04-15 13:42 1697 1131 19 151} {gantt 2005-06-15 11:12 333 209 7 25} {business 2007-09-07 12:15 382 246 7 30} } } plain { These are simple software metrics from the Plotchart source files: } bullets { * The abbreviated name of the file, date and time of the last modification * Total number of lines and number of lines without comments * Number of procedures * Number of if and switch statements, for, foreach and while loops } plain { Rather than use fictitious data, it seemed nice to use these data, related in some way to Plotchart itself. Now, let us plot the number of lines versus the number of procedures: } runnableCode { package require Plotchart # # Create the canvas that will hold the plot # canvas .c -width 400 -height 300 -background white pack .c -fill both # # Create the plot # set p [::Plotchart::createXYPlot .c {0 40 10} {0 1500 250}] # # # Get the data (via the convenience procedure "column") and plot the # data points # # ... }