Skip to content

Commit

Permalink
Initial comit
Browse files Browse the repository at this point in the history
  • Loading branch information
Melkeydev committed Oct 12, 2023
1 parent 3b2c9a2 commit bcf86d5
Show file tree
Hide file tree
Showing 12 changed files with 547 additions and 0 deletions.
Empty file added LICENSE
Empty file.
60 changes: 60 additions & 0 deletions cmd/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package cmd

import (
"os"

tea "github.com/charmbracelet/bubbletea"
"github.com/melkeydev/go-blueprint/cmd/program"
"github.com/melkeydev/go-blueprint/cmd/steps"
"github.com/melkeydev/go-blueprint/cmd/ui/multiInput"
"github.com/melkeydev/go-blueprint/cmd/ui/textinput"
"github.com/spf13/cobra"
)

func init() {
rootCmd.AddCommand(createCmd)
}

var createCmd = &cobra.Command{
Use: "create",
Short: "Create a Go project and don't worry about the structre",
Long: "Go Blueprint is a CLI tool that allows you to focus on the actual Go code, and not the project structure. Perfect for someone new to the Go language",

Run: func(cmd *cobra.Command, args []string) {

options := steps.Options{
ProjectName: &textinput.Output{},
}

project := &program.Project{}
steps := steps.InitSteps(&options)

tprogram := tea.NewProgram(textinput.InitialTextInputModel(options.ProjectName, "What is the name of your project?", project))
if _, err := tprogram.Run(); err != nil {
cobra.CheckErr(err)
}
project.ExitCLI(tprogram)

for _, step := range steps.Steps {
s := &multiInput.Selection{}
tprogram = tea.NewProgram(multiInput.InitialModelMulti(step.Options, s, step.Headers, project))
if _, err := tprogram.Run(); err != nil {
cobra.CheckErr(err)
}
project.ExitCLI(tprogram)

*step.Field = s.Choice
}

project.ProjectName = options.ProjectName.Output
currentWorkingDir, err := os.Getwd()
if err != nil {
cobra.CheckErr(err)
}

project.AbsolutePath = currentWorkingDir

project.CreateAPIProject()

},
}
62 changes: 62 additions & 0 deletions cmd/program/program.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package program

import (
"fmt"
"os"
"os/exec"
"path/filepath"

tea "github.com/charmbracelet/bubbletea"
"github.com/spf13/cobra"
)

type Project struct {
ProjectName string
Exit bool
AbsolutePath string
}

func (p *Project) ExitCLI(tprogram *tea.Program) {
if p.Exit {
// logo render here
tprogram.ReleaseTerminal()
os.Exit(1)
}
}

func (p *Project) CreateAPIProject() {
appDir := fmt.Sprintf("%s/%s", p.AbsolutePath, p.ProjectName)
if _, err := os.Stat(p.AbsolutePath); err == nil {
if err := os.Mkdir(appDir, 0755); err != nil {
cobra.CheckErr(err)
}
}

// Get the current working directory
currentDir, err := os.Getwd()
if err != nil {
fmt.Printf("Error getting current working directory: %v\n", err)
return
}

scriptRelPath := filepath.Join(currentDir, "cmd", "scripts", "create_structure.sh")

// Check if the script file exists
if _, err := os.Stat(scriptRelPath); os.IsNotExist(err) {
fmt.Printf("Script file '%s' does not exist\n", scriptRelPath)
return
}

cmd := exec.Command("bash", scriptRelPath)
cmd.Dir = appDir

cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr

if err := cmd.Run(); err != nil {
fmt.Printf("Error executing Bash script: %v\n", err)
return
}

fmt.Println("Project structure created successfully in", appDir)
}
51 changes: 51 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
*/
package cmd

import (
"os"

"github.com/spf13/cobra"
)



// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "go-blueprint",
Short: "A brief description of your application",
Long: `A longer description that spans multiple lines and likely contains
examples and usage of using your application. For example:
Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
// Uncomment the following line if your bare application
// has an action associated with it:
// Run: func(cmd *cobra.Command, args []string) { },
}

// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
err := rootCmd.Execute()
if err != nil {
os.Exit(1)
}
}

func init() {
// Here you will define your flags and configuration settings.
// Cobra supports persistent flags, which, if defined here,
// will be global for your application.

// rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.go-blueprint.yaml)")

// Cobra also supports local flags, which will only run
// when this action is called directly.
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}


19 changes: 19 additions & 0 deletions cmd/scripts/create_structure.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/bash

app_name="my-go-project"

go mod init "$app_name"

touch Makefile

mkdir -p cmd/api
echo 'package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
' > cmd/api/main.go

echo "Go project '$app_name' created and initialized with 'go mod init'."
41 changes: 41 additions & 0 deletions cmd/steps/steps.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package steps

import textinput "github.com/melkeydev/go-blueprint/cmd/ui/textinput"

type StepSchema struct {
StepName string
Options []string
Headers string
Field *string
}

type Steps struct {
Steps []StepSchema
}

type Options struct {
ProjectName *textinput.Output
GitRepo string
ProjectType string
}

func InitSteps(options *Options) *Steps {
steps := &Steps{
[]StepSchema{
{
StepName: "Git Repo",
Options: []string{"Yes", "No"},
Headers: "Do you want to init a git project?",
Field: &options.GitRepo,
},
{
StepName: "Project Type",
Options: []string{"API Server", "Serverless Lambda"},
Headers: "What kind of Go project are you building?",
Field: &options.ProjectType,
},
},
}

return steps
}
103 changes: 103 additions & 0 deletions cmd/ui/multiInput/multiInput.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package multiInput

import (
"fmt"

"github.com/melkeydev/go-blueprint/cmd/program"

tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
)

// Change this
var (
focusedStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#01FAC6")).Bold(true)
titleStyle = lipgloss.NewStyle().Background(lipgloss.Color("#01FAC6")).Foreground(lipgloss.Color("#030303")).Bold(true).Padding(0, 1, 0)
)

type Selection struct {
Choice string
}

func (s *Selection) Update(value string) {
s.Choice = value
}

type model struct {
cursor int
choices []string
selected map[int]struct{}
choice *Selection
header string
exit *bool
}

func (m model) Init() tea.Cmd {
return nil
}

func InitialModelMulti(choices []string, selection *Selection, header string, program *program.Project) model {
return model{
choices: choices,
selected: make(map[int]struct{}),
choice: selection,
header: titleStyle.Render(header),
exit: &program.Exit,
}
}

func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.String() {
case "ctrl+c", "q":
*m.exit = true
return m, tea.Quit
case "up", "k":
if m.cursor > 0 {
m.cursor--
}
case "down", "j":
if m.cursor < len(m.choices)-1 {
m.cursor++
}
case "enter", " ":
if len(m.selected) == 1 {
m.selected = make(map[int]struct{})
}
_, ok := m.selected[m.cursor]
if ok {
delete(m.selected, m.cursor)
} else {
m.selected[m.cursor] = struct{}{}
}
case "y":
if len(m.selected) == 1 {
m.choice.Update(m.choices[m.cursor])
return m, tea.Quit
}
}
}
return m, nil
}

func (m model) View() string {
s := m.header + "\n\n"

for i, choice := range m.choices {
cursor := " "
if m.cursor == i {
cursor = focusedStyle.Render(">")
}

checked := " "
if _, ok := m.selected[i]; ok {
checked = focusedStyle.Render("x")
}

s += fmt.Sprintf("%s [%s] %s\n", cursor, checked, choice)
}

s += fmt.Sprintf("\nPress %s to confirm choice.\n", focusedStyle.Render("y"))
return s
}
Loading

0 comments on commit bcf86d5

Please sign in to comment.