1
0
mirror of https://github.com/danog/gojekyll.git synced 2024-11-26 23:24:39 +01:00

Move each subcommand into own file

This commit is contained in:
Oliver Steele 2017-08-11 13:25:51 -04:00
parent fb3f7a9af3
commit 8de32110d5
10 changed files with 226 additions and 177 deletions

37
commands/benchmark.go Normal file
View File

@ -0,0 +1,37 @@
package commands
import (
"fmt"
"time"
"github.com/montanaflynn/stats"
)
var benchmark = app.Command("benchmark", "Repeat build for ten seconds. Implies --profile.")
// benchmarkCommand builds the site repeatedly until at least 10 seconds has elapsed,
// and reports the trial times. Empirically, it the same mean but low variance as using
// a separate benchmark runner that invokes a new gojekyll process each time.
func benchmarkCommand() (err error) {
startTime := time.Now()
samples := []float64{}
for i := 0; time.Since(startTime) < 10*time.Second; i++ {
sampleStart := time.Now()
site, err := loadSite(*source, options)
if err != nil {
return err
}
_, err = site.Build()
if err != nil {
return err
}
dur := time.Since(sampleStart).Seconds()
samples = append(samples, dur)
quiet = true
fmt.Printf("Run #%d; %.1fs elapsed\n", i+1, time.Since(commandStartTime).Seconds())
}
median, _ := stats.Median(samples)
stddev, _ := stats.StandardDeviationSample(samples)
fmt.Printf("%d samples @ %.2fs ± %.2fs\n", len(samples), median, stddev)
return nil
}

52
commands/build.go Normal file
View File

@ -0,0 +1,52 @@
package commands
import (
"fmt"
"os"
"time"
"github.com/osteele/gojekyll/site"
)
// main sets this
var commandStartTime = time.Now()
var build = app.Command("build", "Build your site").Alias("b")
func init() {
build.Flag("dry-run", "Dry run").Short('n').BoolVar(&options.DryRun)
}
func buildCommand(site *site.Site) error {
watch := site.Config().Watch
logger.path("Destination:", site.DestDir())
logger.label("Generating...", "")
count, err := site.Build()
switch {
case err == nil:
elapsed := time.Since(commandStartTime)
logger.label("", "wrote %d files in %.2fs.", count, elapsed.Seconds())
case watch:
fmt.Fprintln(os.Stderr, err)
default:
return err
}
// FIXME the watch will miss files that changed during the first build
// server watch is implemented inside Server.Run, in contrast to this command
if watch {
events, err := site.WatchRebuild()
if err != nil {
return err
}
logger.label("Auto-regeneration:", "enabled for %q", site.SourceDir())
for event := range events {
fmt.Print(event)
}
} else {
logger.label("Auto-regeneration:", "disabled. Use --watch to enable.")
}
return nil
}

10
commands/clean.go Normal file
View File

@ -0,0 +1,10 @@
package commands
import "github.com/osteele/gojekyll/site"
var clean = app.Command("clean", "Clean the site (removes site output) without building.")
func cleanCommand(site *site.Site) error {
logger.label("Cleaner:", "Removing %s...", site.DestDir())
return site.Clean()
}

View File

