diff --git a/Dockerfile b/Dockerfile index d29e903..681868a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM siteworxpro/golang:1.24.0 AS build +FROM siteworxpro/golang:1.24.3 AS build WORKDIR /app @@ -23,6 +23,4 @@ RUN adduser -u 1001 -g appuser appuser -D && \ USER 1001 -# docker buildx build --push --sbom=true --provenance=true --platform linux/amd64,linux/arm64 -t siteworxpro/img-proxy-url-generator:v1.4.0-grpc . - ENTRYPOINT ["/app/imgproxy", "grpc"] \ No newline at end of file diff --git a/commands/interactive.go b/commands/interactive.go new file mode 100644 index 0000000..3a33625 --- /dev/null +++ b/commands/interactive.go @@ -0,0 +1,24 @@ +package commands + +import ( + "fmt" + tea "github.com/charmbracelet/bubbletea" + "github.com/siteworxpro/img-proxy-url-generator/interactive" + "github.com/urfave/cli/v2" +) + +func Interactive() *cli.Command { + return &cli.Command{ + Name: "interactive", + Usage: "Start an interactive session", + Action: func(c *cli.Context) error { + p := tea.NewProgram(interactive.InitialModel(c), tea.WithAltScreen()) + + if _, err := p.Run(); err != nil { + return fmt.Errorf("error running interactive session: %w", err) + } + + return nil + }, + } +} diff --git a/generator/format.go b/generator/format.go index b3d2837..bd65bbb 100644 --- a/generator/format.go +++ b/generator/format.go @@ -17,6 +17,10 @@ const ( DEF Format = "default" ) +func ToPtr(format Format) *Format { + return &format +} + func (g *Generator) StringToFormat(string string) (Format, error) { s := strings.ToLower(string) switch s { diff --git a/go.mod b/go.mod index 392235a..e8d7349 100644 --- a/go.mod +++ b/go.mod @@ -3,31 +3,48 @@ module github.com/siteworxpro/img-proxy-url-generator go 1.24.0 require ( - github.com/aws/aws-sdk-go v1.55.5 - github.com/bigkevmcd/go-configparser v0.0.0-20240808124832-fc81059ea0bd - github.com/charmbracelet/lipgloss v1.0.0 - github.com/redis/go-redis/v9 v9.7.0 - github.com/urfave/cli/v2 v2.27.5 - google.golang.org/grpc v1.69.2 - google.golang.org/protobuf v1.36.1 + github.com/aws/aws-sdk-go v1.55.7 + github.com/bigkevmcd/go-configparser v0.0.0-20250311182818-a679eef33309 + github.com/charmbracelet/bubbletea v1.3.5 + github.com/charmbracelet/lipgloss v1.1.0 + github.com/redis/go-redis/v9 v9.8.0 + github.com/urfave/cli/v2 v2.27.6 + google.golang.org/grpc v1.72.0 + google.golang.org/protobuf v1.36.6 ) require ( + github.com/atotto/clipboard v0.1.4 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect + github.com/catppuccin/go v0.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/charmbracelet/x/ansi v0.6.0 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect + github.com/charmbracelet/bubbles v0.21.0 // indirect + github.com/charmbracelet/colorprofile v0.3.1 // indirect + github.com/charmbracelet/huh v0.7.0 // indirect + github.com/charmbracelet/x/ansi v0.9.2 // indirect + github.com/charmbracelet/x/cellbuf v0.0.13 // indirect + github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0 // indirect + github.com/charmbracelet/x/term v0.2.1 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-localereader v0.0.1 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect - github.com/muesli/termenv v0.15.2 // indirect + github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect + github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect + github.com/muesli/cancelreader v0.2.2 // indirect + github.com/muesli/termenv v0.16.0 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect - golang.org/x/net v0.33.0 // indirect - golang.org/x/sys v0.28.0 // indirect - golang.org/x/text v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 // indirect + golang.org/x/net v0.40.0 // indirect + golang.org/x/sync v0.14.0 // indirect + golang.org/x/sys v0.33.0 // indirect + golang.org/x/text v0.25.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250512202823-5a2f75b736a9 // indirect ) diff --git a/go.sum b/go.sum index 73efbc6..dff93ff 100644 --- a/go.sum +++ b/go.sum @@ -1,29 +1,64 @@ +github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= +github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU= github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= +github.com/aws/aws-sdk-go v1.55.7 h1:UJrkFq7es5CShfBwlWAC8DA077vp8PyVbQd3lqLiztE= +github.com/aws/aws-sdk-go v1.55.7/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8= github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA= github.com/bigkevmcd/go-configparser v0.0.0-20240808124832-fc81059ea0bd h1:MsTk4yo6KVYdulsDscuH4AwiZN1CyuCJAg59EWE7HPQ= github.com/bigkevmcd/go-configparser v0.0.0-20240808124832-fc81059ea0bd/go.mod h1:vzEQfW+A1T+AMJmTIX+SXNLNECHOM7GEinHhw0IjykI= +github.com/bigkevmcd/go-configparser v0.0.0-20250311182818-a679eef33309 h1:h2H7P1M0rXm8LTJMhZWr3SAleTmR6vg+7PM1BkTumaw= +github.com/bigkevmcd/go-configparser v0.0.0-20250311182818-a679eef33309/go.mod h1:vzEQfW+A1T+AMJmTIX+SXNLNECHOM7GEinHhw0IjykI= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/catppuccin/go v0.3.0 h1:d+0/YicIq+hSTo5oPuRi5kOpqkVA5tAsU6dNhvRu+aY= +github.com/catppuccin/go v0.3.0/go.mod h1:8IHJuMGaUUjQM82qBrGNBv7LFq6JI3NnQCF6MOlZjpc= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/charmbracelet/lipgloss v1.0.0 h1:O7VkGDvqEdGi93X+DeqsQ7PKHDgtQfF8j8/O2qFMQNg= -github.com/charmbracelet/lipgloss v1.0.0/go.mod h1:U5fy9Z+C38obMs+T+tJqst9VGzlOYGj4ri9reL3qUlo= -github.com/charmbracelet/x/ansi v0.6.0 h1:qOznutrb93gx9oMiGf7caF7bqqubh6YIM0SWKyA08pA= -github.com/charmbracelet/x/ansi v0.6.0/go.mod h1:KBUFw1la39nl0dLl10l5ORDAqGXaeurTQmwyyVKse/Q= +github.com/charmbracelet/bubbles v0.21.0 h1:9TdC97SdRVg/1aaXNVWfFH3nnLAwOXr8Fn6u6mfQdFs= +github.com/charmbracelet/bubbles v0.21.0/go.mod h1:HF+v6QUR4HkEpz62dx7ym2xc71/KBHg+zKwJtMw+qtg= +github.com/charmbracelet/bubbletea v1.3.5 h1:JAMNLTbqMOhSwoELIr0qyP4VidFq72/6E9j7HHmRKQc= +github.com/charmbracelet/bubbletea v1.3.5/go.mod h1:TkCnmH+aBd4LrXhXcqrKiYwRs7qyQx5rBgH5fVY3v54= +github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs= +github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk= +github.com/charmbracelet/colorprofile v0.3.1 h1:k8dTHMd7fgw4bnFd7jXTLZrSU/CQrKnL3m+AxCzDz40= +github.com/charmbracelet/colorprofile v0.3.1/go.mod h1:/GkGusxNs8VB/RSOh3fu0TJmQ4ICMMPApIIVn0KszZ0= +github.com/charmbracelet/huh v0.7.0 h1:W8S1uyGETgj9Tuda3/JdVkc3x7DBLZYPZc4c+/rnRdc= +github.com/charmbracelet/huh v0.7.0/go.mod h1:UGC3DZHlgOKHvHC07a5vHag41zzhpPFj34U92sOmyuk= +github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY= +github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30= +github.com/charmbracelet/x/ansi v0.8.0 h1:9GTq3xq9caJW8ZrBTe0LIe2fvfLR/bYXKTx2llXn7xE= +github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q= +github.com/charmbracelet/x/ansi v0.9.2 h1:92AGsQmNTRMzuzHEYfCdjQeUzTrgE1vfO5/7fEVoXdY= +github.com/charmbracelet/x/ansi v0.9.2/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE= +github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0GVL4jeHEwG5YOXDmi86oYw2yuYUGqz6a8sLwg0X8= +github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= +github.com/charmbracelet/x/cellbuf v0.0.13 h1:/KBBKHuVRbq1lYx5BzEHBAFBP8VcQzJejZ/IA3iR28k= +github.com/charmbracelet/x/cellbuf v0.0.13/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a h1:G99klV19u0QnhiizODirwVksQB91TJKV/UaTnACcG30= github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= +github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 h1:payRxjMjKgx2PaCWLZ4p3ro9y97+TVLZNaRZgJwSVDQ= +github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0 h1:qko3AQ4gK1MTS/de7F5hPGx6/k1u0w4TeYmBFwzYVP4= +github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0/go.mod h1:pBhA0ybfXv6hDjQUZ7hk1lVxBiUbupdw5R31yPUViVQ= +github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= +github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo= +github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= +github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= @@ -46,14 +81,24 @@ github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69 github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= +github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= -github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= +github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= +github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= +github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= +github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= +github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= +github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= +github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= +github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E= github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw= +github.com/redis/go-redis/v9 v9.8.0 h1:q3nRvjrlge/6UD7eTu/DSg2uYiU2mCL0G/uzBWqhicI= +github.com/redis/go-redis/v9 v9.8.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= @@ -62,31 +107,61 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= +github.com/urfave/cli/v2 v2.27.6 h1:VdRdS98FNhKZ8/Az8B7MTyGQmpIr36O1EHybx/LaZ4g= +github.com/urfave/cli/v2 v2.27.6/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= +go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= +go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= +go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= +go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= +go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= +golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 h1:MDc5xs78ZrZr3HMQugiXOAkSZtfTpbJLDr/lwfgO53E= +golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= +golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= +golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= +golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= +golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= +golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 h1:TqExAhdPaB60Ux47Cn0oLV07rGnxZzIsaRhQaqS666A= google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250512202823-5a2f75b736a9 h1:IkAfh6J/yllPtpYFU0zZN1hUPYdT0ogkBT/9hMxHjvg= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250512202823-5a2f75b736a9/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.69.2 h1:U3S9QEtbXC0bYNvRtcoklF3xGtLViumSYxWykJS+7AU= google.golang.org/grpc v1.69.2/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= +google.golang.org/grpc v1.72.0 h1:S7UkcVa60b5AAQTaO6ZKamFp1zMZSU0fGDK2WZLbBnM= +google.golang.org/grpc v1.72.0/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk= google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/interactive/model.go b/interactive/model.go new file mode 100644 index 0000000..5800652 --- /dev/null +++ b/interactive/model.go @@ -0,0 +1,140 @@ +package interactive + +import ( + "fmt" + "github.com/aws/aws-sdk-go/aws" + cbhelp "github.com/charmbracelet/bubbles/help" + "github.com/charmbracelet/bubbles/key" + tea "github.com/charmbracelet/bubbletea" + "github.com/charmbracelet/huh" + "github.com/siteworxpro/img-proxy-url-generator/config" + "github.com/siteworxpro/img-proxy-url-generator/generator" + "github.com/siteworxpro/img-proxy-url-generator/interactive/params" + "github.com/urfave/cli/v2" +) + +type Model struct { + Fields []huh.Field + generator *generator.Generator + url *string + format *generator.Format + selectedParams *[]UrlParam + err error + focusField huh.Field + inParamsFields bool + help cbhelp.Model +} + +type UrlParam interface { + Value() string + Display() string + Key() string + Input() []huh.Field +} + +func InitialModel(c *cli.Context) Model { + + m := Model{ + url: aws.String(""), + selectedParams: &[]UrlParam{}, + format: generator.ToPtr(generator.DEF), + } + + fields := make([]huh.Field, 0) + fields = append(fields, m.initialFields()...) + + m.Fields = fields + + cfg, _ := config.NewConfig(c.String("config")) + + if cfg == nil { + err := fmt.Errorf("config not loaded") + m.err = err + + return m + } + + g, err := generator.NewGenerator(cfg) + + if err != nil { + m.err = err + return m + } + + m.generator = g + + m.help = cbhelp.New() + + return m +} + +func (m Model) initialFields() []huh.Field { + + fields := make([]huh.Field, 0) + + options := []UrlParam{ + params.NewHeight(), + params.NewWidth(), + params.NewResize(), + params.NewMinWidth(), + params.NewMinHeight(), + params.NewQuality(), + params.NewZoom(), + params.NewEnlarge(), + } + + var huhOptions []huh.Option[UrlParam] + for _, option := range options { + huhOptions = append(huhOptions, huh.NewOption[UrlParam](option.Display(), option)) + } + + fields = append(fields, + huh.NewInput(). + Key("imgUrl"). + Description("The URL of the image to generate a proxy for."). + Title("Image URL"). + Value(m.url). + Prompt("Enter the image URL:"), + ) + fields = append(fields, + huh.NewMultiSelect[UrlParam](). + Description("Params to add to the URL."). + Options(huhOptions...). + Value(m.selectedParams). + WithKeyMap(&huh.KeyMap{ + MultiSelect: huh.MultiSelectKeyMap{ + Up: key.NewBinding(key.WithKeys("up"), key.WithHelp("up", "up")), + Down: key.NewBinding(key.WithKeys("down"), key.WithHelp("down", "down")), + Toggle: key.NewBinding(key.WithKeys(" "), key.WithHelp(" ", "toggle")), + }, + }), + ) + + fields = append(fields, huh.NewSelect[generator.Format](). + Description("Convert the image format."). + Options( + huh.NewOption[generator.Format]("JPEG", generator.JPG), + huh.NewOption[generator.Format]("PNG", generator.PNG), + huh.NewOption[generator.Format]("BMP", generator.BMP), + huh.NewOption[generator.Format]("WEBP", generator.WEBP), + huh.NewOption[generator.Format]("GIF", generator.GIF), + huh.NewOption[generator.Format]("ICO", generator.ICO), + huh.NewOption[generator.Format]("Default", generator.DEF), + ). + Key("format"). + Title("Format"). + Value(m.format). + WithKeyMap(&huh.KeyMap{ + Select: huh.SelectKeyMap{ + Up: key.NewBinding(key.WithKeys("up"), key.WithHelp("up", "up")), + Down: key.NewBinding(key.WithKeys("down"), key.WithHelp("down", "down")), + }, + }), + ) + + return fields +} + +func (m Model) Init() tea.Cmd { + return nil +} diff --git a/interactive/params/enlarge.go b/interactive/params/enlarge.go new file mode 100644 index 0000000..79ac3ae --- /dev/null +++ b/interactive/params/enlarge.go @@ -0,0 +1,51 @@ +package params + +import ( + "github.com/charmbracelet/huh" +) + +type Enlarge struct { + enlarge *[]string + field huh.Field +} + +func NewEnlarge() *Enlarge { + e := &Enlarge{ + enlarge: &[]string{}, + field: huh.NewMultiSelect[string](). + Options( + huh.NewOption("true", "true"), + ). + Description("Whether to enlarge the image."). + WithKeyMap( + huh.NewDefaultKeyMap(), + ), + } + + e.enlarge = &[]string{} + e.field.(*huh.MultiSelect[string]).Value(e.enlarge) + + return e +} + +func (e Enlarge) Display() string { + return "enlarge" +} + +func (e Enlarge) Value() string { + value := "0" + + if len(*e.enlarge) > 0 { + value = "1" + } + + return value +} + +func (e Enlarge) Key() string { + return "el" +} + +func (e Enlarge) Input() []huh.Field { + return []huh.Field{e.field} +} diff --git a/interactive/params/height.go b/interactive/params/height.go new file mode 100644 index 0000000..91c9cdb --- /dev/null +++ b/interactive/params/height.go @@ -0,0 +1,41 @@ +package params + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/charmbracelet/huh" +) + +type Height struct { + paramValue *string + field *huh.Input +} + +func NewHeight() *Height { + h := &Height{ + paramValue: aws.String(""), + field: huh.NewInput(). + Key("h"). + Description("The height of the image."). + Title("Height"), + } + + h.field.Value(h.paramValue) + + return h +} + +func (h Height) Display() string { + return "height" +} + +func (h Height) Value() string { + return *h.paramValue +} + +func (h Height) Key() string { + return "h" +} + +func (h Height) Input() []huh.Field { + return []huh.Field{h.field} +} diff --git a/interactive/params/min-height.go b/interactive/params/min-height.go new file mode 100644 index 0000000..79084a0 --- /dev/null +++ b/interactive/params/min-height.go @@ -0,0 +1,42 @@ +package params + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/charmbracelet/huh" +) + +type MinHeight struct { + paramValue *string + field *huh.Input +} + +func NewMinHeight() *MinHeight { + mh := &MinHeight{ + paramValue: nil, + field: huh.NewInput(). + Key("min-height"). + Description("The minimum height of the image."). + Title("Min Height"), + } + + mh.paramValue = aws.String("") + mh.field.Value(mh.paramValue) + + return mh +} + +func (mh MinHeight) Display() string { + return "min-height" +} + +func (mh MinHeight) Value() string { + return *mh.paramValue +} + +func (mh MinHeight) Key() string { + return "mh" +} + +func (mh MinHeight) Input() []huh.Field { + return []huh.Field{mh.field} +} diff --git a/interactive/params/min-width.go b/interactive/params/min-width.go new file mode 100644 index 0000000..8cc7baf --- /dev/null +++ b/interactive/params/min-width.go @@ -0,0 +1,42 @@ +package params + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/charmbracelet/huh" +) + +type MinWidth struct { + paramValue *string + field *huh.Input +} + +func NewMinWidth() *MinWidth { + mw := &MinWidth{ + paramValue: nil, + field: huh.NewInput(). + Key("min-width"). + Description("The minimum width of the image."). + Title("Min Width"), + } + + mw.paramValue = aws.String("") + mw.field.Value(mw.paramValue) + + return mw +} + +func (mw MinWidth) Display() string { + return "min-width" +} + +func (mw MinWidth) Value() string { + return *mw.paramValue +} + +func (mw MinWidth) Key() string { + return "mw" +} + +func (mw MinWidth) Input() []huh.Field { + return []huh.Field{mw.field} +} diff --git a/interactive/params/quality.go b/interactive/params/quality.go new file mode 100644 index 0000000..e04e12d --- /dev/null +++ b/interactive/params/quality.go @@ -0,0 +1,41 @@ +package params + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/charmbracelet/huh" +) + +type Quality struct { + value *string + field *huh.Input +} + +func NewQuality() *Quality { + z := &Quality{ + value: aws.String(""), + field: huh.NewInput(). + Key("q"). + Description("Quality of the image 0-100"). + Title("Quality"), + } + + z.field.Value(z.value) + + return z +} + +func (z *Quality) Value() string { + return *z.value +} + +func (z *Quality) Display() string { + return "quality" +} + +func (z *Quality) Key() string { + return "q" +} + +func (z *Quality) Input() []huh.Field { + return []huh.Field{z.field} +} diff --git a/interactive/params/resize.go b/interactive/params/resize.go new file mode 100644 index 0000000..eed6570 --- /dev/null +++ b/interactive/params/resize.go @@ -0,0 +1,99 @@ +package params + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/charmbracelet/huh" +) + +type Resize struct { + fields []huh.Field + height *string + width *string + resizeType *string + enlarge *[]string + extent *[]string +} + +func NewResize() *Resize { + rs := &Resize{ + fields: []huh.Field{ + huh.NewInput(). + Key("resize.height"). + Description("The height of the image."). + Title("Height"), + huh.NewInput(). + Key("resize.width"). + Description("The width of the image."). + Title("Width"), + huh.NewSelect[string](). + Title("Resize Type"). + Options( + huh.NewOption("fit", "fit"), + huh.NewOption("fill", "fill"), + huh.NewOption("fill-down", "fill-down"), + huh.NewOption("force", "force"), + huh.NewOption("auto", "auto"), + ).WithKeyMap(huh.NewDefaultKeyMap()), + huh.NewMultiSelect[string](). + Options( + huh.NewOption("true", "true"), + ). + Description("Whether to enlarge the image."). + WithKeyMap( + huh.NewDefaultKeyMap(), + ), + huh.NewMultiSelect[string](). + Options( + huh.NewOption("true", "true"), + ). + Description("Whether to extend the image."). + WithKeyMap( + huh.NewDefaultKeyMap(), + ), + }, + } + + rs.height = aws.String("") + rs.width = aws.String("") + rs.enlarge = &[]string{} + rs.extent = &[]string{} + rs.resizeType = aws.String("auto") + + rs.fields[0].(*huh.Input).Value(rs.height) + rs.fields[1].(*huh.Input).Value(rs.width) + rs.fields[2].(*huh.Select[string]).Value(rs.resizeType) + rs.fields[3].(*huh.MultiSelect[string]).Value(rs.enlarge) + rs.fields[4].(*huh.MultiSelect[string]).Value(rs.extent) + + return rs +} + +func (r Resize) Display() string { + return "resize" +} + +func (r Resize) Value() string { + if *r.height == "" || *r.width == "" { + return "" + } + + resize := "0" + if *r.enlarge != nil && len(*r.enlarge) > 0 { + resize = "1" + } + + extent := "0" + if *r.extent != nil && len(*r.extent) > 0 { + extent = "1" + } + + return *r.resizeType + ":" + *r.height + ":" + *r.width + ":" + resize + ":" + extent +} + +func (r Resize) Key() string { + return "rs" +} + +func (r Resize) Input() []huh.Field { + return r.fields +} diff --git a/interactive/params/width.go b/interactive/params/width.go new file mode 100644 index 0000000..fc16a93 --- /dev/null +++ b/interactive/params/width.go @@ -0,0 +1,41 @@ +package params + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/charmbracelet/huh" +) + +type Width struct { + paramValue *string + field *huh.Input +} + +func NewWidth() *Width { + w := &Width{ + paramValue: aws.String(""), + field: huh.NewInput(). + Key("h"). + Description("The width of the image."). + Title("Width"), + } + + w.field.Value(w.paramValue) + + return w +} + +func (h Width) Display() string { + return "width" +} + +func (h Width) Value() string { + return *h.paramValue +} + +func (h Width) Key() string { + return "h" +} + +func (h Width) Input() []huh.Field { + return []huh.Field{h.field} +} diff --git a/interactive/params/zoom.go b/interactive/params/zoom.go new file mode 100644 index 0000000..6be9903 --- /dev/null +++ b/interactive/params/zoom.go @@ -0,0 +1,41 @@ +package params + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/charmbracelet/huh" +) + +type Zoom struct { + zoom *string + field huh.Field +} + +func NewZoom() *Zoom { + z := &Zoom{ + zoom: aws.String(""), + field: huh.NewInput(). + Key("z"). + Description("Percentage to zoom the image (1.4 == 140%) ."). + Title("Zoom"), + } + + z.field.(*huh.Input).Value(z.zoom) + + return z +} + +func (z *Zoom) Value() string { + return *z.zoom +} + +func (z *Zoom) Display() string { + return "zoom" +} + +func (z *Zoom) Key() string { + return "z" +} + +func (z *Zoom) Input() []huh.Field { + return []huh.Field{z.field} +} diff --git a/interactive/update.go b/interactive/update.go new file mode 100644 index 0000000..fa2584a --- /dev/null +++ b/interactive/update.go @@ -0,0 +1,99 @@ +package interactive + +import ( + tea "github.com/charmbracelet/bubbletea" + "github.com/charmbracelet/huh" +) + +func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { + + if m.focusField == nil { + m.Fields[0].Focus() + m.focusField = m.Fields[0] + } + + if msg, ok := msg.(tea.KeyMsg); ok { + switch msg.String() { + case "tab": + if m.focusField != nil { + + index := -1 + + selectedParamFields := make([]huh.Field, 0) + for _, field := range *m.selectedParams { + for _, f := range field.Input() { + selectedParamFields = append(selectedParamFields, f) + } + } + + if m.inParamsFields { + for i, field := range selectedParamFields { + if field == m.focusField { + index = i + break + } + } + } else { + for i, field := range m.Fields { + if field == m.focusField { + index = i + break + } + } + } + + // if the field is not found, return + if index == -1 { + return m, nil + } + + // if the field is the last one, and we have params selected go to the param fields + if !m.inParamsFields && index == len(m.Fields)-1 && len(selectedParamFields) > 0 { + m.focusField.Blur() + m.inParamsFields = true + paramsFields := selectedParamFields + m.focusField = paramsFields[0] + m.focusField.Focus() + + // if the field is the last one, and we have params selected go to the first non params field + } else if m.inParamsFields && index == len(selectedParamFields)-1 { + m.focusField.Blur() + m.inParamsFields = false + m.focusField = m.Fields[0] + m.focusField.Focus() + + // if not in the params fields and the field is the last one, go to the first one + } else if index == len(m.Fields)-1 && !m.inParamsFields { + m.focusField.Blur() + m.focusField = m.Fields[0] + m.focusField.Focus() + } else { + // otherwise, go to the next field + m.focusField.Blur() + if m.inParamsFields { + m.focusField = selectedParamFields[index+1] + } else { + m.focusField = m.Fields[index+1] + } + m.focusField.Focus() + } + } + case "ctrl+c", "esc": + return m, tea.Quit + case "enter": + return m, nil + default: + if m.focusField != nil { + md, cmd := m.focusField.(huh.Field).Update(msg) + + if md != nil { + m.focusField = md.(huh.Field) + } + + return m, cmd + } + } + } + + return m, nil +} diff --git a/interactive/view.go b/interactive/view.go new file mode 100644 index 0000000..2e8c331 --- /dev/null +++ b/interactive/view.go @@ -0,0 +1,71 @@ +package interactive + +import ( + "fmt" + "github.com/charmbracelet/bubbles/key" + "github.com/charmbracelet/lipgloss" +) + +func (m Model) View() string { + + fieldStyle := lipgloss.NewStyle().PaddingBottom(1) + + if m.err != nil { + return lipgloss. + NewStyle(). + Bold(true). + Foreground(lipgloss.Color("red")). + Background(lipgloss.Color("black")). + Render("Error: " + m.err.Error() + "\n" + "Press Ctrl+C to exit.") + } + + output := lipgloss.NewStyle(). + Foreground(lipgloss.Color("5")). + PaddingBottom(1). + Bold(true). + Underline(true). + Render("Welcome to the img-proxy URL Generator!") + "\n" + + for _, field := range m.Fields { + output += fieldStyle.Render("\n" + field.View()) + } + + for _, field := range *m.selectedParams { + for _, f := range field.Input() { + output += fieldStyle.Render("\n" + f.View()) + } + } + + if *m.url == "" { + return output + "\n" + m.renderHelp() + } + + // Generate the URL + params := make([]string, 0) + for _, field := range *m.selectedParams { + if field.Value() != "" { + params = append(params, field.Key()+":"+field.Value()) + } + } + + url, _ := m.generator.GenerateUrl(*m.url, params, *m.format) + + output += fmt.Sprintf("\nGenerated URL: %s\n\n", lipgloss.NewStyle(). + Bold(true). + Foreground(lipgloss.Color("#0000ff")). + Render(url)) + + output += m.renderHelp() + + return output +} + +func (m Model) renderHelp() string { + return m.help.ShortHelpView([]key.Binding{ + key.NewBinding(key.WithKeys("ctrl+c", "esc"), key.WithHelp("esc", "quit")), + key.NewBinding(key.WithKeys("up"), key.WithHelp("↑", "cursor up")), + key.NewBinding(key.WithKeys("down"), key.WithHelp("↓", "cursor down")), + key.NewBinding(key.WithKeys(" "), key.WithHelp("space", "select")), + key.NewBinding(key.WithKeys("tab"), key.WithHelp("tab", "next field")), + }) +} diff --git a/main.go b/main.go index c2c3f8d..5043732 100644 --- a/main.go +++ b/main.go @@ -19,11 +19,12 @@ func main() { commands = append(commands, cliCommands.ReportCommand()) commands = append(commands, cliCommands.GrpcCommand()) commands = append(commands, cliCommands.DecryptCommand()) + commands = append(commands, cliCommands.Interactive()) app := &cli.App{ Name: "img-proxy-url-generator", Usage: "URL Generator for the img proxy service", - DefaultCommand: "generate", + DefaultCommand: "interactive", Version: Version, Commands: commands, Flags: []cli.Flag{