Skip to content

Instantly share code, notes, and snippets.

@leonbreedt
Last active May 16, 2024 19:50
Convert iTerm2 color scheme to Terminal.app color scheme. To use, just save to disk and run it like you would any script. NOTE: Needs Xcode 8.0 or later, since it has been ported to Swift 3.0.
#!/usr/bin/xcrun swift
//
// Copyright © 2016 Leon Breedt
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import Cocoa
/// Enumerates the colors in an iTerm color scheme.
enum iTermColors: String {
case ansi0 = "Ansi 0 Color"
case ansi1 = "Ansi 1 Color"
case ansi2 = "Ansi 2 Color"
case ansi3 = "Ansi 3 Color"
case ansi4 = "Ansi 4 Color"
case ansi5 = "Ansi 5 Color"
case ansi6 = "Ansi 6 Color"
case ansi7 = "Ansi 7 Color"
case ansi8 = "Ansi 8 Color"
case ansi9 = "Ansi 9 Color"
case ansi10 = "Ansi 10 Color"
case ansi11 = "Ansi 11 Color"
case ansi12 = "Ansi 12 Color"
case ansi13 = "Ansi 13 Color"
case ansi14 = "Ansi 14 Color"
case ansi15 = "Ansi 15 Color"
case cursorText = "Cursor Text Color"
case selectedText = "Selected Text Color"
case foreground = "Foreground Color"
case background = "Background Color"
case bold = "Bold Color"
case selection = "Selection Color"
case cursor = "Cursor Color"
}
/// Enumerates the colors in a Terminal.app color scheme.
enum TerminalColors: String {
case ansiBlack = "ANSIBlackColor"
case ansiRed = "ANSIRedColor"
case ansiGreen = "ANSIGreenColor"
case ansiYellow = "ANSIYellowColor"
case ansiBlue = "ANSIBlueColor"
case ansiMagenta = "ANSIMagentaColor"
case ansiCyan = "ANSICyanColor"
case ansiWhite = "ANSIWhiteColor"
case ansiBrightBlack = "ANSIBrightBlackColor"
case ansiBrightRed = "ANSIBrightRedColor"
case ansiBrightGreen = "ANSIBrightGreenColor"
case ansiBrightYellow = "ANSIBrightYellowColor"
case ansiBrightBlue = "ANSIBrightBlueColor"
case ansiBrightMagenta = "ANSIBrightMagentaColor"
case ansiBrightCyan = "ANSIBrightCyanColor"
case ansiBrightWhite = "ANSIBrightWhiteColor"
case background = "BackgroundColor"
case text = "TextColor"
case boldText = "BoldTextColor"
case selection = "SelectionColor"
case cursor = "CursorColor"
}
// Mapping of iTerm colors onto corresponding Terminal.app colors.
let iTermColor2TerminalColor = [
iTermColors.ansi0: TerminalColors.ansiBlack,
iTermColors.ansi1: TerminalColors.ansiRed,
iTermColors.ansi2: TerminalColors.ansiGreen,
iTermColors.ansi3: TerminalColors.ansiYellow,
iTermColors.ansi4: TerminalColors.ansiBlue,
iTermColors.ansi5: TerminalColors.ansiMagenta,
iTermColors.ansi6: TerminalColors.ansiCyan,
iTermColors.ansi7: TerminalColors.ansiWhite,
iTermColors.ansi8: TerminalColors.ansiBrightBlack,
iTermColors.ansi9: TerminalColors.ansiBrightRed,
iTermColors.ansi10: TerminalColors.ansiBrightGreen,
iTermColors.ansi11: TerminalColors.ansiBrightYellow,
iTermColors.ansi12: TerminalColors.ansiBrightBlue,
iTermColors.ansi13: TerminalColors.ansiBrightMagenta,
iTermColors.ansi14: TerminalColors.ansiBrightCyan,
iTermColors.ansi15: TerminalColors.ansiBrightWhite,
iTermColors.background: TerminalColors.background,
iTermColors.foreground: TerminalColors.text,
iTermColors.selection: TerminalColors.selection,
iTermColors.bold: TerminalColors.boldText,
iTermColors.cursor: TerminalColors.cursor,
]
/// Enumerates the names of iTerm color components in the scheme dictionary.
struct iTermColorComponent {
static let red = "Red Component"
static let green = "Green Component"
static let blue = "Blue Component"
}
/// Converts an iTerm color scheme file (.itermcolors), into a Terminal.app color scheme
/// file (.terminal).
func convertToTerminalColors(itermFile: String, terminalFile: String) {
if let itermScheme = NSDictionary(contentsOfFile: itermFile) {
print("converting \(itermFile) -> \(terminalFile)")
let name = terminalFile.ns.lastPathComponent.ns.deletingPathExtension
let terminalScheme = convert(iTermColorScheme: itermScheme, toTerminalSchemeWithName: name)
terminalScheme.write(toFile: terminalFile, atomically: true)
} else {
print("unable to load \(itermFile)")
}
}
/// Converts an iTerm color scheme dictionary into a Terminal.app color scheme dictionary.
func convert(iTermColorScheme: NSDictionary, toTerminalSchemeWithName name: String) -> NSDictionary {
var terminalColorScheme: [String: AnyObject] = [
"name" : name,
"type" : "Window Settings",
"ProfileCurrentVersion" : 2.04,
"columnCount": 90,
"rowCount": 50
]
// SF Mono is pretty sweet.
if let font = archivedFontWithName(name: "SF Mono Regular", size: 13) {
terminalColorScheme["Font"] = font
}
for (rawKey, rawValue) in iTermColorScheme {
guard let name = rawKey as? String else { continue }
guard let itermDict = rawValue as? NSDictionary else { continue }
guard let itermKey = iTermColors(rawValue: name) else { continue }
guard let terminalKey = iTermColor2TerminalColor[itermKey] else { continue }
let (r, g, b) = (
(itermDict[iTermColorComponent.red] as? CGFloat) ?? CGFloat(0),
(itermDict[iTermColorComponent.green] as? CGFloat) ?? CGFloat(0),
(itermDict[iTermColorComponent.blue] as? CGFloat) ?? CGFloat(0)
)
let color = NSColor(deviceRed: r, green: g, blue: b, alpha: 1)
let data = NSKeyedArchiver.archivedData(withRootObject: color)
terminalColorScheme[terminalKey.rawValue] = data
}
return terminalColorScheme
}
/// Creates an `NSData` representation of an `NSFont`.
func archivedFontWithName(name: String, size: CGFloat) -> NSData? {
if let font = NSFont(name: name, size: size) {
return NSKeyedArchiver.archivedData(withRootObject: font)
}
return nil
}
extension String {
/// Gets the canonical version of a path.
var fullPath: String {
get {
let path = ns.standardizingPath
var directory = ns.deletingLastPathComponent
if directory.utf8.count == 0 {
directory = FileManager.default().currentDirectoryPath
}
return directory.ns.appendingPathComponent(path)
}
}
/// Convenience property for accessing this string as an `NSString`.
var ns: NSString {
return self as NSString
}
}
// Entry point.
let args = Process.arguments.dropFirst()
if args.count > 0 {
for itermFile in args {
let path = itermFile.fullPath
let folder = path.ns.deletingLastPathComponent
let schemeName = path.ns.lastPathComponent.ns.deletingPathExtension
let terminalPath = "\(folder)/\(schemeName).terminal"
convertToTerminalColors(itermFile: path, terminalFile: terminalPath)
}
} else {
print("usage: iTermColorsToTerminalColors FILE.itermcolors [...]")
}
@Jones-S
Copy link

