Browse Source

Added cli module with first papero subcommand

Blallo 3 years ago
parent
commit
87c86a8090
5 changed files with 275 additions and 1 deletions
  1. 137 0
      cli/papero/info.go
  2. 85 0
      cli/papero/main.go
  3. 38 0
      cli/utils.go
  4. 3 1
      go.mod
  5. 12 0
      go.sum

+ 137 - 0
cli/papero/info.go

@@ -0,0 +1,137 @@
+package main
+
+import (
+	"flag"
+	"fmt"
+	"io"
+	"os"
+
+	"git.lattuga.net/blallo/papero/cli"
+	"git.lattuga.net/blallo/papero/imaputils"
+)
+
+var infoVerbs cli.CommandMap
+
+func init() {
+	lsMailbox := LsMailboxCmd{}
+	lsMessages := LsMsgCmd{}
+	catMessage := CatMsgCmd{}
+	infoVerbs = cli.CommandMap{
+		"list-mailboxes":  lsMailbox,
+		"list-messages":   lsMessages,
+		"display-message": catMessage,
+	}
+}
+
+type InfoCmd struct{}
+
+func (i InfoCmd) Func(args []string) error {
+	flagset := flag.NewFlagSet(args[0], flag.ExitOnError)
+	flagset.Usage = func() { i.Help(os.Stdout, flagset) }
+	flagset.Parse(args[1:])
+	subArgs := flagset.Args()
+	if len(subArgs) == 0 {
+		i.Help(os.Stderr, flagset)
+		os.Exit(1)
+	}
+	cmd := subArgs[0]
+	if Session.Info.Opts.Debug {
+		Log.Debug("info verb:", cmd)
+	}
+
+	return infoVerbs[cmd].Func(subArgs)
+}
+
+func (i InfoCmd) Help(w io.Writer, set *flag.FlagSet) {
+	fmt.Fprintf(w, "USAGE: %s info VERB [verb opts]\n", Session.Info.Name)
+	fmt.Fprintf(w, "\nVERBS:\n")
+	for verb := range infoVerbs {
+		fmt.Fprintf(w, "\t%s\n", verb)
+	}
+}
+
+// VERBS
+
+type LsMailboxCmd struct{}
+
+func (l LsMailboxCmd) Func(args []string) error {
+	if Session.Info.Opts.Debug {
+		Log.Debug("enter info list-mailboxes")
+	}
+	var withAttributes bool
+	flagset := flag.NewFlagSet(args[0], flag.ExitOnError)
+	flagset.BoolVar(&withAttributes, "with-attrs", false, "toggle attributes display")
+	flagset.Usage = func() { l.Help(os.Stdout, flagset) }
+	flagset.Parse(args[1:])
+
+	mboxInfo, err := imaputils.ListMailboxes(Session.Config, Session.Info.Opts.Debug)
+	if err != nil {
+		return err
+	}
+	if Session.Info.Opts.Debug {
+		Log.Debug(mboxInfo)
+	}
+	for _, box := range mboxInfo {
+		if withAttributes {
+			attrs := fmt.Sprint(box.Attributes)
+			fmt.Printf("%s (attrs: %s)", box.Name, attrs)
+		} else {
+			fmt.Println(box.Name)
+		}
+	}
+	return nil
+}
+
+func (l LsMailboxCmd) Help(w io.Writer, set *flag.FlagSet) {
+	fmt.Fprintf(w, "USAGE: %s info list-mailboxes\n", Session.Info.Name)
+	set.PrintDefaults()
+}
+
+type LsMsgCmd struct{}
+
+func (l LsMsgCmd) Func(args []string) error {
+	if Session.Info.Opts.Debug {
+		Log.Debug("enter info list-messages")
+	}
+	var limit uint
+	flagset := flag.NewFlagSet(args[0], flag.ExitOnError)
+	flagset.UintVar(&limit, "limit", 0, "maximum number of messages to display (0 means no limit)")
+	flagset.Usage = func() { l.Help(os.Stdout, flagset) }
+	flagset.Parse(args[1:])
+
+	subArgs := flagset.Args()
+	if len(subArgs) != 1 {
+		l.Help(os.Stderr, flagset)
+		os.Exit(1)
+	}
+	return nil
+}
+
+func (l LsMsgCmd) Help(w io.Writer, set *flag.FlagSet) {
+	fmt.Fprintf(w, "USAGE: %s info list-messages [opts] MAILBOX_NAME\n", Session.Info.Name)
+	fmt.Fprintf(w, "\nOPTS:\n")
+	set.PrintDefaults()
+}
+
+type CatMsgCmd struct{}
+
+func (c CatMsgCmd) Func(args []string) error {
+	if Session.Info.Opts.Debug {
+		Log.Debug("enter info display-message")
+	}
+	flagset := flag.NewFlagSet(args[0], flag.ExitOnError)
+	flagset.Usage = func() { c.Help(os.Stdout, flagset) }
+	flagset.Parse(args[1:])
+
+	subArgs := flagset.Args()
+	if len(subArgs) != 1 {
+		c.Help(os.Stderr, flagset)
+		os.Exit(1)
+	}
+	return nil
+}
+
+func (c CatMsgCmd) Help(w io.Writer, set *flag.FlagSet) {
+	fmt.Fprintf(w, "USAGE: %s info display-message MAILBOX_NAME MESSAGE_ID\n", Session.Info.Name)
+	set.PrintDefaults()
+}

