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

VSCode doesn't know anything about Automation objects, because they're not defined in your source file, so you won't get code completion on them. If someone wanted to take the time and effort to create an Intellisense JSON file for Automation objects, then you'd have it, but I don't see that happening.

See here for more information: IntelliSense in Visual Studio Code, and the linked JavaScript section.

I installed CodeRunner and also AppleScript extension

Which is good, but they don't have anything to do with code completion. Well, that's not entirely true. The AppleScript extension gives some support for Intellisense with the AppleScript language mode, but that doesn't help with JXA.

And when I try and type the code that you have in your example, this is what I get.

Well, yeah, you don't have the class defined - it's a custom class of mine. I was just pointing out how it works with classes in general. Try a class like I showed (you can copy and paste this):

	class GroupPathNames {
		constructor(groupFileName, repositoryFolderPath)
		{
			this.groupFileName = groupFileName;
			this.groupFolderPath = repositoryFolderPath + groupFileName + "/";
			this.groupSourceFilePath = this.groupFolderPath + groupFileName + sourceFileExtension();
			this.macrosFolderPath = this.groupFolderPath + "macros/";
		}

		makeMacroSourceFilePath(macroFileName) {
			return this.macrosFolderPath + macroFileName + sourceFileExtension();
		}
	}

And then something like:

	var path = new GroupPathNames

and type the parens.

1 Like

Two more things:

  1. Make sure you read this: https://code.visualstudio.com/docs/languages/javascript. It'll give you a good idea of what features you're getting.

  2. Regarding Intellisense for Automation objects, someone has created something for TypeScript/Node.js that has Intellisense definitions for JXA, but I have absolutely no idea how to use it. So don't ask me. :stuck_out_tongue: But if you figure it out, feel free to post it here.

Thank you for the message again. I did what you advised, and I have the auto complete working.

So I guess as far as the setup of VSCode and running JXA files (saved as js files) using Code Runner, I am all set. Thank you! I know it is repetitive, but so be it.

From an earlier message of yours - so say I create myApp like so var myApp = Applications("Keyboard Maestro"). Is there a way to inspect myApp in Safari console? I tried console.log() and JSON.stringify(). Neither seem to work. Nor does console.dir() which Safari reports is not even a function.

I did read this article. Will read again though as I am a newbie, especially with javascript and of course JXA.

I tried it by cloning his repository. But then I quickly realized that I do not know enough javascript to understand all the structure that I need to create. May be will get there in some time and will try to use it again. I wonder though as to why you have not attempted it, or perhaps it is that you attempted it and did not find it that useful.

Thank you!

Awesome, and I'm glad you got it working!

From an earlier message of yours - so say I create myApp like so var myApp = Applications("Keyboard Maestro") . Is there a way to inspect myApp in Safari console?

I don't know. It doesn't seem like it. But you can open the Dictionary in Script Editor and change the Language to JavaScript, and get the definitions from there.

But then I quickly realized that I do not know enough javascript to understand all the structure that I need to create.

Yeah, it was over my head for now. I mean, I'm sure I could figure it out, but it just looks like too much work. :smile:

I've got some JXA scripts that might help. I haven't reviewed them in several years, so while I assume they work, nobody likes the code they wrote a couple of years ago, right?

If you have questions, just ask. Have fun!

1 Like

Thank you for the link. Yes will go through the scripts that you created. And I know what you mean that one does not want to look at one's own old code. :smile:

Quick question on how you do the above. So where do you use console.log or JSON.stringify() to look at what inspect JXA objects?

This is the big issue that I am facing right now. Perhaps I need to start another thread and ask as to how to best interpret and use the Dictionary in Script Editor. May be, if I can interpret the dictionary better, then I will feel less need to inspect JXA objects...

I totally, 100% agree with how frustrating it is. If you go back a few years you'll find some posts from me, where I'm, um, "complaining" to anyone who'll listen about why is this so hard to figure out?

As far as I know, you can't use console.log() to find out the properties of Automation objects.

As for how to use the dictionary, it's easy, if not a little frustrating.

  1. Start Script Editor, and click the "New Document" button in the bottom left.

  2. Click "File->Open Dictionary".

  3. Select the application, like "Keyboard Maestro Engine".

  4. At the top middle is the "Language", which probably defaults to "AppleScript". Change it to "JavaScript".

Then you have to start looking around, but for the KM Engine, try clicking on the "Keyboard Maestro Engine Suite", and in the second column, you'll see some of the functions and objects available.

But in my opinion, it's easier to find examples and just learn from them. Like my scripts I linked to, or search this forum for specifics.

Also, don't forget these links:

I'm pretty sure @JMichaelTX has a bunch of resources listed somewhere, too.

My best advice: Get frustrated, don't get frustrated, either way, don't give up. If it happens to you like it happened to me, one day you'll want to tear your hair out, and the next day it suddenly starts to click.

2 Likes

You can if you first convert the objects to a JSON string, then log that.

1 Like

Thanks for the encouraging words and the help and the links. At this point, I am trying to Automate some things with OmniFocus app. The Script Dictionary concepts that I need to understand are basic concepts however.

I am guessing it is best to start another thread for that.

That would be wonderful. Please don't hold back as to how to do that. That would be huge!

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?