Assigning tags to records within a smart "tags" group

Let’s say you have a group, called “Tags”, in which you’ve created a bunch of topical folders. You have a habit of replicating records within these folders as a form of tagging.

This works well within DEVONthink, but it doesn’t help at the Finder, which doesn’t know anything about DTP’s folder-based tagging approach.

To bridge this gap, I’ve written a Smart Groups script which will auto-tag any records which occur within sub-groups of your Tags group. For example, say you had this hierarchy:

Tags

  • Python
  • Emacs

Later, you use DTP’s Classify feature to replicate a web clipping into both of these groups. Wouldn’t it be nice if the Python records had a “&python” tag automatically inserted into their comment field, so that you could use this information when doing a Spotlight search?

The attached script works by associating it with the parent “Tags” group. Whenever you click on the group, it runs the script and synchronizing your tagged records. Anything in Python gets tagged “&python” – in addition to whatever other tags it may have. Additionally, if you move a record from Python to Emacs, the old &python tag will be removed and a new &emacs tag put in its place.

This scheme lets you do comment-based tagging using just drag-and-drop and replication, with a script trigger at the end to assign your group names as tags to their child records.

Phew… maybe that didn’t make much sense at all. It’s really a lot simpler than it sounded! If you have questions, I’ll be happy to answer them.

John

on triggered(theRecord)
	try
		tell application "DEVONthink Pro"
			set thisPath to (location of theRecord & name of theRecord & "/")
			
			repeat with theTag in children of theRecord
				set tagName to name of theTag
				repeat with theRecord in children of theTag
					set recordComment to comment of theRecord
					set recordTags to words of recordComment
					
					if tagName is not in recordTags then
						copy tagName to the end of recordTags
					end if
					
					set finalTags to {}
					repeat with childTag in recordTags
						if (get record at (thisPath & childTag & "/" & name of theRecord)) ¬
							is not missing value then
							copy childTag to the end of finalTags
						end if
					end repeat
					
					set newComment to ""
					repeat with childTag in finalTags
						if newComment is "" then
							set newComment to "&" & childTag
						else
							set newComment to newComment & " &" & childTag
						end if
					end repeat
					
					if newComment is not recordComment then
						set comment of theRecord to newComment
					end if
				end repeat
			end repeat
		end tell
	on error error_message number error_number
		if the error_number is not -128 then
			try
				display alert "DEVONthink Pro" message error_message
			on error number error_number
				if error_number is -1708 then display dialog error_message buttons {"OK"} default button 1
			end try
		end if
	end try
end triggered

Here is a slightly better version, which shows a progress bar so you can see what’s going on.

Please note that this script clobber any non-tag parts of your comment fields! I haven’t yet coded a way to completely strip all tags, then append the final set at the end.

John

on joinList(delimiter, someList)
	set prevTIDs to AppleScript's text item delimiters
	set AppleScript's text item delimiters to delimiter
	set output to "" & someList
	set AppleScript's text item delimiters to prevTIDs
	return output
end joinList

on splitText(delimiter, someText)
	set prevTIDs to AppleScript's text item delimiters
	set AppleScript's text item delimiters to delimiter
	set output to text items of someText
	set AppleScript's text item delimiters to prevTIDs
	return output
end splitText

on triggered(theRecord)
	set tid to AppleScript's text item delimiters
	try
		set AppleScript's text item delimiters to space
		
		tell application "DEVONthink Pro"
			show progress indicator ¬
				"Assigning tags" cancel button true ¬
				steps (count of children of theRecord)
			
			set thisPath to (location of theRecord & name of theRecord & "/")
			
			repeat with theTag in children of theRecord
				set tagName to name of theTag
				step progress indicator tagName
				set tagName to ("&" & tagName)
				
				repeat with theRecord in children of theTag
					set recordComment to comment of theRecord
					set recordTags to {} & text items of recordComment
					
					if tagName is not in recordTags then
						copy tagName to the end of recordTags
					end if
					
					set finalText to {}
					set finalTags to {}
					repeat with childTag in recordTags
						set isText to true
						if length of childTag is greater than 2 then
							if texts 1 thru 1 of childTag is "&" then
								set childTag to texts 2 thru -1 of childTag
								set recordName to my splitText("/", name of theRecord)
								set recordName to my joinList("\\/", recordName)
								if exists record at (thisPath & childTag & "/" & recordName) then
									set isText to false
								end if
							end if
						end if
						
						if isText is true then
							copy childTag to the end of finalText
						else
							copy childTag to the end of finalTags
						end if
					end repeat
					
					set newComment to ""
					repeat with childText in finalText
						if length of newComment is 0 then
							set newComment to childText
						else
							set newComment to newComment & " " & childText
						end if
					end repeat
					repeat with childTag in finalTags
						if length of newComment is 0 then
							set newComment to "&" & childTag
						else
							set newComment to newComment & " &" & childTag
						end if
					end repeat
					
					if newComment is not equal to recordComment then
						set comment of theRecord to newComment
					end if
				end repeat
			end repeat
		end tell
		
	on error error_message number error_number
		if the error_number is not -128 then
			try
				display alert "DEVONthink Pro" message error_message
			on error number error_number
				if error_number is -1708 then display dialog error_message buttons {"OK"} default button 1
			end try
		end if
	end try
	
	set AppleScript's text item delimiters to tid
	
	tell application "DEVONthink Pro"
		hide progress indicator
	end tell
end triggered

Hello there, I’m a Beginner with DT and still evaluating if DT iss the right tool for what i am up to.
The smart “tags” group might be excatly what i am loking for, to finally tip the scale in Favor for DT.

Just to make sure i got it right: Every image, document or other item I put into a group is assigned the groups name as a “Tag” (i.e. as information in the “comment” field, as visible in the “Information”-dialouge).

Now for my Question: Hw do i integrate the above Script into DT correctly ?

I guessed its not by just putting an .scpt file into the DT Script folder (for the Script seems to be triggert everytime files are moved between folders).

Thanks in Advance for your efforts, and time :slight_smile:

You need to turn your “Tags” umbrella group (which contains all of the various tags as subgroups) into a “Smart Group”. This is done by opening the inspector for the group, and then associating the script that I posted with it. Then, whenever you click on the group’s name, it will trigger the script.

John

Thanks a lot for the fast Reply, works fabolously :smiley: