\documentclass{article} \usepackage{RCS,hyperref,acronym} \RCS$Revision: 1.3 $ \RCS$Date: 2001/03/11 20:33:30 $ \renewcommand{\Diamond}{\relax} \title{nuweb.tcl: A TCL/Tk Front End for Nuweb} \author{Mark Wroth} \date{\RCSDate} \newcommand{\app}[1]{\texttt{#1}\index{#1}} \begin{document}\maketitle \section{Identification} This TCL/Tk script acts as a graphical front end to \app{Nuweb}. This is Revision~\RCSRevision, dated \RCSDate. \section{Background} \label{sec:background} \app{Nuweb}, by Preston Briggs, is a \textit{literate programming} processor that produces output code files and \TeX\ documentation files from a single source file, called a \textit{web} file. In its original form, \app{Nuweb} is a command line utility; the user interacts with the program by typing the command name, various command options, and the name of the target file. This TCL/Tk script provides a \ac{GUI} easing the selection of the target web file, the choice of options, and the repetitive running of \app{Nuweb}. \section{Implementation} \subsection{Organization} \label{sec:org} The basic organization of this script is a series of sections that set up the various pieces of the \ac{GUI}, a setup of the \ac{GUI} itself, and a set of supporting procedures. @O nuweb.tcl @{# $Id: nuwebtcl.w,v 1.3 2001/03/11 20:33:30 Mark Exp $ @ @ @ @ @ @ @} \subsection{Initial Configuration} \label{sec:init} Set up the initial configuration; first we get the name of the intended file, and then set the initial values of the various command line options. @D Initialization @{ @ set noTeX 0 set noCode 0 set verbose 1 set noTest 0 set numberScraps 0 @} Because of the way we use it, the requester that we use to get the target file name involves several related actions; we get the full name of the path and file, and then split it up into the path and file name components. There are several places where we want to execute the same set of actions. While a procedure would do this, it's easier to use a defined scrap; the \texttt{.tcl} script will be slightly larger, but this has little effect. @D Set target path and name @{ set target [tk_getOpenFile -filetypes { {{Nuweb files} {.w}} {{All files} {""}} }] set target_path [file dirname $target] set target_name [file tail $target] eval cd \"$target_path\" @} The next scrap sets up the name of the executable file. It is stored in a variable to facilitate changing it via a configuration menu pick. @D Set up configuration buttons @{ set nuweb_name "nuweb" @} \subsection{The Configuration Buttons} \label{sec:config} The primary configuration is the name of the target file. This button displays the name of the currently selected file, and allows the user to change it if desired by clicking on the button and selecting the new file from the file requester that will appear. This is a very compact user interface. However, some users might not find it intuitive (since Windows tends to provide a separate ``browse'' button next to a label widget). I don't consider this a problem, as I am probably the only user for this particular script. If this script does get wider dissemination, however, consider reimplementing this with a label and a browse button. @D Set up configuration buttons @{ button .browse -textvariable target_name -command { @ } label .pathname -textvariable target_path @} We also allow the user to set the various options of \app{nuweb}; this section sets the options up in a two-column pane. The option defaults are set above (Section~\ref{sec:init}). @D Set up configuration buttons @{ frame .config frame .config.left frame .config.right checkbutton .noTeX -text "Suppress TeX Output" \ -variable noTeX -anchor w checkbutton .noCode -text "Suppress Code Output" \ -variable noCode -anchor w checkbutton .verbose -text "Verbose Output" \ -variable verbose -anchor w checkbutton .noTest -text "Do Not Test For File Changed" \ -variable noTest -anchor w checkbutton .numberScraps -text "Number Scraps Consecutively" \ -variable numberScraps -anchor w @} \subsection{Menus} As a convenience---and as a programming exercise---we set up a series of menus that allow the user to perform various actions. Some of these capabilities duplicate the capabilities provided by other elements of the \ac{GUI}, and some are accessible only from the menu structure. The menus themselves will be contained in a frame. @D Set up the menus @{ frame .menubar -relief groove -borderwidth 4 @} The ``File'' menu @D Set up the menus @{ menubutton .menubar.file -text "File" \ -direction below -menu .menubar.file.menu menu .menubar.file.menu\ -tearoff 0 .menubar.file.menu add command -label "Set target" -command { @} .menubar.file.menu add command -label "Exit" -command { exit} @} The ``configuration'' menu. @D Set up the menus @{ menubutton .menubar.config -text "Config" \ -direction below -menu .menubar.config.menu menu .menubar.config.menu \ -tearoff 0 .menubar.config.menu add command -label "Nuweb" -command { set nuweb [tk_getOpenFile -filetypes { {{Executables} {.exe}} {{All files} {""}} }] } @} The ``Help'' menu. @D Set up the menus @{ menubutton .menubar.help -text "Help" \ -direction below -menu .menubar.help.menu menu .menubar.help.menu \ -tearoff 0 .menubar.help.menu add command -label "Help" \ -command {showHelp} .menubar.help.menu add command -label "About" -command { tk_messageBox -type ok -message \ "This is nuweb.tcl, a TCL/Tk application providing a graphical front end for Nuweb.\n\n Copyright (c) Mark Wroth 2001\n\n Free distribution under the terms of the Gnu Public License is authorized." } @} Finally, the menus are packed in the top frame. @D Set up the menus @{ pack .menubar.file .menubar.config -side left -fill x pack .menubar.help -side right -fill x @} \subsection{Actions} The primary action from this script is to run the \app{nuweb} processor with the configuration options and target selected by the user. We are going to write the normal and error output of the script to log files (via output redirection in the \texttt{exec} command). Because of this, As part of the initialization of this command script, we will delete the log file so it contains only the output from this run when they are written by redirecting the output of \app{nuweb}. It is an oddity of \app{nuweb} that \emph{all} of its output is written to standard error; for this reason only the standard error is redirected into the log file. @D Define the action buttons @{ button .go -text "Tangle/Weave" -command { file delete nuwebtcl.log file delete nuwebtcl.error if $noTeX {set t " -t "} else {set t ""} if $noCode {set o " -o "} else {set o ""} if $verbose {set v " -v "} else {set v ""} if $noTest {set c " -c "} else {set c ""} if $numberScraps {set n " -n "} else {set n ""} catch { eval exec $nuweb_name \ $t $o $v $c $n \ \"$target\" \ 2> nuwebtcl.log } if [expr [file size nuwebtcl.log] > 0] { showFile nuwebtcl.log } else { file delete nuwebtcl.log } } @} Note the redirection of \app{nuweb}'s output to log files. This enables us to automatically display the error log if \app{nuweb} exited abnormally. Once \app{nuweb} has returned, we examine the size of the redirected files. If the error file has non-zero length, we display it, using procedures stolen from the ``Widget Tour''. If it, or the log file, has zero length, we will delete it. @D Define the action buttons @{ button .showlog -text "Show Log" -command { showFile nuwebtcl.log } @} Finally, we provide a button to exit from the application. This is not strictly necessary, since the "close" widget automatically provided by the window manager has the same functionality, but it seems appropriate. @D Define the action buttons @{ button .exit -text "EXIT" -command {exit} @} \subsection{Help Display} \label{sec:help} This procedure displays the text stored in the variable ``helptext'' which is defined in the \app{nuweb} scrap ``help text for display''). @D Supporting procedures @{proc showHelp {} { set helptext "@" set w .text catch {destroy $w} toplevel $w wm title $w "Nuweb TCL/Tk Help" wm iconname $w "text" frame $w.buttons pack $w.buttons -side bottom -fill x -pady 2m button $w.buttons.dismiss -text Dismiss -command "destroy $w" pack $w.buttons.dismiss -side bottom -expand 1 text $w.text -relief sunken -bd 2 -yscrollcommand "$w.scroll set" \ -setgrid 1 -height 30 \ -tabs {1c 2c 3c} \ -wrap word scrollbar $w.scroll -command "$w.text yview" pack $w.scroll -side right -fill y pack $w.text -expand yes -fill both $w.text insert end $helptext $w.text mark set insert 0.0 } @} %$ \subsection{Display The Interface} The actual display of the \ac{GUI} is defined by the series of pack commands. Since the interface is actually quite simple, the pack commands needed to implement it are likewise not complicated. @D Display the \ac{GUI} @{ pack .menubar -side top -fill x pack .pathname .browse .config -side top -fill x pack .config.left .config.right -in .config -side left pack .noTeX .noCode -in .config.left -side top -anchor w pack .verbose .noTest .numberScraps -in .config.right \ -side top -anchor w pack .go .showlog .exit -side left -expand 1 -fill x @} \section{Supporting Procedures} \label{sec:spt} The procedures shown here are relatively generic; they provide the general function of displaying a text file. \subsection{Show Files} These procedures take a single argument, the name of a text file, and display it in a toplevel window. \subsubsection{The ``showFile'' Procedure} This procedure was adapted from \texttt{text.tcl}, a demonstration script that creates a text widget that describes the basic editing functions, found in the ``Widget Tour'' that is part of the \ac{TCL} distribution. Specifically, it is ``text.tcl,v 1.2 1998/09/14 18:23:30 stanton Exp''. The script was adapted to turn it into a procedure and to arrange to fill it with text read from a file rather than with a text hard coded into the procedure. Additionally, the ``Show Code'' option was removed, since it was not relevant to this application. @D Supporting procedures @{proc showFile {thefile} { set w .text catch {destroy $w} toplevel $w wm title $w "$thefile" wm iconname $w "text" frame $w.buttons pack $w.buttons -side bottom -fill x -pady 2m button $w.buttons.dismiss -text Dismiss -command "destroy $w" pack $w.buttons.dismiss -side bottom -expand 1 text $w.text -relief sunken -bd 2 -yscrollcommand "$w.scroll set" \ -setgrid 1 -height 30 scrollbar $w.scroll -command "$w.text yview" pack $w.scroll -side right -fill y pack $w.text -expand yes -fill both textLoadFile $w.text $thefile $w.text mark set insert 0.0 } @} %$ \subsubsection{The ``textLoadFile'' Procedure} This procedure is extracted from \texttt{search.tcl}, a demonstration script found in the ``Widget Tour'' distributed with \ac{TCL}. Specifically, it is ``Id: search.tcl,v 1.2 1998/09/14 18:23:30 stanton Exp''. @D Supporting procedures @{proc textLoadFile {w file} { if [file exists $file] { set f [open $file] $w delete 1.0 end while {![eof $f]} { $w insert end [read $f 10000] } close $f } } @} No modifications to this procedure were needed for this application. \appendix \section{User Help Text} This scrap defines the actual text to be displayed in the help window. Note that the entire scrap will be within quotes when it is used; the text defined here needs to conform to the Tcl syntax. @D help text for display @{\ OVERVIEW This is a Tcl/Tk front end for the Nuweb literate programming \ processor. It takes a single target file and (depending on the \ command options supplied) produces a TeX source file and a set \ of code files defined in the target file. TARGET FILE The name of the target file is displayed in a text button near \ the top of the Nuweb.tcl window, with the path to that file \ displayed above it. The nuweb process will execute in this \ directory, which means that all relative path names defined \ in the target file will be interpreted relative to this directory. \tTo change the target file, click on the text button containing \ the target file name. A file requester will appear; navigate to and \ select the new target file using the requester. By default, the \ requester will show only files ending in \".w\", since this is the \ usual extension given to nuweb target files. \tThe target file requester can also be summoned via the \"File\" \ menu. \n USER OPTIONS\n The user options for nuweb can be set by checking the option boxes \ displayed in the center of the GUI. These options are: \t - Suppress TeX Output: causes nuweb to omit the \"weave\" phase \ of execution. This means that no TeX documentation file will be produced. \t - Suppress Code Output: causes nuweb to omit the \"tangle\" phase \ of execution. This means that no code output files will be produced. \t - Verbose Output: causes nuweb to write the names of the input and \ output files. This information (and any warning or error messages) are \ captured in a log file which is automatically displayed when nuweb \ finishes executing. The log file can also be displayed by selecting the \ \"Show Log\" command button. \t - Do Not Test For File Change: normally, nuweb tests to see that its \ output files have changed before actually writing them. This is intended \ to help with make file dependencies, where updating the file modification \ date can cause unnecessary compilation. By checking this option, you can \ cause nuweb to overwrite the existing files whether they are changed or \ not. \t - Number Scraps Consecutively: have nuweb number the scraps in the TeX \ documentation file with consecutive numbers, rather than by the page they \ are defined on. TANGLE/WEAVE\n To execute nuweb with the currently selected target file and options, click \ on the button labeled \"Tangle/Weave\". CONFIGURATION\n The Nuweb Tcl application assumes that the nuweb executable is found \ somewhere in the operating system path. If this is not the case, the path \ to the nuweb executable can be set using the \"Config\" menu \"Nuweb\" \ option. EXITING FROM THE APPLICATION\n There are three different ways to exit from the Nuweb Tcl application: \t - Click on the button marked \"Exit\" \t - Select the \"Exit\" item on the \"File\" menu \t - Click on the \"Close Window\" button provided by the operating \ system's window manager. @} \section*{Reference Material} \subsection*{Change History} $Log: nuwebtcl.w,v $ Revision 1.3 2001/03/11 20:33:30 Mark Added user help. I'm not quite sure I understand how the text widget displays the resulting text---some of the formatting is not quite what I expected. But the help seems to be usable, which is enough for now. Revision 1.2 2001/03/10 06:38:40 Mark Added a basic menu structure. Corrected a potentially confusing behavior which caused the script to place the Nuweb outputs in the directory from which the script was invoked rather than the directory in which the target file resides. Added protection against the impacts of directory hierarchies which contain spaces by adding quotation marks around the directory names. Completed basic debugging and testing. This appears to be a functional version. \subsection*{Acronyms} \begin{acronym} \acro{GUI}{Graphical User Interface} \acro{TCL}{Tool Command Language} \end{acronym} \begin{thebibliography}{9} \bibitem{Ousterhout94} John K. Ousterhout. \textsl{Tcl and the Tk Toolkit}. Reading, MA: Addison-Wesley, 1994. \bibitem{Raines99} Paul Raines and Jeff Tranter. \textsl{TCL/TK in a Nutshell}. Sebastopol CA: O'Reilly \& Associates, 1999. \bibitem{WidgetDemo} Sun Microsystems, Inc. ``Tk widget demonstration''. Distributed with TCL 8.3, copyright 1996-1997. \end{thebibliography} \end{document}