diff --git a/cmd/cheat/cmd_init.go b/cmd/cheat/cmd_init.go index 47bdde7..e5fa5d2 100644 --- a/cmd/cheat/cmd_init.go +++ b/cmd/cheat/cmd_init.go @@ -44,13 +44,23 @@ func cmdInit() { confpath := confpaths[0] confdir := filepath.Dir(confpath) - // create paths for community and personal cheatsheets + // create paths for community, personal, and work cheatsheets community := filepath.Join(confdir, "cheatsheets", "community") personal := filepath.Join(confdir, "cheatsheets", "personal") + work := filepath.Join(confdir, "cheatsheets", "work") // template the above paths into the default configs configs = strings.Replace(configs, "COMMUNITY_PATH", community, -1) configs = strings.Replace(configs, "PERSONAL_PATH", personal, -1) + configs = strings.Replace(configs, "WORK_PATH", work, -1) + + // locate and set a default pager + configs = strings.Replace(configs, "PAGER_PATH", config.Pager(), -1) + + // locate and set a default editor + if editor, err := config.Editor(); err == nil { + configs = strings.Replace(configs, "EDITOR_PATH", editor, -1) + } // output the templated configs fmt.Println(configs) diff --git a/internal/config/config.go b/internal/config/config.go index 18db880..fb8a08e 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -64,7 +64,8 @@ func New(_ map[string]interface{}, confPath string, resolve bool) (Config, error } // process cheatpaths - for i, cheatpath := range conf.Cheatpaths { + var validPaths []cp.Cheatpath + for _, cheatpath := range conf.Cheatpaths { // expand ~ in config paths expanded, err := homedir.Expand(cheatpath.Path) @@ -83,6 +84,14 @@ func New(_ map[string]interface{}, confPath string, resolve bool) (Config, error if resolve { evaled, err := filepath.EvalSymlinks(expanded) if err != nil { + // if the path simply doesn't exist, warn and skip it + if os.IsNotExist(err) { + fmt.Fprintf(os.Stderr, + "WARNING: cheatpath '%s' does not exist, skipping\n", + expanded, + ) + continue + } return Config{}, fmt.Errorf( "failed to resolve symlink: %s: %v", expanded, @@ -93,8 +102,10 @@ func New(_ map[string]interface{}, confPath string, resolve bool) (Config, error expanded = evaled } - conf.Cheatpaths[i].Path = expanded + cheatpath.Path = expanded + validPaths = append(validPaths, cheatpath) } + conf.Cheatpaths = validPaths // trim editor whitespace conf.Editor = strings.TrimSpace(conf.Editor) diff --git a/internal/config/config_extended_test.go b/internal/config/config_extended_test.go index ef09da0..96f1322 100644 --- a/internal/config/config_extended_test.go +++ b/internal/config/config_extended_test.go @@ -189,10 +189,14 @@ cheatpaths: t.Fatalf("failed to write config: %v", err) } - // Load config with symlink resolution should fail - _, err = New(map[string]interface{}{}, configFile, true) - if err == nil { - t.Error("expected error for broken symlink, got nil") + // Load config with symlink resolution should skip the broken cheatpath + // (warn to stderr) rather than hard-error + conf, err := New(map[string]interface{}{}, configFile, true) + if err != nil { + t.Errorf("expected no error for broken symlink (should skip), got: %v", err) + } + if len(conf.Cheatpaths) != 0 { + t.Errorf("expected broken cheatpath to be filtered out, got %d cheatpaths", len(conf.Cheatpaths)) } } diff --git a/internal/installer/run.go b/internal/installer/run.go index 19f9126..64d0062 100644 --- a/internal/installer/run.go +++ b/internal/installer/run.go @@ -17,13 +17,15 @@ func Run(configs string, confpath string) error { // cheatsheets based on the user's platform confdir := filepath.Dir(confpath) - // create paths for community and personal cheatsheets + // create paths for community, personal, and work cheatsheets community := filepath.Join(confdir, "cheatsheets", "community") personal := filepath.Join(confdir, "cheatsheets", "personal") + work := filepath.Join(confdir, "cheatsheets", "work") // set default cheatpaths configs = strings.Replace(configs, "COMMUNITY_PATH", community, -1) configs = strings.Replace(configs, "PERSONAL_PATH", personal, -1) + configs = strings.Replace(configs, "WORK_PATH", work, -1) // locate and set a default pager configs = strings.Replace(configs, "PAGER_PATH", config.Pager(), -1) @@ -44,15 +46,29 @@ func Run(configs string, confpath string) error { // clone the community cheatsheets if so instructed if yes { - // clone the community cheatsheets fmt.Printf("Cloning community cheatsheets to %s.\n", community) if err := repo.Clone(community); err != nil { return fmt.Errorf("failed to clone cheatsheets: %v", err) } + } else { + // comment out the community cheatpath in the config since + // the directory won't exist + configs = strings.Replace(configs, + " - name: community\n"+ + " path: "+community+"\n"+ + " tags: [ community ]\n"+ + " readonly: true", + " #- name: community\n"+ + " # path: "+community+"\n"+ + " # tags: [ community ]\n"+ + " # readonly: true", + -1, + ) + } - // also create a directory for personal cheatsheets - fmt.Printf("Cloning personal cheatsheets to %s.\n", personal) - if err := os.MkdirAll(personal, os.ModePerm); err != nil { + // always create personal and work directories + for _, dir := range []string{personal, work} { + if err := os.MkdirAll(dir, os.ModePerm); err != nil { return fmt.Errorf("failed to create directory: %v", err) } } diff --git a/internal/installer/run_test.go b/internal/installer/run_test.go index 9cbf688..ef32469 100644 --- a/internal/installer/run_test.go +++ b/internal/installer/run_test.go @@ -54,8 +54,8 @@ cheatpaths: confpath: filepath.Join(tempDir, "conf1", "conf.yml"), userInput: "n\n", wantErr: false, - checkFiles: []string{"conf1/conf.yml"}, - dontWantFiles: []string{"conf1/cheatsheets/community", "conf1/cheatsheets/personal"}, + checkFiles: []string{"conf1/conf.yml", "conf1/cheatsheets/personal", "conf1/cheatsheets/work"}, + dontWantFiles: []string{"conf1/cheatsheets/community"}, }, { name: "user accepts but clone fails", @@ -177,10 +177,18 @@ func TestRunStringReplacements(t *testing.T) { editor: EDITOR_PATH pager: PAGER_PATH cheatpaths: - - name: community - path: COMMUNITY_PATH - name: personal path: PERSONAL_PATH + tags: [ personal ] + readonly: false + - name: work + path: WORK_PATH + tags: [ work ] + readonly: false + - name: community + path: COMMUNITY_PATH + tags: [ community ] + readonly: true ` // Create temp directory @@ -194,7 +202,6 @@ cheatpaths: confdir := filepath.Dir(confpath) // Expected paths - expectedCommunity := filepath.Join(confdir, "cheatsheets", "community") expectedPersonal := filepath.Join(confdir, "cheatsheets", "personal") // Save original stdin/stdout @@ -244,10 +251,16 @@ cheatpaths: if strings.Contains(contentStr, "PAGER_PATH") && !strings.Contains(contentStr, fmt.Sprintf("pager: %s", "")) { t.Error("PAGER_PATH was not replaced") } + if strings.Contains(contentStr, "WORK_PATH") { + t.Error("WORK_PATH was not replaced") + } - // Verify correct paths were used - if !strings.Contains(contentStr, expectedCommunity) { - t.Errorf("expected community path %q in config", expectedCommunity) + // Verify community path is commented out (user declined) + if strings.Contains(contentStr, " - name: community") { + t.Error("expected community cheatpath to be commented out when declined") + } + if !strings.Contains(contentStr, " #- name: community") { + t.Error("expected commented-out community cheatpath") } if !strings.Contains(contentStr, expectedPersonal) { t.Errorf("expected personal path %q in config", expectedPersonal)