package main import ( "fmt" "os" "os/exec" "github.com/charmbracelet/bubbles/textinput" tea "github.com/charmbracelet/bubbletea" ) type detailsModel struct { returnTo tea.Model validationMsg string snippet snippetDetails ti textinput.Model } type snippetDetails struct { name string prevName string contents string } func (m detailsModel) Init() tea.Cmd { return nil } func (m detailsModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { var cmd tea.Cmd switch msg := msg.(type) { case tea.KeyMsg: switch msg.Type { case tea.KeyEnter: m.snippet.name = m.ti.Value() if len(m.snippet.name) == 0 || len(m.snippet.name) > 250 { m.validationMsg = "Name must be 0-250 characters" return m, nil } return m.returnTo, tea.Batch(m.returnTo.Init(), saveSnippetCmd(m.snippet)) case tea.KeyCtrlC, tea.KeyEsc: // exit without saving return m.returnTo, m.returnTo.Init() } case fatalErrorMsg: fmt.Printf("encountered fatal error: %s\n", msg.Error()) return m, tea.Quit } m.ti, cmd = m.ti.Update(msg) return m, cmd } func (m detailsModel) View() string { out := "Enter snippet name\n" out += errorTextStyle.Render(m.validationMsg) + "\n" out += m.ti.View() return appStyle.Render(out) } func switchToDetails(returnTo tea.Model, snippet snippetDetails) (tea.Model, tea.Cmd) { ti := textinput.New() ti.Placeholder = "Snippet name" ti.Focus() ti.CharLimit = 250 ti.SetValue(snippet.name) m := detailsModel{returnTo, "", snippet, ti} return m, m.Init() } func saveSnippetCmd(snippet snippetDetails) tea.Cmd { return func() tea.Msg { err := saveSnippet(snippet) if err != nil { return fatalErrorMsg(err) } return updateListMsg{} } } type updateListMsg struct{} type vimFinishedMsg struct { snippet snippetDetails err error } func newItemCmd() tea.Cmd { return editContentsCmd("", snippetDetails{}) } func editItemCmd(item item) tea.Cmd { return editContentsCmd(item.contents, snippetDetails{name: item.title, prevName: item.title, contents: item.contents}) } func deleteItemCmd(item item) tea.Cmd { return func() tea.Msg { err := deleteItem(item) if err != nil { return fatalErrorMsg(err) } return updateListMsg{} } } func editContentsCmd(existingContents string, snippet snippetDetails) tea.Cmd { f, _ := os.CreateTemp("", "doe.sh") name := f.Name() f.WriteString(existingContents) f.Close() c := exec.Command("vim", f.Name()) return tea.ExecProcess(c, func(err error) tea.Msg { contents, _ := os.ReadFile(name) snippet.contents = string(contents) return vimFinishedMsg{snippet, err} }) }