Script for opening an indexed file or folder/group in DEVONthink from an external app (e.g., Finder, Alfred, HoudahSpot, etc.)?

I only have a quick look at the script and my beginners’ comment as follows:

(1) remind you that DT only look up records in “databases” that are opened. So u need to make sure that all databases remain opened when u run the script or the script will only search in the currently opened database.

(2) logic: if file/s are index into different databases and your script is telling the viewer window to display the file/group in current window. And if you have more than one records in theResults (or same finder’s file in different databases), the script won’t know which one or where to open? You will need to look into the variable theResults to see what items have you retrieved by using the lookup command (I rarely used it) to get a better feel. Use “script debugger” with a free trial period for 15 days (I think) for debugging. The app can run script step-by-step and show the values/records/items in each var in the process in a user-friendly manner.

(3) if you have tagged ur item/s in DT, parent 1 of theResults can be a tag or a group (AFAIMA, there is no fixed rule to determine which one is parent 1, probably based on the time of the creation of each replicant?). That’s why I open a document window for theResults. You may need some code to find all parents of theResults and find the first Parents n that is a group. (This I am not 100% sure)

Might it be possible (via script) for DT to cache a list of all indexed files in a database on close or modification? Then the script can read that file to find files that aren’t open.

@ngan Thanks a ton for the helpful feedback. My intention was to only use the script with one file at time (via a file action in Alfred, which I’ve restricted to a single input). However, you hit the nail on the head with your third point! That explains the weird behavior that I noticed with the “reveal” script that I posted above. In short, occasionally it will errantly reveal the file or group in the Sidebar’s Tags (Globals section) or from the Favorites section (when the group is also located there). Do you know how to restrict it to only selecting the parent (group) from the Open Databases section?

Thanks again to everyone for all of your help!

@korm would have suggested to learn the trick by reading the dictionary or from other script… (for good intention).

Look for one line of code in this post as a starting point?

Find & Goto parent groups of all replicants of an item

1 Like

Take a look at A script library to get the path of the frontmost document

And maybe this Script: Open DEVONthink record for PDF Expert tab

1 Like

@pete31 - Thanks for your help. Ironically, your PDF Expert script was super helpful for fixing a different issue. I created a far more simplistic version of your script a few years ago to work with Alfred for shifting between active PDF documents (PDF Expert, Preview, Adobe Acrobat). I could never figure out how to do it efficiently with PDF Expert (because of its lack of Apple Script support) without running it through Alfred’s search, which never worked particularly well (because it was GUI-based). In any case, your solution with PDF Expert was genius (LSOF - etc.)! It completely solved that problem. Now that script works amazing!

As for this issue, while I’m probably overlooking something, it’s the later part of the problem that I’m struggling with (i.e., how to reveal what you’ve found). Instead of opening the file in DEVONThink, how do I consistently reveal it in the same active window (without opening a new window)? The script that I posted above works in most situations, but will sometimes select the file from the sidebar if its group is located in the Tags or Favorites sections (not the Open Databases section, where it should). Any ideas how to get it to reveal the file or group (instead of open it)?

Thanks again to everyone for all of their help!

This version shows the contents of a group or previews a record

-- opens the file or group in DEVONthink’s current viewer window (selecting/highlighting the file and previewing it, or in the case of groups, showing their contents)

tell application "Finder"
	set theSelection to selection as alias list
end tell

if theSelection ≠ {} then
	set theFile to first item of theSelection
	set theFilePath to POSIX path of (contents of theFile)
end if

tell application id "DNtp"
	try
		set theDatabases to databases
		set theResults to {}
		repeat with thisDatabase in theDatabases
			set thisDatabasesResults to lookup records with path theFilePath in thisDatabase
			set theResults to theResults & thisDatabasesResults
		end repeat
		if theResults = {} then
			display notification "Pfad nicht in offenen Datenbanken enthalten!" with title "Lookup DEVONthink"
			return
		else
			
			set theRecord to (item 1 of theResults)
			
			if type of theRecord = group then
				set root of viewer window 1 to theRecord
				set selection of viewer window 1 to theRecord
				activate
			else
				set root of viewer window 1 to (parent 1 of theRecord)
				set selection of viewer window 1 to (theRecord as list)
				activate
			end if
			
		end if
	end try
