mirror of
https://github.com/vlang/v.git
synced 2025-08-03 17:57:59 -04:00
parent
4a1c7add24
commit
5b44b67211
29
examples/term_key_pressed.v
Normal file
29
examples/term_key_pressed.v
Normal file
@ -0,0 +1,29 @@
|
||||
module main
|
||||
|
||||
import term
|
||||
import time
|
||||
|
||||
fn main() {
|
||||
unbuffer_stdout()
|
||||
println('Press Ctrl-D or ESC to exit.')
|
||||
|
||||
term.enable_echo(false)
|
||||
mut frame := 0
|
||||
for {
|
||||
print('\r${time.now()} | frame: ${frame:06} | ')
|
||||
x := term.key_pressed()
|
||||
if x in [i64(0), 4, 27] {
|
||||
// pressing Ctrl-D or ESC exits the loop
|
||||
// Ctrl-D mean EOF sometimes, so return 0
|
||||
break
|
||||
}
|
||||
if x > 0 {
|
||||
println('${x:08x}')
|
||||
}
|
||||
time.sleep(16 * time.millisecond)
|
||||
frame++
|
||||
}
|
||||
term.enable_echo(true)
|
||||
|
||||
println('done')
|
||||
}
|
@ -2,6 +2,7 @@ module term
|
||||
|
||||
import os
|
||||
import term.termios
|
||||
import time
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
@ -215,3 +216,68 @@ pub fn graphics_num_colors() u16 {
|
||||
}
|
||||
return buf.bytestr().u16()
|
||||
}
|
||||
|
||||
// enable_echo enable/disable echo input characters
|
||||
pub fn enable_echo(enable bool) {
|
||||
mut state := termios.Termios{}
|
||||
termios.tcgetattr(0, mut state)
|
||||
if enable {
|
||||
state.c_lflag |= C.ECHO
|
||||
} else {
|
||||
state.c_lflag &= ~C.ECHO
|
||||
}
|
||||
termios.tcsetattr(0, C.TCSANOW, mut state)
|
||||
}
|
||||
|
||||
// KeyPressedParams contains the optional parameters that you can pass to key_pressed.
|
||||
@[params]
|
||||
pub struct KeyPressedParams {
|
||||
pub mut:
|
||||
blocking bool // whether to wait for a pressed key
|
||||
echo bool // whether to output the pressed key to stdout
|
||||
}
|
||||
|
||||
// key_pressed gives back a single character, read from the standard input.
|
||||
// It returns -1 on error or no character in non-blocking mode
|
||||
pub fn key_pressed(params KeyPressedParams) i64 {
|
||||
mut state := termios.Termios{}
|
||||
if termios.tcgetattr(0, mut state) != 0 {
|
||||
return -1
|
||||
}
|
||||
mut old_state := state
|
||||
defer {
|
||||
// restore the old terminal state:
|
||||
termios.tcsetattr(0, C.TCSANOW, mut old_state)
|
||||
}
|
||||
|
||||
// disable line by line input
|
||||
state.c_lflag &= ~C.ICANON
|
||||
|
||||
if params.echo {
|
||||
state.c_lflag |= C.ECHO
|
||||
} else {
|
||||
state.c_lflag &= ~C.ECHO
|
||||
}
|
||||
termios.tcsetattr(0, C.TCSANOW, mut state)
|
||||
|
||||
mut ret := i64(0)
|
||||
|
||||
for {
|
||||
pending := os.fd_is_pending(0)
|
||||
if pending {
|
||||
r := C.read(0, &ret, 8)
|
||||
if r < 0 {
|
||||
return r
|
||||
} else {
|
||||
return ret
|
||||
}
|
||||
}
|
||||
if !params.blocking {
|
||||
// in non-blocking mode, we need to return immediately
|
||||
return -1
|
||||
}
|
||||
time.sleep(1 * time.millisecond)
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
module term
|
||||
|
||||
import os
|
||||
import time
|
||||
|
||||
#include <conio.h>
|
||||
|
||||
@[typedef]
|
||||
pub struct C.COORD {
|
||||
@ -156,3 +159,54 @@ pub fn graphics_num_colors() u16 {
|
||||
// does not have support for querying the graphics setup this call returns 0
|
||||
return 0
|
||||
}
|
||||
|
||||
// enable_echo enable/disable echo input characters
|
||||
pub fn enable_echo(enable bool) {
|
||||
// no need under windows, use key_pressed func's echo
|
||||
}
|
||||
|
||||
fn C.kbhit() bool
|
||||
fn C._getch() int
|
||||
fn C._getche() int
|
||||
|
||||
// KeyPressedParams contains the optional parameters that you can pass to key_pressed.
|
||||
@[params]
|
||||
pub struct KeyPressedParams {
|
||||
pub mut:
|
||||
blocking bool // whether to wait for a pressed key
|
||||
echo bool // whether to output the pressed key to stdout
|
||||
}
|
||||
|
||||
// key_pressed gives back a single character, read from the standard input.
|
||||
// It returns -1 on error or no character in non-blocking mode
|
||||
pub fn key_pressed(params KeyPressedParams) i64 {
|
||||
for {
|
||||
if C.kbhit() {
|
||||
res := if params.echo {
|
||||
C._getche()
|
||||
} else {
|
||||
C._getch()
|
||||
}
|
||||
// see https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/getche-getwche?view=msvc-170
|
||||
// > When _getche or _getwche reads a function key or an arrow key, the function must be called twice;
|
||||
// > the first call returns 0 or 0xE0, and the second call returns the actual key code.
|
||||
if res in [0, 0xe0] {
|
||||
if C.kbhit() {
|
||||
res2 := if params.echo {
|
||||
C._getche()
|
||||
} else {
|
||||
C._getch()
|
||||
}
|
||||
return i64(u32(0xe0) << 16 | u32(res2))
|
||||
}
|
||||
}
|
||||
return i64(res)
|
||||
}
|
||||
if !params.blocking {
|
||||
// in non-blocking mode, we need to return immediately
|
||||
return -1
|
||||
}
|
||||
time.sleep(1 * time.millisecond)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user