add.go

 1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
 2//
 3// SPDX-License-Identifier: AGPL-3.0-or-later
 4
 5package journal
 6
 7import (
 8	"fmt"
 9	"os"
10	"strings"
11
12	"git.secluded.site/go-lunatask"
13	"git.secluded.site/lune/internal/client"
14	"git.secluded.site/lune/internal/dateutil"
15	"git.secluded.site/lune/internal/ui"
16	"github.com/spf13/cobra"
17)
18
19// AddCmd creates a journal entry. Exported for use by the jrnl shortcut.
20var AddCmd = &cobra.Command{
21	Use:   "add [CONTENT]",
22	Short: "Create a journal entry",
23	Long: `Create a journal entry in Lunatask.
24
25Creates an entry for today by default. Use --date to specify another date
26using natural language (e.g., "yesterday", "last friday", "2024-01-15").
27
28Content supports Markdown formatting for rich text entries.
29Use "-" as CONTENT to read from stdin (useful for piping or multi-line input).`,
30	RunE: runAdd,
31}
32
33func init() {
34	AddCmd.Flags().StringP("date", "d", "", "Entry date (natural language, default: today)")
35	AddCmd.Flags().StringP("name", "n", "", "Entry title (omit to use weekday name)")
36}
37
38func runAdd(cmd *cobra.Command, args []string) error {
39	date, err := dateutil.Parse(cmd.Flag("date").Value.String())
40	if err != nil {
41		return err
42	}
43
44	content, err := resolveContent(args)
45	if err != nil {
46		return err
47	}
48
49	apiClient, err := client.New()
50	if err != nil {
51		return err
52	}
53
54	builder := apiClient.NewJournalEntry(date)
55
56	if content != "" {
57		builder.WithContent(content)
58	}
59
60	if name := cmd.Flag("name").Value.String(); name != "" {
61		builder.WithName(name)
62	}
63
64	entry, err := ui.Spin("Creating journal entry…", func() (*lunatask.JournalEntry, error) {
65		return builder.Create(cmd.Context())
66	})
67	if err != nil {
68		return err
69	}
70
71	fmt.Fprintln(cmd.OutOrStdout(), ui.Success.Render("Created journal entry: "+entry.ID))
72
73	return nil
74}
75
76func resolveContent(args []string) (string, error) {
77	if len(args) == 0 {
78		return "", nil
79	}
80
81	if args[0] != "-" {
82		return strings.Join(args, " "), nil
83	}
84
85	data, err := os.ReadFile("/dev/stdin")
86	if err != nil {
87		return "", fmt.Errorf("reading stdin: %w", err)
88	}
89
90	return strings.TrimSpace(string(data)), nil
91}