I am trying to create a smart rule that moves new tags into specific groups (converting them into group tags) based on the tag prefix. For example, if ‘rk’ is the prefix - i.e., rk.tag1, rk.tag2, I want to move them into RK.Group etc. for different prefixes. I have written a smart rule script that looks at each tag of an item, checks whether it exists as a group tag already, and if not, files it into the appropriate group.
I want the script to trigger when I move the item into its database from the global inbox. The smart rule works well when I run it on demand on an item in a specific database – the ordinary tags are converted into group tags in the right locations. However, when I trigger the smart rule to be ‘on moving into database’ and move an item into the database, it moves the tag into the group tag location, but the item is not there. It creates an empty group tag. The item still remains, but with the original ordinary tags.
I am not sure if I have described it well, so I am including the smart rule and code below and am happy to clarify further.
As a specific example of the problem, if tag an item with ‘rk.tag1’ and move it into the database, the item appears in the database with ordinary tag ‘rk.tag1’ and an empty group tag ‘rk.tag1’ is created in RK.Group. When I run the smart rule on demand on the same item, the ordinary tag ‘rk.tag1’ is converted/moved into a group tag ‘rk.tag1’ in RK.Group and the ordinary tag is gone. The item now appears under /RK.Group/rk.tag1.
property pGlobalSearch : false -- Set to true to search in all opened databases. Otherwise the current database of the records will be used.
property defaultTopLocation : "/TagsToSort"
property topTagLocation : "/Tags/"
property maxPrefixCharacters : 2
--NOTE Toplocations must already exist
property FileLocations : {¬
{prefix:"rk", Toplocation:"/Research/RK.Group"}, ¬
{prefix:"rm", Toplocation:"/Research/RM.Group"}, ¬
{prefix:"rj", Toplocation:"/Research/RJ.Group"}}
on PerformSmartRule(theRecords)
tell application id "DNtp"
try
set oldDelimiters to AppleScript's text item delimiters
set AppleScript's text item delimiters to "."
repeat with thisRecord in theRecords
set theTags to tags of thisRecord -- remove for SR
if (count of theTags) is 0 then return -- if no tags then return - remove for SR
repeat with thisTag in theTags
set thisPrefix to item 1 of (text items of thisTag)
if (count of characters of thisPrefix) is less than or equal to maxPrefixCharacters then
set theQuery to "name==" & thisTag & space & "kind:grouptag"
if (pGlobalSearch) then
set theResults to search theQuery
else
set theResults to search theQuery in root of database of thisRecord
end if
set didMove to true
set numResults to count of theResults
if numResults is 0 then
set destinationTopLocation to my retrieveTopLocation(thisPrefix)
set tagRec to get record at topTagLocation & thisTag
set destRec to get record at destinationTopLocation in database of thisRecord
move record tagRec to destRec
else if numResults is greater than 1 then
log message info "Ambiguous destination." record thisRecord
set didMove to false
end if
end if
end repeat
end repeat
on error error_message number error_number
if the error_number is not -128 then display alert "DEVONthink" message error_message as warning
set AppleScript's text item delimiters to oldDelimiters
end try
end tell
end PerformSmartRule
on retrieveTopLocation(prefixToTest)
repeat with rec in my FileLocations
if prefixToTest is prefix of rec then
return Toplocation of rec
end if
end repeat
return defaultTopLocation
end retrieveTopLocation
No, tags which are also a group. Basically moving the tag from the /Tags/ group where it behaves like an ordinary tag into a group so it can behave as a group tag. I’m not sure the right terminology, but it behaves differently if it is a group tag. Basically, I just want to move the tag into the group I designate.
I can possibly describe the issue better: When I move an item into a database, I want to check the tags and see if they exist in a specific target location; if not, I want to move them to that location. The target location depends on the first two letters of the tag and the database that it is being moved into.
Is this feasible? I thought I had solved it, but I am running into the issues described in my first post.
I am still running into issues when I try to move the location of tag in a smart rule that triggers on moving an item into a database. The tag successfully moves to the new location, but it is empty (i.e., no longer attached to the original item). Is there another way to do this? I am not sure if it is a bug or my implementation.
I am using an applescript because I want to move the tag to different groups depending on its first two characters. I don’t want to make separate smart rules for each possibility.
I have worked on this some more and I am still stumped. The script in my first post works fine when an item is already in the target database. However, it does not work as a smart rule that activates on moving into the database. I can’t figure out what is different, but it seems to be something about what database it thinks it is in when the applescript is executed.
To summarize:
As a standalone script when the item is already in the target database: the tag (for example, “rk.tag”) is moved to its target location (“RK.Group”) and removed from /Tags/rk.tag. The item is in the new location under /RK.Group/rk.tag/.
As a smart rule that activates on moving into the database: a new tag is created at the target location /RK.Group/rk.tag but the original tag remains under /Tags/rk.tag. The item is under /Tags/rk.tag and is not moved to /RK.Group/rk.tag
I tried moving the item to the new location explicitly in the script, but was getting errors. I have not been able to debug because I have not yet figured out how to debug a smart rule script (I cannot add breakpoints etc. as I can with the standalone script and the standalone script is working fine).
If a script is executed in a smart rule that is activated on Moving into the database, is the current database the original database or the database it is being moved into? If the former, is there a way to refer to the database it has been moved into within a script?
I took a look at your script. One problem is that you didn’t set in which database things should happen. See these lines:
set tagRec to get record at topTagLocation & thisTag
set destRec to get record at destinationTopLocation in database of thisRecord
In the first line the in database of part is missing. And get record at defaults to the current database which means some “weird” things will happen … and some minutes later everything will work again … and then it fails … and so on
As mentioned your approach of moving the tag won’t work. I guess you tried with only one record, right? I think what you want is create location, this creates a location if it doesn’t exist, if it exists it does nothing. So instead of moving the actual tag you could use the tag’s name to create the location, leaving the tag untouched.
No idea what to do with the actual tags, though. Maybe the easiest way is to remove them from the record (set tags of thisRecord to {}) and then use a Smart Group or Rule to delete empty tags.
property defaultTopLocation : "/TagsToSort"
property topTagLocation : "/Tags/"
property maxPrefixCharacters : 2
property FileLocations : {¬
{prefix:"rk", Toplocation:"/Research/RK.Group"}, ¬
{prefix:"rm", Toplocation:"/Research/RM.Group"}, ¬
{prefix:"rj", Toplocation:"/Research/RJ.Group"}}
on performSmartRule(theRecords)
tell application id "DNtp"
try
set oldDelimiters to AppleScript's text item delimiters
set AppleScript's text item delimiters to "."
repeat with thisRecord in theRecords
set theTags to tags of thisRecord
repeat with thisTag in theTags
set thisPrefix to item 1 of (text items of thisTag)
if (count of characters of thisPrefix) ≤ maxPrefixCharacters then
set thisGroupTag_Location to my retrieveTopLocation(thisPrefix) & "/" & thisTag
set thisGroupTag to create location thisGroupTag_Location in database of thisRecord
replicate record thisRecord to thisGroupTag
end if
end repeat
end repeat
set AppleScript's text item delimiters to oldDelimiters
on error error_message number error_number
set AppleScript's text item delimiters to oldDelimiters
if the error_number is not -128 then display alert "DEVONthink" message error_message as warning
end try
end tell
end performSmartRule
on retrieveTopLocation(prefixToTest)
repeat with rec in my FileLocations
if prefixToTest is prefix of rec then
return Toplocation of rec
end if
end repeat
return defaultTopLocation
end retrieveTopLocation