Modify add to parse stdin

This commit is contained in:
Miguel de la Cruz 2020-02-29 17:45:53 +01:00
parent 41b8e5db55
commit b38a0ff437
3 changed files with 42 additions and 67 deletions

View file

@ -41,7 +41,7 @@ Use "campaigner [command] --help" for more information about a command.
## Roadmap
- [ ] Modify the add command to only act on `stdin`, using the
- [x] Modify the add command to only act on `stdin`, using the
`--grep` and `--govet` flags to distinguish how to parse the
input.
- [ ] Add `--ag` to the `add` command.

View file

@ -1,8 +1,9 @@
package cmd
import (
"bufio"
"fmt"
"os/exec"
"os"
"strconv"
"strings"
@ -12,28 +13,29 @@ import (
"git.ctrlz.es/mgdelacroix/campaigner/model"
)
const defaultGrepOpts = "-nrFI"
func AddCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "add",
Short: "Adds tickets to the campaign",
Short: "Adds tickets to the campaign from the output of grep/ag/govet",
Long: `Generates tickets for the campaign reading from the standard input the output of one of the following three commands:
- grep (should be run with the -n flag)
- ag
- govet (should be run with the -json flag)`,
Example: ` grep -nriIF --include \*.go cobra.Command | campaigner add --grep
ag cobra.Command | campaigner add --ag
govet -json ./... | campaigner add --govet`,
Args: cobra.NoArgs,
Run: addCmdF,
RunE: addCmdF,
}
cmd.Flags().StringP("dir", "d", "", "directory containing the source code")
_ = cmd.MarkFlagRequired("dir")
cmd.Flags().StringSliceP("grep", "g", []string{}, "runs a grep command to generate the tickets")
cmd.Flags().BoolP("case-insensitive", "i", false, "makes the search case insensitive")
cmd.Flags().StringSliceP("ext", "e", []string{}, "limits the grep to files with certain extensions")
// cmd.Flags().StringP("govet", "v", "", "runs a govet command to generate the tickets")
// govet bin path?
cmd.Flags().BoolP("ag", "a", false, "generates the tickets reading ag's output from stdin")
cmd.Flags().BoolP("grep", "g", false, "generates the tickets reading grep's output from stdin")
cmd.Flags().BoolP("govet", "v", false, "generates the tickets reading govet's output from stdin")
return cmd
}
func parseLine(line string) (*model.Ticket, error) {
func parseGrepLine(line string) (*model.Ticket, error) {
// ToDo: it would be great to be able to relate a line with its
// parent method, at least for JS and Golang
parts := strings.Split(line, ":")
@ -48,68 +50,40 @@ func parseLine(line string) (*model.Ticket, error) {
}
text := strings.Join(parts[2:], "")
return &model.Ticket{filename, lineNo, text}, nil
return &model.Ticket{
Filename: filename,
LineNo: lineNo,
Text: text,
}, nil
}
func RunGrep(dir, str string, exts []string, caseInsensitive bool) ([]*model.Ticket, error) {
opts := defaultGrepOpts
if caseInsensitive {
opts = opts + "i"
}
includes := []string{}
for _, ext := range exts {
if strings.HasPrefix(ext, ".") {
ext = ext[1:]
}
includes = append(includes, []string{"--include", "*." + ext}...)
}
args := append([]string{opts}, includes...)
args = append(args, str, dir)
out, err := exec.Command("grep", args...).Output()
if err != nil {
return nil, fmt.Errorf("execution of grep failed: %w", err)
}
func parseGrep() []*model.Ticket {
tickets := []*model.Ticket{}
for _, line := range strings.Split(string(out), "\n") {
// ToDo: get and check error
ticket, _ := parseLine(line)
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
ticket, _ := parseGrepLine(scanner.Text())
if ticket != nil {
tickets = append(tickets, ticket)
}
}
return tickets, nil
return tickets
}
func RunGreps(dir string, strs, exts []string, caseInsensitive bool) ([]*model.Ticket, error) {
tickets := []*model.Ticket{}
for _, str := range strs {
results, err := RunGrep(dir, str, exts, caseInsensitive)
if err != nil {
return nil, err
}
tickets = append(tickets, results...)
func addCmdF(cmd *cobra.Command, _ []string) error {
grep, _ := cmd.Flags().GetBool("grep")
ag, _ := cmd.Flags().GetBool("ag")
govet, _ := cmd.Flags().GetBool("govet")
if !grep && !ag && !govet {
return fmt.Errorf("one of --grep --ag --govet flags should be active")
}
tickets = model.RemoveDuplicateTickets(tickets)
fmt.Printf("%d matches found\n", len(tickets))
return tickets, nil
}
func addCmdF(cmd *cobra.Command, _ []string) {
dir, _ := cmd.Flags().GetString("dir")
grepStrs, _ := cmd.Flags().GetStringSlice("grep")
extStrs, _ := cmd.Flags().GetStringSlice("ext")
caseInsensitive, _ := cmd.Flags().GetBool("case-insensitive")
tickets, err := RunGreps(dir, grepStrs, extStrs, caseInsensitive)
if err != nil {
ErrorAndExit(cmd, err)
var tickets []*model.Ticket
switch {
case grep:
tickets = parseGrep()
default:
return fmt.Errorf("not implemented yet")
}
cmp, err := campaign.Read()
@ -123,4 +97,5 @@ func addCmdF(cmd *cobra.Command, _ []string) {
if err := campaign.Save(cmp); err != nil {
ErrorAndExit(cmd, err)
}
return nil
}

View file

@ -16,7 +16,7 @@ func InitCmd() *cobra.Command {
}
cmd.Flags().StringP("epic", "e", "", "the epic id to associate this campaign with")
cmd.MarkFlagRequired("epic")
_ = cmd.MarkFlagRequired("epic")
return cmd
}