How To Use "VS Code" for JXA, with Keyboard Maestro

See JSON.stringify() .

Got this. However, can this be used on JXA objects? That does not seem to work for me.

So, when running a JXA script which is in debugger mode and in Safari debugger and halted,
then after running
myApp = Application("Keyboard Maestro");,
executing
JSON.stringify(myApp); in the Safari console results in undefined as output, and console.log(JSON.stringify(myApp)); does not generate any information either.

I think Jim means something like this:

var kme = Application("Keyboard Maestro Engine");
var kmeProps = kme.properties();
console.log(JSON.stringify(kmeProps, null, "\t"));

But that doesn't return much information:

{
	"frontmost": false,
	"pcls": "application",
	"name": "Keyboard Maestro Engine",
	"version": "9.0.2"
}

You are right. He had earlier mentioned that he uses kme.properties() to inspect, and then make a string of it and then print it. Got it.

And as you rightly observed, this does not give the full extent of what is available with the kme object.

Thank you both!

OK, this is interesting. I'll explain the steps I took in a second, but look what I've got here. I've got my cursor over "Application", and I've got Intellisense:

image

And I guess I've got Intellisense for the following applications (I stitched two screenshots together to get the entire list):
image

Here's what I did. I started here: https://github.com/JXA-userland/JXA/issues/4

Interestingly enough, @JMichaelTX had asked some questions, and one of the answers led me to here: https://github.com/JXA-userland/editor-integrate-example

I followed the steps he listed, and I'll add a couple of notes:

  1. I created a folder called Test (not totally relevant, but it's what I did).

  2. Opened a Terminal window inside the Test folder.

  3. I executed the first step from the above "example" link:
    git clone https://github.com/JXA-userland/editor-integrate-example
    It worked, and created a subfolder called editor-integrate-example with some stuff in it.

  4. Next step from link:
    cd editor-integrate-example

  5. Next step:
    npm install

    This failed with a bizarre error because my node or npm installation(s) were messed up (I don't know a lot about this stuff), but some searches led me to this solution, which worked because fortunately, my installation of homebrew is NOT messed up:

    brew uninstall --force node
    brew uninstall --force npm
    brew link --overwrite node
    
  6. Next step:
    vscode .
    But it couldn't find vscode, so I must not have my path set correctly for VSCode from the command line. So I did it this way:

  7. Opened VSCode the normal way, then:

  8. File->Close Workspace

  9. File->Add folder to workspace

  10. Added the folder that had been created in my Test folder, editor-integrate-example.

  11. Opened the file example-jxa.js.

  12. Hovered my cursor over the Application object, and presto! Intellisense! It looks kind of different, but there's certainly good info there.

Here's some thoughts:

  • Either package.json or tsconfig.json are probably what's telling VSCode where to get the Intellisense files. I'm guessing it's package.json because I think the other one is for TypeScript.

  • I have no idea where to put this stuff so it's accessed automatically from other JXA projects.

  • No Intellisense for any other applications, like "Keyboard Maestro", etc. However, if you delve into the source files, I can't believe he typed them all by hand, so I'm guessing there's a way to import a Dictionary entry to create these files. If so, then someone could create them for "Keyboard Maestro", etc. But I don't have the time to spend on it now, so it's up to you guys, or nobody. I've got a video I have to finish, and then some "honey-do" projects, so that's as much time as I can spend on this. I'm telling myself this, also. :slight_smile:

I followed your steps and indeed it works. I had stumbled on it earlier also but must have missed some step. Thank you!

:rofl: I know exactly what you mean.

1 Like

Here are two links that I reached which seem to source Intellisense for other apps. However, 1) the discussion appears to be for Typescript, and 2) most of it I am not able to understand.

Sounds like one has to convert “sde” to “dfs”. More generic discussion as to how to add support for other application is here.

Somebody would know how to make it work... or maybe, once I understand more javascript.

1 Like

Hey Dan,

Many thanks for this very detailed set of instructions❗
I just followed it exactly and it worked for me now.
I don't know what I was doing wrong before.

Did you ever figure this out?

Yeah, that would be great to have the autocomplete for KM.
Any ideas on how to build this?

No. I just decided to copy anything I needed into each JXA file.

And no, I didn't figure out Intellisense either.

@DanThomas @sims, @ccstone, @ComplexPoint et al:

