├── go.mod ├── README.md ├── LICENSE └── main.go /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/mwinters0/itermtohex 2 | 3 | go 1.23.2 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # itermtohex 2 | Convert iTerm colors to hex. (In a single binary!) 3 | 4 | ## Install 5 | ```shell 6 | go install github.com/mwinters0/itermtohex@latest 7 | ``` 8 | 9 | Or see the [releases](https://github.com/mwinters0/itermtohex/releases) page. 10 | 11 | ## Usage 12 | ```shell 13 | itermtohex my-theme.itermcolors # convert to json and output on stdout 14 | itermtohex print my-theme.itermcolors # print the converted color palette (assumes RGB support) 15 | ``` 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Michael Winters 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "encoding/xml" 6 | "fmt" 7 | "os" 8 | ) 9 | 10 | type plist struct { 11 | Dict []dict `xml:"dict"` 12 | } 13 | 14 | type dict struct { 15 | Key []string `xml:"key"` 16 | Real []float64 `xml:"real"` 17 | Dict []dict `xml:"dict"` 18 | } 19 | 20 | type Color struct { 21 | Name string 22 | RFloat float64 23 | GFloat float64 24 | BFloat float64 25 | RInt uint8 26 | GInt uint8 27 | BInt uint8 28 | Hex string 29 | } 30 | 31 | func die(y string) { 32 | fmt.Println("error: " + y) 33 | os.Exit(1) 34 | } 35 | 36 | func usage() { 37 | fmt.Println(fmt.Sprintf( 38 | "Usage:\n %s myfile.itermcolors\n %s print myfile.itermcolors", 39 | os.Args[0], os.Args[0], 40 | )) 41 | os.Exit(1) 42 | } 43 | 44 | func convert(filename string) []Color { 45 | contents, err := os.ReadFile(filename) 46 | if err != nil { 47 | die(err.Error()) 48 | } 49 | var p plist 50 | err = xml.Unmarshal(contents, &p) 51 | if err != nil { 52 | die(err.Error()) 53 | } 54 | 55 | var colors []Color 56 | mainDict := p.Dict[0] 57 | for i, colorName := range mainDict.Key { 58 | c := Color{ 59 | Name: colorName, 60 | } 61 | c.BFloat = mainDict.Dict[i].Real[0] 62 | c.GFloat = mainDict.Dict[i].Real[1] 63 | c.RFloat = mainDict.Dict[i].Real[2] 64 | c.RInt = uint8(c.RFloat * 255) 65 | c.GInt = uint8(c.GFloat * 255) 66 | c.BInt = uint8(c.BFloat * 255) 67 | c.Hex = fmt.Sprintf("#%02x%02x%02x", c.RInt, c.GInt, c.BInt) 68 | colors = append(colors, c) 69 | } 70 | return colors 71 | } 72 | 73 | func main() { 74 | var filename string 75 | var print bool 76 | switch len(os.Args) { 77 | case 2: 78 | filename = os.Args[1] 79 | case 3: 80 | if os.Args[1] != "print" { 81 | usage() 82 | } 83 | filename = os.Args[2] 84 | print = true 85 | default: 86 | usage() 87 | } 88 | 89 | colors := convert(filename) 90 | if print { 91 | printColor := func(c Color) { 92 | fmt.Printf( 93 | "%s (%s): \033[48;2;%d;%d;%dm \033[0m\n", 94 | c.Name, 95 | c.Hex, 96 | c.RInt, 97 | c.GInt, 98 | c.BInt, 99 | ) 100 | } 101 | for _, c := range colors { 102 | printColor(c) 103 | } 104 | return 105 | } 106 | 107 | j, err := json.MarshalIndent(colors, "", " ") 108 | if err != nil { 109 | die(err.Error()) 110 | } 111 | fmt.Println(string(j)) 112 | } 113 | --------------------------------------------------------------------------------