Tools are designed for major extensions in DrScheme's functionality. To extend the appearance or the functionality the DrScheme window (say, to annotate programs in certain ways, to add buttons to the DrScheme frame or to add additional languages to DrScheme) use a tool. The Static Debugger, the Syntax Checker, the Stepper, and the teaching languages are all implemented as tools.
Libraries are for extensions of DrScheme that only want to add new functions and other values bound in the users namespace. See the DrScheme manual for more information on constructing libraries.
Tools rely heavily on MzScheme's units. See units for information on how to construct units. They also require understanding of libraries and collections.
When DrScheme starts up, it looks for tools by reading fields in the info.ss file of each top-level collection. DrScheme checks for these fields:
tools (listof (listof string[subcollection-name]))
tool-names (listof (union #f string))
tool-icons (listof (union #f (
cons string[filename] (listof string[collection-name]))))
The tools field names a list of tools in this
collection. Each tool is specified as a collection path,
relative to the collection where the info.ss file
resides. As an example, if there is only one tool named
tool.ss, this sufficies:
(define tools (list(list"tool.ss")))
If the tool-icons or tool-names fields
are present, they must be the same length as
tool. They specify the path to an icon for each tool
and the name of each tool. This information shows up in the
about box, Help Desk's bug report form, and the icon appears
on the splash screen as the tool is loaded at DrScheme's
startup.
Each of tools files must contain a module that
provides tool@, which must be bound to a
unit/sig The unit
must import the drscheme:tool^ signature, which is
provided by the tool.ss library in the
drscheme collection. The drscheme:tool^
signature contains all of the names listed in this manual.
The unit must export the drscheme:tool-exports^
signature.
The drscheme:tool-exports^ signature contains two
names: phase1 and phase2. These names must
be bound to thunks. After all of the tools are loaded, all of
the phase1 functions are called and then all of the
phase2 functions are called. Certain primitives can
only be called during the dynamic extent of those calls.
This mechanism is designed to support DrScheme's
drscheme:language:language<%> extension
capabilities. That is, this mechanism enables two tools to
cooperate via new capabilities of languages. The first phase
is used for adding functionality that each language must
support and the second is used for creating instances of
languages. As an example, a tool may require certain
specialized language-specific information. It uses phase1 to
extend the drscheme:language:language<%> interface
and supply a default implementation of the interface
extension. Then, other languages that are aware of the
extension can supply non-default implementations of the
additional functionality.
If the tools raises an error as it is loaded, invoked, or as
the phase1 or phase2 thunks are called,
DrScheme catches the error and displays a message box. Then,
DrScheme continues to start up, without the tool.
For example, if the info.ss file in a collection contains:
(module info (lib "infotab.ss" "setup") (define name "Tool Name") (define tools (list(list"tool.ss"))))
then the same collection would be expected to contain a tool.ss file. It might contain something like this:
(module tool mzscheme
(require (lib "tool.ss" "drscheme")
(lib "mred.ss" "mred")
(lib "unitsig.ss"))
(provide tool@)
(define tool@
(unit/sig drscheme:tool-exports^
(import drscheme:tool^)
(define (phase1)
(message-box "tool example" "phase1"))
(define (phase2)
(message-box "tool example" "phase2")))))
This tool just opens a window to indicate that it has been loaded.
If a language can be implemented as a module (see module for details) and the standard language settings are sufficient, simply create an info.ss file in the collection where the module is saved. Include these definitions:
drscheme-language-modules This must be bound to a list of
collection path specifications, one for each language in
the collection. Each collection path specification is the
quoted form of what might appear as an argument to
require, using the lib
argument.
drscheme-language-positions This must be bound to a list of language positions. Each language position corresponds to the position of the language in language dialog. Each language position is a list of strings.
drscheme-language-numbers This is optional. If present, it must be a list of a list of numbers. Each list corresponds to a single language from this collection. Each number indicates a sorting order in the language dialog for the corresponding string in drscheme-language-positions.
drscheme-language-one-line-summaries This is optional. If present, it must be a list of strings. Each string is displayed at the bottom of the language dialog when the corresponding language is selected.
drscheme-language-readers This is optional. If
present, it must be bound to a quoted list of module
specifications (that is, a quoted version of the argument
to require, except not plain strings). Each
specification must be a module that exports a function
named . Each of these
read-syntax functions must match MzScheme's
read-syntax primitive's contract, but may
read different concrete syntax.read-syntax
The lists must have the same length.
As an example, the Essentials of Programming Languages language specification's info.ss looks like this:
(module info (lib "infotab.ss" "setup")
(define name "EoPL Support")
(define drscheme-language-modules
(list '("eopl-lang.ss" "eopl")))
(define drscheme-language-positions
(list '("Essentials of Programming Languages"))))
This info.ss file indicates that there is a single language in this collection. The module that implements the language is the eopl-lang.ss file in the eopl collection. Additionally, the langauge dialog will contain Essentials of Programming Languages as a potential language.
For collections that define multiple (related) languages, if the language-positions contain multiple strings, the languages whose leading strings match are grouped together. That is, if two languages have strings:
'("My Text" "First Language")
and
'("My Text" "Second Language")
the two languages will be grouped together in the language dialog.
With some additional work, any language that can be compiled
to MzScheme's language is supported by the tools interface,
not just those that use standard configurations and
module.
Each language is a class that implement the
drscheme:language:language<%> interface. DrScheme also
provides two simpler interfaces:
drscheme:language:module-based-language<%> and
drscheme:language:simple-module-based-language<%>,
and
mixins
drscheme:language:simple-module-based-language->module-based-language-mixin
and
drscheme:language:module-based-language->language-mixin
that build implementations of language^s from these simpler interfaces.
Once you have an implementation of the
drscheme:language:language<%> interface, call
drscheme:language-configuration:add-language to add the language
to DrScheme.
Each language comes with its own type, called
settings. This can be any type the language
designer chooses, but to aid documentation, we call it
settings here. The settings type is expected to
contain parameters of the language, such as case
sensitivity, etc. The implementor of the language provides a
GUI so the user can configure the settings and all of the
language's operations accept a setting. DrScheme maintains
the current settings for each language.
Some tools may require additional functionality from the
drscheme:language:language<%> interface. The
drscheme:language:extend-language-interface
function and the
drscheme:language:get-default-mixin
mixin make this possible.
For example, the MrFlow tool expands programs, analyzes it
and then displays sets of values for each program point.
These sets of values should be rendered in the syntax of the
language that MrFlow analyzes. Since MrFlow doesn't apriori
know which languages are available, it can call
drscheme:language:extend-language-interface
to extend the drscheme:language:language<%>
interface with a method for rendering sets of values and
provide a default implementation of that method. Tools that
know about MrFlow can then override the value rendering
method to provide a language-specific implementation of
value rendering. Additionally, since the
drscheme:language:get-default-mixin
adds the default implementation for the value-set rendering
method, all languages at least have some form of value-set
rendering.
In addition to normal, textual expressions, DrScheme supports expressions
whose syntax can be arbitrary graphics. Any graphical syntax must be
implemented as snip% objects. If the snip
implements the drscheme:snip:special<%> interface, the
read-special method is used to convert it to a
syntax object. If the snip does not implement the
drscheme:snip:special<%> interface, it is treated as a constant,
like numbers or quoted objects.
DrScheme graphical syntax is provided as part of the
drscheme:language:open-input-text function
(used by the drscheme:language:module-based-language->language-mixin
mixin and the built-in languages of DrScheme).
If you are using the built-in languages or a language that
implements this mixin, you can use this interface. If not,
you should probably use MzScheme's
#$ support directly, or call
drscheme:language:open-input-text.
As an example, this class, derived from snip%
is a graphical small square that expands into a call
to make-square:
Each frame in DrScheme has certain menus and functionality,
most of which is achieved by using the framework.
Additionally, there is one mixin that DrScheme provides to
augment that. It is drscheme:frame:basics-mixin.
Be sure to mix it into any new frame class that you add to
DrScheme.
Each of the names:
is bound to an extender function. In order to change the behavior of drscheme, you can derive new classes from the standard classes for the frame, texts, canvases. Each extender accepts a function as input. The function it accepts must take a class as it's argument and return a classes derived from that class as its result. For example:
(drscheme:get/extend:extend-interactions-text
(lambda (super%)
(class super%
(public method1)
(define (method1 x) ...)
...)))
extends the interactions text class with a method named
rawscmmethod1.
Macro-expanding a program may involve arbitrary computation
and requires the setup of the correct language. To aid this,
DrScheme's tool interface provides
drscheme:eval:expand-program to help. Use
this method to extract the fully expanded program text in a
particular language.
Because expanding the user's program may require DrScheme to
evaluate arbitrary code that the user wrote, tools that
expand the user's program should also also the user to break
the expansion. To help with this, the tools interfaces
provides these methods:
enable-evaluation
and
disable-evaluation.
Since your tool will be expanding the program text, you
should be both overriding
enable-evaluation
and
disable-evaluation
to disable your tool and calling them
to ensure that only one expansion is happening
at a time.
Finally, DrScheme provides the
set-breakables,
method. This method controls what behavior the Break button
has.