Skip to content

Commit 40a9cf2

Browse files
committed
feat: basic project structure creation
1 parent a6393a3 commit 40a9cf2

File tree

8 files changed

+283
-0
lines changed

8 files changed

+283
-0
lines changed

.gitignore

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Binaries for programs and plugins
2+
*.exe
3+
*.exe~
4+
*.dll
5+
*.so
6+
*.dylib
7+
8+
# Test binary, built with "go test -c"
9+
*.test
10+
11+
# Output of the go coverage tool, specifically when used with LiteIDE
12+
*.out
13+
14+
# Dependency directories (remove the comment below to include it)
15+
# vendor/
16+
17+
# Go workspace file
18+
go.work
19+
tmp/
20+
21+
# IDE specific files
22+
.vscode
23+
.idea
24+
25+
# .env file
26+
.env
27+
28+
# Project build
29+
bluecpprint
30+
*templ.go

Makefile

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Variables
2+
BIN_DIR = $(HOME)/.local/bin
3+
TARGET = bluecpprint
4+
SRC = cmd/main.go
5+
6+
all: build
7+
8+
build:
9+
@echo "Building..."
10+
@go build -o $(TARGET) $(SRC) 2>&1
11+
12+
run:
13+
@echo "Running..."
14+
@go run $(SRC)
15+
16+
install: build
17+
@echo "Installing..."
18+
@mkdir -p $(BIN_DIR)
19+
@if [ -f $(BIN_DIR)/$(TARGET) ]; then \
20+
echo "File $(BIN_DIR)/$(TARGET) already exists. Replacing..."; \
21+
rm -f $(BIN_DIR)/$(TARGET); \
22+
fi
23+
@cp $(TARGET) $(BIN_DIR)/
24+
@echo "Installation complete. $(BIN_DIR)/$(TARGET) is now available."
25+
26+
uninstall:
27+
@echo "Uninstalling..."
28+
@if [ -f $(BIN_DIR)/$(TARGET) ]; then \
29+
rm -f $(BIN_DIR)/$(TARGET); \
30+
echo "Uninstallation complete. $(BIN_DIR)/$(TARGET) has been removed."; \
31+
else \
32+
echo "No file to uninstall at $(BIN_DIR)/$(TARGET)."; \
33+
fi
34+
35+
clean:
36+
@echo "Cleaning..."
37+
@rm -f $(TARGET)
38+
@rm -rf test
39+
@echo "Clean complete."
40+
41+
.PHONY: all build run install uninstall clean watch

cmd/main.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package main
2+
3+
import (
4+
"log"
5+
"os"
6+
7+
pro "github.com/ErlanRG/bluecpprint/internal"
8+
)
9+
10+
func main() {
11+
if err := pro.CheckArgs(); err != nil {
12+
log.Fatal(err)
13+
}
14+
15+
currentWorkingDir, err := os.Getwd()
16+
if err != nil {
17+
log.Printf("Could not get current working directory: %v", err)
18+
os.Exit(1)
19+
}
20+
21+
p := pro.Project{
22+
ProjectName: os.Args[1],
23+
AbsolutePath: currentWorkingDir,
24+
}
25+
26+
if err := p.CreateProjectStructure(); err != nil {
27+
log.Fatalf("Error creating project structure: %v", err)
28+
}
29+
30+
log.Printf("Project %s created successfully", p.ProjectName)
31+
}

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module github.com/ErlanRG/bluecpprint
2+
3+
go 1.23.0

go.sum

Whitespace-only changes.

