ansi_writer.go 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. // +build windows
  2. package windowsconsole
  3. import (
  4. "io"
  5. "os"
  6. ansiterm "github.com/Azure/go-ansiterm"
  7. "github.com/Azure/go-ansiterm/winterm"
  8. )
  9. // ansiWriter wraps a standard output file (e.g., os.Stdout) providing ANSI sequence translation.
  10. type ansiWriter struct {
  11. file *os.File
  12. fd uintptr
  13. infoReset *winterm.CONSOLE_SCREEN_BUFFER_INFO
  14. command []byte
  15. escapeSequence []byte
  16. inAnsiSequence bool
  17. parser *ansiterm.AnsiParser
  18. }
  19. // NewAnsiWriter returns an io.Writer that provides VT100 terminal emulation on top of a
  20. // Windows console output handle.
  21. func NewAnsiWriter(nFile int) io.Writer {
  22. initLogger()
  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. logger.Infof("newAnsiWriter: parser %p", parser)
  30. aw := &ansiWriter{
  31. file: file,
  32. fd: fd,
  33. infoReset: info,
  34. command: make([]byte, 0, ansiterm.ANSI_MAX_CMD_LENGTH),
  35. escapeSequence: []byte(ansiterm.KEY_ESC_CSI),
  36. parser: parser,
  37. }
  38. logger.Infof("newAnsiWriter: aw.parser %p", aw.parser)
  39. logger.Infof("newAnsiWriter: %v", aw)
  40. return aw
  41. }
  42. func (aw *ansiWriter) Fd() uintptr {
  43. return aw.fd
  44. }
  45. // Write writes len(p) bytes from p to the underlying data stream.
  46. func (aw *ansiWriter) Write(p []byte) (total int, err error) {
  47. if len(p) == 0 {
  48. return 0, nil
  49. }
  50. logger.Infof("Write: % x", p)
  51. logger.Infof("Write: %s", string(p))
  52. return aw.parser.Parse(p)
  53. }