diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..cf92ac7b0 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +!*/assets \ No newline at end of file diff --git a/Go.AllowList.gitignore b/Go.AllowList.gitignore new file mode 100644 index 000000000..a048e5ab7 --- /dev/null +++ b/Go.AllowList.gitignore @@ -0,0 +1,26 @@ + + + +# Allowlisting gitignore template for GO projects prevents us +# from adding various unwanted local files, such as generated +# files, developer configurations or IDE-specific files etc. +# +# Recommended: Go.AllowList.gitignore + +# Ignore everything +* + +# But not these files... +!/.gitignore + +!*.go +!go.sum +!go.mod + +!README.md +!LICENSE + +# !Makefile + +# ...even if they are in subdirectories +!*/ \ No newline at end of file diff --git a/cli-files/go-cat/LICENSE b/cli-files/go-cat/LICENSE new file mode 100644 index 000000000..e69de29bb diff --git a/cli-files/go-cat/assets/dew.txt b/cli-files/go-cat/assets/dew.txt new file mode 100644 index 000000000..74c9b6edb --- /dev/null +++ b/cli-files/go-cat/assets/dew.txt @@ -0,0 +1,5 @@ +“A World of Dew” by Kobayashi Issa + +A world of dew, +And within every dewdrop +A world of struggle. \ No newline at end of file diff --git a/cli-files/go-cat/assets/for_you.txt b/cli-files/go-cat/assets/for_you.txt new file mode 100644 index 000000000..9e01a74ca --- /dev/null +++ b/cli-files/go-cat/assets/for_you.txt @@ -0,0 +1,5 @@ +Sonia Sanchez “Haiku [for you]” + +Love between us is +speech and breath. Loving you is +a long river running. \ No newline at end of file diff --git a/cli-files/go-cat/assets/rain.txt b/cli-files/go-cat/assets/rain.txt new file mode 100644 index 000000000..149523ec7 --- /dev/null +++ b/cli-files/go-cat/assets/rain.txt @@ -0,0 +1,5 @@ +“The Taste of Rain” by Jack Kerouac + +The taste +Of rain +—Why kneel? \ No newline at end of file diff --git a/cli-files/go-cat/cmd/root.go b/cli-files/go-cat/cmd/root.go new file mode 100644 index 000000000..c55a1c5f6 --- /dev/null +++ b/cli-files/go-cat/cmd/root.go @@ -0,0 +1,60 @@ +/* +Copyright © 2022 NAME HERE + +*/ +package cmd + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" +) + +// rootCmd represents the base command when called without any subcommands +func NewRoodCmd() *cobra.Command { + return &cobra.Command{ + Use: "go-cat", + Short: "Go implementation of cat", + Long: `Works like cat`, + RunE: func(cmd *cobra.Command, args []string) error { + // Don't do anything if we didn't get an arg + if len(args) < 1 { + return nil + } + path := args[0] + + // Get data about the file so we can do this safely + file, err := os.Stat(path) + if err != nil { + return err + } + + // If it's a directory, do the right thing and error + if file.IsDir() { + return fmt.Errorf("go-cat: %s: Is a directory", path) + } + + // Read the data from the file + // https://pkg.go.dev/os#ReadFile + data, err := os.ReadFile(path) + if err != nil { + return err + } + + // Print those lovely bytes + out := cmd.OutOrStdout() + out.Write(data) + + return nil + }, + } +} + +func Execute() { + rootCmd := NewRoodCmd() + if err := rootCmd.Execute(); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} diff --git a/cli-files/go-cat/cmd/root_test.go b/cli-files/go-cat/cmd/root_test.go new file mode 100644 index 000000000..0c9774a82 --- /dev/null +++ b/cli-files/go-cat/cmd/root_test.go @@ -0,0 +1,43 @@ +package cmd + +import ( + "bytes" + "io/ioutil" + "testing" +) + +func TestRootCmd(t *testing.T) { + cmd := NewRoodCmd() + b := bytes.NewBufferString("") + cmd.SetOut(b) + cmd.SetArgs([]string{}) + cmd.Execute() + out, err := ioutil.ReadAll(b) + if err != nil { + t.Fatal(err) + } + expected := `` + if string(out) != expected { + t.Fatalf("expected \"%s\" got \"%s\"", expected, string(out)) + } +} + +func TestRootCmdWithFile(t *testing.T) { + cmd := NewRoodCmd() + b := bytes.NewBufferString("") + cmd.SetOut(b) + cmd.SetArgs([]string{"../assets/dew.txt"}) + cmd.Execute() + out, err := ioutil.ReadAll(b) + if err != nil { + t.Fatal(err) + } + expected := `“A World of Dew” by Kobayashi Issa + +A world of dew, +And within every dewdrop +A world of struggle.` + if string(out) != expected { + t.Fatalf("expected \"%s\" got \"%s\"", expected, string(out)) + } +} diff --git a/cli-files/go-cat/go.mod b/cli-files/go-cat/go.mod new file mode 100644 index 000000000..2367b1c00 --- /dev/null +++ b/cli-files/go-cat/go.mod @@ -0,0 +1,10 @@ +module go-cat + +go 1.18 + +require github.com/spf13/cobra v1.5.0 + +require ( + github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect +) diff --git a/cli-files/go-cat/go.sum b/cli-files/go-cat/go.sum new file mode 100644 index 000000000..0d85248bf --- /dev/null +++ b/cli-files/go-cat/go.sum @@ -0,0 +1,10 @@ +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU= +github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= diff --git a/cli-files/go-cat/main.go b/cli-files/go-cat/main.go new file mode 100644 index 000000000..cca0ed59e --- /dev/null +++ b/cli-files/go-cat/main.go @@ -0,0 +1,11 @@ +/* +Copyright © 2022 NAME HERE + +*/ +package main + +import "go-cat/cmd" + +func main() { + cmd.Execute() +} diff --git a/cli-files/go-ls/cmd/root.go b/cli-files/go-ls/cmd/root.go new file mode 100644 index 000000000..959d54f47 --- /dev/null +++ b/cli-files/go-ls/cmd/root.go @@ -0,0 +1,62 @@ +package cmd + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" +) + +func NewRoodCmd() *cobra.Command { + return &cobra.Command{ + Use: "go-ls", + Short: "go-ls is a re-implementation of the ls command", + Args: cobra.ArbitraryArgs, + RunE: func(cmd *cobra.Command, args []string) error { + // By default, ls the current directory + dir := "." + // If an argument was passed, use the first as our directory + if len(args) > 0 { + dir = args[0] + } + + // Stat the file so we can check if it's a directory or not before + // we try to read it as a directory using ReadDir. os.ReadDir will + // generates an error if the thing you pass to it is not a directory. + // https://pkg.go.dev/os#Stat + fileInfo, err := os.Stat(dir) + if err != nil { + return err + } + + // We can only list the contents of a directory. + // To match the real ls, if we're asked to ls a file, we'll just print + // out the file's name. + // https://pkg.go.dev/io/fs#FileInfo + if fileInfo.IsDir() == false { + fmt.Fprintln(cmd.OutOrStdout(), fileInfo.Name()) + return nil + } + + // Read this directory to get a list of files + // https://pkg.go.dev/os#ReadDir + files, err := os.ReadDir(dir) + if err != nil { + return err + } + // Iterate through each file in the directory, printing the file name + for _, file := range files { + fmt.Fprintln(cmd.OutOrStdout(), file.Name()) + } + return nil + }, + } +} + +func Execute() { + rootCmd := NewRoodCmd() + if err := rootCmd.Execute(); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} diff --git a/cli-files/go-ls/cmd/root_test.go b/cli-files/go-ls/cmd/root_test.go new file mode 100644 index 000000000..bbecc7de6 --- /dev/null +++ b/cli-files/go-ls/cmd/root_test.go @@ -0,0 +1,61 @@ +package cmd + +import ( + "bytes" + "io/ioutil" + "testing" +) + +func TestRootCmd(t *testing.T) { + cmd := NewRoodCmd() + b := bytes.NewBufferString("") + cmd.SetOut(b) + cmd.SetArgs([]string{}) + cmd.Execute() + out, err := ioutil.ReadAll(b) + if err != nil { + t.Fatal(err) + } + expected := `root.go +root_test.go +` + if string(out) != expected { + t.Fatalf("expected \"%s\" got \"%s\"", expected, string(out)) + } +} + +func TestRootCmdRelative(t *testing.T) { + cmd := NewRoodCmd() + b := bytes.NewBufferString("") + cmd.SetOut(b) + cmd.SetArgs([]string{"../assets"}) + cmd.Execute() + out, err := ioutil.ReadAll(b) + if err != nil { + t.Fatal(err) + } + expected := `dew.txt +for_you.txt +rain.txt +` + if string(out) != expected { + t.Fatalf("expected \"%s\" got \"%s\"", expected, string(out)) + } +} + +func TestRootCmdFile(t *testing.T) { + cmd := NewRoodCmd() + b := bytes.NewBufferString("") + cmd.SetOut(b) + cmd.SetArgs([]string{"../assets/dew.txt"}) + cmd.Execute() + out, err := ioutil.ReadAll(b) + if err != nil { + t.Fatal(err) + } + expected := `dew.txt +` + if string(out) != expected { + t.Fatalf("expected \"%s\" got \"%s\"", expected, string(out)) + } +} diff --git a/cli-files/go-ls/go.mod b/cli-files/go-ls/go.mod new file mode 100644 index 000000000..c533a5046 --- /dev/null +++ b/cli-files/go-ls/go.mod @@ -0,0 +1,10 @@ +module go-ls + +go 1.18 + +require github.com/spf13/cobra v1.5.0 + +require ( + github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect +) diff --git a/cli-files/go-ls/go.sum b/cli-files/go-ls/go.sum new file mode 100644 index 000000000..0d85248bf --- /dev/null +++ b/cli-files/go-ls/go.sum @@ -0,0 +1,10 @@ +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU= +github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= diff --git a/cli-files/go-ls/main.go b/cli-files/go-ls/main.go new file mode 100644 index 000000000..de33020d8 --- /dev/null +++ b/cli-files/go-ls/main.go @@ -0,0 +1,9 @@ +package main + +import ( + "go-ls/cmd" +) + +func main() { + cmd.Execute() +}