Modifying the item link copied to the clipboard

Using Copy Item Link in DEVONthink 3 on an item in a database does not simply copy a text string to the macOS clipboard/pasteboard: it copies an object containing the URI of the item and additional information including the title of the item in DEVONthink. You can get a sense for what this is in AppleScript using the clipboard scripting extension:

use AppleScript version "2.4"
use scripting additions
display dialog (clipboard info) as string

If I use Copy Item Link over a PDF document in DEVONthink, then immediately run the script above, I will get something like this:

The is great and works well in other application such as OmniOutliner, because if I then paste the contents of the clipboard, OmniOutliner will not simply insert the link text in my document, but a named link, i.e., one that has the name of the DEVONthink document as a title instead of “x-devonthink://…”. This is very convenient!

Now I want to modify the link destination by adding ?reveal=1 to it. How can I do this without destroying the pasteboard object’s structure?

I haven’t been able to figure out how to do it in AppleScript; the clipboard scripting addition does have a set the clipboard to action, which is presumably what I would need to use but I don’t know enough AppleScript to figure out how to modify the object currently in the clipboard so that I can hand that to set the clipboard.

Using the command-line utilities pbcopy and pbpaste as part of a pipeline to do this doesn’t work, because they end up converting the contents to plain text. Using Python and the pasteboard package doesn’t work because it only supports a subset of pasteboard data types. I think it could be done using PyObjC, but it would require figuring out the NSPasteboard and relevant Objective-C code, which I could learn but I frankly don’t relish spending the hours needed to do that, just to implement a way to add 9 characters to the clipboard.

Has anyone done something similar, or knows of a way to properly manipulate clipboard objects in AppleScript, JavaScript, Python, or Keyboard Maestro?

I use this is an applecsript:
set itemLink to reference URL of theRecord

and it provides a usable and modifiable link. You could add link syntax so it does not show up as a raw URL.

See this post:

Thanks for your reply. I use the reference URL in other AppleScript code. As far as I can tell, the value is simply a text string. I can’t quite figure out what “add link syntax so it does not show up as a raw URL” means. Can you please elaborate?

Some further investigation of the nature of the clipboard object created by DEVONthink has narrowed down what I need to figure out. Here’s an example of the clipboard contents created by Copy Item Link:

«class utf8»:"x-devonthink-item://7F634811-B289-49F4-A085-93212C3720F0", 
URL:«data url 782D6465766F6E7468696E6B2D6974656D3A2F2F37463633343831312D423238392D343946342D413038352D393332313243333732304630», 
«class urln»:«data urln6D616E6167696E6773686172696E67», 
«class ut16»:"x-devonthink-item://7F634811-B289-49F4-A085-93212C3720F0", 
Unicode text:"x-devonthink-item://7F634811-B289-49F4-A085-93212C3720F0"

So my problem is reduced to creating a «data url ...» element and a «class urln»:«data urln....» element somehow. The problem is the data types, not the content: it’s kind of obvious what the content of these items are, but how do I create the right data classes?

Does anyone have tips on how to create such things programmatically (preferably AppleScript, JavaScript, Python, or shell script)?

Never mind, I’m an idiot. Those are obvious hex-encoded values, and indeed if I try to decode the values, I get readable strings. Knowing this, the process of generating new values is easy now.

Try this Script: Modify x-devonthink item links to reveal records

1 Like

I’m coming in late to the party. Care to share your solution?

Care to share your solution?

I had not yet written a full implementation when I wrote that last comment (it was late in my time zone), but had gotten far enough to figure out that the following worked,

set theURL to «data url 782D6465766F6E7468696E6B2D6974656D3A2F2F37463633343831312D423238392D343946342D413038352D393332313243333732304630»
set theTitle to «data urln6D616E6167696E6773686172696E67»
set the clipboard to {URL:theURL, «class urln»:theTitle}

My plan was to use AppleScript to get the URL and title from a selected record in DEVONthink, and convert the title and URI to hex using a hex-to-string conversion routine posted by someone else to another forum in 2013. However, @pete31 posted a more general solution to the whole problem before I got to that, so I never finished :slight_smile: .

Trying it quickly right now, it doesn’t appear to be syntactically straightforward to create those «data ...» values directly from AppleScript. I’m curious if anyone knows how it could be done? I.e., given a string X, how does one directly create an AppleScript value «data X»? (@pete31’s solution avoids the issue by going about it in a different way – it doesn’t create the clipboard object de novo, but instead, rummages inside an existing object and selectively modifies specific field values.)

See Convert NSData into raw data string if you also need to convert AppleScript data into NS data.

-- Convert text to data

use AppleScript version "2.4"
use framework "Foundation"
use scripting additions

set theText to "Hello World"
set theString to (current application's NSString's stringWithString:theText)
set theDataNS to theString's dataUsingEncoding:(current application's NSUTF8StringEncoding)
set theDataAS to my ASDataFromData:theDataNS
--> «data rdat48656C6C6F20576F726C64»

on ASDataFromData:theData
	set theCode to current application's NSHFSTypeCodeFromFileType("'rdat'")
	return (current application's NSAppleEventDescriptor's descriptorWithDescriptorType:theCode |data|:theData) as data
end ASDataFromData:
1 Like