fuzzyworld

template / commit

Added `create` command, which creates a hard-coded profile from a file or directory.

6962cd0b722ad232cf834120107aee6bdd91dca3 · Pavel Safronov · 2023-09-14 09:57:31 -0700 · parents 867871893693

Added `create` command, which creates a hard-coded profile from a file or directory.
The generated profile can then be copy-pasted into the global or the user profile, for customization/parameterization and testing.
 .vscode/launch.json |  12 ++++++
 file.go             |  11 +++++
 main.go             | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 140 insertions(+)

diff --git a/.vscode/launch.json b/.vscode/launch.json
index 882bd7c..9252761 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -40,6 +40,18 @@
                 "list",
             ]
         },
+        {
+            "name": "Run: template create -d /Users/pavel/code/advent/2020/day13",
+            "type": "go",
+            "request": "launch",
+            "mode": "auto",
+            "program": ".",
+            "args": [
+                "create",
+                "-d",
+                "/Users/pavel/code/advent/2020/day13"
+            ]
+        },
         {
             "name": "Run: template get work",
             "type": "go",
diff --git a/file.go b/file.go
index 1f1764b..3189f17 100644
--- a/file.go
+++ b/file.go
@@ -57,3 +57,14 @@ func createFile(
 	}
 	return nil
 }
+

+func readFile(

+	filePath string,

+) (string, error) {

+	file, err := os.ReadFile(filePath)

+	if err != nil {

+		return "", fmt.Errorf("error reading file %s: %w", filePath, err)

+	}

+	return string(file), nil

+}

+

diff --git a/main.go b/main.go
index 4d50cce..f6c9140 100644
--- a/main.go
+++ b/main.go
@@ -3,8 +3,11 @@ package main
 import (
 	"bufio"
 	"fmt"
+	"io/fs"
 	"os"
 	"os/user"
+	"path"
+	"path/filepath"
 	"strconv"
 	"strings"
 
@@ -141,6 +144,120 @@ func main() {
 					return nil
 				},
 			},
+			{
+				Name:  "create",
+				Usage: "create a fully-hardcoded template profile from a file or folder",
+				Flags: []cli.Flag{
+					&cli.StringFlag{
+						Name:        "dir",
+						Aliases:     []string{"d"},
+						Value:       "",
+						Usage:       "folder from which to create the template",
+						Destination: &argumentValues.dirTemplate,
+					},
+					&cli.StringFlag{
+						Name:        "file",
+						Aliases:     []string{"f"},
+						Value:       "",
+						Usage:       "file from which to create the template",
+						Destination: &argumentValues.fileTemplate,
+					},
+				},
+				Action: func(c *cli.Context) error {
+					// get args
+					c.Args()
+
+					filePath := argumentValues.fileTemplate
+					dirPath := argumentValues.dirTemplate
+					if filePath == "" && dirPath == "" {
+						return fmt.Errorf("file or dir not specified, use `file` or `dir` flag")
+					}
+
+					profileName := argumentValues.profile
+					if profileName == "" {
+						profileName = "temp"
+					}
+
+					sourcePath := filePath
+					profileType := FileType
+					if dirPath != "" {
+						profileType = FolderType
+						sourcePath = dirPath
+					}
+					profile := Profile{
+						Name:            profileName,
+						Description:     fmt.Sprintf("temp %s profile generated from %s", profileType, sourcePath),
+						Type:            profileType,
+						TargetDirectory: ".",
+					}
+
+					dir, file := path.Split(sourcePath)
+					profile.TargetDirectory = dir
+					profile.NamePatterns = []ParameterizedText{
+						ParameterizedText(file),
+					}
+					profile.PostScripts = []ParameterizedText{
+						ParameterizedText(fmt.Sprintf("code ./%s", file)),
+					}
+
+					if filePath != "" {
+						file, err := readFile(filePath)
+						if err != nil {
+							return fmt.Errorf("error reading file %s: %w", filePath, err)
+						}
+						template := ParameterizedText(file)
+						profile.FileTemplate = template
+					} else {
+						files := []FileInFolder{}
+						err := filepath.WalkDir(dirPath, func(path string, d fs.DirEntry, err error) error {
+							if err != nil {
+								fmt.Printf("prevent panic by handling failure accessing a path %q: %v\n", path, err)
+								return err
+							}
+
+							isRoot := path == dirPath
+							isDir := d.IsDir()
+							shouldSkip := isRoot || isDir
+							if shouldSkip {
+								return nil
+							}
+							relPath, err := filepath.Rel(dirPath, path)
+							if err != nil {
+								return fmt.Errorf("error getting relative path for %s: %w", path, err)
+							}
+							contents, err := readFile(path)
+							if err != nil {
+								return fmt.Errorf("error reading file %s: %w", path, err)
+							}
+							fif := FileInFolder{
+								Name:         ParameterizedText(relPath),
+								FileTemplate: ParameterizedText(contents),
+							}
+							files = append(files, fif)
+							return nil
+						})
+						if err != nil {
+							return fmt.Errorf("error walking dir %s: %w", dirPath, err)
+						}
+						profile.Files = files
+					}
+
+					config := Config{
+						Profiles: []Profile{profile},
+					}
+
+					writer := strings.Builder{}
+					encoder := yaml.NewEncoder(&writer)
+					err := encoder.Encode(config)
+					if err != nil {
+						return fmt.Errorf("error encoding config: %v", err)
+					}
+
+					yamlText := writer.String()
+					fmt.Println(yamlText)
+					return nil
+				},
+			},
 			{
 				Name:  "get",
 				Usage: "get a profile",