Quill is intended for those learning Tcl/Tk for the first time, and also for those who build libraries or applications in Tcl/Tk that are intended for use by others.
It is still a young project; if it doesn't yet meet your needs, please leave an enhancement request at the Quill issue tracker.
FUTURE: Quill will support multiple project templates. At present, it supports a single template, 'app', for a generic application.
To create a new project, switch to the parent directory of the new project's directory tree, and use the 'quill new' tool:
$ cd ~/github $ quill new app my-project myapp ... $ cd my-project $ quill info ...The 'quill new' command takes the project template name ('app') and the project name, ('my-project'), and any additional information required by the template (the application name, 'myapp', in this case). It creates a project tree for the project, rooted at my-project/ in the current directory.
The 'quill info' command displays the new project's metadata in a human-readable form:
$ quill info my-project 0.0a0: Your project description Project Tree: /Users/will/github/my-project Applications: Name Mode ExeType ----- ------- ------- myapp Console kit Required Packages: Tcl 8.6.1 Distribution Sets: installIn this listing we see the project's name, and its initial version string ('0.0a0') and description. It contains code for one application, 'myapp', which is a console-mode application to be delivered as a starkit. The project has only one dependency, on Tcl 8.6.1, which is the version of Tcl currently installed on the machine in use. It defines a single distribution set, 'install', which in turn defines the files to be included in the installation .zip file.
Typically you will wish to change some or all of these things. You might want a GUI application built as a standalone executable, and you'll probably have additional external dependencies. Ultimately you'll need to change the version number.
All of these things are defined in the project file, which is called project.quill.
$ cd ~/github/my-project $ cat project.quill project my-project 0.0a0 "Your project description" homepage http://home.page.url app myapp require Tcl 8.6.1 dist install { %apps docs/*.html docs/man*/*.html README.md LICENSE }The project file consists of a sequence of statements that define the entities in the project. It always begins with the project statement, which defines the project's name, version number, and description. The app statement declares that the project defines an application called 'myapp', and that it requires version 8.6.1 of a package called 'Tcl'. Finally, it defines an installation set called 'install' which contains the built applications, some HTML files from the project/docs/ subtree, and the README and LICENSE files.
The file is usually edited by hand; to change the project's version number, just edit the file. Then, run 'quill info' to verify that the file is readable:
$ vim project.quill $ quill info ... $In addition to the kind of information shown above, you can also provide library packages; these are Tcl libraries exported by your project for use by other project.
The project file syntax is documented in Quill's project(5) man page. It's a Tcl-formatted file, naturally, but it allows only the commands defined in project(5); and on occasion Quill will write it out again with edits, so you shouldn't get too attached to your formatting.
Similarly, your applications will need to package require some or all of the external dependencies list in project.quill, and will need to include the package version numbers.
Quill handles all of this. Each time a Quill command is executed in the project tree. Quill loads project.quill and updates the project's codebase as needed to match the project's new metadata.
This is another reason why it is a good idea to execute 'quill info' after editing project.quill: it gives Quill a chance to make any necessary changes.
As an example, your application can retrieve the project version number like this:
set version [quillinfo version]See the quillinfo(n) man page for the complete API. Only a few pieces of information are made available at present, but in principle everything in project.quill can be made available.
But if there are many bad project trees, there are many good ones; the choice is to some extent arbitrary. Quill makes the choice for you, mandating a project tree layout that has been known to work in real projects.
root/ | The project root directory. |
 project.quill | The project file; see Section Section 2.2. |
 README.md | The project's "read me" file. |
 LICENSE | The project's license file. |
 .quill/ | Quill's private working directory for this project. It should not be checked into a VCS. |
 bin/ | The project "bin" directory. |
   app.tcl | Application loader script for application app. |
   tool | A project-specific tool, usually a Tcl script. |
 docs/ | The project documentation directory. See Section Section 2.5. |
   index.quilldoc | The root of the project's documentation tree, in quilldoc(5) format. |
   document.quilldoc | Some other document, in quilldoc(5) format. |
   man1/ | Man page directory for application man pages. (Section 1). |
     app.manpage | Man page for application app in manpage(5) format. |
   man5/ | Man page directory for project file formats. (Section 5). |
     format.manpage | Man page for the given file format in manpage(5) format. |
   mann/ | Man page directory for Tcl package APIs. (Section n). |
     module.manpage | Man page for the given package module in manpage(5) format. |
   mani/ | Man page directory for Tcl interfaces. (Section i). |
     interface.manpage | Man page for the given interface in manpage(5) format. An "interface" is a set of subcommands and semantics supported by multiple otherwise unrelated Tcl objects. |
 lib/ | Parent directory for the project's Tcl packages. |
   app_app/ | Directory for the application app's implementation package. |
     pkgIndex.tcl | The package's package index file. |
     pkgModules.tcl | The package's module loader script. See Section Section 3.. |
     main.tcl | Defines the application's main procedure. |
     module.tcl | Another package module. |
   lib/ | Directory for package lib, which might or might not be "provided" for external use. |
     pkgIndex.tcl | The package's package index file. |
     pkgModules.tcl | The package's module loader script. See Section Section 3.. |
     module.tcl | Another package module. |
 test/ | Parent directory for the project's test target directories. |
   target/ | A test target directory. The "target" is usually a package name. |
     /all_tests.test | The target's main tcltest(n) script. (Boilerplate; See Section Section 5..) |
     /module.test | The tcltest(n) script for the given module. |
