├── go.mod ├── go.sum ├── README.md └── main.go /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/Phillip-England/seed 2 | 3 | go 1.23.3 4 | 5 | require ( 6 | github.com/Phillip-England/mood v0.0.5 7 | github.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203 8 | ) 9 | 10 | require golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect 11 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/Phillip-England/mood v0.0.5 h1:IUcm9OSqav6q+3y+AAV9ds6RQeR4v94DoTslTqYs4cU= 2 | github.com/Phillip-England/mood v0.0.5/go.mod h1:py37wX8i4ziEUTphSnNJ6j5PxCN/nXM1ZGlrcGO2xOc= 3 | github.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203 h1:XBBHcIb256gUJtLmY22n99HaZTz+r2Z51xUPi01m3wg= 4 | github.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203/go.mod h1:E1jcSv8FaEny+OP/5k9UxZVw9YFWGj7eI4KR/iOBqCg= 5 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= 6 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # seed 2 | Generate go skeleton projects quickly. 3 | 4 | ## Installation 5 | Install on your `GOPATH` using: 6 | ```bash 7 | go install github.com/Phillip-England/seed@latest 8 | ``` 9 | 10 | If you prefer to build from source, with go installed on your system, clone the repo, install deps, then build: 11 | ```bash 12 | git clone https://github.com/Phillip-England/seed 13 | cd seed 14 | go mod tidy 15 | go build -o seed 16 | ``` 17 | 18 | ## Usage 19 | If you run `seed plant` without any further args, seed will assume you want the project generated in your current directory. 20 | 21 | To specify, a target directory, just pass the name of the directory you'd like to generate. This will generate an app directory containing our project (assuming ./app doesn't already exist). 22 | ```bash 23 | seed plant app 24 | ``` 25 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "strings" 7 | 8 | "github.com/Phillip-England/mood" 9 | "github.com/eiannone/keyboard" 10 | ) 11 | 12 | func main() { 13 | 14 | app := mood.New() 15 | 16 | app.SetDefault(func(app *mood.Mood) error { 17 | fmt.Println("seed - generate skeleton projects with ease") 18 | fmt.Println("run 'seed plant' to get started") 19 | return nil 20 | }) 21 | 22 | app.At("plant", func(app *mood.Mood) error { 23 | 24 | out := app.GetArgOr(1, ".") 25 | if out != "." { 26 | if len(out) >= 2 { 27 | if string(out[0:2]) != "./" { 28 | out = "./" + out 29 | } 30 | } 31 | } 32 | menuPosition := 0 33 | menuLimit := 2 34 | clear() 35 | printMenu(menuPosition) 36 | err := keyboard.Open() 37 | if err != nil { 38 | return err 39 | } 40 | defer keyboard.Close() 41 | 42 | for { 43 | _, key, err := keyboard.GetKey() 44 | if err != nil { 45 | fmt.Println(`error reading key:`, err) 46 | continue 47 | } 48 | switch key { 49 | case keyboard.KeyArrowDown: 50 | menuPosition++ 51 | if menuPosition > menuLimit { 52 | menuPosition = 0 53 | } 54 | clear() 55 | printMenu(menuPosition) 56 | case keyboard.KeyArrowUp: 57 | menuPosition-- 58 | if menuPosition < 0 { 59 | menuPosition = menuLimit 60 | } 61 | clear() 62 | printMenu(menuPosition) 63 | case keyboard.KeyCtrlZ: 64 | clear() 65 | return nil 66 | case keyboard.KeyCtrlX: 67 | clear() 68 | return nil 69 | case keyboard.KeyCtrlC: 70 | clear() 71 | return nil 72 | case keyboard.KeyEnter: 73 | clear() 74 | skeletonType, err := getSkeletonType(menuPosition) 75 | if err != nil { 76 | return err 77 | } 78 | switch skeletonType { 79 | case "server": 80 | err := GenerateGoServer(out) 81 | if err != nil { 82 | return err 83 | } 84 | return nil 85 | case "cli": 86 | err := GenerateGoCli(out) 87 | if err != nil { 88 | return err 89 | } 90 | return nil 91 | case "library": 92 | err := GenerateGoLibrary(out) 93 | if err != nil { 94 | return err 95 | } 96 | return nil 97 | } 98 | return nil 99 | } 100 | } 101 | }) 102 | 103 | err := app.Run() 104 | if err != nil { 105 | fmt.Println(err.Error()) 106 | } 107 | 108 | } 109 | 110 | func GenerateGoLibrary(out string) error { 111 | if out != "." { 112 | err := makeDir(out) 113 | if err != nil { 114 | return fmt.Errorf(`cannot overwrite dir [%s] because it already exists`, out) 115 | } 116 | } 117 | skeleton := NewLibrarySkeleton(out) 118 | err := makeFile(skeleton.LibGoPath) 119 | if err != nil { 120 | return err 121 | } 122 | err = makeFile(skeleton.TestGoPath) 123 | if err != nil { 124 | return err 125 | } 126 | err = writeFile(skeleton.LibGoPath, `package lib 127 | 128 | func Add(a, b int) int { 129 | return a + b 130 | } 131 | `) 132 | if err != nil { 133 | return err 134 | } 135 | err = writeFile(skeleton.TestGoPath, `package lib 136 | 137 | import "testing" 138 | 139 | func TestAdd(t *testing.T) { 140 | result := Add(2, 3) 141 | expected := 5 142 | 143 | if result != expected { 144 | t.Errorf("Expected %d, but got %d", expected, result) 145 | } 146 | } 147 | `) 148 | if err != nil { 149 | return err 150 | } 151 | clear() 152 | if out == "." { 153 | fmt.Println("to initialize the project, run:\n") 154 | fmt.Println("1. go mod init github.com/github-name/repo-name\n") 155 | fmt.Println("thank you for using seed 🌱") 156 | return nil 157 | } 158 | fmt.Println("to initialize the project, run:\n") 159 | fmt.Println("1. cd " + strings.Replace(out, "./", "", 1)) 160 | fmt.Println("2. go mod init github.com/github-name/repo-name\n") 161 | fmt.Println("thank you for using seed 🌱") 162 | return nil 163 | } 164 | 165 | func GenerateGoCli(out string) error { 166 | if out != "." { 167 | err := makeDir(out) 168 | if err != nil { 169 | return fmt.Errorf(`cannot overwrite dir [%s] because it already exists`, out) 170 | } 171 | } 172 | skeleton := NewCliSkeleton(out) 173 | err := makeFile(skeleton.MainGoPath) 174 | if err != nil { 175 | return err 176 | } 177 | err = writeFile(skeleton.MainGoPath, `package main 178 | 179 | import ( 180 | "fmt" 181 | "os" 182 | "github.com/Phillip-England/mood" 183 | ) 184 | 185 | func main() { 186 | 187 | app := mood.New() 188 | 189 | app.SetDefault(NewDefaultCmd) 190 | app.At("help", NewHelpCmd) 191 | 192 | err := app.Run() 193 | if err != nil { 194 | panic(err) 195 | } 196 | 197 | } 198 | 199 | //====================== 200 | // DefaultCmd 201 | //====================== 202 | 203 | type DefaultCmd struct{} 204 | 205 | func NewDefaultCmd(app *mood.App) (mood.Cmd, error) { 206 | return DefaultCmd{}, nil 207 | } 208 | 209 | func (cmd DefaultCmd) Execute(app *mood.App) error { 210 | fmt.Println("working..") 211 | return nil 212 | } 213 | 214 | //====================== 215 | // HelpCmd 216 | //====================== 217 | 218 | type HelpCmd struct{} 219 | 220 | func NewHelpCmd(app *mood.App) (mood.Cmd, error) { 221 | return HelpCmd{}, nil 222 | } 223 | 224 | func (cmd HelpCmd) Execute(app *mood.App) error { 225 | fmt.Println("helping..") 226 | return nil 227 | }`) 228 | if err != nil { 229 | return err 230 | } 231 | clear() 232 | if out == "." { 233 | fmt.Println("to install required packages run:\n") 234 | fmt.Println("1. go mod init github.com/github-name/repo-name") 235 | fmt.Println("2. go mod tidy\n") 236 | fmt.Println("thank you for using seed 🌱") 237 | return nil 238 | } 239 | fmt.Println("to install required packages run:\n") 240 | fmt.Println("1. cd " + strings.Replace(out, "./", "", 1)) 241 | fmt.Println("2. go mod init github.com/github-name/repo-name") 242 | fmt.Println("3. go mod tidy\n") 243 | fmt.Println("thank you for using seed 🌱") 244 | return nil 245 | } 246 | 247 | func GenerateGoServer(out string) error { 248 | if out != "." { 249 | err := makeDir(out) 250 | if err != nil { 251 | return fmt.Errorf(`cannot overwrite dir [%s] because it already exists`, out) 252 | } 253 | } 254 | skeleton := NewServerSkeleton(out) 255 | err := makeDir(skeleton.TemplatePath) 256 | if err != nil { 257 | return err 258 | } 259 | err = makeDir(skeleton.StaticPath) 260 | if err != nil { 261 | return err 262 | } 263 | err = makeFile(skeleton.IndexHtmlPath) 264 | if err != nil { 265 | return err 266 | } 267 | err = makeFile(skeleton.IndexJsPath) 268 | if err != nil { 269 | return err 270 | } 271 | err = makeFile(skeleton.IndexCssPath) 272 | if err != nil { 273 | return err 274 | } 275 | err = makeFile(skeleton.MainGoPath) 276 | if err != nil { 277 | return err 278 | } 279 | err = writeFile(skeleton.IndexHtmlPath, ` 280 | 281 |
282 | 283 | 284 | 285 |