DOpus IntelliSense (aka autocomplete) definitions for VSCode

Hi everyone,

This is not a script on its own but a helper for scripting, imho a big one. Following is from the project's GitHub page. For up-to-date version and info please use Github.

--

The TypeScript definitions for the Scripting Objects to be used in VSCode & similar, for the excellent file manager Directory Opus.

The DO developers accepted my humble request regarding new Get()/Set() methods for the Map object. So I decided to pay my thanks to the developers and to the community, from which I benefitted greatly over the years.

Unlike the name suggests, you don't have to learn TypeScript. TS can parse JavaScript as well and your scripts will still be good (cough), old JScript. If you are used to develop with JSDoc, JavaDoc and similar, you'll feel right at home! In fact, you will enjoy developing DOpus despite lacking a debugger.

Setup

You need VSCode or similar; I prefer VSCodium Portable.

  • First if you haven't done so, activate JS/TS › Implicit Project Config: Check JS in user settings:
  • Copy the .d.ts file to your scripts directory.
  • Put this at the top of your user script:
    ///<reference path="./_DOpusDefinitions.d.ts" />
    // @ts-check
  • Done!

Now all objects in the Scripting Objects section are at your disposal; except where it's not valid JS, e.g. imageMeta.35mmfocallength because it starts with a number and so on.
...
For example as we declared the type of scriptColData, VSC can deduce scriptColData.item is a DOpusItem now:

...and you can access the item's attributes & methods directly:

If VSCode cannot infer it or does incorrectly you can help it via adding /** @type {DOpusXXX} */ in front of it:
05

Help needed

Pull requests are welcome. I don't know much about collaborating on GitHub but we'll figure it out.

I am a complete, total, bloody newbie in TypeScript. If you are a better TypeScript expert than me (not a very high threshold heh), your feedback and help is most welcome! Just submit your pull request, or maybe you'll get commit rights, we'll see from there.

If you are not a TS guru, you can still help. Any formatting help or adjusting the attribute's readonly flags, return values, etc. still need to be adjusted.

Notes

This is a very early stage project. Some or none of features may work for you.

Now all the little details:

  • All DOpus objects are prefixed with DOpus - I do not intend to change this at the moment.
  • Probably the most important one: The DOpus and DOpusFactory objects are not available yet!
  • JavaScript is case-sensitive so all method names are defined twice: Once as defined by DOpus, e.g. item.ShellProp and once in lower-case, e.g. item.shellprop. Since I try to stick to common JS developing styles and did not want to use item.Open() but rather item.open(), I chose doing so. The InitialCapNames() are used generally only for constructor methods. Other than the case, the method pairs are completely identical. Choose your pick.
  • The "default value" of some objects, e.g. FilePath, is very JavaScript-unlike. In such cases, I defined the object with "DOpusFilePath extends String". For all intents and purposes item.filepath behaves like a string, but you might occasionally force some method which accepts only string to accept a filepath with myFunction(''+item.filepath).
  • Most attributes are defined to be read-only... at the moment. But that will improve over time. The information whether a field is readonly (e.g. a file's size) or changeable (e.g. a column's value) is unfortunately in the remarks column in the help file. My parser is not an AI which can deduce that, so adjusting these will be an ongoing manual effort.
  • This was not easy as it seemed. It's the product of ca. 15 hours of work: a lot of JS debugging and many manual corrections. I had to decompile the DOpus.chm file and parse every object's file individually using a Tampermonkey script (which will be uploaded later). Because even the slightest inconsistencies between the files, like formatting, a's within strong's or strong's within a's, different notations or a very obscure constellation broke my parser. So not everything looks perfect.
  • The file dos not pass ESLint & JSHint checks yet, but before fixing it, I want to test the latest beta with the new Map methods.
14 Likes

Do you use this extension to display ascii big comments ?
image

I wasn't aware that there was a VSC extension but of course, there is :smiley: I use this site Figlet Generator in colossal style

Mind you, the big figlets are mainly for the minimap. Colossal font looks best in the minimap for my taste, it stays readable in most situations.

1 Like

Did you try to dev with last JS features then transpile to ES3 ? If yes, what did you use ?

A very good question, and you poke an open wound. Short answer is "No, but I seriously thought - and am thinking - about it and if I do it'll 99% be TypeScript-based."

