Alpha
Version:9.2.3 - "Suhail"
Last update:2021-05-21 14:43:30




This document explains some debugging techniques with Alpha.
See the Bug Reporting file for advice on how to write and send bug reports. In the Help menu, there is a submenu with commands related to bug reporting.

Troubleshooting

The problem you are experiencing most likely came with the version of Alpha you installed, and therefore affects also other people having installed this version. This is the sort of bug it is in the interest of the community to have reported and fixed.
However, there are two other possibilities: one is that your particular installation of Alpha got corrupted somehow. Preferences files and certain index files can sometimes get corrupted (whereas it is highly unlikely that the program itself get corrupted, so it is almost never a solution to reinstall the whole program).
The other possibility is that some of Alpha's numerous preferences got set in some way that make the program behave in a way that seems buggy, but which in reality is an intended feature, appreciated by certain users.
This short section gives some advice on how to rule out these two possibilities: you can try to start up Alpha from a fresh Prefs folder to see if the problem goes away, and you can instruct Alpha to rebuild all the indices it relies on.

The Alpha Developer Menu and The Debugging Palette

For troubleshooting and debugging, it is recommended to activate the Alpha Developer Menu (click here to open the Menus Preferences dialog accessible via Alpha ↣ Global Setup ↣ Menus).
This menu contains many facilities for debugging, in particular the Debugging Palette. This is a small floating window which provides easy access to many of the debugging related tools described in this document, such as Obtaining 'errorInfo', Rebuilding Tcl indices and Package Info, and Tracing.
Click here to see the palette. More information is available in the Debugging Palette Help window.

Rebuilding Tcl indices and Package Info

AlphaTcl relies on two systems of indices to find the Tcl files in which procedures and packages are defined: one are the tclIndex files found in each folder inside AlphaTcl. (This is the standard Tcl way of finding procedures.) The other system consists of index files kept in a Cache folder inside the application bundle and serves to keep track of package definitions without having to source those files as long as they are not needed.
In normal usage of Alpha, it should never be necessary to rebuild any of these indices, but if the Tcl files are modified, for example a new procedure is defined in some file, or some package definition is modified, the indices may need to be rebuilt. The symptom is typically an error telling that some proc is not defined. It is easy to rebuild the indices: select the Alpha ↣ Rebuild AlphaTcl Indices command in the Alpha Developer Menu. This lets you specify which indices or Package Infos you want to rebuild, and after rebuilding indices, quit and restart Alpha, to see if it helps.

Removing preference files

One of the most common problems in any software is a corrupted preferences file. A different problem, which is sometimes encountered in Alpha is that the user sets some exotic setting by accident, leading to unexpected behaviour. Restarting Alpha with a virgin Prefs folder is of course the proper first experiment to confirm these hypotheses. If the problem goes away, then the bug has been localised to the prefs, and some further debugging is then due in order to reconstruct a usable prefs configuration. If the bug is still experienced with a virgin prefs folder, then certainly the bug is of more global nature, and the developers will be very interested in the fact that the bug can be reproduced with a pristine Alpha installation.
Alpha stores all of its preferences in a special folder on your hard drive, which by default is ~/Library/Preferences/Alpha-v9.0
To locate your preferences folder right now, click here.
If the files are not present, a rather minimal set of files will be created automatically at start-up, so that it is present while Alpha runs.
So in order to start up with fresh preference files, do the following:
  1. Quit Alpha.
  2. Locate and rename your preferences folder, say to Alpha-v9.0-suspended
  3. Restart Alpha.
Since Alpha doesn't recognise the old folder's name as its prefs folder, it will create a new one.
You can now test whether the problem has gone away or if it persists. If the problem persists, your prefs are innocent, and you will want to reinstall them. So do this:
  1. Quit Alpha.
  2. Delete the new preferences folder created by the test.
  3. Rename your original prefs folder Alpha-v9.0-suspended to its original name Alpha-v9.0.
  4. Restart Alpha.
