Skip to content

Commit

Permalink
feat: carry config object to template to enable dynamic word wrap
Browse files Browse the repository at this point in the history
⚠️BREAKING CHANGES:
- `.Metadata.title` replaced with `.Info.RecipeName`.
- `.Metadata.ImageName` replaced with `.Info.ImageFileName`.
- Removal of trailing whitespace from `cook.stepsSection`.
- Addition of double new lines to `cook.sourceSection`.

Other changes include:
- Addition of `word-wrap` option to dynamically specify the word wrap length.
- Addition of `.Info.ImageFilePath`, `.Info.NewRecipeFilePath`, and
  `.Info.RecipeFilePath` to template.
- Addition of `.Config.*` to template.
- Addition of config file aliases. E.g. `--word-wrap 80` from the command
  line can be used as `wordWrap: 80` in the config file.
  • Loading branch information
nicholaswilde committed Jul 19, 2022
1 parent da4899e commit b952e80
Show file tree
Hide file tree
Showing 11 changed files with 351 additions and 364 deletions.
1 change: 1 addition & 0 deletions cmd/cook-docs/command_line.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ func newCookDocsCommand(run func(cmd *cobra.Command, args []string)) (*cobra.Com
viper.AutomaticEnv()
viper.SetEnvPrefix("COOK_DOCS")
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
viper.RegisterAlias("wordWrap", "word-wrap")
viper.RegisterAlias("dryRun", "dry-run")
viper.RegisterAlias("ignoreFile", "ignore-file")
viper.RegisterAlias("recipeSearchRoot", "recipe-search-root")
Expand Down
188 changes: 89 additions & 99 deletions cmd/cook-docs/main.go
Original file line number Diff line number Diff line change
@@ -1,99 +1,89 @@
package main

import (
"os"
"path"
"strings"
"sync"

"github.com/aquilax/cooklang-go"
"github.com/nicholaswilde/cook-docs/pkg/cook"
"github.com/nicholaswilde/cook-docs/pkg/document"
"github.com/nicholaswilde/cook-docs/pkg/types"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

func retrieveInfoAndPrintDocumentation(recipeSearchRoot string, recipePath string, templateFiles []string, waitGroup *sync.WaitGroup, config *types.Config) {
defer waitGroup.Done()

recipeInfo := cook.ParseRecipeInformation(recipePath)
_, _ = cook.ParseFile(recipePath, config)
recipeData, err := cooklang.ParseFile(recipeInfo.RecipePath)

if err != nil {
log.Warnf("Error parsing file for recipe %s, skipping: %s", recipeInfo.RecipePath, err)
return
}

recipeData = cook.MergeRecipeData(recipeInfo, recipeData)

document.PrintDocumentation(recipeSearchRoot, recipeData, recipeInfo, templateFiles, config)
}

func GetFullSearchRoot(searchRoot string) (string, error) {
var fullSearchRoot string
if path.IsAbs(searchRoot) {
fullSearchRoot = searchRoot
} else {
cwd, err := os.Getwd()
if err != nil {
return "", err
}
fullSearchRoot = path.Join(cwd, searchRoot)
}
return fullSearchRoot, nil
}

func cookDocs(_ *cobra.Command, _ []string) {
var config types.Config
viper.Unmarshal(&config)
log.Println(config)

initializeCli(&config)

recipeSearchRoot := config.RecipeSearchRoot

fullSearchRoot, err := GetFullSearchRoot(recipeSearchRoot)
if err != nil {
log.Warnf("Error getting working directory: %s", err)
return
}

recipePaths, err := cook.FindRecipePaths(fullSearchRoot)
if err != nil {
log.Errorf("Error finding recipe paths: %s", err)
os.Exit(1)
}
log.Infof("Found recipes [%s]", strings.Join(recipePaths, ", "))

templateFiles := config.TemplateFiles
log.Debugf("Rendering from optional template files [%s]", strings.Join(templateFiles, ", "))

waitGroup := sync.WaitGroup{}

for _, r := range recipePaths {
waitGroup.Add(1)

// On dry runs all output goes to stdout, and so as to not jumble things, generate serially
if config.DryRun {
retrieveInfoAndPrintDocumentation(fullSearchRoot, r, templateFiles, &waitGroup, &config)
} else {
go retrieveInfoAndPrintDocumentation(fullSearchRoot, r, templateFiles, &waitGroup, &config)
}
}
waitGroup.Wait()
}

func main() {
command, err := newCookDocsCommand(cookDocs)
if err != nil {
log.Errorf("Failed to create the CLI commander: %s", err)
os.Exit(1)
}
if err := command.Execute(); err != nil {
log.Errorf("Failed to start the CLI: %s", err)
os.Exit(1)
}
}
package main

import (
"os"
"path"
"strings"
"sync"

"github.com/nicholaswilde/cook-docs/pkg/cook"
"github.com/nicholaswilde/cook-docs/pkg/document"
"github.com/nicholaswilde/cook-docs/pkg/types"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

func retrieveInfoAndPrintDocumentation(recipePath string, waitGroup *sync.WaitGroup, config *types.Config) {
defer waitGroup.Done()

recipe, err := cook.ParseFile(recipePath, config)
if err != nil {
log.Warnf("Error parsing file for recipe %s, skipping: %s", recipePath, err)
return
}

document.PrintDocumentation(recipe)
}

func GetFullSearchRoot(searchRoot string) (string, error) {
var fullSearchRoot string
if path.IsAbs(searchRoot) {
fullSearchRoot = searchRoot
} else {
cwd, err := os.Getwd()
if err != nil {
return "", err
}
fullSearchRoot = path.Join(cwd, searchRoot)
}
return fullSearchRoot, nil
}

func cookDocs(_ *cobra.Command, _ []string) {
var config types.Config
viper.Unmarshal(&config)

initializeCli(&config)

fullSearchRoot, err := GetFullSearchRoot(config.RecipeSearchRoot)
if err != nil {
log.Warnf("Error getting working directory: %s", err)
return
}

recipePaths, err := cook.FindRecipeFilePaths(fullSearchRoot)
if err != nil {
log.Errorf("Error finding recipe paths: %s", err)
os.Exit(1)
}
log.Infof("Found recipes [%s]", strings.Join(recipePaths, ", "))

log.Debugf("Rendering from optional template files [%s]", strings.Join(config.TemplateFiles, ", "))

waitGroup := sync.WaitGroup{}

for _, r := range recipePaths {
waitGroup.Add(1)

// On dry runs all output goes to stdout, and so as to not jumble things, generate serially
if config.DryRun {
retrieveInfoAndPrintDocumentation(r, &waitGroup, &config)
} else {
go retrieveInfoAndPrintDocumentation(r, &waitGroup, &config)
}
}
waitGroup.Wait()
}

func main() {
command, err := newCookDocsCommand(cookDocs)
if err != nil {
log.Errorf("Failed to create the CLI commander: %s", err)
os.Exit(1)
}
if err := command.Execute(); err != nil {
log.Errorf("Failed to start the CLI: %s", err)
os.Exit(1)
}
}
35 changes: 20 additions & 15 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,23 @@

Here is a list of the current supported parameters:

| Command Line | Environmental Variable | Config File | Default | Description |
|---------------------------------|------------------------------|--------------------|--------------------|----------------------------------------------------------------------------------------------------|
| -d, --dry-run | COOK_DOCS_DRY_RUN | dry-run | false | don't actually render any markdown files just print to stdout passed |
| -h, --help | N/A | N/A | N/A | help for cook-docs |
| -i, --ignore-file string | COOK_DOCS_IGNORE_FILE | ignore-file | .cookdocsignore | filename to use as an ignore file to exclude recipe directories |
| -j, --jsonify | COOK_DOCS_JSONIFY | jsonify | false | parse the recipe and display it in json format |
| -l, --log-level string | COOK_DOCS_LOG_LEVEL | log-level | info | level of logs that should printed, one of (panic, fatal, error, warning, info, debug, trace) |
| -c, --recipe-search-root string | COOK_DOCS_RECIPE_SEARCH_ROOT | recipe-search-root | . | directory to search recursively within for recipes. |
| -t, --template-files strings | COOK_DOCS_TEMPLATE_FILES | template-files | [recipe.md.gotmpl] | gotemplate file paths relative to each recipe directory from which documentation will be generated |
| -v, --version | N/A | N/A | N/A | diplay the version of cook-docs |
| Command Line | Environmental Variable | Config File | Default | Description |
|---------------------------------|-------------------------------|-------------------|---------------------|-----------------------------------------------------------------------------------------------------|
| -d, --dry-run | COOK_DOCS_DRY_RUN | dryRun | false | don't actually render any markdown files just print to stdout passed |
| -h, --help | N/A | N/A | N/A | help for cook-docs |
| -i, --ignore-file string | COOK_DOCS_IGNORE_FILE | ignoreFile | .cookdocsignore | filename to use as an ignore file to exclude recipe directories |
| -j, --jsonify | COOK_DOCS_JSONIFY | jsonify | false | parse the recipe and display it in json format |
| -l, --log-level string | COOK_DOCS_LOG_LEVEL | logLevel | info | level of logs that should printed, one of (panic, fatal, error, warning, info, debug, trace) |
| -c, --recipe-search-root string | COOK_DOCS_RECIPE_SEARCH_ROOT | recipeSearchRoot | . | directory to search recursively within for recipes. |
| -t, --template-files strings | COOK_DOCS_TEMPLATE_FILES | templateFiles | [recipe.md.gotmpl] | gotemplate file paths relative to each recipe directory from which documentation will be generated |
| -w, --word-wrap int | COOK_DOCS_WORD_WRAP | wordWrap | 120 | word wrap line length for recipe steps section |
| -v, --version | N/A | N/A | N/A | diplay the version of cook-docs |

## Config Files

Configuration files may be used to set the default app settings.

The config file name is `.cookdocs.yaml` or `.cookdocs.yml` and can be located in
The config file name is `.cookdocs`, `.cookdocs.yaml` or `.cookdocs.yml` and can be located in
any of the following locations:

- `/etc/cook-docs/`
Expand All @@ -28,14 +29,18 @@ any of the following locations:

```yaml title=".cookdocs.yaml"
---
dry-run: false
ignore-file: .cookdocsignore
dryRun: false
ignoreFile: .cookdocsignore
jsonify: false
log-level: info
template-files:
logLevel: info
templateFiles:
- recipe.md.gotmpl
wordWrap: 120
```
!!! note
The variables in the config file can be both in the `Command Line` or `Config File` format. E.g. `dry-run` and `dryRun`.

## Environmental Variables

Environmental variables are also supported. They start with the prefix `COOK_DOCS_` and use
Expand Down
Loading

0 comments on commit b952e80

Please sign in to comment.