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 [...]")
}
@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