Script to insert filename and group path

Short version:

User of DEVONthink 3.
I made a script using Claude. It inserts the filename and the group path inside the RTF document and it can work with multiple selected RTFs at once. It preserves metadata and item links.

I am not sure if it is still good, although it does its job. I would appreciate if someone could take a look at the attached code and if s/he thinks it misses something or alter any functionality of DEVONthink to tell us.

Long story:

I needed a more automated way to insert the filename and the group path inside my rtf notes. I use groups for provenance and tags for topics. I don’t rely on “classify&see also” function (ok. I do like the see also recommendations, but it’s not a big deal if those inserted info mess up a bit with some of the results, it’s not actually that bad), but I do really need to have such info available. I’m an academic, doing research and for my workflow it is very important to be able to tell the source just by looking at the file while being in its topical tag(s). That’s why the group path is important -which is actually mirroring the structure of an archive.

With my nearly non-existing programming capabilities, I started crafting a script to automatically insert the group path and file name in the rtf’s text. Then I realised that this script couldn’t work with multiple selected records. So, I used claude to finalise the script. The first one worked ok, but I noticed it was erasing all the metadata property fields of the rtf files. Then I noticed, that the link I had to another document removed, and as I was trying to write that script using claude, I kept finding new issues and then try and see what works and what not. The last one seems to be fine. It can actually take the filename and group path and insert them on the first two lines. It also preserves the metadata and the links.

My workflow is quite restricted to basics. I don’t -yet- use all the power that DEVONthink has to offer, but I cannot exclude that in the future I won’t. While trying and running all these scripts from claude I saw things that were missing, or went wrong. The final version seems to be ok. But because I don’t have the necessary knowledge to comprehend this script, it would be so much helpful if someone could take a second look on the script, see its structure and if s/he thinks is anything wrong or that it will mess up with some other functionality in DEVONthink, just to point it out.

Thank you so much for your help, I’ve been reading this forum since the 2.xx version of the software!

Here’s the code:

-- Insert File Name and Group Path into RTF Note in DEVONthink 3

-- Works directly on the raw RTF file to preserve metadata, links and annotations

on textToRTF(theText)
	
	set rtfText to ""
	
	repeat with i from 1 to length of theText
		
		set c to character i of theText
		
		set codePoint to id of c
		
		if codePoint is 127 then
			
			set rtfText to rtfText & "\\\\uc0\\\\u" & codePoint & " "
			
		else if c is "\\\\" then
			
			set rtfText to rtfText & "\\\\\\\\"
			
		else if c is "{" then
			
			set rtfText to rtfText & "\\\\{"
			
		else if c is "}" then
			
			set rtfText to rtfText & "\\\\}"
			
		else
			
			set rtfText to rtfText & c
			
		end if
		
	end repeat
	
	return rtfText
	
end textToRTF

tell application id "DNtp"
	
	set theRecords to selection
	
	if theRecords is {} then
		
		display dialog "Please select at least one RTF record first." buttons {"OK"} default button "OK" with icon caution
		
		return
		
	end if
	
	repeat with theRecord in theRecords
		
		if (type of theRecord) is RTF then
			
			-- Get name, strip extension only if there is one
			
			set docName to name of theRecord
			
			set AppleScript's text item delimiters to "."
			
			set nameParts to text items of docName
			
			set AppleScript's text item delimiters to ""
			
			if (count of nameParts) is 1 then
				
				set AppleScript's text item delimiters to "."
				
				set docName to text items 1 thru -2 of docName as string
				
				set AppleScript's text item delimiters to ""
				
			end if
			
			-- Get group path and file path
			
			set groupPath to location of theRecord
			
			set thePath to path of theRecord
			
			-- Read full RTF file
			
			set fileRef to open for access thePath
			
			set rtfContent to read fileRef
			
			close access fileRef
			
			-- Convert name and path to RTF-safe encoding (handles Greek and special chars)
			
			set rtfName to my textToRTF(docName)
			
			set rtfPath to my textToRTF("Path: " & groupPath)
			
			-- Build RTF insert: name, path, blank line
			
			set rtfInsert to rtfName & "\\\\par " & rtfPath & "\\\\par\\\\par "
			
			-- Insert after partightenfactor0 marker
			
			set AppleScript's text item delimiters to "partightenfactor0"
			
			set rtfParts to text items of rtfContent
			
			set AppleScript's text item delimiters to ""
			
			if (count of rtfParts) is 1 then
				
				set newRTF to (item 1 of rtfParts) & "partightenfactor0" & return & rtfInsert & (items 2 thru -1 of rtfParts as string)
				
				set fileRef to open for access thePath with write permission
				
				set eof fileRef to 0
				
				write newRTF to fileRef
				
				close access fileRef
				
			end if
			
		end if
		
	end repeat
	
	display dialog "Done! File name and group path inserted in all selected RTF records." buttons {"OK"} default button "OK"
	
