From 28ffb92b36f1e6e3313797e3676d3601a5791c07 Mon Sep 17 00:00:00 2001 From: spf13 Date: Fri, 2 May 2014 01:06:01 -0400 Subject: [PATCH] Adding the new command and the create package --- commands/hugo.go | 3 ++ commands/new.go | 86 +++++++++++++++++++++++++++++++ create/content.go | 128 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 217 insertions(+) create mode 100644 commands/new.go create mode 100644 create/content.go diff --git a/commands/hugo.go b/commands/hugo.go index fe5642334..df6a063c4 100644 --- a/commands/hugo.go +++ b/commands/hugo.go @@ -62,6 +62,7 @@ func AddCommands() { HugoCmd.AddCommand(check) HugoCmd.AddCommand(benchmark) HugoCmd.AddCommand(convertCmd) + HugoCmd.AddCommand(newCmd) } func init() { @@ -92,10 +93,12 @@ func InitializeConfig() { viper.RegisterAlias("taxonomies", "indexes") + viper.SetDefault("MetadataFormat", "toml") viper.SetDefault("DisableRSS", false) viper.SetDefault("ContentDir", "content") viper.SetDefault("LayoutDir", "layouts") viper.SetDefault("StaticDir", "static") + viper.SetDefault("ArchetypeDir", "archetypes") viper.SetDefault("PublishDir", "public") viper.SetDefault("DefaultLayout", "post") viper.SetDefault("BuildDrafts", false) diff --git a/commands/new.go b/commands/new.go new file mode 100644 index 000000000..6fa66396e --- /dev/null +++ b/commands/new.go @@ -0,0 +1,86 @@ +// 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" + "strings" + + "github.com/spf13/cobra" + "github.com/spf13/hugo/create" + "github.com/spf13/hugo/helpers" + jww "github.com/spf13/jwalterweatherman" +) + +var siteType string +var configFormat string +var contentType string +var contentFormat string +var contentFrontMatter string + +func init() { + //newSiteCmd.Flags().StringVarP(&siteType, "type", "t", "blog", "What type of site to new") + newSiteCmd.Flags().StringVarP(&configFormat, "format", "f", "yaml", "Config file format") + newCmd.Flags().StringVarP(&contentType, "kind", "k", "", "Content type to create") + newCmd.AddCommand(newSiteCmd) +} + +var newCmd = &cobra.Command{ + Use: "new [path]", + Short: "Create new content for your site", + Long: `Create will create a new content file and automatically set the date and title. +It will guess which kind of file to create based on the path provided. +You can also specify the kind with -k KIND +If archetypes are provided in your theme or site, they will be used. +`, + Run: NewContent, +} + +func NewContent(cmd *cobra.Command, args []string) { + InitializeConfig() + + if len(args) < 1 { + jww.FATAL.Fatalln("path needs to be provided") + } + + createpath := args[0] + + var kind string + + // assume the first directory is the section (kind) + if strings.Contains(createpath[1:], "/") { + kind = helpers.GuessSection(createpath) + } + + if contentType != "" { + kind = contentType + } + + err := create.NewContent(kind, createpath) + if err != nil { + jww.ERROR.Println(err) + } +} + +var newSiteCmd = &cobra.Command{ + Use: "site [type]", + Short: "Create a new site of [type]", + Long: `Create a new site as a (blog, project, etc)`, + Run: NewSite, +} + +func NewSite(cmd *cobra.Command, args []string) { + InitializeConfig() + + fmt.Println("new site called") + fmt.Println(args) +} diff --git a/create/content.go b/create/content.go new file mode 100644 index 000000000..1f198b5c6 --- /dev/null +++ b/create/content.go @@ -0,0 +1,128 @@ +// Copyright © 2014 Steve Francia . +// +// 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 create + +import ( + "bytes" + "io/ioutil" + "os" + "path" + "strings" + "time" + + "github.com/spf13/cast" + "github.com/spf13/hugo/helpers" + "github.com/spf13/hugo/hugolib" + "github.com/spf13/hugo/parser" + jww "github.com/spf13/jwalterweatherman" + "github.com/spf13/viper" +) + +func NewContent(kind, name string) (err error) { + jww.INFO.Println("attempting to create", name, "of", kind) + + location := FindArchetype(kind) + + var by []byte + + if location != "" { + by, err = ioutil.ReadFile(location) + if err != nil { + jww.ERROR.Println(err) + } + } + if location == "" || err != nil { + by = []byte("+++\n title = \"title\"\n draft = true \n+++\n") + } + + psr, err := parser.ReadFrom(bytes.NewReader(by)) + if err != nil { + return err + } + metadata, err := psr.Metadata() + if err != nil { + return err + } + newmetadata, err := cast.ToStringMapE(metadata) + if err != nil { + return err + } + + for k, _ := range newmetadata { + switch strings.ToLower(k) { + case "date": + newmetadata[k] = time.Now() + case "title": + newmetadata[k] = helpers.MakeTitle(helpers.Filename(name)) + } + } + + caseimatch := func(m map[string]interface{}, key string) bool { + for k, _ := range m { + if strings.ToLower(k) == strings.ToLower(key) { + return true + } + } + return false + } + + if !caseimatch(newmetadata, "date") { + newmetadata["date"] = time.Now() + } + + if !caseimatch(newmetadata, "title") { + newmetadata["title"] = helpers.MakeTitle(helpers.Filename(name)) + } + + page, err := hugolib.NewPage(name) + if err != nil { + return err + } + + page.Dir = viper.GetString("sourceDir") + page.SetSourceMetaData(newmetadata, parser.FormatToLeadRune(viper.GetString("MetaDataFormat"))) + + if err = page.SafeSaveSourceAs(path.Join(viper.GetString("contentDir"), name)); err != nil { + return + } + jww.FEEDBACK.Println(helpers.AbsPathify(path.Join(viper.GetString("contentDir"), name)), "created") + + return nil +} + +func FindArchetype(kind string) (outpath string) { + search := []string{helpers.AbsPathify(viper.GetString("archetypeDir"))} + + if viper.GetString("theme") != "" { + themeDir := path.Join(helpers.AbsPathify("themes/"+viper.GetString("theme")), "/archetypes/") + if _, err := os.Stat(themeDir); os.IsNotExist(err) { + jww.ERROR.Println("Unable to find archetypes directory for theme :", viper.GetString("theme"), "in", themeDir) + } else { + search = append(search, themeDir) + } + } + + for _, x := range search { + pathsToCheck := []string{kind + ".md", kind, "default.md", "default"} + for _, p := range pathsToCheck { + curpath := path.Join(x, p) + jww.DEBUG.Println("checking", curpath, "for archetypes") + if exists, _ := helpers.Exists(curpath); exists { + return curpath + } + } + } + + return "" +}