github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/utils/readline/raw_windows.go (about)

     1  // Copyright 2011 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build windows
     6  // +build windows
     7  
     8  // Package terminal provides support functions for dealing with terminals, as
     9  // commonly found on UNIX systems.
    10  //
    11  // Putting a terminal into raw mode is the most common requirement:
    12  //
    13  //	oldState, err := terminal.MakeRaw(0)
    14  //	if err != nil {
    15  //	        panic(err)
    16  //	}
    17  //	defer terminal.Restore(0, oldState)
    18  package readline
    19  
    20  import (
    21  	"golang.org/x/sys/windows"
    22  )
    23  
    24  type State struct {
    25  	mode uint32
    26  }
    27  
    28  // IsTerminal returns true if the given file descriptor is a terminal.
    29  func IsTerminal(fd int) bool {
    30  	var st uint32
    31  	err := windows.GetConsoleMode(windows.Handle(fd), &st)
    32  	return err == nil
    33  }
    34  
    35  // MakeRaw put the terminal connected to the given file descriptor into raw
    36  // mode and returns the previous state of the terminal so that it can be
    37  // restored.
    38  func MakeRaw(fd int) (*State, error) {
    39  	var st uint32
    40  	if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
    41  		return nil, err
    42  	}
    43  	raw := st &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT)
    44  	raw |= windows.ENABLE_VIRTUAL_TERMINAL_INPUT
    45  	if err := windows.SetConsoleMode(windows.Handle(fd), raw); err != nil {
    46  		return nil, err
    47  	}
    48  	return &State{st}, nil
    49  }
    50  
    51  // GetState returns the current state of a terminal which may be useful to
    52  // restore the terminal after a signal.
    53  func GetState(fd int) (*State, error) {
    54  	var st uint32
    55  	if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
    56  		return nil, err
    57  	}
    58  	return &State{st}, nil
    59  }
    60  
    61  // Restore restores the terminal connected to the given file descriptor to a
    62  // previous state.
    63  func Restore(fd int, state *State) error {
    64  	return windows.SetConsoleMode(windows.Handle(fd), state.mode)
    65  }
    66  
    67  // GetSize returns the dimensions of the given terminal.
    68  func GetSize(fd int) (width, height int, err error) {
    69  	var info windows.ConsoleScreenBufferInfo
    70  	if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil {
    71  		return 0, 0, err
    72  	}
    73  	return int(info.Window.Right - info.Window.Left + 1), int(info.Window.Bottom - info.Window.Top + 1), nil
    74  }