Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of cat-ls exercise #2

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
!*/assets
26 changes: 26 additions & 0 deletions Go.AllowList.gitignore
Original file line number Diff line number Diff line change
@@ -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
!*/
Empty file added cli-files/go-cat/LICENSE
Empty file.
5 changes: 5 additions & 0 deletions cli-files/go-cat/assets/dew.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
“A World of Dew” by Kobayashi Issa

A world of dew,
And within every dewdrop
A world of struggle.
5 changes: 5 additions & 0 deletions cli-files/go-cat/assets/for_you.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Sonia Sanchez “Haiku [for you]”

Love between us is
speech and breath. Loving you is
a long river running.
5 changes: 5 additions & 0 deletions cli-files/go-cat/assets/rain.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
“The Taste of Rain” by Jack Kerouac

The taste
Of rain
—Why kneel?
60 changes: 60 additions & 0 deletions cli-files/go-cat/cmd/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
Copyright © 2022 NAME HERE <EMAIL ADDRESS>

*/
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)
}
}
43 changes: 43 additions & 0 deletions cli-files/go-cat/cmd/root_test.go
Original file line number Diff line number Diff line change
@@ -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))
}
}
10 changes: 10 additions & 0 deletions cli-files/go-cat/go.mod
Original file line number Diff line number Diff line change
@@ -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
)
10 changes: 10 additions & 0 deletions cli-files/go-cat/go.sum
Original file line number Diff line number Diff line change
@@ -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=
11 changes: 11 additions & 0 deletions cli-files/go-cat/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
Copyright © 2022 NAME HERE <EMAIL ADDRESS>

*/
package main

import "go-cat/cmd"

func main() {
cmd.Execute()
}
62 changes: 62 additions & 0 deletions cli-files/go-ls/cmd/root.go
Original file line number Diff line number Diff line change
@@ -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)
}
}
61 changes: 61 additions & 0 deletions cli-files/go-ls/cmd/root_test.go
Original file line number Diff line number Diff line change
@@ -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))
}
}
10 changes: 10 additions & 0 deletions cli-files/go-ls/go.mod
Original file line number Diff line number Diff line change
@@ -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
)
10 changes: 10 additions & 0 deletions cli-files/go-ls/go.sum
Original file line number Diff line number Diff line change
@@ -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=
9 changes: 9 additions & 0 deletions cli-files/go-ls/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package main

import (
"go-ls/cmd"
)

func main() {
cmd.Execute()
}