OK, I think I have a workable process to develop JXA scripts in VSC, and then to debug, run in Script Editor/Safari, and finally execute that JXA script in KM:

  1. Setup VSC workspace/folder using the method @DanThomas provided above. (one time setup)
  2. Use the Folder setup above for ALL JXA scripts. (unless you know how to make the JXA Intellisense work for all VSC projects).
  3. In VSC, create a new file, and use the .scpt extension.
    • As Dan noted, the first time you will need to assign this extension to "JavaScript"
  4. Create your script in VSC.
    • Intellisense works for the main JXA scripting objects (like "Application", "System Events", etc) and for most Apple Mac apps (like Dan showed above).
  5. When you are ready to run your script, just open the file in Script Editor and run.
    • You cannot make any changes in SE to your script
  6. If you want to use the Safari Debugger, add a "debugger;" line in VSC, then open Safari, and open the .scpt file in Script Editor, and run.
    • If you have Safari setup correctly, the Safari debug window will open when the first "debugger;" line is executed.
  7. When you script is completed and ready for production, use an "Execute JavaScript for Automation Action in KM, and just select the same .scpt file.
    • Since official JXA script files created and saved in Script editor are really just plain text files, this works fine in KM.

I have just successfully testing this process on one script. So far, so good. :wink:

I'm going to develop a script to automate opening/running the VSC .scpt file in Script Editor, so with one hot key we can go from VSC to debugging in Safari.

If anyone has any questions or suggestions, please feel free to post.

@JMichaelTX Thank you for sharing.

Q. Is there any benefit of running the script in script editor - I am sure there is and I do not know? Especially if one is using debugger; to debug the script - not that I have used the safar debugger lately - will try to use now?

The main reason is to use the Safari Debugger.
This is the ONLY debugger I know of for JXA.

Also, the SE log pane (at the bottom) provides more output than simply console.log(). If there is a better way, with better output solely using VSC I am open to that.

Bingo❗ Found a converter:

Convert Scripting definition files (.sdefs) to TypeScript(d.ts) -- GitHub JXA-userland

I am such a novice at Terminal and VSC that I don't understand how to use this tool. It looks like it offers a script that can be run from VSC, but I don't understand how. Maybe one of you VSC gurus can figure this out:

From the GitHub

Install with npm:

npm install @jxa/sdef-to-dts

Usage as library
Convert ./input/*.sdef file and output it as d.ts to ./output directory.

const fs = require("fs");
const path = require("path");
const { transform } = require("@jxa/sdef-to-dts");
const sdefDir = path.join(__dirname, "./input");
const outputDir = path.join(__dirname, "./output");
const promises = fs.readdirSync(sdefDir).map(async caseName => {
    const fileName = path.basename(caseName, ".sdef");
    const normalizedTestName = fileName.replace(/\s/g, "");
    const actualContent = fs.readFileSync(path.join(fixturesDir, caseName), "utf-8");
    console.log("transform " + normalizedTestName);
    const actual = await transform(normalizedTestName, actualContent);
    fs.writeFileSync(path.join(outputDir, normalizedTestName) + ".d.ts", actual, "utf-8");
});
Promise.all(promises).then(() => {
    console.log("All write");
});

How do we use as "library" to convert .sdef files (actually the .app file)???

Oh. I did not realize that Safari Debugger cannot be invoked from JXA using Code Runner. In that case, it makes most sense to try and use the .scpt route that you found and marry VS Code, SE and KBM. Very creative solution. Will work on adopting it.

@DanThomas @sims, @ccstone, @ComplexPoint et al:

I have just posted a macro and video:

MACRO: Run Current VSC JXA Script in Script Editor

My sincere thanks to everyone who has helped us all understand how to use VSC to develop JXA.

1 Like

3 posts were split to a new topic: Problems with KMFAM Macro System

I am wondering if Keyboard Maestro can plug into the text cursor position within VSCode.

I think you would probably need to explore the VSC extension API:

Your First Extension | Visual Studio Code Extension API

1 Like

In a word – nyet.

@ComplexPoint's idea is intriguing, athough I don't know of any way to run external code in VSC and return a result.

Worth a peek:

visual studio code - vscode API: get Position of last character of line - Stack Overflow

-Chris

I think that's right – the obvious route would be to do the whole thing from inside the VSC extension.