aboutsummaryrefslogtreecommitdiffstats
path: root/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'cmd')
-rw-r--r--cmd/lulu/flag.go86
-rw-r--r--cmd/lulu/main.go117
-rw-r--r--cmd/lulu/validate_cover.go44
-rw-r--r--cmd/lulu/validate_interior.go63
4 files changed, 174 insertions, 136 deletions
diff --git a/cmd/lulu/flag.go b/cmd/lulu/flag.go
index a981886..0103dfc 100644
--- a/cmd/lulu/flag.go
+++ b/cmd/lulu/flag.go
@@ -11,12 +11,21 @@ import (
"unicode"
)
+func nPagesFlag(nPages *uint) Flag {
+ return Flag{&uintValue{p: nPages}, "n", "Number of interior pages"}
+}
+
type Flag struct {
- val flag.Value
+ val FlagValue
name string
usage string
}
+type FlagValue interface {
+ flag.Value
+ IsSet() bool
+}
+
func (f Flag) Synopsis() string {
s := fmt.Sprintf("-%s", f.name)
if bf, ok := f.val.(boolFlag); !ok || !bf.IsBoolFlag() {
@@ -30,7 +39,7 @@ func (f Flag) AddTo(fs *flag.FlagSet) {
}
func (f Flag) IsSet() bool {
- return f.val.String() != ""
+ return f.val.IsSet()
}
func (f Flag) MustBeSet(fs *flag.FlagSet) {
@@ -46,94 +55,113 @@ type boolFlag interface {
// boolValue implements flag.Value.
type boolValue struct {
- p *bool
+ p *bool
+ isSet bool
}
-func (bv boolValue) String() string {
- if bv.p != nil {
- return fmt.Sprint(*bv.p)
+func (v boolValue) String() string {
+ if v.p != nil {
+ return fmt.Sprint(*v.p)
}
return ""
}
-func (bv boolValue) Set(s string) error {
+func (v *boolValue) Set(s string) error {
b, err := strconv.ParseBool(s)
if err != nil {
return err
}
- *bv.p = b
+ *v.p = b
+ v.isSet = true
return nil
}
-func (bv boolValue) IsBoolFlag() bool { return true }
+func (v boolValue) IsSet() bool { return v.isSet }
+
+func (v boolValue) IsBoolFlag() bool { return true }
type uintValue struct {
- p *uint
+ p *uint
+ isSet bool
}
-func (uv uintValue) String() string {
- if uv.p != nil {
- return fmt.Sprint(*uv.p)
+func (v uintValue) String() string {
+ if v.p != nil {
+ return fmt.Sprint(*v.p)
}
return ""
}
-func (uv uintValue) Set(s string) error {
- v, err := strconv.ParseUint(s, 10, 32)
+func (v *uintValue) Set(s string) error {
+ u, err := strconv.ParseUint(s, 10, 32)
if err != nil {
return err
}
- *uv.p = uint(v)
+ *v.p = uint(u)
+ v.isSet = true
return nil
}
+func (v uintValue) IsSet() bool { return v.isSet }
+
// textValue implements flag.Value for string types that implement
// TextUnmarshaler.
type textValue[T ~string, PT interface {
*T
encoding.TextUnmarshaler
}] struct {
- p PT
+ p PT
+ isSet bool
}
func newTextValue[T ~string, PT interface {
*T
encoding.TextUnmarshaler
-}](p PT) textValue[T, PT] {
- return textValue[T, PT]{p}
+}](p PT) *textValue[T, PT] {
+ return &textValue[T, PT]{p: p}
}
-func (tv textValue[T, PT]) String() string {
- if tv.p != nil {
- return string(*(*T)(tv.p))
+func (v textValue[T, PT]) String() string {
+ if v.p != nil {
+ return string(*(*T)(v.p))
}
return ""
}
-func (tv textValue[T, PT]) Set(s string) error {
- return tv.p.UnmarshalText([]byte(s))
+func (v *textValue[T, PT]) Set(s string) error {
+ if err := v.p.UnmarshalText([]byte(s)); err != nil {
+ return err
+ }
+ v.isSet = true
+ return nil
}
+func (v textValue[T, PT]) IsSet() bool { return v.isSet }
+
type urlValue struct {
- *url.URL
+ p *url.URL
+ isSet bool
}
func (v urlValue) String() string {
- if v.URL != nil {
- return v.URL.String()
+ if v.p != nil {
+ return v.p.String()
}
return ""
}
-func (v urlValue) Set(s string) error {
+func (v *urlValue) Set(s string) error {
u, err := url.Parse(s)
if err != nil {
return err
}
- *v.URL = *u
+ *v.p = *u
+ v.isSet = true
return nil
}
+func (v urlValue) IsSet() bool { return v.isSet }
+
func mutexFlags(fs *flag.FlagSet, a, b Flag) {
if a.IsSet() && b.IsSet() {
lg.Printf("lulu: %s: -%s is incompatible with -%s\n", fs.Name(), a.name, b.name)
diff --git a/cmd/lulu/main.go b/cmd/lulu/main.go
index d86d418..06d5ad4 100644
--- a/cmd/lulu/main.go
+++ b/cmd/lulu/main.go
@@ -5,6 +5,7 @@ import (
"flag"
"fmt"
"log"
+ "net/url"
"os"
"time"
@@ -30,6 +31,10 @@ var commands = []command{
"validate-cover", "vc",
validateCover,
"Validate a cover file",
+ }, {
+ "cover-dimensions", "cd",
+ coverDimensions,
+ "Calculate the required dimensions of the cover",
},
}
@@ -107,3 +112,115 @@ func flagBoolFunc(name, usage string, f func()) {
return nil
})
}
+
+func validateInterior(clnt *lulu.Client, args []string) {
+ var (
+ basic bool
+ url url.URL
+ mfg = newMfgFlagSet()
+ timeout time.Duration
+ )
+
+ basicFlag := Flag{&boolValue{p: &basic}, "basic", "Basic validation without pod_package_id manufacturing options"}
+ urlFlag := Flag{&urlValue{p: &url}, "url", "URL of interior file for Lulu to download"}
+
+ fs := flag.NewFlagSet("validate-interior", flag.ExitOnError)
+ basicFlag.AddTo(fs)
+ urlFlag.AddTo(fs)
+ mfg.AddTo(fs)
+ fs.DurationVar(&timeout, "t", defaultTimeout, "Timeout")
+
+ fs.Usage = func() {
+ out := fs.Output()
+ name := "validate-interior"
+ fmt.Fprintf(out, "Usage of %s:\n", name)
+ fmt.Fprintf(out, " %s %s %s [flags]\n", name, urlFlag.Synopsis(), mfg.Synopsis())
+ fmt.Fprintf(out, " %s %s %s [flags]\n", name, basicFlag.Synopsis(), urlFlag.Synopsis())
+ fmt.Fprintf(out, "Flags:\n")
+ fs.PrintDefaults()
+ }
+
+ if err := fs.Parse(args); err != nil {
+ lg.Fatalf("lulu: %v\n", err)
+ }
+
+ var val lulu.InteriorValidation
+ var err error
+ ctx, cancel := context.WithTimeout(clnt.Context(), timeout)
+ defer cancel()
+ if basic {
+ urlFlag.MustBeSet(fs)
+ for _, f := range mfg.flags {
+ mutexFlags(fs, f, basicFlag)
+ }
+ val, err = clnt.ValidateInteriorBasic(ctx, url.String())
+ } else {
+ urlFlag.MustBeSet(fs)
+ mfg.MustBeSet(fs)
+ val, err = clnt.ValidateInterior(ctx, url.String(), mfg.PkgId())
+ }
+ if err != nil {
+ lg.Fatal(err)
+ }
+ fmt.Println(val) // TODO: output format?
+}
+
+func validateCover(clnt *lulu.Client, args []string) {
+ var (
+ url url.URL
+ mfg = newMfgFlagSet()
+ nPages uint
+ timeout time.Duration
+ )
+
+ urlFlag := Flag{&urlValue{p: &url}, "url", "URL of cover file for Lulu to download"}
+ nPagesFlag := nPagesFlag(&nPages)
+
+ fs := flag.NewFlagSet("validate-cover", flag.ExitOnError)
+ urlFlag.AddTo(fs)
+ mfg.AddTo(fs)
+ nPagesFlag.AddTo(fs)
+ fs.DurationVar(&timeout, "t", defaultTimeout, "Timeout")
+
+ if err := fs.Parse(args); err != nil {
+ lg.Fatalf("lulu: %v\n", err)
+ }
+ urlFlag.MustBeSet(fs)
+ mfg.MustBeSet(fs)
+ nPagesFlag.MustBeSet(fs)
+
+ ctx, cancel := context.WithTimeout(clnt.Context(), timeout)
+ defer cancel()
+ val, err := clnt.ValidateCover(ctx, url.String(), mfg.PkgId(), nPages)
+ if err != nil {
+ lg.Fatal(err)
+ }
+ fmt.Println(val) // TODO: output format?
+}
+
+func coverDimensions(clnt *lulu.Client, args []string) {
+ var (
+ mfg = newMfgFlagSet()
+ nPages uint
+ unit = lulu.Points
+ )
+ nPagesFlag := nPagesFlag(&nPages)
+ unitFlag := Flag{newTextValue(&unit), "u", fmt.Sprintf("Unit of measurement %v", lulu.UnitValues())}
+
+ fs := flag.NewFlagSet("cover-dimensions", flag.ExitOnError)
+ mfg.AddTo(fs)
+ nPagesFlag.AddTo(fs)
+ unitFlag.AddTo(fs)
+
+ if err := fs.Parse(args); err != nil {
+ lg.Fatalf("lulu: %v\n", err)
+ }
+ mfg.MustBeSet(fs)
+ nPagesFlag.MustBeSet(fs)
+
+ dims, err := clnt.CoverDimensions(mfg.PkgId(), nPages, unit)
+ if err != nil {
+ lg.Fatal(err)
+ }
+ fmt.Println(dims)
+}
diff --git a/cmd/lulu/validate_cover.go b/cmd/lulu/validate_cover.go
deleted file mode 100644
index dd16db7..0000000
--- a/cmd/lulu/validate_cover.go
+++ /dev/null
@@ -1,44 +0,0 @@
-package main
-
-import (
- "context"
- "flag"
- "fmt"
- "net/url"
- "time"
-
- "git.samanthony.xyz/lulu"
-)
-
-func validateCover(clnt *lulu.Client, args []string) {
- var (
- url url.URL
- mfg = newMfgFlagSet()
- nPages uint
- timeout time.Duration
- )
-
- urlFlag := Flag{urlValue{&url}, "url", "URL of cover file for Lulu to download"}
- nPagesFlag := Flag{uintValue{&nPages}, "n", "Number of interior pages"}
-
- fs := flag.NewFlagSet("validate-cover", flag.ExitOnError)
- urlFlag.AddTo(fs)
- mfg.AddTo(fs)
- nPagesFlag.AddTo(fs)
- fs.DurationVar(&timeout, "t", defaultTimeout, "Timeout")
-
- if err := fs.Parse(args); err != nil {
- lg.Fatalf("lulu: %v\n", err)
- }
- urlFlag.MustBeSet(fs)
- mfg.MustBeSet(fs)
- nPagesFlag.MustBeSet(fs)
-
- ctx, cancel := context.WithTimeout(clnt.Context(), timeout)
- defer cancel()
- val, err := clnt.ValidateCover(ctx, url.String(), mfg.PkgId(), nPages)
- if err != nil {
- lg.Fatal(err)
- }
- fmt.Println(val) // TODO: output format?
-}
diff --git a/cmd/lulu/validate_interior.go b/cmd/lulu/validate_interior.go
deleted file mode 100644
index d2b34bf..0000000
--- a/cmd/lulu/validate_interior.go
+++ /dev/null
@@ -1,63 +0,0 @@
-package main
-
-import (
- "context"
- "flag"
- "fmt"
- "net/url"
- "time"
-
- "git.samanthony.xyz/lulu"
-)
-
-func validateInterior(clnt *lulu.Client, args []string) {
- var (
- basic bool
- url url.URL
- mfg = newMfgFlagSet()
- timeout time.Duration
- )
-
- basicFlag := Flag{boolValue{&basic}, "basic", "Basic validation without pod_package_id manufacturing options"}
- urlFlag := Flag{urlValue{&url}, "url", "URL of interior file for Lulu to download"}
-
- fs := flag.NewFlagSet("validate-interior", flag.ExitOnError)
- basicFlag.AddTo(fs)
- urlFlag.AddTo(fs)
- mfg.AddTo(fs)
- fs.DurationVar(&timeout, "t", defaultTimeout, "Timeout")
-
- fs.Usage = func() {
- out := fs.Output()
- name := "validate-interior"
- fmt.Fprintf(out, "Usage of %s:\n", name)
- fmt.Fprintf(out, " %s %s %s [flags]\n", name, urlFlag.Synopsis(), mfg.Synopsis())
- fmt.Fprintf(out, " %s %s %s [flags]\n", name, basicFlag.Synopsis(), urlFlag.Synopsis())
- fmt.Fprintf(out, "Flags:\n")
- fs.PrintDefaults()
- }
-
- if err := fs.Parse(args); err != nil {
- lg.Fatalf("lulu: %v\n", err)
- }
-
- var val lulu.InteriorValidation
- var err error
- ctx, cancel := context.WithTimeout(clnt.Context(), timeout)
- defer cancel()
- if basic {
- urlFlag.MustBeSet(fs)
- for _, f := range mfg.flags {
- mutexFlags(fs, f, basicFlag)
- }
- val, err = clnt.ValidateInteriorBasic(ctx, url.String())
- } else {
- urlFlag.MustBeSet(fs)
- mfg.MustBeSet(fs)
- val, err = clnt.ValidateInterior(ctx, url.String(), mfg.PkgId())
- }
- if err != nil {
- lg.Fatal(err)
- }
- fmt.Println(val) // TODO: output format?
-}