From 922b0b7ee54ea83be7fd03f0f16e4766b1992b90 Mon Sep 17 00:00:00 2001 From: Jake <jake.read@cba.mit.edu> Date: Fri, 3 May 2019 13:28:09 -0400 Subject: [PATCH] halfway through program loading from the view, and find and fix update-output-on-def-replace bug --- README.md | 21 ++- gogetter.js | 220 +++++++++++++++--------------- hunks/manager.js | 26 ++-- hunks/view.js | 75 ++++++---- programs/linktest.json | 55 -------- programs/ptest.json | 1 + {programs => scratch}/llink.json | 0 {programs => scratch}/mvnv.json | 0 {programs => scratch}/ntlink.json | 0 {programs => scratch}/wstest.json | 0 view/vmsg.js | 5 +- view/vptch.js | 156 +++++++++++++++------ 12 files changed, 321 insertions(+), 238 deletions(-) delete mode 100644 programs/linktest.json create mode 100644 programs/ptest.json rename {programs => scratch}/llink.json (100%) rename {programs => scratch}/mvnv.json (100%) rename {programs => scratch}/ntlink.json (100%) rename {programs => scratch}/wstest.json (100%) diff --git a/README.md b/README.md index f4e98b0..41e07b6 100644 --- a/README.md +++ b/README.md @@ -16,10 +16,29 @@ Native Cuttlefish 'Hunks' are given access to a DOM/div element, making them nic 'aye, but as the legends state: software doth make the hardware singeth' +ok, I want to chart a path through this ... I need to + - load programs, + - load a program that speaks to nautilus + - (and then) load a nautilus program that speaks to ponyo + - then I'm on trax for ponyo dev, that's ok + - I think I can hit all of these steps today ... nt soon, + - it's probably worth some time at that point to organize the net-via-net-via-view issue? this problem as it goes ... + +once I'm back at ponyo, wakeup, I'll minmax some pnp time to make the headboards, and a stepper + + -> view + - could save some headache, place contextmenu in top-level dom, not on plane? makes some sense + - on hunk reload ... sending a new def ... links not retained ? + -> typeset - do name -> names: ['float64', 'number'], for same byte-cast for colloquial type cast ... i.e. uint8 and byte, ? what else ? is it worth it, or just copy pasta ? should also be lists of things that can be hooked up ! - -> with programs, prototype a bootstrap that loads cuttlefish and waits ... then loads a program there ? + what of these hunks that will autoload each time, the bootstraps? + ... np, fam, when we send a request to the manager to add them, + managers should just reply w/ an error - we have paths for that + this is a bug we can iron out later and ignore + + -> with programs, prototype a bootstrap that loads cuttlefish and waits ... then loads a program there ? maybe this is something of a JAMTOC moment ... the view stores and manipulates represenations, we only need a minimum set of messages to load that representation remotely diff --git a/gogetter.js b/gogetter.js index 79c1bd6..0f5613a 100644 --- a/gogetter.js +++ b/gogetter.js @@ -1,119 +1,123 @@ // fs abstraction for sys function GoGetter() { - this.findHunks = (debug) => { - return new Promise((resolve, reject) => { - let htmlTreeDiver = (response) => { - // do we try to pick links out of this plaintext ? like a monkey ? - // I suppose we do - // header, for names - let hfront = response.indexOf('<h1>Index of /hunks') + 14 - let hback = response.indexOf('</h1>') - let header = response.slice(hfront, hback) - if (debug) console.log('DIVE:', header); - let igot = unreturned.indexOf(header) - if (igot != -1) { - //console.log('return success') - unreturned.splice(igot, 1) - } - - // git those paths (these aren't names, are they?) - let paths = response.split('<a href="/hunks/') - // rm first two, and last () - paths = paths.slice(2) // - - paths.forEach((path, index) => { - let end = path.indexOf('"') - //console.log('index', index, 'end', end) - paths[index] = path.slice(0, end) - }) - - paths.forEach((path, index) => { - if (path[path.length - 1] == '/') { - //console.log('folder', path) - let recurse = 'hunks/' + path - //console.log('getting', recurse) - unreturned.push(recurse) - jQuery.get(recurse, htmlTreeDiver) - } else if (path.includes('.js')) { - //console.log('likely hunk', path) - // secrets are rming .js - path = path.slice(0, path.indexOf('.')) - if (path === 'hunks' || path === 'manager' || path === 'template' || path.includes('hidden/')) { - // don't add these special hunks - } else { - returned.push(path) - } - } - }) - - if (unreturned.length === 0) { - // TODO cull hunks and hidden paths ... - // now, writing menu options for each path - // sort alphabetically - returned.sort() - //console.log('GG returns this', JSON.parse(JSON.stringify(returned))) - resolve(returned) - } - } - - let unreturned = new Array() - let returned = new Array() - unreturned.push('hunks/') - jQuery.get('hunks/', htmlTreeDiver) + // I'm keeping this here because GoGetter is localized to the environment, mgr is not + this.interpreterName = 'cuttlefish' + this.interpreterVersion = 'v0.1' + + this.recursivePathSearch = (root, extension, debug) => { + return new Promise((resolve, reject) => { + let htmlTreeDiver = (response) => { + // do we try to pick links out of this plaintext ? like a monkey ? + // I suppose we do + // header, for names + let faceString = '<h1>Index of /' + root + if (debug) console.log('facestring', faceString) + let hfront = response.indexOf(faceString) + 14 + let hback = response.indexOf('</h1>') + let header = response.slice(hfront, hback) + if (debug) console.log('DIVE:', header); + let igot = unreturned.indexOf(header) + if (igot != -1) { + //console.log('return success') + unreturned.splice(igot, 1) + } + + // git those paths (these aren't names, are they?) + let paths = response.split('<a href="/' + root + '/') + // rm first two, and last () + paths = paths.slice(2) // + + paths.forEach((path, index) => { + let end = path.indexOf('"') + if (debug) console.log('index', index, 'end', end) + paths[index] = path.slice(0, end) }) - } - - // https://github.com/tc39/proposal-dynamic-import - this.importSource = (url) => { - // escape characters that are used to delimit the module URL. - // this way the following module works: 'data:text/javascript,console.log("hello")' - url = url.replace(/\\/g, '\\\\').replace(/"/g, '\\"'); - - return new Promise((resolve, reject) => { - const script = document.createElement("script") - const tempGlobal = "__tempModuleLoadingVariable" + Math.random().toString(32).substring(2) - - function cleanup() { - delete window[tempGlobal] - script.remove() - } - window[tempGlobal] = function(module) { - cleanup() - //console.log('ADDHUNK (2) import resolves', url) - resolve(module[Object.keys(module)[0]]) + paths.forEach((path, index) => { + if (path[path.length - 1] == '/') { + //console.log('folder', path) + let recurse = root + '/' + path + //console.log('getting', recurse) + unreturned.push(recurse) + jQuery.get(recurse, htmlTreeDiver) + } else if (path.includes(extension)) { + //console.log('likely hunk', path) + // secrets are rming .js + path = path.slice(0, path.indexOf('.')) + if (path === 'hunks' || path === 'manager' || path === 'template' || path.includes('hidden/')) { + // don't add these special hunks + } else { + returned.push(path) } - - script.type = "module" - script.textContent = `import * as m from "${url}"; window.${tempGlobal}(m);` - - script.onerror = () => { - reject(new Error("Failed to load module script with URL " + url)) - cleanup() - } - - document.documentElement.appendChild(script) - }) - } - - this.getJson = (path) => { - return new Promise((resolve, reject) => { - $.ajax({ - url: path, - type: 'GET', - success: (data) => { - resolve(data) - }, - error: (err) => { - reject(new Error("failure at GG ajax get for json object: program probably doesn't exist")) - } - }) + } }) - } - // I'm keeping this here because GoGetter is localized to the environment, mgr is not - this.interpretername = 'cuttlefish 0.1' + if (unreturned.length === 0) { + // TODO cull hunks and hidden paths ... + // now, writing menu options for each path + // sort alphabetically + returned.sort() + //console.log('GG returns this', JSON.parse(JSON.stringify(returned))) + resolve(returned) + } + } + + let unreturned = new Array() + let returned = new Array() + unreturned.push(root + '/') + jQuery.get(root + '/', htmlTreeDiver) + }) + } + + // https://github.com/tc39/proposal-dynamic-import + this.importSource = (url) => { + // escape characters that are used to delimit the module URL. + // this way the following module works: 'data:text/javascript,console.log("hello")' + url = url.replace(/\\/g, '\\\\').replace(/"/g, '\\"'); + + return new Promise((resolve, reject) => { + const script = document.createElement("script") + const tempGlobal = "__tempModuleLoadingVariable" + Math.random().toString(32).substring(2) + + function cleanup() { + delete window[tempGlobal] + script.remove() + } + + window[tempGlobal] = function(module) { + cleanup() + //console.log('ADDHUNK (2) import resolves', url) + resolve(module[Object.keys(module)[0]]) + } + + script.type = "module" + script.textContent = `import * as m from "${url}"; window.${tempGlobal}(m);` + + script.onerror = () => { + reject(new Error("Failed to load module script with URL " + url)) + cleanup() + } + + document.documentElement.appendChild(script) + }) + } + + this.getJson = (path) => { + return new Promise((resolve, reject) => { + $.ajax({ + url: path, + type: 'GET', + success: (data) => { + resolve(data) + }, + error: (err) => { + reject(new Error("failure at GG ajax get for json object: program probably doesn't exist")) + } + }) + }) + } + } export default GoGetter diff --git a/hunks/manager.js b/hunks/manager.js index cb89f5f..1eb02e4 100644 --- a/hunks/manager.js +++ b/hunks/manager.js @@ -1,4 +1,4 @@ -// heart of the fish ... +// heart of the fish ... import { Hunkify, @@ -19,7 +19,7 @@ import GoGetter from '../gogetter.js' function Manager() { Hunkify(this, 'Manager') // need this tool - let GG = new GoGetter + let gg = new GoGetter let msgsin = new Input('byteArray', 'msgs') let msgsout = new Output('byteArray', 'msgs') @@ -42,7 +42,7 @@ function Manager() { // for now, managers take callback paths to pipe data back through ? let getListOfAvailableComponents = () => { return new Promise((resolve, reject) => { - GG.findHunks().then((list) => { + gg.recursivePathSearch('hunks', '.js').then((list) => { resolve(list) }).catch((err) => { reject(err) @@ -103,8 +103,8 @@ function Manager() { console.log('ok, from path', path) return new Promise((resolve, reject) => { - GG.importSource(path).then((src) => { - if (addHunkVerbose) console.log('GG importing source resolves', src) + gg.importSource(path).then((src) => { + if (addHunkVerbose) console.log('gg importing source resolves', src) try { let hunk = sourceToHunk(src, hunkName, id, state) hunks.push(hunk) @@ -168,7 +168,7 @@ function Manager() { } // if the hunk has a dom, and we have a view, add it ... - if (hunk.dom !== null || hunk.dom !== undefined) { + if (hunk.dom !== null && hunk.dom !== undefined) { // this is only allowed in the tlview, and we manage that... let tlv = hunks.find((cnd) => { return cnd.id === 'TLView' @@ -377,7 +377,8 @@ function Manager() { case MK.REQDESCRIBESELF: resp.push(MK.BRIEF) MSGS.writeTo(resp, this.id, 'string') - MSGS.writeTo(resp, GG.interpretername, 'string') + MSGS.writeTo(resp, gg.interpreterName, 'string') + MSGS.writeTo(resp, gg.interpreterVersion, 'string') MSGS.writeTo(resp, hunks.length, 'uint32') MSGS.writeTo(resp, writeLinkList().length, 'uint32') writeMessage(resp) @@ -418,14 +419,21 @@ function Manager() { case MK.REQADDHUNK: // pull the rest out, // unknown-len types return with return.item and return.increment - let strname = MSGS.readFrom(msg, 1, 'string').item + let reqaddinc = 1 + let strname = MSGS.readFrom(msg, reqaddinc, 'string') + reqaddinc += strname.increment + strname = strname.item + let strid = undefined + if(reqaddinc < msg.length) { + strid = MSGS.readFrom(msg, reqaddinc, 'string').item + } // then do, // a meta comment is that this add promise doesn't fail for // things like path-loading errors, that would be inside of gogetter.js // i.e. pulling a hunk loads it into that import script hack, that just // gets evaluated into the dom ... console.log('manager to add', strname) - this.addHunk(strname).then((hunk) => { + this.addHunk(strname, strid).then((hunk) => { console.log('successfully added hunk', hunk) // serialize resp.push(MK.HUNKALIVE) diff --git a/hunks/view.js b/hunks/view.js index 7789920..c64a1d8 100644 --- a/hunks/view.js +++ b/hunks/view.js @@ -235,12 +235,10 @@ function View() { }) this.addContextOption('load a patch', (evt) => { - $(evt.target).append(' loading a list...') - patchset.findPatches() + patchset.findPatches(evt) }) this.addContextOption('save this patch', (evt) => { - $(evt.target).append(' > input for the name > ') patchset.saveCurrent(evt, true) }) // writeMessage([MK.REQLISTAVAIL]) @@ -617,10 +615,12 @@ function View() { let mt = {} let match = $(this.plane).find('#' + def.id).get(0) let menu = $(this.plane).children('.contextmenu').get(0) - if (match !== undefined) { + if (match) { // we have one already, we are likely updating it + // we need to be more careful about this + msgbox.write(`received new definition for the hunk with id "${def.id}", replacing that...`) + // need to carefully walk outputs to replace, mt = dt.readTransform(match) - $(match).remove() } else if (menu !== undefined) { mt = dt.readTransform(menu) } else if (def.id === "NROL39_0") { // TEMPORARY until better management with force layout @@ -646,27 +646,45 @@ function View() { // write the def dom let de = dt.writeDefDom(def, true) - // if it's in the ref-to-add - let native = cuttlefishHunkRef.find((hnk) => { - return hnk.id === def.id - }) + // later, we can walk for similar outputs, to maintain those links + if (match) { + // poll new outputs, replace with old outputs (these contain link information, should retain) + let newOtps = $(de).children('.outputs').children('.output') + for(let notp of newOtps){ + let equiv = $(match).children('.outputs').children('#' + notp.id).get(0) + if(equiv){ + msgbox.write(`maintaining output for ${equiv.id}`) + $(de).children('.outputs').children('#' + notp.id).replaceWith(equiv) + } else { + msgbox.write(`no equivalent output for ${equiv.id}, adding that`) + } + } + $(match).remove() + } else { + // shouldn't have to do this for refreshing descriptions... + // if it's in the ref-to-add + let native = cuttlefishHunkRef.find((hnk) => { + return hnk.id === def.id + }) - if (native !== undefined) { - console.log("trying to add native hunk's dom") - try { - $(de).append($(native.dom).addClass('cuttlefishhunkdom')) - if ($(native.dom).is('.view')) { - de.style.height = '800px' - de.style.width = '1200px' - // leader on starting to reize these ... - $(de).append($('<div>').addClass('rsHandle').on('mousedown', (evt) => { - console.log('rshandle down') - })) + if (native !== undefined && native !== null) { + console.log("trying to add native hunk's dom: native:", native) + try { + $(de).append($(native.dom).addClass('cuttlefishhunkdom')) + if ($(native.dom).is('.view')) { + de.style.height = '800px' + de.style.width = '1200px' + // leader on starting to reize these ... + $(de).append($('<div>').addClass('rsHandle').on('mousedown', (evt) => { + console.log('rshandle down') + })) + } + } catch (err) { + msgbox.write(`native hunk attach fails ${err}`) } - } catch (err) { - msgbox.write(`native hunk attach fails ${err}`) } } + // dt.writeTransform(de, mt) // rm menu if it's around @@ -755,9 +773,10 @@ function View() { writeMessage([MK.HELLO]) } - this.requestAddHunk = (name) => { + this.requestAddHunk = (name, id) => { let msg = [MK.REQADDHUNK] MSGS.writeTo(msg, name, 'string') + if (id) MSGS.writeTo(msg, id, 'string') writeMessage(msg) } @@ -900,13 +919,18 @@ function View() { let intrprtrnm = MSGS.readFrom(msg, bi, 'string') bi += intrprtrnm.increment brief.interpreterName = intrprtrnm.item + let intrprtrv = MSGS.readFrom(msg, bi, 'string') + bi += intrprtrv.increment + brief.interpreterVersion = intrprtrv.item brief.numHunks = MSGS.readFrom(msg, bi, 'uint32') brief.numLinks = MSGS.readFrom(msg, bi + 5, 'uint32') + this.interpreterName = brief.interpreterName + this.interpreterVersion = brief.interpreterVersion msgbox.briefState.setFromBrief(brief) break case MK.LISTOFAVAIL: let stringlist = MSGS.readListFrom(msg, 1, 'string') - this.changeContextTitle('list of available:') + this.changeContextTitle('available hunks:') for (let item of stringlist) { this.addContextOption(item, (evt) => { let msg = [MK.REQADDHUNK] @@ -920,6 +944,8 @@ function View() { console.log('hunk alive, going to deserialize') let def = defBySerial(msg, 1) putDef(def) + patchset.onHunkLoaded(def) + // bfstate should mixin to vptches msgbox.briefState.decrementHunks() break case MK.HUNKSTATECHANGE: @@ -939,6 +965,7 @@ function View() { case MK.LINKALIVE: let alal = MSGS.readListFrom(msg, 1, 'string') putLink(alal[0], alal[1], alal[2], alal[3]) + patchset.onLinkLoaded() msgbox.briefState.decrementLinks() break case MK.LINKREMOVED: diff --git a/programs/linktest.json b/programs/linktest.json deleted file mode 100644 index 383d995..0000000 --- a/programs/linktest.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "programname": "linktest", - "hunks": [ - { - "name": "input/string", - "id": "String_X" - }, - { - "name": "interface/logger", - "id": "Logger_Uno" - }, - { - "name": "interface/logger", - "id": "Logger_Duo" - }, - { - "name": "link", - "id": "link_one" - }, - { - "name": "comm/websocketclient", - "id": "wsclient" - }], - "links": [ - { - "outhunk": "String_X", - "outname": "string", - "inhunk": "Logger_Uno", - "inname": "tolog" - }, - { - "outhunk": "link_one", - "outname": "bytes", - "inhunk": "wsclient", - "inname": "bytes" - }, - { - "outhunk": "wsclient", - "outname": "bytes", - "inhunk": "link_one", - "inname": "bytes" - }, - { - "outhunk": "String_X", - "outname": "string", - "inhunk": "link_one", - "inname": "zero" - }, - { - "outhunk": "link_one", - "outname": "one", - "inhunk": "Logger_Duo", - "inname": "tolog" - }] -} \ No newline at end of file diff --git a/programs/ptest.json b/programs/ptest.json new file mode 100644 index 0000000..bd114b6 --- /dev/null +++ b/programs/ptest.json @@ -0,0 +1 @@ +{"interpreterName":"cuttlefish","interpreterVersion":"v0.1","hunks":[{"id":"NROL39_0","name":"manager"},{"id":"TLView","name":"view"},{"id":"hnk_3","name":"view"},{"id":"hnk_2","name":"link","state":[{"name":"inputList","type":"string","value":"mgrMsgs (byteArray), num (number)"},{"name":"outputList","type":"string","value":"mgrMsgs (byteArray)"}]}],"links":[{"outhunk":"NROL39_0","outname":"msgs","inhunk":"TLView","inname":"msgs"},{"outhunk":"TLView","outname":"msgs","inhunk":"NROL39_0","inname":"msgs"},{"outhunk":"hnk_3","outname":"msgs","inhunk":"hnk_2","inname":"data"},{"outhunk":"hnk_2","outname":"data","inhunk":"hnk_3","inname":"msgs"}]} \ No newline at end of file diff --git a/programs/llink.json b/scratch/llink.json similarity index 100% rename from programs/llink.json rename to scratch/llink.json diff --git a/programs/mvnv.json b/scratch/mvnv.json similarity index 100% rename from programs/mvnv.json rename to scratch/mvnv.json diff --git a/programs/ntlink.json b/scratch/ntlink.json similarity index 100% rename from programs/ntlink.json rename to scratch/ntlink.json diff --git a/programs/wstest.json b/scratch/wstest.json similarity index 100% rename from programs/wstest.json rename to scratch/wstest.json diff --git a/view/vmsg.js b/view/vmsg.js index 48accca..418cfce 100644 --- a/view/vmsg.js +++ b/view/vmsg.js @@ -13,6 +13,7 @@ function MessageBox(View) { numLinksLeft: 0, setFromBrief: function(brief) { this.recipId = brief.interpreterId + this.recipVer = brief.interpreterVersion this.recipName = brief.interpreterName this.numHunksLeft = brief.numHunks this.numLinksLeft = brief.numLinks @@ -37,9 +38,9 @@ function MessageBox(View) { postToDom: function() { let str if (this.numHunksLeft > 0 || this.numLinksLeft > 0) { - str = `manager id: ${this.recipId} <br>interpreter: ${this.recipName} <br> awaiting ${this.numHunksLeft} hunks and ${this.numLinksLeft} links` + str = `manager id: ${this.recipId} <br>interpreter: ${this.recipName} ${this.recipVer} <br> awaiting ${this.numHunksLeft} hunks and ${this.numLinksLeft} links` } else { - str = `manager id: ${this.recipId} <br>interpreter: ${this.recipName} <br> all loaded OK` + str = `manager id: ${this.recipId} <br>interpreter: ${this.recipName} ${this.recipVer} <br> all loaded OK` } $(themsgbox).find('#titleBox').html(str) } diff --git a/view/vptch.js b/view/vptch.js index a711a9a..5c1b8a5 100644 --- a/view/vptch.js +++ b/view/vptch.js @@ -1,31 +1,116 @@ // patches are programs that are *incomplete without you* -function PatchSet(View, MsgBox){ +import GoGetter from '../../gogetter.js' + +function PatchSet(View, MsgBox) { let view = View let msgbox = MsgBox + let gg = new GoGetter() this.init = () => { msgbox.write('hello from patchset') } - // the issue you're worrying about is: - /* - what of these hunks that will autoload each time, the bootstraps? - ... np, fam, when we send a request to the manager to add them, - managers should just reply w/ an error - we have paths for that - this is a bug we can iron out later and ignore - */ + // load from server should be assumed, just rip that *baybie* + this.findPatches = (evt) => { + // and then, + $(evt.target).append(' > loading a list ...') + gg.recursivePathSearch('programs', '.json', true).then((list) => { + console.log('returns list', list) + // title, and options + view.changeContextTitle('available patches:') + // HERE NOW WRITE EM UUUUP VERY SIMPLE + for (let item of list) { + view.addContextOption(item, (evt) => { + try { + this.loadPatch(item) + } catch (err) { + msgbox.write('caught an error while starting program load') + } + $(view.plane).find('.contextmenu').remove() + }) + } + }) + } + + let unloadedHunks = [] + let unloadedStates = [] + let unloadedLinks = [] + + let reqNextHunk = () => { + // from 0th position in array + view.requestAddHunk(unloadedHunks[0].name, unloadedHunks[0].id) + } + + // callbacks, + this.onHunkLoaded = (def) => { + // not interested, + if(unloadedHunks.length < 1) return true + // find in list, rm + let place = unloadedHunks.findIndex((cand) => { + return (cand.id === def.id && cand.name === def.name) + }) + if(place !== -1) { + if(place !== 0) console.error("watch out of order loading for programs... shouldn't be like that but it do") + unloadedHunks.shift() + msgbox.write(`patchset placed ${def.id}, ${unloadedHunks.length} hunks remaining`) + if(unloadedHunks.length < 1){ + msgbox.write(`patchset loaded all hunks, now updating state`) + } else { + reqNextHunk() + } + } else { + console.error(`hunk not found in unloaded hunks, ${def.id}`) + } + // if place, else bad news ... + // HERE + // ... + // and when complete, load first link + } + + // try for a one-at-a-time cycle, + this.loadHunkList = (list) => { + + } + + this.onLinkLoaded = (outId, outName, inId, inName) => { + // find in list, rm, + } + + this.loadPatch = (name) => { + msgbox.write(`ok, loading a patch from: ${name}`) + gg.getJson('/programs/' + name + '.json').then((patch) => { + console.log('the patch', patch) + if (patch.interpreterName !== view.interpreterName) { + msgbox.write(`WARN: loading patch built in a different interpreter... some hunks may not exist: patch for: "${patch.interpreterName}", but view is connected to "${view.interpreterName}"`) + } + if (patch.interpreterVersion !== view.interpreterVersion) { + msgbox.write(`WARN: loading patch built in a different version of the interpreter... patch from "${patch.interpreterVersion}" and manager is running "${view.interpreterVersion}"`) + } + unloadedHunks = patch.hunks + unloadedLinks = patch.links + // kick it off by sending this message, + reqNextHunk() + // continue loading ... write a bootload of messages, in queu, waiting for each response? + }).catch((err) => { + console.error(err) + msgbox.write(`could not load program from: ${name}, caught an error from json load, see the console`) + }) + } + this.saveCurrent = (evt, debug) => { - if(debug) console.log('saving ...') + if (debug) console.log('saving ...') // riperoni ok let patch = { + interpreterName: gg.interpreterName, + interpreterVersion: gg.interpreterVersion, hunks: [], links: [] } // js, u wyld - for(let hnk of $(view.plane).children('.block')){ + for (let hnk of $(view.plane).children('.block')) { // dom is truth - if(debug) console.log('hnk', hnk) + if (debug) console.log('hnk', hnk) let name = $(hnk).children('.blockid').find('span').text() name = name.substring(1, name.length - 1) let phnk = { @@ -33,20 +118,20 @@ function PatchSet(View, MsgBox){ name: name } let state = [] - for(let st of $(hnk).children('.state').children('.stateItem')){ + for (let st of $(hnk).children('.state').children('.stateItem')) { // text is faithful, let text = $(st).find('p').text() let name = text.substring(0, text.indexOf(' ')) let type = text.substring(text.indexOf('(') + 1, text.indexOf(')')) - if(debug) console.log('state: name', `"${name}"`, 'type', `"${type}"`) + if (debug) console.log('state: name', `"${name}"`, 'type', `"${type}"`) // the value... (typing on program saves? not if we JSON ...) let value - if(type === 'boolean'){ + if (type === 'boolean') { let vstring = $(st).find('span').text() vstring = vstring.substring(vstring.indexOf('(') + 1, vstring.indexOf(')')) - if(vstring === 'true'){ + if (vstring === 'true') { value = true - } else if (vstring === 'false'){ + } else if (vstring === 'false') { value = false } else { console.error('error saving boolean value, setting to false') @@ -57,23 +142,23 @@ function PatchSet(View, MsgBox){ } else { // must be some kind of number, value = parseFloat($(st).find('input').val()) - }// end if-on-types sequence + } // end if-on-types sequence state.push({ name: name, type: type, value: value }) } // end roll over states, - if(state.length > 0){ + if (state.length > 0) { phnk.state = state } patch.hunks.push(phnk) // now roll over links in the hunk, to write outputs - for(let otp of $(hnk).children('.outputs').children('.output')){ - if(debug) console.log('and output', otp) + for (let otp of $(hnk).children('.outputs').children('.output')) { + if (debug) console.log('and output', otp) let outId = otp.id.substring(0, otp.id.indexOf('_output_')) let outName = otp.id.substring(otp.id.indexOf('_output_') + 8) - for(let conn of otp.connectedTo){ + for (let conn of otp.connectedTo) { let inId = conn.substring(1, conn.indexOf('_input_')) let inName = conn.substring(conn.indexOf('_input_') + 7) patch.links.push({ @@ -86,23 +171,25 @@ function PatchSet(View, MsgBox){ } // end loop over outputs, for links ... } // end loop over hunks // we have this now, - if(debug) console.log('a patch', patch) + if (debug) console.log('a patch', patch) // prompt for name? ... via the (evt) on the callback ?? $(evt.target).text('') - let tinput = $('<input>').attr('type', 'text').attr('size', 24).attr('value', 'patch').get(0) + let tinput = $('<input>').attr('type', 'text').attr('size', 24).attr('value', 'patchName').get(0) $(evt.target).append(tinput) // etc $(tinput).focus() $(tinput).select() $(tinput).on('keyup', (evt) => { - if(evt.keyCode == 13){ - console.log('yar, ', tinput.value + '.json') + if (evt.keyCode == 13) { + if (debug) console.log('yar, ', tinput.value + '.json') let bleb = JSON.stringify(patch) - console.log('tryit...') - let url = URL.createObjectURL(new Blob([JSON.stringify(patch)], {type: "application/json"})) + if (debug) console.log('tryit...') + let url = URL.createObjectURL(new Blob([JSON.stringify(patch)], { + type: "application/json" + })) //window.location.href = url - console.log('url', url) - let anchor = $('<a>ok</a>').attr('href', url).attr('download', tinput.value+ '.json').get(0) - console.log(anchor) + if (debug) console.log('url', url) + let anchor = $('<a>ok</a>').attr('href', url).attr('download', tinput.value + '.json').get(0) + if (debug) console.log(anchor) $(evt.target).append(anchor) anchor.click() // finally, rip @@ -113,15 +200,6 @@ function PatchSet(View, MsgBox){ // should name it, and ID it for the interpeter ? } - // load from server should be assumed, just rip that *baybie* - this.findPatches = () => { - msgbox.write('would look for list') - } - - this.loadPatch = (name) => { - - } - } export default PatchSet -- GitLab