parent
f851eb004b
commit
27b1f4ccf4
@ -0,0 +1,2 @@ |
|||||||
|
cat |
||||||
|
cat.exe |
||||||
@ -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") |
||||||
|
}) |
||||||
|
*/ |
||||||
|
} |
||||||
@ -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 |
||||||
|
) |
||||||
@ -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= |
||||||
@ -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)) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,2 @@ |
|||||||
|
od |
||||||
|
od.exe |
||||||
@ -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 |
||||||
|
) |
||||||
@ -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= |
||||||
@ -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); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -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") |
||||||
|
} |
||||||
Loading…
Reference in new issue