diff --git a/tested/cat/.gitignore b/tested/cat/.gitignore new file mode 100644 index 0000000..a7053b1 --- /dev/null +++ b/tested/cat/.gitignore @@ -0,0 +1,2 @@ +cat +cat.exe diff --git a/tested/cat/cat_test.go b/tested/cat/cat_test.go new file mode 100644 index 0000000..f3db0dd --- /dev/null +++ b/tested/cat/cat_test.go @@ -0,0 +1,32 @@ +package main + +import ( + "testing" + "github.com/stretchr/testify/assert" + "os" +) + +func WithArgs(args []string, test func ()) { + old_args := os.Args + defer (func() { os.Args = old_args })() + os.Args = args + test() +} + +func TestParseOpts(t *testing.T) { + args := []string{"cat.exe", "-n", "main.go"} + + WithArgs(args, func () { + opts := ParseOpts() + assert.Equal(t, opts.Number, true, "-n didn't work") + }) + + /* + // This fails because flag can't be run more than once + args = []string{"cat.exe", "-s", "main.go"} + WithArgs(args, func () { + opts := ParseOpts() + assert.Equal(t, opts.Squeeze, true, "-s didn't work") + }) + */ +} diff --git a/tested/cat/go.mod b/tested/cat/go.mod new file mode 100644 index 0000000..6c3a0f7 --- /dev/null +++ b/tested/cat/go.mod @@ -0,0 +1,11 @@ +module lcthw.dev/go/go-coreutils/cat + +go 1.24.2 + +require github.com/stretchr/testify v1.11.1 + +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 +) diff --git a/tested/cat/go.sum b/tested/cat/go.sum new file mode 100644 index 0000000..c4c1710 --- /dev/null +++ b/tested/cat/go.sum @@ -0,0 +1,10 @@ +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.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +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= diff --git a/tested/cat/main.go b/tested/cat/main.go new file mode 100644 index 0000000..fc6686b --- /dev/null +++ b/tested/cat/main.go @@ -0,0 +1,58 @@ +package main + +import ( + "fmt" + "flag" + "os" + "log" + "strings" +) + +type Opts struct { + Number bool + Squeeze bool + Filenames []string +} + +func ParseOpts() (Opts) { + var opts Opts + + fmt.Println("args:", os.Args) + + flag.BoolVar(&opts.Number, "n", false, "Number all nonempty output lines, starting with 1") + flag.BoolVar(&opts.Squeeze, "s", false, "Suppress repeated adjacent blank lines") + flag.Parse() + + if flag.NArg() < 1 { + log.Fatal("USAGE: cat [-n] [-s] file0 [fileN]") + os.Exit(1) + } + + opts.Filenames = flag.Args() + + return opts +} + +func main() { + opts := ParseOpts() + + for _, filename := range opts.Filenames { + in_file, err := os.ReadFile(filename) + + if err != nil { log.Fatalf("cannot open %s: %v", filename, err) } + + if(opts.Number) { + count := 1 + for line := range strings.Lines(string(in_file)) { + if opts.Squeeze && len(line) <= 1 { + continue + } + + fmt.Printf("%0.4d: %s", count, line) + count++ + } + } else { + fmt.Print(string(in_file)) + } + } +} diff --git a/tested/od/.gitignore b/tested/od/.gitignore new file mode 100644 index 0000000..f2e57ad --- /dev/null +++ b/tested/od/.gitignore @@ -0,0 +1,2 @@ +od +od.exe diff --git a/tested/od/go.mod b/tested/od/go.mod new file mode 100644 index 0000000..625e69c --- /dev/null +++ b/tested/od/go.mod @@ -0,0 +1,11 @@ +module lcthw.dev/go/go-coreutils/od + +go 1.24.2 + +require github.com/stretchr/testify v1.11.1 + +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 +) diff --git a/tested/od/go.sum b/tested/od/go.sum new file mode 100644 index 0000000..c4c1710 --- /dev/null +++ b/tested/od/go.sum @@ -0,0 +1,10 @@ +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.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +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= diff --git a/tested/od/main.go b/tested/od/main.go new file mode 100644 index 0000000..9409942 --- /dev/null +++ b/tested/od/main.go @@ -0,0 +1,67 @@ +package main + +import ( + "fmt" + "os" + "flag" + "log" + "bufio" +) + +type Opts struct { + Width int + Filenames []string + Hex bool + Octal bool + Format string +} + +func ParseOpts(args []string) (Opts) { + var opts Opts + myflags := flag.NewFlagSet("od", flag.ContinueOnError) + + myflags.IntVar(&opts.Width, "w", 16, "Width of output grid") + myflags.BoolVar(&opts.Hex, "x", false, "Output hex bytes") + myflags.BoolVar(&opts.Octal, "o", false, "Output octal bytes") + + myflags.Parse(args[1:]) + + if myflags.NArg() == 0 { + log.Fatal("USAGE: od [files]") + } + + if opts.Hex { + opts.Format = "%0.2x " + } else { + opts.Format = "%0.3o " + } + + opts.Filenames = myflags.Args() + return opts +} + +func main() { + opts := ParseOpts(os.Args) + + for _, filename := range opts.Filenames { + reader, err := os.Open(filename) + defer reader.Close() + if err != nil { log.Fatalf("can't open: %s: %v", filename, err) } + + buf := bufio.NewReader(reader) + count := buf.Size() + + fmt.Printf("%0.8o ", 0); + + for index := 0; index < count; index++ { + data, err := buf.ReadByte() + if err != nil { break } + fmt.Printf(opts.Format, data); + + if (index + 1) % opts.Width == 0 { + fmt.Print("\n") + fmt.Printf("%0.8o ", index); + } + } + } +} diff --git a/tested/od/od_test.go b/tested/od/od_test.go new file mode 100644 index 0000000..db0aa10 --- /dev/null +++ b/tested/od/od_test.go @@ -0,0 +1,17 @@ +package main + +import ( + "testing" + "github.com/stretchr/testify/assert" +) + +func TestParseOpts(t *testing.T) { + args := []string{"od.exe", "-x", "main.go"} + opts := ParseOpts(args) + assert.Equal(t, opts.Hex, true, "-x didn't work") + + // This fails because flag can't be run more than once + args = []string{"cat.exe", "-o", "main.go"} + opts = ParseOpts(args) + assert.Equal(t, opts.Octal, true, "-o didn't work") +}