src.elv.sh@v0.21.0-dev.0.20240515223629-06979efb9a2a/pkg/cli/examples/win_tty/main_windows.go (about)

     1  package main
     2  
     3  import (
     4  	"log"
     5  	"os"
     6  	"strings"
     7  	"unicode"
     8  
     9  	"golang.org/x/sys/windows"
    10  
    11  	"src.elv.sh/pkg/sys/ewindows"
    12  )
    13  
    14  func main() {
    15  	restore := setup(os.Stdin, os.Stdout)
    16  	defer restore()
    17  
    18  	log.Println("ready")
    19  	console, err := windows.GetStdHandle(windows.STD_INPUT_HANDLE)
    20  	if err != nil {
    21  		log.Fatalf("GetStdHandle(STD_INPUT_HANDLE): %v", err)
    22  	}
    23  	for {
    24  		var buf [1]ewindows.InputRecord
    25  		nr, err := ewindows.ReadConsoleInput(console, buf[:])
    26  		if nr == 0 {
    27  			log.Fatal("no event read")
    28  		}
    29  		if err != nil {
    30  			log.Fatal(err)
    31  		}
    32  		event := buf[0].GetEvent()
    33  		switch event := event.(type) {
    34  		case *ewindows.KeyEvent:
    35  			typ := "up"
    36  			if event.BKeyDown != 0 {
    37  				typ = "down"
    38  			}
    39  			r := rune(event.UChar[0]) + rune(event.UChar[1])<<8
    40  			rs := "(" + string(r) + ")"
    41  			if unicode.IsControl(r) {
    42  				rs = "   "
    43  			}
    44  			var mods []string
    45  			testMod := func(mask uint32, name string) {
    46  				if event.DwControlKeyState&mask != 0 {
    47  					mods = append(mods, name)
    48  				}
    49  			}
    50  			testMod(0x1, "right alt")
    51  			testMod(0x2, "left alt")
    52  			testMod(0x4, "right ctrl")
    53  			testMod(0x8, "left ctrl")
    54  			testMod(0x10, "shift")
    55  			// testMod(0x20, "numslock")
    56  			testMod(0x40, "scrolllock")
    57  			testMod(0x80, "capslock")
    58  			testMod(0x100, "enhanced")
    59  
    60  			log.Printf("%4s, key code = %02x, char = %04x %s, mods = %s\n",
    61  				typ, event.WVirtualKeyCode, r, rs, strings.Join(mods, ", "))
    62  		}
    63  	}
    64  }
    65  
    66  const (
    67  	wantedInMode = windows.ENABLE_WINDOW_INPUT |
    68  		windows.ENABLE_MOUSE_INPUT | windows.ENABLE_PROCESSED_INPUT
    69  	wantedOutMode = windows.ENABLE_PROCESSED_OUTPUT |
    70  		windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING
    71  )
    72  
    73  func setup(in, out *os.File) func() {
    74  	hIn := windows.Handle(in.Fd())
    75  	hOut := windows.Handle(out.Fd())
    76  
    77  	var oldInMode, oldOutMode uint32
    78  	err := windows.GetConsoleMode(hIn, &oldInMode)
    79  	if err != nil {
    80  		log.Fatal(err)
    81  	}
    82  	err = windows.GetConsoleMode(hOut, &oldOutMode)
    83  	if err != nil {
    84  		log.Fatal(err)
    85  	}
    86  
    87  	err = windows.SetConsoleMode(hIn, wantedInMode)
    88  	if err != nil {
    89  		log.Fatal(err)
    90  	}
    91  	err = windows.SetConsoleMode(hOut, wantedOutMode)
    92  	if err != nil {
    93  		log.Fatal(err)
    94  	}
    95  
    96  	return func() {
    97  		err := windows.SetConsoleMode(hIn, oldInMode)
    98  		if err != nil {
    99  			log.Fatal(err)
   100  		}
   101  		err = windows.SetConsoleMode(hOut, oldOutMode)
   102  		if err != nil {
   103  			log.Fatal(err)
   104  		}
   105  	}
   106  }