Skip to content

Commit

Permalink
feat: add default project template
Browse files Browse the repository at this point in the history
  • Loading branch information
crhntr committed Oct 29, 2024
1 parent 61d8c3f commit 84173cc
Show file tree
Hide file tree
Showing 8 changed files with 167 additions and 17 deletions.
89 changes: 89 additions & 0 deletions cmd/muxt/data/new/default.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
-- main.go --
package server

import (
"context"
"embed"
"html/template"
"log"
"net/http"
)

//go:embed *.gohtml
var templateFiles embed.FS

var templates = template.Must(template.ParseFS(templateFiles, "*"))

//go:generate muxt generate --receiver-static-type=Server

func main() {
srv := Server{}
mux := http.NewServeMux()
routes(mux, &srv)
log.Fatal(http.ListenAndServe(":8080", mux))
}

type Server struct{}

type IndexData struct{}

func (srv *Server) Index(ctx context.Context) IndexData {
return IndexData{}
}
-- index.gohtml --
<!DOCTYPE html>
<html lang="en">
{{block "head" "Welcome!"}}
<head>
<meta charset='UTF-8'/>
<title>{{.}}</title>
<script src='https://unpkg.com/htmx.org@2.0.3/dist/htmx.min.js'
crossorigin='anonymous'
integrity='sha384-0895/pl2MU10Hqc6jd4RvrthNlDiE9U1tWmX7WRESftEDRosgxNsQG/Ze9YMRzHq'></script>

<link rel='stylesheet'
href='https://unpkg.com/browse/@picocss/pico@2.0.6/css/pico.min.css'
integrity='sha384-7P0NVe9LPDbUCAF+fH2R8Egwz1uqNH83Ns/bfJY0fN2XCDBMUI2S9gGzIOIRBKsA'>
</head>
{{end}}
<body>
<main class='container'>

<h1>Hello, friend!</h1>

{{- define "GET /{$} Index(ctx)" -}}
{{template "index.gohtml" .}}
{{- end -}}

</main>
{{block "footer" 0}}
<footer>
<ul>
<li>
<a href='/'>Welcome</a>
</li>
<li>
<a href='/about'>About</a>
</li>
</ul>
</footer>
{{end}}
</body>
</html>

{{define "About"}}
<!DOCTYPE html>
<html lang="en">
{{template "head" "About"}}
<body>
<main class='container'>

<h1>About Page</h1>

</main>
</body>
</html>
{{end}}{{- define "GET /about" -}}
{{template "About" .}}
{{- end -}}

7 changes: 4 additions & 3 deletions cmd/muxt/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,14 @@ type Generate struct {
receiverInterfaceIdent string
}

func newGenerate(args []string, getEnv func(string) string) (Generate, error) {
func newGenerate(args []string, getEnv func(string) string, stderr io.Writer) (Generate, error) {
g := Generate{
goPackage: getEnv("GOPACKAGE"),
goFile: getEnv("GOFILE"),
goLine: getEnv("GOLINE"),
}
flagSet := flag.NewFlagSet("generate", flag.ContinueOnError)
flagSet.SetOutput(stderr)
flagSet.StringVar(&g.outputFilename, outputFlagFlagName, muxt.DefaultOutputFileName, "file name of generated output")
flagSet.StringVar(&g.templatesVariable, templatesVariable, muxt.DefaultTemplatesVariableName, "templates variable name")
flagSet.StringVar(&g.routesFunction, routesFunc, muxt.DefaultRoutesFunctionName, "file name of generated output")
Expand All @@ -75,8 +76,8 @@ func newGenerate(args []string, getEnv func(string) string) (Generate, error) {
return g, nil
}

func generateCommand(args []string, workingDirectory string, getEnv func(string) string, stdout io.Writer) error {
g, err := newGenerate(args, getEnv)
func generateCommand(args []string, workingDirectory string, getEnv func(string) string, stdout, stderr io.Writer) error {
g, err := newGenerate(args, getEnv, stderr)
if err != nil {
return err
}
Expand Down
11 changes: 6 additions & 5 deletions cmd/muxt/generate_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"io"
"testing"

"github.com/stretchr/testify/assert"
Expand All @@ -14,31 +15,31 @@ func Test_newGenerate(t *testing.T) {
t.Run("unknown flag", func(t *testing.T) {
_, err := newGenerate([]string{
"--unknown",
}, func(s string) string { return "" })
}, func(s string) string { return "" }, io.Discard)
assert.ErrorContains(t, err, "flag provided but not defined")
})
t.Run(receiverStaticType+" flag value is an invalid identifier", func(t *testing.T) {
_, err := newGenerate([]string{
"--" + receiverStaticType, "123",
}, func(s string) string { return "" })
}, func(s string) string { return "" }, io.Discard)
assert.ErrorContains(t, err, errIdentSuffix)
})
t.Run(routesFunc+" flag value is an invalid identifier", func(t *testing.T) {
_, err := newGenerate([]string{
"--" + routesFunc, "123",
}, func(s string) string { return "" })
}, func(s string) string { return "" }, io.Discard)
assert.ErrorContains(t, err, errIdentSuffix)
})
t.Run(templatesVariable+" flag value is an invalid identifier", func(t *testing.T) {
_, err := newGenerate([]string{
"--" + templatesVariable, "123",
}, func(s string) string { return "" })
}, func(s string) string { return "" }, io.Discard)
assert.ErrorContains(t, err, errIdentSuffix)
})
t.Run(outputFlagFlagName+" flag value is not a go file", func(t *testing.T) {
_, err := newGenerate([]string{
"--" + outputFlagFlagName, "output.txt",
}, func(s string) string { return "" })
}, func(s string) string { return "" }, io.Discard)
assert.ErrorContains(t, err, "filename must use .go extension")
})
}
8 changes: 4 additions & 4 deletions cmd/muxt/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ func main() {
if err != nil {
os.Exit(handleError(err))
}
os.Exit(handleError(command(wd, flag.Args(), os.Getenv, os.Stdout)))
os.Exit(handleError(command(wd, flag.Args(), os.Getenv, os.Stdout, os.Stderr)))
}

