Added "argv", "autorun" and "merge STDOUT+ERR"

A squash of commits:
- 1381ced6fe
  Allow passing in argv array instead of cmdline
- 3d90c22fe7
  Added "autorun" option
- d856a1b817
  Made "merge STDOUT+ERR" option conf'able in editor
gh-pages
Hauke D 7 years ago
parent 4bf870b776
commit 2e57c3c787

@ -118,7 +118,28 @@ iFrameResize({checkOrigin:false}, document.getElementById('perl1'));
<!-- The following example demonstrates (almost) all of the possible <!-- The following example demonstrates (almost) all of the possible
options that can be passed to the editor. options that can be passed to the editor.
The "cmdline" supports only very basic quoting constructs. The "cmdline" option and the corresponding input box in the editor
only support very basic quoting constructs:
- Strings in double quotes may contain whitespace, \\, and/or \",
the latter two will be changed to \ and " respectively;
- strings in single quotes may contain whitespace, \\, and/or \',
the latter two will be changed to \ and ' respectively;
- other strings (without whitespace) will not be modified.
Note: As a consequence of these rules, inside of single or double
quotes, both \\n and \n resolve to \n (for any character "n" that
is not a backslash or single resp. double quote).
Instead of "cmdline", you may specify "argv" as an array ("cmdline"
overrides "argv"). This array should *not* include "perl" as the
first element; this is added automatically.
So that it can be displayed in the input box, the "argv" array
will be encoded into a single string - this means that if you want
full control over the formatting of the command line as it is
displayed to the user in the editor, use "cmdline" instead. The
"Copy JSON" data will include both "cmdline" and "argv" (so you
can choose to delete whichever one you don't need), while "Copy
URL" will include only "cmdline" (for brevity).
You may specify the text of a script via "script", or, alternatively, You may specify the text of a script via "script", or, alternatively,
a "script_url" from which the script is to be fetched - however, be a "script_url" from which the script is to be fetched - however, be
@ -149,14 +170,24 @@ this will not work.
Additional options: Setting "mergeStdOutErr" to a true value causes Additional options: Setting "mergeStdOutErr" to a true value causes
STDOUT and STDERR output to be output together, similar to the way STDOUT and STDERR output to be output together, similar to the way
they would be on the console. they would be on the console. *However,* note that WebPerl
currently doesn't think it's connected to a terminal, which means
that perl defaults to block instead of line buffering STDOUT, so
it may seem like you always see STDERR output before STDOUT. If you
want to truly intermix the two, turn on autoflush ("$|=1;").
If you set the "autorun" option, the editor will attempt to run the
script as soon as the runner is ready. *WARNING:* If you have
multiple editors embedded in the page, *do not* enable "autorun"
for more than one editor, as otherwise you will likely trigger a
race condition, resulting in an error being shown to the user.
--> -->
<iframe id="perl2" sandbox="allow-scripts" class="perleditor" style="height:42em;"></iframe> <iframe id="perl2" sandbox="allow-scripts" class="perleditor" style="height:42em;"></iframe>
<script> <script>
document.getElementById('perl2').src = document.getElementById('perl2').src =
"perleditor.html#" + encodeURIComponent(JSON.stringify( { "perleditor.html#" + encodeURIComponent(JSON.stringify( {
cmdline: "perl devoweler.pl mytext.txt other.txt", argv: ["devoweler.pl","mytext.txt","other.txt"],
script: "use warnings;\nuse strict;\n\nopen my $vfh, '>', 'vowels.txt' or die $!;\n" script: "use warnings;\nuse strict;\n\nopen my $vfh, '>', 'vowels.txt' or die $!;\n"
+"while (<>) {\n\tprint $vfh $1 while s/([aeiou])/_/i;\n\tprint;\n}\nclose $vfh;", +"while (<>) {\n\tprint $vfh $1 while s/([aeiou])/_/i;\n\tprint;\n}\nclose $vfh;",
script_fn: "devoweler.pl", script_fn: "devoweler.pl",
@ -165,6 +196,7 @@ document.getElementById('perl2').src =
{ fn: "other.txt", text: "Hello, World!" }, { fn: "other.txt", text: "Hello, World!" },
], ],
outputs: [ "vowels.txt" ], outputs: [ "vowels.txt" ],
autorun: true,
} )); } ));
iFrameResize({checkOrigin:false}, document.getElementById('perl2')); iFrameResize({checkOrigin:false}, document.getElementById('perl2'));
</script> </script>

