feat: squash multiple modules to one
This commit is contained in:
@ -1,50 +0,0 @@
|
||||
.DEFAULT_GOAL := help
|
||||
|
||||
# ==================================================================================== #
|
||||
# HELPERS
|
||||
# ==================================================================================== #
|
||||
|
||||
## help: print this help message
|
||||
.PHONY: help
|
||||
help:
|
||||
@echo 'Usage:'
|
||||
@sed -n 's/^##//p' ${MAKEFILE_LIST} | column -t -s ':' | sed -e 's/^/ /'
|
||||
|
||||
## all: tidy + audit + test/cover
|
||||
all: tidy audit test/cover
|
||||
|
||||
# ==================================================================================== #
|
||||
# QUALITY CONTROL
|
||||
# ==================================================================================== #
|
||||
|
||||
## tidy: format code and tidy modfile
|
||||
.PHONY: tidy
|
||||
tidy:
|
||||
go fmt ./...
|
||||
go mod tidy -v
|
||||
|
||||
## audit: run quality control checks
|
||||
.PHONY: audit
|
||||
audit:
|
||||
go mod verify
|
||||
go vet ./...
|
||||
go run honnef.co/go/tools/cmd/staticcheck@latest -checks=all,-ST1000,-U1000 ./...
|
||||
go run golang.org/x/vuln/cmd/govulncheck@latest ./...
|
||||
go test -race -buildvcs -vet=off ./...
|
||||
go run github.com/golangci/golangci-lint/cmd/golangci-lint@latest run -v ./...
|
||||
|
||||
|
||||
# ==================================================================================== #
|
||||
# DEVELOPMENT
|
||||
# ==================================================================================== #
|
||||
|
||||
## test: run all tests
|
||||
.PHONY: test
|
||||
test:
|
||||
go test -v -race -buildvcs ./...
|
||||
|
||||
## test/cover: run all tests and display coverage
|
||||
.PHONY: test/cover
|
||||
test/cover:
|
||||
go test -v -race -buildvcs -coverprofile=/tmp/coverage.out ./...
|
||||
go tool cover -html=/tmp/coverage.out
|
@ -1,28 +0,0 @@
|
||||
package main
|
||||
|
||||
import "flag"
|
||||
|
||||
const stdin = "-"
|
||||
|
||||
type Config struct {
|
||||
Key int
|
||||
Numeric bool
|
||||
Reverse bool
|
||||
Unique bool
|
||||
Sources []string
|
||||
}
|
||||
|
||||
func (c *Config) ParseFlags() {
|
||||
flag.IntVar(&c.Key, "k", 0, "sort via column")
|
||||
flag.BoolVar(&c.Numeric, "n", false, "compare according to string numerical value")
|
||||
flag.BoolVar(&c.Reverse, "r", false, "reverse the result of comparisons")
|
||||
flag.BoolVar(&c.Unique, "u", false, "output only the first of an equal run")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
c.Sources = flag.Args()
|
||||
|
||||
if len(c.Sources) == 0 {
|
||||
c.Sources = []string{stdin}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package sortcli
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
@ -13,9 +13,9 @@ import (
|
||||
// NL New line constant
|
||||
const NL = "\n"
|
||||
|
||||
type content [][]byte
|
||||
type Content [][]byte
|
||||
|
||||
func (c *content) Sort(reverse bool) {
|
||||
func (c *Content) Sort(reverse bool) {
|
||||
slices.SortFunc(*c, func(a, b []byte) int {
|
||||
if reverse {
|
||||
a, b = b, a
|
||||
@ -25,10 +25,10 @@ func (c *content) Sort(reverse bool) {
|
||||
})
|
||||
}
|
||||
|
||||
func (c *content) Uniques() {
|
||||
func (c *Content) Uniques() {
|
||||
m := make(map[string]struct{}, len(*c))
|
||||
|
||||
*c = slices.DeleteFunc[content, []byte](*c, func(line []byte) bool {
|
||||
*c = slices.DeleteFunc[Content, []byte](*c, func(line []byte) bool {
|
||||
if _, ok := m[string(line)]; !ok {
|
||||
m[string(line)] = struct{}{}
|
||||
|
||||
@ -39,7 +39,7 @@ func (c *content) Uniques() {
|
||||
})
|
||||
}
|
||||
|
||||
func (c *content) String() string {
|
||||
func (c *Content) String() string {
|
||||
lines := *c
|
||||
|
||||
var n int
|
||||
@ -64,7 +64,7 @@ func (c *content) String() string {
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func (c *content) Load(r io.Reader) {
|
||||
func (c *Content) Load(r io.Reader) {
|
||||
br := bufio.NewReader(r)
|
||||
|
||||
for {
|
||||
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package sortcli
|
||||
|
||||
import (
|
||||
"strings"
|
||||
@ -16,7 +16,7 @@ Africa
|
||||
`
|
||||
|
||||
func TestLoad(t *testing.T) {
|
||||
c := &content{}
|
||||
c := &Content{}
|
||||
c.Load(strings.NewReader(input))
|
||||
|
||||
assert.Equal(t, input, c.String())
|
||||
@ -42,7 +42,7 @@ America`,
|
||||
tc := tc
|
||||
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
c := &content{}
|
||||
c := &Content{}
|
||||
c.Load(strings.NewReader(tc.Content))
|
||||
|
||||
c.Uniques()
|
||||
|
@ -1,14 +0,0 @@
|
||||
module sort-cli
|
||||
|
||||
go 1.21.6
|
||||
|
||||
require (
|
||||
github.com/stretchr/testify v1.8.4
|
||||
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
@ -1,12 +0,0 @@
|
||||
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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o=
|
||||
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package sortcli
|
||||
|
||||
import (
|
||||
"io"
|
||||
@ -6,13 +6,13 @@ import (
|
||||
"os"
|
||||
)
|
||||
|
||||
func open(sources []string) io.Reader {
|
||||
func Open(sources []string) io.Reader {
|
||||
rs := make([]io.Reader, 0, len(sources))
|
||||
|
||||
for _, source := range sources {
|
||||
var r io.Reader
|
||||
|
||||
if source == stdin {
|
||||
if source == "-" {
|
||||
r = os.Stdin
|
||||
} else {
|
||||
if _, err := os.Stat(source); err != nil {
|
||||
|
@ -1,31 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result := run()
|
||||
|
||||
if _, err := os.Stdout.WriteString(result); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func run() string {
|
||||
cfg := &Config{}
|
||||
cfg.ParseFlags()
|
||||
|
||||
lines := content{}
|
||||
lines.Load(open(cfg.Sources))
|
||||
|
||||
if cfg.Unique {
|
||||
lines.Uniques()
|
||||
}
|
||||
|
||||
lines.Sort(cfg.Reverse)
|
||||
|
||||
return lines.String()
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestFlags(t *testing.T) {
|
||||
// We manipulate the Args to set them up for the testcases
|
||||
// after this test we restore the initial args
|
||||
oldArgs := os.Args
|
||||
defer func() { os.Args = oldArgs }()
|
||||
|
||||
cases := []struct {
|
||||
Name string
|
||||
Args []string
|
||||
ExpectedExit int
|
||||
ExpectedOutput string
|
||||
}{
|
||||
{
|
||||
"No flags",
|
||||
[]string{"testdata/first"},
|
||||
0,
|
||||
"alabama barcelona\nbarcelona california\ncalifornia denver\ncalifornia denver\nамур брянск\nбелгород волгоград\nволгоград геленджик",
|
||||
},
|
||||
{
|
||||
"Reverse",
|
||||
[]string{"-r", "testdata/first"},
|
||||
0,
|
||||
"волгоград геленджик\nбелгород волгоград\nамур брянск\ncalifornia denver\ncalifornia denver\nbarcelona california\nalabama barcelona",
|
||||
},
|
||||
{
|
||||
"Unique",
|
||||
[]string{"-u", "testdata/first"},
|
||||
0,
|
||||
"alabama barcelona\nbarcelona california\ncalifornia denver\nамур брянск\nбелгород волгоград\nволгоград геленджик",
|
||||
},
|
||||
{
|
||||
"Column 2",
|
||||
[]string{"-k=2", "testdata/first"},
|
||||
0,
|
||||
"alabama barcelona\nbarcelona california\ncalifornia denver\ncalifornia denver\nамур брянск\nбелгород волгоград\nволгоград геленджик",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
// this call is required because otherwise flags panics, if args are set between flag.Parse calls
|
||||
flag.CommandLine = flag.NewFlagSet(tc.Name, flag.ExitOnError)
|
||||
// we need a value to set Args[0] to, cause flag begins parsing at Args[1]
|
||||
os.Args = append([]string{tc.Name}, tc.Args...)
|
||||
|
||||
assert.Equal(t, tc.ExpectedOutput, strings.Trim(run(), "\n"))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkRun(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
flag.CommandLine = flag.NewFlagSet("Bench", flag.ExitOnError)
|
||||
os.Args = append([]string{"Bench"}, "testdata/first")
|
||||
|
||||
_ = run()
|
||||
}
|
||||
}
|
7
sort-cli/testdata/first
vendored
7
sort-cli/testdata/first
vendored
@ -1,7 +0,0 @@
|
||||
волгоград геленджик
|
||||
амур брянск
|
||||
alabama barcelona
|
||||
california denver
|
||||
california denver
|
||||
barcelona california
|
||||
белгород волгоград
|
Reference in New Issue
Block a user