From 81144edfe4ab07c90ffc79d0e98e4ff0725c56fd Mon Sep 17 00:00:00 2001 From: jolheiser Date: Tue, 9 Aug 2022 13:46:36 -0500 Subject: [PATCH] Updates Signed-off-by: jolheiser --- .gitignore | 3 +- .goreleaser.yaml | 25 +++++++ .woodpecker/goreleaser.yml | 38 ++++++++++ Makefile | 21 ------ README.md | 9 +-- format/format.go | 40 +++++++++++ format/format_test.go | 65 +++++++++++++++++ format/struct.go | 107 ++++++++++++++++++++++++++++ go.mod | 13 ++-- go.sum | 43 +++++------- imp.go | 138 +++++++------------------------------ main.go | 49 ++++++------- struct.go | 49 ------------- 13 files changed, 348 insertions(+), 252 deletions(-) create mode 100644 .goreleaser.yaml create mode 100644 .woodpecker/goreleaser.yml delete mode 100644 Makefile create mode 100644 format/format.go create mode 100644 format/format_test.go create mode 100644 format/struct.go delete mode 100644 struct.go diff --git a/.gitignore b/.gitignore index 8e8b1bf..2b10f78 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ .idea/ # Binaries -/imp* \ No newline at end of file +/imp +/imp.exe \ No newline at end of file diff --git a/.goreleaser.yaml b/.goreleaser.yaml new file mode 100644 index 0000000..2dc95f7 --- /dev/null +++ b/.goreleaser.yaml @@ -0,0 +1,25 @@ +builds: + - env: + - CGO_ENABLED=0 + goos: + - linux + - windows + - darwin + ldflags: + - "-s -w -X main.Version={{.Version}}" +archives: + - replacements: + 386: i386 + amd64: x86_64 + format_overrides: + - goos: windows + format: zip +checksum: + name_template: 'checksums.txt' +release: + gitea: + owner: jolheiser + name: imp +gitea_urls: + api: https://git.jojodev.com/api/v1/ + download: https://git.jojodev.com diff --git a/.woodpecker/goreleaser.yml b/.woodpecker/goreleaser.yml new file mode 100644 index 0000000..cfeef80 --- /dev/null +++ b/.woodpecker/goreleaser.yml @@ -0,0 +1,38 @@ +clone: + git: + image: woodpeckerci/plugin-git + settings: + tags: true + +pipeline: + compliance: + image: golang:1.18 + commands: + - go test -race ./... + - go vet ./... + when: + event: pull_request + + build: + image: goreleaser/goreleaser + commands: + - goreleaser build --snapshot + when: + event: pull_request + + release: + image: goreleaser/goreleaser + commands: + - goreleaser release + secrets: [ gitea_token ] + when: + event: tag + + prune: + image: jolheiser/drone-gitea-prune + settings: + base: https://git.jojodev.com + token: + from_secret: gitea_token + when: + event: tag diff --git a/Makefile b/Makefile deleted file mode 100644 index 9c54931..0000000 --- a/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -GO ?= go - -.PHONY: build -build: - $(GO) build - -.PHONY: fmt -fmt: - $(GO) fmt ./... - -.PHONY: test -test: - $(GO) test -race ./... - -.PHONY: vet -vet: - $(GO) vet ./... - -.PHONY: imp -imp: build - ./imp -w \ No newline at end of file diff --git a/README.md b/README.md index abdae36..e4105b4 100644 --- a/README.md +++ b/README.md @@ -16,15 +16,10 @@ import ( imp includes three flags: * `--write` will write out the formatting rather than printing -* `--imp-ignore` reads a `.impignore` file for globs to include/exclude (`.impignore` by default) -* `--verbose` will print out extended information +* `--ignore` reads a `.impignore` file for globs to include/exclude (`.impignore` by default) ### `.impignore` format The `.impignore` file follows a [globber format](https://gitea.com/jolheiser/globber), -which closely resembles a traditional `.gitignore` file. - -### Example - -https://gitea.com/jolheiser/sip/pulls/17 \ No newline at end of file +which closely resembles a traditional `.gitignore` file. \ No newline at end of file diff --git a/format/format.go b/format/format.go new file mode 100644 index 0000000..1cf20ac --- /dev/null +++ b/format/format.go @@ -0,0 +1,40 @@ +package format + +import ( + "errors" + "regexp" + "strings" +) + +var ( + importRe = regexp.MustCompile(`(?ms)import \(([^)]+)\)`) + otherRe = regexp.MustCompile(`(?:var|const|func)\s`) + ErrNoImports = errors.New("no imports found") +) + +// Source formats a given src's imports +func Source(src []byte, module string) ([]byte, error) { + importStart := importRe.FindIndex(src) + if importStart == nil { + return nil, ErrNoImports + } + + otherStart := otherRe.FindIndex(src) + if otherStart != nil && otherStart[0] < importStart[0] { + return nil, ErrNoImports + } + + groups := importRe.FindStringSubmatch(string(src)) + if groups[0] == "" { + return nil, ErrNoImports + } + + imports := strings.Split(groups[1], "\n") + for idx, i := range imports { + imports[idx] = strings.TrimSpace(i) + } + + block := parseBlock(module, imports) + replaced := strings.Replace(string(src), groups[0], block.String(), 1) + return []byte(replaced), nil +} diff --git a/format/format_test.go b/format/format_test.go new file mode 100644 index 0000000..8c60602 --- /dev/null +++ b/format/format_test.go @@ -0,0 +1,65 @@ +package format + +import ( + "bytes" + "errors" + "testing" + + "github.com/matryer/is" +) + +func TestSource(t *testing.T) { + module := "foo.bar" + + assert := is.New(t) + + _, err := Source(noImports, module) + assert.True(errors.Is(err, ErrNoImports)) // Should get error for no imports + + _, err = Source(fakeImports, module) + assert.True(errors.Is(err, ErrNoImports)) // Should get error for no "real" imports + + formatted, err := Source(before, module) + assert.NoErr(err) // Should be able to format before block + assert.True(bytes.Equal(formatted, after)) // Formatted should match after block +} + +var ( + noImports = []byte(`package main + +func main() {}`) + fakeImports = []byte(`package main + +func main() { + s := "import \"fmt\"" + _ = s +}`) + before = []byte(`package main + +import ( + "foo.bar/baz" + "net/http" + "github.com/peterbourgon/ff/v3" + "io" + "os" + "github.com/matryer/is" + "foo.bar/bux" +) + +func main() {}`) + after = []byte(`package main + +import ( + "io" + "net/http" + "os" + + "foo.bar/baz" + "foo.bar/bux" + + "github.com/matryer/is" + "github.com/peterbourgon/ff/v3" +) + +func main() {}`) +) diff --git a/format/struct.go b/format/struct.go new file mode 100644 index 0000000..8ef07d8 --- /dev/null +++ b/format/struct.go @@ -0,0 +1,107 @@ +package format + +import ( + "fmt" + "sort" + "strings" +) + +type importItem struct { + Comment string + Name string + Path string +} + +func (ii importItem) String() string { + var comment string + if ii.Comment != "" { + comment = ii.Comment + "\n\t" + } + var name string + if ii.Name != "" { + name = ii.Name + " " + } + return comment + name + ii.Path +} + +type importBlock struct { + Stdlib []importItem + Module []importItem + Other []importItem +} + +func importItemSlice(ii []importItem) []string { + iis := make([]string, 0, len(ii)) + for _, i := range ii { + iis = append(iis, i.String()) + } + return iis +} + +func (i importBlock) String() string { + var decl strings.Builder + + decl.WriteString(strings.Join(importItemSlice(i.Stdlib), "\n\t")) + if len(i.Stdlib) > 0 { + decl.WriteString("\n\n\t") + } + decl.WriteString(strings.Join(importItemSlice(i.Module), "\n\t")) + if len(i.Module) > 0 { + decl.WriteString("\n\n\t") + } + decl.WriteString(strings.Join(importItemSlice(i.Other), "\n\t")) + + return fmt.Sprintf(`import ( + %s +)`, decl.String()) +} + +func parseBlock(module string, imports []string) importBlock { + var block importBlock + var comment string + for _, imp := range imports { + if imp == "" { + continue + } + i := imp + if strings.HasPrefix(i, `//`) { + var nl string + if comment != "" { + nl = "\n" + } + comment = nl + i + continue + } + + var name string + if !strings.HasPrefix(i, `"`) { + parts := strings.SplitN(i, " ", 2) + name = parts[0] + i = parts[1] + } + item := importItem{ + Comment: comment, + Name: name, + Path: i, + } + switch { + case strings.Contains(i, module): + block.Module = append(block.Module, item) + case strings.Contains(i, "."): + block.Other = append(block.Other, item) + default: + block.Stdlib = append(block.Stdlib, item) + } + comment = "" + } + + fn := func(ii []importItem) func(int, int) bool { + return func(i, j int) bool { + return ii[i].Path < ii[j].Path + } + } + sort.Slice(block.Stdlib, fn(block.Stdlib)) + sort.Slice(block.Module, fn(block.Module)) + sort.Slice(block.Other, fn(block.Other)) + return block +} diff --git a/go.mod b/go.mod index a9fb86d..3bfd57e 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,14 @@ module gitea.com/jolheiser/imp -go 1.14 +go 1.18 require ( gitea.com/jolheiser/globber v0.0.1 - github.com/gobuffalo/here v0.6.2 - github.com/urfave/cli/v2 v2.2.0 - go.jolheiser.com/beaver v1.0.2 - go.jolheiser.com/regexp v0.1.1 + github.com/gobuffalo/here v0.6.6 + github.com/matryer/is v1.4.0 +) + +require ( + github.com/gobwas/glob v0.2.3 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 5bb2ead..d32f4b9 100644 --- a/go.sum +++ b/go.sum @@ -1,40 +1,31 @@ gitea.com/jolheiser/globber v0.0.1 h1:BVoc4Ml9N3ssix5Xy32gpQOO1jnAuzMsYc5h/LP7/jA= gitea.com/jolheiser/globber v0.0.1/go.mod h1:vr1VkO/biaYgeGj8tRD6SMAWhsqINKFYl9en3YbpQvc= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/gobuffalo/here v0.6.2 h1:ZtCqC7F9ou3moLbYfHM1Tj+gwHGgWhjyRjVjsir9BE0= -github.com/gobuffalo/here v0.6.2/go.mod h1:D75Sq0p2BVHdgQu3vCRsXbg85rx943V19urJpqAVWjI= +github.com/gobuffalo/here v0.6.6 h1:/o+jfSwe36pKQ577grsXGoMYql/zheiGwg1XFo3CBJU= +github.com/gobuffalo/here v0.6.6/go.mod h1:C4JZL5PsXWKzP/CAchaIzuUWlaae6CaAiMYQ0ieY62M= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= +github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4= -github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= -go.jolheiser.com/beaver v1.0.2 h1:KA2D6iO8MQhZi1nZYi/Chak/f1Cxfrs6b1XO623+Khk= -go.jolheiser.com/beaver v1.0.2/go.mod h1:7X4F5+XOGSC3LejTShoBdqtRCnPWcnRgmYGmG3EKW8g= -go.jolheiser.com/regexp v0.1.1 h1:nMCzilEL/oIcZJwnRT4bb+FNxaeAFBdqSjq7rgoNSGg= -go.jolheiser.com/regexp v0.1.1/go.mod h1:58uCpYxGy/DbqVRuo6oU93kh3B3GeyK5eJznQvy2N6c= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/imp.go b/imp.go index e37cbf1..b391640 100644 --- a/imp.go +++ b/imp.go @@ -1,50 +1,35 @@ package main import ( + "bytes" "errors" - "fmt" - "io/ioutil" + "io/fs" "os" "path/filepath" - "sort" "strings" + "gitea.com/jolheiser/imp/format" + "gitea.com/jolheiser/globber" "github.com/gobuffalo/here" - "github.com/urfave/cli/v2" - "go.jolheiser.com/beaver" - "go.jolheiser.com/beaver/color" - "go.jolheiser.com/regexp" ) -var ( - module string - importRe = regexp.MustCompile(`(?ms)import \(([^)]+)\)`) - otherRe = regexp.MustCompile(`(?:var|const|func)\s`) -) - -func runImp(ctx *cli.Context) error { - if ctx.Bool("verbose") { - beaver.Console.Level = beaver.DEBUG - } +func runImp(root, ignore string, write bool) error { info, err := here.Current() if err != nil { return err } - module = info.Module.Path - beaver.Debugf("Current module: %s", module) - - globs, err := globber.ParseFile(ctx.String("imp-ignore")) + module := info.Module.Path + globs, err := globber.ParseFile(ignore) if err != nil { - if !os.IsNotExist(err) { + if !errors.Is(err, fs.ErrNotExist) { return err } globs = globber.New() } var failed bool - diffColor := color.New(color.FgGreen, color.BgHiBlack) - if err := filepath.Walk(".", func(walkPath string, walkInfo os.FileInfo, walkErr error) error { + if err := filepath.Walk(root, func(walkPath string, walkInfo os.FileInfo, walkErr error) error { if walkErr != nil { return walkErr } @@ -58,43 +43,21 @@ func runImp(ctx *cli.Context) error { return nil } - beaver.Debugf("Checking file %s", walkPath) - data, err := ioutil.ReadFile(walkPath) + data, err := os.ReadFile(walkPath) + if err != nil { + return err + } + formatted, err := format.Source(data, module) if err != nil { return err } - importStart := importRe.FindIndex(data) - if importStart == nil { - return nil + if write { + return os.WriteFile(walkPath, formatted, walkInfo.Mode()) } - otherStart := otherRe.FindIndex(data) - if otherStart != nil && otherStart[0] < importStart[0] { - return nil - } - - groups := importRe.Groups(string(data)) - if groups.Index(0) == "" { - return nil - } - - imports := strings.Split(groups.Index(1), "\n") - for idx, i := range imports { - imports[idx] = strings.TrimSpace(i) - } - - formatted := formatImportStmt(splitImports(imports)) - if ctx.Bool("write") { - replaced := strings.Replace(string(data), groups.Index(0), formatted, 1) - return ioutil.WriteFile(walkPath, []byte(replaced), walkInfo.Mode()) - } - - if !strings.EqualFold(groups.Index(0), formatted) { + if !bytes.Equal(data, formatted) { failed = true - beaver.Infof("File: %s", diffColor.Format(walkPath)) - beaver.Infof("Expected:\n%s", diffColor.Format(formatted)) - beaver.Infof("Got:\n%s\n", diffColor.Format(groups.Index(0))) } return nil }); err != nil { @@ -107,7 +70,6 @@ func runImp(ctx *cli.Context) error { } func checkSkip(walkPath string, walkInfo os.FileInfo, globs *globber.GlobSet) walkStatus { - // Skip current directory if strings.EqualFold(walkPath, ".") { return SKIP @@ -115,7 +77,6 @@ func checkSkip(walkPath string, walkInfo os.FileInfo, globs *globber.GlobSet) wa // Skip hidden paths (starting with ".") if strings.HasPrefix(walkPath, ".") { - beaver.Debugf("Skipping hidden path %s", walkPath) if walkInfo.IsDir() { return SKIPDIR } @@ -129,75 +90,22 @@ func checkSkip(walkPath string, walkInfo os.FileInfo, globs *globber.GlobSet) wa // Skip non-Go files if !strings.HasSuffix(walkInfo.Name(), ".go") { - beaver.Debugf("Skipping non-Go file %s", walkPath) return SKIP } // Skip included (ignored) globs i, e := globs.Explain(walkPath) if len(i) > 0 && len(e) == 0 { - beaver.Debugf("Skipping file %s because of .impignore rule %s", walkPath, i[0].Pattern) return SKIP } return CHECK } -func splitImports(imports []string) []importList { - // 0 -> stdlib - // 1 -> this module - // 2 -> others - split := []importList{{}, {}, {}} - var comment string - for _, imp := range imports { - if imp == "" { - continue - } - i := imp - if strings.HasPrefix(i, `//`) { - var nl string - if comment != "" { - nl = "\n" - } - comment = nl + i - continue - } +type walkStatus int - var name string - if !strings.HasPrefix(i, `"`) { - parts := strings.SplitN(i, " ", 2) - name = parts[0] - i = parts[1] - } - switch { - case strings.HasPrefix(i, `"`+module): - split[1] = append(split[1], importItem{comment, name, i}) - case strings.Contains(i, "."): - split[2] = append(split[2], importItem{comment, name, i}) - default: - split[0] = append(split[0], importItem{comment, name, i}) - } - comment = "" - } - - for _, s := range split { - sort.Sort(s) - } - return split -} - -func formatImportStmt(imports []importList) string { - var decl string - for _, imp := range imports { - var pre string - if decl != "" { - pre = "\n\n\t" - } - if len(imp) > 0 { - decl += pre + strings.Join(imp.StringSlice(), "\n\t") - } - } - return fmt.Sprintf(`import ( - %s -)`, decl) -} +const ( + SKIP walkStatus = iota + SKIPDIR + CHECK +) diff --git a/main.go b/main.go index d76d593..96b0ec3 100644 --- a/main.go +++ b/main.go @@ -1,37 +1,30 @@ package main import ( + "flag" + "fmt" "os" - - "github.com/urfave/cli/v2" - "go.jolheiser.com/beaver" ) -func main() { - app := cli.NewApp() - app.Name = "Imp" - app.Usage = "Re-order imports" - app.Flags = []cli.Flag{ - &cli.BoolFlag{ - Name: "write", - Aliases: []string{"w"}, - Usage: "Write the re-ordered imports instead of just printing them", - }, - &cli.BoolFlag{ - Name: "verbose", - Aliases: []string{"v"}, - Usage: "Print more information", - }, - &cli.StringFlag{ - Name: "imp-ignore", - Aliases: []string{"i"}, - Usage: "Path to a .impignore file for globs", - Value: ".impignore", - }, - } - app.Action = runImp +var Version = "develop" - if err := app.Run(os.Args); err != nil { - beaver.Fatal(err) +func main() { + fs := flag.NewFlagSet("imp", flag.ExitOnError) + writeFlag := fs.Bool("write", false, "Write the re-ordered imports instead of just printing them") + fs.BoolVar(writeFlag, "w", *writeFlag, "--write") + ignoreFlag := fs.String("ignore", ".impignore", "Path to .impignore file") + fs.StringVar(ignoreFlag, "i", *ignoreFlag, "--ignore") + + if err := fs.Parse(os.Args[1:]); err != nil { + fmt.Println(err) + } + + root := "." + if fs.NArg() > 0 { + root = fs.Arg(0) + } + + if err := runImp(root, *ignoreFlag, *writeFlag); err != nil { + fmt.Println(err) } } diff --git a/struct.go b/struct.go deleted file mode 100644 index b27b828..0000000 --- a/struct.go +++ /dev/null @@ -1,49 +0,0 @@ -package main - -type importItem struct { - Comment string - Name string - Path string -} - -func (ii importItem) String() string { - var comment string - if ii.Comment != "" { - comment = ii.Comment + "\n\t" - } - var name string - if ii.Name != "" { - name = ii.Name + " " - } - return comment + name + ii.Path -} - -type importList []importItem - -func (il importList) Len() int { - return len(il) -} - -func (il importList) Less(i, j int) bool { - return il[i].Path < il[j].Path -} - -func (il importList) Swap(i, j int) { - il[i], il[j] = il[j], il[i] -} - -func (il importList) StringSlice() []string { - s := make([]string, len(il)) - for idx, ii := range il { - s[idx] = ii.String() - } - return s -} - -type walkStatus int - -const ( - SKIP walkStatus = iota - SKIPDIR - CHECK -)