@ -39,11 +39,12 @@ If not, see http://perldoc.perl.org/index-licence.html
<script> <script>
"use strict"; "use strict";
var mergeStdOutErr = 0; // Possible To-Do for Later: could make an options hash var mergeStdOutErr = false; // Possible To-Do for Later: could make an options hash
var perlRunner; // the Perl runner iframe found by findPerlRunner() var perlRunner; // the Perl runner iframe found by findPerlRunner()
var buttonBlockers = {}; // for updateButtonState() var buttonBlockers = {}; // for updateButtonState()
var lastExitStatus; // for runnerState() var lastExitStatus; // for runnerState()
var loadedRunnerIframe = false; // for findPerlRunner() var loadedRunnerIframe = false; // for findPerlRunner()
var autoRunPerl = false; // for the message listener
function makeCM (textarea,plain,ro) { function makeCM (textarea,plain,ro) {
return CodeMirror.fromTextArea( textarea[0], { return CodeMirror.fromTextArea( textarea[0], {
@ -131,6 +132,10 @@ window.addEventListener('message', function (event) {
perlRunner = event.source; perlRunner = event.source;
delete buttonBlockers.runnerState; delete buttonBlockers.runnerState;
updateButtonState(); updateButtonState();
if (autoRunPerl) {
autoRunPerl = false;
$('#runperl').click();
}
} }
else if ( data.perlRunnerState=="Ended" ) { else if ( data.perlRunnerState=="Ended" ) {
if ('exitStatus' in data) if ('exitStatus' in data)
@ -165,9 +170,22 @@ function parseCmdLine(str) {
if (typeof match[1] != 'undefined') argv.push(match[1].replace(/\\\\/g,"\\").replace(/\\"/g,"\"")); if (typeof match[1] != 'undefined') argv.push(match[1].replace(/\\\\/g,"\\").replace(/\\"/g,"\""));
else if (typeof match[2] != 'undefined') argv.push(match[2].replace(/\\\\/g,'\\').replace(/\\'/g,'\'')); else if (typeof match[2] != 'undefined') argv.push(match[2].replace(/\\\\/g,'\\').replace(/\\'/g,'\''));
else if (typeof match[3] != 'undefined') argv.push(match[3]); else if (typeof match[3] != 'undefined') argv.push(match[3]);
else throw "Unexpected match "+match;
} }
return argv; return argv;
} }
function encodeCmdLine(arr) {
var out = [];
for (var i=0; i<arr.length; i++) {
/* Note: we only *need* to encode strings if they contain /[\s'"\\]/,
* but since we want to show the users a command line similar to a shell,
* I've added $ */
out.push( arr[i].match(/[\s'"\\\$]/)
? "'"+arr[i].replace(/\\/g, "\\\\").replace(/'/g, "\\'")+"'"
: arr[i] );
}
return out.join(' ');
}
function fetchUrl(url,cm) { // fetch the contents of a URL into a CodeMirror instance function fetchUrl(url,cm) { // fetch the contents of a URL into a CodeMirror instance
cm.setValue("Fetching URL\n"+url+"\nPlease wait..."); cm.setValue("Fetching URL\n"+url+"\nPlease wait...");
@ -286,6 +304,18 @@ function setupInputFile (inp) {
function getFileData () { function getFileData () {
var filedata = {}; var filedata = {};
// command-line args
filedata.cmdline = $('#argv').val();
var argv = parseCmdLine( filedata.cmdline );
if ( argv.length<1 || argv[0]!="perl" ) {
$('#runnererrors>pre').text('Invalid command line, command must be "perl"');
$('#runnererrors').show();
return;
} // else
argv.shift();
$('#runnererrors>pre').text('');
$('#runnererrors').hide();
filedata.argv = argv;
// script // script
var scriptdiv = $('#script'); var scriptdiv = $('#script');
if (scriptdiv.is(':visible')) { if (scriptdiv.is(':visible')) {
@ -362,6 +392,8 @@ $(function () {
}); });
if (hash["cmdline"]) if (hash["cmdline"])
argv_inp.val(hash.cmdline); argv_inp.val(hash.cmdline);
else if (hash["argv"])
argv_inp.val("perl "+encodeCmdLine(hash.argv));
argv_inp.trigger('input'); argv_inp.trigger('input');
// input files // input files
@ -374,15 +406,24 @@ $(function () {
}); });
// stdout/stderr // stdout/stderr
var mergestdoe = $('#mergestdoe');
var stdout_fn = $('#stdout .filename');
if (hash["mergeStdOutErr"]) { if (hash["mergeStdOutErr"]) {
mergeStdOutErr = 1; mergeStdOutErr = true;
$('#stdout .filename').val("STDOUT+STDERR"); stdout_fn.val("STDOUT+STDERR");
mergestdoe.text("Split STDOUT+ERR");
} }
else { else {
mergeStdOutErr = 0; mergeStdOutErr = false;
$('#stdout .filename').val("STDOUT"); stdout_fn.val("STDOUT");
} }
clearStdOutput(); clearStdOutput();
mergestdoe.click(function () {
clearStdOutput();
mergeStdOutErr = !mergeStdOutErr;
stdout_fn.val( mergeStdOutErr ? "STDOUT+STDERR" : "STDOUT" );
mergestdoe.text( mergeStdOutErr ? "Split STDOUT+ERR" : "Merge STDOUT+ERR" );
});
// output files // output files
$('.outputs').remove(); $('.outputs').remove();
@ -393,21 +434,23 @@ $(function () {
setupOutputFile(); setupOutputFile();
}); });
// autorun option
if (hash["autorun"])
autoRunPerl = true;
var autorunstate = $('#autorunstate');
$('#autoruntoggle').click(function () {
// the text keeps state (bit of a hack, I know)
autorunstate.text(
autorunstate.text().match(/without/i)
? "with" : "without" );
});
// "run perl" button // "run perl" button
$('#runperl').click( function () { $('#runperl').click( function () {
clearStdOutput(); clearStdOutput();
// command-line args
var argv = parseCmdLine(argv_inp.val());
if (argv.length<1 || argv[0]!="perl") {
$('#runnererrors>pre').text('Invalid command line, command must be "perl"');
$('#runnererrors').show();
return;
} // else
argv.shift();
$('#runnererrors>pre').text('');
$('#runnererrors').hide();
var rp_data = getFileData(); var rp_data = getFileData();
rp_data.argv = argv; if (!rp_data) return;
delete rp_data.cmdline;
// send message to runner // send message to runner
buttonBlockers.runnerState = 1; buttonBlockers.runnerState = 1;
updateButtonState(); updateButtonState();
@ -419,14 +462,19 @@ $(function () {
// "copy url / json" function // "copy url / json" function
$('#copyurl').click(function () { $('#copyurl').click(function () {
var data = getFileData(); var data = getFileData();
data.cmdline = $('#argv').val(); if (!data) return;
delete data.argv;
if (!autorunstate.text().match(/without/i)) data.autorun=true;
if (mergeStdOutErr) data.mergeStdOutErr=true;
var loc = new URL(window.location); var loc = new URL(window.location);
loc.hash = encodeURIComponent(JSON.stringify(data)); loc.hash = encodeURIComponent(JSON.stringify(data));
copyit(loc); copyit(loc);
}); });
$('#copyjson').click(function () { $('#copyjson').click(function () {
var data = getFileData(); var data = getFileData();
data.cmdline = $('#argv').val(); if (!data) return;
if (!autorunstate.text().match(/without/i)) data.autorun=true;
if (mergeStdOutErr) data.mergeStdOutErr=true;
copyit(JSON.stringify(data, null, "\t")); copyit(JSON.stringify(data, null, "\t"));
}); });
@ -478,8 +526,12 @@ $(function () {
&nbsp; &nbsp;
<span id="addoutput" class="fakelink">Add Output File</span> <span id="addoutput" class="fakelink">Add Output File</span>
&nbsp; &nbsp;
<span id="mergestdoe" class="fakelink">Merge STDOUT+ERR</span>
&nbsp;
<span id="copyurl" class="fakelink">Copy URL</span> <span id="copyurl" class="fakelink">Copy URL</span>
/ <span id="copyjson" class="fakelink">JSON</span> / <span id="copyjson" class="fakelink">JSON</span>
(<span id="autorunstate">with</span>
<span id="autoruntoggle" class="fakelink">autorun</span>)
</span> </span>
</div> </div>
</div> </div>

Loading…
Cancel
Save