Move Here / Replicate Here scripts

I love Finder’s Copy (Cmd-C) / Move Here (Cmd-Opt-V) workflow so I prepared two scripts that bring this behavior to DT3 – both for moving and for replicating records.


Move Here (My keyboard shortcut: Cmd-Opt-V just like in Finder)

Workflow:

  • Copy a record or multiple records (i.e. via Cmd-C).
  • Navigate to the target group.
  • Use the script to move copied records to that group.
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

set pb to current application's NSPasteboard's generalPasteboard() -- get pasteboard
set pbData to pb's dataForType:"dyn.ah62d4rv4gu8y6y4grf0gn5xbrzw1gydcr7u1e3cytf2gn"
if pbData is not missing value then
	set plist to current application's class "NSPropertyListSerialization"'s propertyListWithData:pbData options:0 format:100 |error|:0
	set filePaths to plist as list
end if

tell application id "DNtp"
	
	try
		
		if pbData is missing value then display alert "DEVONthink" message "No copied records found" as warning
		
		set viewerRoot to root of viewer window 1
		try
			viewerRoot
		on error number -2753
			set viewerRoot to root of inbox
		end try
		
		set newSelection to {}
		
		repeat with filePath in filePaths
			
			set AppleScript's text item delimiters to {".dtBase2"}
			set textItems to text items of filePath
			set dbPath to first item of textItems & ".dtBase2"
			
			set db to open database dbPath
			
			set recs to lookup records with path filePath in db
			if (count of recs) is 0 then display alert "DEVONthink" message "No records found" as warning
			
			repeat with rec in recs
				set movedRec to move record rec to viewerRoot
				set end of newSelection to movedRec
			end repeat
			
		end repeat
		
		set selection of viewer window 1 to newSelection
		
	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

Replicate Here (My keyboard shortcut: Cmd-Shift-Opt-V)

Workflow:

  • Copy a record or multiple records (i.e. via Cmd-C).
  • Navigate to the target group.
  • Use the script to replicate copied records to that group.
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

set pb to current application's NSPasteboard's generalPasteboard() -- get pasteboard
set pbData to pb's dataForType:"dyn.ah62d4rv4gu8y6y4grf0gn5xbrzw1gydcr7u1e3cytf2gn"
if pbData is not missing value then
	set plist to current application's class "NSPropertyListSerialization"'s propertyListWithData:pbData options:0 format:100 |error|:0
	set filePaths to plist as list
end if

tell application id "DNtp"
	
	try
		
		if pbData is missing value then display alert "DEVONthink" message "No copied records found" as warning
		
		set viewerRoot to root of viewer window 1
		try
			viewerRoot
		on error number -2753
			set viewerRoot to root of inbox
		end try
		
		set newSelection to {}
		
		repeat with filePath in filePaths
			
			set AppleScript's text item delimiters to {".dtBase2"}
			set textItems to text items of filePath
			set dbPath to first item of textItems & ".dtBase2"
			
			set db to open database dbPath
			
			set recs to lookup records with path filePath in db
			if (count of recs) is 0 then display alert "DEVONthink" message "No records found" as warning
			
			repeat with rec in recs
				set movedRec to move record rec to viewerRoot
				set end of newSelection to movedRec
			end repeat
			
		end repeat
		
		set selection of viewer window 1 to newSelection
		
	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

Thanks for sharing these scripts! However, I wouldn’t recommend usage of dynamic pasteboard types as these might change depending on the macOS version. Here’s a revised version which simply uses NSFilenamesPboardType:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