The thought crossed my mind many times, while developing my biggest but unreleased DOpus script yet, a multi-threaded hasher; check my Github. That one grew to over 10k LOC/250KB at times, in 1(!) single file, which was frustrating to work with to no ends; now you know why the big figlets are there :wink:

DOpus devs probably hadn't foreseen that user scripts might grow this large (I've seen a few other scripts in the forum upwards of 100-200KB) but neither had we foreseen that JS would rule all Internet 25 years ago. After the editor problem is now mostly solved, the single one "modern" (heh) JS feature I miss sorely in JScript is require/import/export or modularization, bar none. Shared, stable libraries with their own unit tests, etc. No other missing feature comes eeeeeven close. Unfortunately libs like requirejs.org don't help either, because the initial import is implicitly done by the browser runtime, which we don't have. It's remotely followed by missing for...of & the error handling in plain JavaScript, not just JScript but JS in general (see Type-safe Rust-like Result in VSCode for JScript and newer | cy-gh.github.io). I can either already implement or work around everything else: unit tests, enums, classes, inheritance, etc. Other missing syntactic sugar, promises, freeze, etc. don't bother me, at least not in the context of DOpus scripts.

The modularization problem put me on a crossroads and I froze all DOpus developments: Either I stay in WSH-land and use something like forum guru tbone's genius solution (HowTo: Create a function-library with Windows Script Components (WSC)) or switch to TS, which is obviously the "proper" choice. The problem is I don't use JS, TS, npm, grunt, etc. in my day job so many new tools mean a lot of learning curve and time investment, which I lack at the moment. Also my local, very ugly copy of the hasher script works very stable so the urgency to work on it mostly vanished. But at the same time that script also fundamentally changed my workflow and how I see checksums and file management. So I want everybody to be able to use checksums as seamlessly so I'll probably do it in upcoming months.

If you do any work on this, say prepare a small tutorial how to setup a small user script with TS/npm/babel/grunt backend, I'd volunteer to review/work on it together.

I would switch to C++ or C# for that kind of size/complexity!

You mean write plugins in C++/C# instead of user scripts? Or for transpiling from C++/C# to JScript?

For transpiling TS/npm is perfectly OK for me, from what I've seen they can handle very heavy duty stuff, they're the code base of VSC after all. If you mean plugins, that's a whole different topic.

Depends what the aim is. You can write COM objects that can be called from JScript/VBScript, or just have a standalone exe which is run either on its own or via a script and does everything in its own process, or plugins, etc. depending on what the code needs to do and where the results need to end up (on screen in a separate window, in a file display column, in a file, etc.).

For now, I would keep it simple and see what can I do with babel outputing an internet explorer 6 compatible file. I should be enough in the context of DOpus scripting helper. One of the assets using VSCode is versioning with git. It offsets the lack of debugging capabilities in DOpus other than the console.

About what Leo said, in the past I wrote a simple autoit app and called it via a button like I would call any other .exe passing arguments. But I didn’t need to access DOpus methods and objects, which scripts allow to do easily.

There are a lot of solutions to help you navigate into one file. The outline panel first.

Bookmarks from extensions like this and the one I like : Mark Jump with this little setting I made here.
You will have panel with your marks in the explorer or via a shortkey.
image
image

1 Like

@Leo
C++ & COM?! Hsss! dracula-garlic-reaction.png :smiley:
At the moment, I'm primarily interested in metadata/user columns, JS/TS do fine and your scripting API is very extensive (big kudos for that!). For launching external apps from DOpus, there are plenty of best-of-breed CLI apps already and JS as glue code works very well there, too. If not I use, AHK, Powershell, Python, TCC, whatever works. We only have to solve the "JScript problem" which @Fred also recognized (incl. his separate feature-request). In fact, if we can solve it that might help more people, because there are most likely more JS devs among DOpus users than C++ devs. The main reason why that script grew that big was my stupidity: featuritis, it crept in slowly. At some point I will develop a plugin, but not for this development, too late for that. Regardless, as said above the "JScript problem" boils down to one single issue for me: modularization, that's it. Luckily JS ecosystem has all the solutions, like transpiling, it's only I lack the time.

@fred
If you'd find out even the simplest proof-of-concept, that'd be great!

