Page 1 of 1

Hazel not firing my AppleScript

PostPosted: Sat Nov 07, 2020 4:55 am
by johncatalano
I've only been able to get very simple AppleScripts working with Hazel, so please guide me a bit on what might be wrong, here.

The script below works perfectly fine if I run it from the macOS Script Editor - hashtags in my file get written to the Tags attribute of my manually selected file.

Code: Select all
-- https://macscripter.net/viewtopic.php?pid=204309#p204309
-- haolesurferdude
-- 2020-11-06
-- on hazelProcessFile(theFile, inputAttributes)
set readFile to POSIX path of (choose file of type {"pdf", false})
-- set readFile to POSIX path of theFile
-- end hazelProcessFile

use scripting additions
use framework "Foundation"

property endChars : return & linefeed & space

set theText to do shell script "/usr/local/bin/pdftotext " & readFile & " -"
set theText to theText & return
set hashTagList to my getHashTags(theText)
my setTags:hashTagList forPath:readFile

on getHashTags(fileText)
   set hashTagsList to {}
   repeat until fileText does not contain "#"
      set poundLoc to offset of "#" in fileText
      set thisHashTag to ""
      repeat with i from poundLoc to (count of fileText)
         set thisChar to item i of fileText
         if endChars does not contain thisChar then
            set thisHashTag to thisHashTag & thisChar
         else
            copy thisHashTag to the end of the hashTagsList
            set fileText to characters (poundLoc + (count of thisHashTag)) thru -1 of fileText as text
            exit repeat
         end if
      end repeat
   end repeat
   return hashTagsList
end getHashTags

-- The following routines are by Shane Stanley

on returnTagsFor:posixPath -- get the tags
   set aURL to current application's |NSURL|'s fileURLWithPath:posixPath -- make URL
   set {theResult, theTags} to aURL's getResourceValue:(reference) forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
   if theTags = missing value then return {} -- because when there are none, it returns missing value
   return theTags as list
end returnTagsFor:

on setTags:tagList forPath:posixPath -- set the tags, replacing any existing
   set aURL to current application's |NSURL|'s fileURLWithPath:posixPath -- make URL
   aURL's setResourceValue:tagList forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
end setTags:forPath:

on addTags:tagList forPath:posixPath -- add to existing tags
   set aURL to current application's |NSURL|'s fileURLWithPath:posixPath -- make URL
   -- get existing tags
   set {theResult, theTags} to aURL's getResourceValue:(reference) forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
   if theTags ≠ missing value then -- add new tags
      set tagList to (theTags as list) & tagList
      set tagList to (current application's NSOrderedSet's orderedSetWithArray:tagList)'s allObjects() -- delete any duplicates
   end if
   aURL's setResourceValue:tagList forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
end addTags:forPath:


I receive errors trying to use the script as embedded and so I tried it as an external script. I understand this requires that I add "on hazelProcessFile(theFile, inputAttributes)" and "end hazelProcessFile".

Here's the external script, with the necessary hazel bits. Even though I confirm that the file matches (any file), the Finder tags are never updated. What do I need to change?

Code: Select all
-- https://macscripter.net/viewtopic.php?pid=204309#p204309
-- haolesurferdude
-- 2020-11-06
on hazelProcessFile(theFile, inputAttributes)
   -- set readFile to POSIX path of (choose file of type {"pdf", false})
   set readFile POSIX path of theFile
end hazelProcessFile

use scripting additions
use framework "Foundation"

property endChars : return & linefeed & space

set theText to do shell script "/usr/local/bin/pdftotext " & readFile & " -"
set theText to theText & return
set hashTagList to my getHashTags(theText)
my setTags:hashTagList forPath:readFile

on getHashTags(fileText)
   set hashTagsList to {}
   repeat until fileText does not contain "#"
      set poundLoc to offset of "#" in fileText
      set thisHashTag to ""
      repeat with i from poundLoc to (count of fileText)
         set thisChar to item i of fileText
         if endChars does not contain thisChar then
            set thisHashTag to thisHashTag & thisChar
         else
            copy thisHashTag to the end of the hashTagsList
            set fileText to characters (poundLoc + (count of thisHashTag)) thru -1 of fileText as text
            exit repeat
         end if
      end repeat
   end repeat
   return hashTagsList
end getHashTags

-- The following routines are by Shane Stanley

on returnTagsFor:posixPath -- get the tags
   set aURL to current application's |NSURL|'s fileURLWithPath:posixPath -- make URL
   set {theResult, theTags} to aURL's getResourceValue:(reference) forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
   if theTags = missing value then return {} -- because when there are none, it returns missing value
   return theTags as list
end returnTagsFor:

on setTags:tagList forPath:posixPath -- set the tags, replacing any existing
   set aURL to current application's |NSURL|'s fileURLWithPath:posixPath -- make URL
   aURL's setResourceValue:tagList forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
end setTags:forPath:

