Added cli module with first papero subcommand
This commit is contained in:
parent
54a31ad825
commit
87c86a8090
5 changed files with 275 additions and 1 deletions
137
cli/papero/info.go
Normal file
137
cli/papero/info.go
Normal file
|
@ -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
cli/papero/main.go
Normal file
85
cli/papero/main.go
Normal file
|
@ -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
cli/utils.go
Normal file
38
cli/utils.go
Normal file
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
4
go.mod
4
go.mod
|
@ -4,7 +4,9 @@ go 1.15
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/BurntSushi/toml v0.3.1
|
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/google/go-cmp v0.5.4
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
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
go.sum
12
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/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/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
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 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
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=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
|
Loading…
Reference in a new issue