It is possible that this restart will trigger a rebuilding of indices (which you are informed about in the status bar).
IMPORTANT: only move or restore prefs files while Alpha is not running. Otherwise Alpha may overwrite the files with current values, and either the experiment or your old precious prefs file may be ruined.
If the problem went away with the clean-prefs relaunch, surely there is something wrong with the original prefs. You now have two options: either you can stick with the new prefs, and from within Alpha reconfigure all the settings you had made. If you had not made many changes to the default configuration, perhaps making them once again is not so difficult. On the other hand, if you had spent a lot of time configuring, and possibly made many tweaks in you prefs.tcl file, then of course you will rather go into the trouble of restoring these files little by little to see where the problem lies. In other words, you'll have to figure out exactly which file causes the problem.
Here is a list of the most common prefs files, which you may look into, to see if you can detect some anomaly, or guess which is most likely to be related to the problem:
prefs.tclthe prefs you wrote yourself in Tcl
arrdefs.tclholding many of the prefs you set in dialogues, including filesets information
defs.tclditto
earlydefs.tclmostly more internal prefs that Alpha defines itself

In addition, there may be mode specific prefs files like for example
TeXprefs.tclTeX-mode specific prefs (that you wrote yourself)

Starting from the clean prefs, you can try to
  1. Quit
  2. Copy one of the original prefs files into the current experimental prefs folder
  3. Restart
  4. Test
If you detect that one specific prefs file causes the problem, you can either leave it out, hoping that the settings it contains can be restored manually from within Alpha, or you can try to look into the file and restore it in pieces. If you try this, beware that if you edit it in Alpha, then Alpha is already open, and then when it quits it may overwrite the changes you made! You might consider editing in another editor, or you should edit the file outside the prefs folder and only copy it in after Alpha has quit.
Note: outside the Alpha-v9.0 folder there is also a .plist file net.sourceforge.alphacocoa.plist. At present, none of your user settings are stored there; it is used only for caching some values. It won't hurt to delete this file, but it is also quite unlikely that it will address any problem.

Removing single preference settings

Sometimes one of your preferences has a faulty value that prevents the proper operation of some routine. If the error message (or a note from an AlphaTcl developer) suggests that this might be the case, you can try selecting the menu command Alpha ↣ Preferences ↣ Remove Saved Setting to restore a preference value to the default value. You must immediately restart Alpha after selecting this command in order for the default value to be restored.

Debugging

The AlphaTcl library is huge: more than 160000 lines of code in over 500 Tcl files. How to figure out where the wrong code is? Of course this requires some familiarity with the layout of AlphaTcl, but here are some tricks to narrow it down.
Most scripts and code snippets are bundled into procedures, often just called procs. Each proc takes certain arguments, does some things to the content of some window, modifies the state of some global variables, and finally returns some value. The expected behaviour of each proc is specified in comments before the actual Tcl code.
The tclMode.tcl file is one example of an installed .tcl file that defines AlphaTcl's Tcl mode. Click here to locate this collection of files in your local disk. AlphaTcl's Tcl mode and the package Alpha Developer Menu are used extensively by developers to improve Alpha.

Which proc to debug?

Identifying the faulty proc is already a substantial part of the debugging. If there is an error, the first step is to look into 'errorInfo', as described below. (Be aware that this info can sometimes be misleading, as it can contain older irrelevant "errors".)
If a menu-selection causes a problem, then there are three ways you may be able to determine which procedure to investigate:
  1. Ask on the alphatcl-developers mailing list; see the information in the Internet Resources section for more information.
  2. If the menu item has a Keyboard Shortcut (or if the problem occurs with a given key-press), then use Alpha ↣ Global Setup ↣ Keyboard Shortcuts ↣ Describe Shortcut menu item (which is bound to F7) to find the procedure. For example, ⌘I might be bound to menu::textEditProc Text fillParagraph. In this case, [menu::textEditProc] is the first procedure that you might want to debug.
  3. If the menu item is called Line To Paragraph, then the procedure might be named lineToParagraph (i.e. scrunch everything together and make the first character lower case).
Click here to open a dialogue listing all defined procedures in the various Tcl namespaces -- selecting one will open the file in which the procedure is defined.

Obtaining 'errorInfo'