end tell

And this reveals a record

-- reveals the file or group, similar to how “reveal” works from the context menu of a search result

tell application "Finder"
	set theSelection to selection as alias list
end tell

if theSelection ≠ {} then
	set theFile to first item of theSelection
	set theFilePath to POSIX path of (contents of theFile)
end if

tell application id "DNtp"
	try
		set theDatabases to databases
		set theResults to {}
		repeat with thisDatabase in theDatabases
			set thisDatabasesResults to lookup records with path theFilePath in thisDatabase
			set theResults to theResults & thisDatabasesResults
		end repeat
		if theResults = {} then
			display notification "Pfad nicht in offenen Datenbanken enthalten!" with title "Lookup DEVONthink"
			return
		else
			
			set theRecord to (item 1 of theResults)
			
			set root of viewer window 1 to (root of (database of theRecord))
			set selection of viewer window 1 to (theRecord as list)
			activate
			
		end if
	end try
end tell

For testing I used a folder which I indexed in two databases but without tagging or replicating the group. It seems the scripts will always use the record in the database that was last used.

Have you tried the script library? With this it’s possible to open a DEVONthink record from a lot of apps, not only Finder

2 Likes

@pete31 Thanks a ton! These scripts are amazing, and I can now see what I was screwing up in the “reveal” script previously. I can’t thank you enough!

In the reveal script, by chance, is it possible to have DEVONthink select the parent folder/group in the Sidebar, too? At the moment, it selects the database - which fixes the problem I mentioned above about errantly selecting from the Tags or Shortcuts sections of the Sidebar - however, it doesn’t drill down any further in the Sidebar to let the user know they’re at in the hierarchy (based on the Sidebar alone - i.e., obviously you can still see it in the main window, however).

While I understand that you can’t select the actual file or group in the Sidebar (or else it would open the group, instead of just revealing it), I like the idea of quickly seeing where I’m at from the Sidebar by at least selecting its parent folder. In addition, it also makes it easier to subsequently run a search on a group that is in close proximity to the file/group you just revealed (which, in DT3, from what I understand, always requires you to actually select the group in the sidebar).

To accomplish this, I tried adding the “parent” line from your “open” script, but that didn’t change it’s end result:

		set theRecord to (item 1 of theResults)
		set root of viewer window 1 to (parent of (database of theRecord)) -- ADDED !!
		set root of viewer window 1 to (root of (database of theRecord))
		set selection of viewer window 1 to (theRecord as list)
		activate

The hope was that it would first select the parent folder/group from the sidebar, leaving it expanded, before revealing the actual file/group. However, it seems to behave the same way (never expanding the database from sidebar). Is this possible?

I haven’t tried your script library yet. It’s probably a little beyond my skill set at the moment (AppleScript and DEVONthink). However, I’ll definitely take a look at it now!!! Thanks for sharing! Another part of the reason that I haven’t, is that I’m not quite as dependent on Finder, as this script might seem. I included Finder because I felt like it would be most helpful for other DT newbies, like myself. In fact, I’m still pretty surprised there isn’t a MacOS service included in DT3 that does the same thing (at least for those who prefer to go the index route, it feels like a must). In any case, as an Alfred user, it’s not as difficult to do similar things from other apps, like HoudahSpot, etc. Thanks again for all of your help!! I really appreciate it.

It’s only UI scripting (as I didn’t find another way) and it’s a little bit slow… But maybe that helps if your folder hierarchy isn’t “too deep”

