1
0
mirror of https://github.com/danog/gojekyll.git synced 2024-12-02 14:47:47 +01:00

Implement serve --[no-]watch

This commit is contained in:
Oliver Steele 2017-07-14 18:40:09 -04:00
parent 41c60daf1e
commit 2a582e9778
6 changed files with 45 additions and 24 deletions

View File

@ -147,8 +147,8 @@ Muzukashii:
- [x] `clean` - [x] `clean`
- [x] `help` - [x] `help`
- [x] `serve` - [x] `serve`
- [x] `--open-uri`, `--host`, `--port` - [x] `--open-uri`, `--host`, `--port`, `watch` (enabled by default)
- [ ] `--baseurl`, `--config`, `--incremental`, `--[no-]watch` (`watch` is always enabled) - [ ] `--baseurl`, `--config`, `--incremental`
- [ ] `--detach`, `--ssl`-* not planned - [ ] `--detach`, `--ssl`-* not planned
- [ ] `doctor`, `import`, `new`, `new-theme` not planned - [ ] `doctor`, `import`, `new`, `new-theme` not planned
- [ ] Windows - [ ] Windows

View File

@ -9,7 +9,8 @@ import (
// Command-line options // Command-line options
var ( var (
buildOptions site.BuildOptions buildOptions site.BuildOptions
configFlags = config.Flags{} watch = true
configFlags = config.Flags{Watch: &watch}
profile = false profile = false
quiet = false quiet = false
) )
@ -36,7 +37,7 @@ var (
serve = app.Command("serve", "Serve your site locally").Alias("server").Alias("s") serve = app.Command("serve", "Serve your site locally").Alias("server").Alias("s")
open = serve.Flag("open-url", "Launch your site in a browser").Short('o').Bool() open = serve.Flag("open-url", "Launch your site in a browser").Short('o').Bool()
_ = app.Flag("host", "Host to bind to").Short('H').Action(stringVar("host", &configFlags.Host)).String() _ = serve.Flag("host", "Host to bind to").Short('H').Action(stringVar("host", &configFlags.Host)).String()
_ = serve.Flag("port", "Port to listen on").Short('P').Action(intVar("port", &configFlags.Port)).Int() _ = serve.Flag("port", "Port to listen on").Short('P').Action(intVar("port", &configFlags.Port)).Int()
variables = app.Command("variables", "Display a file or URL path's variables").Alias("v").Alias("var").Alias("vars") variables = app.Command("variables", "Display a file or URL path's variables").Alias("v").Alias("var").Alias("vars")
@ -50,4 +51,5 @@ func init() {
app.Flag("profile", "Create a Go pprof CPU profile").BoolVar(&profile) app.Flag("profile", "Create a Go pprof CPU profile").BoolVar(&profile)
app.Flag("quiet", "Silence (some) output.").Short('q').BoolVar(&quiet) app.Flag("quiet", "Silence (some) output.").Short('q').BoolVar(&quiet)
build.Flag("dry-run", "Dry run").Short('n').BoolVar(&buildOptions.DryRun) build.Flag("dry-run", "Dry run").Short('n').BoolVar(&buildOptions.DryRun)
serve.Flag("watch", "Watch for changes and rebuild").Short('w').Default("true").BoolVar(&watch)
} }

View File

@ -45,6 +45,9 @@ type Config struct {
// Outputting // Outputting
Permalink string Permalink string
// CLI-only
Watch bool `yaml:"-"`
Defaults []struct { Defaults []struct {
Scope struct { Scope struct {
Path string Path string

View File

@ -4,7 +4,7 @@ package config
// They are pointers to represent optional types, to tell whether they have been set. // They are pointers to represent optional types, to tell whether they have been set.
type Flags struct { type Flags struct {
Destination, Host *string Destination, Host *string
Drafts, Future, Unpublished *bool Drafts, Future, Unpublished, Watch *bool
Port *int Port *int
} }
@ -28,4 +28,7 @@ func (c *Config) ApplyFlags(flags Flags) {
if flags.Unpublished != nil { if flags.Unpublished != nil {
c.Unpublished = *flags.Unpublished c.Unpublished = *flags.Unpublished
} }
if flags.Watch != nil {
c.Watch = *flags.Watch
}
} }

View File

@ -27,12 +27,14 @@ func (s *Server) Run(open bool, logger func(label, value string)) error {
s.Site.SetAbsoluteURL("") s.Site.SetAbsoluteURL("")
address := fmt.Sprintf("%s:%d", cfg.Host, cfg.Port) address := fmt.Sprintf("%s:%d", cfg.Host, cfg.Port)
logger("Server address:", "http://"+address+"/") logger("Server address:", "http://"+address+"/")
if cfg.Watch {
if err := s.StartLiveReloader(); err != nil { if err := s.StartLiveReloader(); err != nil {
return err return err
} }
if err := s.watchAndReload(); err != nil { if err := s.watchAndReload(); err != nil {
return err return err
} }
}
http.HandleFunc("/", s.handler) http.HandleFunc("/", s.handler)
c := make(chan error) c := make(chan error)
go func() { go func() {

View File

@ -51,24 +51,35 @@ func (s *Server) watchFiles(fn func([]string)) error {
}() }()
go func() { go func() {
for { for {
filenames := <-debounced paths := s.sitePaths(<-debounced)
relpaths := make([]string, 0, len(filenames)) if len(paths) > 0 {
seen := map[string]bool{} fn(paths)
for _, filename := range filenames {
relpath := utils.MustRel(sourceDir, filename)
if relpath == "_config.yml" || !site.Exclude(relpath) {
if !seen[relpath] {
seen[relpath] = true
relpaths = append(relpaths, relpath)
} }
} }
}
fn(relpaths)
}
}() }()
return watcher.Add(sourceDir) return watcher.Add(sourceDir)
} }
// relativize and de-dup paths and filter to those the site source
func (s *Server) sitePaths(filenames []string) []string {
var (
site = s.Site
dir = site.SourceDir()
paths = make([]string, 0, len(filenames))
seen = map[string]bool{}
)
for _, filename := range filenames {
path := utils.MustRel(dir, filename)
if path == "_config.yml" || !site.Exclude(path) {
if !seen[path] {
seen[path] = true
paths = append(paths, path)
}
}
}
return paths
}
// debounce relays values from input to output, merging successive values within interval // debounce relays values from input to output, merging successive values within interval
// TODO consider https://github.com/ReactiveX/RxGo // TODO consider https://github.com/ReactiveX/RxGo
func debounce(interval time.Duration, input <-chan string) <-chan []string { func debounce(interval time.Duration, input <-chan string) <-chan []string {