summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
Diffstat (limited to 'internal')
-rw-r--r--internal/parse/userinput.go (renamed from internal/userinput/userinput.go)20
-rw-r--r--internal/picker/keys.go4
-rw-r--r--internal/switcher/keys.go54
-rw-r--r--internal/switcher/misc.go54
-rw-r--r--internal/switcher/switcher.go79
5 files changed, 154 insertions, 57 deletions
diff --git a/internal/userinput/userinput.go b/internal/parse/userinput.go
index 8f1ecdc..d61a185 100644
--- a/internal/userinput/userinput.go
+++ b/internal/parse/userinput.go
@@ -1,4 +1,4 @@
-package userinput
+package parse
import (
"errors"
@@ -25,23 +25,23 @@ func sanitize(s string) string {
return s
}
-func ParseColor(s string) (colors.ColorSpace, error) {
+func Color(s string) (colors.ColorSpace, error) {
s = sanitize(s)
switch {
case strings.Contains(s, "#"):
- return parseHex(s)
+ return hex(s)
case strings.Contains(s, "rgb"):
- return parseRGB(s)
+ return rgb(s)
case strings.Contains(s, "hsl"):
- return parseHSL(s)
+ return hsl(s)
case strings.Contains(s, "cmyk"):
- return parseCMYK(s)
+ return cmyk(s)
default:
return nil, errUnknownColorFormat
}
}
-func parseRGB(s string) (colors.ColorSpace, error) {
+func rgb(s string) (colors.ColorSpace, error) {
var r, g, b int
_, err := fmt.Sscanf(s, "rgb(%d,%d,%d)", &r, &g, &b)
if err != nil {
@@ -50,7 +50,7 @@ func parseRGB(s string) (colors.ColorSpace, error) {
return colors.RGB{R: r, G: g, B: b}, nil
}
-func parseHex(s string) (colors.ColorSpace, error) {
+func hex(s string) (colors.ColorSpace, error) {
var r, g, b int
_, err := fmt.Sscanf(s, "#%02x%02x%02x", &r, &g, &b)
if err != nil {
@@ -59,7 +59,7 @@ func parseHex(s string) (colors.ColorSpace, error) {
return colors.RGB{R: r, G: g, B: b}, nil
}
-func parseCMYK(s string) (colors.ColorSpace, error) {
+func cmyk(s string) (colors.ColorSpace, error) {
var c, m, y, k int
_, err := fmt.Sscanf(s, "cmyk(%d,%d,%d,%d)", &c, &m, &y, &k)
if err != nil {
@@ -68,7 +68,7 @@ func parseCMYK(s string) (colors.ColorSpace, error) {
return colors.CMYK{C: c, M: m, Y: y, K: k}, nil
}
-func parseHSL(str string) (colors.ColorSpace, error) {
+func hsl(str string) (colors.ColorSpace, error) {
var h, s, l int
_, err := fmt.Sscanf(str, "hsl(%d,%d,%d)", &h, &s, &l)
if err != nil {
diff --git a/internal/picker/keys.go b/internal/picker/keys.go
index e219878..1b7b558 100644
--- a/internal/picker/keys.go
+++ b/internal/picker/keys.go
@@ -1,6 +1,8 @@
package picker
-import "github.com/charmbracelet/bubbles/key"
+import (
+ "github.com/charmbracelet/bubbles/key"
+)
type keybinds struct {
next, prev key.Binding
diff --git a/internal/switcher/keys.go b/internal/switcher/keys.go
index 215a8e2..73ba710 100644
--- a/internal/switcher/keys.go
+++ b/internal/switcher/keys.go
@@ -1,9 +1,20 @@
package switcher
-import "github.com/charmbracelet/bubbles/key"
+import (
+ "strings"
+
+ "github.com/charmbracelet/bubbles/key"
+)
+
+const (
+ cpHex = "x"
+ cpRGB = "r"
+ cpHSL = "s"
+ cpCMYK = "c"
+)
type keybinds struct {
- next, prev, cpHex, cpRgb, cpHsl, cpCmyk, help, quit key.Binding
+ next, prev, copy, help, insert, esc, confirm, quit key.Binding
}
func newKeybinds() keybinds {
@@ -14,28 +25,33 @@ func newKeybinds() keybinds {
),
prev: key.NewBinding(
key.WithKeys("shift+tab"),
- key.WithHelp("shift+tab", "prev. picker"),
- ),
- cpHex: key.NewBinding(
- key.WithKeys("x"),
- key.WithHelp("x", "copy hex"),
- ),
- cpRgb: key.NewBinding(
- key.WithKeys("r"),
- key.WithHelp("r", "copy rgb"),
+ key.WithHelp("shift+tab", "prev picker"),
),
- cpHsl: key.NewBinding(
- key.WithKeys("s"),
- key.WithHelp("s", "copy hsl"),
- ),
- cpCmyk: key.NewBinding(
- key.WithKeys("c"),
- key.WithHelp("c", "copy cmyk"),
+ copy: key.NewBinding(
+ key.WithKeys(cpHex, cpRGB, cpHSL, cpCMYK),
+ key.WithHelp(
+ strings.Join([]string{cpHex, cpRGB, cpHSL, cpCMYK}, "/"),
+ "copy color",
+ ),
),
help: key.NewBinding(
key.WithKeys("?"),
key.WithHelp("?", "help"),
),
+ insert: key.NewBinding(
+ key.WithKeys("i", ":"),
+ key.WithHelp("i", "manual input"),
+ ),
+ esc: key.NewBinding(
+ key.WithKeys("esc"),
+ key.WithHelp("esc", "exit manual input"),
+ key.WithDisabled(),
+ ),
+ confirm: key.NewBinding(
+ key.WithKeys("enter"),
+ key.WithHelp("enter", "confirm manual input"),
+ key.WithDisabled(),
+ ),
quit: key.NewBinding(
key.WithKeys("q", "ctrl+c"),
key.WithHelp("q", "quit"),
@@ -45,7 +61,7 @@ func newKeybinds() keybinds {
func Keys() []key.Binding {
k := newKeybinds()
- return []key.Binding{k.next, k.prev, k.cpHex, k.cpRgb, k.cpHsl, k.cpCmyk, k.help, k.quit}
+ return []key.Binding{k.next, k.prev, k.copy, k.insert, k.esc, k.confirm, k.help, k.quit}
}
func shortKeys() [][]key.Binding {
diff --git a/internal/switcher/misc.go b/internal/switcher/misc.go
new file mode 100644
index 0000000..e87f219
--- /dev/null
+++ b/internal/switcher/misc.go
@@ -0,0 +1,54 @@
+package switcher
+
+import (
+ "log/slog"
+
+ "github.com/ChausseBenjamin/termpicker/internal/colors"
+ "github.com/ChausseBenjamin/termpicker/internal/parse"
+ "github.com/ChausseBenjamin/termpicker/internal/util"
+)
+
+const (
+ okCpMsg = "Copied %s to clipboard as %s"
+)
+
+func (m Model) copyColor(format string) string {
+ pc := m.pickers[m.active].GetColor().ToPrecise()
+ switch format {
+ case cpHex:
+ return util.Copy(colors.Hex(m.pickers[m.active].GetColor()))
+ case cpRGB:
+ rgb := colors.RGB{}.FromPrecise(pc).(colors.RGB)
+ return util.Copy(rgb.String())
+ case cpHSL:
+ hsl := colors.HSL{}.FromPrecise(pc).(colors.HSL)
+ return util.Copy(hsl.String())
+ case cpCMYK:
+ cmyk := colors.CMYK{}.FromPrecise(pc).(colors.CMYK)
+ return util.Copy(cmyk.String())
+ default:
+ return "Copy format not supported"
+ }
+}
+
+func (m *Model) SetColorFromText(colorStr string) string {
+ color, err := parse.Color(colorStr)
+ if err != nil {
+ slog.Error("Failed to parse color", util.ErrKey, err)
+ return err.Error()
+ } else {
+ pc := color.ToPrecise()
+ switch color.(type) {
+ case colors.RGB:
+ m.UpdatePicker(IndexRgb, pc)
+ m.SetActive(IndexRgb)
+ case colors.CMYK:
+ m.UpdatePicker(IndexCmyk, pc)
+ m.SetActive(IndexCmyk)
+ case colors.HSL:
+ m.UpdatePicker(IndexHsl, pc)
+ m.SetActive(IndexHsl)
+ }
+ return "Color set to " + colorStr
+ }
+}
diff --git a/internal/switcher/switcher.go b/internal/switcher/switcher.go
index 860bf81..74f0d6b 100644
--- a/internal/switcher/switcher.go
+++ b/internal/switcher/switcher.go
@@ -9,30 +9,43 @@ import (
"github.com/ChausseBenjamin/termpicker/internal/picker"
"github.com/ChausseBenjamin/termpicker/internal/preview"
"github.com/ChausseBenjamin/termpicker/internal/quit"
- "github.com/ChausseBenjamin/termpicker/internal/util"
"github.com/charmbracelet/bubbles/help"
"github.com/charmbracelet/bubbles/key"
+ "github.com/charmbracelet/bubbles/textinput"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
)
+const (
+ IndexRgb int = iota
+ IndexCmyk
+ IndexHsl
+)
+
type Model struct {
active int
pickers []picker.Model
preview preview.Model
help help.Model
- fullHelp bool // When false, only show help for the switcher (not children)
+ input textinput.Model
notices notices.Model
+ fullHelp bool // When false, only show help for the switcher (not children)
}
-func New(pickers []picker.Model) Model {
+func New() Model {
+ pickers := []picker.Model{ // Order MUST match the Index* constants
+ *picker.RGB(),
+ *picker.CMYK(),
+ *picker.HSL(),
+ }
return Model{
active: 0,
pickers: pickers,
preview: *preview.New(colors.Hex(pickers[0].GetColor())),
help: help.New(),
- fullHelp: false,
+ input: textinput.New(),
notices: notices.New(),
+ fullHelp: false,
}
}
@@ -110,14 +123,20 @@ func (m Model) View() string {
// helpstr = m.help.FullHelpView([][]key.Binding{m.AllKeys()[0]})
helpstr = m.help.FullHelpView(shortKeys())
}
-
helpstr = boxStyle.Render(helpstr)
- return fmt.Sprintf("%s\n%s\n%s\n%v\n%v",
+ inputStr := ""
+ if m.input.Focused() {
+ boxStyle = boxStyle.Border(lipgloss.RoundedBorder(), true, true, true, true).Width(w)
+ inputStr = boxStyle.Render(m.input.View())
+ }
+
+ return fmt.Sprintf("%s\n%s\n%s\n%v\n%v\n%v",
tabs,
pickerView,
previewStr,
helpstr,
+ inputStr,
m.notices.View(),
)
}
@@ -131,7 +150,28 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
newNotices, cmd := m.notices.Update(msg)
m.notices = newNotices.(notices.Model)
cmds = append(cmds, cmd)
+
case tea.KeyMsg:
+
+ if m.input.Focused() {
+ keys.esc.SetEnabled(true)
+ keys.confirm.SetEnabled(true)
+ if key.Matches(msg, keys.esc) {
+ m.input.Blur()
+ } else if key.Matches(msg, keys.confirm) {
+ m.input.Blur()
+ cmds = append(
+ cmds,
+ m.NewNotice(m.SetColorFromText(m.input.Value())),
+ m.Init(), // Will force a slider update/animation
+ )
+ }
+ newInput, cmd := m.input.Update(msg)
+ m.input = newInput
+ cmds = append(cmds, cmd)
+ return m, tea.Batch(cmds...)
+ }
+
switch {
case key.Matches(msg, keys.next):
cs := m.pickers[m.active].GetColor()
@@ -143,31 +183,17 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.Prev()
m.pickers[m.active].SetColor(cs)
- case key.Matches(msg, keys.cpHex):
- cmd := m.notices.New(util.Copy(colors.Hex(m.pickers[m.active].GetColor())))
- cmds = append(cmds, cmd)
-
- case key.Matches(msg, keys.cpRgb):
- pc := m.pickers[m.active].GetColor().ToPrecise()
- rgb := colors.RGB{}.FromPrecise(pc).(colors.RGB)
- cmd := m.notices.New(util.Copy(rgb.String()))
- cmds = append(cmds, cmd)
-
- case key.Matches(msg, keys.cpHsl):
- pc := m.pickers[m.active].GetColor().ToPrecise()
- hsl := colors.HSL{}.FromPrecise(pc).(colors.HSL)
- cmd := m.notices.New(util.Copy(hsl.String()))
- cmds = append(cmds, cmd)
-
- case key.Matches(msg, keys.cpCmyk):
- pc := m.pickers[m.active].GetColor().ToPrecise()
- cmyk := colors.CMYK{}.FromPrecise(pc).(colors.CMYK)
- cmd := m.notices.New(util.Copy(cmyk.String()))
+ case key.Matches(msg, keys.copy):
+ cmd := m.notices.New(m.copyColor(msg.String()))
cmds = append(cmds, cmd)
case key.Matches(msg, keys.help):
m.fullHelp = !m.fullHelp
+ case key.Matches(msg, keys.insert):
+ cmd := m.input.Focus()
+ cmds = append(cmds, cmd)
+
case key.Matches(msg, keys.quit):
return quit.Model{}, tea.Quit
@@ -183,7 +209,6 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
newNotices, cmd := m.notices.Update(msg)
m.notices = newNotices.(notices.Model)
cmds = append(cmds, cmd)
-
return m, tea.Batch(cmds...)
}
default: