package ui import ( "fmt" "os" "os/exec" "strings" "time" gemlog "git.travisshears.com/travisshears/gemlog-cli/gemlog" tea "github.com/charmbracelet/bubbletea" "gopkg.in/yaml.v3" ) // TODO: add edit command // func EditPostCMD(config *gemlog.Config) tea.Cmd {} func WritePostCMD(config *gemlog.Config) tea.Cmd { return func() tea.Msg { // Create a temporary file tmpFile, err := os.CreateTemp("/tmp", "gemlog-*.md") if err != nil { return ErrorMsg{fmt.Errorf("failed to create temporary file: %w", err)} } // Load initial content from template file initialContent, err := os.ReadFile("templates/default_post.gmi") if err != nil { tmpFile.Close() os.Remove(tmpFile.Name()) return ErrorMsg{fmt.Errorf("failed to read template file: %w", err)} } if _, err := tmpFile.Write(initialContent); err != nil { tmpFile.Close() os.Remove(tmpFile.Name()) return ErrorMsg{fmt.Errorf("failed to write initial content: %w", err)} } tmpFile.Close() // Get the editor from environment variable, default to vim editor := os.Getenv("EDITOR") if editor == "" { editor = "vim" } // Create the command to open the editor with the temp file c := exec.Command(editor, tmpFile.Name()) //nolint:gosec // Return tea.ExecProcess which will suspend the TUI and run the editor return tea.ExecProcess(c, func(err error) tea.Msg { defer os.Remove(tmpFile.Name()) // Clean up the temp file if err != nil { return ErrorMsg{fmt.Errorf("editor command failed: %w", err)} } // Read the contents of the file after editing content, readErr := os.ReadFile(tmpFile.Name()) if readErr != nil { return ErrorMsg{fmt.Errorf("failed to read file contents: %w", readErr)} } gemlogEntry, err := parsePost(string(content)) if err != nil { return ErrorMsg{fmt.Errorf("failed to parse post: %w", err)} } if err := gemlog.SaveGemlogEntry(config, &gemlogEntry); err != nil { return ErrorMsg{fmt.Errorf("failed to save gemlog entry: %w", err)} } // Return success with the content return Notification(fmt.Sprintf("Post created: \ngemini://travisshears.com/gemlog/%s\n\n", gemlogEntry.Slug)) })() } } func parsePost(post string) (gemlog.GemlogEntry, error) { // split post on new lines lines := strings.Split(post, "\n") // Find the separator line "---" separatorIndex := -1 for i, line := range lines { if strings.TrimSpace(line) == "---" { separatorIndex = i break } } if separatorIndex == -1 { return gemlog.GemlogEntry{}, fmt.Errorf("no frontmatter separator '---' found") } // Extract frontmatter and body frontmatterLines := lines[:separatorIndex] bodyLines := lines[separatorIndex+1:] // Parse frontmatter YAML frontmatterYAML := strings.Join(frontmatterLines, "\n") var frontmatter struct { Title string `yaml:"title"` Date string `yaml:"date"` Slug string `yaml:"slug"` Tags string `yaml:"tags"` } if err := yaml.Unmarshal([]byte(frontmatterYAML), &frontmatter); err != nil { return gemlog.GemlogEntry{}, fmt.Errorf("failed to parse frontmatter: %w", err) } // Parse date date, err := time.Parse("2006-01-02", strings.TrimSpace(frontmatter.Date)) if err != nil { return gemlog.GemlogEntry{}, fmt.Errorf("failed to parse date: %w", err) } // Parse tags (comma-separated) var tags []string if frontmatter.Tags != "" { tagParts := strings.Split(frontmatter.Tags, ",") for _, tag := range tagParts { trimmed := strings.TrimSpace(tag) if trimmed != "" { tags = append(tags, trimmed) } } } // Join body lines body := strings.Join(bodyLines, "\n") return gemlog.GemlogEntry{ Title: frontmatter.Title, Date: date, Slug: frontmatter.Slug, Tags: tags, Gemtxt: body, }, nil }