TextExpander Applescript to Retrieve DT3 Data

The benefit may depend on your use case.

I use DT3 to store legal and medical documents I used in my consulting practice where I am a physician who reviews cases for attorneys in order to advise on the merits of a malpractice/injury case (or lack of merit) and the cost of future treatment.

Often I will send emails to my staff members or to my clients referencing various metadata in documents I have on file. The script as-is only lists the Name of the documents, but it will be easy to add in other metadata fields. Then I will be able to tweak the TE snippet so I can highlight multiple documents in DT3 and then in my email open on the same computer it will create a mini report with the name and associated metadata for each of the items.

Or I might want to make a comment in the metadata on various documents and send an email to my client which includes document names and my comments.

Or I might want to use Javascript to filter by due date and create a list of cases due this week and alert my staff.

Another major use may be for citations/quotation of reference sources and associated annotated commentary that I organize in DT3 and then periodically need to add into my reports or email correspondence.

etc. etc.

So basically it will be used as a lightweight custom report generator.

1 Like

Hi there,
If by coincidence you’re using Keyboard Maestro, you could use this script


It copies the names of the currently selected DT records to the system clipboard, separated by newlines (the same as the original AppleScript, if I understand that correctly). You should be able to incorpoate that in an action that is triggered by a keystroke and inserts the data in the currently open e-mail.

1 Like

out of curiosity: What method or tool do you use for e.g. consistent document naming if not TextExpander?

Thank you - you read my mind. . Another major aspect of my workflow recently involves learning/using Javascript with Retool so I was wondering how I can shift some of my scripts to Javascript. I will try it out.

My need for consistency is in naming the Group I use to hold all of the documents for each case. That is pretty simple - last name, first name of the claimant in the case.

Beyond that, all of my referral sources have their own way of naming documents so there is no need nor method to name things consistently. As long as it is filed in the right group, I will find the document and likely create subgroups or tags or annotations to organize the information based on each client’s unique issues which I have been asked to review.

Perhaps more importantly, I have a set of about half a dozen custom metadata fields with information such as referral source, nature of the referral, due date, etc. Those fields enforce consistency so I do not lose track of cases.

As you can see, it requires a lot less typing than AppleScript :wink:

Yes indeed

Question - is there an equivalent to Script Debugger for Javascript? Maybe a Javascript IDE like Webstorm? Something else?

Not really. One could use the browser to debug JavaScript code running in it. But for JXA (JavaScript for Automation) you’d need the Apple runtime environment. Which is only available in the ScriptEditor and in Safari, it seems. Here’s a description on how to use the latter for debugging purposes:

I tried that a long time ago and found it not to be very reliable. So nowadays I’m running the scripts in Script Editor and try to figure out what goes wrong there. Possibly with the help of console.log().
Just a word of caution: JXA is not really well supported, and Apple didn’t do any work on it since its inception. Which is one reason why there’s only few information available on the net. And it is nearly impossible to figure out the internals of JXA objects (that’s unfortunately also true for debugging within Safari). But with some experimentation, you’ll find your way.

1 Like

Thanks

I am trying to learn where you derived the syntax

For example your script refers to app.selectedRecords.name

(1) How did you know to prefix it with “app”?

(2) The plural “selectedRecords” is not in the Script Editor Javascript Dictionary - did you just assume or by trial and error realize it must be plural since that is allowed for other elements?

@chrillek

Thanks again for the suggestion - when I try this either in KM or in Text Expander, in each case the output is blank. Am I missing something?

image

The output is blank because there is none. All the script does is save the names (one on each line) to the system clipboard, as you can see at the very bottom of the screenshot. So Cmd-V should insert it into whereever you want to insert it.

As to your other question re app etc.:

  • app is the JavaScript equivalent of tell ... end tell: It calls a method of a certain application object (DT, in this case). So basically all methods in the dictionary of an application have to be called on the app object.
  • If you check the Application entry in the function library, you’ll see selectedRecords mentioned there. Generally, all classes are available on the app object in plural form (databases for example).
  • To get at one particular object, you can use array notation like in app.databases[0]. You can also iterate over them with (e.g) databases.forEach().
  • This singular/plural thing continues: If you look at the description of Database (singular!), you’ll notice records, smartGroups in the contains section. So to get at the records of a particular database, you can use app.databases[0].records
  • selectedRecords is actually fun: as you’ve noticed, you do not have to drill down into it but can get a certain property of all selected records with a single function call like app.selectedRecords.name(). While selectedRecords is an array of record objects, selectedRecords.name() is an array of string, i.e. of the names of the selected records.
  • What you can also see is that you’ll have to use a function call to get the value of a property (name(), plainText() and so on). To set a property, you use simple assignment (name = "newName" etc.).

