Skip to content

Commit e1bd66f

Browse files
Add coin toss game and GitHub CLI commands
1 parent 6d6f8fe commit e1bd66f

7 files changed

Lines changed: 169 additions & 17 deletions

File tree

.gitignore

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,29 @@
1+
# If you prefer the allow list template instead of the deny list, see community template:
2+
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
3+
#
4+
# Binaries for programs and plugins
5+
*.exe
6+
*.exe~
7+
*.dll
8+
*.so
9+
*.dylib
10+
11+
# Test binary, built with `go test -c`
12+
*.test
13+
14+
# Output of the go coverage tool, specifically when used with LiteIDE
15+
*.out
16+
17+
# Dependency directories (remove the comment below to include it)
18+
# vendor/
19+
20+
# Go workspace file
21+
go.work
22+
go.work.sum
23+
24+
# env file
25+
.env
26+
27+
# Prevent binaries from being added
128
/gh-game
2-
/gh-game.exe
29+
/gh-game.exe

cmd/cointoss.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
"math/rand"
6+
"strings"
7+
"time"
8+
9+
"github.com/spf13/cobra"
10+
)
11+
12+
// Helper functions
13+
func tossCoin() string {
14+
rand.Seed(time.Now().UnixNano())
15+
if rand.Float32() < 0.5 {
16+
return "heads"
17+
}
18+
return "tails"
19+
}
20+
21+
func validateGuess(guess string) error {
22+
guess = strings.ToLower(strings.TrimSpace(guess))
23+
if guess != "heads" && guess != "tails" {
24+
return fmt.Errorf("guess must be either 'heads' or 'tails'")
25+
}
26+
return nil
27+
}
28+
29+
func getNextGuess() (string, bool) {
30+
fmt.Print("Play again? Enter 'heads' or 'tails' (or 'quit' to end): ")
31+
var answer string
32+
fmt.Scanln(&answer)
33+
34+
if strings.ToLower(strings.TrimSpace(answer)) == "quit" {
35+
return "", false
36+
}
37+
38+
if err := validateGuess(answer); err != nil {
39+
fmt.Println(err)
40+
return getNextGuess()
41+
}
42+
43+
return strings.ToLower(strings.TrimSpace(answer)), true
44+
}
45+
46+
var cointossCmd = &cobra.Command{
47+
Use: "cointoss [guess]",
48+
Short: "Toss a coin",
49+
Long: `Toss a virtual coin and get heads or tails as the result.`,
50+
Args: func(cmd *cobra.Command, args []string) error {
51+
if len(args) != 1 {
52+
return fmt.Errorf("requires exactly 1 argument (guess)")
53+
}
54+
return validateGuess(args[0])
55+
},
56+
Run: func(cmd *cobra.Command, args []string) {
57+
guess := strings.ToLower(strings.TrimSpace(args[0]))
58+
streak := 0
59+
keepPlaying := true
60+
61+
for keepPlaying {
62+
result := tossCoin()
63+
fmt.Printf("The coin shows: %s!\n", strings.Title(result))
64+
65+
if guess == result {
66+
streak++
67+
fmt.Printf("Correct! Streak: %d\n", streak)
68+
var continuePlay bool
69+
guess, continuePlay = getNextGuess()
70+
keepPlaying = continuePlay
71+
} else {
72+
fmt.Printf("Game Over! Final streak: %d\n", streak)
73+
keepPlaying = false
74+
}
75+
}
76+
},
77+
}

cmd/root.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package cmd
2+
3+
import (
4+
"github.com/spf13/cobra"
5+
)
6+
7+
var rootCmd = &cobra.Command{
8+
Use: "gh-game",
9+
Short: "A GitHub CLI extension for games",
10+
Long: `A GitHub CLI extension that allows you to play games through the GitHub CLI.`,
11+
}
12+
13+
func Execute() error {
14+
return rootCmd.Execute()
15+
}
16+
17+
func init() {
18+
rootCmd.AddCommand(whoamiCmd)
19+
rootCmd.AddCommand(cointossCmd)
20+
}