Whenever an AlphaTcl procedure encounters a true error in the code, the error info is recorded in a global 'errorInfo' variable, which can be easily displayed in a new window. There are several ways to achieve this:
If the error has just occurred, and you still do not know whether you will be able to reproduce it, the best is to try to get the 'errorInfo' immediately. (The more operations you do before getting the 'errorInfo', the higher is the risk that the error will be overwritten by some irrelevant info.) The most direct methods is
METHOD 1: press Escape-X and then type this command into the status bar:
    putScrap $errorInfo
followed by return. This will place the value of 'errorInfo' into the Clipboard. Now open a new window and do Paste.

Alternatively, you can use the shell:
METHOD 2: Open the Alpha Tcl Shell (⌘Y), and write
    set errorInfo
in the prompt, followed by return. This will display the error message directly in the shell.

METHOD 3: if the Alpha Developer Menu is active, select in it Alpha Testing ↣ Display Error Info. You can also find this item in the Debugging Palette, which is activated through the Alpha Developer Menu, or by clicking here. Finally the item Display Error Info is also available from the Tcl Menu, should that be active.
If the bug is reproducible, then you have time to prepare all these tools: open the Tcl Shell, turn the Alpha Developer Menu on, create the Debugging Palette. And then, once all this is active, go back to the original window and reproduce the bug, and immediately select Display Error Info from the Debugging Palette.
Having the shell open while reproducing a bug is also useful because certain errors are displayed here automatically if it is open.
Finally, it is very useful, while you are debugging, to adjust the preference variable Display Errors In (in the Errors Preferences panel) to the value new window. This will make all errors be displayed immediately in a new window.
We assume now that you got hold of the 'errorInfo'. Even if you don't understand it -- it is a rather technical message -- you might at least figure out from it in which proc the error occurs: typically it will say something like error, unknown variable bla in proc alpha::foo. Then of course the proc alpha::foo has to be investigated.
If you don't feel like debugging yourself, you can attach the 'errorInfo' to your bug report, or ask for help on one of the mailing lists, described in the Readme file.

Looking into Tcl procs

Once you know the name of the AlphaTcl procedure causing the problem, you wish to have a look at the file where this proc is defined. To find the proc definition, there are tools in the Tcl Menu (see Tcl Procedures ↣ Find Proc Definition), or in the Alpha Developer Menu.
Another way which is useful is to use the AlphaTcl Shell: write the name of the proc here and press F6 (Shift-Command-double-click). This will open the file containing the proc definition, and move to it. Shift-Command-Double-Clicking on the name of a proc works in any window in Tcl mode, like for example an error window.
From now on, some rudimentary knowledge of programming is required, in order to understand what the proc is supposed to do. The first step is to read the description in the comments surrounding the proc definition, to learn how it is supposed to work and which arguments the proc takes. If you have the 'errorInfo' available, you can probably spot the exact line of code that throws the error.
Is it an undefined variable? A missing argument to a function call? In any case, the task now consists in figuring out why the variables are not as expected.

Creating debugging windows