The practices and usage of these directories are discussed in the following sections. And, of course, you can define any other subdirectories you need.
$ quill test Summarizing test results. Use 'quill -verbose test' to see the details. app_quill: Total 35 Passed 35 Skipped 0 Failed 0 quill: Total 169 Passed 167 Skipped 2 Failed 0 $You can execute a particular target or module test as well:
$ quill test quill ... output from running test/quill/all_tests.test ... $ quill test quill listutils ... output from running test/quill/listutils.test ... $Finally, you can add any tcltest(n) options you like to the command line. To run just one family of tests, for example, you can add the -match option:
$ quill test quill listutils -match lshift-* ... output from running the lshift-* tests in listutils(n) ... $See Section Section 5. for information on how to set up test target directories for use with Quill.
The quilldoc(5) format is for short HTML files and full documents with section numbers, like this user's guide. The manpage(5) format is for man pages. The quilldoc(5) and manpage(5) man pages go into detail about the formats and how to make use of them.
To format the documentation, use the 'quill docs' command:
$ quill docs ... formats all .quilldoc and .manpage files found in the docs/ tree ... $ quill docs mann ... formats all manpages in docs/mann/ ... $ quill docs docs ... formats all .quilldoc files in docs/ ... $ quill docs docs/ug.quilldoc ... formats the specific file ... $If any errors are found, they are described in the console output.
Further, if your project defines at least one application then 'quill shell' automatically load the package for the first app in your project.quill file. (The app's main procedure is not executed.)
FUTURE: The 'quill shell' command will allow you to select the app whose code you want loaded, or none.
NOTE: Before this mechanism will work properly, it may be necessary to set up your own local "teapot"; see Section Section 2.7.2.
External dependencies are declared in project.quill using the require statement:
require snit 2.3 require mylib 1.2 -local
This example requires two packages, "snit" and "mylib". The "mylib" package is declared to be "local", which is to say it's a package that's built and installed locally; if it isn't available, there's no point in looking for it at teapot.activestate.com.
To check whether all of your project's external dependencies are available locally, use this:
$ quill deps Dependency Status: snit 2.3 (Missing) mylib 1.2 (OK)
To retrieve missing dependencies,
$ quill deps update ...
Quill will attempt to retrieve all missing depedencies, and will report on its success or failure. Finally, you can refresh any or all dependencies, explicitly downloading a new copy, by using:
$ quill deps refresh ...
Instead, your applications and library packages must call package require in the usual way for each needed dependency. However, Quill does provide a mechanism to keep the package version numbers in sync between project.quill and your code. See Section Section 3. for details.
First, see if there is a problem:
$ quill teapot Teapot Status: Location: /Users/name/.quill/teapot Writable? Yes Linked? Yes The local teapot is writable, and is properly linked to the default Tcl shell. Everything appears to be OK.In this the local teapot exists, and is writable, and everything is fine. If you see output like this there is nothing more to do.
The first time Quill is used, though, this is not likely to be the case. To resolve the problem, then, do this:
$ quill teapot fix ...This command will do two things. First, it will create a new local teapot in your home directory, e.g., as ~/.quill/teapot/. (The precise location varies by operating system). Being in your home directory, this teapot is writable.
Second, 'quill teapot fix' will output a short script; executing this script with admin privileges will link the new teapot to your development tclsh, and will also resolve several issues related to running the teacup executable with admin privileges.
On a Linux or OSX system, for example, you would run this script using sudo:
$ sudo ~/.quill/fixteapot ... $On Windows, the script would be called fixteapot.bat, and would need to be run by a user with Admin privileges.
The 'quill teapot fix' command will output the script file's full path name; you are encouraged to look at the script and verify that it isn't doing anything nefarious.
provide mylib
Quill does two special things for provided packages. First, on 'quill build' Quill builds a teapot .zip file for the package. This .zip file is constructed so that it can be installed into any local teapot repository for use by other Tcl programs. The file is stashed in the project/.quill/teapot/ directory, and has a name like this:
package-name-version-tcl.zip
where name is the package name and version is the package version.
Second, 'quill install' will install the package's .zip file into your local teapot, for use by your other projects.
And of course you can define a test target (Section Section 2.4) and man pages (Section Section 2.5) for the provided package, just as you can for any of the project's libraries.
See Section Section 3. for the structure of library packages, whether provided or not.
FUTURE: At present, Quill requires TclDevKit to build the teapot .zip files. This is expected to change in the near future.
app myapp -exetype exe -guiThe first app statement in project.quill defines the project's primary application. Quill provides many tools for working with applications:
'quill run' invokes the project's primary application, passing it any command-line arguments. This is convenient if you don't want to add the project's project/bin/ directory to your PATH.
'quill shell' loads the primary application's code into a tkcon shell for interactive development and debugging.
'quill build' builds the application as starkit or starpack in the project's project/bin/ directory. The executable will have a name like
name-version-tcl.kit
(for starkits) or
name-version-platform[.exe]
for standalone executables, where the name is the application name, version is the project version number, and platform is the current platform string as returned by platform::identify.
And finally, 'quill install' will install the application into the user's ~/bin directory for local use as name.kit, name.exe, or simply name, depending on the application and current platform.
FUTURE: At present, Quill requires TclDevKit in order to build the application executables. This will remain an option, but it is hoped that other choices will be available in the future.
Distribution sets are defined in project.quill using the dist statement. For example, a project that provides a set of pure-Tcl libraries might have a distribution set like this:
dist install { %libs docs/*.html docs/man*/*.html README.md LICENSE }It includes the .html files from the project's documentation tree, the project's README and LICENSE files, and the teapot .zip files for each provided library, as indicated by the special pattern %libs.
When built, this distribution set will result in a file with a name like this:
project-version-install.zip
where project is the project's name and version is the project's version number.
If the project provides an application built as a starpack, it might have an installation distribution set that looks like this:
dist install-%platform { %apps docs/*.html docs/man*/*.html README.md LICENSE }The %apps pattern is like the %libs pattern; it matches the executable files built by 'quill build'.
The "%platform" in the distribution set name is present because starpack executables are specific to a particular platform; when the distribution set is built, the "%platform" token will be replaced with the actual platform. If it were built for a 32-bit Windows system, for example, the distribution .zip file would have a name like this:
project-version-install-win32_x86.zip
The project can define any number of distribution sets for different purposes. For example, a project might want to define a "docs" distribution.
$ quill build all ... $This command will:
$ quill basekit Finding basekits at teapot.activestate.com... Platforms for which cross-platform builds can be done: platform version name tcltk source ---------------------- -------------- --------------- ----- ------ linux-glibc2.3-ix86 8.6.3.0.298609 base-tcl-thread tcl web base-tk-thread tk web 8.6.1.1.298358 base-tcl-thread tcl local 8.6.1.1.297892 base-tcl tcl web base-tk tk web linux-glibc2.3-x86_64 8.6.3.0.298584 base-tcl-thread tcl web base-tk-thread tk web 8.6.2.1.298536 base-tcl-thread tcl local macosx-universal 8.6.0.0.296279 base-tcl-thread tcl web base-tk-thread tk web macosx10.5-i386-x86_64 8.6.3.0.298584 base-tcl-thread tcl web base-tk-thread tk web win32-ix86 base-tcl-thread tcl web base-tk-thread tk web 8.6.2.1.298536 base-tk-thread tk local 8.6.2.0.298433 base-tcl-thread tcl local win32-x86_64 8.6.3.0.298609 base-tcl-thread tcl web base-tk-thread tk web $Basekits with a source of "local" have already been downloaded to your machine; basekits with a source of "web" are available for download. Note that only Tcl 8.6 basekits are listed; that's because the project I'm working on has the 'require Tcl 8.6' statement in project.quill. If it required Tcl 8.5, we'd see Tcl 8.5 basekits instead.
You then have your choices of the precise platform and version of Tcl, whether you want the Tk GUI toolkit included, and whether you want threaded or unthreaded Tcl (most distributions are now threaded).
The next step is to retrieve the basekits you want using quill basekit get. For example, to get threaded Tcl and Tk basekits for all platforms for Tcl 8.6.2,
$ quill basekit get "*" "8.6.2*" "*" ... $This command takes three arguments, the basekit name, the version, and the platform; each argument can contain glob-style wildcard characters as shown. (The double-quotes are to protect the wildcard characters from your shell.)
Quill will download all matching basekits and save them locally. If you wish to see which basekits you have available locally, use this command:
$ quill basekit list -source local Platforms for which cross-platform builds can be done: platform version name tcltk source --------------------- -------------- --------------- ----- ------ linux-glibc2.3-ix86 8.6.1.1.298358 base-tcl-thread tcl local linux-glibc2.3-x86_64 8.6.2.1.298536 base-tcl-thread tcl local win32-ix86 base-tk-thread tk local 8.6.2.0.298433 base-tcl-thread tcl local $See 'quill help basekit' for the full syntax of the 'quill basekit' command.
Then use 'quill build for' for the desired platform. For example, to build for 32-bit Windows,
$ quill build for win32-ix86 ... $Quill will build all applications with -exetype exe using the locally available basekits for win32-ix86 with the highest version number. Then, it will build any distribution sets that have '%platform' embedded in their names, substituting win32-ix86 for '%platform'.
This is why you must run 'quill build all' before running 'quill build for'; the latter builds only the applications, assuming that any documentation and library teapot .zip files are already available.
If you wish to run with a specific version or without threading (if both threaded and unthreaded are available) you can use the -version and -threads options. See 'quill help build' for specifics.
In the mean time, the easiest way to add a new library or application is to copy and rename the required files and directories. See Sections Section 3., Section 4., and Section 5. for complete descriptions of Quill's expectations with regard to library packages, applications, and test targets.
$ quill env Quill 0.3.0 thinks it is running on Mac OSX. Local Teapot: /Users/will/.quill/teapot Helper Tools: tclsh /usr/local/bin/tclsh (v8.6.1) tkcon /usr/bin/tkcon teacup /usr/local/bin/teacup (v8.5.15.1.298288) tclapp /usr/local/bin/tclapp basekit.tcl /Library/Tcl/basekits/base-tcl8.6-thread-macosx10.5-i386-x86_64 basekit.tk /Library/Tcl/basekits/base-tk8.6-thread-macosx10.5-i386-x86_64 teapot-pkg /usr/local/bin/teapot-pkg ! - Helper tool could not be found on disk. + - Path is configured explicitly.If you have multiple versions of any tool on your system, or if Quill cannot locate the required tools, you can use the 'quill config' command to tell Quill where to find them:
$ quill config list ... list of configuration parameters and value ... $ quill config set helper.tclsh pathToTclShell... $See 'quill help config' for the complete syntax of the 'quill config' command.
At least one library package is included in each new project. Additional packages can be added using the quill add command (not yet implemented) or by hand, by copying an existing library.
Quill has some very specific expectations of project library packages; for the details, see the following subsections.
0001 #------------------------------------------------------------------------- 0002 # TITLE: 0003 # pkgIndex.tcl 0004 # 0005 # PROJECT: 0006 # my-project: Your project descriptionA0007 # 0008 # DESCRIPTION: 0009 # mylib(n): pkgIndex file 0010 # 0011 # Generated by Quill 0012 # 0013 #------------------------------------------------------------------------- 0014 0015 # -quill-ifneeded-beginBDO NOT EDIT BY HANDC0016 package ifneeded mylib 1.2.3D[list source [file join $dir pkgModules.tcl]]E0017 # -quill-ifneeded-endB
A |
Quill uses your project's metadata when creating the file header.
|
B |
These are Quill block markers. They are used to mark code segments that
Quill will update automatically, as needed.
|
C |
The contents of this kind of block (quill-ifneeded-*) is replaced in
its entirety; do not edit the code between the markers.
|
D |
The package ifneeded command loads the package's code when TCL is asked
to package require it, and references the package's name and version
number. The version number of a package in a Quill project is always the
same as the project version number. When the version number changes,
Quill will update this command with the latest version number.
|
E |
The package's code is loaded by calling the module's
pkgModules.tcl file. See Section 3.2.
|
0001 #------------------------------------------------------------------------- 0002 # TITLE: 0003 # pkgModules.tcl 0004 # 0005 # PROJECT: 0006 # my-project: Your project descriptionA0007 # 0008 # DESCRIPTION: 0009 # mylib(n): Package Loader 0010 # 0011 # Generated by Quill 0012 # 0013 #------------------------------------------------------------------------- 0014 0015 #------------------------------------------------------------------------- 0016 # Provide Package 0017 0018 # -quill-provide-beginBDO NOT EDIT BY HANDC0019 package provide mylib 1.2.3D0020 # -quill-provide-endB0021 0022 #------------------------------------------------------------------------- 0023 # Require Packages 0024 0025 # -quill-require-beginBINSERT PACKAGE REQUIRES HEREE0026 package require snit 2.3F0027 package require -exact myotherlib 1.2.3G0028 # -quill-require-endB0029 0030 #------------------------------------------------------------------------- 0031 # Get the library directory 0032 0033 namespace eval ::mylib::H{ 0034 variable library [file dirname [info script]]I0035 } 0036 0037 source [file join $::mylib::library mymodule.tcl]J0038 ...
A |
Quill uses your project's metadata when creating the file header.
|
B |
These are Quill block markers. They are used to mark code segments that
Quill will update automatically, as needed.
|
C |
The contents of this kind of block (quill-provide-*) is replaced in
its entirety; do not edit the line between the markers.
|
D |
The package provide command notifies TCL that the given version of the
package is available to be required and used. The version number for a
package in a Quill project is always the same as the project's version
number, so Quill automatically updates this code when the project
version number changes.
|
E |
Your package's package require commands should go between these
quill-require-* marks, so that Quill can keep the version numbers
up to date. Quill updates only the lines whose first non-whitespace
tokens are "package require".
|
F |
In this line, Snit is an external dependency named in the
project file using the require
statement. Quill consequently knows the required version number, and
will make sure to keep this command up-to-date with it.
|
G |
In this line, myotherlib is another library provided by this same
project. In this case, Quill not only keeps the version number up-to-date
with the project's version number, it adds the -exact flag.
myotherlib might exist in the local teapot repository
as well as in the project tree, and using -exact ensures that
mylib will load the version in the same project tree
during development and a consistent version when deployed.
|
H |
Every package defines a namespace of the same name, just as a matter of
convention. Provided packages should usually put their code in the
package namespace; for application and infrastructure packages, it's a
matter of taste.
|
I |
Every package saves the path its library directory in a variable called
library in its namespace. This variable has multiple uses. If
the package has resources (e.g., image files) that need to be loaded
at runtime, it can find them relative to this path. And if it isn't
clear which version of a package is being loaded, a glance at the
library variable will usually make things plain.
|
J |
The package's modules should always be sourced using this idiom, which
is guaranteed to work on all platforms.
|
Second, do not put your package's implementation at the tail end of the pkgModules.tcl file, even if you have only one file. Instead, put the implementation in another file or files, and update pkgModules.tcl only when adding or deleting a module or a package require.
0001 #------------------------------------------------------------------------- 0002 # TITLE: 0003 # mymodule.tcl 0004 # 0005 # PROJECT: 0006 # mylib: Your project descriptionA0007 # 0008 # DESCRIPTION: 0009 # mylib(n): my module for this and that 0010 # 0011 #------------------------------------------------------------------------- 0012 0013B0014 0015 #------------------------------------------------------------------------- 0016 # Exported Commands 0017 0018 namespace eval ::mylib { 0019 namespace export myprocC0020 } 0021 0022 #------------------------------------------------------------------------- 0023 # Commands 0024 0025 # myproc text 0026 # 0027 # Dummy procedure 0028 0029 proc ::mylib::myproc {text} {D0030 puts "Hello, $text!" 0031 }
A |
Quill uses your project's metadata when creating the file header.
Update it to describe your module as desired.
|
B |
Notice that there are no package require or package provide
commands here. Those go in pkgModules.tcl; see
Section 3.2.
|
C |
If you put the module's code in the package namespace, you might want to
export some commands.
|
D |
This part is up to the user.
|
The application loader script performs the following functions:
Here is an example loader script:
0001 #!/bin/sh 0002 # -*-tcl-*- 0003 # the next line restarts using tclsh\A0004 exec tclsh "$0" "$@" 0005 0006 #------------------------------------------------------------------------- 0007 # NAME: myapp.tclB0008 # 0009 # PROJECT: 0010 # my-project: Your project description 0011 # 0012 # DESCRIPTION: 0013 # Loader script for the myapp(1) tool. 0014 # 0015 #------------------------------------------------------------------------- 0016 0017 #------------------------------------------------------------------------- 0018 # Prepare to load application 0019 0020 set bindir [file dirname [info script]]C0021 set libdir [file normalize [file join $bindir .. lib]] 0022 0023 set auto_path [linsert $auto_path 0 $libdir] 0024 0025 # -quill-tcl-beginD0026 package require Tcl 8.6.1E0027 # -quill-tcl-endD0028 0029 # quillinfo(n) is a generated package containing this project's 0030 # metadata. 0031 package require quillinfoF0032 0033 # If it's a gui, load Tk. 0034 if {[quillinfo isgui myapp]} {G0035 # -quill-tk-beginD0036 package require Tk 8.6.1E0037 # -quill-tk-endD0038 } 0039 0040 # app_myapp(n) is the package containing the bulk of the 0041 # myapp code. In particular, this package defines the 0042 # "main" procedure. 0043 package require app_myappH0044 namespace import app_myapp::* 0045 0046 #------------------------------------------------------------------------- 0047 # Invoke the application 0048 0049 if {!$tcl_interactive} {I0050 if {[catch { 0051 main $argv 0052 } result eopts]} { 0053 if {[dict get $eopts -errorcode] eq "FATAL"} {J0054 # The application has flagged a FATAL error; display it 0055 # and halt. 0056 puts $result 0057 exit 1 0058 } else { 0059 puts "Unexpected error: $result" 0060 puts "Error Code: ([dict get $eopts -errorcode])\n" 0061 puts [dict get $eopts -errorinfo] 0062 } 0063 } 0064 }
A |
The application loader script can be run directly on Un*x-like platforms;
it will be run against whatever tclsh is on the PATH.
Alternatively, you can execute it using 'quill run'.
|
B |
Quill uses your project's metadata when creating the file header.
Update it to describe your module as desired.
|
C |
The loader script sets up the auto_path to point at the user's
code. Any local teapots are presumed to be on the path already.
Note: it can cause confusion to set the TCL_LIB_PATH environment
variable when working with Quill projects.
|
D |
These marks allow Quill to update the Tcl and Tk version as your project
changes. Do not edit the code between the marks.
|
E |
Quill determines the Tcl/Tk version from the
'require Tcl' statement in project.quill, and from the
version of the development tclsh, as found on the PATH or
overridden by a configuration setting
|
F |
The loader always requires the quillinfo(n) package, which gives
the application access to the project metadata.
|
G |
If the metadata indicates that this app is a GUI app, then Tk is
loaded automatically.
|
H |
The loader requires the application's implementation package, and imports
all exported commands from the package's namespace. Note that the global
namespace is there for the user of the application; it is up to the
developer whether application code resides in other namespaces or not.
|
I |
The loader doesn't execute the application's main routine when the
application is loaded into an interactive shell. This gives the
developer the ability to run it interactive from the shell command line,
as desired.
|
J |
This code allows the application to exit with a fatal error message just by calling 'throw FATAL' with the error message. Any other error code will result in an "Unexpected error" message and a stack trace. |
0001 #------------------------------------------------------------------------- 0002 # TITLE: 0003 # main.tclA0004 # 0005 # PROJECT: 0006 # my-project: Your project description 0007 # 0008 # DESCRIPTION: 0009 # app_myapp(n): main procedure 0010 # 0011 #------------------------------------------------------------------------- 0012 0013B0014 0015 #------------------------------------------------------------------------- 0016 # Exported Commands 0017 0018 namespace eval ::app_myapp {C0019 namespace export \ 0020 main 0021 } 0022 0023 #------------------------------------------------------------------------- 0024 # Commands 0025 0026 # main argv 0027 # 0028 # Dummy procedure 0029 0030 proc ::app_myapp::main {argv} { 0031 puts "[quillinfo project] [quillinfo version]"D0032 puts "" 0033 puts "Args: <$argv>" 0034 }
A |
Quill uses your project's metadata when creating the file header.
Update it to describe your module as desired.
|
B |
Notice that there are no package require or package provide
commands here. Those go in pkgModules.tcl; see
Section 3.2.
|
C |
The default template puts main in the package namespace, and
exports it; alternatively, you can put main in the global
namespace.
|
D |
This part is up to the developer.
|
$ quill test ...Quill will run all test targets, and output the results. Alternatively, Quill will run a single test target given its name:
$ quill test mylib ...Test targets are defined by adding subdirectories to project/test/; the name of the subdirectory is the name of the target.
Each test directory contains an all_tests.test file, and one or more normal tcltest(n) files, e.g., mymodule.test. To run a specific test file, add its name to the command line:
$ quill test mylib mymoduleFinally, any options are passed along to tcltest:
$ quill test mylib mymodule -match "mytest-1.*"
The content of all_tests.test is pure boilerplate; it simply arranges to execute all other *.test files in the directory, each in its own instance of the Tcl interpreter, and accumulate the results. It is generally created automatically by Quill, or by copying all_tests.test from an existing test subdirectory.
Here is the skeleton of a typical module test script, as created by Quill:
0001 #------------------------------------------------------------------------- 0002 # TITLE: 0003 # mymodule.test 0004 # 0005 # PROJECT: 0006 # myproject: Description of my project 0007 # 0008 # DESCRIPTION: 0009 # mymodule(n): Test Suite 0010 #------------------------------------------------------------------------- 0011 0012 #------------------------------------------------------------------------- 0013 # Load the tcltest package 0014 0015 if {[lsearch [namespace children] ::tcltest] == -1} {There are several things to note in the above listing:A0016 package require tcltest 2.3 0017 eval ::tcltest::configure $argv 0018 } 0019 0020 namespace import ::tcltest::testB0021 0022 #------------------------------------------------------------------------- 0023 # Load the package to be tested 0024 0025 sourceC../../lib/mymodule/pkgModules.tclD0026 namespace import ::mymodule::* 0027 0028 #------------------------------------------------------------------------- 0029 # dummy 0030 0031 test dummy-1.1 {dummy test} -body { 0032 set a false 0033 } -result {true}
A |
The tcltest(n) package is loaded, and any options
passed to quill test are passed along to tcltest.
|
B |
Only the test command is imported from the tcltest:: namespace.
Used fully-qualified names for other tcltest(n) commands, or edit
this line to import additional commands.
|
C |
The test script uses source to load the package, rather than
package require; if the library package is installed into the
local environment (not unusual), it can be difficult to ensure that
package require always loads the code in the project tree.
|
D |
Quill generally creates library packages and test directories together,
and assumes that the tests in the directory are for the package in the
project/lib subdirectory of the same name. Also, notice that the test script sources the library package's pkgModules.tcl file. By convention, all library packages in a Quill project have such a file; see Section 3.2 for details.
|
In the meantime, test directories must be added by hand, usually by copying an existing directory and changing the names.