ansi_writer.go 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. //go:build windows
  2. // +build windows
  3. package windowsconsole
  4. import (
  5. "io"
  6. "os"
  7. ansiterm "github.com/Azure/go-ansiterm"
  8. "github.com/Azure/go-ansiterm/winterm"
  9. )
  10. // ansiWriter wraps a standard output file (e.g., os.Stdout) providing ANSI sequence translation.
  11. type ansiWriter struct {
  12. file *os.File
  13. fd uintptr
  14. infoReset *winterm.CONSOLE_SCREEN_BUFFER_INFO
  15. command []byte
  16. escapeSequence []byte
  17. inAnsiSequence bool
  18. parser *ansiterm.AnsiParser
  19. }
  20. // NewAnsiWriter returns an io.Writer that provides VT100 terminal emulation on top of a
  21. // Windows console output handle.
  22. func NewAnsiWriter(nFile int) io.Writer {
  23. file, fd := winterm.GetStdFile(nFile)
  24. info, err := winterm.GetConsoleScreenBufferInfo(fd)
  25. if err != nil {
  26. return nil
  27. }
  28. parser := ansiterm.CreateParser("Ground", winterm.CreateWinEventHandler(fd, file))
  29. return &ansiWriter{
  30. file: file,
  31. fd: fd,
  32. infoReset: info,
  33. command: make([]byte, 0, ansiterm.ANSI_MAX_CMD_LENGTH),
  34. escapeSequence: []byte(ansiterm.KEY_ESC_CSI),
  35. parser: parser,
  36. }
  37. }
  38. func (aw *ansiWriter) Fd() uintptr {
  39. return aw.fd
  40. }
  41. // Write writes len(p) bytes from p to the underlying data stream.
  42. func (aw *ansiWriter) Write(p []byte) (total int, err error) {
  43. if len(p) == 0 {
  44. return 0, nil
  45. }
  46. return aw.parser.Parse(p)
  47. }