[27464] in Perl-Users-Digest

home help back first fref pref prev next nref lref last post

Perl-Users Digest, Issue: 9081 Volume: 10

daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Thu Mar 23 21:05:42 2006

Date: Thu, 23 Mar 2006 18:05:03 -0800 (PST)
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)

Perl-Users Digest           Thu, 23 Mar 2006     Volume: 10 Number: 9081

Today's topics:
        Debugging with Speech: Issues and Work-arounds? <vtatila@mail.student.oulu.fi>
    Re: LWP and HTTP HEAD <glex_no-spam@qwest-spam-no.invalid>
        More help requested on permutation code. <jack@abc.net>
        Digest Administrivia (Last modified: 6 Apr 01) (Perl-Users-Digest Admin)

----------------------------------------------------------------------

Date: Fri, 24 Mar 2006 02:33:43 +0200
From: "Veli-Pekka Tätilä" <vtatila@mail.student.oulu.fi>
Subject: Debugging with Speech: Issues and Work-arounds?
Message-Id: <dvvepe$4v6$1@news.oulu.fi>

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.

-- 
With kind regards Veli-Pekka Tätilä (vtatila@mail.student.oulu.fi)
Accessibility, game music, synthesizers and programming:
http://www.student.oulu.fi/~vtatila/ 




------------------------------

Date: Thu, 23 Mar 2006 18:06:33 -0600
From: "J. Gleixner" <glex_no-spam@qwest-spam-no.invalid>
Subject: Re: LWP and HTTP HEAD
Message-Id: <EJGUf.48$eT5.1626@news.uswest.net>

Martin Kissner wrote:

> When I compare the results to a telnet session I always get three
> additional fileds (the values are from de.yahoo.com):
> 
> Client-Date: Thu, 23 Mar 2006 21:55:37 GMT
> Client-Peer: 217.12.3.11:80
> Client-Response-Num: 1
> 
> These are produced by LWP an not part of the server's response.
> AFAIK they are not even part of the HTTP spec.
> Why are thes returned as "header fields"?

They're set by LPW::Protocol::http.pm, no idea why.  Try asking the author.


------------------------------

Date: Fri, 24 Mar 2006 01:36:47 GMT
From: Michael Press <jack@abc.net>
Subject: More help requested on permutation code.
Message-Id: <jack-167317.17364723032006@newsclstr02.news.prodigy.com>

Thank you all for the help. Would you guys look at 
the rest of the code? First a disclaimer.
The sort assumes numerical permutation elements. 
This is a limitation I can rectify. 

________________CUT________________
#! /usr/bin/perl 

use warnings;
use strict;

# Multiply permutation cycles, into a permutation map;
# then turn the map into a cycle representation, and print. 
# Knuth ACP 1.3.3 Algorithm B. 

sub permutation_multiply 
{
    my $t;
    my $hold;
    my $prev;

    #  Read in the cycles, and initialize the permutation array. 
    my %permutation_map = map { /\w/ ? ( $_ => $_ ) : () } my @token_list = $_[0] =~ /\w+|[()]/g;

    #  Multiply the cycles generating the permutation as a map. 
    for (my $idx = $#token_list; $idx >= 0; --$idx)
    {
        my $it  = $token_list[$idx];
        if    ($it eq ')' ) { $prev = $it }
        elsif ($it  eq '(' ) { $permutation_map{$hold} = $prev }
        else
        {
            if ( $prev eq ')' ) { $hold = $it }
            $t = $prev, $prev = $permutation_map{$it}, $permutation_map{$it} = $t;
        }
    }

    #  Generate the cycle representation from the permutation in %permutation_map
    my @cycles;
    for my $key (sort { $a <=> $b } keys %permutation_map)
    {
        my @element_list;
        next if $permutation_map{$key} =~ m/-$/ ;
        do
        {
            push @element_list,  $key;
            $t = $permutation_map{$key};
            $permutation_map{$key} .= '-';
            $key = $t;
        } while ($permutation_map{$key} !~ m/-$/ );
        push @cycles, [@element_list];
    }
    for my $key (keys %permutation_map) {$permutation_map{$key} =~ tr/-//d }

    #  Print out the cycles:
    #   Sort the cycles by length.
    #   Put spaces between permutation elements.
    #   Put in cycle delimiter parentheses.
    #   Put spaces between permutation cycles.
    #   Print.
    print join(' ',  map { sprintf "(%s)", join ' ', @{$_}} sort {$#{$a} <=> $#{$b}} @cycles ), "\n";
}

my $alpha = "(99)(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22)";
my $beta =  "(99)(0)(3 6 12 1 2 4 8 16 9 18 13)(15 7 14 5 10 20 17 11 22 21 19)";
my $gamma = "(99 0)(1 22)(2 11)(3 15)(4 17)(5 9)(6 19)(7 13)(8 20)(10 16)(12 21)(14 18)";
my $delta = "(99)(0)(3)(15)(1 18 4 2 6)(5 21 20 10 7)(8 16 13 9 12)(11 19 22 14 17)";
my $x;

print "beta =  alpha^5 gamma alpha^5 gamma alpha^14 gamma alpha^18 \n";
$x = ($alpha x 5 . $gamma) x 2 . $alpha x 14 . $gamma . $alpha x 18;
permutation_multiply $x;
$x = $beta;
permutation_multiply $x;
print "\n";

print "(alpha^13 gamma delta^2)^3 has shape 4^6\n";
$x = (($alpha x 13) . $gamma . ($delta x 2)) x 3;
permutation_multiply $x;
print "\n";

________________END________________

-- 
Michael Press


------------------------------

Date: 6 Apr 2001 21:33:47 GMT (Last modified)
From: Perl-Users-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin) 
Subject: Digest Administrivia (Last modified: 6 Apr 01)
Message-Id: <null>


Administrivia:

#The Perl-Users Digest is a retransmission of the USENET newsgroup
#comp.lang.perl.misc.  For subscription or unsubscription requests, send
#the single line:
#
#	subscribe perl-users
#or:
#	unsubscribe perl-users
#
#to almanac@ruby.oce.orst.edu.  

NOTE: due to the current flood of worm email banging on ruby, the smtp
server on ruby has been shut off until further notice. 

To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.

#To request back copies (available for a week or so), send your request
#to almanac@ruby.oce.orst.edu with the command "send perl-users x.y",
#where x is the volume number and y is the issue number.

#For other requests pertaining to the digest, send mail to
#perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
#sending perl questions to the -request address, I don't have time to
#answer them even if I did know the answer.


------------------------------
End of Perl-Users Digest V10 Issue 9081
***************************************


home help back first fref pref prev next nref lref last post