V
Veli-Pekka Tätilä
Hi,
I'm just discovering the Perl debugger, and contrary to my initial
expectations as a GUI-guy, I seem to like it after a while. ONe indirect
reason for this is the fact that only one GUI-element can have the focus at
a time. So as a legally blind screen reader user, any fancy docking views or
logs are no good in a graphical debugger. The reason, the keyboard and
screen reader focus can be only on a single control at a time so there's no
good way to merely glance at the screen contents. Speech is also a linear
output medium in which you cannot navigate backwords or skip around in real
time apart from moving the keyboard or screen readder focus. So a
command-line debugger for a visually impaired (or vi) user is pretty much
like the GUI equivalent but provides a more minimal and on-demand type of
interface.
There are some problems with the Perl debugger from an accessibility, speech
user, point of view which I'd like to briefly point out here. Don't get me
wrong, I've seen apps that do much worse but this being Perl, I'd be
interested in trying to customize the debugger or workaround these issues in
some other way. Also, all this is written from a screen reader user's point
of view, most sighted designers of console or GUI apps take their eyes and
mice for granted. On the other hand, graphical debuggers can be quite
keyboard inaccessible, or require the use of heavy full-screen magnification
which is even slower personally.
Though the problems may seem marginal at first, actually working with speech
in any longer debugging session reveals this is not the case. I'm using XP
and a beta of Dolphin Supernova here but you could try the yasr reader in
Linux, without the monitor of course, to see how it is like. Jaws or
WindowEyes will do just as well, of which Windows demos are available.
When it comes to the debug commands, consider the stepping first. Here's a
sample from a recent script of mine:
main:taskman.plx:4): focusToRunning();
DB<1>
In a conventional GUI reader working in a console, which is how most Mac and
WIndows readres are like, the reader will usually read the new console
contents when you hit enter. THis flow is linear and the only thing you can
do to affect it is stopping it. Many readers also provide their own
cursor-like navigation, irrespective of the consoel cursor, but this feature
is still char, word and line oriented and doesn't support regular
expressions in any reader I've seen.
So the above prompt would be read in its entirety with the package, script
and line number pre-pended before the code , which I usually consider the
most important. While the file and package info is great initially, it is
mostly redundant after the first reading, cannot be skipped and slows down
getting the rest of the information. The two major principles here would be
having the most important stuff, the code line, first and minimizing
redundant information by not redisplaying info that the user can ask for or
is supposed to know. Alternatively, you can put the redundant bits last so
they can be skipped by interrupting speech.
The debugger prompt can actually be much worse if you happen to visit
someone else's package:
Win32::GuiTest::FindWindowLike(C:/Perl/site/lib/Win32/GuiTest.pm:434):
434: my $hWndStart = shift || GetDesktopWindow(); # Where to start
DB<1>
This time rattling through the path and the package name takes several
seconds, even at speeds over 300 words per minute. There are some other
aspects that are worth considering. The colons can be interpreted funnily
with some speech synths such as Dolphin Orpheus. If they aren't read out
loud, they add long pauses which cascade, further lengthening the wait.
While colons for a long and commas for a short pause can be used to
structure speech output, the pause is all too long for package names.
Ideally they could be whitespace separated to add no delay but to tell the
reader that it should deal with the parts as separate words. The debugger
prompt DB is slightly redundant, too, I would change it to a greater than
sign.
The line and command numbers aren't as useful as for the sighted, either,
and could be removed. Besides the line number appears twice and both
instances are read. I rarely use the history mechanism directly for the
commands. As to the lines, there's no easy way to see the larger context all
at once. Sure you can print out a window of code with v as in:
433 sub FindWindowLike {
434==> my $hWndStart = shift || GetDesktopWindow(); # Where to start
435: my $windowre = shift; # Regexp
436: my $classre = shift; # Regexp
<snip>
However, the code must be cursored through in textual units like lines or
words. Without the find command or good markers, you would also have to find
the right line by listening to the beginning of the numbers until they match
the one you are looking for. This is true of simple console readers or the
kind of GUI readers in which the console is just another app. Even when you
do find the line, you cannot easily skip the numbers in the beginning of
lines or move the focus between the debugger output and the code listing,
without some heavy marker trickery. Here I can see two underlying design
considerations. Firstly, the screen reader sees only a single very small bit
of the screen at a time which is commonly called the straw analogy (you can
also think of it as a tiny viewport). The second is that unless you know
hotkeys or the app in advance, most keyboard navigation is essentially
sequential and text can only be navigated mechanically in simple units.
Though data structures are mostly printed very nicely, arrays could do with
some improvements. e.g:
DB<1> x a..z
0 'a'
1 'b'
2 'c'
3 'd'
<snip>
Indeces are great if you have to depend on them but say for a stack like
instance, just getting the count and a comma separated list of elements as
in Python or Java would fit the bill better. Again part of the problem are
the screen readers themselves. That is, they cannot skip the initial indeces
and cannot be trained to do so, much as I'd like to.
Well, the other features I thought I'd deal with here are stack traces and
watch expressions. However, they aren't that problematic to begin with and
their primary issues have already been identifiedd so I'll skip them. I
should mention that one extra issue is telling app prompts apart from the
text printed by the debugger. You can do it by context but the sudden prints
often surprise me and again there's no bullet proof way of skipping to the
next debugger prompt in a screen reader.
As the last example here, I'd like to mention the h command for help. While
the debug man page is pretty nice the help screen can look quite confusing
to a GUI reader.
List/search source lines: Control script execution:
l [ln|sub] List source code T Stack trace
- or . List previous/current line s [expr] Single step [in expr]
v [line] View around line n [expr] Next, steps over subs
<snip>
The problem is that the reader doesn't recognize the multi-column layout and
reads it in units of lines from column one till the line break. There are no
commas or other things that would render to pauses in speech so the commands
are badly run together. The only sensible way to decode the output in once
head would be to cursor through it by word, again manually. Also, while this
would be more relevant to OT affairs like ls, notice that most readers will
always read columns from left to right so the order does matter. So the
first one should be the most varying, often needed or uniquely identifying
column. As to the help screen, I wish an optional single-column layout could
be used. Identifying the issue, one shouldn't rely on a screen reader's
ability to break info into columns or read indents, unless some good
semantic info is available (i.e. in a formatted or tagged document).
Now that I've covered the issues, I'd like to ask for help in solving them.
The very first things that came to mind were to use a graphical debugger or
an editor that integrates well to Perl. The graphical debuggers I've read
about are based on X or TK. The latter is horribly keyboard inaccessible and
none of the GUI frameworks in the former seem to be accessible on Windows
using Active Accessibility. Even Gnome 2 is not, as far as I can tell. The
only accessible GUI lib I know of is Win32, with Swing and FireFox based
solutions requiring reader additions or extra components. As for the editor
situation, it is not exactly bright either. WinVi works almost good enough
to be truely accessible but I'm not sure if it can integrate with Perl. I'm
currently using NoteTab Pro taking advantage of its goto line and regexp
features for quick navigation, plus the tabs of course. Most Vi or Emacs
Win32 ports I've seen have serious issues with focus tracking due to custom
cursors, or are totally console based and poorly supported by GUI readers.
GUI readers can only properly read the semantics and structure of Win32 and
Swing applications. An ASCII check box is just punctuation to them and again
none I know can be trained at this level. Heck even app-specific
interpretation for punctuation is a no-can-do.
Lastly even if I would get EmacsSpeak working either in Win32 or Cygwin it
would not, as far as I know, be able to interface with SAPI synths in
Windows. As I've been using this particular speech synth in Finnish and US
English for about seven years now, switching to something else would mean a
huge speed and intelligibility drop at least initially. I don't think too
highly of Festival, see my speech synth page, and neither do I have a
hardware synth.
The second option that occurred to me was to customize the debugger. I've
browsed through the perldebug man page but for the life of me cannot find
any commands that would let me re-order output as outlined above, or even
make the debugger much less verbose. I did, however, find some hooks that
let me execute code prior to or right after the debugging prompts. If it was
somehow possible to get the debugger text in these hooks, i guess I could
filter it with regular expressions. The debugger can output most lines in a
file, too, but I cannot think of easy means of reading it on update and
displaying the info appropriately snipped and re-arranged.
The last option, I think, would be to hack or rewrite the debugger. If it is
possible, I'd much rather filter the debugger output using some other
program, or patch and eval code in memory, as opposed to physically touching
the debugger code or even making a copy of it. I've been reading bits of the
perldebguts man page and while some hooks seem clean and simple, there are
passages that totally beat me. Still I reckon it might not be awfully
difficult to get a very bearbones debugger up and running, I reckon.
However, if the existing debugger can cleanly offer the various chunks in
the output, it would be redundant for me to reverse-engineer how to pull the
pieces apart. I must confess I have merely taken a very brief look at the
debugger source just to see how it is like rather than to truely grasp it,
if you know what I mean, <grin>.
Well it seems to be more than 2 am here local time so I'll stop right here.
Hope this might be an enlightening read and doesn't ccome across as merely
nagging. For more info on usability principles and screen reading, you could
take a look at my accessibility section.
PS: Before I forget, I'm running Active Perl 5.8.7 here.
I'm just discovering the Perl debugger, and contrary to my initial
expectations as a GUI-guy, I seem to like it after a while. ONe indirect
reason for this is the fact that only one GUI-element can have the focus at
a time. So as a legally blind screen reader user, any fancy docking views or
logs are no good in a graphical debugger. The reason, the keyboard and
screen reader focus can be only on a single control at a time so there's no
good way to merely glance at the screen contents. Speech is also a linear
output medium in which you cannot navigate backwords or skip around in real
time apart from moving the keyboard or screen readder focus. So a
command-line debugger for a visually impaired (or vi) user is pretty much
like the GUI equivalent but provides a more minimal and on-demand type of
interface.
There are some problems with the Perl debugger from an accessibility, speech
user, point of view which I'd like to briefly point out here. Don't get me
wrong, I've seen apps that do much worse but this being Perl, I'd be
interested in trying to customize the debugger or workaround these issues in
some other way. Also, all this is written from a screen reader user's point
of view, most sighted designers of console or GUI apps take their eyes and
mice for granted. On the other hand, graphical debuggers can be quite
keyboard inaccessible, or require the use of heavy full-screen magnification
which is even slower personally.
Though the problems may seem marginal at first, actually working with speech
in any longer debugging session reveals this is not the case. I'm using XP
and a beta of Dolphin Supernova here but you could try the yasr reader in
Linux, without the monitor of course, to see how it is like. Jaws or
WindowEyes will do just as well, of which Windows demos are available.
When it comes to the debug commands, consider the stepping first. Here's a
sample from a recent script of mine:
main:taskman.plx:4): focusToRunning();
DB<1>
In a conventional GUI reader working in a console, which is how most Mac and
WIndows readres are like, the reader will usually read the new console
contents when you hit enter. THis flow is linear and the only thing you can
do to affect it is stopping it. Many readers also provide their own
cursor-like navigation, irrespective of the consoel cursor, but this feature
is still char, word and line oriented and doesn't support regular
expressions in any reader I've seen.
So the above prompt would be read in its entirety with the package, script
and line number pre-pended before the code , which I usually consider the
most important. While the file and package info is great initially, it is
mostly redundant after the first reading, cannot be skipped and slows down
getting the rest of the information. The two major principles here would be
having the most important stuff, the code line, first and minimizing
redundant information by not redisplaying info that the user can ask for or
is supposed to know. Alternatively, you can put the redundant bits last so
they can be skipped by interrupting speech.
The debugger prompt can actually be much worse if you happen to visit
someone else's package:
Win32::GuiTest::FindWindowLike(C:/Perl/site/lib/Win32/GuiTest.pm:434):
434: my $hWndStart = shift || GetDesktopWindow(); # Where to start
DB<1>
This time rattling through the path and the package name takes several
seconds, even at speeds over 300 words per minute. There are some other
aspects that are worth considering. The colons can be interpreted funnily
with some speech synths such as Dolphin Orpheus. If they aren't read out
loud, they add long pauses which cascade, further lengthening the wait.
While colons for a long and commas for a short pause can be used to
structure speech output, the pause is all too long for package names.
Ideally they could be whitespace separated to add no delay but to tell the
reader that it should deal with the parts as separate words. The debugger
prompt DB is slightly redundant, too, I would change it to a greater than
sign.
The line and command numbers aren't as useful as for the sighted, either,
and could be removed. Besides the line number appears twice and both
instances are read. I rarely use the history mechanism directly for the
commands. As to the lines, there's no easy way to see the larger context all
at once. Sure you can print out a window of code with v as in:
433 sub FindWindowLike {
434==> my $hWndStart = shift || GetDesktopWindow(); # Where to start
435: my $windowre = shift; # Regexp
436: my $classre = shift; # Regexp
<snip>
However, the code must be cursored through in textual units like lines or
words. Without the find command or good markers, you would also have to find
the right line by listening to the beginning of the numbers until they match
the one you are looking for. This is true of simple console readers or the
kind of GUI readers in which the console is just another app. Even when you
do find the line, you cannot easily skip the numbers in the beginning of
lines or move the focus between the debugger output and the code listing,
without some heavy marker trickery. Here I can see two underlying design
considerations. Firstly, the screen reader sees only a single very small bit
of the screen at a time which is commonly called the straw analogy (you can
also think of it as a tiny viewport). The second is that unless you know
hotkeys or the app in advance, most keyboard navigation is essentially
sequential and text can only be navigated mechanically in simple units.
Though data structures are mostly printed very nicely, arrays could do with
some improvements. e.g:
DB<1> x a..z
0 'a'
1 'b'
2 'c'
3 'd'
<snip>
Indeces are great if you have to depend on them but say for a stack like
instance, just getting the count and a comma separated list of elements as
in Python or Java would fit the bill better. Again part of the problem are
the screen readers themselves. That is, they cannot skip the initial indeces
and cannot be trained to do so, much as I'd like to.
Well, the other features I thought I'd deal with here are stack traces and
watch expressions. However, they aren't that problematic to begin with and
their primary issues have already been identifiedd so I'll skip them. I
should mention that one extra issue is telling app prompts apart from the
text printed by the debugger. You can do it by context but the sudden prints
often surprise me and again there's no bullet proof way of skipping to the
next debugger prompt in a screen reader.
As the last example here, I'd like to mention the h command for help. While
the debug man page is pretty nice the help screen can look quite confusing
to a GUI reader.
List/search source lines: Control script execution:
l [ln|sub] List source code T Stack trace
- or . List previous/current line s [expr] Single step [in expr]
v [line] View around line n [expr] Next, steps over subs
<snip>
The problem is that the reader doesn't recognize the multi-column layout and
reads it in units of lines from column one till the line break. There are no
commas or other things that would render to pauses in speech so the commands
are badly run together. The only sensible way to decode the output in once
head would be to cursor through it by word, again manually. Also, while this
would be more relevant to OT affairs like ls, notice that most readers will
always read columns from left to right so the order does matter. So the
first one should be the most varying, often needed or uniquely identifying
column. As to the help screen, I wish an optional single-column layout could
be used. Identifying the issue, one shouldn't rely on a screen reader's
ability to break info into columns or read indents, unless some good
semantic info is available (i.e. in a formatted or tagged document).
Now that I've covered the issues, I'd like to ask for help in solving them.
The very first things that came to mind were to use a graphical debugger or
an editor that integrates well to Perl. The graphical debuggers I've read
about are based on X or TK. The latter is horribly keyboard inaccessible and
none of the GUI frameworks in the former seem to be accessible on Windows
using Active Accessibility. Even Gnome 2 is not, as far as I can tell. The
only accessible GUI lib I know of is Win32, with Swing and FireFox based
solutions requiring reader additions or extra components. As for the editor
situation, it is not exactly bright either. WinVi works almost good enough
to be truely accessible but I'm not sure if it can integrate with Perl. I'm
currently using NoteTab Pro taking advantage of its goto line and regexp
features for quick navigation, plus the tabs of course. Most Vi or Emacs
Win32 ports I've seen have serious issues with focus tracking due to custom
cursors, or are totally console based and poorly supported by GUI readers.
GUI readers can only properly read the semantics and structure of Win32 and
Swing applications. An ASCII check box is just punctuation to them and again
none I know can be trained at this level. Heck even app-specific
interpretation for punctuation is a no-can-do.
Lastly even if I would get EmacsSpeak working either in Win32 or Cygwin it
would not, as far as I know, be able to interface with SAPI synths in
Windows. As I've been using this particular speech synth in Finnish and US
English for about seven years now, switching to something else would mean a
huge speed and intelligibility drop at least initially. I don't think too
highly of Festival, see my speech synth page, and neither do I have a
hardware synth.
The second option that occurred to me was to customize the debugger. I've
browsed through the perldebug man page but for the life of me cannot find
any commands that would let me re-order output as outlined above, or even
make the debugger much less verbose. I did, however, find some hooks that
let me execute code prior to or right after the debugging prompts. If it was
somehow possible to get the debugger text in these hooks, i guess I could
filter it with regular expressions. The debugger can output most lines in a
file, too, but I cannot think of easy means of reading it on update and
displaying the info appropriately snipped and re-arranged.
The last option, I think, would be to hack or rewrite the debugger. If it is
possible, I'd much rather filter the debugger output using some other
program, or patch and eval code in memory, as opposed to physically touching
the debugger code or even making a copy of it. I've been reading bits of the
perldebguts man page and while some hooks seem clean and simple, there are
passages that totally beat me. Still I reckon it might not be awfully
difficult to get a very bearbones debugger up and running, I reckon.
However, if the existing debugger can cleanly offer the various chunks in
the output, it would be redundant for me to reverse-engineer how to pull the
pieces apart. I must confess I have merely taken a very brief look at the
debugger source just to see how it is like rather than to truely grasp it,
if you know what I mean, <grin>.
Well it seems to be more than 2 am here local time so I'll stop right here.
Hope this might be an enlightening read and doesn't ccome across as merely
nagging. For more info on usability principles and screen reading, you could
take a look at my accessibility section.
PS: Before I forget, I'm running Active Perl 5.8.7 here.