internal/program.go

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
package internal
2+
3+
import (
4+
"errors"
5+
"log"
6+
"os"
7+
"os/exec"
8+
"path/filepath"
9+
"strings"
10+
"text/template"
11+
)
12+
13+
const (
14+
gitignoreTmplPath = "templates/.gitignore.tmpl"
15+
mainTmplPath = "templates/main.cpp.tmpl"
16+
srcPath = "src"
17+
binPath = "bin"
18+
includePath = "include"
19+
)
20+
21+
type Project struct {
22+
ProjectName string
23+
AbsolutePath string
24+
}
25+
26+
func (p *Project) CreateProjectStructure() error {
27+
// Check for AbsolutePath. Create if it does not exist
28+
if _, err := os.Stat(p.AbsolutePath); os.IsNotExist(err) {
29+
if err := os.Mkdir(p.AbsolutePath, 0o754); err != nil {
30+
log.Printf("Could not create directory: %v", err)
31+
return err
32+
}
33+
}
34+
35+
// Trim whitespaces from ProjectName
36+
p.ProjectName = strings.TrimSpace(p.ProjectName)
37+
38+
// Create the root project directory
39+
projectPath := filepath.Join(p.AbsolutePath, p.ProjectName)
40+
if _, err := os.Stat(projectPath); os.IsNotExist(err) {
41+
if err := os.MkdirAll(projectPath, 0o751); err != nil {
42+
log.Printf("Error creating root project directory %v\n", err)
43+
return err
44+
}
45+
}
46+
47+
// Create project structure (src, bin, include directories)
48+
if err := p.CreatePath(srcPath, projectPath); err != nil {
49+
log.Printf("Error creating src directory %v\n", err)
50+
return err
51+
}
52+
53+
if err := p.CreatePath(includePath, projectPath); err != nil {
54+
log.Printf("Error creating include directory %v\n", err)
55+
return err
56+
}
57+
58+
if err := p.CreatePath(binPath, projectPath); err != nil {
59+
log.Printf("Error creating bin directory %v\n", err)
60+
return err
61+
}
62+
63+
// Initialize git repository
64+
if err := ExecuteCmd("git", []string{"init"}, projectPath); err != nil {
65+
log.Printf("Error initializing git repository %v\n", err)
66+
return err
67+
}
68+
69+
// Create .gitignore file
70+
if err := p.CreateFileFromTemplate(gitignoreTmplPath, projectPath, ".gitignore"); err != nil {
71+
log.Printf("Error creating .gitignore file: %v\n", err)
72+
return err
73+
}
74+
75+
// Create main.cpp file
76+
mainPath := filepath.Join(projectPath, srcPath)
77+
if err := p.CreateFileFromTemplate(mainTmplPath, mainPath, "main.cpp"); err != nil {
78+
log.Printf("Error creating main.cpp file: %v\n", err)
79+
return err
80+
}
81+
82+
return nil
83+
}
84+
85+
func (p *Project) CreateFileFromTemplate(tmplPath string, destinationPath string, filename string) error {
86+
// read template file
87+
tmpl, err := template.ParseFiles(tmplPath)
88+
if err != nil {
89+
log.Printf("Error parsing template file: %v\n", err)
90+
return err
91+
}
92+
93+
// create the output file
94+
generatedFile, err := os.Create(filepath.Join(destinationPath, filename))
95+
if err != nil {
96+
log.Printf("Error creating %s file: %v\n", filename, err)
97+
return err
98+
}
99+
defer generatedFile.Close()
100+
101+
err = tmpl.Execute(generatedFile, nil)
102+
if err != nil {
103+
log.Printf("Error executing template: %v", err)
104+
}
105+
106+
return nil
107+
}
108+
109+
func (p *Project) CreatePath(pathToCreate string, projectPath string) error {
110+
path := filepath.Join(projectPath, pathToCreate)
111+
if _, err := os.Stat(path); os.IsNotExist(err) {
112+
if err := os.MkdirAll(path, 0o751); err != nil {
113+
log.Printf("Error creating directory %v\n", err)
114+
return err
115+
}
116+
}
117+
118+
return nil
119+
}
120+
121+
// [https://github.com/Melkeydev/go-blueprint/blob/main/cmd/utils/utils.go]:
122+
// Melkeydev implementation of ExecuteCmd
123+
func ExecuteCmd(name string, args []string, dir string) error {
124+
cmd := exec.Command(name, args...)
125+
cmd.Dir = dir
126+
127+
if err := cmd.Run(); err != nil {
128+
return err
129+
}
130+
return nil
131+
}
132+
133+
func CheckArgs() error {
134+
// Check if there are enough arguments
135+
if len(os.Args) != 2 {
136+
return errors.New("Usage: bluecpprint <project_name>")
137+
}
138+
139+
return nil
140+
}

templates/.gitignore.tmpl

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Prerequisites
2+
*.d
3+
4+
# Compiled Object files
5+
*.slo
6+
*.lo
7+
*.o
8+
*.obj
9+
10+
# Precompiled Headers
11+
*.gch
12+
*.pch
13+
14+
# Compiled Dynamic libraries
15+
*.so
16+
*.dylib
17+
*.dll
18+
19+
# Fortran module files
20+
*.mod
21+
*.smod
22+
23+
# Compiled Static libraries
24+
*.lai
25+
*.la
26+
*.a
27+
*.lib
28+
29+
# Executables
30+
*.exe
31+
*.out
32+
*.app

templates/main.cpp.tmpl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#include <iostream>
2+
3+
int main (int argc, char *argv[]) {
4+
std::cout << "Hello World" << std::endl;
5+
return 0;
6+
}

0 commit comments

Comments
 (0)