ca1ek
ca1ek

Reputation: 415

How do I get keyboard input without the user pressing the Enter key?

I would use ncurses but I want it to run on Windows. In C++, I could use kbhit() and getch() from conio to first check if a character was pressed, then get it.

I would like something similar in Rust.

Upvotes: 14

Views: 14533

Answers (3)

Mateo Lafalce
Mateo Lafalce

Reputation: 101

You can get the keyboard events in rust without pressing enter adding as a development dependency to k_board a lightweight crate developed with the purpose of offering a listener to the keyboard in raw mode using low-level resources (it does not have dependencies like other crates), I attach how you could capture any letter from the keyboard

cargo add k_board


use k_board::{keyboard::Keyboard, keys::Keys};

fn main() {
    println!("[*] I use k_board lightweight software");
    println!("[ ] I use heavyweight software");
    for key in Keyboard::new() {
        match key {
            Keys::Up => {
                std::process::Command::new("clear").status().unwrap();
                println!("[*] I use k_board lightweight software");
                println!("[ ] I use heavyweight software");
            }
            Keys::Down => {
                std::process::Command::new("clear").status().unwrap();
                println!("[ ] I use k_board lightweight software");
                println!("[*] I use heavyweight software");
            }
            Keys::Enter => {
                break;
            }
            _ => {}
        }
    }
}

Here I attach the list of keys and events

pub enum Keys {
    Up,
    Down,
    Left,
    Right,
    Enter,
    Space,
    Delete,
    Escape,
    Char(char)
    F(u8),
    Ctrl(char),
    Alt(char),
    AltGr(char),
    Null,
}

Upvotes: 0

Miiao
Miiao

Reputation: 998

You still can do something like

extern {
    fn _getch() -> core::ffi::c_char;
}

fn getch() -> char {
    unsafe {
        _getch() as char
    }
}

Upvotes: 0

Constantin
Constantin

Reputation: 8961

With the crate device_query you can query the keyboard state without requiring an active window. You just need to add in your Cargo.toml file the dependency to this crate:

[dependencies]
device_query = "0.1.0"

The usage is straightforward and similar to kbhit() and getch(). The difference is you'll receive a Vec of pressed keys (Keycode) and this Vec will be empty if no key is pressed. A single call covers the functionality of both kbhit() and getch() combined.

use device_query::{DeviceQuery, DeviceState, Keycode};

fn main() {
    let device_state = DeviceState::new();
    loop {
        let keys: Vec<Keycode> = device_state.get_keys();
        for key in keys.iter() {
            println!("Pressed key: {:?}", key);
        }
    }
}

This program will print out all pressed keys on the console. To instead just check if any key is pressed (like with kbhit() only), you could use is_empty() on the returned Vec<> like this:

let keys: Vec<Keycode> = device_state.get_keys();
if !keys.is_empty(){
    println!("kbhit");
}

Upvotes: 8

Related Questions