@ -1,119 +1,13 @@
package commands
import (
"fmt"
"os"
"path/filepath"
"sort"
"strings"
"time"
yaml "gopkg.in/yaml.v1"
"github.com/montanaflynn/stats"
"github.com/osteele/gojekyll/pages"
"github.com/osteele/gojekyll/server"
"github.com/osteele/gojekyll/site"
"github.com/osteele/gojekyll/utils"
"github.com/osteele/liquid"
)
// main sets this
var commandStartTime = time.Now()
func buildCommand(site *site.Site) error {
watch := site.Config().Watch
logger.path("Destination:", site.DestDir())
logger.label("Generating...", "")
count, err := site.Build()
switch {
case err == nil:
elapsed := time.Since(commandStartTime)
logger.label("", "wrote %d files in %.2fs.", count, elapsed.Seconds())
case watch:
fmt.Fprintln(os.Stderr, err)
default:
return err
}
// FIXME the watch will miss files that changed during the first build
// server watch is implemented inside Server.Run, in contrast to this command
if watch {
events, err := site.WatchRebuild()
if err != nil {
return err
}
logger.label("Auto-regeneration:", "enabled for %q", site.SourceDir())
for event := range events {
fmt.Print(event)
}
} else {
logger.label("Auto-regeneration:", "disabled. Use --watch to enable.")
}
return nil
}
func cleanCommand(site *site.Site) error {
logger.label("Cleaner:", "Removing %s...", site.DestDir())
return site.Clean()
}
// benchmarkCommand builds the site repeatedly until at least 10 seconds has elapsed,
// and reports the trial times. Empirically, it the same mean but low variance as using
// a separate benchmark runner that invokes a new gojekyll process each time.
func benchmarkCommand() (err error) {
startTime := time.Now()
samples := []float64{}
for i := 0; time.Since(startTime) < 10*time.Second; i++ {
sampleStart := time.Now()
site, err := loadSite(*source, options)
if err != nil {
return err
}
_, err = site.Build()
if err != nil {
return err
}
dur := time.Since(sampleStart).Seconds()
samples = append(samples, dur)
quiet = true
fmt.Printf("Run #%d; %.1fs elapsed\n", i+1, time.Since(commandStartTime).Seconds())
}
median, _ := stats.Median(samples)
stddev, _ := stats.StandardDeviationSample(samples)
fmt.Printf("%d samples @ %.2fs ± %.2fs\n", len(samples), median, stddev)
return nil
}
func routesCommand(site *site.Site) error {
logger.label("Routes:", "")
urls := []string{}
for u, p := range site.Routes {
if !(*dynamicRoutes && p.Static()) {
urls = append(urls, u)
}
}
sort.Strings(urls)
for _, u := range urls {
filename := site.Routes[u].SourcePath()
fmt.Printf(" %s -> %s\n", u, filename)
}
return nil
}
func renderCommand(site *site.Site) error {
p, err := pageFromPathOrRoute(site, *renderPath)
if err != nil {
return err
}
logger.path("Render:", filepath.Join(site.SourceDir(), p.SourcePath()))
logger.label("URL:", p.Permalink())
logger.label("Content:", "")
return site.WriteDocument(os.Stdout, p)
}
// If path starts with /, it's a URL path. Else it's a file path relative
// to the site source directory.
func pageFromPathOrRoute(s *site.Site, path string) (pages.Document, error) {
@ -135,52 +29,3 @@ func pageFromPathOrRoute(s *site.Site, path string) (pages.Document, error) {
return page, nil
}
}
func serveCommand(site *site.Site) error {
server := server.Server{Site: site}
return server.Run(*open, func(label, value string) {
logger.label(label, value)
})
}
func variablesCommand(site *site.Site) (err error) {
var data interface{}
switch {
case strings.HasPrefix(*variablePath, "site"):
data, err = utils.FollowDots(site, strings.Split(*variablePath, ".")[1:])
if err != nil {
return
}
case *variablePath != "":
data, err = pageFromPathOrRoute(site, *variablePath)
if err != nil {
return
}
default:
data = site
}
data = liquid.FromDrop(data)
if m, ok := data.(map[string]interface{}); ok {
for k, v := range m {
if b, ok := v.([]byte); ok {
m[k] = string(b)
}
}
}
b, err := yaml.Marshal(data)
if err != nil {
return err
}
logger.label("Variables:", "")
fmt.Println(string(b))
return nil
}
func versionCommand() error {
var d string
if !BuildTime.IsZero() {
d = BuildTime.Format(" (Build time: 2006-01-02T15:04)")
}
fmt.Printf("gojekyll version %s%s\n", Version, d)
return nil
}

View File

