Other Tools
This document is unfinished - there a quite a bunch of other tools to be documented ...
Transcript - The Smalltalk Messages Window
In smalltalk, the Transcript plays the role of a console,
where useful information is sent to. For example, the compiler
outputs progress information onto the transcript when compiling methods
from a file or from the browser.
From your programs, you can send output to the Transcript via the messages:
show:,
cr and
showCR:.
Here are a few concrete examples (click to execute):
Transcript showCR:'Hello World'.
Transcript clear.
Transcript show:'The time is '.
Transcript show:(Time now).
Transcript cr
or:
Transcript show:'The time is '; show:(Time now); cr
or:
Transcript
showCR:('The time is %1, today is %2'
bindWith: (Time now)
with: (Date today) )
In very old Smalltalk versions, the Transcript and Launcher (described below)
were two separate applications.
Today, these two applications have been merged into a new Launcher.
NewLauncher - Combined Launcher and Transcript Tool
The Launcher allows startup of commonly used tools and utilities,
and contains the transcript window for messages to the user.
This application offers pulldown menus and buttons to open
useful applications, monitors and to perform most common operations.
In addition, the language, viewStyle and compiler settings can be set
via more convenient dialogs
(in previous versions, these had to be set by evaluating Smalltalk
expressions in a workspace or by editing the startup scripts).
The launcher is typically started from your "private.rc"
startup file.
Screenimage of the Launcher with a "motif" view style.
Starting with ST/X rev 3.3, the Launcher was completely rewritten,
using the new UI-builder framework.
The items found in the pullDown-menu
and the toolBar panel can now be changed using the convenient menu-editor;
i.e. it is very easy to create a user/project specific
subclass with different functions offered.
Also, the launchers functionality was moved to an abstract generic launcher superclass,
which does not provide any GUI, but is purely functional.
This architecture allows for future- and custom launchers to be build easily.
Use the launcher's settings dialog to change, save and load your personal preferences and settings.
The initial setting values are loaded from a
file named "settings.stx" in either the current directory
(where ST/X was started),
or under the ".smalltalk"-subdirectory under your home directory.
The settings dialog operates on the current setting values,
which are only valid during the current ST/X session.
I.e.: if you forget to save your settings to the settings-file,
these changes are lost when you exit Smalltalk/X.
Two area are of special interest:
- the behavior of text editors (cursor at end-of-line, tabulators, etc.)
can be changed in the "Settings"-"Tools"-"Editor" area.
Notice that tabulator columns are only used for cursor positioning.
The tabs in extenral files are always assumed to be multiple-of-8 tabs.
- the way sourcecode is colorized (syntax coloring)
is defined in "Settings"-"Tools"-"Editor"-"Syntax Color".
If you are used to Squeak or VisualAge styles, select the style and press the "Rest to:" button.
- the source code management (repository check-in and out) is
configured in "Settings"-"Sourcecode Management".
- compiler warnings are
configured in "Settings"-"Tools"-"Compilation"-"ByteCode".
Individual warnings, which have been disabled interactively, can also be reenabled there.
Workspace - A Tool for Expression Evaluation
Workspaces allow smalltalk expression to be entered and evaluated.
You can also use them as scratchpads or notepads for ordinary text.
Beside the general text editing features, Workspaces allow for Smalltalk code to
be evaluated (interpreted).
To do this,
select some text (which should represent a valid smalltalk expression),
and use one of the following popup- or toolbar-menu functions for evaluation (*)
- doIt - To evaluate the expression
- printIt - To evaluate the expression and paste the result
- inspectIt - To evaluate the expression and open an inspectorView on the result
- browse - To evaluate the expression and open a browser on the results classes
(*) In fact, if nothing is selected, the current cursor line is taken.
Therefore, most of the time, you simply have to enter an expression and click on one of the
evaluation buttons, or press one of the shortkey commands as listed below.
There are also keyboard shortcuts for the above function - typically
"ALT-d" ,
"ALT-p" ,
"ALT-i" and
"ALT-Shift-B".
Depending on your keyboard settings file ("keyboard.rc"
), the key assignments might be
different on your particular system.
If in doubt, look at the right-button menu or consult the Launchers System-Settings-Keyboard dialog.
An ongoing expression evaluation can be interrupted and a debugger is opened
by pressing the Interrupt key, "CTRL-c"
("Break" or "Untbr" under Windows).
By pressing the Abort key, ("CTRL-y" or "CTRL-Break" under Windows),
an ongoing expression evaluation can be aborted (without going into a debugger).
Aborting means: 'raising an AbortSignal', which is cought in all views' eventLoop.
Starting with release 4.1 of ST/X, workspaces support multiple pages (aka "buffers" or "tabs")
and a pull down menu, with additional functions:
- TimeIt
show the execution time it takes to evaluate the selected expression
- SpyOnIt
show an execution trace (messageTally-spy) of the selected expressions evaluation
- Browse Implementors
open a browser on the selected message selectors implementors
- Browse Senders
open a browser on the selected message selectors senders
- Browse References
open a browser on methods which refer to the selected global variable name
In addition, WorkspaceVariables and DoItVariables have been added:
- WorkspaceVariables
These are much like global variables,
but only visible and known in the context of "doIt" evaluations
(i.e. NOT in a methods code).
Being shared among all workspaces, these are very useful to pass an object reference
from one workspace or inspector to another,
or to keep objects around for later use without a need to introduce new global variable names.
Of course, they also save you from the danger of overwriting a global name by accident.
- DoItVariables
These are like local variables,
and only visible and known in the context of one single "doIt" evaluation.
They do not add new functionality, but avoid the need to declare locals in a doIt evaluation.
The workspace menu contains items labeled "Auto Define Variables", which can be checked
to force all unknown variables to be automatically declared as workspace or doIt variables.
If this option is turned off, undefined variables trigger an error message, as usual.
A special variant of the workspace is the so called "Evaluation Workspace".
This adds a separate view to show an evaluation's result, a list of currently defined
workspace variables, and the last few results in a history list.
The evaluation workspace can be opened from a regular workspace's pull down menu.
The set of sharedPools which are visible inside a doIt evaluation can be controlled by the
"Add SharedPool" and "Remove SharedPool" menu functions from
the "Workspace" section in the main menu.
Initially, no sharedPools are visible in a doIt evaluation.
You can add a private personalized page to the system workspace,
by creating a file named "MyWorkspace.wsp"
in the ST/X startup directory.
There, you may keep commonly used expressions/doIts to start tools or applications.
If such a file exists, the WorkspaceApplication automatically adds another page to its tab-list
and presents the contents of that file there.
In the 6.2 version, this has been extended to support multiple such private workspaces.
To do so,
- save the contents (using the "save as" menu function) into the ".smalltalk" folder in your home folder.
- add a bookmark (using the "bookmark-add bookmark" menu item).
Now, whenever you open a "myWorkspace", all of the bookmarked files
are shown in separate tab-pages.
You can remember a piece of code as a so called "Code Sniplet".
These sniplets are shared among all workspaces and code-views and are retained in a class variable
(they are not lost, when a workspace window is closed).
However, they are only persistent inside the image, which means that there is no external file persistency.
If you forget to save a snapshot image, or you start ST/X anew, these sniplets are lost .
The functions for sniplet handling are found in the "Edit" section in the main menu.
Snipplets can be very easily pasted into a textview via the abbreviation keystroke: type the name of the sniplet
followed by CMD-SPACE (on most keyboards, the CMD-key is named "Alt" and found to the left of the space-key).
For example, to paste a template for the "ifTrue:ifFalse:"
message,
type "itf "CMD-SPACE.
Standard sniplets are setup in
"Workspace>>initializeDefaultAbbreviations
"
as:
Abbrev | Expands to |
in | isNil |
nn | notNil |
it | ifTrue: [!] |
if | ifFalse: [!] |
itf | ifTrue: [!] ifFalse: [] |
int | isNil ifTrue: [!] |
inf | isNil ifFalse: [!] |
ints | isNil ifTrue: [^self] |
infs | isNil ifFalse: [^self] |
wt | whileTrue: [!] |
wf | whileFalse: [!] |
do | do: [:each | !] |
dt | detect: [:each | !] |
de | detect: [:each | !] |
det | detect: [:each | !] |
dtn | detect: [:each | !] ifNone: [] |
cl | collect: [:each | !] |
co | collect: [:each | !] |
col | collect: [:each | !] |
sl | select: [:each | !] |
se | select: [:each | !] |
sel | select: [:each | !] |
rj | reject: [:each | !] |
re | reject: [:each | !] |
rej | reject: [:each | !] |
inj | inject: ! into:[:pValue :each | ] |
ex | Error handle:[ex | !] do:[] |
np | nextPut: |
npa | nextPutAll: |
y | yourself. |
sh | self halt. |
ps | printString |
sr | self subclassResponsibility |
st | Smalltalk |
ts | Transcript showCR: |
trs | Transcript showCR: |
ik | includesKey: # |
abb | Workspace sniplets inspect |
ws | Delay waitForSeconds: 1 |
wfs | Delay waitForSeconds: 1 |
wfm | Delay waitForMilliseconds: 1000 |
slef | self |
sefl | self |
s | self |
ati | at:! ifAbsent: |
ini | initialize super initialize. |
newi | new ^ super new initialize. |
upd | update:something with:aParameter from:changedObject ! ^ super update:something with:aParameter from:changedObject. |
A | Array |
An | Array new> |
Aw | Array with:> |
Aww | Array with: with:> |
OC | OrderedCollection |
SC | SortedCollection |
D | Dictionary |
ID | IdentityDictionary |
Id | IdentityDictionary |
OCn | OrderedCollection new |
SCn | SortedCollection new |
IDn | IdentityDictionary new |
Dn | Dictionary new |
Sn | Set new |
0 | (0.0 @ 0.0) |
[ | [: !] |
Notice that the position of the text cursor after the sniplet insertion
is controlled by the presence and position of an exclamation mark ("!") in the sniplets text.
Also notice, that misspellings such as "sefl" are also included.
These help to fix typing errors immediately (as you see them while typing).
Starting with the 6.2 version, workspaces support multiple languages.
If the corresponding packages are loaded (libjavascript,libjava, libruby),
the evaluation language's syntax can be specified via the "workspace" menu.
Multilanguage support is still being developed, so you might encounter
inconveniences. For example, the debugger might not be able to deal with
other languages as nicely as with Smalltalk code.
Click here for a
tutorial on workspaces, which is found
in the "Tutorial for Beginners".
Text edit functions are described in
the "Editing Text Section"
of the "Getting started Document".
Inspector - Looking into an Object
Introduction
Inspectors allow looking into an object. They usually consist of
2 subviews, one showing the names (and possibly indices) of the
objects instance variables, the other showing the value of the selected
instance variable.
There are some specialized inspectors (for example: image inspectors), which
add more subviews and/or show the object additionally in a more user friendly
form.
Opening an inspector
Inspectors can be started:
- by executing:
anObject inspect
or:
anObject basicInspect
to any object.
(see below for the difference between inspect
and basicInspect
).
- by executing:
Inspector openOn:anObject
- by using the inspectIt-menu function in any codeview.
All codeviews allow inspecting the result of an expression evaluation,
by the inspectIt menu-entry
(there is also a keyboard abbreviation, such as CMD-i available).
- by double-clicking on a name entry in an inspector
Beside the obvious behavior, there are some special situations to consider:
- inspecting large collections
If the inspected object contains a large number of indexed instance variables,
only some of these are shown in the instance variable list initially (to save
some time during startup of the inspector).
In this case, the lists popup menu will contain an entry 'show more' to
increase (double) the number of instance variables shown.
- inspecting dictionaries
The variable list shown when dictionaries are inspected will show the
dictionaries keys instead of the raw (i.e. real) instance variables.
If this is not what you are interested in, use basicInspect:
,
which will open an inspector without this behavior.
- updating after a change
To avoid overhead, inspectors do not update their list automatically.
To force an update (for example, after a collection has changed its
size) click on the self
entry in the list.
This will both update the list
AND show the objects new printed representation in the value view.
Without updating, you may run into an index error (and therefore: a debugger),
if you select an entry in a collection which is no longer valid.
For example, try:
#(1 2 3) asOrderedCollection inspect
then, in the inspector, evaluate (doIt):
self grow:2
and finally click on the entry labeled '3' in the namelist.
Since the index 3 is no longer a legal one, you will run into a
debugger due to an index error.
To fix this, `continue' or `abort'
in the debugger, and force an update in the inspector by clicking on the self
entry.
- inspecting instances
Double clicking on a name/index in the instance variable list will open an
inspector on this instance variables value.
Examples (click to execute):
#('one' #two 3.0 4) inspect
#('one' #two 3.0 4) asOrderedCollection inspect
#('one' #two 3.0 4) asOrderedCollection basicInspect
( #('one' #two 3.0 4) asOrderedCollection removeFirst; yourself ) inspect
( #('one' #two 3.0 4) asOrderedCollection removeFirst; yourself ) basicInspect
(Image fromFile:'../../goodies/bitmaps/xpmBitmaps/smileys/smiley_angry.xpm') inspect
(Image fromFile:'../../goodies/bitmaps/xpmBitmaps/smileys/smiley_angry.xpm') basicInspect
(Color yellow) inspect
(Color yellow) basicInspect
(Array new:400) inspect
Inspect vs. basicInspect
Sending basicInspect
to an object will always open a general inspector,
which shows instance variables as they are physically present in the inspected object.
In contrast, inspect
is redefined in some classes to open an inspector showing
the logical contents.
In some collections, the physical implementation uses an extra collection to hold the contents.
Try inspecting an (nonempty) instance of Dictionary to see the difference:
|d|
d := Dictionary new.
d at:#foo put:1.
d at:#bar put:2.
d inspect.
d basicInspect.
or the differences in the inspectors of the above examples.
Process Monitor - Show & manipulate Smalltalk Processes
This tool displays a list of active Smalltalk processes (i.e. threads) and their current state.
Its popupMenu allows common operations to be applied to a process or a group of processes.
The process monitor is a very useful tool to find (and terminate or debug) leftover
background processes - especially during program development & debugging.
The fields are:
- Id - the processes ID; this number is assigned by the runtime system when
the process is created. Each process has a unique ID.
- Group - the process group ID; this is empty for process group leaders and
the ID of the group leader (the creator) for other processes.
The process group allows for easy termination of some process with all of
its subprocesses.
- Name - the processes name; this is provided for your convenience and has
no semantic meaning.
If no explicit name was ever given to the process, it's the name and ID
of its creator with " sub" appended.
- State - the processes execution state. See definitions below.
- Prio - the processes execution priority.
The priority is an integer in the range 1..31. If two or more
processes are runnable, the system selects the highest priority process
for execution.
If the process has a dynamic priority range, the range is shown behind
its current priority (which may change).
- Where - the method in which the process is currently executing or
in which it was suspended (went sleeping).
The states shown are:
- run - the process is runnable (but CPU is not executing it)
- active - the CPU executes this process right now
- wait - the process is waiting on some semaphore
- ioWait - the process is waiting on a IO-semaphore
- wrapWait - the process is waiting in a blocking API call (win32 only)
- eventWait - the process is waiting on an eventQueue-semaphore
- timeWait - the process is waiting on a timer-semaphore
- suspended - the process is suspended, but not waiting on a semaphore
- stopped - manually stopped; like suspended, but will not respond to interrupts
- halted - stopped by CTRL-C (win32 only)
- light - the process has not yet started (it has no stack allocated yet)
- dead - the process has died (these are normally not shown)
The process which ran at the time of the update is marked with
an (*) character. If none is marked, the scheduler was active (or waiting
for an event).
Processes which ran during the last timeSlicing period (1/10th second) are marked
with a (+) character.
The list is updated every few seconds, so be prepared for some delayed
visibility of new processes.
A popup-menu (and tool-buttons in the new version)
allows for useful operations to be performed on a selected process:
- Inspect - opens an inspector on the selected process.
- Debug - opens a debugger on the selected process.
- Resume - resume execution of a suspended process
- Suspend - suspend execution of the process
notice, that the process may be resumed by the system due to a timer
or I/O event.
- Stop - stop execution of the process
timer or I/O events will not resume a stopped process
- Abort - send an AbortSignal to the process
all processes are supposed to return to a save place (typically the
main event handling loop) when an abortSignal arrives. This can be used to
force a process "out of" a long term (or endless) computation.
- Terminate - terminate the process
sends a TerminateSignal to the process; the process has a chance to
perform any cleanup (unwind) actions and is then removed from the system.
- Terminate group - terminate the process and all of its group members
use this to terminate a process which has created background processes.
(for example, a workspace in which subprocesses were forked)
- Hard Terminate - terminate the process without cleanup
immediately terminates the process, without giving it a chance
to perform any cleanup (unwind) actions.
Only use this, if a terminating process blocks in its unwind actions
(due to a bug or deadlock).
As there are no unwind actions performed, the process has no chance for any
proper cleanup and leftover resources, open streams or locked semaphores
are likely to be encountered afterwards. Be aware of this, and only use this
if a regular abort or terminate operation fails.
- Raise prio - raise the processes priority by one
- Lower priority - lower its priority by one
By holding down the "CTRL" key while pressing the middle button,
another popupMenu is opened, which allows toggling the display details
flag.
With details on, more info is shown (which you might not be interested in).
The additional information (among others) is:
- UsedStack - the size of the stack being in use by the process
- TotalStack - the size of the stack as allocated for the process
This is adjusted dynamically by the runtime system.
Other items are only of interest for ST/X runtime system debugging.
Probably the most useful item found is the debug function,
which opens an inspector-like debugger on the selected process.
This may be useful if some process is waiting on
a semaphore and you want to see exactly where the wait is and how it reached
it. With the debuggers monitor option, you can even watch & see what
that process is doing !
Note:
Since at the time of the view update,
the active process is always
the process monitor itself, the distinction between run and active
states is useless here: you will always see that process as being active
in the monitors display.
This tool displays a list of Smalltalk semaphores, their internal count
and the list of processes on its waiting list.
This tool is useful to debug deadlock or endless-wait situations in
multithread applications.
The columns shown are:
- Id - an internal id (actually, the semaphores hashKey)
- Name - the semaphores userFriendly name (if it has one)
- Count - the semaphores count (i.e. the number of waits that go through
without blocking)
- Owner - the processId of the process which was dropping the count to
zero the last time (i.e. which got the semaphore). This id is not cleared
when the process releases the semaphore - it stays set, even if the semaphore
is actually free. I.e. it giced the ID of the current or the last owner.
- Waiting processes - the number and names of process(es) waiting for the semaphore
to be signalled.
Memory Monitor - Displays overall Memory Usage
This utility displays the amount of object memory used by the system,
and displays various other statistic values.
Its popUpMenu offers functions to manually perform
either blocking- or nonBlocking background garbage collects.
Some of those functions are provided as debugging & measuring tools,
and not required by the typical user.
The numbers shown are (top to bottom):
- max - the maximum overall amount in bytes (since start of the monitor),
- tot - the current total amount of used memory (new + old + free)
- all - the current used amount of memory (new + old)
- new - the amount of newSpace used
- frl - the amount of memory in free lists (fragmented free space)
- fre - the unused portion of oldSpace (compact free space)
- old - the amount of oldSpace used
- mal - malloc'd memory (not inside object memory)
- mto - malloc'd memory (not inside object memory)
- code - jitted code (not inside object memory)
- min - the minimum overall amount (since start of the monitor)
the other numbers are less of interest to normal users, but give some info to VM developers:
- t - the current dynamic tenureAge
- I - the internal state of the incremental garbage collector (2 = idle)
- weak - the number of weak objects
- rem - the number of objects in the remembered list (old->new crossrefs)
- lrem - the number of contexts in the lifo list (obj->stack crossrefs)
- minSc - scavengers worst case survivor percentage
- number of scavenges (minor collections) since system started
- % - the fill-grade of newSpace after the last scavenge
the graphic displays a history of the used amount. Newspace size
is shown in orange (light grey in b&w displays),
freelistspace in green (dark grey)
and oldspace in white.
The history is updated twice a second.
Use the key-commands 'f' (for faster) and 's' (for slower) to change
the update interval.
Pressing 'r' (for reset) rescales the display.
The typical picture shown is some saw-tooth figure;
memory use is usually growing until a new-space collection reduces the amount.
The memoryMonitor also provides a popup menu for common garbage collect
operations:
- collect garbage - perform a mark&sweep oldSpace collect.
the system will be blocked while doing this.
- collect garbage & symbols - like above, but reclaim unused symbols as well.
- collect garbage & compress - perform a compressing oldSpace collect.
the system will be blocked while doing this.
- background collect - perform a non blocking mark&sweep collect.
the system will continue to react, since this collect is performed
incrementally in the background.
This is executed at low priority; if other user processes (at normal priority)
are currently running, this garbage collect may not make any progress.
- reset statistic values - clears minSc & max amount
The others submenu allows less frequently needed operations
to be invoked:
- scavenge - perform a newSpace collect
- tenure - clean the newSpace; surviving objects
are immediately tenured into the oldSpace
- hi prio incremental collect - perform a non blocking mark&sweep collect.
the system will continue to react, since this collect is performed
incrementally in the background.
In contrast to the above ("background collect"),
the incremental garbage collect is performed at high prioriy and guaranteed
to make some progress.
- cleanup memory - sends all classes a
#lowSpaceCleanup
message, to have them free any cached or buffered data.
If your classes keep any recoverable objects in classVariables (caching),
these should implement this message and release these objects there.
- flush method history - flush method history
The method history (if enabled in the launchers "Source & Debugger"
settings dialog) keeps previous versions of changed methods.
Over time, this may take up a lot of memory and should be flushed
periodically by selecting this menu item.
- unload autoloaded classes - unloads all classes which were autoloaded
and changes them to become autoloaded again.
Use this, to remove examples, demos and games which are no longer needed.
- compress sources
this writes out all incore method source string to a file called
st.src
and replaces the in memory strings by references
into this file. This reduces memory requirements after you have changed
(or filedIn) lots of code.
Be very careful in keeping this file
intact, unchanged and in sync with images.
Since your methods sources are no longer directly
available as string objects after doing this,
your methods source is lost, if this file gets corrupted.
(However, you still have your changes file around for emergency)
Memory usage - Displays Statistics on Memory Usage by Class
This utility
displays the amount of memory allocated by individual classes.
The display can be sorted by different criteria - use its popupMenu to
change this.
Since scanning the memory is a time consuming operation,
there is no automatic update of the list;
use the menus update function to manually update the display.
A memoryUsageView is useful to find memory leaks.
In Smalltalk, these are not caused by not freeing memory, but instead
by keeping references to objects in globals or class variables.
(so, if you find those leaks, don't blame it on the garbage collector;
the collector cannot free the memory as long as any reachable
reference to an object exists.)
The menu includes two very useful functions, which help in finding
those references:
- owners
which opens an
inspector on all objects owning references to instances of the
selected class
(showing the names/indices of the instance variables,
which hold a reference).
- ref chains
which displays chains of references from a global to instances of the
selected class.
Thus, if you have trouble finding out why some object is not garbage collected,
open a memory usage view, select the class and use the ref chains
menu function to find out how those instances are still references.
Notice, that the owners function will not be much of a help,
if the object in question is kept from being freed by a long
chain of references (for example, if it's in a long linked list which is
anchored in a global variable).
Also notice, that the ref chains function may be very time consuming.
This tool lists the classes/methods/functions as contained in the loaded
dlls (shared libraries).
This is useful to find out version information in case of an error.
The tool's menu also allows for a dll or the complete package to be unloaded.
Its popUpMenu also provides a convenient way to get a module's version information into the clipBoard.
Event Monitor - Displays Events sent to a View
This tool is useful when keyboard mappings are changed or tested.
It outputs the
incoming event-messages on the standard output (xterm-window / console)
or alternatively to the Transcript.
(similar to the 'xev'
XWindow utility).
To try it, open an EventMonitor, place the mouse pointer into it, and press
some key(s) on the keyboard. Watch the trace output.
An EventMonitor can also be started via the Launchers "System-EventMonitor" menu item.
This tool displays a view's widget hierarchy graphically (Smalltalk views only).
When started via the launcher, a crosshair cursor is shown, and
you should click on some (smalltalk-) view on the screen.
That view's widget hierarchy will then be displayed;
visible components are displayed in red color,
invisible (i.e. hidden or unmapped views) are drawn black.
The popupMenu shows various details about a selected widget
and allows further inspection.
A graphical viewTree can be opened via the launchers "Tools-Views"
pullDown menu; either on a single view (which is to be selected with
the mouse), or on all views.
This tool is opened via the Launcher's "Window"-menu.
This tool has been obsoleted by the "View Tree Inspector", described below.
This tool allows for the hierarchy of a (Smalltalk) window's widgets
to be inspected. After startup, you should pick a window by first clicking on
the "Pick a Window" button. Then, when the crosshair cursor is shown,
click on some (smalltalk-) view on the screen.
That view's widget hierarchy will then be displayed and the menus provide access to various
useful information to a programmer.
This tool is opened via the Launcher's "Window"-menu.
Method Finder - Find a Selector by Argument & Result
The method finder answers questions of the form: "given this input, and that desired output, what is the name of the
method to invoke". A concrete example could be: "what is the name of a function to convert a string from lower- to uppercase".
This tool was ported from squeak, and can be started via the Laucher's "Classes-Special->MethodFinder" menu function.
Use an example to find a method in the system.
Type receiver, args, and answer in the top panes, like 4 5 1
.
Then press the search button.
The lower left pane will show all messages which - when send to the receiver 4 with an argument of 5 answer the value 1.
Try it again with a receiver of 'hello'
, and argument of 3
and an
answer of 'llo'
.
Finally, to answer the above example-question, try it again with a receiver of 'hello'
, no argument
and an answer of 'HELLO'
.
You can write expressions in the fields to create a non-literal
object such as a Dictionary (rather than using strings and numbers).
In addition, a limited browser is included: selecting an item in the lower left pane
shows the implementors in the upper right pane; selecting any of the implementors will
display the methods code in the lower right pane (which is readOnly; i.e. no accept
is possible).
The methodFinder-GUI is actually using the MethodFinder
-class to do the actual work.
This one provides even more search functionality.
For example, if you evaluate ("printIt") the following in a workspace
MethodFinder methodFor: #(
(4 3) 7
(0 5) 5
(5 5) 10)
it will discover (data1 + data2) - i.e. a message selector which satisfies all of the three
constraints.
MethodFinder GUI
The MethodFinderWindows provides an easy to use GUI interface to the above described functionality.
To use, enter the receiver value, the number of arguments, optionally any argument values, and the expected
result (answer) into the top-left panes.
Press Search to find the set of methods which conform to this specification.
Some fancy examples of its usefulness are:
Receiver | Arg1 | Arg2 | Result | Finds this |
'knock knock' | $k | | 'noc noc' | 'knock knock' copyWithout: $k |
'30 apr 1999' asDate | | | 'friday' | '30 apr 1999' asDate weekday |
Float pi / 2 | | | 1 | 1.570796 sin |
This tools was originally written by Ted Kaehler, Scott Wallace and Dan Ingalls for Squeak.
It is opened via the Launcher's "Classes"-"MethodFinder"-menu,
ToDo List - Tool to Remember Things to be Fixed
This tool monitors error and warning-messages from the compiler and displays them in a list.
Whenever a change is made to a class or a method, the TODO-list checks if any of those remembered
errors is now fixed. If that is the case, the entry is removed from the list.
The list is initially empty; however, every compilation error which is confirmed with
a "Continue" and many warnings will lead to an entry being added.
As an example, try to remove an instance variable which is still accessed in a method
from a class.
The use of this tool is especially helpful while programming new code,
where some of the sent messages are not yet implemented.
A double click on an entry in the list will open a systembrowser and navigate it to
the corresponding code.
Notice: you can quickly check a class (or group of classes) by selecting them in a browser
and then performing the "Recompile-All-Methods" menu item in the classLists "Debug"
submenu, while a ToDo-List tool is open.
This tool is opened via the Launcher's "Tools"-menu,
This tool shows a list of methods which contain either a static (coded) breakpoint
or which have a dynamic trap attached,
and makes it very easy to quickly locate and enable or disable breakpoints.
Usage
The Breakpoint-Browser's major use is in finding methods which contain breakpoints and to
enable or disable them.
When started, the list displays all locations of a breakpoint.
For that, the whole system is scanned for breakpoints, which takes a few seconds initially;
after that, it watches your changes and updates its list incrementally in real time,
without any further noticable delay. Therefore, it is better to keep this view open (or iconified)
during a development session, instead of closing and reopening it.
By checking corresponding
items in the "View"-menu, this list is filtered by type of breakpoint and by argument.
Breakpoints can be enabled or disabled both by type and parameter.
By default, halts and assertions are enabled, whereas breakPoints are disabled.
To open a browser on a selected method, either double-click on the item in the list,
or press the "Browse"-button in the toolBar menu.
Small editing changes like removing breakpoint code or adding information prints
can also be done directly in the code view: simply type it and accept as usual.
Dynamic breakpoints are set/cleared from within the system browser's debugging menu
(or via the traffic light buttons). Message selectors for statically coded breakpoints are:
#halt
#halt:
#breakPoint:
#breakPoint:info:
#assert:
#assert:message:
Breakpoints
Of special interest are the #breakPoint:
methods;
these behave much like ordinary #halt
messages, but differ in two aspects:
- by default,
#breakPoint:
-messages are ignored.
This means, that you can leave them in production code.
- they can be enabled/disabled easily;
individual breakpoint groups can be differentiated by their (symbolic) argument.
A typical use of these breakpoints is with the initials of a programmer as (symbolic) argument,
to allow individual programmers within a team to control the execution of
his own breakpoints. To do so, add a piece of code such as:
self breakPoint:#ab
or:
self breakPoint:#ab info:'bla bla'
where #ab
stands for an arbitrary key (such as your initials).
By default, these breakpoint-halts are ignored, so that the execution is not interrupted by a debugger.
However, they can be enabled or disabled at any time by evaluating:
self enableBreakPoint:#ab
or:
self disableBreakPoint:#ab
or from within the Breakpoint-Browser's "Enable"-menu.
Typically, this is done by the user named "ab", in order to activate his own breakpoints.
Halts
Halts can also be temporarily ignored by the debugger: the debugger's breakpoint menu
includes items to disable a halt for some time, for a number of occurrences or forever.
Such temporarily disabled halts can be found quickly by checking one of the halt-filters
in the "View"-"Halt"menu.
The list's popupMenu also includes a function to re-enable such a disabled halt.
Startup
The breakpoint browser tool is opened via the Launcher's "System"-menu,
Notice our convention at Exept Software AG:
in contrast to halts
, coded breakpoints can be left in published
code as long as further development and enhancements to the code are ongoing or likely,
and individual team members are still interested in aspects of the execution.
Then, this team member adds a breakpoint with his/her initials as argument to the code,
and individually enables all of his/her breakpoints using this tool for testing.
As breakpoints are ignored by default, this does not affect other team members.
SUnit - Unit testing framework and TestRunner GUI
This framework (-> Kent Beck, Ward Cunningham and others) allows for convenient
component testing.
This tool was ported to ST/X by Samuel Shuster and Travis Griggs - thanks to you and
all other Camp Smalltalk guys !
For automatic testing, testcases (subclasses of TestCase
) should define a bunch of methods
named 'test*', which test various aspects of your code.
For checks, the inherited messages #assert:, #should, #shouldNot etc. should be used.
See the provided ExampleSetTest for more info on how to use this.
The TestRunner GUI interface automatically searches for all testCases as present in the system,
and offers execution via a convenient pull-down list:
After selection of the test, run its test-methods by pressing the Run-Button.
All failures will be collected and provided in the lower pull-down list for debugging.
Although simple, this is a very useful tool and we highly recommend its use -
it will make your life MUCH easier.
Please read some good book(s) on eXtreme programming or
Kent Becks original "Smalltalk Testing"" paper
for more information.
Using the TestRunner
The TestRunner is started either by double-clicking on a TestCase class in the browser,
by evaluating:
TestRunner open.
or via the launchers "Tools-SUnit" menu item.
- Refresh - Button
Press this button to update the list of offered testCases (in the TestCase-PullDown list)
(Use this after new testCases have been added, or when testCases have been filedIn/autoloaded).
- TestCase Selection - PullDown list
Select a particular TestCase to run.
- Run - Button
Executes all test* methods from the selected testCase; rememberes the results and changes the
information view's background color to red, if any test failed or green, if all tests succeeded.
- ReRun Defects - Button
Re-Executes only the failed testCases from the previous run.
- RunAll - Button
Executes all testCases present in the system
- Defects - PullDown List
Displays failed testCases and allows for selective reRun with a debugger opening up at
point of failure.
- Browse - Button
Opens a SystemBrowser on the selected TestCase.
- Debug - Button
ReRun the selected failed testCase with a debugger opening up at point of failure (if it fails).
The main information window displays progress information (while executing testCases) and the final
result. Its color is changed to yellow while executing, and back to
green (if all ok) or red if any testCase failed.
Notice that some of the test runner's functionality has also been built into the
New Systembrowser.
This tool can also be opened via the Launcher's "Tools"-menu.
This tool provides a side-by-side comparison for two versions of a class or two classes.
Typically it is used to compare the current (in-memory) version of a class against an
other version of the same class in the source code repository.
Packager - A Standalone-Executable Builder and Packager
This assistant-application allows for standalone applications and binary class libraries
to be built very easily.
It will generate all required classes, files, start the compilation process,
generate a self-installing executable with a few mouse clicks.
A simple demo application like the (in)famous "Hello World" can be generated in a few minutes
(read the Introductionary Text for more info about it).
Prerequisites
Windows Users:
Please install either the "Borland Free Commandline Compiler Tools (bcc32)"
or the "Microsoft Visual-C++" package (also free).
In addition, the "NullSoft NSIS-Installer Package" is required.
Due to limitations and bugs in the Visual-C++ compiler (limit on the size of string-constants),
some Smalltalk code is still not compilable (classes which contain image-resource methods
for big images). Although microsoft is doing their best (a relative measure) to make things better
(they increase the string-limit with every new release), they still seem to be undable
to figure out how ti use malloc for string-data). We are patiently waiting for a real fix
and still using bcc in the meanwhile.
Therefore, we still recommend using the borland compiler suite.
Please install it at its standard location ("C:\Borland") as our makefiles might still contain
hard-coded pathes (yes, we are ashamed about this).
Unix Users:
You should already have the gcc compile suite (including all required header files) installed and ready to use.
For a lack of time on our side, there is currently no self-installer support for Unix.
The packager will generate a zipped tar file, which must be deployed and unpacked for use.
This may change in the near future.
Packages, Projects, PackageIDs and ProjectDefinitions
Smalltalk/X basically uses two objects for packaging and package identification:
- PackageIDs (also called ProjectID's occasionally)
- ProjectDefinitions
Older ST/X versions used instances of a Project class - this is now obsolete and will be
removed from the system (although there are still some minor uses of it, which might remain
there for backward compatibility for some time, as some customers have built their own packaging
scheme around it).
PackageIDs
These are simple symbols and are attached to classes and methods. If a method has a packageID
different from its class, it is called an extension method.
PackageIDs are used by the source-code manager to locate a classes' source container
within the directory hierarchy. Therefore, these IDs must have a certain fixed format:
they always consist of exactly two parts, the module and the directory part,
which are separated by a colon character.
The module is used as main-selector on where and how the
source code repository is accessed.
The directory is a path below that repository.
If checked out into the local filesystem, the module defines the top-level directory.
Thus, if a packageID is "stx:libbasic
", the corresponding sources will be found in the repository
associated to the "stx" module, under the directory "libbasic
". In the local file system,
it will be found under "stx/libbasic
".
As another example, if the packageID is "exept:expecco/plugins/foo
",
the repository is whichever
is associated with the "exept" module, and the subdirectory is "expecco/plugins/foo
".
The local path to the sourcefiles would be "exept/expecco/plugins/foo
".
Please notice that it does make sense to associate different repositories to different modules:
for example, you could setup the sourceCodeManager to use CVS access to the exept repository
for everything under the "stx" module, and at the same time, use a local SVN repository for
everything under the "myCompany" module.
Your own projects should always have a module which is distinct from other people's modules
(and especially from "exept" and "stx"). A good choice is your company name, your name
or a similar. This avoids conflicts, when you load other's packages later.
ProjectDefinitions
These describe the contents of a project, such as the classes to include, the set of extension
methods, any additional compilation information. ProjectDefinitions come in 3 flavours:
- GUI Application Definition
- non-GUI Application Definition
- ClassLibrary Definition
ProjectDefinitions are stored and managed as class-instances, located as subclasses of one
of ApplicationDefinition
or LibraryDefinition
.
As classes, they are themself managed, compiled and packaged as
part of the project (and also have the same PackageID as their components).
They are also treated like any other class w.r.t. source code management.
Packaging
All classes and extension methods belonging to a single package are supposed to be loaded (and possibly unloaded)
together. They are also usually deployed inside a single dynamic link library ("dll", for short).
In the Unix world, these are called "shared object" or "so".
Finally, they are stored in a common directory both on the local file system and
in a source code repository (CVS, SVN, etc.).
Structure of a Project
The artefacts as manipulated by the packager are:
- the ProjectDefinition class
This defines the type of application (GUI / non-GUI), its contents (i.e. the set of classes to
be included in the binary itself and the set of library-dll's to be included in the deployed
package), and some other metadata, such as icon, title etc.
- the ApplicationModel class (GUI-Applications only)
This defines the GUI, and is typically created using the UI-Painter.
- the Startup class
This is the first class which gets control when the executable is started;
it can analyze the command line arguments, read patches or updates, start background ptocesses,
and will eventually open the applications GUI. This corresponds to the "main" function in
other programming languages.
Build Procedure
All of the three components above can be generated for you by the packager,
to provide an initial framework for further work. Of course, this automatically generated
code will only implement an empty application without any useful functionality.
However, it is easy to modify this into something more interesting, using the
UI-Painter,
the Menu-Builder and the
SystemBrowser.
When these classes have been defined, all required files are stored in a temporary
build directory. This means that the classes are filed out,
and make- and other support files are generated.
Finally, the actual build process is started. This requires an external C-compiler.
Under windows, both Borland-C (free download available via the internet) and
Microsoft's Visual-C++ (also available for free) can be used. Support for the
lcc compiler suite is also being developed, but not yet finished.
As of Nov 2009, we still recommend the use of the Borland Suite (bcc), because
the Microsoft compiler still has serious bugs which prevent some classes from being
compiled (especially: the string.constant limitation is fatal).
A self-installing executable is built using the NullSoft NSIS package.
This is also required to be installed before the packager is started.
After the build, all required files are packaged in a single install-file.
This is called "MyApplicationSetup.exe" and found in the project-specific subdirectory
of the build directory. For deployment, this single file has to be delivered to a customer
and executed there.
Summary: It has NEVER been easier to create a GUI application.
Terminal - A Shell Terminal
This application provides a VT100 terminal emulation as an interface to the Operating
Systems command line interface (i.e. "shell" under Unix / "command.com" under DOS based systems).
This application is known to have some bugs:
- The VT100 emulation is neither complete nor correct.
- Under windows, any input is buffered and only passed to the command shell (command.com)
when the return key is pressed (then, the echoed characters magically appear).
This behavior started after windows95 (where it worked correctly). Some magic setting
of the comsole seems to be missing to set it to "raw/immediate/unbuffered" mode.
Any help would be appreciated.
Copyright © 1995 Claus Gittinger Development & Consulting, all rights reserved
<cg@exept.de>
Doc $Revision: 1.139 $ $Date: 2012/06/01 11:25:05 $