Browse Source

Extracted the bacis js routine from the sandbox

pull/203/head
Eugenio Parodi 2 years ago
parent
commit
72f0535ea4
  1. 205
      tests/sandbox/js/ttkproxy.js
  2. 184
      tests/sandbox/sandbox.new.html

205
tests/sandbox/js/ttkproxy.js

@ -0,0 +1,205 @@
/*
MIT License
Copyright (c) 2023 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// Declaration
class TTkProxy {
constructor(term) {
this.term = term
}
pyodideProxy = {
consoleLog: function(m){
console.log("TTk:",m)
},
termPush: function (s) {
this.term.write(s);
},
termSize: function () {
return [this.term.cols, this.term.rows]
},
setTimeout: function(t, i) {
// console.log("TIME (Start)",i,t)
return setTimeout(() => this.ttk_timer(i), t)
},
stopTimeout: function(t) {
// console.log("TIME (Stop)",t)
clearTimeout(t)
},
clearTimeout: function(){
let highestTimeoutId = setTimeout(";");
for (let i = 0 ; i < highestTimeoutId ; i++) {
clearTimeout(i);
}
},
setInterval: function(t, i) {
setTinterval(() => console.log('WIP -> Interval' + i), t)
}
};
async init(){
this.pyodide = await loadPyodide();
this.ttk_timer = (i) => console.log("ttk_timer unimplemented")
this.term.write('Pyodide ('+this.pyodide.version+') - Loaded\n\r')
this.pyodide.registerJsModule("pyodideProxy", this.pyodideProxy);
this.term.write('Pyodide Proxy - Loaded\n\r')
}
async loadLib(lib) {
let zipResponse = await fetch(lib);
let zipBinary = await zipResponse.arrayBuffer();
this.pyodide.unpackArchive(zipBinary, ".tar.gz");
}
async loadFile(fileUri,file){
this.pyodide.FS.writeFile(this.pyodide.FS.currentPath+file, await (await fetch(fileUri)).text());
}
readFile(file){
return this.pyodide.FS.readFile(file, {encoding:'utf8'})
}
currentPath(){
return this.pyodide.FS.currentPath
}
getAllFiles(p){
let ls = this.pyodide.FS.readdir(p)
let ret = []
for(let i=0 ; i<ls.length; i++){
let n = p+"/"+ls[i]
if(ls[i]=='.' || ls[i]=='..' || n==(this.pyodide.FS.currentPath+"/TermTk")) continue;
if( this.pyodide.FS.isDir(this.pyodide.FS.lstat(n).mode)){
ret.push({id:n, text:ls[i], expanded: true, nodes:this.getAllFiles(n)})
}else{
if(n.endsWith('.py')){
ret.push({id:n, text:ls[i]})
}
}
}
return ret
}
preRun(){
this.namespace = this.pyodide.globals.get("dict")();
this.pyodide.runPython(`
import sys
import TermTk as ttk
from TermTk.TTkCore.TTkTerm.input import TTkInput
import pyodideProxy
def ttk_input(val):
kevt,mevt,paste = TTkInput.key_process(val)
if kevt or mevt:
TTkInput.inputEvent.emit(kevt, mevt)
if paste:
TTkInput.pasteEvent.emit(paste)
def ttk_resize(w,h):
ttk.TTkLog.debug(f"Resize: {w=} {h=}")
if ttk.TTkHelper._rootWidget:
ttk.TTkHelper._rootWidget._win_resize_cb(w,h)
ttk.TTkHelper.rePaintAll()
ttk.TTkTerm.cont()
def ttk_timer(tid):
ttk.TTkTimer.triggerTimerId(tid)
def ttk_log(val):
# hex = [f"0x{ord(x):02x}" for x in val]
ttk.TTkLog.debug("---> "+val.replace("\\033","<ESC>") + " - ")
ttk.TTkHelper.paintAll()
def ttk_clean():
if ttk.TTkHelper._rootWidget:
ttk.TTkTimer.pyodideQuit()
ttk.TTkHelper._rootWidget.quit()
ttk.TTkHelper._focusWidget = None
ttk.TTkHelper._rootCanvas = None
ttk.TTkHelper._rootWidget = None
ttk.TTkHelper._updateBuffer = set()
ttk.TTkHelper._updateWidget = set()
ttk.TTkHelper._overlay = []
ttk.TTkHelper._shortcut = []
ttk.TTkLog._messageHandler = [message_handler]
def ttk_init():
ttk.TTkToolTip.toolTipTimer = ttk.TTkTimer()
ttk.TTkToolTip.toolTipTimer.timeout.connect(ttk.TTkToolTip._toolTipShow)
def message_handler(mode, context, message):
msgType = "DEBUG"
if mode == ttk.TTkLog.InfoMsg: msgType = "[INFO]"
elif mode == ttk.TTkLog.WarningMsg: msgType = "[WARNING]"
elif mode == ttk.TTkLog.CriticalMsg: msgType = "[CRITICAL]"
elif mode == ttk.TTkLog.FatalMsg: msgType = "[FATAL]"
elif mode == ttk.TTkLog.ErrorMsg: msgType = "[ERROR]"
pyodideProxy.consoleLog(f"{msgType} {context.file} {message}")
# Register the callback to the message handler
ttk.TTkLog.installMessageHandler(message_handler)
`,{ globals: this.namespace }
);
this.ttk_log = this.namespace.get("ttk_log");
this.ttk_input = this.namespace.get("ttk_input");
this.ttk_timer = this.namespace.get("ttk_timer");
this.ttk_resize = this.namespace.get("ttk_resize");
this.ttk_clean = this.namespace.get("ttk_clean");
this.ttk_init = this.namespace.get("ttk_init");
this.pyodideProxy.ttk_timer = this.ttk_timer
this.pyodideProxy.term = this.term
this.term.onResize( (obj) => {
this.term.reset()
this.ttk_resize(obj.cols, obj.rows)
});
this.term.onData((d, evt) => { this.ttk_input(d) })
this.pyodide.runPython(`
import sys,os
sys.path.append(os.path.join(sys.path[0],'demo'))
__name__ = "__main__"
`,{ globals: this.namespace }
);
}
run(code,filename,fps) {
this.ttk_clean()
console.log("Run App")
let pwd = this.pyodide.PATH.dirname(filename)
this.pyodide.runPython(`
__file__='`+filename+`'
os.chdir('`+pwd+`')
ttk.TTkCfg.maxFps = `+fps,{ globals: this.namespace })
this.ttk_init()
this.pyodide.runPython(code,{ globals: this.namespace });
this.ttk_log(filename + " - LOADED")
}
}

184
tests/sandbox/sandbox.new.html

@ -0,0 +1,184 @@
<!DOCTYPE html>
<html>
<head>
<title>Mr. pyTermTk Sandbox</title>
<link rel="icon" type="image/x-icon" href="www/favicon.ico">
<script src="www/pyodide/pyodide.js"></script>
<link href="www/xterm/xterm.css" rel="stylesheet" />
<script src="www/xterm/xterm.js"></script>
<script src="www/xterm-addon-fit/xterm-addon-fit.js"></script>
<script src="www/xterm-addon-unicode11/xterm-addon-unicode11.js"></script>
<link href="www/fontawesome/fontawesome.min.css" rel="stylesheet">
<link href="www/fontawesome/regular.min.css" rel="stylesheet">
<script type="text/javascript" src="www/w2ui/w2ui-2.0.min.js"></script>
<link rel="stylesheet" type="text/css" href="www/w2ui/w2ui-2.0.min.css" />
<link href="www/codemirror/theme/mbo.css" rel="stylesheet" >
<link href="www/codemirror/codemirror.css" rel="stylesheet" />
<script src="www/codemirror/codemirror.js"></script>
<script src="www/codemirror/modes/python.js"></script>
<script src="js/ttkproxy.js"></script>
<style>
.CodeMirror { height: 100%; }
</style>
</head>
<body>
<div id="layout" style="position: absolute; left: 0px; top: 0px; right: 0px; bottom: 0px"></div>
<script type="text/javascript">
let pstyle = 'border: 1px solid #efefef; padding: 5px;';
let expand = 'position: absolute; left: 0px; top: 0px; right: 0px; bottom: 0px';
new w2layout({
box: '#layout',
name: 'layout_pyTermTk_sandbox',
padding: 4,
panels: [
//{ type: 'top', size: 50, resizable: true, style: pstyle, html: 'top' },
{ type: 'left', size: 200, resizable: true, style: pstyle,
html: '<div id="sidebar" style="position: absolute; left: 0px; top: 0px; right: 0px; bottom: 0px"></div>' },
{ type: 'main', style: pstyle,
toolbar: {
items: [
{ type: 'button', id: 'run_button', text: 'Run', icon: 'far fa-play-circle' },
{ type: 'html', id: 'uri',
html(item) {
let html =
'<div style="padding: 0px 10px; margin-top: -2px;" >'+
' URI: <input id="codeUri" size="50"/>'+
' FPS Cap: <input id="fpsCap" value="30" size="1">'+
'</div>';
return html;
},
},
],
onClick(event) { run(); }
},
html: '<div id="codeArea" style="position: absolute; left: 0px; top: 0px; right: 0px; bottom: 25px"></div>'+
`<div id="codeArea" style="position: absolute; left: 15px; right: 0px; bottom: 0px">
<a href="https://github.com/ceccopierangiolieugenio/pyTermTk">pyTermTk</a> sandbox,
Powered by <a href="https://pyodide.org/">Pyodide</a>
and <a href="https://xtermjs.org">xterm.js</a>
and <a href="https://codemirror.net/5/">CodeMirror5</a>
and <a href="https://w2ui.com/">w2ui</a>
</div>`},
{ type: 'right', size: 1000, resizable: true, style: pstyle,
html: '<div id="terminal" style="position: absolute; left: 0px; top: 0px; right: 0px; bottom: 0px"></div>' }
]
});
new w2field({ el: query('#fpsCap')[0], type: 'int', autoFormat: false })
</script>
<script type="text/javascript">
/* xterm.js demo */
/* https://www.npmjs.com/package/xterm-addon-fit */
const fitAddon = new FitAddon.FitAddon();
/* https://www.npmjs.com/package/xterm-addon-unicode11 */
const unicode11Addon = new Unicode11Addon.Unicode11Addon();
var term = new Terminal({allowProposedApi: true});
term.loadAddon(fitAddon);
term.loadAddon(unicode11Addon);
term.unicode.activeVersion = '11';
term.open(document.getElementById('terminal'));
term.write('xterm.js - Loaded\n\r')
fitAddon.fit()
w2ui.layout_pyTermTk_sandbox.on('resize', (event) => {
setTimeout(()=>{fitAddon.fit()},0.5)
});
/* Code Mirror */
let myCodeMirror = CodeMirror(document.getElementById('codeArea'), {
mode: "python",
lineNumbers: true,
styleActiveLine: true,
matchBrackets: true
});
myCodeMirror.setOption("theme", "mbo");
let getCode = function(){
return myCodeMirror.getValue()
}
let setCode = function(txt){
myCodeMirror.setValue(txt)
}
/* pyodide demo */
async function main(){
ttkProxy = new TTkProxy(term)
await ttkProxy.init()
await ttkProxy.loadLib("bin/TermTk.tgz");
term.write('TermTk - Loaded\n\r')
await ttkProxy.loadLib("bin/demo.tgz");
term.write('Demos - Loaded\n\r')
await ttkProxy.loadLib("bin/tutorial.tgz");
term.write('Tutorials - Loaded\n\r')
/* Sidebar
Fetch all the files in the pyodide.FS
And push them in the sidebar
*/
let files = ttkProxy.getAllFiles(ttkProxy.currentPath())
new w2sidebar({
box: '#sidebar',
name: 'sidebar',
nodes: files })
w2ui.sidebar.on('click', function (event) {
console.log('Last Event: ' + event.type + ' Target: ' + event.target);
loadFile(event.target)
});
var loadFile = function(f){
let content = ttkProxy.readFile(f)
setCode(content)
document.getElementById("codeUri").value = f
}
/* check the "fileUri" field in the address
and load it if defined */
const queryString = window.location.search;
console.log(queryString);
const urlParams = new URLSearchParams(queryString);
fileUri = urlParams.get("fileUri")
filePath = urlParams.get("filePath")
if (fileUri != null){
ttkProxy.loadFile(fileUri, ttkProxy.currentPath()+"/test_file.py");
loadFile(ttkProxy.currentPath()+"/test_file.py")
}else if (filePath != null){
loadFile(ttkProxy.currentPath()+"/"+filePath)
}else{
loadFile(ttkProxy.currentPath()+"/demo/demo.py")
}
//loadFile("/home/pyodide/tutorial/calculator/calculator.005.py")
w2ui.sidebar.select(ttkProxy.currentPath()+"/demo/demo.py")
term.write('Starting Demo...\n\r')
ttkProxy.preRun()
run = function(){
let filename = document.getElementById("codeUri").value
let fps = document.getElementById("fpsCap").value
ttkProxy.run(getCode(), filename,fps)
};
run()
}
main()
</script>
</body>
</html>
Loading…
Cancel
Save