cmd/whoami.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/cli/go-gh/v2/pkg/api"
7+
"github.com/spf13/cobra"
8+
)
9+
10+
var whoamiCmd = &cobra.Command{
11+
Use: "whoami",
12+
Short: "Display GitHub user information",
13+
Long: `Display information about the currently authenticated GitHub user.`,
14+
Run: func(cmd *cobra.Command, args []string) {
15+
client, err := api.DefaultRESTClient()
16+
if err != nil {
17+
fmt.Println(err)
18+
return
19+
}
20+
response := struct{ Login string }{}
21+
err = client.Get("user", &response)
22+
if err != nil {
23+
fmt.Println(err)
24+
return
25+
}
26+
fmt.Printf("running as %s\n", response.Login)
27+
},
28+
}

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,15 @@ require (
99
github.com/cli/safeexec v1.0.0 // indirect
1010
github.com/cli/shurcooL-graphql v0.0.4 // indirect
1111
github.com/henvic/httpretty v0.0.6 // indirect
12+
github.com/inconshreveable/mousetrap v1.1.0 // indirect
1213
github.com/kr/text v0.2.0 // indirect
1314
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
1415
github.com/mattn/go-isatty v0.0.20 // indirect
1516
github.com/mattn/go-runewidth v0.0.15 // indirect
1617
github.com/muesli/termenv v0.15.2 // indirect
1718
github.com/rivo/uniseg v0.4.7 // indirect
19+
github.com/spf13/cobra v1.8.1 // indirect
20+
github.com/spf13/pflag v1.0.5 // indirect
1821
github.com/thlib/go-timezone-local v0.0.0-20210907160436-ef149e42d28e // indirect
1922
golang.org/x/sys v0.28.0 // indirect
2023
golang.org/x/term v0.27.0 // indirect

go.sum

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,16 @@ github.com/cli/safeexec v1.0.0 h1:0VngyaIyqACHdcMNWfo6+KdUYnqEr2Sg+bSP1pdF+dI=
66
github.com/cli/safeexec v1.0.0/go.mod h1:Z/D4tTN8Vs5gXYHDCbaM1S/anmEDnJb1iW0+EJ5zx3Q=
77
github.com/cli/shurcooL-graphql v0.0.4 h1:6MogPnQJLjKkaXPyGqPRXOI2qCsQdqNfUY1QSJu2GuY=
88
github.com/cli/shurcooL-graphql v0.0.4/go.mod h1:3waN4u02FiZivIV+p1y4d0Jo1jc6BViMA73C+sZo2fk=
9+
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
910
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
1011
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
1112
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
1213
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
1314
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
1415
github.com/henvic/httpretty v0.0.6 h1:JdzGzKZBajBfnvlMALXXMVQWxWMF/ofTy8C3/OSUTxs=
1516
github.com/henvic/httpretty v0.0.6/go.mod h1:X38wLjWXHkXT7r2+uK8LjCMne9rsuNaBLJ+5cU2/Pmo=
17+
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
18+
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
1619
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
1720
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
1821
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@@ -30,6 +33,11 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
3033
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
3134
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
3235
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
36+
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
37+
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
38+
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
39+
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
40+
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
3341
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
3442
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
3543
github.com/thlib/go-timezone-local v0.0.0-20210907160436-ef149e42d28e h1:BuzhfgfWQbX0dWzYzT1zsORLnHRv3bcRcsaUk0VmXA8=

main.go

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,14 @@ package main
22

33
import (
44
"fmt"
5+
"os"
56

6-
"github.com/cli/go-gh/v2/pkg/api"
7+
"github.com/chrisreddington/gh-game/cmd"
78
)
89

910
func main() {
10-
fmt.Println("hi world, this is the gh-game extension!")
11-
client, err := api.DefaultRESTClient()
12-
if err != nil {
13-
fmt.Println(err)
14-
return
11+
if err := cmd.Execute(); err != nil {
12+
fmt.Fprintln(os.Stderr, err)
13+
os.Exit(1)
1514
}
16-
response := struct {Login string}{}
17-
err = client.Get("user", &response)
18-
if err != nil {
19-
fmt.Println(err)
20-
return
21-
}
22-
fmt.Printf("running as %s\n", response.Login)
2315
}
24-
25-
// For more examples of using go-gh, see:
26-
// https://github.com/cli/go-gh/blob/trunk/example_gh_test.go

0 commit comments

Comments
 (0)