No file name for AppleScript action when creating document using take-note hotkey?

In DEVONthink 3.8, I have a Smart Rule to run an AppleScript script that uses a document’s file path to run an external command. It’s set to execute “On Creation”, “On Import”, and “On Duplicating”. It works fine when I create a document via, e.g., DataNewMarkdown text, but not when I create a markdown document using the “Take Note Hotkey”, and I discovered why: the record in the AppleScript executed by the Smart Rule does not have a file name at the time the Smart Rule runs. Specifically, in the code

repeat with _record in selectedRecords
	set file_path to the path of the first item of _record

the value of file_path is an empty string. Presumably, it’s because the document has been created but has not yet been saved. I attempted to change the condition to “After Saving”, but that didn’t seem to have an effect.

So … how can I write a smart rule that invokes an external command on the file created by using the “Take Note Hotkey” pop-up window?

In your repeat you’re using path of the first item of _record but it should be path of _record.

No – I know it looks like a mistake, but I tried just path of _record, and it also fails to have a value. It also causes an error later in my code. At least with first item of _record, it works in the case of creating documents within DEVONthink.

Before replying I tried it by setting the comment of a record that was created via the Sorter to its path via a Smart Rule - the comment has the full path. No idea why it doesn’t work for you.

Thanks @pete31 – the fact it worked for you was a useful clue.

I think I understand now what’s causing it, although it’s unexpected. This smart rule is one of the first in my set of smart rules, but it is not the only one with the trigger condition of “On Creation”. One of the rules further down in my list happens to rename documents if they have a certain pattern. (I use this in combination with the sorter to file notes automatically.) Now, I thought putting the current smart rule near the top would cause it to run before the other/later rule ran. My understanding is that Smart Rules are supposed to be executed in the order they’re listed. What seems to be happening is that DEVONthink runs the other rule fast enough that it’s changing the name before this rule’s Applescript code is executed.

My current hypothesis is that the rules are executed in the expected order, but because this rule invokes AppleScript and because DEVONthink no doubt runs scripts in a process thread, DEVONthink probably starts that thread and simply moves on to other Smart Rules before the thread finishes.

Not exactly the same (in fact it’s the opposite order) but I used one Smart Rule that renames specific records and another one that opens them (both via AppleScript). Most of the time it worked but quite often the Smart Rule that should open them didn’t work. Once I merged both scripts there wasn’t a failure anymore. So it might be that there’s a problem with renaming records via AppleScript in Smart Rules.

2 Likes

Yeah. I spent over half hour trying to get the rules to work but am giving up in frustration. I can’t find a way to force the non-renaming rule to run before the renaming rule executes, can’t find a way to delay the renaming rule since there’s no “pause” action in smart rules, and consequently, can’t get a file name into the non-renaming rule because the renaming rule causes the record’s file path to appear blank when the non-renaming rule runs.

1 Like

Yes, if they work the way one wants them to work then Smart Rules are a very big help. But if they use AppleScript and they don’t do what one wants to do then there’s no (easy) way to find out what might go wrong :expressionless:

1 Like

I apologise for barging in from three side line. But _record seems to be the current element of a list. And afaict, it is not a list itself. So what is first item of _record supposed to be in this case? A record? But that’s what _record already is (or should be, I think).

In terms of JavaScript: app.selectedRecords() returns an array, so app.selectedRecords().forEach(r => {}) loops over all elements of this array. Which are records. Trying to use r[0] (which is the equivalent of first item of _record) gives undefined

Edit: In the case of AppleScript, the behavior is weird (even for AppleScript). Here’s a sample script

tell application id "DNtp"
	set _record to first item of selected records
	set r to first item of _record
	log r
end tell

which gives me these AppleScript events:

tell application "DEVONthink 3"
	get item 1 of every selected record
	get item 1 of content id 214165 of database id 1
	(*content id 214165 of database id 1*)
end tell