on addTags:tagList forPath:posixPath -- add to existing tags
   set aURL to current application's |NSURL|'s fileURLWithPath:posixPath -- make URL
   -- get existing tags
   set {theResult, theTags} to aURL's getResourceValue:(reference) forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
   if theTags ≠ missing value then -- add new tags
      set tagList to (theTags as list) & tagList
      set tagList to (current application's NSOrderedSet's orderedSetWithArray:tagList)'s allObjects() -- delete any duplicates
   end if
   aURL's setResourceValue:tagList forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
end addTags:forPath:

Re: Hazel not firing my AppleScript

PostPosted: Mon Nov 09, 2020 10:33 am
by Mr_Noodle
Are you sure that script does anything? It only seems to set some variables and not do anything else.

Re: Hazel not firing my AppleScript

PostPosted: Mon Nov 09, 2020 11:37 am
by johncatalano
Mr_Noodle wrote:Are you sure that script does anything? It only seems to set some variables and not do anything else.


Yes. There is a lot of script, there, if you expand the quote.

Re: Hazel not firing my AppleScript

PostPosted: Mon Nov 09, 2020 3:37 pm
by Mr_Noodle
Whoops, sorry. My window was cutting off the scrollbars. Nonetheless, point still stands. Your hazelProcessFile() handler doesn't do anything. You have the "end" line way too early.

Re: Hazel not firing my AppleScript

PostPosted: Mon Nov 09, 2020 6:43 pm
by johncatalano
Mr_Noodle wrote:Whoops, sorry. My window was cutting off the scrollbars. Nonetheless, point still stands. Your hazelProcessFile() handler doesn't do anything. You have the "end" line way too early.


I originally put the "end" line at the very bottom of the script and I had the same issues - nothing happens when fired by Hazel.

Then, I thought that maybe I just need to contain the file part in the hazel container, so I moved the end, up.

Where should the end go in my script?

Re: Hazel not firing my AppleScript

PostPosted: Tue Nov 10, 2020 11:09 am
by Mr_Noodle
It depends on how the code is structured. Looking at yours, I think it should go before the next "on..." line but you may have to play with it to get it right.

Re: Hazel not firing my AppleScript

PostPosted: Thu Nov 12, 2020 9:21 am
by johncatalano
Mr_Noodle wrote:It depends on how the code is structured. Looking at yours, I think it should go before the next "on..." line but you may have to play with it to get it right.


Thanks for the tip. I moved the use and property lines to just above the on getHashTags line and then put the end hazelProcessFile above that. Works great! Here's the full script for the next person:

Code: Select all
-- https://macscripter.net/viewtopic.php?pid=204309#p204309
-- haolesurferdude
-- 2020-11-06
on hazelProcessFile(theFile, inputAttributes)
   -- set readFile to POSIX path of (choose file of type {"pdf", false})
   set readFile to POSIX path of theFile
   -- https://stackoverflow.com/questions/64760845/do-shell-script-with-awk-fails-in-applescript-but-same-awk-command-works-in-ter
   set theText to do shell script "mdimport -t -d3" & " " & readFile & " " & "| awk -F'\"' '/kMDItemTextContent/{print $2}'"
   set theText to theText & return
   set hashTagList to my getHashTags(theText)
   my setTags:hashTagList forPath:readFile
   
end hazelProcessFile

use scripting additions
use framework "Foundation"
property endChars : return & linefeed & space & "\\n"

on getHashTags(fileText)
   set hashTagsList to {}
   repeat until fileText does not contain "#"
      set poundLoc to offset of "#" in fileText
      set thisHashTag to ""
      repeat with i from poundLoc to (count of fileText)
         set thisChar to item i of fileText
         if endChars does not contain thisChar then
            set thisHashTag to thisHashTag & thisChar
         else
            copy thisHashTag to the end of the hashTagsList
            set fileText to characters (poundLoc + (count of thisHashTag)) thru -1 of fileText as text
            exit repeat
         end if
      end repeat
   end repeat
   return hashTagsList
end getHashTags

-- The following routines are by Shane Stanley

on returnTagsFor:posixPath -- get the tags
   set aURL to current application's |NSURL|'s fileURLWithPath:posixPath -- make URL
   set {theResult, theTags} to aURL's getResourceValue:(reference) forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
   if theTags = missing value then return {} -- because when there are none, it returns missing value
   return theTags as list
end returnTagsFor:

on setTags:tagList forPath:posixPath -- set the tags, replacing any existing
   set aURL to current application's |NSURL|'s fileURLWithPath:posixPath -- make URL
   aURL's setResourceValue:tagList forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
end setTags:forPath:

on addTags:tagList forPath:posixPath -- add to existing tags
   set aURL to current application's |NSURL|'s fileURLWithPath:posixPath -- make URL
   -- get existing tags
   set {theResult, theTags} to aURL's getResourceValue:(reference) forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
   if theTags ≠ missing value then -- add new tags
      set tagList to (theTags as list) & tagList
      set tagList to (current application's NSOrderedSet's orderedSetWithArray:tagList)'s allObjects() -- delete any duplicates
   end if
   aURL's setResourceValue:tagList forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
end addTags:forPath: