URI: 
       Change the interface to use commands and flags instead of just flags. Better organization of main (controller style) code. - hugo - [fork] hugo port for 9front
  HTML git clone git@git.drkhsh.at/hugo.git
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
   DIR README
   DIR LICENSE
       ---
   DIR commit 94d7fe52f87a3188a27767433e7a07f5ada84988
   DIR parent 92cff055828ff250a5d40c3dae55f0d0235c7f61
  HTML Author: spf13 <steve.francia@gmail.com>
       Date:   Sun, 29 Sep 2013 02:09:03 -0400
       
       Change the interface to use commands and flags instead of just flags.
       Better organization of main (controller style) code.
       
       Diffstat:
         A commands/benchmark.go               |      51 +++++++++++++++++++++++++++++++
         A commands/check.go                   |      31 +++++++++++++++++++++++++++++++
         A commands/hugo.go                    |     138 ++++++++++++++++++++++++++++++
         A commands/server.go                  |     123 +++++++++++++++++++++++++++++++
         A commands/version.go                 |      28 ++++++++++++++++++++++++++++
         M main.go                             |     220 +------------------------------
       
       6 files changed, 373 insertions(+), 218 deletions(-)
       ---
   DIR diff --git a/commands/benchmark.go b/commands/benchmark.go
       @@ -0,0 +1,51 @@
       +// Copyright © 2013 Steve Francia <spf@spf13.com>.
       +//
       +// Licensed under the Simple Public License, Version 2.0 (the "License");
       +// you may not use this file except in compliance with the License.
       +// You may obtain a copy of the License at
       +// http://opensource.org/licenses/Simple-2.0
       +//
       +// Unless required by applicable law or agreed to in writing, software
       +// distributed under the License is distributed on an "AS IS" BASIS,
       +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       +// See the License for the specific language governing permissions and
       +// limitations under the License.
       +
       +package commands
       +
       +import (
       +        "github.com/spf13/cobra"
       +        "os"
       +        "runtime/pprof"
       +)
       +
       +var cpuProfilefile string
       +var benchmarkTimes int
       +
       +var benchmark = &cobra.Command{
       +        Use:   "benchmark",
       +        Short: "Benchmark hugo by building a site a number of times",
       +        Long: `Hugo can build a site many times over and anlyze the
       +    running process creating a `,
       +        Run: bench,
       +}
       +
       +func init() {
       +        benchmark.Flags().StringVar(&cpuProfilefile, "outputfile", "/tmp/hugo-cpuprofile", "path/filename for the profile file")
       +        benchmark.Flags().IntVarP(&benchmarkTimes, "count", "n", 13, "number of times to build the site")
       +}
       +
       +func bench(cmd *cobra.Command, args []string) {
       +        f, err := os.Create(cpuProfilefile)
       +
       +        if err != nil {
       +                panic(err)
       +        }
       +
       +        pprof.StartCPUProfile(f)
       +        defer pprof.StopCPUProfile()
       +
       +        for i := 0; i < benchmarkTimes; i++ {
       +                _, _ = buildSite()
       +        }
       +}
   DIR diff --git a/commands/check.go b/commands/check.go
       @@ -0,0 +1,31 @@
       +// Copyright © 2013 Steve Francia <spf@spf13.com>.
       +//
       +// Licensed under the Simple Public License, Version 2.0 (the "License");
       +// you may not use this file except in compliance with the License.
       +// You may obtain a copy of the License at
       +// http://opensource.org/licenses/Simple-2.0
       +//
       +// Unless required by applicable law or agreed to in writing, software
       +// distributed under the License is distributed on an "AS IS" BASIS,
       +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       +// See the License for the specific language governing permissions and
       +// limitations under the License.
       +
       +package commands
       +
       +import (
       +        "github.com/spf13/cobra"
       +        "github.com/spf13/hugo/hugolib"
       +)
       +
       +var check = &cobra.Command{
       +        Use:   "check",
       +        Short: "Check content in the source directory",
       +        Long: `Hugo will perform some basic analysis on the
       +    content provided and will give feedback.`,
       +        Run: func(cmd *cobra.Command, args []string) {
       +                InitializeConfig()
       +                site := hugolib.Site{Config: *Config}
       +                site.Analyze()
       +        },
       +}
   DIR diff --git a/commands/hugo.go b/commands/hugo.go
       @@ -0,0 +1,138 @@
       +// Copyright © 2013 Steve Francia <spf@spf13.com>.
       +//
       +// Licensed under the Simple Public License, Version 2.0 (the "License");
       +// you may not use this file except in compliance with the License.
       +// You may obtain a copy of the License at
       +// http://opensource.org/licenses/Simple-2.0
       +//
       +// Unless required by applicable law or agreed to in writing, software
       +// distributed under the License is distributed on an "AS IS" BASIS,
       +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       +// See the License for the specific language governing permissions and
       +// limitations under the License.
       +
       +package commands
       +
       +import (
       +        "fmt"
       +        "github.com/mostafah/fsync"
       +        "github.com/spf13/cobra"
       +        "github.com/spf13/hugo/hugolib"
       +        "log"
       +        "os"
       +        "path/filepath"
       +        "time"
       +)
       +
       +var Config *hugolib.Config
       +var HugoCmd = &cobra.Command{
       +        Use:   "hugo",
       +        Short: "Hugo is a very fast static site generator",
       +        Long: `A Fast and Flexible Static Site Generator built with
       +love by spf13 and friends in Go.
       +
       +Complete documentation is available at http://hugo.spf13.com`,
       +        Run: build,
       +}
       +
       +var Hugo *cobra.Commander
       +var BuildWatch, Draft, UglyUrls, Verbose bool
       +var Source, Destination, BaseUrl, CfgFile string
       +
       +func Execute() {
       +        AddCommands()
       +        Hugo := HugoCmd.ToCommander()
       +        Hugo.Execute()
       +}
       +
       +func AddCommands() {
       +        HugoCmd.AddCommand(serverCmd)
       +        HugoCmd.AddCommand(version)
       +        HugoCmd.AddCommand(check)
       +        HugoCmd.AddCommand(benchmark)
       +}
       +
       +func init() {
       +        HugoCmd.PersistentFlags().BoolVarP(&Draft, "build-drafts", "D", false, "include content marked as draft")
       +        HugoCmd.PersistentFlags().StringVarP(&Source, "source", "s", "", "filesystem path to read files relative from")
       +        HugoCmd.PersistentFlags().StringVarP(&Destination, "destination", "d", "", "filesystem path to write files to")
       +        HugoCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output")
       +        HugoCmd.PersistentFlags().BoolVar(&UglyUrls, "uglyurls", false, "if true, use /filename.html instead of /filename/")
       +        HugoCmd.PersistentFlags().StringVarP(&BaseUrl, "base-url", "b", "", "hostname (and path) to the root eg. http://spf13.com/")
       +        HugoCmd.PersistentFlags().StringVar(&CfgFile, "config", "", "config file (default is path/config.yaml|json|toml)")
       +        HugoCmd.Flags().BoolVarP(&BuildWatch, "watch", "w", false, "watch filesystem for changes and recreate as needed")
       +}
       +
       +func InitializeConfig() {
       +        Config = hugolib.SetupConfig(&CfgFile, &Source)
       +        Config.BuildDrafts = Draft
       +        Config.UglyUrls = UglyUrls
       +        Config.Verbose = Verbose
       +        if BaseUrl != "" {
       +                Config.BaseUrl = BaseUrl
       +        }
       +        if Destination != "" {
       +                Config.PublishDir = Destination
       +        }
       +}
       +
       +func build(cmd *cobra.Command, args []string) {
       +        InitializeConfig()
       +
       +        err := copyStatic()
       +        if err != nil {
       +                log.Fatalf("Error copying static files to %s: %v", Config.GetAbsPath(Config.PublishDir), err)
       +        }
       +        if _, err := buildSite(); err != nil {
       +                fmt.Println(err)
       +                os.Exit(-1)
       +        }
       +
       +        // Does this even make sense without the server setting?
       +        //if BuildWatch {
       +        //fmt.Println("Watching for changes in", Config.GetAbsPath(Config.ContentDir))
       +        //_, err = buildSite()
       +        //if err != nil {
       +        //fmt.Println(err)
       +        //os.Exit(-1)
       +        //}
       +        //}
       +}
       +
       +func copyStatic() error {
       +        // Copy Static to Destination
       +        return fsync.Sync(Config.GetAbsPath(Config.PublishDir+"/"), Config.GetAbsPath(Config.StaticDir+"/"))
       +}
       +
       +func getDirList() []string {
       +        var a []string
       +        walker := func(path string, fi os.FileInfo, err error) error {
       +                if err != nil {
       +                        fmt.Println("Walker: ", err)
       +                        return nil
       +                }
       +
       +                if fi.IsDir() {
       +                        a = append(a, path)
       +                }
       +                return nil
       +        }
       +
       +        filepath.Walk(Config.GetAbsPath(Config.ContentDir), walker)
       +        filepath.Walk(Config.GetAbsPath(Config.LayoutDir), walker)
       +        filepath.Walk(Config.GetAbsPath(Config.StaticDir), walker)
       +
       +        return a
       +}
       +
       +func buildSite() (site *hugolib.Site, err error) {
       +        startTime := time.Now()
       +        site = &hugolib.Site{Config: *Config}
       +        err = site.Build()
       +        if err != nil {
       +                return
       +        }
       +        site.Stats()
       +        fmt.Printf("in %v ms\n", int(1000*time.Since(startTime).Seconds()))
       +        return site, nil
       +}
   DIR diff --git a/commands/server.go b/commands/server.go
       @@ -0,0 +1,123 @@
       +// Copyright © 2013 Steve Francia <spf@spf13.com>.
       +//
       +// Licensed under the Simple Public License, Version 2.0 (the "License");
       +// you may not use this file except in compliance with the License.
       +// You may obtain a copy of the License at
       +// http://opensource.org/licenses/Simple-2.0
       +//
       +// Unless required by applicable law or agreed to in writing, software
       +// distributed under the License is distributed on an "AS IS" BASIS,
       +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       +// See the License for the specific language governing permissions and
       +// limitations under the License.
       +
       +package commands
       +
       +import (
       +        "fmt"
       +        "github.com/howeyc/fsnotify"
       +        "github.com/spf13/cobra"
       +        "net/http"
       +        "strconv"
       +        "strings"
       +        "sync"
       +)
       +
       +var serverPort int
       +var serverWatch bool
       +
       +func init() {
       +        serverCmd.Flags().IntVarP(&serverPort, "port", "p", 1313, "port to run the server on")
       +        serverCmd.Flags().BoolVarP(&serverWatch, "watch", "w", false, "watch filesystem for changes and recreate as needed")
       +}
       +
       +var serverCmd = &cobra.Command{
       +        Use:   "server",
       +        Short: "Hugo runs it's own a webserver to render the files",
       +        Long: `Hugo is able to run it's own high performance web server.
       +Hugo will render all the files defined in the source directory and
       +Serve them up.`,
       +        Run: server,
       +}
       +
       +func server(cmd *cobra.Command, args []string) {
       +        InitializeConfig()
       +
       +        if Config.BaseUrl == "" {
       +                Config.BaseUrl = "http://localhost:" + strconv.Itoa(serverPort)
       +        }
       +
       +        // Watch runs its own server as part of the routine
       +        if serverWatch {
       +                fmt.Println("Watching for changes in", Config.GetAbsPath(Config.ContentDir))
       +                err := NewWatcher(serverPort, true)
       +                if err != nil {
       +                        fmt.Println(err)
       +                }
       +        }
       +
       +        serve(serverPort)
       +}
       +
       +func serve(port int) {
       +        if Verbose {
       +                fmt.Println("Serving pages from " + Config.GetAbsPath(Config.PublishDir))
       +        }
       +
       +        fmt.Println("Web Server is available at http://localhost:", port)
       +        fmt.Println("Press ctrl+c to stop")
       +        panic(http.ListenAndServe(":"+strconv.Itoa(port), http.FileServer(http.Dir(Config.GetAbsPath(Config.PublishDir)))))
       +}
       +
       +func NewWatcher(port int, server bool) error {
       +        watcher, err := fsnotify.NewWatcher()
       +        var wg sync.WaitGroup
       +
       +        if err != nil {
       +                fmt.Println(err)
       +                return err
       +        }
       +
       +        defer watcher.Close()
       +
       +        wg.Add(1)
       +        go func() {
       +                for {
       +                        select {
       +                        case ev := <-watcher.Event:
       +                                if Verbose {
       +                                        fmt.Println(ev)
       +                                }
       +                                watchChange(ev)
       +                                // TODO add newly created directories to the watch list
       +                        case err := <-watcher.Error:
       +                                if err != nil {
       +                                        fmt.Println("error:", err)
       +                                }
       +                        }
       +                }
       +        }()
       +
       +        for _, d := range getDirList() {
       +                if d != "" {
       +                        _ = watcher.Watch(d)
       +                }
       +        }
       +
       +        if server {
       +                go serve(port)
       +        }
       +
       +        wg.Wait()
       +        return nil
       +}
       +
       +func watchChange(ev *fsnotify.FileEvent) {
       +        if strings.HasPrefix(ev.Name, Config.GetAbsPath(Config.StaticDir)) {
       +                fmt.Println("Static file changed, syncing\n")
       +                copyStatic()
       +        } else {
       +                fmt.Println("Change detected, rebuilding site\n")
       +                buildSite()
       +        }
       +}
   DIR diff --git a/commands/version.go b/commands/version.go
       @@ -0,0 +1,28 @@
       +// Copyright © 2013 Steve Francia <spf@spf13.com>.
       +//
       +// Licensed under the Simple Public License, Version 2.0 (the "License");
       +// you may not use this file except in compliance with the License.
       +// You may obtain a copy of the License at
       +// http://opensource.org/licenses/Simple-2.0
       +//
       +// Unless required by applicable law or agreed to in writing, software
       +// distributed under the License is distributed on an "AS IS" BASIS,
       +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       +// See the License for the specific language governing permissions and
       +// limitations under the License.
       +
       +package commands
       +
       +import (
       +        "fmt"
       +        "github.com/spf13/cobra"
       +)
       +
       +var version = &cobra.Command{
       +        Use:   "version",
       +        Short: "Print the version number of Hugo",
       +        Long:  `All software has versions. This is Hugo's`,
       +        Run: func(cmd *cobra.Command, args []string) {
       +                fmt.Println("Hugo Static Site Generator v0.9 -- HEAD")
       +        },
       +}
   DIR diff --git a/main.go b/main.go
       @@ -14,225 +14,9 @@
        package main
        
        import (
       -        "fmt"
       -        "github.com/howeyc/fsnotify"
       -        "github.com/mostafah/fsync"
       -        flag "github.com/ogier/pflag"
       -        "github.com/spf13/hugo/hugolib"
       -        "log"
       -        "net/http"
       -        "os"
       -        "path/filepath"
       -        "runtime/pprof"
       -        "strings"
       -        "sync"
       -        "time"
       +        "github.com/spf13/hugo/commands"
        )
        
       -var (
       -        baseUrl     = flag.StringP("base-url", "b", "", "hostname (and path) to the root eg. http://spf13.com/")
       -        cfgfile     = flag.String("config", "", "config file (default is path/config.yaml|json|toml)")
       -        checkMode   = flag.Bool("check", false, "analyze content and provide feedback")
       -        draft       = flag.BoolP("build-drafts", "D", false, "include content marked as draft")
       -        help        = flag.BoolP("help", "h", false, "show this help")
       -        source      = flag.StringP("source", "s", "", "filesystem path to read files relative from")
       -        destination = flag.StringP("destination", "d", "", "filesystem path to write files to")
       -        verbose     = flag.BoolP("verbose", "v", false, "verbose output")
       -        version     = flag.Bool("version", false, "which version of hugo")
       -        cpuprofile  = flag.Int("profile", 0, "Number of times to create the site and profile it")
       -        watchMode   = flag.BoolP("watch", "w", false, "watch filesystem for changes and recreate as needed")
       -        server      = flag.BoolP("server", "S", false, "run a (very) simple web server")
       -        port        = flag.String("port", "1313", "port to run web server on, default :1313")
       -        uglyUrls    = flag.Bool("uglyurls", false, "if true, use /filename.html instead of /filename/")
       -)
       -
       -func usage() {
       -        PrintErr("usage: hugo [flags]", "")
       -        flag.PrintDefaults()
       -        os.Exit(0)
       -}
       -
        func main() {
       -
       -        flag.Usage = usage
       -        flag.Parse()
       -
       -        if *help {
       -                usage()
       -        }
       -
       -        if *version {
       -                fmt.Println("Hugo Static Site Generator v0.8")
       -                return
       -        }
       -
       -        config := hugolib.SetupConfig(cfgfile, source)
       -        config.BuildDrafts = *draft
       -        config.UglyUrls = *uglyUrls
       -        config.Verbose = *verbose
       -
       -        if *baseUrl != "" {
       -                config.BaseUrl = *baseUrl
       -        } else if *server {
       -                config.BaseUrl = "http://localhost:" + *port
       -        }
       -
       -        if *destination != "" {
       -                config.PublishDir = *destination
       -        }
       -
       -        if *cpuprofile != 0 {
       -                f, err := os.Create("/tmp/hugo-cpuprofile")
       -
       -                if err != nil {
       -                        panic(err)
       -                }
       -
       -                pprof.StartCPUProfile(f)
       -                defer pprof.StopCPUProfile()
       -
       -                for i := 0; i < *cpuprofile; i++ {
       -                        _, _ = buildSite(config)
       -                }
       -        }
       -
       -        err := copyStatic(config)
       -        if err != nil {
       -                log.Fatalf("Error copying static files to %s: %v", config.GetAbsPath(config.PublishDir), err)
       -        }
       -
       -        if *checkMode {
       -                site := hugolib.Site{Config: *config}
       -                site.Analyze()
       -                os.Exit(0)
       -        }
       -
       -        if *watchMode {
       -                fmt.Println("Watching for changes. Press ctrl+c to stop")
       -                _, err = buildSite(config)
       -                if err != nil {
       -                        fmt.Println(err)
       -                        os.Exit(-1)
       -                }
       -                err := NewWatcher(config, *port, *server)
       -                if err != nil {
       -                        fmt.Println(err)
       -                }
       -        }
       -
       -        if _, err = buildSite(config); err != nil {
       -                fmt.Println(err)
       -                os.Exit(-1)
       -        }
       -
       -        if *server {
       -                serve(*port, config)
       -        }
       -
       -}
       -
       -func copyStatic(config *hugolib.Config) error {
       -        // Copy Static to Destination
       -        return fsync.Sync(config.GetAbsPath(config.PublishDir+"/"), config.GetAbsPath(config.StaticDir+"/"))
       -}
       -
       -func serve(port string, config *hugolib.Config) {
       -
       -        if config.Verbose {
       -                fmt.Println("Serving pages from " + config.GetAbsPath(config.PublishDir))
       -        }
       -
       -        fmt.Println("Web Server is available at http://localhost:" + port)
       -        fmt.Println("Press ctrl+c to stop")
       -        panic(http.ListenAndServe(":"+port, http.FileServer(http.Dir(config.GetAbsPath(config.PublishDir)))))
       -}
       -
       -func buildSite(config *hugolib.Config) (site *hugolib.Site, err error) {
       -        startTime := time.Now()
       -        site = &hugolib.Site{Config: *config}
       -        err = site.Build()
       -        if err != nil {
       -                return
       -        }
       -        site.Stats()
       -        fmt.Printf("in %v ms\n", int(1000*time.Since(startTime).Seconds()))
       -        return site, nil
       -}
       -
       -func watchChange(c *hugolib.Config, ev *fsnotify.FileEvent) {
       -        if strings.HasPrefix(ev.Name, c.GetAbsPath(c.StaticDir)) {
       -                fmt.Println("Static file changed, syncing\n")
       -                copyStatic(c)
       -        } else {
       -                fmt.Println("Change detected, rebuilding site\n")
       -                buildSite(c)
       -        }
       -}
       -
       -func NewWatcher(c *hugolib.Config, port string, server bool) error {
       -        watcher, err := fsnotify.NewWatcher()
       -        var wg sync.WaitGroup
       -
       -        if err != nil {
       -                fmt.Println(err)
       -                return err
       -        }
       -
       -        defer watcher.Close()
       -
       -        wg.Add(1)
       -        go func() {
       -                for {
       -                        select {
       -                        case ev := <-watcher.Event:
       -                                if c.Verbose {
       -                                        fmt.Println(ev)
       -                                }
       -                                watchChange(c, ev)
       -                                // TODO add newly created directories to the watch list
       -                        case err := <-watcher.Error:
       -                                if err != nil {
       -                                        fmt.Println("error:", err)
       -                                }
       -                        }
       -                }
       -        }()
       -
       -        for _, d := range getDirList(c) {
       -                if d != "" {
       -                        _ = watcher.Watch(d)
       -                }
       -        }
       -
       -        if server {
       -                go serve(port, c)
       -        }
       -
       -        wg.Wait()
       -        return nil
       -}
       -
       -func getDirList(c *hugolib.Config) []string {
       -        var a []string
       -        walker := func(path string, fi os.FileInfo, err error) error {
       -                if err != nil {
       -                        PrintErr("Walker: ", err)
       -                        return nil
       -                }
       -
       -                if fi.IsDir() {
       -                        a = append(a, path)
       -                }
       -                return nil
       -        }
       -
       -        filepath.Walk(c.GetAbsPath(c.ContentDir), walker)
       -        filepath.Walk(c.GetAbsPath(c.LayoutDir), walker)
       -        filepath.Walk(c.GetAbsPath(c.StaticDir), walker)
       -
       -        return a
       -}
       -
       -func PrintErr(str string, a ...interface{}) {
       -        fmt.Fprintln(os.Stderr, str, a)
       +        commands.Execute()
        }