Jones-S commented Feb 24, 2016

does not work anymore, I think.
I am getting the following output

Any hints on how I could still convert a .itermcolors file to a .terminal file?

iTermColorsToTerminalColors.swift:85:76: error: '#' has been removed from Swift; 'name' already has an argument label
func itermColorSchemeToTerminalColorScheme(itermColorScheme: NSDictionary, #name: String) -> NSDictionary {
                                                                           ^

iTermColorsToTerminalColors.swift:93:37: error: missing argument label 'size:' in call
  if let font = archivedFontWithName("PragmataPro", 14) {
                                    ^
                                                    size: 
iTermColorsToTerminalColors.swift:132:16: error: use of unresolved identifier 'C_ARGC'
  for i in 1...C_ARGC {
               ^~~~~~
iTermColorsToTerminalColors.swift:143:18: error: 'stringByStandardizingPath' is unavailable: Use URLByStandardizingPath on NSURL instead.
      let path = stringByStandardizingPath
                 ^~~~~~~~~~~~~~~~~~~~~~~~~
Foundation.String:382:16: note: 'stringByStandardizingPath' has been explicitly marked unavailable here
    public var stringByStandardizingPath: String { get }
               ^
iTermColorsToTerminalColors.swift:144:28: error: 'stringByDeletingLastPathComponent' is unavailable: Use URLByDeletingLastPathComponent on NSURL instead.
      var directory = path.stringByDeletingLastPathComponent
                           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Foundation.String:339:16: note: 'stringByDeletingLastPathComponent' has been explicitly marked unavailable here
    public var stringByDeletingLastPathComponent: String { get }
               ^
iTermColorsToTerminalColors.swift:145:10: error: use of unresolved identifier 'countElements'
      if countElements(directory) == 0 {
         ^~~~~~~~~~~~~
iTermColorsToTerminalColors.swift:148:24: error: 'stringByAppendingPathComponent' is unavailable: Use URLByAppendingPathComponent on NSURL instead.
      return directory.stringByAppendingPathComponent(path)
                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Foundation.String:326:17: note: 'stringByAppendingPathComponent' has been explicitly marked unavailable here
    public func stringByAppendingPathComponent(aString: String) -> String
                ^
iTermColorsToTerminalColors.swift:155:5: error: 'println' has been renamed to 'print'
    println("converting \(itermFile) -> \(terminalFile)")
    ^~~~~~~
    print
Swift.println:2:13: note: 'println' has been explicitly marked unavailable here
public func println<T>(value: T)
            ^
iTermColorsToTerminalColors.swift:156:37: error: 'lastPathComponent' is unavailable: Use lastPathComponent on NSURL instead.
    let terminalName = terminalFile.lastPathComponent.stringByDeletingPathExtension
                                    ^~~~~~~~~~~~~~~~~
Foundation.String:198:16: note: 'lastPathComponent' has been explicitly marked unavailable here
    public var lastPathComponent: String { get }
               ^
iTermColorsToTerminalColors.swift:156:55: error: 'stringByDeletingPathExtension' is unavailable: Use URLByDeletingPathExtension on NSURL instead.
    let terminalName = terminalFile.lastPathComponent.stringByDeletingPathExtension
                                                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Foundation.String:343:16: note: 'stringByDeletingPathExtension' has been explicitly marked unavailable here
    public var stringByDeletingPathExtension: String { get }
               ^
iTermColorsToTerminalColors.swift:160:5: error: 'println' has been renamed to 'print'
    println("unable to load \(itermFile)")
    ^~~~~~~
    print
Swift.println:2:13: note: 'println' has been explicitly marked unavailable here
public func println<T>(value: T)
            ^
iTermColorsToTerminalColors.swift:168:23: error: 'stringByDeletingLastPathComponent' is unavailable: Use URLByDeletingLastPathComponent on NSURL instead.
    let folder = path.stringByDeletingLastPathComponent
                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Foundation.String:339:16: note: 'stringByDeletingLastPathComponent' has been explicitly marked unavailable here
    public var stringByDeletingLastPathComponent: String { get }
               ^
iTermColorsToTerminalColors.swift:169:27: error: 'lastPathComponent' is unavailable: Use lastPathComponent on NSURL instead.
    let schemeName = path.lastPathComponent.stringByDeletingPathExtension
                          ^~~~~~~~~~~~~~~~~
Foundation.String:198:16: note: 'lastPathComponent' has been explicitly marked unavailable here
    public var lastPathComponent: String { get }
               ^
iTermColorsToTerminalColors.swift:169:45: error: 'stringByDeletingPathExtension' is unavailable: Use URLByDeletingPathExtension on NSURL instead.
    let schemeName = path.lastPathComponent.stringByDeletingPathExtension
                                            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Foundation.String:343:16: note: 'stringByDeletingPathExtension' has been explicitly marked unavailable here
    public var stringByDeletingPathExtension: String { get }
               ^
iTermColorsToTerminalColors.swift:171:28: error: missing argument label 'terminalFile:' in call
    convertToTerminalColors(path, terminalPath)
                           ^
                                  terminalFile: 
iTermColorsToTerminalColors.swift:174:3: error: 'println' has been renamed to 'print'
  println("usage: iTermColorsToTerminalColors FILE.itermcolors [...]")
  ^~~~~~~
  print
Swift.println:2:13: note: 'println' has been explicitly marked unavailable here
public func println<T>(value: T)
            ^

@leonbreedt
Copy link
Author

leonbreedt commented Jun 17, 2016

@Jones-S: seems I don't get email notifications of comments....

Script was not compatible with Swift 2.x.

I have now updated it to Swift 3.0, you'll need the latest Xcode 8.0 beta installed, and active:

$ sudo xcode-select -s /Applications/Xcode-beta.app/Contents/Developer

Then you can run the script, here's an example:

$ chmod +x iTermColorsToTerminalColors.swift
$ ./iTermColorsToTerminalColors.swift Spacegray.itermcolors
converting /Users/ljb/Documents/SpaceGray.itermcolors -> /Users/ljb/Documents/SpaceGray.terminal

@prabhakhar
Copy link

in Downloads/
› ./iTermColorsToTerminalColors.swift anderson.itermcolors
./iTermColorsToTerminalColors.swift:189:12: error: instance member 'arguments' cannot be used on type 'Process'
let args = Process.arguments.dropFirst()
^~~~~~~ ~~~~~~~~~
./iTermColorsToTerminalColors.swift:126:18: error: value of type 'String' does not conform to expected dictionary value type 'AnyObject'
"name" : name,
^~~~
as AnyObject
./iTermColorsToTerminalColors.swift:153:53: error: cannot assign value of type 'Data' to type 'AnyObject?'
terminalColorScheme[terminalKey.rawValue] = data
^~~~
as AnyObject?
./iTermColorsToTerminalColors.swift:156:12: error: cannot convert return expression of type '[String : AnyObject]' to return type 'NSDictionary'
return terminalColorScheme
^~~~~~~~~~~~~~~~~~~
as NSDictionary
./iTermColorsToTerminalColors.swift:162:32: error: cannot convert return expression of type 'Data' to return type 'NSData?'
return NSKeyedArchiver.archivedData(withRootObject: font)
~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
as NSData?
./iTermColorsToTerminalColors.swift:175:48: error: cannot call value of non-function type 'FileManager'
directory = FileManager.default().currentDirectoryPath
~~~~~~~~~~~~~~~~~~~^~

in Downloads/
› swift --version
Apple Swift version 3.0.2 (swiftlang-800.0.63 clang-800.0.42.1)
Target: x86_64-apple-macosx10.9

Copy link

ghost commented Dec 6, 2017

I ran these commands:

$ sudo xcode-select -s /Applications/Xcode-beta.app/Contents/Developer
xcode-select: error: invalid developer directory '/Applications/Xcode-beta.app/Contents/Developer'
$ chmod +x iTermColorsToTerminalColors.swift
$ ./iTermColorsToTerminalColors.swift Untitled.itermcolors

(I'm not sure what the Xcode error is about)

And at the end I get this error:

./iTermColorsToTerminalColors.swift:188:12: error: instance member 'arguments' cannot be used on type 'Process'
let args = Process.arguments.dropFirst()
           ^~~~~~~ ~~~~~~~~~
./iTermColorsToTerminalColors.swift:174:48: error: cannot call value of non-function type 'FileManager'
                directory = FileManager.default().currentDirectoryPath
                            ~~~~~~~~~~~~~~~~~~~^~

./iTermColorsToTerminalColors.swift:125:18: error: value of type 'String' does not conform to expected dictionary value type 'AnyObject'
        "name" : name,
                 ^~~~
                      as AnyObject
./iTermColorsToTerminalColors.swift:152:53: error: cannot assign value of type 'Data' to type 'AnyObject?'
        terminalColorScheme[terminalKey.rawValue] = data
                                                    ^~~~
                                                         as AnyObject
./iTermColorsToTerminalColors.swift:155:12: error: cannot convert return expression of type '[String : AnyObject]' to return type 'NSDictionary'
    return terminalColorScheme
           ^~~~~~~~~~~~~~~~~~~
                               as NSDictionary
./iTermColorsToTerminalColors.swift:161:32: error: cannot convert return expression of type 'Data' to return type 'NSData?'
        return NSKeyedArchiver.archivedData(withRootObject: font)
               ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                                                                  as NSData

Copy link

ghost commented Dec 6, 2017

My

$ swift --version
Apple Swift version 4.0.2 (swiftlang-900.0.69.2 clang-900.0.38)
Target: x86_64-apple-macosx10.9

@pmorelli92
Copy link

pmorelli92 commented Jun 4, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment