From ddea614772e60bc64d7176a2d9e6ba9a770fd68b Mon Sep 17 00:00:00 2001 From: majiayu000 <1835304752@qq.com> Date: Wed, 31 Dec 2025 07:47:26 +0800 Subject: [PATCH] fix: improve error reporting instead of silent exit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace silent exits and crashes with proper error messages: - main.go: Exit with code 1 on parse errors (not 0), print error to stderr - list.go: Show status messages instead of silent tea.Quit on errors - viewport.go: Return to list view with error message on failures - commands.go: Replace log.Fatal with log.Printf to avoid crashes - tui.go: Skip invalid regex patterns with log instead of crashing Closes #170 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 Signed-off-by: majiayu000 <1835304752@qq.com> --- cmd/nom/main.go | 10 ++++++---- internal/commands/commands.go | 6 ++++-- internal/commands/list.go | 10 +++++----- internal/commands/tui.go | 3 ++- internal/commands/viewport.go | 24 ++++++++++++++++-------- 5 files changed, 33 insertions(+), 20 deletions(-) diff --git a/cmd/nom/main.go b/cmd/nom/main.go index e9290d7..e916dca 100755 --- a/cmd/nom/main.go +++ b/cmd/nom/main.go @@ -160,11 +160,13 @@ func main() { _, err := parser.Parse() // check for help flag if err != nil { - if flagErr, ok := err.(*flags.Error); ok && flagErr.Type != flags.ErrHelp { - parser.WriteHelp(os.Stdout) + if flagErr, ok := err.(*flags.Error); ok && flagErr.Type == flags.ErrHelp { + os.Exit(0) } - - os.Exit(0) + // For actual errors, print help and exit with error code + fmt.Fprintf(os.Stderr, "Error: %s\n\n", err) + parser.WriteHelp(os.Stderr) + os.Exit(1) } // no subcommand or help flag, run the TUI diff --git a/internal/commands/commands.go b/internal/commands/commands.go index d87ea88..5caf507 100644 --- a/internal/commands/commands.go +++ b/internal/commands/commands.go @@ -251,7 +251,7 @@ func (c Commands) fetchAllFeeds() ([]store.Item, []ErrorItem, error) { err := c.store.UpsertItem(&i) if err != nil { - log.Fatalf("[commands.go] fetchAllFeeds: %e", err) + log.Printf("[commands.go] fetchAllFeeds: failed to upsert item: %v", err) continue } @@ -381,7 +381,9 @@ func htmlToMd(html string) string { mdown, err := converter.ConvertString(html) if err != nil { - log.Fatal(err) + log.Printf("[commands.go] htmlToMd: failed to convert HTML to markdown: %v", err) + // Return the original HTML if conversion fails + return html } return mdown diff --git a/internal/commands/list.go b/internal/commands/list.go index a5eb142..7ea97d6 100644 --- a/internal/commands/list.go +++ b/internal/commands/list.go @@ -84,7 +84,7 @@ func (d itemDelegate) Render(w io.Writer, m list.Model, index int, listItem list func (m *model) UpdateList() tea.Cmd { fs, err := m.commands.GetAllFeeds() if err != nil { - return tea.Quit + return m.list.NewStatusMessage(fmt.Sprintf("Error: %s", err)) } cmd := m.list.SetItems(convertItems(fs)) @@ -211,7 +211,7 @@ func updateList(msg tea.Msg, m model) (tea.Model, tea.Cmd) { current := item.(TUIItem) err := m.commands.store.ToggleRead(current.ID) if err != nil { - return m, tea.Quit + return m, m.list.NewStatusMessage(fmt.Sprintf("Error marking read: %s", err)) } cmds = append(cmds, m.UpdateList()) @@ -249,7 +249,7 @@ func updateList(msg tea.Msg, m model) (tea.Model, tea.Cmd) { current := item.(TUIItem) err := m.commands.store.ToggleFavourite(current.ID) if err != nil { - return m, tea.Quit + return m, m.list.NewStatusMessage(fmt.Sprintf("Error toggling favourite: %s", err)) } cmds = append(cmds, m.UpdateList()) @@ -308,8 +308,8 @@ func updateList(msg tea.Msg, m model) (tea.Model, tea.Cmd) { content, err := m.commands.GetGlamourisedArticle(*m.selectedArticle) if err != nil { - // LKS: there should be an error message here - return m, tea.Quit + m.selectedArticle = nil + return m, m.list.NewStatusMessage(fmt.Sprintf("Error opening article: %s", err)) } m.viewport.SetContent(content) diff --git a/internal/commands/tui.go b/internal/commands/tui.go index 2df8355..43cbd56 100644 --- a/internal/commands/tui.go +++ b/internal/commands/tui.go @@ -98,7 +98,8 @@ func (m model) OpenLink(url string) tea.Cmd { for _, o := range m.cfg.Openers { match, err := regexp.MatchString(o.Regex, url) if err != nil { - return tea.Quit + log.Printf("[tui.go] OpenLink: invalid regex pattern: %v", err) + continue } if match { diff --git a/internal/commands/viewport.go b/internal/commands/viewport.go index e6bfb58..c14db3b 100644 --- a/internal/commands/viewport.go +++ b/internal/commands/viewport.go @@ -42,7 +42,8 @@ func updateViewport(msg tea.Msg, m model) (tea.Model, tea.Cmd) { case key.Matches(msg, ViewportKeyMap.OpenInBrowser): current, err := m.commands.store.GetItemByID(*m.selectedArticle) if err != nil { - return m, nil + m.selectedArticle = nil + return m, m.list.NewStatusMessage("Error: failed to get article") } it := ItemToTUIItem(current) @@ -52,11 +53,13 @@ func updateViewport(msg tea.Msg, m model) (tea.Model, tea.Cmd) { case key.Matches(msg, ViewportKeyMap.Favourite): current, err := m.commands.store.GetItemByID(*m.selectedArticle) if err != nil { - return m, nil + m.selectedArticle = nil + return m, m.list.NewStatusMessage("Error: failed to get article") } err = m.commands.store.ToggleFavourite(current.ID) if err != nil { - return m, tea.Quit + m.selectedArticle = nil + return m, m.list.NewStatusMessage("Error toggling favourite") } case key.Matches(msg, ViewportKeyMap.Read): @@ -65,11 +68,13 @@ func updateViewport(msg tea.Msg, m model) (tea.Model, tea.Cmd) { } current, err := m.commands.store.GetItemByID(*m.selectedArticle) if err != nil { - return m, nil + m.selectedArticle = nil + return m, m.list.NewStatusMessage("Error: failed to get article") } err = m.commands.store.ToggleRead(current.ID) if err != nil { - return m, tea.Quit + m.selectedArticle = nil + return m, m.list.NewStatusMessage("Error marking read") } if !m.commands.config.ShowRead { @@ -93,7 +98,8 @@ func updateViewport(msg tea.Msg, m model) (tea.Model, tea.Cmd) { // trigger refresh to update read indication content, err := m.commands.GetGlamourisedArticle(*m.selectedArticle) if err != nil { - return m, tea.Quit + m.selectedArticle = nil + return m, m.list.NewStatusMessage("Error rendering article") } m.viewport.SetContent(content) @@ -111,7 +117,8 @@ func updateViewport(msg tea.Msg, m model) (tea.Model, tea.Cmd) { content, err := m.commands.GetGlamourisedArticle(*m.selectedArticle) if err != nil { - return m, tea.Quit + m.selectedArticle = nil + return m, m.list.NewStatusMessage("Error rendering article") } m.viewport.SetContent(content) @@ -134,7 +141,8 @@ func updateViewport(msg tea.Msg, m model) (tea.Model, tea.Cmd) { content, err := m.commands.GetGlamourisedArticle(*m.selectedArticle) if err != nil { - return m, tea.Quit + m.selectedArticle = nil + return m, m.list.NewStatusMessage("Error rendering article") } m.viewport.SetContent(content)