You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
webperl-for/experiments/democode/perleditor.html

272 lines
8.1 KiB
HTML

<!doctype html>
<html lang="en-us">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>WebPerl Perl Editor</title>
<!-- ----- WebPerl - http://webperl.zero-g.net -----
Copyright (c) 2018 Hauke Daempfling (haukex@zero-g.net)
at the Leibniz Institute of Freshwater Ecology and Inland Fisheries (IGB),
Berlin, Germany, http://www.igb-berlin.de
This program is free software; you can redistribute it and/or modify
it under the same terms as Perl 5 itself: either the GNU General Public
License as published by the Free Software Foundation (either version 1,
or, at your option, any later version), or the "Artistic License" which
comes with Perl 5.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the licenses for details.
You should have received a copy of the licenses along with this program.
If not, see http://perldoc.perl.org/index-licence.html
-->
<!--cacheable--><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.0/normalize.min.css" integrity="sha256-oSrCnRYXvHG31SBifqP2PM1uje7SJUyX0nTwO2RJV54=" crossorigin="anonymous" />
<!--cacheable--><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.39.2/codemirror.min.css" integrity="sha256-I8NyGs4wjbMuBSUE40o55W6k6P7tu/7G28/JGUUYCIs=" crossorigin="anonymous" />
<style>
body {
margin: 0.4em;
}
.text {
font-family: Calibri, Ubuntu, "Droid Sans", Tahoma, Arial, Helvetica, sans-serif;
}
pre,textarea,code,.code,.filename,.CodeMirror {
font-family: Consolas, "Ubuntu Mono", "Droid Sans Mono", "Lucida Console", "Courier New", Courier, monospace;
}
pre {
margin: 0;
}
.CodeMirror {
border: 1px solid grey;
height: auto;
}
.CodeMirror-scroll {
max-height: 10em;
}
</style>
<!--cacheable--><script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.39.2/codemirror.min.js" integrity="sha256-uRIJ6Wfou5cTtmcCvQNA9lvsYl8sUbZXxnfG+P79ssY=" crossorigin="anonymous"></script>
<!--cacheable--><script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.39.2/mode/perl/perl.min.js" integrity="sha256-Uu9QBfi8gU6J/MzQunal8ewmY+i/BbCkBrcAXA5bcCM=" crossorigin="anonymous"></script>
<!--cacheable--><script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script>
"use strict";
function makeCM (textarea,plain,ro) {
return CodeMirror.fromTextArea( textarea[0], {
viewportMargin: Infinity, // so browser's search works, not good for long documents though
lineNumbers:true, indentWithTabs:true,
tabSize:4, indentUnit:4,
mode: plain?"text/plain":"perl",
readOnly: ro?true:false,
} );
}
var mergeStdOutErr = 0;
var cm_std = { 1:null, 2:null }; // 1=stdout, 2=stderr
function stdOutput (which, data) { // 1=stdout, 2=stderr
if (mergeStdOutErr) which = 1;
if (!cm_std[which]) {
var div = $(which==1?'#stdout':'#stderr');
div.show();
cm_std[which] = makeCM($('textarea',div),1,1);
div.data('CodeMirrorInstance', cm_std[which]);
}
if (data && data.length)
cm_std[which].setValue( cm_std[which].getValue() + data );
}
function clearStdOutput () {
if (cm_std["1"]) cm_std["1"].setValue("");
if (cm_std["2"]) cm_std["2"].setValue("");
}
var perlRunner;
window.addEventListener('message', function (event) {
var data = event.data;
//console.log("editor got message", data); //DB
if (data["perlRunnerState"]) {
var disableBtn = true;
if ( data.perlRunnerState=="Ready" ) {
perlRunner = event.source;
disableBtn = false;
}
else if ( data.perlRunnerState=="Ended" ) {
perlRunner = null;
findPerlRunner();
}
$('#runperl').prop("disabled",disableBtn);
}
else if (data["perlOutput"]) {
stdOutput(data.perlOutput.chan, data.perlOutput.data);
}
else console.warn("Perl Editor ignoring unknown message:",data);
});
function findPerlRunner () {
var pollId;
var pollUntil = Date.now() + 10*1000; // milliseconds
pollId = window.setInterval( function () {
if (perlRunner) {
window.clearInterval(pollId);
}
else if ( Date.now()>pollUntil ) {
window.clearInterval(pollId);
console.error("Perl Editor could not contact Perl Runner"); //TODO: report error to user via UI (same for other console.error calls in this script)
}
else
if (window.parent && window.parent.frames["perlrunner"])
window.parent.frames["perlrunner"].postMessage(
{perlRunnerRegisterClient:1}, '*');
}, 100);
}
function parseCmdLine(str) {
var re = /"((?:\\"|\\\\|[^"])*)"|'((?:\\'|\\\\|[^'])*)'|(\S+)/g;
var argv = [];
var match;
while ((match = re.exec(str)) !== null) {
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[3] != 'undefined') argv.push(match[3]);
}
return argv;
}
function parseParams(str) { // Thanks to https://stackoverflow.com/a/26849194
if (!str || !str.length) return {};
return str.split('&').reduce(function (params, param) {
var paramSplit = param.split('=').map(function (value) {
return decodeURIComponent(value.replace(/\+/g, ' '));
});
params[paramSplit[0]] = paramSplit[1];
return params;
}, {});
}
function initialize (hash) {
console.log("hash", hash); //DB
// script
if (hash["script"] || hash["scripturl"]) {
var script = $('#script');
script.show();
var cm = makeCM($('#perlcode'));
script.data('CodeMirrorInstance', cm);
if (hash["script"])
cm.setValue(hash.script);
else if (hash["scripturl"]) {
//TODO: fetch URL
}
else throw "internal error: this shouldn't happen";
if (hash["scriptfn"])
$('.filename',script).text(hash.scriptfn);
}
if (hash["cmdline"]) {
$('#argv').val(hash.cmdline);
}
// input files
$('.inputs').remove();
for (var i=1;;i++) {
if (!( hash["i"+i+"f"] || hash["i"+i+"u"] )) break;
var fn = hash["i"+i+"n"] || "input"+i+".txt";
var div = $('<div/>',{class:"codewithfn inputs"});
div.append( $('<div/>',{class:"filename",text:fn}) );
var ta = $('<textarea/>').appendTo(div);
$('#inputhere').before(div);
var cm = makeCM(ta,1,0);
div.data('CodeMirrorInstance', cm);
if (hash["i"+i+"f"]) {
cm.setValue(hash["i"+i+"f"]);
}
else if (hash["i"+i+"u"]) {
//TODO: fetch URLs
}
}
// stdout/stderr
if (hash["mergestdouterr"]) {
mergeStdOutErr = 1;
$('#stdout>.filename').text("STDOUT+STDERR");
}
else {
mergeStdOutErr = 0;
$('#stdout>.filename').text("STDOUT");
}
clearStdOutput();
// output files
for (var i=1;;i++) {
if (hash["o"+i+"n"]) {
var div = $('<div/>',{class:"codewithfn outputs"});
div.append( $('<div/>',{class:"filename",text:hash["o"+i+"n"]}) );
var ta = $('<textarea/>').appendTo(div);
$('#outputhere').before(div);
var cm = makeCM(ta,1,1);
div.data('CodeMirrorInstance', cm);
}
else break;
}
}
$(function () {
initialize(parseParams(window.location.hash.substr(1)));
var btn_runperl = $('#runperl');
btn_runperl.click( function () {
clearStdOutput();
var argv = parseCmdLine($('#argv').val());
if (argv.length<1 || argv[0]!="perl") {
console.error("invalid command line");
return }
else argv.shift();
var runperl = {
//TODO: input files
argv: argv,
//TODO: script: perl_cm.getValue(),
};
btn_runperl.prop("disabled",true);
perlRunner.postMessage({ runPerl: runperl },'*');
});
btn_runperl.prop("disabled",true);
findPerlRunner();
});
</script>
</head>
<body>
<div id="inputhere" style="display:none;"></div>
<div id="script" class="codewithfn" style="display:none;">
<div class="filename">script.pl</div>
<textarea id="perlcode"></textarea>
</div>
<div>
<button id="runperl"><code>perl</code> &#x25BA;</button>
<input type="text" id="argv" class="code" size="60" value='perl' />
</div>
<div id="stdout" class="codewithfn" style="display:none;">
<div class="filename">STDOUT</div>
<textarea></textarea>
</div>
<div id="stderr" class="codewithfn" style="display:none;">
<div class="filename">STDERR</div>
<textarea></textarea>
</div>
<div id="outputhere" style="display:none;"></div>
</body>
</html>