1package cli
2
3import (
4 "fmt"
5 "io"
6 "os"
7 "time"
8
9 "arche/internal/issuedb"
10
11 "github.com/spf13/cobra"
12)
13
14var wikiCmd = &cobra.Command{
15 Use: "wiki",
16 Short: "Manage the embedded wiki",
17 Long: `Read and write pages in the repository's embedded wiki.
18
19 arche wiki list - list all wiki pages
20 arche wiki get <title> - print a page's Markdown content
21 arche wiki set <title> - create or update a page (reads from stdin)
22 arche wiki set <title> -f file - create or update a page from a file`,
23}
24
25var wikiListCmd = &cobra.Command{
26 Use: "list",
27 Short: "List all wiki pages",
28 Args: cobra.NoArgs,
29 RunE: func(cmd *cobra.Command, args []string) error {
30 r := openRepo()
31 defer r.Close()
32
33 idb, err := issuedb.Open(r.ArcheDir())
34 if err != nil {
35 return fmt.Errorf("open issuedb: %w", err)
36 }
37 defer idb.Close()
38
39 pages, err := idb.Wiki.List()
40 if err != nil {
41 return err
42 }
43 if len(pages) == 0 {
44 fmt.Println("No wiki pages yet. Create one with: arche wiki set <title>")
45 return nil
46 }
47 for _, p := range pages {
48 updated := time.Unix(p.Updated, 0).Format("2006-01-02")
49 fmt.Printf("%-40s %s %s\n", p.Title, updated, p.Author)
50 }
51 return nil
52 },
53}
54
55var wikiGetCmd = &cobra.Command{
56 Use: "get <title>",
57 Short: "Print a wiki page's Markdown content",
58 Args: cobra.ExactArgs(1),
59 RunE: func(cmd *cobra.Command, args []string) error {
60 r := openRepo()
61 defer r.Close()
62
63 idb, err := issuedb.Open(r.ArcheDir())
64 if err != nil {
65 return fmt.Errorf("open issuedb: %w", err)
66 }
67 defer idb.Close()
68
69 page, err := idb.Wiki.Get(args[0])
70 if err != nil {
71 return err
72 }
73 fmt.Print(page.Content)
74 if len(page.Content) > 0 && page.Content[len(page.Content)-1] != '\n' {
75 fmt.Println()
76 }
77 return nil
78 },
79}
80
81var wikiSetFile string
82
83var wikiSetCmd = &cobra.Command{
84 Use: "set <title>",
85 Short: "Create or update a wiki page",
86 Long: `Create or update the wiki page with the given title.
87
88Content is read from stdin unless --file is given:
89
90 echo "# Hello" | arche wiki set "Getting Started"
91 arche wiki set "Getting Started" --file docs/getting-started.md`,
92 Args: cobra.ExactArgs(1),
93 RunE: func(cmd *cobra.Command, args []string) error {
94 r := openRepo()
95 defer r.Close()
96
97 var content []byte
98 var err error
99 if wikiSetFile != "" {
100 content, err = os.ReadFile(wikiSetFile)
101 if err != nil {
102 return fmt.Errorf("read file: %w", err)
103 }
104 } else {
105 content, err = io.ReadAll(os.Stdin)
106 if err != nil {
107 return fmt.Errorf("read stdin: %w", err)
108 }
109 }
110 if len(content) == 0 {
111 return fmt.Errorf("page content is empty")
112 }
113
114 idb, err := issuedb.Open(r.ArcheDir())
115 if err != nil {
116 return fmt.Errorf("open issuedb: %w", err)
117 }
118 defer idb.Close()
119
120 author := r.Cfg.User.Name
121 if author == "" {
122 author = "unknown"
123 }
124 title := args[0]
125 if err := idb.Wiki.Set(title, string(content), author); err != nil {
126 return err
127 }
128 fmt.Printf("Wiki page %q saved.\n", title)
129 return nil
130 },
131}
132
133func init() {
134 wikiSetCmd.Flags().StringVarP(&wikiSetFile, "file", "f", "", "Read content from this file instead of stdin")
135
136 wikiCmd.AddCommand(wikiListCmd, wikiGetCmd, wikiSetCmd)
137}