package main import ( "fmt" "os" "os/exec" "path/filepath" "strings" "github.com/cheat/cheat/internal/cheatpath" "github.com/cheat/cheat/internal/config" "github.com/cheat/cheat/internal/sheets" ) // cmdEdit opens a cheatsheet for editing (or creates it if it doesn't exist). func cmdEdit(opts map[string]interface{}, conf config.Config) { cheatsheet := opts["--edit"].(string) // load the cheatsheets cheatsheets, err := sheets.Load(conf.Cheatpaths) if err != nil { fmt.Fprintf(os.Stderr, "failed to list cheatsheets: %v\n", err) os.Exit(1) } // filter cheatcheats by tag if --tag was provided if opts["--tag"] != nil { cheatsheets = sheets.Filter( cheatsheets, strings.Split(opts["--tag"].(string), ","), ) } // consolidate the cheatsheets found on all paths into a single map of // `title` => `sheet` (ie, allow more local cheatsheets to override less // local cheatsheets) consolidated := sheets.Consolidate(cheatsheets) // the file path of the sheet to edit var editpath string // determine if the sheet exists sheet, ok := consolidated[cheatsheet] // if the sheet exists and is not read-only, edit it in place if ok && !sheet.ReadOnly { editpath = sheet.Path // if the sheet exists but is read-only, copy it before editing } else if ok && sheet.ReadOnly { // compute the new edit path // begin by getting a writeable cheatpath writepath, err := cheatpath.Writeable(conf.Cheatpaths) if err != nil { fmt.Fprintf(os.Stderr, "failed to get writeable path: %v\n", err) os.Exit(1) } // compute the new edit path editpath = filepath.Join(writepath.Path, sheet.Title) // create any necessary subdirectories dirs := filepath.Dir(editpath) if dirs != "." { if err := os.MkdirAll(dirs, 0755); err != nil { fmt.Fprintf(os.Stderr, "failed to create directory: %s, %v\n", dirs, err) os.Exit(1) } } // copy the sheet to the new edit path err = sheet.Copy(editpath) if err != nil { fmt.Fprintf(os.Stderr, "failed to copy cheatsheet: %v\n", err) os.Exit(1) } // if the sheet does not exist, create it } else { // compute the new edit path // begin by getting a writeable cheatpath writepath, err := cheatpath.Writeable(conf.Cheatpaths) if err != nil { fmt.Fprintf(os.Stderr, "failed to get writeable path: %v\n", err) os.Exit(1) } // compute the new edit path editpath = filepath.Join(writepath.Path, cheatsheet) // create any necessary subdirectories dirs := filepath.Dir(editpath) if dirs != "." { if err := os.MkdirAll(dirs, 0755); err != nil { fmt.Fprintf(os.Stderr, "failed to create directory: %s, %v\n", dirs, err) os.Exit(1) } } } // split `conf.Editor` into parts to separate the editor's executable from // any arguments it may have been passed. If this is not done, the nearby // call to `exec.Command` will fail. parts := strings.Fields(conf.Editor) editor := parts[0] args := append(parts[1:], editpath) // edit the cheatsheet cmd := exec.Command(editor, args...) cmd.Stdout = os.Stdout cmd.Stdin = os.Stdin cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { fmt.Fprintf(os.Stderr, "failed to edit cheatsheet: %v\n", err) os.Exit(1) } }