package cli import ( "context" "fmt" "net" "net/http" "os" "github.com/spf13/cobra" "github.com/tamnd/kage/pack" "github.com/tamnd/kage/zim" ) func newOpenCmd() *cobra.Command { var addr string var openBrowser bool cmd := &cobra.Command{ Use: "open ", Short: "Serve a ZIM archive in your browser for offline reading", Long: "open serves a packed ZIM file over a local HTTP server so you can browse the\n" + "site exactly as it was cloned. It is the read side of kage pack --format zim.", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { return runOpen(cmd.Context(), args[0], addr, openBrowser) }, } cmd.Flags().StringVarP(&addr, "addr", "a", "127.0.0.1:8800", "address to listen on") cmd.Flags().BoolVar(&openBrowser, "open", true, "open the default browser") return cmd } func runOpen(ctx context.Context, path, addr string, openBrowser bool) error { r, err := zim.Open(path) if err != nil { return fmt.Errorf("cannot open %q: %w", path, err) } defer r.Close() ln, err := net.Listen("tcp", addr) if err != nil { return fmt.Errorf("cannot listen on %s: %w", addr, err) } url := "http://" + ln.Addr().String() fmt.Fprintln(os.Stderr, styleTitle.Render("kage open")+" "+styleDim.Render(path)) fmt.Fprintln(os.Stderr, " open "+styleAccent.Render(url)) fmt.Fprintln(os.Stderr, styleDim.Render(" press Ctrl-C to stop")) if openBrowser { _ = pack.OpenInBrowser(url) } srv := &http.Server{Handler: pack.Handler(r)} go func() { <-ctx.Done() _ = srv.Close() }() if err := srv.Serve(ln); err != nil && err != http.ErrServerClosed { return err } return nil }