set pb to current application's NSPasteboard's generalPasteboard() -- get pasteboard
set filePaths to (pb's propertyListForType:"NSFilenamesPboardType") as list

tell application id "DNtp"
	try
		if filePaths is missing value then error "No copied records found" as warning
		...	
	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	
2 Likes

Indeed! What’s worse though is that a file path based solution (like the one I wrote initially and the one you fixed) does not work for selected groups (as they don’t seem to be mapped to folders in the filesystem). So it seems there’s no alternative to parsing a dictionary from another dynamic pasteboard type.

Here’s an updated version of the scripts – works both for file records and for groups.

Move Here

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

set itemUUIDs to {}

set pb to current application's NSPasteboard's generalPasteboard() -- get pasteboard
set pbData to pb's dataForType:"dyn.ah62d4rv4gu8ykzcmsvw04xdmr3z1gydcr7u1e3cytf2gn"

if pbData is not missing value then
	set plist to current application's class "NSPropertyListSerialization"'s propertyListWithData:pbData options:0 format:100 |error|:0
	set itemDicts to plist as list
	repeat with itemDict in itemDicts
		set itemUUID to itemDict's |URL| as string
		set end of itemUUIDs to itemUUID
	end repeat
end if

tell application id "DNtp"
	
	try
		
		if pbData is missing value then display alert "DEVONthink" message "No copied records found" as warning
		
		set viewerRoot to root of viewer window 1
		try
			viewerRoot
		on error number -2753
			set viewerRoot to root of inbox
		end try
		
		set newSelection to {}
		
		repeat with itemUUID in itemUUIDs
			
			set rec to get record with uuid itemUUID
			set movedRec to move record rec to viewerRoot
			set end of newSelection to movedRec
			
		end repeat
		
		set selection of viewer window 1 to newSelection
		
	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

Replicate Here

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

set itemUUIDs to {}

set pb to current application's NSPasteboard's generalPasteboard() -- get pasteboard
set pbData to pb's dataForType:"dyn.ah62d4rv4gu8ykzcmsvw04xdmr3z1gydcr7u1e3cytf2gn"

if pbData is not missing value then
	set plist to current application's class "NSPropertyListSerialization"'s propertyListWithData:pbData options:0 format:100 |error|:0
	set itemDicts to plist as list
	repeat with itemDict in itemDicts
		set itemUUID to itemDict's |URL| as string
		set end of itemUUIDs to itemUUID
	end repeat
end if

tell application id "DNtp"
	
	try
		
		if pbData is missing value then display alert "DEVONthink" message "No copied records found" as warning
		
		set viewerRoot to root of viewer window 1
		try
			viewerRoot
		on error number -2753
			set viewerRoot to root of inbox
		end try
		
		set newSelection to {}
		
		repeat with itemUUID in itemUUIDs
			
			set rec to get record with uuid itemUUID
			set movedRec to replicate record rec to viewerRoot
			set end of newSelection to movedRec
			
		end repeat
		
		set selection of viewer window 1 to newSelection
		
	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

I’ll keep using these scripts and providing fixed versions in case any macOS internals change.

In that case the internal type DevonThinkRecordPboardType would be a better solution, it’s actually intended for third-party apps like Tinderbox and contains a list of UUIDs:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

set pb to current application's NSPasteboard's generalPasteboard() -- get pasteboard
set itemUUIDs to (pb's propertyListForType:"DevonThinkRecordPboardType") as list

tell application id "DNtp"
	try
		if itemUUIDs is missing value then error "No copied records found"

Great tip! I’ve updated the scripts:

Move Here

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

set pb to current application's NSPasteboard's generalPasteboard() -- get pasteboard
set itemUUIDs to (pb's propertyListForType:"DevonThinkRecordPboardType") as list

tell application id "DNtp"
	
	try
		
		if itemUUIDs is missing value then error "No copied records found"
		
		set viewerRoot to root of viewer window 1
		try
			viewerRoot
		on error number -2753
			set viewerRoot to root of inbox
		end try
		
		set newSelection to {}
		
		repeat with itemUUID in itemUUIDs
			
			set rec to get record with uuid itemUUID
			set movedRec to move record rec to viewerRoot
			set end of newSelection to movedRec
			
		end repeat
		
		set selection of viewer window 1 to newSelection
		
	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

Replicate Here

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

set pb to current application's NSPasteboard's generalPasteboard() -- get pasteboard
set itemUUIDs to (pb's propertyListForType:"DevonThinkRecordPboardType") as list

log itemUUIDs

tell application id "DNtp"
	
	try
		
		if itemUUIDs is missing value then
			display dialog "a"
			error "No copied records found"
		end if
		
		set viewerRoot to root of viewer window 1
		try
			viewerRoot
		on error number -2753
			set viewerRoot to root of inbox
		end try
		
		set newSelection to {}
		
		repeat with itemUUID in itemUUIDs
			
			set rec to get record with uuid itemUUID
			set replicatedRec to replicate record rec to viewerRoot
			set end of newSelection to replicatedRec
			
		end repeat
		
		set selection of viewer window 1 to newSelection
		
	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