func command(wd string, args []string, getEnv func(string) string, stdout io.Writer) error {
func command(wd string, args []string, getEnv func(string) string, stdout, stderr io.Writer) error {
if len(args) > 0 {
switch args[0] {
case "generate", "gen", "g":
return generateCommand(args[1:], wd, getEnv, stdout)
return generateCommand(args[1:], wd, getEnv, stdout, stderr)
case "new", "n":
return newCommand(args[1:], wd, getEnv, stdout)
return newCommand(args[1:], wd, getEnv, stdout, stderr)
}
}
return fmt.Errorf("unknown command")
Expand Down
2 changes: 1 addition & 1 deletion cmd/muxt/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func commandTest(t *testing.T, pattern string) {
err := command(state.Getwd(), args, func(s string) string {
e, _ := state.LookupEnv(s)
return e
}, &stdout)
}, &stdout, &stderr)
if err != nil {
stderr.WriteString(err.Error())
}
Expand Down
53 changes: 51 additions & 2 deletions cmd/muxt/new.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,60 @@
package main

import (
"embed"
"flag"
"fmt"
"io"
"io/fs"
"os"
"path"
"slices"
"strings"

"golang.org/x/tools/txtar"
)

func newCommand(_ []string, _ string, _ func(string) string, stdout io.Writer) error {
_, err := fmt.Fprintln(stdout, "Coming soon...")
//go:embed data/new/*.txtar
var projectTemplates embed.FS

func newCommand(args []string, workingDirectory string, _ func(string) string, stdout, stderr io.Writer) error {
templateFilePaths, err := fs.Glob(projectTemplates, "data/new/*.txtar")
if err != nil {
return fmt.Errorf("failed to load new project templates")
}
var newProjectTemplateNames []string
for _, filePath := range templateFilePaths {
name := strings.TrimSuffix(path.Base(filePath), path.Ext(filePath))
newProjectTemplateNames = append(newProjectTemplateNames, name)
}
var (
templateName string
)
flagSet := flag.NewFlagSet("new", flag.ContinueOnError)
flagSet.SetOutput(stderr)
flagSet.StringVar(&templateName, "template", "default", fmt.Sprintf("new project template name one of: %s", strings.Join(newProjectTemplateNames, ", ")))
if err := flagSet.Parse(args); err != nil {
return fmt.Errorf("failed to parse arguments for new command: %w", err)
}
i := slices.Index(newProjectTemplateNames, templateName)
if i < 0 {
return fmt.Errorf("unknown new project tamplate name: %q", templateName)
}
selectedTemplateName := templateFilePaths[i]

buf, err := fs.ReadFile(projectTemplates, selectedTemplateName)
if err != nil {
return fmt.Errorf("failed to read new project template: %w", err)
}

archive := txtar.Parse(buf)
dir, err := txtar.FS(archive)
if err != nil {
return fmt.Errorf("failed to use new project template as directory: %w", err)
}
if err := os.CopyFS(workingDirectory, dir); err != nil {
return fmt.Errorf("failed to copy new project template files to output directory %q: %w", workingDirectory, err)
}
_, err = fmt.Fprintf(stdout, "new project generated\nnow run:\n\n\tgo generate")
return err
}
12 changes: 12 additions & 0 deletions cmd/muxt/testdata/new/default.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
exec go mod init example.com/my-project

muxt new

stdout 'new project generated'
stdout 'now run:'
stdout 'go generate'

exec go generate -x
stderr 'muxt generate --receiver-static-type=Server'

muxt generate --receiver-static-type=Server
2 changes: 0 additions & 2 deletions cmd/muxt/testdata/new/simple.txtar

This file was deleted.

0 comments on commit 84173cc

Please sign in to comment.