So first item of _record obviously is just _record itself. Whereas it should result in an error because first item of does not make sense for a non-list. Unless, of course, AS simply casts a single item silently into a single item list. Yuck.

1 Like

Thanks for looking into this! I agree the situation makes no sense :-).

I did an experiment using two smart rules: one that prints the path, and another that prints the path of the first item of the record. Here are the rules, so we can see exactly what’s happening. They are in my list of rules in this order, but ahead of the rule that does the renaming.

Rule 1:

Rule 2:

For completeness, here is the rule that does the renaming:

When I write a note using the take-note pop-up, like this:

both rules print the same path – this despite that the “first item of the record” version doesn’t make sense, and should result in an error:


When I write a note that looks like this, to trigger the renaming rule,

both rules print an empty path:


I can no longer remember why I hit on the “first item” version while writing the smart rule that I’m actually trying to make work (which was part of the original posting). Seeing now that both test rules print the same path, my guess is that, at the time, I was trying to figure out why I sometimes got an empty string and sometimes didn’t (not knowing at the time that it was a side-effect of the renaming rule), and probably concluded mistakenly that using the first item was needed.

In any case, this experiment seems pretty conclusive: something about the renaming rule causes the file path to be empty (perhaps only temporarily, but long enough to cause problems) when the other rules run their applescript code.

Hopefully, the DEVONthink devs will weigh in on this topic after the weekend is over.

FWIW, here are the rule definitions, exported from my copy of DEVONthink 3.8 on a macOS 10.14.6 system:

print path.dtSmartRule.zip (1.3 KB)
print first item of path.dtSmartRule.zip (1.4 KB)

After having read a bit in Apple’s documentation, I guess the first item of clause applied to a non-list simply converts the variable/object/whatever to a one-element list. So an implicit cast, which is A Bad Thing™

If it were a programming language worthy of the name, it would either throw an error (applying an operator to an object not supporting this operator), have it clearly documented (improbable given Apple’s unwilligness to write documentation) or optimize the first item of clause away (if it had a compiler, that is). In decresaing order of preference.

As to your experiments: In the first case, the name is not changed at all since the RegEx is not matched (I guess). I have no idea what happens in the second case (where body starts with @self.... Is the name in fact changed? Then maybe the “print it” rule runs at a bad moment? What happens if you change its condition to “after rename”?

I’m not really on right now, but there is a specific event trigger for notes made via the Sorter - Via Sorter. Have you tried that?

In fact, the rule conditions don’t match at all, since they include a test for the name beginning with @self.

I can’t find an “after rename” or “after renaming” condition in the smart rule editor, but there is a “on renaming”. I tried that but it never fires. Other conditions tried:

  • On renaming
  • Before saving
  • After saving
  • On moving

When these are used, the rule never even runs. The only ones that work are On creation and On creation ▹ Via sorter. (Ok, I didn’t try all possible trigger conditions, but the others don’t make much sense in this context.)

Yes – the behavior is the same as when I use the broader “On creation” condition.

I was guessing since I use the German version.

I didn’t mean for my reply to sound critical. I really was only trying to clarify what I did and did not try, and in the back of my mind, was also thinking that perhaps I was missing something or misunderstood …

:+1:
Just wanted to clarify why my terminology was off

1 Like

Additional note:

If I attach the print-the-path script to the renaming rule itself, as the final action of the rule (after the other actions have renamed the file), the script prints the path rather than an empty string :-).

I think this narrows the problem to something concerning the state of the record while separate rules are executing.

For the time being, inspired by @pete31’s suggestion above about merging scripts in smart rules, I’ve solved my immediate problem by (a) extending the renaming rules to also do what the other rule was supposed to do, and (b) rewriting the other rule to avoid firing when the name pattern matches the conditions in the renaming rule. This approach is suboptimal because it duplicates actions cross rules, but it’ll have to do for now.

You could perhaps use a library to provide the otherwise duplicated code.