diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 00000000..1142932b
Binary files /dev/null and b/.DS_Store differ
diff --git a/.gitignore b/.gitignore
index 865bcb3c..30a3fba9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,4 @@ splash-cli
.envrc
dist/
*.log
+showcase.sh
diff --git a/cmd/extract/root.go b/cmd/extract/root.go
new file mode 100644
index 00000000..e96dce37
--- /dev/null
+++ b/cmd/extract/root.go
@@ -0,0 +1,49 @@
+package extract
+
+import (
+ "fmt"
+
+ "github.com/rawnly/splash-cli/pkg/base16"
+ generator "github.com/rawnly/splash-cli/pkg/theme-generator"
+ "github.com/reujab/wallpaper"
+ "github.com/spf13/cobra"
+)
+
+var flagPlatform generator.Platform
+
+func init() {
+ Cmd.Flags().VarP(&flagPlatform, "platform", "p", fmt.Sprintf("platform to extract colors for (%v)", flagPlatform.Values()))
+}
+
+var Cmd = &cobra.Command{
+ Use: "extract",
+ Short: "extract colors from the current wallpaper",
+ Example: "splash extract -p wezterm",
+ Aliases: []string{"export", "e"},
+ RunE: func(cmd *cobra.Command, args []string) error {
+ filepath, err := wallpaper.Get()
+ if err != nil {
+ return err
+ }
+
+ if flagPlatform.String() == "" {
+ var json []byte
+ _, json, err = base16.GetSchemeFromImage(filepath)
+ if err != nil {
+ return err
+ }
+
+ fmt.Println(string(json))
+ return nil
+ }
+
+ thm, err := generator.GetTheme(filepath, flagPlatform)
+ if err != nil {
+ return err
+ }
+
+ fmt.Println(thm)
+
+ return nil
+ },
+}
diff --git a/cmd/root.go b/cmd/root.go
index 4f6f6750..a3653867 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -15,6 +15,7 @@ import (
"github.com/rawnly/splash-cli/cmd/alias"
"github.com/rawnly/splash-cli/cmd/auth"
"github.com/rawnly/splash-cli/cmd/collection"
+ "github.com/rawnly/splash-cli/cmd/extract"
"github.com/rawnly/splash-cli/cmd/settings"
"github.com/rawnly/splash-cli/config"
"github.com/rawnly/splash-cli/lib"
@@ -213,12 +214,6 @@ var rootCmd = &cobra.Command{
}
var location string
-
- // debug printing
- fmt.Println("Download location:", downloadLocation)
- fmt.Println("Ignore cache:", ignoreCacheFlag)
- fmt.Println("File exists:", lib.FileExists(downloadLocation))
-
if lib.FileExists(downloadLocation) && !ignoreCacheFlag {
location = downloadLocation
@@ -359,6 +354,7 @@ func init() {
rootCmd.AddCommand(alias.Cmd)
rootCmd.AddCommand(settings.Cmd)
rootCmd.AddCommand(collection.Cmd)
+ rootCmd.AddCommand(extract.Cmd)
rootCmd.SetVersionTemplate("{{ .Version }}")
}
diff --git a/go.mod b/go.mod
index 75bf59c7..c36ff9cb 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
module github.com/rawnly/splash-cli
-go 1.23.0
+go 1.24.0
toolchain go1.24.1
@@ -9,13 +9,16 @@ require (
github.com/MakeNowJust/heredoc v1.0.0
github.com/bbrks/go-blurhash v1.1.1
github.com/briandowns/spinner v1.23.0
+ github.com/cenkalti/dominantcolor v1.0.3
github.com/cli/browser v1.3.0
github.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203
github.com/getsentry/sentry-go v0.25.0
github.com/google/uuid v1.6.0
+ github.com/lucasb-eyer/go-colorful v1.3.0
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d
github.com/posthog/posthog-go v0.0.0-20230801140217-d607812dee69
github.com/rawnly/go-wallpaper v1.0.2
+ github.com/reujab/wallpaper v0.0.0-20210630195606-5f9f655b3740
github.com/rs/zerolog v1.34.0
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cast v1.6.0
@@ -47,9 +50,10 @@ require (
github.com/subosito/gotenv v1.6.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/exp v0.0.0-20231226003508-02704c960a9b // indirect
- golang.org/x/sys v0.33.0 // indirect
+ golang.org/x/image v0.18.0 // indirect
+ golang.org/x/sys v0.37.0 // indirect
golang.org/x/term v0.15.0 // indirect
- golang.org/x/text v0.14.0 // indirect
+ golang.org/x/text v0.30.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
diff --git a/go.sum b/go.sum
index b5264985..a5be10e7 100644
--- a/go.sum
+++ b/go.sum
@@ -11,6 +11,8 @@ github.com/bbrks/go-blurhash v1.1.1 h1:uoXOxRPDca9zHYabUTwvS4KnY++KKUbwFo+Yxb8ME
github.com/bbrks/go-blurhash v1.1.1/go.mod h1:lkAsdyXp+EhARcUo85yS2G1o+Sh43I2ebF5togC4bAY=
github.com/briandowns/spinner v1.23.0 h1:alDF2guRWqa/FOZZYWjlMIx2L6H0wyewPxo/CH4Pt2A=
github.com/briandowns/spinner v1.23.0/go.mod h1:rPG4gmXeN3wQV/TsAY4w8lPdIM6RX3yqeBQJSrbXjuE=
+github.com/cenkalti/dominantcolor v1.0.3 h1:Pt0vfRZ8enkZh1n22RvoboA53SMM/v2aEwNQTZKSqww=
+github.com/cenkalti/dominantcolor v1.0.3/go.mod h1:mGpFMbWUnyXaGN48Zbf9bU9HJP1eCCD7dnsscb4lyR4=
github.com/cli/browser v1.3.0 h1:LejqCrpWr+1pRqmEPDGnTZOjsMe7sehifLynZJuqJpo=
github.com/cli/browser v1.3.0/go.mod h1:HH8s+fOAxjhQoBUAsKuPCbqUuxZDhQ2/aD+SzsEfBTk=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
@@ -60,6 +62,8 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag=
+github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
@@ -91,6 +95,8 @@ github.com/posthog/posthog-go v0.0.0-20230801140217-d607812dee69 h1:01dHVodha5Bz
github.com/posthog/posthog-go v0.0.0-20230801140217-d607812dee69/go.mod h1:migYMxlAqcnQy+3eN8mcL0b2tpKy6R+8Zc0lxwk4dKM=
github.com/rawnly/go-wallpaper v1.0.2 h1:ttmYCIMwzjuPDTpL7pG9eXjN8PZ3TOVu8wEKO9ojuFA=
github.com/rawnly/go-wallpaper v1.0.2/go.mod h1:qpQ8yj7TK2yZL2YtBjbGf8l0QwtHRwjXfW28j1XjhBs=
+github.com/reujab/wallpaper v0.0.0-20210630195606-5f9f655b3740 h1:X6IDPPN+zrSClp0Q+JiERA//d8L0WcU5MqcGeulCW1A=
+github.com/reujab/wallpaper v0.0.0-20210630195606-5f9f655b3740/go.mod h1:WYwPVmM/8szeItLeWkwZSLRvQgrvsvstRzgznR8+E4Q=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
@@ -145,6 +151,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20231226003508-02704c960a9b h1:kLiC65FbiHWFAOu+lxwNPujcsl8VYyTYYEZnsOO1WK4=
golang.org/x/exp v0.0.0-20231226003508-02704c960a9b/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
+golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ=
+golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -162,8 +170,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
-golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
+golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
@@ -172,8 +180,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
-golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
+golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
diff --git a/lib/template.go b/lib/template.go
index 7fc8541a..ce8fba70 100644
--- a/lib/template.go
+++ b/lib/template.go
@@ -3,11 +3,13 @@ package lib
import (
"bytes"
"fmt"
- "github.com/mgutz/ansi"
"io"
"math"
"strconv"
"text/template"
+
+ "github.com/lucasb-eyer/go-colorful"
+ "github.com/mgutz/ansi"
)
type Template struct {
@@ -25,6 +27,18 @@ var templateFunctions = map[string]interface{}{
"diff": func(a interface{}, b interface{}) interface{} { return a.(int32) - b.(int32) },
"abs": math.Abs,
"formatNumber": formatNumber,
+ "itermRGB": itermRGB,
+}
+
+func itermRGB(hex string) string {
+ c, _ := colorful.Hex(hex)
+
+ return fmt.Sprintf(
+ `Red Component%.6f
+Green Component%.6f
+Blue Component%.6f`,
+ c.R, c.G, c.B,
+ )
}
func NewTemplate(templateString string, name string) (*template.Template, error) {
@@ -36,7 +50,6 @@ func NewTemplate(templateString string, name string) (*template.Template, error)
func (t Template) Execute(w io.Writer) error {
temp, err := NewTemplate(t.Template, "")
-
if err != nil {
return err
}
diff --git a/pkg/base16/extractor.go b/pkg/base16/extractor.go
new file mode 100644
index 00000000..77426927
--- /dev/null
+++ b/pkg/base16/extractor.go
@@ -0,0 +1,99 @@
+package base16
+
+import (
+ "encoding/json"
+ "image"
+ "os"
+ "sort"
+
+ _ "image/jpeg"
+ _ "image/png"
+
+ "github.com/cenkalti/dominantcolor"
+ "github.com/lucasb-eyer/go-colorful"
+)
+
+type Scheme struct {
+ Base00 string `json:"base00"`
+ Base01 string `json:"base01"`
+ Base02 string `json:"base02"`
+ Base03 string `json:"base03"`
+ Base04 string `json:"base04"`
+ Base05 string `json:"base05"`
+ Base06 string `json:"base06"`
+ Base07 string `json:"base07"`
+ Base08 string `json:"base08"`
+ Base09 string `json:"base09"`
+ Base0A string `json:"base0A"`
+ Base0B string `json:"base0B"`
+ Base0C string `json:"base0C"`
+ Base0D string `json:"base0D"`
+ Base0E string `json:"base0E"`
+ Base0F string `json:"base0F"`
+}
+
+func buildScheme(cols []colorful.Color) Scheme {
+ return Scheme{
+ Base00: cols[0].Hex(),
+ Base01: cols[1].Hex(),
+ Base02: cols[2].Hex(),
+ Base03: cols[3].Hex(),
+ Base04: cols[4].Hex(),
+ Base05: cols[5].Hex(),
+ Base06: cols[6].Hex(),
+ Base07: cols[7].Hex(),
+ Base08: cols[8].Hex(),
+ Base09: cols[9].Hex(),
+ Base0A: cols[10].Hex(),
+ Base0B: cols[11].Hex(),
+ Base0C: cols[12].Hex(),
+ Base0D: cols[13].Hex(),
+ Base0E: cols[14].Hex(),
+ Base0F: cols[15].Hex(),
+ }
+}
+
+func GetSchemeFromImage(imagePath string) (*Scheme, []byte, error) {
+ f, err := os.Open(imagePath)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ defer f.Close()
+
+ img, _, err := image.Decode(f)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ raw := dominantcolor.FindN(img, 8)
+ var cols []colorful.Color
+ for _, c := range raw {
+ col, _ := colorful.MakeColor(c)
+ cols = append(cols, col)
+ }
+
+ sort.Slice(cols, func(i, j int) bool {
+ _, _, vi := cols[i].Hsv()
+ _, _, vj := cols[j].Hsv()
+
+ return vi < vj
+ })
+
+ for len(cols) < 16 {
+ a := cols[len(cols)-1]
+ b := cols[0]
+
+ mid := a.BlendLab(b, float64(len(cols))/16.0)
+ cols = append(cols, mid)
+ }
+
+ scheme := buildScheme(cols)
+
+ out, err := json.MarshalIndent(scheme, "", " ")
+ if err != nil {
+ return &scheme, nil, err
+ }
+
+ return &scheme, out, nil
+}
diff --git a/pkg/theme-generator/builder.go b/pkg/theme-generator/builder.go
new file mode 100644
index 00000000..e457245a
--- /dev/null
+++ b/pkg/theme-generator/builder.go
@@ -0,0 +1,197 @@
+package themegenerator
+
+import (
+ "fmt"
+
+ "github.com/MakeNowJust/heredoc"
+ "github.com/rawnly/splash-cli/lib"
+ "github.com/rawnly/splash-cli/pkg/base16"
+)
+
+var ghosttyTemplate = heredoc.Doc(`
+## author: Splash CLI
+
+background = {{ .Base00 }}
+foreground= {{ .Base07 }}
+
+selection-foreground= {{ .Base00 }}
+selection-background = {{ .Base07 }}
+
+
+# black
+palette = 0={{ .Base00 }}
+palette = 8={{ .Base08 }}
+# red
+palette = 1={{ .Base01 }}
+palette = 9={{ .Base09 }}
+# green
+palette = 2={{ .Base02 }}
+palette = 10={{ .Base0A }}
+# yellow
+palette = 3={{ .Base03 }}
+palette = 11={{ .Base0B }}
+# blue
+palette = 4={{ .Base04 }}
+palette = 12={{ .Base0C }}
+# purple
+palette = 5={{ .Base05 }}
+palette = 13={{ .Base0D }}
+# aqua
+palette = 6={{ .Base06 }}
+palette = 14={{ .Base0E }}
+# white
+palette = 7={{ .Base07 }}
+palette = 15={{ .Base0F }}
+`)
+
+var weztermTemplate = heredoc.Doc(`
+[colors]
+# Standard colors
+base00 = "{{ .Base00 }}" # 0 - Background
+base01 = "{{ .Base01 }}" # 1
+base02 = "{{ .Base02 }}" # 2
+base03 = "{{ .Base03 }}" # 3
+base04 = "{{ .Base04 }}" # 4
+base05 = "{{ .Base05 }}" # 5 - Default text / foreground
+base06 = "{{ .Base06 }}" # 6
+base07 = "{{ .Base07 }}" # 7
+base08 = "{{ .Base08 }}" # 8 - Red / errors
+base09 = "{{ .Base09 }}" # 9 - Orange / warnings
+base10 = "{{ .Base0A }}" # 10 - Yellow / highlights
+base11 = "{{ .Base0B }}" # 11 - Green / success
+base12 = "{{ .Base0C }}" # 12 - Cyan / accents
+base13 = "{{ .Base0D }}" # 13 - Blue / keywords
+base14 = "{{ .Base0E }}" # 14 - Magenta / constants
+base15 = "{{ .Base0F }}" # 15 - Brightest / white
+
+[colors.mapping]
+foreground = "{{ .Base07 }}"
+background = "{{ .Base00 }}"
+cursor_bg = "{{ .Base07 }}"
+cursor_fg = "{{ .Base00 }}"
+cursor_border = "{{ .Base07 }}"
+selection_bg = "{{ .Base07 }}"
+selection_fg = "{{ .Base00 }}"
+
+ansi = [
+ "{{ .Base00 }}", # 0
+ "{{ .Base08 }}", # 1
+ "{{ .Base0B }}", # 2
+ "{{ .Base0A }}", # 3
+ "{{ .Base0D }}", # 4
+ "{{ .Base0E }}", # 5
+ "{{ .Base0C }}", # 6
+ "{{ .Base05 }}", # 7
+]
+
+brights = [
+ "{base03}", # 8
+ "{base08}", # 9
+ "{base0B}", # 10
+ "{base0A}", # 11
+ "{base0D}", # 12
+ "{base0E}", # 13
+ "{base0C}", # 14
+ "{base0F}", # 15
+]
+`)
+
+var kittyTemplate = heredoc.Doc(`
+# 0–7: Normal colors
+color0 {{ .Base00 }} # base00 - Background
+color1 {{ .Base01 }} # base01
+color2 {{ .Base02 }} # base02
+color3 {{ .Base03 }} # base03
+color4 {{ .Base04 }} # base04
+color5 {{ .Base05 }} # base05
+color6 {{ .Base06 }} # base06
+color7 {{ .Base07 }} # base07
+
+# 8–15: Bright colors
+color8 {{ .Base08 }} # base08
+color9 {{ .Base09 }} # base09
+color10 {{ .Base0A }} # base10
+color11 {{ .Base0B }} # base11
+color12 {{ .Base0C }} # base12
+color13 {{ .Base0D }} # base13
+color14 {{ .Base0E }} # base14
+color15 {{ .Base0F }} # base15
+
+# UI colors
+background {{ .Base00 }}
+foreground {{ .Base05 }}
+cursor {{ .Base05 }}
+selection_background {{ .Base02 }}
+selection_foreground {{ .Base05 }}
+url_color {{ .Base08 }}
+active_border_color {{ .Base05 }}
+inactive_border_color {{ .Base02 }}
+active_tab_foreground {{ .Base07 }}
+active_tab_background {{ .Base00 }}
+inactive_tab_foreground {{ .Base04 }}
+inactive_tab_background {{ .Base01 }}
+`)
+
+var itermTemplate = heredoc.Doc(`
+
+
+
+
+
+ Ansi 0 Color {{ itermRGB .Base00 }}
+ Ansi 1 Color {{ itermRGB .Base08 }}
+ Ansi 2 Color {{ itermRGB .Base0B }}
+ Ansi 3 Color {{ itermRGB .Base0A }}
+ Ansi 4 Color {{ itermRGB .Base0D }}
+ Ansi 5 Color {{ itermRGB .Base0E }}
+ Ansi 6 Color {{ itermRGB .Base0C }}
+ Ansi 7 Color {{ itermRGB .Base05 }}
+
+
+ Ansi 8 Color {{ itermRGB .Base03 }}
+ Ansi 9 Color {{ itermRGB .Base08 }}
+ Ansi 10 Color {{ itermRGB .Base0B }}
+ Ansi 11 Color {{ itermRGB .Base0A }}
+ Ansi 12 Color {{ itermRGB .Base0D }}
+ Ansi 13 Color {{ itermRGB .Base0E }}
+ Ansi 14 Color {{ itermRGB .Base0C }}
+ Ansi 15 Color {{ itermRGB .Base07 }}
+
+
+ Background Color {{ itermRGB .Base00 }}
+ Foreground Color {{ itermRGB .Base05 }}
+ Cursor Color {{ itermRGB .Base05 }}
+ Cursor Text Color {{ itermRGB .Base00 }}
+ Selection Color {{ itermRGB .Base02 }}
+ Selected Text Color {{ itermRGB .Base05 }}
+ Bold Color {{ itermRGB .Base07 }}
+
+
+`)
+
+func GetTheme(imagePath string, theme Platform) (string, error) {
+ scheme, _, err := base16.GetSchemeFromImage(imagePath)
+ if err != nil {
+ return "", err
+ }
+
+ templates := map[Platform]string{
+ PlatformGhostty: ghosttyTemplate,
+ PlatformIterm: itermTemplate,
+ PlatformKitty: kittyTemplate,
+ PlatformWezterm: weztermTemplate,
+ }
+
+ template, ok := templates[theme]
+ if !ok {
+ return "", fmt.Errorf("unsupported platform: %v", theme)
+ }
+
+ thm, err := lib.StringTemplate(template, scheme)
+ if err != nil {
+ return "", err
+ }
+
+ return thm, nil
+}
diff --git a/pkg/theme-generator/builder_test.go b/pkg/theme-generator/builder_test.go
new file mode 100644
index 00000000..b0f54c42
--- /dev/null
+++ b/pkg/theme-generator/builder_test.go
@@ -0,0 +1,30 @@
+package themegenerator_test
+
+import (
+ "testing"
+
+ themegenerator "github.com/rawnly/splash-cli/pkg/theme-generator"
+)
+
+func TestGetTheme(t *testing.T) {
+ platforms := themegenerator.PlatformValues()
+
+ for _, platform := range platforms {
+ _, e := themegenerator.GetTheme("../../test-assets/demo.jpeg", themegenerator.Platform(platform))
+
+ if e != nil {
+ t.Fatal(e.Error())
+ }
+ }
+}
+
+// func TestParsePhotoIDFromURL(t *testing.T) {
+// for i, tCase := range photoUrls {
+// result := lib.ParsePhotoIDFromURL(tCase.data)
+//
+// if result != tCase.expected {
+// t.Errorf("[%d] Expected \"%s\" received \"%s\"", i, tCase.expected, parseResult(result))
+// }
+// }
+// }
+//
diff --git a/pkg/theme-generator/platform.go b/pkg/theme-generator/platform.go
new file mode 100644
index 00000000..7f5667c6
--- /dev/null
+++ b/pkg/theme-generator/platform.go
@@ -0,0 +1,43 @@
+package themegenerator
+
+import "fmt"
+
+type Platform string
+
+const (
+ PlatformGhostty Platform = "ghostty"
+ PlatformKitty Platform = "kitty"
+ PlatformIterm Platform = "iterm"
+ PlatformWezterm Platform = "wezterm"
+)
+
+func PlatformValues() []string {
+ return []string{
+ string(PlatformGhostty),
+ string(PlatformIterm),
+ string(PlatformKitty),
+ string(PlatformWezterm),
+ }
+}
+
+func (p *Platform) Values() []string {
+ return PlatformValues()
+}
+
+func (p *Platform) String() string {
+ return string(*p)
+}
+
+func (p *Platform) Type() string {
+ return "Platform"
+}
+
+func (p *Platform) Set(v string) error {
+ switch v {
+ case string(PlatformGhostty), string(PlatformIterm), string(PlatformKitty), string(PlatformWezterm):
+ *p = Platform(v)
+ return nil
+ }
+
+ return fmt.Errorf("invalid platform: %s. Must be one of %v", v, p.Values())
+}
diff --git a/test-assets/.DS_Store b/test-assets/.DS_Store
new file mode 100644
index 00000000..5008ddfc
Binary files /dev/null and b/test-assets/.DS_Store differ
diff --git a/test-assets/demo.jpeg b/test-assets/demo.jpeg
new file mode 100644
index 00000000..93caefd8
Binary files /dev/null and b/test-assets/demo.jpeg differ
diff --git a/unsplash/auth.go b/unsplash/auth.go
index b264c2a8..707fd0d0 100644
--- a/unsplash/auth.go
+++ b/unsplash/auth.go
@@ -57,7 +57,7 @@ func (a Api) Authenticate(code string) (*models.AuthRes, error) {
}
logrus.WithField("error", errorRes).WithField("status", response.Status).Error("Error while authenticating")
- return nil, fmt.Errorf(errorRes.ErrorDescription)
+ return nil, fmt.Errorf("%s", errorRes.ErrorDescription)
}
var authRes models.AuthRes