Skip to content

Instantly share code, notes, and snippets.

@JoshAshby
Last active September 25, 2017 19:52
Show Gist options
  • Save JoshAshby/7f1c529d54e4d02c506a30cee7cecce5 to your computer and use it in GitHub Desktop.
Save JoshAshby/7f1c529d54e4d02c506a30cee7cecce5 to your computer and use it in GitHub Desktop.
Manipulate and list the Finder tags on an MacOS file.
#!/usr/bin/env ruby
require "ffi-xattr"
require "cfpropertylist"
require "pry"
class Tag
COLORS = {
white: 0,
gray: 1,
green: 2,
purple: 3,
blue: 4,
yellow: 5,
red: 6,
orange: 7
}.freeze
INVERSE_COLORS = COLORS.values.zip(COLORS.keys).to_h.freeze
attr_accessor :name, :color
def initialize name:, color: :white
color = INVERSE_COLORS[ color ] if color.is_a? Numeric
fail ArgumentError, "Color must be one of #{ COLORS.keys }, got `#{ color }' instead!" unless COLORS.key? color
@name = name.to_s
@color = color
end
def to_s
[name, COLORS[ color ]].join("\n")
end
def to_binary binary
CFPropertyList::CFString.new(to_s).to_binary(binary)
end
end
class TaggedFile
attr_reader :pathname
def initialize pathname
@pathname = pathname
end
def tags_plist
CFPropertyList::List.new(data: xattrs["com.apple.metadata:_kMDItemUserTags"])
end
def xattrs
Xattr.new(pathname.to_s)
end
def get_tags
tags_plist
.value
.value
.map do |attr|
tag_tuples = attr.value.split "\n"
Tag.new(name: tag_tuples[0], color: tag_tuples[1].to_i)
end
end
def set_tag name:, color:
tags = get_tags
tags << Tag.new(name: name, color: color)
set_tags tags: tags
end
def remove_tag name:
tags = get_tags
tags.delete_if { |tag| tag.name == name }
set_tags tags: tags
end
def set_tags tags:
xattrs["com.apple.metadata:_kMDItemUserTags"] = tags_plist.tap do |plist|
plist.value = CFPropertyList::CFArray.new(tags)
end.to_str
end
end
class Runner
def run
file = TaggedFile.new Pathname.new("tagtest/1")
tags = [
Tag.new(name: "Test", color: :red),
Tag.new(name: "Other Test", color: :gray)
]
file.set_tags tags: tags
end
end
Runner.new.run
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment