Professional Documents
Culture Documents
by Jaap (Curate) | Log in | Create a new user | The Monastery Gates | Super Search |
| Obfuscation | Reviews | Cool Uses For Perl | Perl News | Q&A | Tutorials |
on Mar 12, 2004 at 12:26 UTC ( #336126=monkdiscuss: print w/ replies, xml ) Need Help??
After reading this thread: Feature Request: Adding Colors to Source Code i got kindof carried away and
made a Javascript rip-off of Cory Johns' excellent Syntax::Highlight::Perl module.
Here it is:
To try, cut&paste into a html file, run it in IE or Mozilla and click anywhere in the perl code you see.
<html> <head> <style> .quotedString { color: #0000FF; } .comment { color: #999999; } .operator { color:
#00CCCC; } .builtinVariable { color: #CCCC00; } .variableSpecifier { color: #FF0000; } .keyword { color:
#9900FF; } .builtinFunction { color: #FF00FF; } .identifier { color: #009900; } .number { color: #9999FF; }
</style> <script> var ie = document.all != null; var moz = !ie && document.getElementById != null &&
document.layers == + null; function emulateHTMLModel() { // copied from
http://www.webfx.nu/dhtml/ieemu/htmlmodel.html // This function is used to generate a html string
for the text pr +operties/methods // It replaces '\n' with "<BR"> as well as fixes consecutive white +
spaces // It also repalaces some special characters function convertTextToHTML(s) { s = s.replace(/\&/g,
"&").replace(/</g, "<").replace(/> +/g, ">").replace(/\n/g, "<BR>").replace(/\t/g, " ");
//tachyon while (/\s\s/.test(s)) s = s.replace(/\s\s/, " "); return s.replace(/\s/g, " "); }
HTMLElement.prototype.__defineSetter__("innerText", function (sTex +t) { this.innerHTML =
convertTextToHTML(sText); return sText; }); var tmpGet;
HTMLElement.prototype.__defineGetter__("innerText", tmpGet = funct +ion () { var r =
this.ownerDocument.createRange(); r.selectNodeContents(this); return r.toString(); }); } if (moz)
emulateHTMLModel(); // Regular Expressions largely copied from Cory Johns (darkness@yossma +n.net)
excellent Syntax::Highlight::Perl module (see http://search.cp +an.org/~johnsca/) var re; var RE = new
Array; // quoted string re = /('|"|`).*?\1/; RE[0] = new RegExp(re); // comment re = /\#.*?[\r\n]+/;
//tachyon RE[1] = new RegExp(re); // operator re = /xor|\.\.\.|and|not|\|\|\=|
cmp|\>\>\=|\<\<\=|\<\=\>|\&\&\=|or|\=\ +>|\!\~|\^\=|\&\=|\|\=|\.\=|x\=|\%\=|\/\=|\*\=|\-\=|\
+\=|\=\~|\*\*|\-\ +-|\.\.|\|\||\&\&|\+\+|\-\>|ne|eq|\!\=|\=\=|ge|le|gt|lt|\>\=|\<\=|\>\>
+|\<\<|\,|\=|\:|\?|\^|\||x|\%|\/|\*|\<|\&|\\|\~|\!|\>|\.|\-|\+ /; RE[2] = new RegExp(re); // builtin
variables re = /\$\#?_|\$(?:\^[LAECDFHIMOPRSTWX]|[0-9&`'+*.\/|,\\";#%=\-~^:?!@\$ +<>()\[\]])|\$\#?
ARGV(?:\s*\[)?|\$\#?INC\s*\[|\$(?:ENV|SIG|INC)\s*\{|\ +@(?:_|ARGV|INC)|\%(?:INC|ENV|SIG)/;
RE[3] = new RegExp(re); // variable class specifiers re = /(?:(?:[\@\%\*]|\$\#?)\$*)/; RE[4] = new
RegExp(re); // keyword re = /(continue|foreach|require|package|scalar|format|unless|local|un +til|
while|elsif|next|last|goto|else|redo|sub|for|use|no|if|my)\b/; RE[5] = new RegExp(re); // builtin
function re = /(getprotobynumber|getprotobyname|getservbyname|gethostbyaddr|ge +thostbyname|
getservbyport|getnetbyaddr|getnetbyname|getsockname|getpe +ername|setpriority|getprotoent|
setprotoent|getpriority|endprotoent|ge +tservent|setservent|endservent|sethostent|socketpair|
getsockopt|getho +stent|endhostent|setsockopt|setnetent|quotemeta|localtime|prototype|g
+etnetent|endnetent|rewinddir|wantarray|getpwuid|closedir|getlogin|rea +dlink|endgrent|getgrgid|
getgrnam|shmwrite|shutdown|readline|endpwent| +setgrent|readpipe|formline|truncate|dbmclose|
syswrite|setpwent|getpwn +am|getgrent|getpwent|ucfirst|sysread|setpgrp|shmread|sysseek|
sysopen| +telldir|defined|opendir|connect|lcfirst|getppid|binmode|syscall|sprin +tf|getpgrp|
readdir|seekdir|waitpid|reverse|unshift|symlink|dbmopen|se +mget|msgrcv|rename|listen|chroot|
msgsnd|shmctl|accept|unpack|exists|f +ileno|shmget|system|unlink|printf|gmtime|msgctl|semctl|
values|rindex| +substr|splice|length|msgget|select|socket|return|caller|delete|alarm| +ioctl|index|
undef|lstat|times|srand|chown|fcntl|close|write|umask|rmd +ir|study|sleep|chomp|untie|print|
utime|mkdir|atan2|split|crypt|flock| +chmod|BEGIN|bless|chdir|semop|shift|reset|link|stat|chop|
grep|fork|du +mp|join|open|tell|pipe|exit|glob|warn|each|bind|sort|pack|eval|push|k +eys|getc|
kill|seek|sqrt|send|wait|rand|tied|read|time|exec|recv|eof|c +hr|int|ord|exp|pos|pop|sin|log|
abs|oct|hex|tie|cos|vec|END|ref|map|di +e|\-C|\-b|\-S|\-u|\-t|\-p|\-l|\-d|\-f|\-g|\-s|\-z|uc|\-k|\-
e|\-O|\-T| +\-B|\-M|do|\-A|\-X|\-W|\-c|\-R|\-o|\-x|lc|\-w|\-r)\b/; RE[6] = new RegExp(re); //
identifier (variable, subroutine, packages) re = /(?:(?:[A-Za-z_]|::)(?:\w|::)*)/; RE[7] = new RegExp(re); //
number re = /0x[\da-fA-F]+|[_.\d]+([eE][-+]?\d+)?/; RE[8] = new RegExp(re); var classes = new
Array("quotedString", "comment", "operator", "built +inVariable", "variableSpecifier", "keyword",
"builtinFunction", "iden +tifier", "number"); /* This is the actual highlighting function. * Takes an html
object as argument * returns nothing * replaces the text inside the html object with colored text using
<s +pan>'s * css is defined separately. See the array classes to find out the cs +s class names. */ function
HighlightCode(object) { codeText = object.innerText; //HTML.replace(/<.*?>/g, ""); object.innerHTML =
''; var left; var match; var right; while (codeText.length > 0) { var mode = -1 ; var index = 999999999; for
(var i = 0; i < RE.length; i++) { if ((codeText.match(RE[i])) && (RegExp.leftContext.length +< index)) { left =
RegExp.leftContext; match = RegExp.lastMatch; right = RegExp.rightContext; index =
RegExp.leftContext.length; mode = i; } } if (mode == -1)
{ object.appendChild(document.createTextNode(codeText)); //. +replace(/\r\n/g, "\r"))); codeText = ''; }
else { // append the plain text to the <code> block
object.appendChild(document.createTextNode(left)); //.repl +ace(/\r\n/g, "\r"))); // create a new
<span> with the current code var span = document.createElement("span");
span.setAttribute("className", classes[mode]); // ie span.setAttribute("class", classes[mode]); //mozilla
span.appendChild(document.createTextNode(match)); object.appendChild(span); codeText = right; } } }
</script> </head> <body> <pre onClick ="HighlightCode(this);"> %EXPORT_TAGS = ( crlf => [qw(CR LF
CRLF $CR $LF $CRLF)], all => [@EXPORT, @EXPORT_OK], ); BEGIN { sub CR () {"\015"} sub LF () {"\012"}
sub CRLF () {"\015\012"} } *CR = \CR(); *LF = \LF(); *CRLF = \CRLF(); sub sockaddr_in { if (@_ == 6 && !
wantarray) { # perl5.001m compat; use this && die my($af, $port, @quad) = @_; warnings::warn "6-ARG
sockaddr_in call is deprecated" if warnings::enabled(); pack_sockaddr_in($port, inet_aton(join('.',
@quad))); } elsif (wantarray) { croak "usage: (port,iaddr) = sockaddr_in(sin_sv)" unless @_ == 1 +;
unpack_sockaddr_in(@_); } else { croak "usage: sin_sv = sockaddr_in(port,iaddr))" unless @_ == 2;
pack_sockaddr_in(@_); } } # comment blaat my $i = 2345; sub sockaddr_un { if (wantarray) { croak
"usage: (filename) = sockaddr_un(sun_sv)" unless @_ == 1; unpack_sockaddr_un(@_); } else { croak
"usage: sun_sv = sockaddr_un(filename)" unless @_ == 1; pack_sockaddr_un(@_); } } </pre> </body>
</html>
[download]
At the moment it's rather colorfull but that's just to show what it can.
If you find bugs or have suggestions for improvements, you might want to pm/mail/call/write me.
Download Code
++Jaap
[reply]
«Rich36»
[reply]
A great contribution, I always knew there must be a good use for JavaScript!
[reply]
++
[reply]
Here's a few additions to make the javascript completely unobtrusive :)(all you add is the <script
src...</script> and that's it)
addEvent(window, "load", FunHighlight); function addEvent(obj, evType, fn){ /* adds an
eventListener for browsers which support it Written by Scott Andrew: nice one, Scott */ if
(obj.addEventListener){ obj.addEventListener(evType, fn, true); return true; } else if (obj.attachEvent)
{ var r = obj.attachEvent("on"+evType, fn); return r; } else { return false; } } function FunHighlight() { //
We don't actually need createElement, but we do // need good DOM support, so this is a good check. if
(!document.createElement) return; pres = document.getElementsByTagName("tt"); for(var prei=0; prei
< pres.length; prei++) { var pre = pres[prei]; if( pre.className == "code") { HighlightCode(pre); } } }
[download]
This of course relies on the fact that <code> tags translate into <pre><tt class="code"><font size="-
1"> .
MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
[reply]
[d/l]
[select]
Hmmm that's pretty nifty. The only problem that remains is how to get the <script .../> tags in.
[reply]
Re: Re: Re: (Client side) Perl Syntax Highlighter
Sure, why not? It'd be perlmonks approved javascript (it already exists). It could be optional (a
setting) but it doesn't have to be (if javascript is on, it works, otherwise, who cares).
MJD says "you can't just make shit up and expect the computer to know what you mean,
retardo!"
I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
[reply]
That's the best use for JS I've seen so far. Great work!
[reply]
Fascinating! These patches fix the moving my issue (actually any key word that follows a comment
will right shift onClick refresh) and convert tabs to 4 spaces for consistency.
45c45 < s = s.replace(/\&/g, "&").replace(/</g, "<").replace( +/>/g, ">").replace(/\n/g,
"<BR>"); --- > s = s.replace(/\&/g, "&").replace(/</g, "<").replace( +/>/g, ">").replace(/\n/g,
"<BR>").replace(/\t/g, ' '); 80c80 < re = /\#.*?(\r|\n)/; --- > re = /\#.*?[\r|\n]+/;
[download]
cheers
tachyon
[reply]
[d/l]
Thank you. Did you mean for the '|' to be between the \r and \n?
[reply]
Nope! I meant [\n\r]+ Great work, very impressive use of JS. As the author you have to patch
the patches :-)
cheers
tachyon
[reply]
[d/l]
Thats incredibly cool stuff. Two bugs though, stuff to the left of a => should be displayed as a string,
and stuff inside a qwxx should also be displayed as strings, currently it's highlighting the sigils of
variables inside one.
[reply]
Regexes and qwx stuff are not implemented yet, if anyone has a good suggestion on how to
match stuff like qw{}, please let me know.
[reply]
That 'looks' nice, but unfortunately doesnt run at all in Opera. This is because Opera is trying to
support the ecma script standard, and RegExp.leftContext (and some other bits), are not part of that
standard. They are also apparently depreciated as of Netscape JS 1.5 (from the JS reference
Shame, really..
C.
[reply]
Yes currently this only works in IE and Mozilla/gecko based browsers. I doubt that Opera will ever
be supported with the lack of features it has.
[reply]
Login:
Password
remember me
What's my password?
Node Status?
node history
Node Type: monkdiscuss [id://336126]
Approved by matija
Front-paged by sschneid
help
Chatterbox?
Other Users?
GrandFather
atcroft
herveus
Eyck
Burak
AndyZaft
im2
Sections?
Meditations
PerlMonks Discussion
Categorized Q&A
Tutorials
Obfuscated Code
Perl Poetry
Perl News
Information?
PerlMonks FAQ
Voting/Experience System
Tutorials
Reviews
Library
Perl FAQs
Find Nodes?
Super Search
Robert adhi
List Nodes By Users
kusuma putra
Robert adhi
kusuma putra
Robert adhi
kusuma putra
Robert adhi
kusuma putra
Robert adhi
kusuma putra
Robert adhi
kusuma putra
Robert adhi
kusuma putra
Robert adhi
kusuma putra
Robert adhi
kusuma putra
Robert adhi
kusuma putra
Robert adhi
kusuma putra
Newest Nodes
Best Nodes
Worst Nodes
Offering Plate
Awards
Craft
Snippets Section
Code Catacombs
Quests
Editor Requests
PerlMonks Merchandise
Planet Perl
Perlsphere
Use Perl
Perl.com
Perl 5 Wiki
Perl Jobs
Perl Mongers
Perl Directory
Perl documentation
CPAN
Random Node
Voting Booth?
What is the largest number of tests you have created for a single project you have worked on?
Test??? There's a test?!? Oh. I didn't study!!!
Tests? I don't need no stinkin' tests-my code is flawless, you insensitive clod!
I've forgotten.
I lost count.
Someone else lost a bet, and paid up by writing the tests for me.
Other