As a comparative newcomer I am only now trying to use KM properly.
I would like to have a folder change its label colour when an item is added, or when the folder is not empty. Is this possible?
I have found the ‘folder adds an item’ trigger but cannot see a way to change the colour. Many thanks for your help.
You can tag a folder (using the Set File Attribute action). So you could tag it “Red” and it will show with a Red dot. But the folder wont turn red.
To do that you would have to create a custom icon and set the folder’s icon that way.
There is a possible solution for doing that here: https://stackoverflow.com/questions/20172959/change-icon-of-folder-with-applescript
And there are answers here: https://apple.stackexchange.com/questions/6901/how-can-i-change-a-file-or-folder-icon-using-the-terminal
And I strongly suspect this python solution:
#!/usr/bin/env python
import Cocoa
import sys
Cocoa.NSWorkspace.sharedWorkspace().setIcon_forFile_options_(Cocoa.NSImage.alloc().initWithContentsOfFile_(sys.argv[1].decode('utf-8')), sys.argv[2].decode('utf-8'), 0) or sys.exit("Unable to set file icon")
could be converted to JXA fairly directly to give an easy solution.
Thank you, for the moment the tag will do fine. Cheers.
JXA may very well be possible, but straight-up AppleScriptObjC has been done already.
Feed the script the path to an image and a target path, and et voilà!
-Chris
------------------------------------------------------------------------------
# Auth: Christopher Stone { Heavy Lifting by Shane Stanley }
# dCre: 2017/11/14 04:38
# dMod: 2017/11/14 04:48
# Appl: AppleScriptObjC
# Task: Change the icon of a given item to an image.
# Libs: None
# Osax: None
# Tags: @Applescript, @Script, @ASObjC, @Change, @Icon, @Image
------------------------------------------------------------------------------
use framework "Foundation"
use framework "AppKit"
use scripting additions
------------------------------------------------------------------------------
set sourceImagePath to "/POSIX Path/to/your/image"
set targetPath to "/POSIX Path/to/your/target/item"
set theImage to (current application's NSImage's alloc()'s initWithContentsOfFile:sourceImagePath)
(current application's NSWorkspace's sharedWorkspace()'s setIcon:theImage forFile:targetPath options:0)
------------------------------------------------------------------------------
and wrapping as a function for re-use and composition (and allowing for ~ expansion and file-not-found return vallues), we could write in AppleScript, and in JavaScript for Automation:
Applescript version
use framework "Foundation"
use framework "AppKit"
use scripting additions
-- fileIconSetMay:: FilePath -> FilePath -> Maybe FilePath
on fileIconSetMay(pathImage, pathTarget)
set ca to current application
if doesFileExist(pathImage) then
if doesFileExist(pathTarget) then
set img to (ca's NSImage's alloc()'s initWithContentsOfFile:pathImage)
{nothing:not (ca's NSWorkspace's sharedWorkspace()'s ¬
setIcon:img forFile:pathTarget options:0), just:pathTarget, msg:"setIconForFile error"}
else
{nothing:true, msg:"Target file not found at: " & pathTarget}
end if
else
{nothing:true, msg:"Image not found at: " & pathImage}
end if
end fileIconSetMay
-- TEST ----------------------------------------------------------------------
on run
-- Any ~ expanded to full user Home path
set pathImage to filePath("~/Desktop/redArrow.png")
set pathTarget to filePath("~/Desktop/report.taskpaper")
set maybeIconSet to fileIconSetMay(pathImage, pathTarget)
if nothing of maybeIconSet then
msg of maybeIconSet
else
"Icon (" & pathImage & ") set for " & pathTarget
end if
end run
-- GENERIC FUNCTIONS ---------------------------------------------------------
-- doesFileExist :: String -> Bool
on doesFileExist(strPath)
set ca to current application
set oPath to (ca's NSString's stringWithString:strPath)'s ¬
stringByStandardizingPath
set {bln, int} to (ca's NSFileManager's defaultManager()'s ¬
fileExistsAtPath:oPath isDirectory:(reference))
bln and (int ≠ 1)
end doesFileExist
-- filePath :: String -> FilePath
on filePath(s)
unwrap(stringByStandardizingPath of wrap(s))
end filePath
-- unwrap :: NSObject -> a
on unwrap(objCValue)
if objCValue is missing value then
return missing value
else
set ca to current application
item 1 of ((ca's NSArray's arrayWithObject:objCValue) as list)
end if
end unwrap
-- wrap :: a -> NSObject
on wrap(v)
set ca to current application
ca's (NSArray's arrayWithObject:v)'s objectAtIndex:0
end wrap
JavaScript for Automation version
(() => {
ObjC.import('AppKit');
// SPECIFIED FILE ICON ---------------------------------------------------
// fileIconSetMay:: FilePath -> FilePath -> Maybe FilePath
const fileIconSetMay = (pathImage, pathTarget) =>
doesFileExist(pathImage) ? (
doesFileExist(pathTarget) ? {
nothing: !$.NSWorkspace.sharedWorkspace.setIconForFileOptions(
$.NSImage.alloc.initWithContentsOfFile(pathImage),
pathTarget, 0
),
just: pathTarget,
msg: "setIconForFile error ?"
} : {
nothing: true,
msg: 'Target file not found at: ' + pathTarget
}
) : {
nothing: true,
msg: 'Image not found at: ' + pathImage
};
// GENERIC FUNCTIONS -----------------------------------------------------
// filePath :: String -> FilePath
const filePath = s =>
ObjC.unwrap(ObjC.wrap(s)
.stringByStandardizingPath);
// doesFileExist :: String -> IO Bool
const doesFileExist = strPath => {
const ref = Ref();
return $.NSFileManager.defaultManager
.fileExistsAtPathIsDirectory(
ObjC.wrap(strPath)
.stringByStandardizingPath, ref
) && ref[0] !== 1;
};
// TEST ------------------------------------------------------------------
const
// Any ~ expanded to user Home path
pathImage = filePath('~/Desktop/redArrow.png'),
pathTarget = filePath('~/Desktop/report.taskpaper');
const maybeIconSet = fileIconSetMay(pathImage, pathTarget);
return maybeIconSet.nothing ? (
maybeIconSet.msg
) : 'Icon (' + pathImage + ') set for ' + pathTarget
})();
So for a one-off shell script or Execute JavaScript for Automation action, something like:
Bash
#!/bin/bash
osascript -l JavaScript <<JXA_END 2>/dev/null
(() => {
ObjC.import('AppKit');
const
pathImage = '~/Desktop/redArrow.png',
pathTarget = '~/Desktop/report.taskpaper';
return $.NSWorkspace.sharedWorkspace.setIconForFileOptions(
$.NSImage.alloc.initWithContentsOfFile(
\$(pathImage)
.stringByStandardizingPath.js
),
\$(pathTarget)
.stringByStandardizingPath.js, 0
);
})();
JXA_END
Execute Javascript for Automation Action
(() => {
ObjC.import('AppKit');
const
pathImage = '~/Desktop/redArrow.png',
pathTarget = '~/Desktop/report.taskpaper';
return $.NSWorkspace.sharedWorkspace.setIconForFileOptions(
$.NSImage.alloc.initWithContentsOfFile(
$(pathImage)
.stringByStandardizingPath.js
),
$(pathTarget)
.stringByStandardizingPath.js, 0
);
})();
Thanks for this one! Very nice.