Hi,
here is a **suggestion** to format Perl's error messages a bit better:
-some highlighting stuff -hyperlinks for errors given as 'at FILE line X' (works with current script and also for errors coming from other scripts)
PLEASE forgive my Ruby syntax! I'm just learning ;)
BTW Would it be worth to think about a general css for outputting errors as HTML coming from scriptmate?
Cheers,
Hans
On 28. Nov 2006, at 09:38, Hans-Joerg Bibiko wrote:
here is a **suggestion** to format Perl's error messages a bit better: [...]
Thanks -- I will let Alex Ross handle this.
BTW Would it be worth to think about a general css for outputting errors as HTML coming from scriptmate?
We definitely want that! We also have some non-scriptmate based runners. Soryu and I have briefly spoken about it, but run-time errors, exception info, stack traces, etc. is difficult to unify with a few CSS rules.
Hans,
I've just committed an improved PerlMate. PerlMate now causes perl to load exception_handler.pm before executing the user code. exception_handler.pm overrides CORE::GLOBAL::die to format unhandled exceptions and print them to the file descriptor given by the environment varibale TM_ERROR_FD. This let's us manipulate the actual exception objects instead of just their string representations.
The implementation is very basic, as I have no actual Perl programming experience. But it handles `die "Sometext";` just fine. I don't know how it will react to the throwing of except objects.
Perhaps you can look this over, and let me know what you think?
-Alex
On 11/28/06, Hans-Joerg Bibiko bibiko@eva.mpg.de wrote:
Hi,
here is a **suggestion** to format Perl's error messages a bit better:
-some highlighting stuff -hyperlinks for errors given as 'at FILE line X' (works with current script and also for errors coming from other scripts)
PLEASE forgive my Ruby syntax! I'm just learning ;)
BTW Would it be worth to think about a general css for outputting errors as HTML coming from scriptmate?
Cheers,
Hans
For new threads USE THIS: textmate@lists.macromates.com (threading gets destroyed and the universe will collapse if you don't) http://lists.macromates.com/mailman/listinfo/textmate
Hi Alex
On 30 Nov 2006, at 09:15, Alexander Ross wrote:
I've just committed an improved PerlMate. PerlMate now causes perl to load exception_handler.pm before executing the user code. exception_handler.pm overrides CORE::GLOBAL::die to format unhandled exceptions and print them to the file descriptor given by the environment varibale TM_ERROR_FD. This let's us manipulate the actual exception objects instead of just their string representations.
The implementation is very basic, as I have no actual Perl programming experience. But it handles `die "Sometext";` just fine. I don't know how it will react to the throwing of except objects.
I just checked your exception handler. It works fine as long as you use 'die' mot in a 'eval' environment. In Perl you often write your own handler like this:
Example: _______________________ #!/usr/bin/perl -w
$a = 5; $b = -1;
eval { $c = $a / $b; die "Denominator cannot be negative" if ($b < 0); };
print "Run-time error: $@"; _________________________
If I run this the 'die' output never reaches your exception handler because of
if($^S) { CORE::die($@); }...
Perl's $@ refers now to exception_handler.pm line 34 and this is not what I want to see.
Why did you choose this 'if clause' to call CORE::die?
If you leave it out and take only the else clause it works. (?)
On the other hand you have a small typo in line 55 of exception_handler.pm
corrected: print TM_ERROR_FD '<tr><td>in <a href="txmt://open?' . $url . '&line=' . $line . '"> ' . $display_name . "</a> at line $line<td></ tr>\n" ;
because:
print '$line' will print "$line" not the content of the variable $line.
###########
I wrote a small error/warning formatter in my posted perlmate.rb. Would it better to use TM_ERROR_FD instead of
class PerlMate < ScriptMate def filter_stderr(str) ... ?
-Hans
Hans,
The the reason we don't want to handle errors that were throw in eval blocks is the reason you mentioned. Typically, the user handles the error themself. But it is bad that $@ refers to exception_handler.pm line 34 after a die. I think we can fix this somehow.
Also, for things that are errors, they should be written to TM_ERROR_FD. Something written to STDERR that isn't an error should be left alone. Would it be possible to filter STDERR from a perl module that we can load using the -m switch?
- Alex
On Nov 30, 2006, at 2:06 AM, Hans-Joerg Bibiko wrote:
Hi Alex
On 30 Nov 2006, at 09:15, Alexander Ross wrote:
I've just committed an improved PerlMate. PerlMate now causes perl to load exception_handler.pm before executing the user code. exception_handler.pm overrides CORE::GLOBAL::die to format unhandled exceptions and print them to the file descriptor given by the environment varibale TM_ERROR_FD. This let's us manipulate the actual exception objects instead of just their string representations.
The implementation is very basic, as I have no actual Perl programming experience. But it handles `die "Sometext";` just fine. I don't know how it will react to the throwing of except objects.
I just checked your exception handler. It works fine as long as you use 'die' mot in a 'eval' environment. In Perl you often write your own handler like this:
Example: _______________________ #!/usr/bin/perl -w
$a = 5; $b = -1;
eval { $c = $a / $b; die "Denominator cannot be negative" if ($b < 0); };
print "Run-time error: $@"; _________________________
If I run this the 'die' output never reaches your exception handler because of
if($^S) { CORE::die($@); }...
Perl's $@ refers now to exception_handler.pm line 34 and this is not what I want to see.
Why did you choose this 'if clause' to call CORE::die?
If you leave it out and take only the else clause it works. (?)
On the other hand you have a small typo in line 55 of exception_handler.pm
corrected: print TM_ERROR_FD '<tr><td>in <a href="txmt://open?' . $url . '&line=' . $line . '"> ' . $display_name . "</a> at line $line<td></ tr>\n" ;
because:
print '$line' will print "$line" not the content of the variable $line.
###########
I wrote a small error/warning formatter in my posted perlmate.rb. Would it better to use TM_ERROR_FD instead of
class PerlMate < ScriptMate def filter_stderr(str) ... ?
-Hans
For new threads USE THIS: textmate@lists.macromates.com (threading gets destroyed and the universe will collapse if you don't) http://lists.macromates.com/mailman/listinfo/textmate
Alex,
The the reason we don't want to handle errors that were throw in eval blocks is the reason you mentioned. Typically, the user handles the error themself. But it is bad that $@ refers to exception_handler.pm line 34 after a die. I think we can fix this somehow.
Try the attached exception_handler.pm.
I only changed 'sub die'.
perl example:
__________ #!/usr/bin/perl $a = 5; $b = -1; #open (F, '/t/t') || die "Can't find file and program exits!"; eval { $c = $a / $b; die "Denominator cannot be negative" if ($b < 0); };
print "eval exception is printed and program runs further"; _____________
Now if you uncomment open (F, ...
the program will stop with the exception message at line 4
If you disable open(F, ... again
the program will run through the eval block, will print the exception message, AND will run further to the end.
Also, for things that are errors, they should be written to TM_ERROR_FD. Something written to STDERR that isn't an error should be left alone. Would it be possible to filter STDERR from a perl module that we can load using the -m switch?
???Well, if you are using the switch -w or -W or the statement warn() perl will also output warnings at STDERR. So, to distinguish between a real error and warnings is a bit tricky. A very quick and dirty solution for that would be to run the perl script with the switch -c first to check whether the syntax is ok and after that execute this script. If the syntax is ok everything is written to STDERR should be 'only' warnings. Otherwise if the syntax check is not ok this output should go to TM_ERROR_FD. At least this is my first thought. Tomorrow I will see whether I find an other solution.
Best,
Hans
---------------------------------------------------------------- This message was sent using IMP, the Internet Messaging Program.
On Nov 30, 2006, at 6:07 PM, Hans-Joerg Bibiko wrote:
Alex,
The the reason we don't want to handle errors that were throw in eval blocks is the reason you mentioned. Typically, the user handles the error themself. But it is bad that $@ refers to exception_handler.pm line 34 after a die. I think we can fix this somehow.
Try the attached exception_handler.pm.
Hmm, can't Perl exception catching be done the way we do it in Ruby? My Perl is rusty but a close translation would be something like the following (I think):
END { if ($@) { # we are exiting with an exception here... } }
James Edward Gray II
James,
I tried this out but couldn't get it to work. $@ wasn't set when the END block was called.
The good news is if we are in an eval block, exception_handler::die can call Carp::croak[1]. Which "dies of errors (from perspective of caller)".
- Alex
[1] http://perldoc.perl.org/Carp.html
On Nov 30, 2006, at 4:27 PM, James Edward Gray II wrote:
On Nov 30, 2006, at 6:07 PM, Hans-Joerg Bibiko wrote:
Alex,
The the reason we don't want to handle errors that were throw in eval blocks is the reason you mentioned. Typically, the user handles the error themself. But it is bad that $@ refers to exception_handler.pm line 34 after a die. I think we can fix this somehow.
Try the attached exception_handler.pm.
Hmm, can't Perl exception catching be done the way we do it in Ruby? My Perl is rusty but a close translation would be something like the following (I think):
END { if ($@) { # we are exiting with an exception here... } }
James Edward Gray II
For new threads USE THIS: textmate@lists.macromates.com (threading gets destroyed and the universe will collapse if you don't) http://lists.macromates.com/mailman/listinfo/textmate
On 1 Dec 2006, at 07:49, Alexander Ross wrote:
James,
I tried this out but couldn't get it to work. $@ wasn't set when the END block was called.
? Did you tried out my version with 'exit(1) if(!$^S);'? If yes could you please send me an example script which doesn't work.
What do you mean with: "$@ wasn't set when the END block was called"? I'm dealing with $^S.
The good news is if we are in an eval block, exception_handler::die can call Carp::croak[1]. Which "dies of errors (from perspective of caller)".
Yes, to use Carp is a very good idea. You can call in perlmate.rb
def args ["-I#{e_sh(Pathname.new(ENV['TM_BUNDLE_SUPPORT']) + "PerlMate")}", "-Mexception_handler", "-MCarp=verbose"] end
and write within the 'sub die' (excep... .pm)
print TM_ERROR_FD "<p>".Carp::longmess()."</p";
which will print something like
at /Users/.../untitled.pl line 8 eval {...} called at /Users/.../ untitled.pl line 6
-Hans
Hi,
I don't know if this would be a good idea, but no I can distinguish between warnings and errors
With the attached exception_handler.pm now it is possible to redirect system warning, user-defined warnings to what ever. ( Exemplarily I wrote both to TM_ERRO_FD with an header.) This file should be a discussion base. It is not yet perfect.
Then maybe it would be good to specify a TM variable for switching on/ off the perl's module diagnostics (?)
But for errors: How to redirect Perl's stderr to TM_ERROR_FD?
Best,
Hans
Alex
Now I'm able to distinguish separately:
-syntax errors (missing colons etc.) via $SIG{__DIE__} = &syserror; -system errors via $SIG{__DIE__} = &syserror; -system warnings (useless use of etc.) via $SIG{__WARN__} = &syswarn; -user-defined warnings (warn("foo";) via ::warn -die statements if it occurs within eval block message will printed out and the program runs further else message will printed out and the program will be aborted due to exception
In order to hide stderr for perlmate you have to write in perlmate.rb
class PerlMate < ScriptMate def filter_stderr(str) "" end end
I don't use your 'sub id' except for 'sub warn'. Here everything should be clear. Otherwise I trust Perl's error messages more than 'caller($level);'. Esp. for the case if Perl's message contains more than one link like Carp::longmess() it often does.
Comments?
This code is up to now very redundant. It's only for testing!
-Hans
Hi,
there is still a problem with STDERR.
Some packages write messages directly to STDERR. So, to hide stderr in perlmate.rb makes problems.
Example:
#!/usr/bin/perl -w
use Foundation;
$f= NSString->foo("H");
STDERR: **** ERROR **** PerlObjCBridge: sendObjcMessage: Can't get NSMethodSignature for message "foo" Undefined subroutine &__PACKAGE__::die called at /System/Library/Perl/ Extras/5.8.6/darwin-thread-multi-2level/PerlObjCBridge.pm line 230.
But my latest exception_handler.pm only gets the info:
System Error: Undefined subroutine &__PACKAGE__::die called
in PerlObjCBridge.pm at line 230.
*** ERROR **** PerlObjCBridge: ... is written to STDERR
So my question still is how to redirect this avoiding to modify scriptmate.rb???
Any hints ;)
-Hans
ps I already solved the problem to 'htmlize' the error messages.
Hans,
Yes, we don't want to hide STDERR from perlmate. The main idea is to simply format the die message as a link so that you can travel back to the file quickly. The only thing we want to filter from STDERR are unhandled die's which we format ourselves. Everything else should be left alone. If extra formatting is required, we can do it using filter_stderr/filter_stdout.
- Alex
On Dec 1, 2006, at 8:17 AM, Hans-Joerg Bibiko wrote:
Hi,
there is still a problem with STDERR.
Some packages write messages directly to STDERR. So, to hide stderr in perlmate.rb makes problems.
Example:
#!/usr/bin/perl -w
use Foundation;
$f= NSString->foo("H");
STDERR: **** ERROR **** PerlObjCBridge: sendObjcMessage: Can't get NSMethodSignature for message "foo" Undefined subroutine &__PACKAGE__::die called at /System/Library/ Perl/Extras/5.8.6/darwin-thread-multi-2level/PerlObjCBridge.pm line 230.
But my latest exception_handler.pm only gets the info:
System Error: Undefined subroutine &__PACKAGE__::die called
in PerlObjCBridge.pm at line 230.
*** ERROR **** PerlObjCBridge: ... is written to STDERR
So my question still is how to redirect this avoiding to modify scriptmate.rb???
Any hints ;)
-Hans
ps I already solved the problem to 'htmlize' the error messages.
For new threads USE THIS: textmate@lists.macromates.com (threading gets destroyed and the universe will collapse if you don't) http://lists.macromates.com/mailman/listinfo/textmate
Hi Alex,
after 'sleeping' the whole weekend about that here my suggestion:
####################### - if you write BEGIN { *CORE::GLOBAL::die = &__PACKAGE__::die; }
then we run into problems if the 'die' is called from inside a package, because you get the error message unknown subroutine for '__PACKAGE__::die'
That's why I tried: BEGIN { $SIG{__DIE__} = ¨
######################## - we also have to catch a 'warn' statement within an 'eval block'
That's why include the subroutine warn. Otherwise you get an error message for an unknown routine.
######################## - I change the id subroutine to get really the line which emitted the exception. Example:
#!/usr/bin/perl -w
use Foundation;
$f= NSString->foo("H");
will write something like this: **** ERROR **** PerlObjCBridge: sendObjcMessage: Can't get NSMethodSignature for message "foo" **** ERROR **** PerlObjCBridge: error sending message foo at /System/ Library/Perl/Extras/5.8.6/darwin-thread-multi-2level/ PerlObjCBridge.pm line 230.
But here I don't know which line of my script emitted this error. After my changes at the subroutine id now I get: **** ERROR **** PerlObjCBridge: sendObjcMessage: Can't get NSMethodSignature for message "foo" **** ERROR **** PerlObjCBridge: error sending message foo at /System/ Library/Perl/Extras/5.8.6/darwin-thread-multi-2level/ PerlObjCBridge.pm line 230. in untitled.pl at line 5
What I'm done here is to call 'caller' as long as the return is defined; go one level back and ask whether the exception/warn was called from inside of an eval block.
######################## - if 'die' is called from inside of 'eval' the handler writes the message and the script is running further exit($!) if (!$^S);
######################## - to output the real content of $message I wrote a tiny htmlize subroutine
######################## - to avoid redundancy I wrote two tiny subroutines for file name checking and printing
######################## - to avoid an error on a closed file handle if warn and die occur within an eval block I specified BEGIN { $SIG{__DIE__} = ¨ my $error_fd = $ENV{"TM_ERROR_FD"}; open (TM_ERROR_FD, ">&=$error_fd"); }
END { print TM_ERROR_FD "</div>"; close (TM_ERROR_FD); }
########################
I tested it several times and it seems that it works. Comments?
All the best,
Hans
Hi,
as attachment I send the two files
perlmate.rb exception_handler.pm
For both files I only changed the output format for stderr and for all exceptions (hyperlink to source).
Is there a general css syntax for ScriptMate available? I read some class and css tags in RubyMate but I could find them defined. So I defined the style within both files directly (not using css).
Cheers,
Hans
Hans,
I tried the version with `exit(1) if(!$^S);` but it didn't mimic the true behavior of die. Specifically, if die is called inside of eval, the $@ value is not set up appropriately.
- Alex
On Dec 1, 2006, at 12:52 AM, Hans-Joerg Bibiko wrote:
On 1 Dec 2006, at 07:49, Alexander Ross wrote:
James,
I tried this out but couldn't get it to work. $@ wasn't set when the END block was called.
? Did you tried out my version with 'exit(1) if(!$^S);'? If yes could you please send me an example script which doesn't work.
What do you mean with: "$@ wasn't set when the END block was called"? I'm dealing with $^S.
The good news is if we are in an eval block, exception_handler::die can call Carp::croak[1]. Which "dies of errors (from perspective of caller)".
Yes, to use Carp is a very good idea. You can call in perlmate.rb
def args ["-I#{e_sh(Pathname.new(ENV['TM_BUNDLE_SUPPORT']) + "PerlMate")}", "-Mexception_handler", "-MCarp=verbose"] end
and write within the 'sub die' (excep... .pm)
print TM_ERROR_FD "<p>".Carp::longmess()."</p";
which will print something like
at /Users/.../untitled.pl line 8 eval {...} called at /Users/.../ untitled.pl line 6
-Hans
For new threads USE THIS: textmate@lists.macromates.com (threading gets destroyed and the universe will collapse if you don't) http://lists.macromates.com/mailman/listinfo/textmate