wombat/post/post.go
2024-06-18 23:01:52 +02:00

141 lines
3.1 KiB
Go

package post
import (
"bytes"
"errors"
"flag"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"text/template"
"time"
goutil "git.fireandbrimst.one/aw/goutil/misc"
"git.fireandbrimst.one/aw/wombat/blog"
gen "git.fireandbrimst.one/aw/wombat/generate"
)
const dateformat string = "2006-01-02"
const stub string = `---
title: "{{.Title}}"
date: {{.Date}}
categories:
---
`
type post struct {
Title string
Date string
}
func filename(dirsuffix string, title string, now time.Time) string {
date := now.Format(dateformat)
asciiTitle := blog.ConvASCII(title)
return filepath.Join("stage0", "blog"+dirsuffix, fmt.Sprintf("%s-%s.md", date, asciiTitle))
}
func ensureDirectory(file string) {
dir := filepath.Dir(file)
err := os.MkdirAll(dir, 0755)
if err != nil {
panic(err)
}
}
func makePostFile(now time.Time, dirsuffix string, title string, content string) string {
file := filename(dirsuffix, title, now)
ensureDirectory(file)
post := post{}
post.Title = title
post.Date = now.Format(blog.TimeFormat)
t := template.Must(template.New("Poststub").Parse(stub))
buf := new(bytes.Buffer)
t.Execute(buf, post)
err := goutil.WriteFile(file, buf.String()+content)
if err != nil {
fmt.Println(err)
}
return file
}
func postNew(fl postFlags) error {
var err error
if fl.title == "" {
fl.title, err = goutil.AskFor("Title")
if err != nil {
return err
}
}
var content string
if fl.category != "" && fl.title != "" {
tmpcontent, _ := ioutil.ReadAll(os.Stdin)
content = string(tmpcontent)
}
var t time.Time
if fl.datetime.val != nil {
t = *fl.datetime.val
} else {
t = time.Now().UTC()
}
f := makePostFile(t, fl.blog, fl.title, content)
fmt.Println(f)
if content == "" {
wait := true
err = goutil.OpenInEditor(f, wait)
if err != nil {
fmt.Println(err)
fmt.Println("trying default application...")
err = goutil.OpenInDefaultApp(f, wait)
}
}
if err != nil {
return err
}
return gen.Generate(gen.GenerateFlags{Noserve: fl.noserve})
}
type DateFlag struct {
val *time.Time
}
func (d DateFlag) String() string {
if d.val == nil {
return ""
} else {
return time.Time(*d.val).Format(blog.TimeFormat)
}
}
func (d *DateFlag) Set(s string) error {
if d == nil {
return errors.New("func (d *DateFlag) Set(s string): d is nil")
}
val, err := time.Parse(blog.TimeFormat, s)
if err == nil {
d.val = &val
}
return err
}
type postFlags struct {
blog string
title string
category string
noserve bool
datetime DateFlag
}
func Command() (goutil.CommandFlagsInit, goutil.CommandFunc) {
f := postFlags{}
flagsInit := func(s *flag.FlagSet) {
s.StringVar(&f.blog, "blog", "", "which blog folder to post to, e.g. -blog=foo for 'blogfoo' (default \"blog\")")
s.StringVar(&f.title, "title", "", "if title and category are set: read content from stdin")
s.StringVar(&f.category, "category", "", "if title and category are set: read content from stdin")
s.BoolVar(&f.noserve, "noserve", false, "don't generate and serve afterwards")
s.Var(&f.datetime, "date", "use date and time other than now (yyyy-mm-dd HH:MM)")
}
return flagsInit, func([]string) error { return postNew(f) }
}