diff --git a/go.mod b/go.mod index 8d0cbaf..f897371 100644 --- a/go.mod +++ b/go.mod @@ -5,14 +5,17 @@ go 1.21.6 require ( github.com/charmbracelet/bubbles v0.18.0 github.com/charmbracelet/bubbletea v0.26.2 + github.com/charmbracelet/huh v0.3.0 github.com/charmbracelet/lipgloss v0.10.0 ) require ( + github.com/atotto/clipboard v0.1.4 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect + github.com/catppuccin/go v0.2.0 // indirect github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect - github.com/mattn/go-isatty v0.0.18 // 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.15 // indirect github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect @@ -23,7 +26,7 @@ require ( golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.20.0 // indirect golang.org/x/term v0.20.0 // indirect - golang.org/x/text v0.3.8 // indirect + golang.org/x/text v0.13.0 // indirect ) replace github.com/jshawl/abcd v0.0.0 => ./ diff --git a/go.sum b/go.sum index 1b8e96a..001953a 100644 --- a/go.sum +++ b/go.sum @@ -1,17 +1,23 @@ +github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= +github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= 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/catppuccin/go v0.2.0 h1:ktBeIrIP42b/8FGiScP9sgrWOss3lw0Z5SktRoithGA= +github.com/catppuccin/go v0.2.0/go.mod h1:8IHJuMGaUUjQM82qBrGNBv7LFq6JI3NnQCF6MOlZjpc= github.com/charmbracelet/bubbles v0.18.0 h1:PYv1A036luoBGroX6VWjQIE9Syf2Wby2oOl/39KLfy0= github.com/charmbracelet/bubbles v0.18.0/go.mod h1:08qhZhtIwzgrtBjAcJnij1t1H0ZRjwHyGsy6AL11PSw= github.com/charmbracelet/bubbletea v0.26.2 h1:Eeb+n75Om9gQ+I6YpbCXQRKHt5Pn4vMwusQpwLiEgJQ= github.com/charmbracelet/bubbletea v0.26.2/go.mod h1:6I0nZ3YHUrQj7YHIHlM8RySX4ZIthTliMY+W8X8b+Gs= +github.com/charmbracelet/huh v0.3.0 h1:CxPplWkgW2yUTDDG0Z4S5HH8SJOosWHd4LxCvi0XsKE= +github.com/charmbracelet/huh v0.3.0/go.mod h1:fujUdKX8tC45CCSaRQdw789O6uaCRwx8l2NDyKfC4jA= github.com/charmbracelet/lipgloss v0.10.0 h1:KWeXFSexGcfahHX+54URiZGkBFazf70JNMtwg/AFW3s= github.com/charmbracelet/lipgloss v0.10.0/go.mod h1:Wig9DSfvANsxqkRsqj6x87irdy123SR4dOXlKa91ciE= 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/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= -github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= -github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +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.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= @@ -37,5 +43,5 @@ golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= -golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= diff --git a/ui/command.go b/ui/command.go new file mode 100644 index 0000000..ecd2240 --- /dev/null +++ b/ui/command.go @@ -0,0 +1,70 @@ +package ui + +import ( + "strings" + + tea "github.com/charmbracelet/bubbletea" + "github.com/charmbracelet/huh" + "github.com/charmbracelet/lipgloss" +) + +type Command struct { + isOpen bool + form *huh.Form +} + +type commandMsg string + +func (m Command) Init() tea.Cmd { + return m.form.Init() +} + +func NewCommand(args []string) Command { + cur := strings.Join(args, " ") + m := Command{} + m.form = huh.NewForm( + huh.NewGroup( + huh.NewInput(). + Key("cmd"). + Title("Change command:"). + Prompt("git diff "). + Value(&cur), + ), + ) + return m +} + +func (m Command) Update(msg tea.Msg) (Command, tea.Cmd) { + var cmds []tea.Cmd + switch msg := msg.(type) { + case tea.KeyMsg: + k := msg.String() + if m.isOpen { + if k == "enter" { + m.isOpen = false + } + } else { + if k == "c" { + m.isOpen = !m.isOpen + } + return m, nil + } + } + form, cmd := m.form.Update(msg) + cmds = append(cmds, cmd) + if f, ok := form.(*huh.Form); ok { + m.form = f + gitDiffArgs := f.GetString("cmd") + if m.form.State == huh.StateCompleted { + m = NewCommand([]string{gitDiffArgs}) + nextCommand := func() tea.Msg { return commandMsg(gitDiffArgs) } + cmds = append(cmds, m.Init(), nextCommand) + } + } + return m, tea.Batch(cmds...) +} + +func (m Command) View() string { + style := lipgloss.NewStyle().Padding(1, 2) + return style.Render(m.form.View()) +} diff --git a/ui/diff.go b/ui/diff.go index 58f3777..37fc345 100644 --- a/ui/diff.go +++ b/ui/diff.go @@ -118,6 +118,9 @@ func (m Diff) Update(msg tea.Msg) (Diff, tea.Cmd) { ) switch msg := msg.(type) { + case commandMsg: + m.args = strings.Split(string(msg), " ") + cmds = append(cmds, m.Tick(true)) case tea.KeyMsg: k := msg.String() if k == "s" { diff --git a/ui/help.go b/ui/help.go index 5456e23..629e0b0 100644 --- a/ui/help.go +++ b/ui/help.go @@ -20,6 +20,7 @@ func NewHelp() Help { "?": "toggle help", "q": "quit", "s": "toggle --staged", + "c": "change git diff command arguments", "tab": "jump to next file", }, } diff --git a/ui/main.go b/ui/main.go index 3580c3f..14b30f1 100644 --- a/ui/main.go +++ b/ui/main.go @@ -10,12 +10,13 @@ import ( ) type model struct { - diff Diff - help Help + command Command + diff Diff + help Help } func (m model) Init() tea.Cmd { - return m.diff.Init() + return tea.Batch(m.diff.Init(), m.command.Init()) } func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { @@ -31,6 +32,9 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.help, _ = m.help.Update(msg) } + m.command, cmd = m.command.Update(msg) + cmds = append(cmds, cmd) + m.diff, cmd = m.diff.Update(msg) cmds = append(cmds, cmd) @@ -38,11 +42,14 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } func (m model) View() string { + if m.command.isOpen { + return m.command.View() + } if m.help.isOpen { return m.help.View() - } else { - return fmt.Sprintf("%s %s", m.diff.View(), m.help.View()) } + + return fmt.Sprintf("%s %s", m.diff.View(), m.help.View()) } func Render() { @@ -61,10 +68,13 @@ func Render() { staged := flag.Bool("staged", false, "diff --staged ?") flag.Parse() + args := flag.Args() + p := tea.NewProgram( model{ - help: NewHelp(), - diff: NewDiff(*staged, flag.Args()), + help: NewHelp(), + diff: NewDiff(*staged, args), + command: NewCommand(args), }, tea.WithAltScreen(), tea.WithMouseCellMotion(),