@ -20,27 +20,6 @@ var (
_ = app.Flag("future", "Publishes posts with a future date").Action(boolVar("future", &options.Future)).Bool()
_ = app.Flag("unpublished", "Render posts that were marked as unpublished").Action(boolVar("unpublished", &options.Unpublished)).Bool()
versionFlag = app.Flag("version", "Print the name and version").Short('v').Bool()
build = app.Command("build", "Build your site").Alias("b")
clean = app.Command("clean", "Clean the site (removes site output) without building.")
benchmark = app.Command("benchmark", "Repeat build for ten seconds. Implies --profile.")
render = app.Command("render", "Render a file or URL path to standard output")
renderPath = render.Arg("PATH", "Path or URL").String()
routes = app.Command("routes", "Display site permalinks and associated files")
dynamicRoutes = routes.Flag("dynamic", "Only show routes to non-static files").Bool()
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()
_ = serve.Flag("host", "Host to bind to").Short('H').Action(stringVar("host", &options.Host)).String()
_ = serve.Flag("port", "Port to listen on").Short('P').Action(intVar("port", &options.Port)).Int()
variables = app.Command("variables", "Display a file or URL path's variables").Alias("v").Alias("var").Alias("vars")
variablePath = variables.Arg("PATH", "Path, URL, site, or site...").String()
versionCmd = app.Command("version", "Print the name and version")
)
func init() {
@ -48,7 +27,6 @@ func init() {
app.Flag("profile", "Create a Go pprof CPU profile").BoolVar(&profile)
app.Flag("quiet", "Silence (some) output.").Short('q').BoolVar(&quiet)
_ = app.Flag("verbose", "Print verbose output.").Short('V').Action(boolVar("verbose", &options.Verbose)).Bool()
build.Flag("dry-run", "Dry run").Short('n').BoolVar(&options.DryRun)
// these flags are just present on build and serve, but I don't see a DRY way to say this
app.Flag("incremental", "Enable incremental rebuild.").Short('I').Action(boolVar("incremental", &options.Incremental)).Bool()

22
commands/render.go Normal file
View File

@ -0,0 +1,22 @@
package commands
import (
"os"
"path/filepath"
"github.com/osteele/gojekyll/site"
)
var render = app.Command("render", "Render a file or URL path to standard output")
var renderPath = render.Arg("PATH", "Path or URL").String()
func renderCommand(site *site.Site) error {
p, err := pageFromPathOrRoute(site, *renderPath)
if err != nil {
return err
}
logger.path("Render:", filepath.Join(site.SourceDir(), p.SourcePath()))
logger.label("URL:", p.Permalink())
logger.label("Content:", "")
return site.WriteDocument(os.Stdout, p)
}

27
commands/routes.go Normal file
View File

@ -0,0 +1,27 @@
package commands
import (
"fmt"
"sort"
"github.com/osteele/gojekyll/site"
)
var routes = app.Command("routes", "Display site permalinks and associated files")
var dynamicRoutes = routes.Flag("dynamic", "Only show routes to non-static files").Bool()
func routesCommand(site *site.Site) error {
logger.label("Routes:", "")
urls := []string{}
for u, p := range site.Routes {
if !(*dynamicRoutes && p.Static()) {
urls = append(urls, u)
}
}
sort.Strings(urls)
for _, u := range urls {
filename := site.Routes[u].SourcePath()
fmt.Printf(" %s -> %s\n", u, filename)
}
return nil
}

20
commands/serve.go Normal file
View File

@ -0,0 +1,20 @@
package commands
import (
"github.com/osteele/gojekyll/server"
"github.com/osteele/gojekyll/site"
)
var (
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()
_ = serve.Flag("host", "Host to bind to").Short('H').Action(stringVar("host", &options.Host)).String()
_ = serve.Flag("port", "Port to listen on").Short('P').Action(intVar("port", &options.Port)).Int()
)
func serveCommand(site *site.Site) error {
server := server.Server{Site: site}
return server.Run(*open, func(label, value string) {
logger.label(label, value)
})
}

47
commands/variables.go Normal file
View File

@ -0,0 +1,47 @@
package commands
import (
"fmt"
"strings"
"github.com/osteele/gojekyll/site"
"github.com/osteele/gojekyll/utils"
"github.com/osteele/liquid"
yaml "gopkg.in/yaml.v1"
)
var variables = app.Command("variables", "Display a file or URL path's variables").Alias("v").Alias("var").Alias("vars")
var variablePath = variables.Arg("PATH", "Path, URL, site, or site...").String()
func variablesCommand(site *site.Site) (err error) {
var data interface{}
switch {
case strings.HasPrefix(*variablePath, "site"):
data, err = utils.FollowDots(site, strings.Split(*variablePath, ".")[1:])
if err != nil {
return
}
case *variablePath != "":
data, err = pageFromPathOrRoute(site, *variablePath)
if err != nil {
return
}
default:
data = site
}
data = liquid.FromDrop(data)
if m, ok := data.(map[string]interface{}); ok {
for k, v := range m {
if b, ok := v.([]byte); ok {
m[k] = string(b)
}
}
}
b, err := yaml.Marshal(data)
if err != nil {
return err
}
logger.label("Variables:", "")
fmt.Println(string(b))
return nil
}

View File

@ -26,3 +26,14 @@ func init() {
}
}
}
var versionCmd = app.Command("version", "Print the name and version")
func versionCommand() error {
var d string
if !BuildTime.IsZero() {
d = BuildTime.Format(" (Build time: 2006-01-02T15:04)")
}
fmt.Printf("gojekyll version %s%s\n", Version, d)
return nil
}