Also thanks for the tips! I use outline a lot, also Codemap extension, bookmarks less so. Sometimes the minimap is faster. Split editors (#1 fave), find references and Ctrl-Shift-O (go to symbol, #2 fave) also help a lot, but sometimes you need to scroll, you know. So I end up using... everything. At the end, as long as it's one big file all of this is just band-aids.

After reading through this thread I still have one simple question: What is the purpose of using VSCode regarding DO?

Can I code scripts in VSCode to be used in DO?
Do I still have to copy&paste the appropriate code into DO?
Can I use VSCode debugger to debug scripts that run inside DO?

Or do I completely misunderstand the whole thing here?

Michael

So that you have a full-fledged IDE with best-of-breed JavaScript support, than a simple text-editor. It is meant for (external) user scripts, rather than the scripts you would put directly into buttons or alike. You don't need it if your scripts don't go beyond 100-200 lines but anything bigger would hugely benefit from a good IDE. And you could always turn embedded scripts to user commands and maintain the code via VSC instead.

With VSC and this Intellisense file, you basically get basically embedded help for all JS objects, plus much much more, e.g. what kind of object they are, what methods and attributes they have, which string you have to pass to a method to open a file in readonly vs append mode, and more.

You can e.g. write "DOpus." and press ctrl-space and see all the methods available e.g. output(). Or if the type of a variable can be determined (inferred, I explain a few ways to do it in GitHub), e.g. a DOpusItem object, you can press Ctrl-space and see all methods and parameters. Of course the major benefit of using VSC is, you can find all references to a method or variable, jump directly to its definition/declaration. Of course VSC can also use industry-standard tools like ESLint to warn you of various problems, like misspelled variables, etc. If you accidentally pass a DOpusItem variable to a method which expects a DOpusPath, VSC will warn you, too. All that shebang of good IDEs.

If you've never used an IDE or VSC it might be overwhelming at first, but once you get used to one, you will never go back.

With external scripts, yes. As soon as you save it in VSC, DO will reload the script instantly.

If you only use small and/or embedded scripts, you don't need VSC. You can safely stay in DO-land and use internal editor. I personally find scripts, big or small, in buttons not reusable and rather use external files.

If you mean setting breakpoints in VSC and triggering them from DO, then definitely no. Windows WSH and VSC will run in completely separate memory areas.
But if you have blocks which you can test independently, e.g. a sprintf class which you temporarily start like this:

function sprintf() { /* ... */ }
// the line below would be the temporary start
// or alternatively it could be external Unit Test files
sprintf('%s -- Output: %s', _myDatetime, _myLogEntry); 

then you could debug it.

Hope this clarifies a few things.

Thank you very much for these comprehensive and very helpful explanations.

Michael

1 Like

I've come up with a possible way to allow both character cases (PascalCase like in the documentation and camelCase like typical javascript), doesn't require much extra code, and doesn't require making any modifications to the existing interface declarations or anything. (I had not a small amount of help from AI lol)

It's two parts, first just a tiny function that creates a new copy of the type but with the first letter capitalized (this function only needs to appear once in the whole .d.ts file)

// Create a type that generates PascalCase aliases
type PascalCaseProperties<T> = {
    [K in keyof T as Capitalize<K & string>]: T[K]
}

Then for each interface it's a matter of adding one line each, for example:

interface DOpusConstructor extends PascalCaseProperties<DOpusConstructor> {}

And with that it allows it as both cases:
image

Whereas before it would give an error:
image


One limitation is that for properties (not methods), while it is able to recognize the pascal case names and even the types, VSCode doesn't seem to be able to recognize the original definition, so you can't use "go to definition" for example. See like:
image

It sees the type but not the info:
image

As opposed to:

But at least it would make it so if working on existing code that uses pascal case, it wouldn't throw any errors. And strangely even for the second one, using "Go To Definition" on the delete method still works.


So basically it would require adding a bunch of lines like at the bottom of the d.ts file. Though a silver lining is that might make it helpful to be able to see which objects have been added so far and which still need to be added, and at least it's all in one place so one could just comment it all out if they don't want to use it like that.

Edit:

Here's a quick powershell script that goes through the file then outputs the lines as necessary which can then can be copied into the file:
MakeTypes.ps1.txt (923 Bytes)

And an example with the d.ts file all put together with the additions:
_DOpusDefinitions.d.ts.txt (357.3 KB)