add watcher

Adds the ability to watch a directory for changes and run a command
when changes are spit out
This commit is contained in:
Aaron Bieber 2017-02-27 11:12:49 -07:00
parent 913e4bf460
commit e6bcf25e65
3 changed files with 137 additions and 90 deletions

6
glide.lock generated
View File

@ -1,6 +1,8 @@
hash: af0c2b0e7fd58c70a43dcf5c75b802f7a49c5d53ad6aec1975adfebe0acee206 hash: aa963bb1783c6d48ae4d7001851c87e2abb46cfbcdfd8a4792dbe766b7fafcd3
updated: 2017-02-04T09:25:07.785352554-07:00 updated: 2017-02-27T10:22:14.549716708-07:00
imports: imports:
- name: github.com/fsnotify/fsnotify
version: 629574ca2a5df945712d3079857300b5e4da0236
- name: github.com/gorilla/feeds - name: github.com/gorilla/feeds
version: 441264de03a8117ed530ae8e049d8f601a33a099 version: 441264de03a8117ed530ae8e049d8f601a33a099
- name: github.com/russross/blackfriday - name: github.com/russross/blackfriday

View File

@ -4,3 +4,5 @@ import:
version: ~1.4.0 version: ~1.4.0
- package: github.com/ylih/extrasys - package: github.com/ylih/extrasys
- package: github.com/gorilla/feeds - package: github.com/gorilla/feeds
- package: github.com/fsnotify/fsnotify
version: ^1.4.2

219
main.go
View File

