Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft: rewrite the generator in go #258

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions bin/generator

This file was deleted.

1 change: 1 addition & 0 deletions generator/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/generator
17 changes: 17 additions & 0 deletions generator/ah.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package main

type Talk struct {
Author string
Title string
Description string
Duration uint
}

type ApiHour struct {
Version uint
Date Date
Location string
Address string
EventbriteId uint
Talks []Talk
}
42 changes: 42 additions & 0 deletions generator/date.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package main

import (
"errors"
"fmt"
"io"
"time"
)

var ErrInvalidDate = errors.New("invalid date")

type Date time.Time

func (d *Date) UnmarshalText(v []byte) error {
t, err := time.Parse("2006-01-02", string(v))
if err != nil {
return ErrInvalidDate
}

*d = Date(t)
return nil
}

func (d *Date) Scan(state fmt.ScanState, verb rune) error {
buf := make([]byte, 0, 10)
for {
r, _, err := state.ReadRune()
if err != nil {
if err == io.EOF {
return d.UnmarshalText(buf)
}
return err
}

buf = append(buf, byte(r))
}

}

func (d Date) Format(format string) string {
return time.Time(d).Format(format)
}
3 changes: 3 additions & 0 deletions generator/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/clermontech/clermontech.github.com/generator

go 1.20
193 changes: 193 additions & 0 deletions generator/input.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
package main

import (
"bufio"
"context"
"fmt"
"io"
"os"
"os/exec"
)

var Editor string

func init() {
env := os.Getenv("EDITOR")
if env == "" {
panic("$EDITOR not found")
}

bin, err := exec.LookPath(env)
if err != nil {
panic(fmt.Errorf("editor lookpath: %w", err))
}

Editor = bin
}

type Yes bool

func (y *Yes) UnmarshalText(v []byte) error {
var vv bool
switch string(v) {
case "y", "Y":
vv = true
default:
vv = false
}

*y = Yes(vv)
return nil
}

func (y *Yes) Scan(state fmt.ScanState, verb rune) error {
buf := make([]byte, 0, 1)
for {
r, _, err := state.ReadRune()
if err != nil {
if err == io.EOF {
return y.UnmarshalText(buf)
}
return err
}

buf = append(buf, byte(r))
}

}

func ReadInput(ctx context.Context) (ApiHour, error) {
var ah ApiHour

var v uint
if err := Ask("ApiHour Version (ex: 54)", &v); err != nil {
return ah, fmt.Errorf("ask: %w", err)
}
ah.Version = v

var d Date
if err := Ask("Date (ex: 2023-01-01)", &d); err != nil {
return ah, fmt.Errorf("ask: %w", err)
}
ah.Date = d

var l string
if err := Ask("Location (ex: Centre Jean Richepin)", &l); err != nil {
return ah, fmt.Errorf("ask: %w", err)
}
ah.Location = l

var a string
if err := Ask("Address (ex: 21 Rue J. Richepin, 63000 Clermont-Ferrand)", &a); err != nil {
return ah, fmt.Errorf("ask: %w", err)
}
ah.Address = a

var y Yes
if err := Ask("Set an Eventbrite Id? y/N", &y); err != nil {
return ah, fmt.Errorf("ask: %w", err)
}
if y {
var eid uint
if err := Ask("Eventbrite id", &eid); err != nil {
return ah, fmt.Errorf("ask: %w", err)
}
ah.EventbriteId = eid
}

// talks
oneLong := false
for {
var y Yes
if err := Ask("Set a talk? y/N", &y); err != nil {
return ah, fmt.Errorf("ask: %w", err)
}
if !y {
break
}

var t Talk

var a string
if err := Ask("\tAuthor", &a); err != nil {
return ah, fmt.Errorf("ask: %w", err)
}
t.Author = a

var tt string
if err := Ask("\tTitle", &tt); err != nil {
return ah, fmt.Errorf("ask: %w", err)
}
t.Title = tt

d, err := Edit(ctx)
if err != nil {
return ah, fmt.Errorf("edit: %w", err)
}
t.Description = d

var l Yes
if err := Ask("\tIs 30min? y/N", &l); err != nil {
return ah, fmt.Errorf("ask: %w", err)
}
if l {
t.Duration = 30
oneLong = true
} else {
t.Duration = 15
}

ah.Talks = append(ah.Talks, t)

// stop after 4 talks or 3 talks is we have a 30min talk.
if len(ah.Talks) == 4 || (oneLong && len(ah.Talks) == 3) {
break
}
}

return ah, nil
}

func Ask(q string, v any) error {
scanner := bufio.NewScanner(os.Stdin)
for {
fmt.Print(q, ": ")
scanner.Scan()
if _, err := fmt.Sscan(scanner.Text(), v); err != nil {
fmt.Printf("err: %v\n", err)
continue
}

break
}

if err := scanner.Err(); err != nil {
return fmt.Errorf("reading standard input: %w", err)
}
return nil
}

func Edit(ctx context.Context) (string, error) {
tempf, err := os.CreateTemp(os.TempDir(), "")
if err != nil {
return "", fmt.Errorf("create tmp: %w", err)
}
name := tempf.Name()
tempf.Close()
defer os.Remove(name)

cmd := exec.CommandContext(ctx, Editor, name)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout

if err := cmd.Run(); err != nil {
return "", fmt.Errorf("run editor: %w", err)
}

b, err := os.ReadFile(name)
if err != nil {
return "", fmt.Errorf("read file: %w", err)
}

return string(b), nil
}
55 changes: 55 additions & 0 deletions generator/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package main

import (
"context"
"errors"
"fmt"
"os"
"time"
)

func main() {
ctx := context.Background()

if err := run(ctx); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}

func Usage() {
fmt.Println("Usage: ./generator [../_posts]")
}

func run(ctx context.Context) error {
dir := "../_posts"
if len(os.Args) > 2 {
Usage()
return errors.New("bad args")
}
if len(os.Args) == 2 {
dir = os.Args[1]
}

ah, err := ReadInput(ctx)
if err != nil {
return fmt.Errorf("read input: %w", err)
}

filename := fmt.Sprintf("%s/%s-api-hour-%d.md",
dir, time.Now().Format("2006-01-02"), ah.Version,
)
f, err := os.Create(filename)
if err != nil {
return fmt.Errorf("create file: %s: %w", filename, err)
}
defer f.Close()

if err := ahTmpl.ExecuteTemplate(f, "apiHour.md.tpl", ah); err != nil {
return fmt.Errorf("execute template: %w", err)
}

fmt.Println("post generated:", filename)

return nil
}
Loading