@SupportHumans and anyone else who may be paying attention:
I am playing around with the JS automation to try to generate code from UML diagrams… but I’m up against a few different issues.
I have tried a few different ways of accessing the properties and methods on the various JS APIs - things like foo.keys() or “for ( i in document.windows[0]) { console.log(i) }” so I can inspect the API and figure out what pieces and parts contain the data I need to spit out my code. I am wondering if I am missing something, because none of these techniques are working out very well.
I was wondering if there is, or if there are plans to, an integration of something like jQuery into the JS APIs so that there’s the ability to do something like “$(typeof Table).forEach(function() {//do stuff here})”?
Is there a way I can interface the OmniJS to use the developer tools in Chrome or Safari to example the objects/properties/values in the object model?
And finally, are there any examples out there of plugins or actions being used for code generation? I am looking at the JS APIs and considering whether trying to write something like that myself is worth the effort… especially considering the lack of tools for introspection/inspection or visualization, and the scanty documentation available at this point.
Not quite sure which JSC embedding you are working with (JXA/osa, or omniJS inside omniGraffle), but neither is an embedding in a browser, so you won’t find any of the DOM objects that much of jQuery depends on.
The basic incantation for listing the objects available to the global context of a particular JS interpreter is, of course:
Object.getOwnPropertyNames(this)
(The DOM is, as you know, not part of Javascript – it’s just an API to any browser that a particular JS interpreter may be embedded in – where there are no HTML documents there is also no DOM)
Can you use the Copy as JavaScript option from the context menu on canvas to generate some JavaScript? You might need to alter the output some to make it fit with your script. I can go into the Keyboard Shortcuts and assign a custom shortcut to Copy as JavaScript. I’d try using a System Event to trigger the command with a delay to give the copy time to work (it isn’t instant). It might help you get some information about the way to recreate some items on canvas. I’d love to hear back how it goes if you try this.
I’ve never seen an example like you describe. It’s worth sending an email to request it at omnigraffle@omnigroup.com. When you send feature requests for scripting, it helps to explain what you are trying to accomplish and what is limiting you. That way, we can tell if the solution matches your workflow.
Would using forEach work for any of this? Here’s an example from Sal. I wanted to check that all of the graphic names matched the graphic IDs for part of a test, and this is the approach he recommended for checking each graphic.id. Of course, this example works only at the per document level.
I’m using the Automation menu, OmniJS inside OmniGraffle.
As for the comment about JS, blinks I had to think about it for a second… I’ve been working with C# and Java for so long, I was in the JS console in Graffle and was just thinking “WHERE ARE MY SELECTORS!!” lol I will try playing around with getOwnPropertyNames() and see what I can drum up… so yeah, I get what you mean about jQuery being essentially an HTML DOM library that has no role in something like OmniJS.
What I WOULD ask for is a way to a) visualize the object model… like watch variables in Visual Studio, or anywhere… where complex objects are displayed visually with “twisties” to expose their children. Breakpoints? Developer tools… :D I know that’s asking for a lot for something that’s supposed to be a convenience feature, you could spend years just fleshing out the JS tooling in OG. I appreciate what you’ve done tho… it looks awesome and I look forward to seeing it mature over time, man…
Ultimately my goal is to build UML docs in Graffle and then run a script that stubs out the object model with method signatures, “extends” statements, etc., using the Connection lines to establish inheritance chains and composition where it can be discerned based on the diagram. No code gen method is perfect, but if Graffle+automation can get be CLOSE I’ll be giddy… I am not yet sure if I will have to do the code generation into a text file, into the console or into an object inserted in the canvas…
I’ll report my progress tho! Thanks for the input. :)
My only real question about that code is whether it doesn’t seem a bit of a pity to interrogate every single graphic, over the automation interface, for all of its details, before actually testing whether it has an ID mismatch or not ?
Another approach might be to :
first harvest a list of any graphics which do have mismatching ids,
then apply a (possibly reusable) JSON generating function to just the stragglers in that list.
Cool idea! When using the first set of scripts, the graphicIDs weren’t stable, so the chance of a problem was much higher than it is now. I will try this change and see if it works!
So I know this is horrendously crappy code… so no worries, this isn’t going to be used for anything other than pre-alpha examination of the API… but I just wanted you to know I came up with this snipped to start giving me the data I’m looking for.
for (var p in Object.getOwnPropertyNames(Document.prototype)) {
console.info("document[" + Object.getOwnPropertyNames(Document.prototype)[p] + "] is " +
document[Object.getOwnPropertyNames(Document.prototype)[p]])
}
Getting somewhere - It’s extremely rudimentary, but it’s starting to look like something… which is nice. Even if it doesn’t turn out to be insanely complete… just the ability to spit out a starting place… that’s huge. Saves me countless time typing boilerplate code!
Dude… check this out… I am finally getting the hang of this, finding the methods and properties I need to make this happen… here’s another screenshot for ya…
Maybe someday I can create a new codegen package that will spit out Java, C#, etc… that would be cool, aye? :)
var alertText = new String()
for (var i in g) {
if (g[i].constructor.name == "Table") {
var txt = "namespace Crawler.lib {\n"
txt += " public class " + g[i].graphics[0].text + "{\n"
txt += " public " + g[i].graphics[0].text + "() {\n"
txt += " }\n"
txt += " }\n"
txt += "}"
alertText += txt + "\n\n\n"
}
}
new Alert("C# Code Gen", alertText).show(function(result){})
alertText = ""
Well, it’s far from perfect, and it’s still very kludgy and brittle… but, for the moment… it stubs me out way faster than I could do by hand, and after this it’s just touchup.
@all… thank you so much for your input… I intent (someday) to release this as a plugin… I will use the HELL out of such a thing… lots of work to go before that, but here’s the JS I have at the moment:
var g = document.windows[0].selection.canvas.graphics
var alertText = new String()
for (var i in g) {
if (g[i].constructor.name == "Table") {
var name = g[i].graphics[0].text
var props = g[i].graphics[1].text.split(/[\r\n]+/)
var funcs = g[i].graphics[2].text.split(/[\r\n]+/)
// found a table, time to build code - namespace
var txt = "namespace Crawler.lib {\n"
// class declaration
txt += " public class " + g[i].graphics[0].text + "{\n"
// default constructor
txt += " public " + g[i].graphics[0].text + "() {\n"
txt += " }\n" // here would go the properties
txt += " // properties below this comment\n"
props.forEach(p => {
txt += " protected " + p + " " + p + "Prop { get; set; }\n"
});
// here would go the functions
txt += " // functions below this comment\n"
funcs.forEach(f => {
txt += " public " + f + "{\n"
txt += " }\n"
});
txt += " }\n"
txt += "}"
alertText += txt + "\n\n\n"
}
}
new Alert("C# Code Gen", alertText).show(function(result){})
alertText = ""
Yeah, crappy-ass code, but it spits out semi-complete C# that I can actually just drop into files and tweak!
Instead of an alert, would it possible to send the output to a file or to the clipboard or to another app like a (possibly AppleScript-able) text editor?