package main import ( "fmt" "os" "regexp" "strings" "github.com/cheat/cheat/internal/config" "github.com/cheat/cheat/internal/display" "github.com/cheat/cheat/internal/sheets" ) // cmdSearch searches for strings in cheatsheets. func cmdSearch(opts map[string]interface{}, conf config.Config) { phrase := opts["--search"].(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), ","), ) } // iterate over each cheatpath out := "" for _, pathcheats := range cheatsheets { // sort the cheatsheets alphabetically, and search for matches for _, sheet := range sheets.Sort(pathcheats) { // if was provided, constrain the search only to // matching cheatsheets if opts[""] != nil && sheet.Title != opts[""] { continue } // assume that we want to perform a case-insensitive search for pattern := "(?i)" + phrase // unless --regex is provided, in which case we pass the regex unaltered if opts["--regex"] == true { pattern = phrase } // compile the regex reg, err := regexp.Compile(pattern) if err != nil { fmt.Fprintf(os.Stderr, "failed to compile regexp: %s, %v\n", pattern, err) os.Exit(1) } // `Search` will return text entries that match the search terms. // We're using it here to overwrite the prior cheatsheet Text, // filtering it to only what is relevant. sheet.Text = sheet.Search(reg) // if the sheet did not match the search, ignore it and move on if sheet.Text == "" { continue } // if colorization was requested, apply it here if conf.Color(opts) { sheet.Colorize(conf) } // display the cheatsheet body out += fmt.Sprintf( "%s %s\n%s\n", // append the cheatsheet title sheet.Title, // append the cheatsheet path display.Faint(fmt.Sprintf("(%s)", sheet.CheatPath), conf), // indent each line of content display.Indent(sheet.Text), ) } } // trim superfluous newlines out = strings.TrimSpace(out) // display the output // NB: resist the temptation to call `display.Write` multiple times in the // loop above. That will not play nicely with the paginator. display.Write(out, conf) }