template / commit
Added `create` command, which creates a hard-coded profile from a file or directory.
.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",