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