I suggest you google for “JXA release notes”. That should get you to the only two documents available from Apple on JXA. They describe the features fairly completely, albeit incredibly brief. Of particular interest are the usage of whose to get at certain array elements and the peculiarities of UI usage. Also, if you ever have to read or write a file, make sure to do that with an Application object returned by Application.currentApplication. Nothing else will do (yes, JXA is crap in many aspects).
BTW: white on black is not very legible (people from the printing business are aware of that) unless you take special care of the fonts. So maybe using the white-on-black model for screenshots might be more helpful.

Many thanks - that is extremely helpful - Interesting by the way that the links in the function library i.e. “selectedRecords”, do not show up in the search feature - I will need to remember that in the future looking up items.

Puzzlingly - the script takes a few seconds to execute (suggesting it is functioning) but the result is to set my system clipboard to blank. So it is working but yields no output. Odd.

Edited later… in Textexpander I get this error:

(script evaluation timed out)

So it appears that the script is failing due to a timeout error. Thoughts on why that might be?

Here’s what I did in KM:

  • selected three records in DT
  • clicked on “Try” in KM
  • did Cmd-V in my editor
  • got the names of the three selected records there

That worked ok. Can you run the script in Script Editor to see if it raises an error there? And how many records did you select in DT?

I selected just one record - and also tried it with a few records. Same result

In script editor it does not time out - but again nothing shows up in the clipboard.

Weird. It looks as if the records had no names (impossible?) or there where no records selected. Here’s what I get:


(Please ignore the stupid £ sign - that was just a keyboard glitch). I selected a JPEG, a PDF and a Webarchive.
You’re running DT 3.7.2, right?
Could you perhaps try this:

(() => {
const app = Application("DEVONthink 3");
const names = app.selectedRecords.name();
var result="";
console.log(names);
names.forEach(n => result += n + "\n");
return result;
})();

This should give you the names of the records one by one and finally the list separated by a newline. Please klick on the right most button on the bottom (the one with the three lines) and then on “Messages” to see console output.

Thank you for trying here - this is quite odd

Yes I am using DT 3.7.2

With the console.log and other items added, the output is again blank (including selecting console output as you suggest)

And just to verify I am looking in the right place - console logs do work if I add a fixed string - but still the script overall has no output

I’m out of my wits here. If you have selected records in DT, they must have names. If I do this in DT


I get this when I run the script in Script Editor:

(having selected Replies in the bottom toolbar). What does

(() => {
const app = Application("DEVONthink 3");
const recs = app.selectedRecords;
console.log(recs.length);
})()

tell you?

I agree - very puzzling.

I suspect there may be a timeout error because I get that error sometimes when running Textexpander with the same scripts and sometimes Keyboard Maestro never proceeds to a next step in the macro.

Alternatively - is there any. permissions/security setting that would permit Applescript operation with DT3 but deny Javascript access to the database?

Yes, I have records; the Applescript version of the script works fine (with no delay at all) with the same records.

If I try these records:

The result is “undefined” as below

But the Applescript version of the script runs fine:

So is this group a RSS feed that somehow gets converted into markdown? I checked with my RSS feeds (which are all HTML) and had no problem there. But I’m really at the end of my wits here. The code is obviously not wrong (i.e. it throws no error) but it somehow fails to retrieve the selected records… You could try to use the old method like so:

const app = Application("DEVONthink 3");
const recs = app.selection();
console.log(recs.length);

And please select “Replies” in the lower tool bar, that is a bit more verbose.

Nope. JavaScript and AppleScript go through the same backend, AFAIK. And a permission problem would probably raise an error.

Yes, it is an RSS feed that is converted to Markdown. I used that as an example here because there is no personal information in that Group. But I also tried it on a different Group with just PDF files and the same thing happened.

Same response with the alternate script - if I understand the message, it means that it is not recognizing my selection