template / commit
A few changes:
README.md | 41 +++++++++++++++++----------------- config_test.go | 16 +++++++++++--- profile.go | 69 +++++++++++++++++++++++++++++----------------------------- utils.go | 10 +++++++++ 4 files changed, 77 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index aeb9ff8..b6e09c9 100644 --- a/README.md +++ b/README.md @@ -20,11 +20,22 @@ Please keep in mind that since my focus is on the CLI, CLI bugs and features wil This is one of the profiles that comes with the tool. ```yaml - - file: + - name: daily + description: Creates a MD file in ~/DailyNotes folder in the format YYYY-MM-DD[-vX].md + isdefault: false + type: file + path: ~/DailyNotes + namepatterns: + - '{{.Year}}-{{.Month}}-{{.Day}}.md' + scriptshell: pwsh + runpostscriptonfailure: true + postscripts: + - code . {{ if .FullPath }}"{{.FullPath}}"{{else}}(gci . | select -last 1){{ end }} + file: template: |- - # {{.Year}}-{{.Month}}-{{.Day}} + # {{.FileNameWithoutExtension}} - Today's notes + Today's notes for {{.Year}}-{{.Month}}-{{.Day}}. ## Todo @@ -34,29 +45,17 @@ This is one of the profiles that comes with the tool. 4. Check yesterday's notes 5. Have fun! 6. ADD MORE ITEMS HERE - isdefault: false - name: daily - description: Creates a MD file in ~/DailyNotes folder in the format YYYY-MM-DD[-vX].md - path: ~/DailyNotes - type: file - namepatterns: - - '{{.Year}}-{{.Month}}-{{.Day}}.md' - postscripts: - - code . "{{.Path}}" - scriptshell: pwsh - os: "" - files: [] ``` Using the above configuration: ```pwsh -> template daily -Config loaded from 'C:\Users\fuzzy\.template.yaml' -args: &[daily] +> template daily Profile: daily -extras file ~/.template-extras.yaml does not exist, extras not being used -Creating file 'C:\Users\fuzzy\DailyNotes\2022-10-23.md' from template string -Executing post script: pwsh -c code . "C:\Users\fuzzy\DailyNotes\2022-10-23.md" +Project name: +Loaded config from /Users/fuzzy/.template.yaml +Creating file: /Users/fuzzy/DailyNotes/2022-11-02.md +Executing post script: pwsh -c code . "/Users/fuzzy/DailyNotes/2022-11-02.md" +Post script had no output ``` This will cause VSCode to open the `~\DailyNotes` folder as a workspace, and the newly-created file `2022-09-26.md` will be opened as well. diff --git a/config_test.go b/config_test.go index 01a7528..4163c89 100644 --- a/config_test.go +++ b/config_test.go @@ -8,6 +8,15 @@ import ( "github.com/stretchr/testify/assert" ) +// Compares YAML representation of two objects +func compareObjectYaml(t *testing.T, expected, actual interface{}) { + expectedYaml, err := getYaml(expected) + assert.Nil(t, err, "Error marshalling expected") + actualYaml, err := getYaml(actual) + assert.Nil(t, err, "Error marshalling actual") + assert.Equal(t, expectedYaml, actualYaml) +} + func TestSaveLoadConfig(t *testing.T) { config := defaultConfig() @@ -22,7 +31,7 @@ func TestSaveLoadConfig(t *testing.T) { assert.Nil(t, err, "Error loading config") // test config - assert.Equal(t, loadedConfig, config) + compareObjectYaml(t, loadedConfig, config) // test load non-existent config _, err = loadConfig("non-existent-file.yaml") @@ -50,9 +59,10 @@ func TestSaveLoadConfig(t *testing.T) { // create default config err = saveConfig(configPath, defaultConfig()) + assert.Nil(t, err, "Error saving config") // test config - assert.Equal(t, loadedConfig, config) + compareObjectYaml(t, loadedConfig, config) // verify config file exists stat1, err := os.Stat(configPath) @@ -63,7 +73,7 @@ func TestSaveLoadConfig(t *testing.T) { assert.Nil(t, err, "Error loading config") // test config - assert.Equal(t, loadedConfig, config) + compareObjectYaml(t, loadedConfig, config) // verify config file wasn't updated stat2, err := os.Stat(configPath) diff --git a/profile.go b/profile.go index 1a1ac07..55b70a4 100644 --- a/profile.go +++ b/profile.go @@ -10,7 +10,6 @@ import ( "strings" "time" - log "github.com/sirupsen/logrus" "golang.org/x/exp/slices" ) @@ -33,27 +32,27 @@ const ( type ParameterizedText string type File struct { - Template ParameterizedText + Template ParameterizedText `yaml:"template,omitempty"` } type FileInFolder struct { - File + File `yaml:"file,omitempty"` Name ParameterizedText } type Profile struct { - File - IsDefault bool Name string - Description string - Path string + Description string `yaml:"description,omitempty"` + IsDefault bool Type ProfileType + Path string `yaml:"path,omitempty"` + OS OSType `yaml:"os,omitempty"` NamePatterns []ParameterizedText - PostScripts []ParameterizedText - ScriptShell string - OS OSType - Files []FileInFolder - RunPostscriptOnFailure bool + ScriptShell string `yaml:"scriptshell,omitempty"` + Files []FileInFolder `yaml:"files,omitempty"` + RunPostscriptOnFailure bool `yaml:"runpostscriptonfailure,omitempty"` + PostScripts []ParameterizedText `yaml:"postscripts,omitempty"` + File `yaml:"file,omitempty"` } var forbiddenProfileNames = []string{ @@ -113,18 +112,14 @@ func processProfile(profile Profile, projectName string, extras map[string]strin now := time.Now() errors := []error{} newName, prePatternData, err := createNewNameForPatterns(now, projectName, profile.NamePatterns, extras, entities) - - if err != nil { - errors = append(errors, err) - if !profile.RunPostscriptOnFailure { - return errors - } - } + swallowPrePostScriptErrors := profile.RunPostscriptOnFailure && profile.PostScripts != nil && len(profile.PostScripts) > 0 // check newName is created if newName == "" { - errors = append(errors, fmt.Errorf("couldn't find a good new name")) - if !profile.RunPostscriptOnFailure { + if swallowPrePostScriptErrors { + fmt.Println("No new name was created, but will attempt to run post scripts") + } else { + errors = append(errors, fmt.Errorf("couldn't find a good new name")) return errors } } @@ -133,8 +128,10 @@ func processProfile(profile Profile, projectName string, extras map[string]strin if err == nil && newName != "" { fullPath, err = createEntity(now, profile, cwd, newName, projectName, extras, prePatternData) if err != nil { - errors = append(errors, fmt.Errorf("unable to create entity: %v", err)) - if !profile.RunPostscriptOnFailure { + if swallowPrePostScriptErrors { + fmt.Printf("Error creating entity, but will attempt to run post scripts: %v", err) + } else { + errors = append(errors, fmt.Errorf("unable to create entity: %v", err)) return errors } } @@ -150,14 +147,20 @@ func processProfile(profile Profile, projectName string, extras map[string]strin for _, postScript := range postScripts { allArgs := []string{"-c", postScript} shell := profile.ScriptShell + + var out bytes.Buffer fmt.Printf("Executing post script: %v %v\n", shell, strings.Join(allArgs, " ")) cmd := monkey.ExecCommand(shell, allArgs...) - var out bytes.Buffer cmd.Stdout = &out err := cmd.Run() - fmt.Printf("Post script output: %v", out.String()) + output := out.String() + if output != "" { + fmt.Printf("Post script output: %v\n", output) + } else { + fmt.Printf("Post script had no output\n") + } if err != nil { - // post scripts tend to fail (TODO: investigate why), so for now we'll just log the error + // post scripts can fail (TODO: investigate why), so for now we'll just log the error fmt.Printf("Error executing post script '%v': %v\n", fmt.Sprintf("%v %v", shell, strings.Trim(fmt.Sprint(allArgs), "[]")), err) @@ -179,10 +182,7 @@ func createEntity( profileType := profile.Type fullPath := filepath.Join(cwd, newName) if profileType == FolderType { - log.WithFields(log.Fields{ - "fullPath": fullPath, - "profileType": profileType, - }).Debug("Creating directory") + fmt.Printf("Creating folder: %v\n", fullPath) err := monkey.OSMkdir(fullPath, os.ModePerm) if err != nil { return "", fmt.Errorf("error creating directory: %v", err) @@ -194,16 +194,14 @@ func createEntity( // create files in the new folder if len(profile.Files) > 0 { - log.WithFields(log.Fields{ - "fullPath": fullPath, - "fileCount": len(profile.Files), - }).Debug("Creating files in directory") + fmt.Printf("Creating %v files in folder: %v\n", len(profile.Files), fullPath) for index, file := range profile.Files { fileName, filePrePatternData, err := createNewNameForPatterns(now, projectName, []ParameterizedText{file.Name}, extras, []string{}) if err != nil { return "", fmt.Errorf("error creating file name for file index %v : %v", index, err) } subFilePath := filepath.Join(fullPath, fileName) + fmt.Printf("Creating sub file: %v\n", subFilePath) err = createFile(filePrePatternData, file.File, subFilePath) if err != nil { return "", fmt.Errorf("error creating file %v: %v", subFilePath, err) @@ -211,12 +209,13 @@ func createEntity( } } } else if profileType == FileType { + fmt.Printf("Creating file: %v\n", fullPath) err := createFile(prePatternData, profile.File, fullPath) if err != nil { return "", err } } else { - log.Debug("Profile type is script, doing nothing during main phase") + fmt.Printf("Profile type is script, doing nothing during main phase\n") } return fullPath, nil } diff --git a/utils.go b/utils.go index 7a794bb..eb774fc 100644 --- a/utils.go +++ b/utils.go @@ -4,6 +4,8 @@ import ( "os/user" "path/filepath" "strings" + + "gopkg.in/yaml.v3" ) func getFullPath(path string, usr user.User) string { @@ -18,3 +20,11 @@ func getFullPath(path string, usr user.User) string { } return newPath } + +func getYaml(data interface{}) (string, error) { + yaml, err := yaml.Marshal(data) + if err != nil { + return "", err + } + return string(yaml), nil +}