How are colorschemes represented in OS X Terminal.app Settings Files?
I'm interested in moving color values I've created for OS X Terminal to applications on other platforms, such as Linux. I'm familiar with the usual methods of representing color values like RGB, HSB, L*A*B, HEX, etc. However, the <data>
strings used in Terminal settings files are unlike other methods used to define colors. I'd like help understanding this XML <data>
type in relation to other color values.
As an example, I used OS X's built-in Color Picker to manually change Terminal's default ANSI scheme with HSB values from Ethan Schoonover's excellent Solarized. I then saved those settings in an XML .plist called Solarized Dark xterm-256color.terminal
(The contents of that file may be found here.)
I arbitrarily chose brblack
from that file as a single color value for comparison:
<key>ANSIBrightBlackColor</key>
<data>
YnBsaXN0MDDUAQIDBAUGFRZYJHZlcnNpb25YJG9iamVjdHNZJGFyY2hpdmVyVCR0b3AS
AAGGoKMHCA9VJG51bGzTCQoLDA0OVU5TUkdCXE5TQ29sb3JTcGFjZVYkY2xhc3NOMCAw
LjE2NDUgMC4yMQAQAoAC0hAREhNaJGNsYXNzbmFtZVgkY2xhc3Nlc1dOU0NvbG9yohIU
WE5TT2JqZWN0XxAPTlNLZXllZEFyY2hpdmVy0RcYVHJvb3SAAQgRGiMtMjc7QUhOW2Jx
c3V6hY6WmaK0t7wAAAAAAAABAQAAAAAAAAAZAAAAAAAAAAAAAAAAAAAAvg==
</data>
This looks much different (and more complex) than the simple HSB value 193 100 21
taken from Schoonover's table:
SOLARIZED HEX 16/8 TERMCOL XTERM/HEX L*A*B RGB HSB
--------- ------- ---- ------- ----------- ---------- ----------- -----------
base03 #002b36 8/4 brblack 234 #1c1c1c 15 -12 -12 0 43 54 193 100 21
...
Why does the simple value 193 100 21
get converted into a data string 5 lines long? What other information is contained in that string? Finally, and most importantly, how can I convert such a string into simple standard color values that I can use on other platforms?
bplist
means binary property list, which can be converted to XML with plutil -convert xml1
. Inside each plist for a color is another data key for the fractional RGB values.
/usr/libexec/PlistBuddy -x -c 'Print "Window Settings":"My Theme"' ~/Library/Preferences/com.apple.Terminal.plist|tr -d '\n\t'|grep -o '[^>]*</key><data>[^<]*'|while read l;do echo ${l%%<*} $(base64 -D<<<${l##*>}|plutil -convert xml1 - -o -|awk '/<data>/{getline;print}'|tr -d '\t'|base64 -D);done
The output looks like this:
ANSIBlueColor 0.4769933663 0.4769933663 0.9314516129
ANSICyanColor 0.2666655827 0.8165705831 0.8588709677
ANSIGreenColor 0.428833897 0.8508064516 0.490967087
ANSIMagentaColor 0.9072580645 0.4499707336 0.9072580645
ANSIRedColor 0.9072580645 0.508503512 0.508503512
ANSIYellowColor 0.9072580645 0.9072580645 0.3914379553
CursorColor 0.9998760223 0.999984026 0.999786377
SelectionColor 0.3899414837 0.4639441073 0.5917825699
TextBoldColor 0.9441435337 0.4102420509 0.427282244
TextColor 1 0.99997437 0.9999912977
You're looking at base64 encoded serialized data.
Base64 + serialized original:
YnBsaXN0MDDUAQIDBAUGFRZYJHZlcnNpb25YJG9iamVjdHNZJGFyY2hpdmVyVCR0b3AS
AAGGoKMHCA9VJG51bGzTCQoLDA0OVU5TUkdCXE5TQ29sb3JTcGFjZVYkY2xhc3NOMCAw
LjE2NDUgMC4yMQAQAoAC0hAREhNaJGNsYXNzbmFtZVgkY2xhc3Nlc1dOU0NvbG9yohIU
WE5TT2JqZWN0XxAPTlNLZXllZEFyY2hpdmVy0RcYVHJvb3SAAQgRGiMtMjc7QUhOW2Jx
c3V6hY6WmaK0t7wAAAAAAAABAQAAAAAAAAAZAAAAAAAAAAAAAAAAAAAAvg==
Using something like http://www.base64decode.org/, you can see the decoded version:
bplist00X$versionX$objectsY$archiverT$topU$null
UNSRGB\NSColorSpaceV$classN0 0.1645 0.21Z$classnameX$classesWNSColorXNSObject_NSKeyedArchiverTroot#-27;AHN[bqsuz
At this point, the interesting part is: NSKeyedArchiver
which is the built-in serialization engine in Objective-C, which of course, OSX apps are written in.
As for the question behind your question, of how to convert between this and other standard representations of color: The answer is unfortunately, not easily or reliably.
It's clear that you know how to take an HSB value and generate the encoded data. If you wanted to take the time to reverse engineer how the archiving happens, you'd be able to do it. Not sure what your familiarity with the objective c language is, but you could probably make a simple program that converts between the two. Essentially, probably not worth your time.