Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

erroneousBollock's scratchpad

by erroneousBollock (Curate)
on Feb 15, 2006 at 09:24 UTC ( #530323=scratchpad: print w/ replies, xml ) Need Help??

For props

use warnings; use strict; sub menu { print <<'EOM'; What would you like to do? 1) FLASHCARD MODE 2) TEST MODE 3) OPTIONS 4) Exit EOM } sub really { print "Are you sure? "; my $input = <STDIN>; return $input =~ /^y/i; } sub prompt { print "> "; } sub main { print "Welcome to Multiplication Challenge\n\n"; menu(); prompt(); while (my $input = <STDIN>) { print "$1\n" if $input =~ /^([123])/; last if $input =~ /^4/ && really(); menu(); prompt(); } print "done.\n"; } main();

FreeNodeLet hack for QUOTE button in comment nodes.

Notes:
  • contains backtick (`) characters to escape bracket (], [) characters as required by the FreeNodeLet
<script type="text/javascript"> (function(){ /* TODO: 1. In IE7, a strange document selection remains (harmless) after + selection-less document quote. 2. Keybindings ? 3. Configuration ? 4. Nicer looking error dialog. */ // browser identification variables // (some unused for now, but will inevitably be used in future bug +-fixes) // var isOpera = !!window.opera; / +/ is the browser Opera ? var isSafari = (typeof(window.devicePixelRatio) != 'undefined'); / +/ is the browser Safari ? var isIE = /*@cc_on!@*/false; / +/ is the browser Internet Explorer ? var isIE7 = false /*@cc_on || @_jscript_version >= 5.7 @*/; / +/ is the browser IE version 7 (or later) ? // filter a list (for older javascript implmentations) var filter = function (l,f) { var a = `[`]; for (var i = 0; i<l.length; i++) if (f(l`[i`])) a.push(l`[i`]); return a; }; // check a node has the given className var hasClass = function(node, cname) { var cnre = new RegExp('\\b'+cname+'\\b'); return cnre.test(""+node.className) ? 1 : 0; }; // does this node have a parentNode (somewhere up the chain) with +the given class var hasParentWithClass = function (node, cname) { var pnode = node.parentNode; if (!pnode || (typeof(pnode.className)!='string')) return false; return hasClass(pnode, cname) || hasParentWithClass(pnode, cname +); }; // cross-platform event handler attacher var addEvent = !isIE ? function (obj, type, fn) { obj.addEventListener(type, fn, fals +e); } : function (obj, type, fn) { obj`['e'+type+fn`] = fn; obj`[type+fn`] = function(){ obj`['e'+type+fn`](window.event +); }; obj.attachEvent('on'+type,obj`[type+fn`]); }; // translate entity-encoded html back to original form var unescapeHTML = function (html) { return html.replace('&lt;', '<') .replace('&gt;', '>') .replace('&quot;', '"') .replace('&amp;', '&'); }; // save/restore scroll offsets for specified elements... this help +s in IE, but is overridden by the 'focus' on the textarea if that com +es into play. var saveScrolls, restoreScrolls; (function(){ var _elems; saveScrolls = function(list) { _elems = `[`]; for (var i=0; i<l +ist.length; i++) _elems.push(`[list`[i`],+list`[i`].scrollTop`]); }; restoreScrolls = function() { for (var i=0; i<_elems.length; i++ +) _elems`[i`]`[0`].scrollTop = _elems`[i`]`[1`]; }; })(); // get top-level user selection object var getSel = window.getSelection ? function () { return window.getSelection(); } : function () { if (!document.selection) return null; return document.selection.createRange(); }; // convert selection object to (Text/W3C)Range object var sel2Range = isIE ? function (sel) { return sel; } : function (sel) { if (sel.getRangeAt) return sel.getRangeAt(0); var r = document.createRange(); r.setStart(sel.anchorNode,sel.anchorOffset); r.setEnd(sel.focusNode,sel.focusOffset); return r; }; // get HTML of document selection var getDocSelHTML = isIE ? function (s) { return s.htmlText } : function (s) { var t = document.createElement('DIV'); t.appendChild(sel2Range(s).cloneContents()); return t.innerHTML; }; // get inner HTML of selected fragment var getSelHTML = function () { var s = getSel(); // nothing selected ? if (((''+s.htmlText) == '') || !s || s == '') { // get the whole parent post var previews = filter(document.getElementsByTagName('DIV'), fu +nction(n){ return n.className == 'preview'; }); if (!previews || !previews.length) return ''; return previews`[0`].innerHTML.replace(/\s*<hr\s*\/?>\s*<p>\s* +<i>In reply to<\/i>`[\s\S`]+/i,''); } else { // otherwise, get only the (document) selection var inCode = selectionCompletelyInsideCodeBlock(s); return (inCode ? '<c>\n' : '') + getDocSelHTML(s) + (inCode ? '\n</'+'c>' : ''); } }; // test if the selection is completely inside a <code> block. var selectionCompletelyInsideCodeBlock = isIE ? function (sel) { var pnode = sel.parentElement(); return ((pnode != null) && (hasClass(pnode, 'codeblock') || hasParentWithClass(pnode, 'codeblock'))) ? 1 : 0; } : function (sel) { return ((sel.anchorNode != null) && (sel.focusNode != null) && hasParentWithClass(sel.anchorNode, 'codeblock') && hasParentWithClass(sel.focusNode, 'codeblock')) ? 1 +: 0; }; // get the caret (cursor) position in the supplied textarea/text f +ield (for Internet Explorer) // XXX: should we minus selection length from this value ? var getRealIECaretIdx = function (fld){ // formula to decode microsoft selection bookmark string var calcBmrk = function(bk) { return (bk.charCodeAt(0)-1) + (bk.charCodeAt(3)-1) * 65536 + (bk.charCodeAt(2)-1); }; // count number of newlines in str var countNL = function(str) { var m = (/\r\n/g).exec(str); if (!m || !m.length) return 0; return m.length-1; }; // get caret index from the text selection by way of the nasty M +S-selection bookmark string var p = -1; fld.focus(); if (fld && fld.createTextRange) { var r = document.selection.createRange().duplicate(); r.setEndPoint('StartToEnd',r); var s = document.body.createTextRange(); s.moveToElementText(fld); p = calcBmrk(r.getBookmark())-calcBmrk(s.getBookmark()); var rLen = 0; do { var BrLen = rLen; rLen = countNL(fld.value.substring(0,p+rLen+1)); } while(BrLen!=rLen); p += rLen; } return p; }; // IE-specific code to get/set simulated textarea caret index var mkUpdateCaret,getIECaretIdx; (function(){ // variable to monitor caret index in comment textarea var cIdx = 0; // (build) generic textarea event handler mkUpdateCaret = function (fld) { var _fld = fld; return function() { // close over _fld and cIdx cIdx = getRealIECaretIdx(_fld); }; }; // simple getter for simulated caret index getIECaretIdx = function () { return cIdx; }; })(); // get the caret (cursor) position in the supplied text/textarea f +ield var getCaretIdx = isIE ? getIECaretIdx : function (fld) { return (fld.selectionStart || fld.selectionStart == '0') ? fld.selectionStart : 0; }; // set the caret (cursor) position in the supplied textarea (or te +xt) field var setCaretIdx = isIE ? function(fld, idx) { fld.focus(); var sel = document.selection.createRange(); sel.moveStart ('character', -fld.value.length); sel.moveStart ('character', idx); sel.moveEnd ('character', 0); sel.select(); } : function(fld, idx) { if (!(fld.selectionStart || fld.selectionStart == '0')) retu +rn; // why? fld.selectionStart = idx; fld.selectionEnd = idx; fld.focus(); }; // insert text at cursor (in textarea) var insertAtCursor = function(fld, text) { var idx = getCaretIdx(fld); var fln = fld.value.length - idx; var val = fld.value; fld.value = val.substr(0, idx) + text + val.substr(idx, fln); setCaretIdx(fld, idx + text.length); }; // turn supplied HTML into text suitable for pasting into Perlmonk +s comment textarea var quoteHTML = function (html) { var sig = 0; return html.replace( /* build translation regexp */ (new RegExp(`[ '<pre\\s+class=`[\'"`]?code`[\'"`]?>`[\\s\\S`]*?<tt\\sclass= +`[\'"`]?codetext`[\'"`]?>(`[\\s\\S`]+?)<\\/tt>`[\\s\\S`]*?<\/pre>', / +* codeblock */ '<tt\\sclass=`[\'"`]?inlinecode`[\'"`]?>(`[\\s\\S`]*?)<\\/tt +>', / +* inlinecode */ '`[^<>`]+', + / +* plain text */ '<a\\s+href=`[\'"`]?(`[^\'">`]+)`[\'"`]?>(.+?)<\\/a>', + / +* anchor tag */ '<'+'!--`[\\s\\S`]*?-->', + / +* comment tag */ '<`[^<>`]*>' + / +* other tag */ `].join('|'), "ig")), /* pass matches to this function */ function (m, c, c2, href, t) { if (m.match(/^<div\sclass=`["'`]?pmsig`["'`]?>/i)) { sig++; return ""; } if (sig) { if (m.match(/<div\b/i)) sig++; else if (m.match(/<\/div\b/i)) sig--; return ""; } if (m.match(/<{1}!--/)) return ""; if (c2 != null && c2 != "") c = c2; if (c != null && c!= "") return (function(cc){ return cc.match(/<\/c>/i) ? '<code>'+cc+'<'+'/code>' : '<c>'+cc+'<'+'/c>'; })(c.replace(/\n<font color=`['"`]?red`['"`]?>\+<\/font>/i +g, '') .replace(/&gt;/g, '>') .replace(/&lt;/g, '<') .replace(/&amp;/g, '&')); if (href != "" && href != null && t != "" && t != null) retu +rn monkLink(unescapeHTML(href), unescapeHTML(t)) || m; return m; }); }; // reverse-engineer PM markup from the supplied link (and optional + title) var monkLink = function (url, text) { var A,L; if (A = /^(?:http:\/\/(?:www\.)?perlmonks\.(?:org|com|net)\/|\/) +?(?:index\.pl)?\?(node(_id)?=(`[^;&`]+)|.+)$/.exec(url)) { L = (A`[3`] == null) ? `['href://','?'+A`[1`]`] : (/^\d+$/.tes +t(A`[3`])) ? `['id://',A`[3`]`] : `['',unescape(A`[3`])`]; // normal + PM-Link } else if (A = /^http:\/\/perlmonks\.thepen\.com\/(.+)\.html$/.e +xec(url)) { L = (/^\d+$/.test(A`[1`])) ? `['id://',A`[1`]`] : `['',unescap +e(A`[1`])`]; // the pe +n } else if (A = /^http:\/\/search\.cpan\.org\/search\?mode=module +\&query=(.+)$/.exec(url)) { L = `['cpan://',unescape(A`[1`])`]; + // search + cpan link } else if (A = /^http:\/\/search\.cpan\.org\/perldoc\?(.+)$/.exe +c(url)) { L = `['module://',unescape(A`[1`])`]; + // cpan d +ocumentation link } else if (A = /^http:\/\/search\.cpan\.org\/dist\/(`[^\/`]+)\/? +$/.exec(url)) { L = `['dist://',unescape(A`[1`])`]; + // cpan d +istribution link } else if (A = /^http:\/\/cpan\.uwinnipeg\.ca\/search\?query=(. ++)&mode=module$/.exec(url)) { L = `['kobes://',unescape(A`[1`])`]; + // kobes +cpan link } else if (A = /^http:\/\/perldoc\.perl\.org\/(?:functions\/)?(. ++)\.html$/.exec(url)) { L = `['doc://',unescape(A`[1`]).replace(/\//g, '::')`]; + // perldo +c link } else if (/^https?:\/\//.test(url)) { L = `['',url`]; + // other +link } return (!L) ? null : "`["+L`[0`]+L`[1`]+((text == L`[1`]) ? '' : + '|'+text)+"`]"; }; // (build) quote button click event handler var qfunc = function(fs) { var _fs = fs; return function() { // close over _fs try { saveScrolls(document.body, _fs); insertAtCursor(_fs, ('\n<blockquote>\n' + quoteHTML(getSelHT +ML()) + '\n</blockquote>\n').replace(/\n+/g,'\n').replace(/<p>\s*<\/p +>/g,'')); restoreScrolls(); } catch (e) { alert('quote error: '+e); // FIXME } return false; }; }; // IE 6/7 doesn't have per-element selection, so you can't remembe +r the textarea cursor location when selecting text in the // page to be quoted into the textarea. This workaround records th +e caret index (in the textarea) after every useful event. var monitorCaret = function (fld) { var up = mkUpdateCaret(fld); var events = `['keydown', 'keyup', 'paste', 'change', 'mouseup', + 'mousedown', 'dragstart', 'dragend'`]; for (var x=0; x<events.length; x++) addEvent(fld, events`[x`], u +p); }; // on document load, create the 'quote' button and attach its han +dler function. addEvent(window,'load',function(e){ // only do the following for the 'Comment on' page if (document.body.id != 'id-3333') return; // if we've not already been run... if (document.getElementById('fnh_quote')) return; // find the comment textarea var nodes = document.getElementsByName('note_doctext'); if (!nodes || !nodes.length) return; var tArea = nodes`[0`]; // add the 'quote' button to the UI var q = document.createElement('BUTTON'); q.appendChild(document.createTextNode('quote')); tArea.parentNode.appendChild(q); q.onclick = qfunc(tArea); q.id = 'fnh_quote'; // work around IE selection deficiences if (isIE) monitorCaret(tArea); }); })(); </script>


IDEA: DownEmAll-like perl library

- properties
  - select-based
  - make use of HTTP::Range
  - use LWP::Parallel::UA so that encodings, compression work ootb.
  - optional pre-alloc, otherwise join & move

- features
  - throw exception if range not supported, unless conf'd otherwise
  - per-file pause/resume/cancel & in-active timeout
  - split/merge downloaders to add/remove "threads"
  - auto detect site maxconn, reassign range segments to active downloaders
  - smart per-file/site "maximise speed" setting
  - "thread"/file/site/total -> speed, bytes, progress
  - per "thread"/file/site/total throttling
  - per-file md5 check
  - configurable: buffer, max "threads", speed-sample, select-timeout, etc
  - daemon mode (per user?), get-opt support
  - renaming masks / overwriting, dta-like renaming options
  - progress event API
  - batch url's (ranges, functions), all (file-type / link-file-type) in URL
  - understand "main" video/picture in linked HTML ?
Log In?
Username:
Password:

What's my password?
Create A New User
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others browsing the Monastery: (14)
As of 2014-12-18 09:03 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (47 votes), past polls