arche / internal/cli/cmd_wiki.go

commit 154431fd
  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}