@ -2,17 +2,20 @@ package main
import ( import (
"bufio" "bufio"
"flag"
"fmt" "fmt"
"html/template" "html/template"
"io/ioutil" "io/ioutil"
"log" "log"
"os" "os"
"os/exec"
"path" "path"
"regexp" "regexp"
"sort" "sort"
"strings" "strings"
"time" "time"
"github.com/fsnotify/fsnotify"
. "github.com/gorilla/feeds" . "github.com/gorilla/feeds"
"github.com/russross/blackfriday" "github.com/russross/blackfriday"
// "github.com/ylih/extrasys" // "github.com/ylih/extrasys"
@ -259,107 +262,147 @@ func main() {
var err error var err error
// extrasys.Pledge("stdio wpath rpath cpath", nil) // extrasys.Pledge("stdio wpath rpath cpath", nil)
if len(os.Args) < 2 { var watch = flag.Bool("w", false, "Enable 'watch' mode. Requires 'wdir' and 'wcmd'.")
fmt.Println("Wrong number of arguments") var watchDir = flag.String("wdir", "", "watch a directory for changes, run command when change happens.")
os.Exit(1) var watchCmd = flag.String("wcmd", "", "command to run when changes are detected in 'wdir'.")
}
src := os.Args[1] flag.Parse()
tmpl := os.Args[2]
dst := os.Args[3]
templ, err = template.New("boring").Funcs(funcMap).ParseGlob(tmpl + "/*.html") if !*watch {
if err != nil { if len(os.Args) < 2 {
log.Fatal(err) fmt.Println("Wrong number of arguments")
} os.Exit(1)
}
log.Printf("Generating static html from %s to %s\n", src, dst) src := os.Args[1]
tmpl := os.Args[2]
dst := os.Args[3]
files, err := ioutil.ReadDir(src) templ, err = template.New("boring").Funcs(funcMap).ParseGlob(tmpl + "/*.html")
if err != nil {
log.Fatal(err)
}
posts := Posts{}
for _, file := range files {
fn := file.Name()
srcFile := path.Join(src, fn)
dstFile := path.Join(dst, "/posts/", md2html(fn))
post, err := renderPost(srcFile, path.Join("posts/", fn))
fmt.Println("-----")
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
renderTemplate(dstFile, "default.html", struct { log.Printf("Generating static html from %s to %s\n", src, dst)
Content Post
}{
post,
})
posts = append(posts, &post) files, err := ioutil.ReadDir(src)
} if err != nil {
log.Fatal(err)
}
sort.Sort(posts) posts := Posts{}
for _, file := range files {
fn := file.Name()
srcFile := path.Join(src, fn)
dstFile := path.Join(dst, "/posts/", md2html(fn))
post, err := renderPost(srcFile, path.Join("posts/", fn))
fmt.Println("-----")
if err != nil {
log.Fatal(err)
}
renderTemplate(path.Join(dst, "/index.html"), "index.html", content{ renderTemplate(dstFile, "default.html", struct {
Title: "", Content Post
Posts: posts, }{
}) post,
renderTemplate(path.Join(dst, "/about.html"), "about.html", content{ })
Title: "About",
Author: posts[0].Author, posts = append(posts, &post)
}) }
renderTemplate(path.Join(dst, "/contact.html"), "contact.html", content{
Title: "Contact", sort.Sort(posts)
Author: posts[0].Author,
}) renderTemplate(path.Join(dst, "/index.html"), "index.html", content{
if len(posts) < 5 { Title: "",
renderTemplate(path.Join(dst, "/archive.html"), "archive.html", content{
Title: "Archive",
Posts: posts, Posts: posts,
}) })
} else { renderTemplate(path.Join(dst, "/about.html"), "about.html", content{
renderTemplate(path.Join(dst, "/archive.html"), "archive.html", content{ Title: "About",
Title: "Archive", Author: posts[0].Author,
Posts: posts[5:],
}) })
renderTemplate(path.Join(dst, "/contact.html"), "contact.html", content{
Title: "Contact",
Author: posts[0].Author,
})
if len(posts) < 5 {
renderTemplate(path.Join(dst, "/archive.html"), "archive.html", content{
Title: "Archive",
Posts: posts,
})
} else {
renderTemplate(path.Join(dst, "/archive.html"), "archive.html", content{
Title: "Archive",
Posts: posts[5:],
})
}
// TODO variablize all of this and shove it in some kind of config
latestDate := posts[0].Date
feed := &Feed{
Title: "deftly.net - All posts",
Link: &Link{Href: "https://deftly.net/"},
Description: "Personal blog of Aaron Bieber",
Author: &Author{Name: "Aaron Bieber", Email: "aaron@bolddaemon.com"},
Created: latestDate,
Copyright: "This work is copyright © Aaron Bieber",
}
for _, post := range posts {
var i = &Item{}
i.Title = post.Title
i.Description = string(post.Body)
i.Link = &Link{Href: "https://deftly.net" + post.URL}
i.Author = &Author{Name: post.Author.Combine(), Email: "aaron@bolddaemon.com"}
i.Created = post.Date
feed.Items = append(feed.Items, i)
}
atomFile, err := os.Create(path.Join(dst, "atom.xml"))
if err != nil {
log.Fatal(err)
}
rssFile, err := os.Create(path.Join(dst, "rss.xml"))
if err != nil {
log.Fatal(err)
}
feed.WriteAtom(atomFile)
feed.WriteRss(rssFile)
} else {
// Watch mode
watcher, err := fsnotify.NewWatcher()
if err != nil {
log.Fatal(err)
}
defer watcher.Close()
done := make(chan bool)
go func() {
for {
select {
case event := <-watcher.Events:
if event.Op&fsnotify.Write == fsnotify.Write {
log.Println("modified file:", event.Name)
c := exec.Command(*watchCmd)
if err := c.Run(); err != nil {
fmt.Println("Error: ", err)
}
}
case err := <-watcher.Errors:
log.Fatal(err)
}
}
}()
err = watcher.Add(*watchDir)
if err != nil {
log.Fatal(err)
}
<-done
} }
// TODO variablize all of this and shove it in some kind of config
latestDate := posts[0].Date
feed := &Feed{
Title: "deftly.net - All posts",
Link: &Link{Href: "https://deftly.net/"},
Description: "Personal blog of Aaron Bieber",
Author: &Author{Name: "Aaron Bieber", Email: "aaron@bolddaemon.com"},
Created: latestDate,
Copyright: "This work is copyright © Aaron Bieber",
}
for _, post := range posts {
var i = &Item{}
i.Title = post.Title
i.Description = string(post.Body)
i.Link = &Link{Href: "https://deftly.net" + post.URL}
i.Author = &Author{Name: post.Author.Combine(), Email: "aaron@bolddaemon.com"}
i.Created = post.Date
feed.Items = append(feed.Items, i)
}
atomFile, err := os.Create(path.Join(dst, "atom.xml"))
if err != nil {
log.Fatal(err)
}
rssFile, err := os.Create(path.Join(dst, "rss.xml"))
if err != nil {
log.Fatal(err)
}
feed.WriteAtom(atomFile)
feed.WriteRss(rssFile)
} }