+ 85 - 0
cli/papero/main.go

@@ -0,0 +1,85 @@
+package main
+
+import (
+	"flag"
+	"os"
+
+	"git.lattuga.net/blallo/papero/cli"
+	"git.lattuga.net/blallo/papero/config"
+	"github.com/withmandala/go-log"
+)
+
+var Session struct {
+	Info   cli.ProgramInfo
+	Config *config.AccountData
+}
+var Log *log.Logger
+
+func init() {
+	info := InfoCmd{}
+	Session.Info.Commands = cli.CommandMap{
+		"info": info,
+	}
+	Session.Info.Name = "papero"
+	flag.Usage = func() { cli.Usage(os.Stdout, Session.Info) }
+	Log = log.New(os.Stdout)
+}
+
+func main() {
+	var configPath string
+	flag.StringVar(&Session.Info.Opts.ConfigPath, "config", "", "path to the configuration")
+	flag.BoolVar(&Session.Info.Opts.Debug, "debug", false, "execute in debug mode")
+	flag.StringVar(&Session.Info.Opts.ConfigStanza, "account", "", "specify which account to use")
+	flag.Parse()
+
+	args := flag.Args()
+	if len(args) == 0 {
+		cli.Usage(os.Stderr, Session.Info)
+		os.Exit(1)
+	}
+
+	if Session.Info.Opts.Debug {
+		Log.WithDebug()
+		Log.Debugf(
+			"opts -> config: %s\tdebug: %v\taccount: %s\n",
+			Session.Info.Opts.ConfigPath,
+			Session.Info.Opts.Debug,
+			Session.Info.Opts.ConfigStanza,
+		)
+	}
+
+	if Session.Info.Opts.ConfigPath == "" {
+		var err error
+		configPath, err = config.Find()
+		if err != nil {
+			Log.Fatal(err)
+		}
+	} else {
+		configPath = Session.Info.Opts.ConfigPath
+	}
+
+	fullConfig, err := config.Parse(configPath)
+	if err != nil {
+		os.Exit(2)
+	}
+
+	var ok bool
+	var account string
+	if Session.Info.Opts.ConfigStanza != "" {
+		account = Session.Info.Opts.ConfigStanza
+		Session.Config, ok = fullConfig.Accounts[account]
+	} else {
+		account = fullConfig.Default
+		Session.Config, ok = fullConfig.Accounts[account]
+	}
+	if !ok {
+		Log.Error("Account not found in config:", account)
+		os.Exit(2)
+	}
+
+	err = Session.Info.Commands[args[0]].Func(args)
+	if err != nil {
+		Log.Error(err)
+		os.Exit(-1)
+	}
+}

+ 38 - 0
cli/utils.go

@@ -0,0 +1,38 @@
+package cli
+
+import (
+	"flag"
+	"fmt"
+	"io"
+)
+
+type GlobalOpts struct {
+	ConfigPath   string
+	Debug        bool
+	ConfigStanza string
+}
+
+func (o GlobalOpts) String() string {
+	return "--config --debug --account"
+}
+
+type Command interface {
+	Func([]string) error
+	Help(io.Writer, *flag.FlagSet)
+}
+
+type CommandMap map[string]Command
+
+type ProgramInfo struct {
+	Name     string
+	Opts     GlobalOpts
+	Commands CommandMap
+}
+
+func Usage(w io.Writer, info ProgramInfo) {
+	fmt.Fprintf(w, "USAGE: %s [%s] SUBCOMMAND [subcommand opts]\n", info.Name, info.Opts)
+	fmt.Fprintf(w, "\nSUBCOMMANDS:\n")
+	for command := range info.Commands {
+		fmt.Fprintf(w, "\t%s\n", command)
+	}
+}

+ 3 - 1
go.mod

@@ -4,7 +4,9 @@ go 1.15
 
 require (
 	github.com/BurntSushi/toml v0.3.1
-	github.com/emersion/go-imap v1.0.6 // indirect
+	github.com/emersion/go-imap v1.0.6
 	github.com/google/go-cmp v0.5.4
 	github.com/mitchellh/go-homedir v1.1.0
+	github.com/withmandala/go-log v0.1.0
+	golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad // indirect
 )

+ 12 - 0
go.sum

@@ -16,6 +16,18 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/withmandala/go-log v0.1.0 h1:wINmTEe7BQ6zEA8sE7lSsYeaxCLluK6RFjF/IB5tzkA=
+github.com/withmandala/go-log v0.1.0/go.mod h1:/V9xQUTW74VjYm3u2Liv/bIUGLWoL9z2GlHwtscp4vg=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
+golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
+golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM=
+golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=