end tell

Welcome @fkoutsopoulos

  1. This is actually one of the worst bits of code I’ve seen. Did you write this in Claude via the web?

  2. I fixed your post. Code should be placed in between a line with three backticks (`) at the beginning and end.

It inserts the filename and the group path inside the RTF document and it can work with multiple selected RTFs at once. It preserves metadata and item links.

There should be no need to preserve anything as a proper script does this easily.
So you’re inserting this information at the top of the document, correct?


PS: Version 3 is in maintenance and will be retired from development and support at some point. Version 4 is the active focus of development. We highly encourage you to upgrade sooner rather than later, if your Mac supports at least macOS Ventura 13.5

2 Likes

Thank you for your hospitality!

  1. Yes, I made this script from claude web version.

  2. Thank you for the tip, I didn’t know how to do this :slight_smile:

    Ok, so you did mention that this is one of the worst bits of code you’ve ever seen. Imagine that its first versions that I discarded were actually recreating the rtf file (i believe it was using the setRTF or something like that) and as a result it kept erasing all the metadata.

    Yes, the info is added on the first top lines of the document.
    —–
    Upgrading will be delayed for a few more months, as our research PI has a different approach on budgeting :smiley:

1 Like

Like so…

And yes, I dressed it up a little to show how to do a bit of styling as well. :slight_smile:

Here is the code to do this, works on multiple selected documents, and error-trapping for only rich text documents…

tell application id "DNtp"
	if (selected records) is {} then return -- No selection, just stop.
	
	set currentDocs to (selected records)
	repeat with theRecord in currentDocs
		if record type of theRecord is in {RTF, RTFD} then
			set databaseName to (name of database of theRecord) -- Get the database's name
			set locationName to (location of theRecord) -- Get the group's name via its location
			set documentName to (name of theRecord) -- Get the name of the document
			
			update record theRecord with text (documentName & return & "Path: " & (databaseName) & " - " & locationName & return & return) mode inserting -- String it all together and update the document's text by inserting it at the top
			
			-- For extra fun with rich text
			tell rich text of theRecord
				set size of paragraphs 1 thru 2 to 12
				bold paragraph 1
				italicize paragraph 2
				bold words 2 thru -1 of paragraph 2
			end tell
		end if
	end repeat
end tell
1 Like

Wow, that was really guick!

And to be honest, much much MUCH slimmer.

Ok, so I tried to run the script and it returned syntax error: Expected end of line, etc. but found class name.

line:
update record theRecord with text (documentName & return & "Path: " & (databaseName) & " - " & locationName & return & return) mode inserting

highlights: record

In Script Editor you don’t use the backticks. Those are for posting code on these forums.

And yes, this is a very trivial thing to script and not beyond the reach of beginners, I’d say.

1 Like

You are most certainly right, i just tried to use the backticks to highlight the line in my post.
The issue is still there though
(I realy need to study some applescript)

Not sure about studying AppleScript, I’d suggest using JavaScript instead.

And what happens if you move the document to another group or duplicate it or replicate it?

Post a screen capture of Script Editor.

PS: For a little extended fun…

			tell rich text of theRecord
				tell paragraphs 1 thru 2
					set size to 14
					set font to "Avenir Next Condensed" -- Family Name in Identifiers in Font Book
					set color to {14265, 32678, 32678} -- Values are 16bit, 0-65535.
				end tell
				bold paragraph 1
				italicize paragraph 2
				bold words 2 thru -1 of paragraph 2
			end tell

And here it is implemented in a batch process…

insert-name-and-path

Woohooooo!!! :smiley:

In general I believe some programming courses would help, in whatever direction and/or language, I should also check about javascript :slight_smile:

In my (claude’s) version of script, there is no change if I move the file to a different directory.
Think my groups structure as a direct mirroring of a physical archive (those that store real paper documents). Those groups I have for provenance are excluded form classifying and are static, as they represent boxes, folders, subfolders of the real physical archive. In order to work with replicants/duplicants etc I need to have that provenance info inside the text.


here is the screenshot

Ugh! Got ahead of myself… the update command is DEVONthink 4.

DEVONthink 4 is much more flexible that DEVONthink 3 but this works for the current record in version 3 and yields the same result…

tell application id "DNtp"
	if (selected records) is {} then return -- No selection, just stop.
	
	set currentDoc to (content record) -- Processes the actively viewed document in DEVONthink 3.
	tell currentDoc
		if type is in {rtf, rtfd} then
			set databaseName to (name of database of it) -- Get the database's name
			set locationName to location -- Get the group's name via its location
			set documentName to name -- Get the name of the document
			
			tell text of it
				make new paragraph at beginning with data (documentName & return & "Path: " & (databaseName) & " - " & locationName & return & return as string)
				
				-- For extra fun with rich text
				tell paragraphs 1 thru 2
					set size to 14
					set font to "Avenir Next" -- Family Name in Identifiers in Font Book
					set color of words to {14265, 32678, 32678} -- Values are 16bit, 0-65535.
				end tell
				bold paragraph 1
				italicize paragraph 2
				bold words 2 thru -1 of paragraph 2
			end tell
		end if
	end tell
end tell

Check it out @fkoutsopoulos . Select a rich text document and run it. The location should not matter.

3 Likes

So, in DT3, you’d have to add the text in front of the existing RTF as a new paragraph?

Or perhaps putting the path and name in a user metadata field would be easier.

So, in DT3, you’d have to add the text in front of the existing RTF as a new paragraph?

Yep!

Or perhaps putting the path and name in a user metadata field would be easier.

Also possible and an avenue I would go down personally. :smiley:

Hah, that’s ok! :smiley:
Good news is that I already have the script, so in the next few months during our upgrade, I would be ready.

Wow, I just saw and tried your new script! It works like charm!
To be honest, I’m really envy of that capibility you have to draft so quick scripts :smiley:

This is really good, thank you so much!

You’re welcome and you obviously can remove or modify the formatting tell… end tell block as you wish. It’s really just to show how simple things like this can be accomplished fairly easily.

PS: It’s also possible to extend this to handle multiple documents, etc. but I strongly recommend you use this version for a bit and assess its usefulness.

1 Like

Well, now that I have a proper script, I’ll try to study it alongside with applescript, because it is crucial for some automated work. Maybe I’ll try messing up with the metadata fields, just to see how it goes.
Also, I’ll try to play a bit with the formating :smiley:

Thanks again!

1 Like

Using metadata fields has the advantage that it works regardless of the file format. More flexible.

1 Like

There’s always the problem of sharing those files. If the recipient doesn’t use DEVONthink, it will be quite hard to retrieve the info stored in those fields. I haven’t yet find a more viable workaround. Otherwise, regular and custom metadata would be the way to go, that’s for sure!

Maybe I’ll take some time to post a complete description of usage scenario/workflow. But, I think I’ll wait for the upgrade, because as I can see there are lots of stuff that I’m missing right now.

If the recipient doesn’t use DT, what good does the group name do them? And the file name … is the file name and implicitly shared anyway.