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) } }