Scripting question: update name of selected item link

I would like to have a version of the command “Update Name of Item Links” (under Tools > Item Links) that work only on a selected link, not all links in the document. So I am trying to write a script to do this, but ran into an issues.

To start, I found an AppleScript by @BLUEFROG that simulates the Update Name of Item Links. I modified it to step through each link and confirm if you want to change it or not. This works fine, but is not good for long documents with many links, because you cannot where the link appears in the text to make your decision.

I’d like to make a script that only modifies the selected link, but I can’t figure out if this is possible. When I try to process selected text, it gets stripped of the RTF attributes, so that’s no good.

Anyone have any ideas?

Here’s what I have right now:

tell application id "DNtp"
	
	-- Get the selected file
	set sel to content record
	
	-- Only process rich text files
	if (type of sel = RTF) or (type of sel = RTFD) then
		
		-- Process attribute runs (blocks of text grouped by common attributes) in the text
		repeat with textBlock in (attribute runs of rich text of sel)
			
			-- Check if the current block has a URL
			if exists (URL of textBlock) then
				
				-- Cache the URL of the current block in a variable
				set currentURL to (URL of textBlock)
				
				-- Check if the URL is a DEVONthink item link
				if currentURL begins with "x-devonthink-item://" then
					
					-- If so, cache the text of the current block in a variable
					set currentText to rich text of textBlock
					
					-- Strip the "x-devonthink-item://" from the URL
					set currentURL to (characters 21 thru -1 of currentURL) as string
					
					-- if the linked record no longer exists, remove it
					if not (exists (get record with uuid currentURL)) then
						beep
						display dialog "Link for '" & currentText & "' is broken. Removing it." buttons {"ok"} default button 1
						set (URL of textBlock) to ""
					else
						-- if linked record exists, continue...	
						
						-- Get the linked record
						set linkedRecord to (get record with uuid currentURL)
						
						-- Get the name of the linked record
						set linkName to (name of linkedRecord)
						
						-- Check if the name of the linked file matches the text of the current block
						if linkName ≠ currentText then
							-- ask if you want to update this link
							set this_line to the current line of current tab of think window 1
							
							set question to "Do you want to update the name of this link?" & return & return & "NOW:  " & currentText & return & "NEW:  " & linkName
							set options to {"no", "yes"}
							set answer to the button returned of (display dialog question buttons the options default button 1)
							
							if answer = "yes" then
								-- If the name and text don't match, update the text to the name of the linked record
								set rich text of textBlock to linkName
							end if
						end if
					end if
					
				end if
			end if
		end repeat
	end if
end tell

Basically, you want to access the currently selected text. I never found a possibility to do that in scripting. Perhaps @BLUEFROG or @cgrunenberg know more about it. But the selection is probably only accessible in an event-driven GUI app.

Assuming that the currently selected text in the frontmost window is a link in an RTF document, then this script just replaces the text, not the link:

tell application id "DNtp"
	set text content of selected text of think window 1 to "Test"
end tell

Ah, cool. And I see that this lets me grab the URL of that selected link:

set currentURL to (URL of selected text of think window 1)

This give me a start, thanks!

Here’s my next version, which is now working. If you select a link in the text and run this script, it will confirm if the link’s text matches the filename it links to. If not, it asks if you want to update it.

tell application id "DNtp"
	
	set currentText to text content of selected text of think window 1
	if currentText = "" then error "Please select some text."
	
	set currentURL to (URL of selected text of think window 1)
	
	-- Check if the current block has a URL
	if not (currentURL = "") then
		
		-- Check if the URL is a DEVONthink item link
		if currentURL begins with "x-devonthink-item://" then
			
			-- Strip the "x-devonthink-item://" from the URL
			set currentURL to (characters 21 thru -1 of currentURL) as string
			
			-- if the linked record no longer exists, remove it
			if not (exists (get record with uuid currentURL)) then
				beep
				display dialog "The link for '" & currentText & "' is broken. Removing it." buttons {"ok"} default button 1
				set (URL of selected text of think window 1) to ""
				
			else
				-- if linked record exists, get the name of the linked record
				set linkedRecord to (get record with uuid currentURL)
				set linkName to (name of linkedRecord)
				
				-- if the name of the selected link does not match, ask if you want to update it
				if linkName ≠ currentText then
					set question to "Do you want to update the text of this link to match the filename it links to?" & return & return & "Change this:  " & currentText & return & "To filename:  " & linkName
					set options to {"no", "yes"}
					set answer to the button returned of (display dialog question buttons the options default button 1)
					if answer = "yes" then
						set text content of selected text of think window 1 to linkName
						beep
					end if
				else
					display dialog "This link already matches the file name it links to." buttons {"ok"} default button 1
				end if
			end if
		else
			-- if the URL is NOT a DEVONthink item link
			display dialog "This link does not point to a DevonThink document." buttons {"ok"} default button 1
			
		end if
		
	end if
	
end tell

I still have to clean this up a bit, but this is great. Thanks @BLUEFROG for my start, and @cgrunenberg for pointing me in the right direction!

1 Like

You’re welcome. Frequently it’s still better to ask the creators (or other experts on this forum) than to ask AI… :wink:

2 Likes

Yes, I did try AI, just to see. Woof. (“Oh, I’m sorry you are right that would not work, let me try again….”).

Next step: I just added my script to MacOS’s Quick Actions (using Automator), and now I can right-click on a link, and update it from the popup menu. Sweet.

1 Like