forked from charmbracelet/gum
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
01a6651
commit 969153b
Showing
10 changed files
with
312 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package date | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
|
||
tea "github.com/charmbracelet/bubbletea" | ||
"github.com/charmbracelet/gum/internal/exit" | ||
|
||
"github.com/fxtlabs/date" | ||
This comment has been minimized.
Sorry, something went wrong. |
||
) | ||
|
||
// Run provides a shell script interface for the text input bubble. | ||
This comment has been minimized.
Sorry, something went wrong. |
||
// https://github.com/charmbracelet/bubbles/textinput | ||
func (o Options) Run() error { | ||
picker := basePicker() | ||
|
||
picker.prompt = o.Prompt | ||
picker.promptStyle = o.PromptStyle.ToLipgloss() | ||
picker.cursorTextStyle = o.CursorTextStyle.ToLipgloss() | ||
if value, err := date.ParseISO(o.Value); err == nil { | ||
picker.Date = value | ||
} | ||
p := tea.NewProgram(model{ | ||
picker: picker, | ||
aborted: false, | ||
header: o.Header, | ||
headerStyle: o.HeaderStyle.ToLipgloss(), | ||
timeout: o.Timeout, | ||
hasTimeout: o.Timeout > 0, | ||
}, tea.WithOutput(os.Stderr)) | ||
tm, err := p.Run() | ||
if err != nil { | ||
return fmt.Errorf("failed to run input: %w", err) | ||
} | ||
m := tm.(model) | ||
|
||
if m.aborted { | ||
return exit.ErrAborted | ||
} | ||
|
||
fmt.Println(m.picker.Value()) | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
// Package date provides a shell script interface for picking a date. | ||
// | ||
// The date the user selected will be sent to stdout in ISO-8601 format: | ||
// YYYY-MM-DD. | ||
// | ||
// $ gum date --value 2023-11-28 > date.text | ||
package date | ||
|
||
import ( | ||
"time" | ||
|
||
tea "github.com/charmbracelet/bubbletea" | ||
"github.com/charmbracelet/gum/timeout" | ||
"github.com/charmbracelet/lipgloss" | ||
) | ||
|
||
type model struct { | ||
header string | ||
headerStyle lipgloss.Style | ||
picker *picker | ||
quitting bool | ||
aborted bool | ||
timeout time.Duration | ||
hasTimeout bool | ||
} | ||
|
||
func (m model) Init() tea.Cmd { | ||
return tea.Batch( | ||
timeout.Init(m.timeout, nil), | ||
) | ||
} | ||
|
||
func (m model) View() string { | ||
if m.quitting { | ||
return "" | ||
} | ||
if m.header != "" { | ||
header := m.headerStyle.Render(m.header) | ||
return lipgloss.JoinVertical(lipgloss.Left, header, m.picker.View()) | ||
} | ||
|
||
return m.picker.View() | ||
} | ||
|
||
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { | ||
switch msg := msg.(type) { | ||
case timeout.TickTimeoutMsg: | ||
if msg.TimeoutValue <= 0 { | ||
m.quitting = true | ||
m.aborted = true | ||
return m, tea.Quit | ||
} | ||
m.timeout = msg.TimeoutValue | ||
return m, timeout.Tick(msg.TimeoutValue, msg.Data) | ||
// case tea.WindowSizeMsg: | ||
This comment has been minimized.
Sorry, something went wrong. |
||
// if m.autoWidth { | ||
// m.textinput.Width = msg.Width - lipgloss.Width(m.textinput.Prompt) - 1 | ||
// } | ||
case tea.KeyMsg: | ||
switch msg.String() { | ||
case "ctrl+c", "esc": | ||
m.quitting = true | ||
m.aborted = true | ||
return m, tea.Quit | ||
case "enter": | ||
m.quitting = true | ||
return m, tea.Quit | ||
} | ||
} | ||
|
||
var cmd tea.Cmd | ||
m.picker, cmd = m.picker.Update(msg) | ||
return m, cmd | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package date | ||
|
||
import ( | ||
"time" | ||
|
||
"github.com/charmbracelet/gum/style" | ||
) | ||
|
||
// Options are the customization options for the date. | ||
type Options struct { | ||
Prompt string `help:"Prompt to display" default:"> " env:"GUM_DATE_PROMPT"` | ||
PromptStyle style.Styles `embed:"" prefix:"prompt." envprefix:"GUM_DATE_PROMPT_"` | ||
CursorTextStyle style.Styles `embed:"" prefix:"cursor." set:"defaultForeground=212" set:"defaultUnderline=true" envprefix:"GUM_DATE_CURSOR_"` //nolint:staticcheck | ||
Value string `help:"Initial value in ISO 8601 format, e.g. 2023-11-28" default:""` | ||
Header string `help:"Header value" default:"" env:"GUM_DATE_HEADER"` | ||
HeaderStyle style.Styles `embed:"" prefix:"header." set:"defaultForeground=240" envprefix:"GUM_DATE_HEADER_"` | ||
Timeout time.Duration `help:"Timeout until input aborts" default:"0" env:"GUM_DATE_TIMEOUT"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
package date | ||
|
||
import ( | ||
"strings" | ||
"time" | ||
|
||
tea "github.com/charmbracelet/bubbletea" | ||
"github.com/charmbracelet/lipgloss" | ||
"github.com/fxtlabs/date" | ||
) | ||
|
||
type interval int | ||
|
||
// Default styles. | ||
var ( | ||
weekdayStyle = lipgloss.NewStyle().Faint(true) | ||
defaultCursorTextStyle = lipgloss.NewStyle().Underline(true).Foreground(lipgloss.Color("201")) | ||
) | ||
|
||
const ( | ||
day interval = 0 | ||
month interval = 1 | ||
year interval = 2 | ||
) | ||
|
||
// incr i in direction d; bodge mod-3 indexing. | ||
func (i interval) incr(d direction) interval { | ||
mod := (int(i) + int(d)) % 3 | ||
if mod < 0 { | ||
return year | ||
} | ||
return interval(mod) | ||
} | ||
|
||
type direction int | ||
|
||
const ( | ||
forward direction = 1 | ||
backward direction = -1 | ||
) | ||
|
||
// picker implements tea.Model for a date.Date. | ||
type picker struct { | ||
date.Date | ||
focus interval | ||
|
||
promptStyle lipgloss.Style | ||
prompt string | ||
|
||
cursorTextStyle lipgloss.Style | ||
} | ||
|
||
func basePicker() *picker { | ||
return &picker{ | ||
Date: date.Today(), | ||
focus: day, | ||
prompt: "> ", | ||
cursorTextStyle: defaultCursorTextStyle, | ||
} | ||
} | ||
|
||
func (p *picker) formatDate() string { | ||
raw := p.Date.Format("02 Jan 2006") | ||
parts := strings.Split(raw, " ") | ||
parts[int(p.focus)] = p.cursorTextStyle.Render(parts[int(p.focus)]) | ||
return strings.Join(parts, " ") + " " + p.formatWeekday() | ||
} | ||
|
||
func (p *picker) formatWeekday() string { | ||
name := "" | ||
switch p.Date.Weekday() { | ||
case time.Monday: | ||
name = "Mon" | ||
case time.Tuesday: | ||
name = "Tue" | ||
case time.Wednesday: | ||
name = "Wed" | ||
case time.Thursday: | ||
name = "Thu" | ||
case time.Friday: | ||
name = "Fri" | ||
case time.Saturday: | ||
name = "Sat" | ||
case time.Sunday: | ||
name = "Sun" | ||
} | ||
return weekdayStyle.Render(name) | ||
} | ||
|
||
func (p *picker) incr(d direction) { | ||
switch p.focus { | ||
case day: | ||
p.Date = p.Date.AddDate(0, 0, int(d)) | ||
case month: | ||
p.Date = p.Date.AddDate(0, int(d), 0) | ||
case year: | ||
p.Date = p.Date.AddDate(int(d), 0, 0) | ||
} | ||
} | ||
|
||
// Init implements tea.Model. | ||
func (p *picker) Init() tea.Cmd { | ||
return nil | ||
} | ||
|
||
// Update implements tea.Model. | ||
func (p *picker) Update(msg tea.Msg) (*picker, tea.Cmd) { | ||
switch msg := msg.(type) { | ||
case tea.KeyMsg: | ||
switch msg.String() { | ||
// "up"/"down" increment/decrement the focused component, respectively | ||
case "up", "k": | ||
p.incr(forward) | ||
case "down", "j": | ||
p.incr(backward) | ||
|
||
// "left"/"right" cycle the focused component | ||
case "left", "h": | ||
p.focus = p.focus.incr(backward) | ||
case "right", "l": | ||
p.focus = p.focus.incr(forward) | ||
} | ||
} | ||
return p, nil | ||
} | ||
|
||
// View implements tea.Model. | ||
func (p *picker) View() string { | ||
return p.promptStyle.Render(p.prompt) + p.formatDate() | ||
} | ||
|
||
// Value of p. | ||
func (p *picker) Value() date.Date { | ||
return p.Date | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Revert.