github.com/kcmvp/gob@v1.0.17/cmd/gbc/artifact/multiple_writer.go (about) 1 package artifact 2 3 import ( 4 "bufio" 5 "fmt" 6 "os" 7 "os/exec" 8 "path/filepath" 9 "regexp" 10 "strings" 11 "time" 12 13 "github.com/fatih/color" 14 "github.com/samber/lo" 15 16 "github.com/creack/pty" 17 ) 18 19 type consoleFormatter func(msg string) string 20 21 func StreamCmdOutput(cmd *exec.Cmd, task string, formatter consoleFormatter) error { 22 // Start the command with a pty 23 var scanner *bufio.Scanner 24 if ptmx, err := pty.Start(cmd); err == nil { 25 scanner = bufio.NewScanner(ptmx) 26 defer ptmx.Close() 27 } else if rd, err := cmd.StdoutPipe(); err == nil { 28 scanner = bufio.NewScanner(rd) 29 } else { 30 return err 31 } 32 color.Green("start %s ......\n", task) 33 // Create a file to save the output 34 log, err := os.Create(filepath.Join(CurProject().Target(), fmt.Sprintf("%s.log", strings.ReplaceAll(task, " ", "_")))) 35 if err != nil { 36 return fmt.Errorf(color.RedString("Error creating file:", err)) 37 } 38 defer log.Close() 39 40 // Create a regular expression to match color escape sequences 41 colorRegex := regexp.MustCompile(`\x1b\[[0-9;]*m`) 42 // Goroutine to remove color escape sequences, print the colored output, and write the modified output to the file 43 ch := make(chan string) 44 eof := false 45 go func() { 46 for scanner.Scan() { 47 line := strings.TrimSpace(scanner.Text()) 48 if formatter != nil { 49 line = strings.TrimSpace(formatter(line)) 50 } 51 if len(line) > 1 { 52 ch <- line 53 } 54 } 55 eof = true 56 if err = scanner.Err(); err != nil { 57 fmt.Println("Error reading output:", err) 58 } 59 }() 60 ticker := time.NewTicker(150 * time.Millisecond) 61 overwrite := true 62 progress := NewProgress() 63 for !eof { 64 select { 65 case line := <-ch: 66 progress.Reset() 67 lineWithoutColor := colorRegex.ReplaceAllString(line, "") 68 _, err = log.WriteString(lineWithoutColor + "\n") 69 line = lo.IfF(overwrite, func() string { 70 overwrite = false 71 return fmt.Sprintf("\r%-15s", line) 72 }).Else(line) 73 fmt.Println(line) 74 if err != nil { 75 fmt.Println("Error writing to file:", err) 76 break 77 } 78 case <-ticker.C: 79 if !overwrite { 80 overwrite = true 81 } 82 _ = progress.Add(1) 83 } 84 } 85 _ = progress.Finish() 86 color.Green("\rfinished %s ......\n", task) 87 ticker.Stop() 88 return cmd.Wait() 89 }