// disableNativeConsole turns off native console mode func disableNativeConsole(state *State) error { // Try and restore both in an out before error checking. errout := winterm.SetConsoleMode(uintptr(state.outHandle), state.outMode) errin := winterm.SetConsoleMode(uintptr(state.inHandle), state.inMode) if errout != nil { return errout } if errin != nil { return errin } return nil }
// enableNativeConsole turns on native console mode func enableNativeConsole(state State) error { if err := winterm.SetConsoleMode(uintptr(state.outHandle), state.outMode|enableVirtualTerminalProcessing); err != nil { return err } if err := winterm.SetConsoleMode(uintptr(state.inHandle), state.inMode|enableVirtualTerminalInput); err != nil { winterm.SetConsoleMode(uintptr(state.outHandle), state.outMode) // restore out if we can return err } return nil }
// probeNativeConsole probes the console to determine if native can be supported, func probeNativeConsole(state State) error { if err := winterm.SetConsoleMode(uintptr(state.outHandle), state.outMode|enableVirtualTerminalProcessing); err != nil { return err } defer winterm.SetConsoleMode(uintptr(state.outHandle), state.outMode) if err := winterm.SetConsoleMode(uintptr(state.inHandle), state.inMode|enableVirtualTerminalInput); err != nil { return err } defer winterm.SetConsoleMode(uintptr(state.inHandle), state.inMode) return nil }
// MakeRaw puts the terminal (Windows Console) connected to the given file descriptor into raw // mode and returns the previous state of the terminal so that it can be restored. func MakeRaw(fd uintptr) (*State, error) { state, err := SaveState(fd) if err != nil { return nil, err } // See // -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx // -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx mode := state.mode // Disable these modes mode &^= winterm.ENABLE_ECHO_INPUT mode &^= winterm.ENABLE_LINE_INPUT mode &^= winterm.ENABLE_MOUSE_INPUT mode &^= winterm.ENABLE_WINDOW_INPUT mode &^= winterm.ENABLE_PROCESSED_INPUT // Enable these modes mode |= winterm.ENABLE_EXTENDED_FLAGS mode |= winterm.ENABLE_INSERT_MODE mode |= winterm.ENABLE_QUICK_EDIT_MODE err = winterm.SetConsoleMode(fd, mode) if err != nil { return nil, err } return state, nil }
// enableNativeConsole turns on native console mode func enableNativeConsole(state State) error { // First attempt both enableVirtualTerminalProcessing and disableNewlineAutoReturn if err := winterm.SetConsoleMode(uintptr(state.outHandle), state.outMode|(enableVirtualTerminalProcessing|disableNewlineAutoReturn)); err != nil { // That may fail, so fallback to trying just enableVirtualTerminalProcessing if err := winterm.SetConsoleMode(uintptr(state.outHandle), state.outMode|enableVirtualTerminalProcessing); err != nil { return err } } if err := winterm.SetConsoleMode(uintptr(state.inHandle), state.inMode|enableVirtualTerminalInput); err != nil { winterm.SetConsoleMode(uintptr(state.outHandle), state.outMode) // restore out if we can return err } return nil }
// SetRawTerminalOutput puts the output of terminal connected to the given file // descriptor into raw mode. On UNIX, this does nothing and returns nil for the // state. On Windows, it disables LF -> CRLF translation. func SetRawTerminalOutput(fd uintptr) (*State, error) { state, err := SaveState(fd) if err != nil { return nil, err } // Ignore failures, since disableNewlineAutoReturn might not be supported on this // version of Windows. winterm.SetConsoleMode(fd, state.mode|disableNewlineAutoReturn) return state, err }
// DisableEcho disables echo for the terminal connected to the given file descriptor. // -- See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx func DisableEcho(fd uintptr, state *State) error { mode := state.inMode mode &^= winterm.ENABLE_ECHO_INPUT mode |= winterm.ENABLE_PROCESSED_INPUT | winterm.ENABLE_LINE_INPUT err := winterm.SetConsoleMode(fd, mode) if err != nil { return err } // Register an interrupt handler to catch and restore prior state restoreAtInterrupt(fd, state) return nil }
// RestoreTerminal restores the terminal connected to the given file descriptor // to a previous state. func RestoreTerminal(fd uintptr, state *State) error { return winterm.SetConsoleMode(fd, state.mode) }
// RestoreTerminal restores the terminal connected to the given file descriptor // to a previous state. func RestoreTerminal(fd uintptr, state *State) error { if usingNativeConsole { return disableNativeConsole(state) } return winterm.SetConsoleMode(fd, state.outMode) }
// StdStreams returns the standard streams (stdin, stdout, stedrr). func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) { // Turn on VT handling on all std handles, if possible. This might // fail, in which case we will fall back to terminal emulation. var emulateStdin, emulateStdout, emulateStderr bool fd := os.Stdin.Fd() if mode, err := winterm.GetConsoleMode(fd); err == nil { // Validate that enableVirtualTerminalInput is supported, but do not set it. if err = winterm.SetConsoleMode(fd, mode|enableVirtualTerminalInput); err != nil { emulateStdin = true } else { vtInputSupported = true } // Unconditionally set the console mode back even on failure because SetConsoleMode // remembers invalid bits on input handles. winterm.SetConsoleMode(fd, mode) } fd = os.Stdout.Fd() if mode, err := winterm.GetConsoleMode(fd); err == nil { // Validate disableNewlineAutoReturn is supported, but do not set it. if err = winterm.SetConsoleMode(fd, mode|enableVirtualTerminalProcessing|disableNewlineAutoReturn); err != nil { emulateStdout = true } else { winterm.SetConsoleMode(fd, mode|enableVirtualTerminalProcessing) } } fd = os.Stderr.Fd() if mode, err := winterm.GetConsoleMode(fd); err == nil { // Validate disableNewlineAutoReturn is supported, but do not set it. if err = winterm.SetConsoleMode(fd, mode|enableVirtualTerminalProcessing|disableNewlineAutoReturn); err != nil { emulateStderr = true } else { winterm.SetConsoleMode(fd, mode|enableVirtualTerminalProcessing) } } if os.Getenv("ConEmuANSI") == "ON" { // The ConEmu terminal emulates ANSI on output streams well. emulateStdin = true emulateStdout = false emulateStderr = false } if emulateStdin { stdIn = windows.NewAnsiReader(syscall.STD_INPUT_HANDLE) } else { stdIn = os.Stdin } if emulateStdout { stdOut = windows.NewAnsiWriter(syscall.STD_OUTPUT_HANDLE) } else { stdOut = os.Stdout } if emulateStderr { stdErr = windows.NewAnsiWriter(syscall.STD_ERROR_HANDLE) } else { stdErr = os.Stderr } return }