-- reveals the file or group, similar to how “reveal” works from the context menu of a search result
-- expands the sidebar (but only with UI scripting so it's quite slow)

tell application "Finder"
	set theSelection to selection as alias list
end tell

if theSelection ≠ {} then
	set theFile to first item of theSelection
	set theFilePath to POSIX path of (contents of theFile)
end if

tell application id "DNtp"
	try
		set theDatabases to databases
		set theResults to {}
		repeat with thisDatabase in theDatabases
			set thisDatabasesResults to lookup records with path theFilePath in thisDatabase
			set theResults to theResults & thisDatabasesResults
		end repeat
		if theResults = {} then
			display notification "Pfad nicht in offenen Datenbanken enthalten!" with title "Lookup DEVONthink"
			return
		else
			
			set theRecord to item 1 of theResults
			
			set root of viewer window 1 to root of database of theRecord
			set selection of viewer window 1 to theRecord as list
			activate
			
			set thisParent to parent 1 of theRecord
			set theParents to {} & name of thisParent
			repeat until thisParent = root of database of theRecord
				set thisParent to parent 1 of thisParent
				set beginning of theParents to name of thisParent
			end repeat
			
			if type of theRecord = group then
				set isGroup to true
			else
				set isGroup to false
			end if
			
			tell application "System Events" -- expand sidebar with UI scripting
				tell process "DEVONthink 3"
					try
						repeat with thisGroup in theParents
							set thisGroupName to contents of thisGroup
							set theUIElement to (a reference to (UI element 2 of UI element 1 of (first row of outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of window 1 whose value of static text 1 of UI element 1 is thisGroupName)))
							if value of theUIElement = 0 then -- database / group is closed
								click theUIElement
								delay 0.15
							end if
						end repeat
						
						if isGroup = true then
							select (first row of outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of window 1 whose value of static text 1 of UI element 1 is (name of theRecord))
						else
							select (first row of outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of window 1 whose value of static text 1 of UI element 1 is (item -1 in theParents))
						end if
						
					on error
						if isGroup = true then
							select (first row of outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of window 1 whose value of static text 1 of UI element 1 is (name of theRecord))
						else
							select (first row of outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of window 1 whose value of static text 1 of UI element 1 is (item -1 in theParents))
						end if
					end try
				end tell
			end tell
		end if
		
	on error error_message number error_number
		if the error_number is not -128 then display alert "DEVONthink" message error_message as warning
		
	end try
end tell

Perhaps @cgrunenberg would consider this a feature request?

1 Like

@pete31 Thanks for taking a crack at it. I really appreciate it.

Unfortunately, I think it might be time to throw in the towel on this one. I added a couple of short delays to help get rid of the errors, but the new script only seems to work intermittently. It also clicks the wrong things in the sidebar sometimes (e.g., Tags or Favorites sections, instead of Open Databases). Thanks for trying though. Can’t tell you how much I appreciate it!!

Assuming it’s not possible to do what I described previously, how do people quickly search within a given group?

It seems odd to require selection in the sidebar to search within a specific group (using search prefix - scope:selection), if you can’t also script it (or at least rely on the selection within main viewer (i.e., instead of sidebar’s selection). While I prefer to see the sidebar expand when revealing the file/folder/group anyways - to have a better sense of location or geography in the database’s hierarchy - it seems to make even more sense, given its importance to subsequent searches. I’ll keep my fingers crossed they address this one in the next beta…

Thanks again!

But that’s what you experienced before. :wink: While testing with a real database (no indexed files) I’ve also found that I couldn’t figure out which replicant would reveal. That’s something the DEVONthink people could comment on (would be very interesting to learn the logic behind it).

+1

Wonder how do you even set this up in KM……

The macro is triggered from a conflict menu that appears only in Finder. The script I posted is located inside the “Execute Applescript” action in the macro shown below.

The macro loops through each selected file in a selection (the “collection”). Of course a collection can have one member – the single selected file – or multiple.

Thank you.

Looks interesting k o r m.

Im new to KM so I have to find my way around. I thought it was just adding the script to Keyboard Maestro lol

I was wondering if I could get the group’s help with this script again? By way of reminder, one of the scripts that I originally posted was intended to “reveal” files from Finder in a new DEVONthink window (first, find the file in DEVONthink; then, open a new window for its parent folder/group in DEVONthink; finally, select the file in the new DEVONthink window). However, I’ve never been able to figure out how to get this particular script to work with more than one file at a time.

In the script below, it seems clear to me that the problem lies in the way that I’ve set the window (when opening it and setting its selection). However, I’ve never understood how to deal with this issue in DEVONthink. Because I’ve set the window’s name, in order to make a selection, when there is more than one file, they all open in the same window. Does anyone know how to fix those last couple lines of code, so that each file opens in its own window and is selected appropriately (i.e., the lines beginning with “set theWindow…”)?

Thanks again for all of your help!! To make things easy for everyone, I’ve also uploaded the script here: Download Script.

tell application "Finder"
	set theSelection to selection as alias list
end tell

if theSelection ≠ {} then
	set my text item delimiters to tab
	set theFilePaths to {}
	repeat with i in theSelection
		set end of theFilePaths to POSIX path of (contents of i)
	end repeat
end if

if theFilePaths ≠ {} then
	repeat with i in theFilePaths
		tell application id "DNtp"
			try
				set theDatabases to databases
				set theResults to {}
				repeat with thisDatabase in theDatabases
					set thisDatabasesResults to lookup records with path i in thisDatabase
					set theResults to theResults & thisDatabasesResults
				end repeat
				if theResults is not {} then
					set theResultsParent to (first parent of first item of theResults)
					set theWindow to open window for record theResultsParent
					set theWindow's selection to theResults
				else
					display alert "the file/group does not exist in the current DT database"
				end if
			end try
		end tell
	end repeat
end if

I’ve no idea at the moment why your script doesn’t work over here but maybe using a “dummy” record in your global inbox to create new windows will do what you want to do

set newWindow to open window for record (get record with uuid "1A2A6304-21C2-4B7F-9932-3956C799462B") -- "dummy" record uuid
		
set record of newWindow to theResultsParent -- https://discourse.devontechnologies.com/t/set-record-for-window-random-article/8256/2?
		
activate
1 Like

Hi @pete31 - Thanks for taking a look at this for me. It’s had me puzzled, in large part, because it seems like it should be easy enough to do in DEVONthink (especially since I can do it with one file without any problems).

I tried your suggestion but, unfortunately, was not able to have any luck with it. I might be doing something wrong, but, on my end, your amendment to the script just opens the dummy file (i.e., it doesn’t open the parent group in a new window and then select/highlight the file in the window - similar to how you might “reveal” it from search results, etc.). Thanks for taking a crack at it though.

Sorry I missed that you want a selection. This should work (but I didn’t try it in a repeat loop)

set newWindow to open window for record incoming group
set root of newWindow to root of (database of theResultsParent)
set selection of newWindow to theResultsParent as list
activate
1 Like

Ok I tried a repeat loop - and all windows appear over each other.

As you (probably) want to have them visible try something like this (but you’ll have to experiment on your own)

tell application id "DNtp"
	try
		set theBounds to bounds of window 2
		set bounds of window 1 to {(item 1 of theBounds) + 22, (item 2 of theBounds) + 22, ((item 3 of theBounds) + 22), (item 4 of theBounds) + 22}
	on error error_message number error_number
		if the error_number is not -128 then display alert "DEVONthink" message error_message as warning
	end try
end tell
1 Like

@pete31 I can’t thank you enough!! It works!! This has been driving me crazy for so long. Thank you so much for all of your help!! You’re the best.

I made one very small change to your code so that the target file is selected in DEVONthink, and not its parent. So for others who are looking to mimic a “reveal” like action for files, especially when dealing with indexed files, the following works (i.e., substitute these lines with the ones you see in my previous post above):

				if theResults is not {} then
					repeat with theRecord in theResults
						set theResultsParent to (first parent of first item of theResults)
						set newWindow to open window for record incoming group
						set root of newWindow to root of (database of theResultsParent)
						set selection of newWindow to theResults as list
						activate
					end repeat
				else

I’ve also uploaded the full working version of the script here: Download. If you index files in Finder and want to quickly reveal them in DEVONthink, this script is great! And, if you’re an Alfred user, it’s very easy to just add the second half of the script to a workflow’s file action, making things even more convenient!

@pete31 I haven’t tried setting the bounds of the windows yet (in order to avoid the overlap issue). That’s a great idea for improving the script! I’ll tinker around with it a bit. To be honest, just opening the window is more than enough for me, however! You’re a lifesaver. I really appreciate your help with everything!