One useful way of figuring out where exactly inside a proc an error occurs (and which in any case can help understanding how the proc works) is to modify the code temporarily. Doing this directly in the .tcl file is possible, but not recommended. It is much more convenient to work on a temporary copy. To get one, highlight the name of the proc (in the Tcl file the proc is defined in, or in an error window, or in the Shell), and select Tcl Menu ↣ Tcl Procedures ↣ Debug Proc to create a debugging window. (If there is no proc name highlighted, you will get instead a listpick dialogue to navigate to the desired proc. If the name contains :: (the namespace separator), as in 'text::isInComment', you'll have to choose the namespaces successively in the listpicks, i.e. first ::text, then isInComment.)
Alternatively, you can demand the debugging window directly from the Shell by giving the command
    procs::debug <procName>
where <procName> could be for example 'text::isInComment'.
In any case, the result will be a new editable window containing the definition of the procedure. In this window you can make modifications to the proc. To see how the change affects the functioning, the proc has to be evaluated again, so that Alpha's tcl interpreter knows the proc has been modified. You do this with ⌃⌘L. See the Tcl Menu for many other features.
Now we are ready to experiment with modifications of the proc.

Alertnote debugging

If the given proc throws an error before it reaches the end of its script, we want to know where the error happens. You can now modify the proc to make it give extra feedback when running. One common method for this is with alertnotes. The command
    alertnote "hello"
will simply display an alertnote saying hello, and wait until the user presses OK. The idea is to sprinkle some [alertnote] commands over the code of the proc. For a simple example, if the proc looks like this
    proc testProc {args} {
        set value [lindex $args end]
        incr value
        ...
        return $value
    }
modify it to
    proc testProc {args} {
        set myvar [lindex $args end]
        alertnote "beginning value: $myvar"
        incr myvar
        alertnote "new value: $myvar"
        ...
        return $myvar
    }
For the modification to take effect, you need to reload the proc. You do this with ⌃⌘L. Now when you call the proc, in the Shell or in the status bar, or by performing the malfunctioning operation, you can see from the alertnotes displayed how far you got before you ran into a problem, and what happens to the variables.
Tip: if the error results in a freeze/crash, you should save the file containing the debugging [alertnote] dialogue calls before you evaluate it, so that it is easier to remember which step caused the bug when restarting Alpha.

Recording info in global variables

If it is too intrusive with the alertnotes, you may prefer to write the interesting values to a global variable which can be examined afterwards. You can do this by inserting a line like this in the proc
    set ::XXX1 $pos
This creates a variable XXX1 in the global namespace (that's what the :: do), so that it is still accessible after the proc has terminated or aborted with an error. You can then inspect it in the Shell by doing
    set XXX1
If the proc is actually called more than once during the operation, only the last value of XXX1 will be available afterwards. In this case, it may be appropriate to use instead a list: in the Tcl Shell (⌘Y) do
    set ::LLL [list]
to create an empty list in the global namespace. Now inside the proc you are debugging write
    lappend ::LLL $pos
(if $pos is the variable you are interested in). This will append this value to the list, and once the proc returns, you can inspect the whole list in the Tcl Shell.

Recording info in log files

Another method for recording information for later inspection is to send it to a log file. AlphaTcl defines a proc called alpha::logFile for this purpose. By default, it expects two arguments: the name of the log file (any name chosen by you) and the text you want to write in this file.
When you are debugging a piece of code, you can insert calls to alpha::logFile. This is useful for instance when you want to check some values inside a loop because alertnotes are a nuisance in that case (since they interrupt the process at each iteration). Here is an example:
    for {set i 0} {$i < 100} {incr i} {
        set value [getSomeValue]
        alpha::logFile valuesInLoop "Step $i: $value"
    }
In this example, the log file is named valuesInLoop: it will be located in ~/Library/Logs/AlphaTcl/.

Catching errors

The Tcl command [catch] is very useful for determining if some other procedure that is called by one in question is causing the error. Any [catch] script returns "1" if an error was thrown, and "0" if the script was fine, and will optionally place the return value or error code into a variable. For example, you can include this:
    proc testProc {args} {
        set value [lindex $args end]
        alertnote "beginning value: $value"
        if {[catch {Tcl::MarkFile} result]} {
            alertnote "caught: $result"
        }
        ...
    }
This can help you determine why a complicated procedure is failing.

Forced shell dumps

Another way to debug Tcl routines is to insert statements that print values to another window. For example, one could use the proc [alpha::stderr] to insert the value of the args variable that is created by the procedure in the previous example into an already opened Tcl Shell window.

More Tcl Shell debugging tricks

When you want to get a handle on what a proc is doing, you can use a combination of the source in one window and the shell in another.
  1. First, figure out what values the parameters of the proc would take on in the case you want to investigate, (perhaps from a trace while running things normally).
  2. Now go to the shell and set variables with the same names as the parameters to the values you discovered through the trace.
  3. Now go to the tcl source file and select a subset of the proc's internal code and just load it (with the Tcl Menu ↣ Evaluate menu item or the key combo ⌘L).
After each successive part is run you can pop over to the shell and use it to check out the state of any variable with a simple [set] statement, or, even easier, just Shift-Command-Double-Click on a variable name if you want to inspect the variable's value.

Tracing

Alertnote debugging and the like are really very ad hoc methods, but it can be a quite efficient way of debugging average bugs. For more subtle issues, a much more methodic technique is tracing: simply put, it amounts to an instruction to the Tcl interpreter to dump ALL the information about a function call to a window -- this info is equivalent of having all the possible alertnotes in the code, so that every single instruction is recorded. The result of this, called a stack trace, is usually huge, so it can be a lot of work to dig out useful information from it.
If a bug you have reported cannot be reproduced by the developer looking into it, he will typically ask you send him a stack trace of some specific proc, so as to get all the information in one go, instead of bothering the reporter to write alertnote commands all over the place.

Performing a trace

To create a stack trace of a specific proc, follow these steps:
  1. Click here to display the Debugging Palette.
  2. Select the Perform A Stack Trace command in the palette.
  3. Select the procedure you need to trace. If the name of the procedure includes "::" in the middle, as in ::Tcl::MarkFile, then you need to first select the ::Tcl namespace in a first listpick dialog, and then MarkFile should be included in the list presented in the subsequent dialog.
  4. Perform the action that triggers the problem.
  5. Immediately select Display Trace Results in the Debugging Palette.
A new window should be opened with the trace information.

Tracing via the Tcl Menu

The tracing facilities are also available from the Tcl Menu, in the submenu Tcl Tracing. (The Tcl Menu is activated for example when the Tcl Shell is frontmost). To start the trace using the menu items, perform the following steps:
  1. Select the Tcl Tracing ↣ Trace Tcl Proc menu item.
  2. From the listbox that appears, select the procedure you need to trace.
  3. Go back to a situation in which the bug occurs and repeat the action that triggers the problem.
  4. Go back to the Tcl shell, and select Tcl Tracing ↣ Display Traces from the Tcl Menu.

Tracing tips

Applying AlphaTcl patches

Identifying the cause of a problem is only the first step towards resolving it. If the errant code belonged to a file in the standard distribution, it should be corrected for the next release. In most cases, the fix can also be applied to your working version of Alpha as well.
If the fix was added to the AlphaTcl Subversion repository by a developer, you could update your own AlphaTcl library (inside the application bundle) to the latest development version. This Update AlphaTcl hyperlink will update your AlphaTcl library right now. (Click on the More Info button in the confirmation dialogue to learn more about the AlphaTcl Subversion Repository.)
In some cases, the developer will supply you with some code to place in your prefs.tcl file. Select Alpha ↣ Preferences ↣ Edit Prefs File to open it and insert the code as directed. Then save this file, select the command Tcl Menu ↣ Evaluate to load it into the interpreter, and then test to see if this solved your problem. Your prefs.tcl file will always be sourced automatically whenever you restart Alpha. At this point the patch has been added to your personal distribution and there is nothing more to do.
Otherwise, you might be instructed to modify an existing AlphaTcl file. Assuming that you have been supplied with a patch from a helpful developer, you can easily create an over-ride for the file in question. Your corrected version will reside in an Alpha Support Folder, and will always be used preferentially when the program is launched. Once the installed AlphaTcl file has been opened, you need to select the command Tools ↣ Support Folders ↣ Save In Support Folder to create the over-ride version. Now you can modify this file to apply the patch. Save this file when you are finished, select the Tcl Menu ↣ Evaluate command to load the new code into the interpreter, and then perform the action which caused the original bug to see if the fix actually worked. If so, you can close this file. The next time you launch Alpha, your over-ride file will automatically be used instead of the installed version.
See the Support Folders Help file for more information.
N.B. Any Support Folder over-ride file (or "prefs.tcl" code) will still be used even after you update Alpha to the next release. To confirm that the patch has been added to the standard distribution, temporarily remove the over-ride file (or comment out the code in your preferences file), restart Alpha, and test the operation that caused the original bug.

Credits and Copyright

Author: Joachim Kock, with many snippets from earlier help files.
This document has been placed in the public domain.