tty_windows.go 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. //go:build windows
  2. // +build windows
  3. package tea
  4. import (
  5. "fmt"
  6. "os"
  7. "github.com/charmbracelet/x/term"
  8. "golang.org/x/sys/windows"
  9. )
  10. func (p *Program) initInput() (err error) {
  11. // Save stdin state and enable VT input
  12. // We also need to enable VT
  13. // input here.
  14. if f, ok := p.input.(term.File); ok && term.IsTerminal(f.Fd()) {
  15. p.ttyInput = f
  16. p.previousTtyInputState, err = term.MakeRaw(p.ttyInput.Fd())
  17. if err != nil {
  18. return err
  19. }
  20. // Enable VT input
  21. var mode uint32
  22. if err := windows.GetConsoleMode(windows.Handle(p.ttyInput.Fd()), &mode); err != nil {
  23. return fmt.Errorf("error getting console mode: %w", err)
  24. }
  25. if err := windows.SetConsoleMode(windows.Handle(p.ttyInput.Fd()), mode|windows.ENABLE_VIRTUAL_TERMINAL_INPUT); err != nil {
  26. return fmt.Errorf("error setting console mode: %w", err)
  27. }
  28. }
  29. // Save output screen buffer state and enable VT processing.
  30. if f, ok := p.output.(term.File); ok && term.IsTerminal(f.Fd()) {
  31. p.ttyOutput = f
  32. p.previousOutputState, err = term.GetState(f.Fd())
  33. if err != nil {
  34. return err
  35. }
  36. var mode uint32
  37. if err := windows.GetConsoleMode(windows.Handle(p.ttyOutput.Fd()), &mode); err != nil {
  38. return fmt.Errorf("error getting console mode: %w", err)
  39. }
  40. if err := windows.SetConsoleMode(windows.Handle(p.ttyOutput.Fd()), mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING); err != nil {
  41. return fmt.Errorf("error setting console mode: %w", err)
  42. }
  43. }
  44. return
  45. }
  46. // Open the Windows equivalent of a TTY.
  47. func openInputTTY() (*os.File, error) {
  48. f, err := os.OpenFile("CONIN$", os.O_RDWR, 0o644)
  49. if err != nil {
  50. return nil, err
  51. }
  52. return f, nil
  53. }