Skip to content

Instantly share code, notes, and snippets.

@leonbreedt
Last active March 5, 2021 01:31
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save leonbreedt/365fae61b96167fe6402 to your computer and use it in GitHub Desktop.
Save leonbreedt/365fae61b96167fe6402 to your computer and use it in GitHub Desktop.
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

@nodingneu
Copy link

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

@nodingneu
Copy link

My

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

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