diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8999f23..69d3f08 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -81,273 +81,4 @@ jobs: - uses: actions-rs/cargo@v1 with: command: build - - - standar: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@master - - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - - - uses: actions-rs/cargo@v1 - with: - command: build - args: --features standar - - - numbers: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@master - - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - - - uses: actions-rs/cargo@v1 - with: - command: build - args: --features numbers - - - lower_letter: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@master - - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - - - uses: actions-rs/cargo@v1 - with: - command: build - args: --features lower_letter - - - upper_letter: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@master - - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - - - uses: actions-rs/cargo@v1 - with: - command: build - args: --features upper_letter - - - f: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@master - - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - - - uses: actions-rs/cargo@v1 - with: - command: build - args: --features f - - - ctrl_lower_letter: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@master - - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - - - uses: actions-rs/cargo@v1 - with: - command: build - args: --features ctrl_lower_letter - - - ctrl_upper_letter: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@master - - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - - - uses: actions-rs/cargo@v1 - with: - command: build - args: --features ctrl_upper_letter - - - ctrl_standar: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@master - - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - - - uses: actions-rs/cargo@v1 - with: - command: build - args: --features ctrl_standar - - - ctrl_numbers: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@master - - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - - - uses: actions-rs/cargo@v1 - with: - command: build - args: --features ctrl_numbers - - - alt_lower_letter: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@master - - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - - - uses: actions-rs/cargo@v1 - with: - command: build - args: --features alt_lower_letter - - - alt_upper_letter: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@master - - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - - - uses: actions-rs/cargo@v1 - with: - command: build - args: --features alt_upper_letter - - - alt_gr_lower_letter: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@master - - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - - - uses: actions-rs/cargo@v1 - with: - command: build - args: --features alt_gr_lower_letter - - - alt_gr_upper_letter: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@master - - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - - - uses: actions-rs/cargo@v1 - with: - command: build - args: --features alt_gr_upper_letter - - - alt_gr_numbers: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@master - - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - - - uses: actions-rs/cargo@v1 - with: - command: build - args: --features alt_gr_numbers - - - full: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@master - - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - - - uses: actions-rs/cargo@v1 - with: - command: build - args: --features full \ No newline at end of file + args: --all-features \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 1a7b6ef..ab91cd8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "k_board" -version = "1.2.3" +version = "1.2.4" edition = "2021" license = "GPL-3.0" authors = ["Mateo Lafalce "] diff --git a/README.md b/README.md index 90d64f6..cd79c5b 100644 --- a/README.md +++ b/README.md @@ -412,22 +412,7 @@ Feel free to contribute to the repository. Run the bash command below to make al clear && cargo fmt && cargo clippy && -cargo build --features standar && -cargo build --features numbers && -cargo build --features lower_letter && -cargo build --features upper_letter && -cargo build --features f && -cargo build --features ctrl_lower_letter && -cargo build --features ctrl_upper_letter && -cargo build --features ctrl_standar && -cargo build --features ctrl_numbers && -cargo build --features alt_lower_letter && -cargo build --features alt_upper_letter && -cargo build --features alt_numbers && -cargo build --features alt_gr_lower_letter && -cargo build --features alt_gr_upper_letter && -cargo build --features alt_gr_numbers && -cargo build --features full +cargo build --all-features ``` ```rust diff --git a/src/keyboard.rs b/src/keyboard.rs index bfd4b4d..4226cd2 100644 --- a/src/keyboard.rs +++ b/src/keyboard.rs @@ -1,7 +1,7 @@ /*************************************************************************************** * keyboard.rs -- This file is part of k_board. * * * - * Copyright (C) 2023 Mateo Lafalce * + * Copyright (C) 2024 Mateo Lafalce * * * * k_board is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published * @@ -18,8 +18,67 @@ * * **************************************************************************************/ -use crate::{get_key_from_keyboard, Keys}; +use crate::{ + keys::{Keys, ARROWS_ENTER, BYTES}, + termio::{restore, setup_raw_mode, termios}, +}; +use std::io::{stdin, stdout, Read, Write}; +#[cfg(any(feature = "alt_gr_lower_letter", feature = "full"))] +use crate::keys::ALT_GR_LOWER_LETTER; +#[cfg(any(feature = "alt_gr_numbers", feature = "full"))] +use crate::keys::ALT_GR_NUMBERS; +#[cfg(any(feature = "alt_gr_upper_letter", feature = "full"))] +use crate::keys::ALT_GR_UPPER_LETTER; +#[cfg(any(feature = "alt_lower_letter", feature = "full"))] +use crate::keys::ALT_LOWER_LETTER; +#[cfg(any(feature = "alt_numbers", feature = "full"))] +use crate::keys::ALT_NUMBERS; +#[cfg(any(feature = "alt_upper_letter", feature = "full"))] +use crate::keys::ALT_UPPER_LETTER; +#[cfg(any(feature = "ctrl_lower_letter", feature = "full"))] +use crate::keys::CTRL_LOWER_LETTER; +#[cfg(any(feature = "ctrl_numbers", feature = "full"))] +use crate::keys::CTRL_NUMBERS; +#[cfg(any(feature = "ctrl_standar", feature = "full",))] +#[cfg(not(feature = "standar"))] +use crate::keys::CTRL_STANDAR; +#[cfg(any(feature = "ctrl_upper_letter", feature = "full"))] +use crate::keys::CTRL_UPPER_LETTER; +#[cfg(any(feature = "f", feature = "full"))] +use crate::keys::F; +#[cfg(any(feature = "lower_letter", feature = "full"))] +use crate::keys::LOWER_LETTERS; +#[cfg(any(feature = "numbers", feature = "full"))] +use crate::keys::NUMBERS; +#[cfg(any(feature = "standar", feature = "full"))] +use crate::keys::STANDAR; +#[cfg(any(feature = "upper_letter", feature = "full"))] +use crate::keys::UPPER_LETTER; + +#[cfg(any( + feature = "ctrl_lower_letter", + feature = "ctrl_upper_letter", + feature = "full" +))] +use crate::termio::{sig_handler, signal, SIGINT}; + +#[cfg(any( + feature = "ctrl_lower_letter", + feature = "ctrl_upper_letter", + feature = "full" +))] +use std::sync::Mutex; + +/// Global varible to get the CTRL+C event +#[cfg(any( + feature = "ctrl_lower_letter", + feature = "ctrl_upper_letter", + feature = "full" +))] +pub static CTRL_C: Mutex = Mutex::new(false); + +/// Keyboard struct pub struct Keyboard; impl Default for Keyboard { @@ -29,9 +88,11 @@ impl Default for Keyboard { } impl Keyboard { + /// Get a Keyboard instance pub fn new() -> Self { Keyboard } + /// Read the key is pressed pub fn read_key(&mut self) -> Keys { get_key_from_keyboard() } @@ -43,3 +104,178 @@ impl Iterator for Keyboard { Some(self.read_key()) } } + +/// Get the key press from the keyboard looking the +/// hex data in the I/O termios +pub fn get_key_from_keyboard() -> Keys { + #[cfg(any( + feature = "ctrl_lower_letter", + feature = "ctrl_upper_letter", + feature = "full" + ))] + unsafe { + signal(SIGINT, sig_handler as usize) + }; + + let termios_enviroment: termios = setup_raw_mode().unwrap(); + stdout().flush().unwrap(); + let mut buffer: [u8; BYTES] = [0; BYTES]; + let mut key: Keys = Keys::Null; + match stdin().read(&mut buffer) { + Ok(_) => (), + Err(err) => eprintln!("Error: {}", err), + } + + for &(ref pattern, keys) in ARROWS_ENTER.iter() { + if buffer == *pattern { + restore(&termios_enviroment).expect("Error with termios restore"); + key = keys; + } + } + + #[cfg(any(feature = "standar", feature = "full"))] + for &(ref pattern, keys) in STANDAR.iter() { + if buffer == *pattern { + restore(&termios_enviroment).expect("Error with termios restore"); + key = keys; + } + } + + #[cfg(any(feature = "numbers", feature = "full"))] + for &(ref pattern, keys) in NUMBERS.iter() { + if buffer == *pattern { + restore(&termios_enviroment).expect("Error with termios restore"); + key = keys; + } + } + + #[cfg(any(feature = "lower_letter", feature = "full"))] + for &(ref pattern, keys) in LOWER_LETTERS.iter() { + if buffer == *pattern { + restore(&termios_enviroment).expect("Error with termios restore"); + key = keys; + } + } + + #[cfg(any(feature = "upper_letter", feature = "full"))] + for &(ref pattern, keys) in UPPER_LETTER.iter() { + if buffer == *pattern { + restore(&termios_enviroment).expect("Error with termios restore"); + key = keys; + } + } + + #[cfg(any(feature = "f", feature = "full"))] + for &(ref pattern, keys) in F.iter() { + if buffer == *pattern { + restore(&termios_enviroment).expect("Error with termios restore"); + key = keys; + } + } + + #[cfg(any(feature = "ctrl_lower_letter", feature = "full"))] + for &(ref pattern, keys) in CTRL_LOWER_LETTER.iter() { + let mut ctrl_c_handler = CTRL_C.lock().unwrap(); + if *ctrl_c_handler { + *ctrl_c_handler = false; + restore(&termios_enviroment).expect("Error with termios restore"); + return Keys::Ctrl('c'); + } + if buffer == *pattern { + restore(&termios_enviroment).expect("Error with termios restore"); + key = keys; + } + } + + #[cfg(any(feature = "ctrl_upper_letter", feature = "full"))] + for &(ref pattern, keys) in CTRL_UPPER_LETTER.iter() { + let mut ctrl_c_handler = CTRL_C.lock().unwrap(); + if *ctrl_c_handler { + *ctrl_c_handler = false; + restore(&termios_enviroment).expect("Error with termios restore"); + return Keys::Ctrl('C'); + } + if buffer == *pattern { + restore(&termios_enviroment).expect("Error with termios restore"); + key = keys; + } + } + + #[cfg(any(feature = "ctrl_standar", feature = "full",))] + #[cfg(not(feature = "standar"))] + for &(ref pattern, keys) in CTRL_STANDAR.iter() { + if buffer == *pattern { + restore(&termios_enviroment).expect("Error with termios restore"); + key = keys; + } + } + + #[cfg(any(feature = "ctrl_numbers", feature = "full"))] + for &(ref pattern, keys) in CTRL_NUMBERS.iter() { + if buffer == *pattern { + restore(&termios_enviroment).expect("Error with termios restore"); + key = keys; + } + } + + #[cfg(any(feature = "alt_lower_letter", feature = "full"))] + for &(ref pattern, keys) in ALT_LOWER_LETTER.iter() { + if buffer == *pattern { + restore(&termios_enviroment).expect("Error with termios restore"); + key = keys; + } + } + + #[cfg(any(feature = "alt_upper_letter", feature = "full"))] + for &(ref pattern, keys) in ALT_UPPER_LETTER.iter() { + if buffer == *pattern { + restore(&termios_enviroment).expect("Error with termios restore"); + key = keys; + } + } + + #[cfg(any(feature = "alt_numbers", feature = "full"))] + for &(ref pattern, keys) in ALT_NUMBERS.iter() { + if buffer == *pattern { + restore(&termios_enviroment).expect("Error with termios restore"); + key = keys; + } + } + + #[cfg(any(feature = "alt_gr_lower_letter", feature = "full"))] + for &(ref pattern, keys) in ALT_GR_LOWER_LETTER.iter() { + if buffer == *pattern { + restore(&termios_enviroment).expect("Error with termios restore"); + key = keys; + } + } + + #[cfg(any(feature = "alt_gr_upper_letter", feature = "full"))] + for &(ref pattern, keys) in ALT_GR_UPPER_LETTER.iter() { + if buffer == *pattern { + restore(&termios_enviroment).expect("Error with termios restore"); + key = keys; + } + } + + #[cfg(any(feature = "alt_gr_numbers", feature = "full"))] + for &(ref pattern, keys) in ALT_GR_NUMBERS.iter() { + if buffer == *pattern { + restore(&termios_enviroment).expect("Error with termios restore"); + key = keys; + } + } + + restore(&termios_enviroment).expect("Error with termios restore"); + + #[cfg(any( + feature = "ctrl_lower_letter", + feature = "ctrl_upper_letter", + feature = "full" + ))] + unsafe { + signal(SIGINT, 0) + }; + + key +} diff --git a/src/keys.rs b/src/keys.rs index 61b655e..9d334aa 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -1,7 +1,7 @@ /*************************************************************************************** * keys.rs -- This file is part of k_board. * * * - * Copyright (C) 2023 Mateo Lafalce * + * Copyright (C) 2024 Mateo Lafalce * * * * k_board is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published * @@ -18,8 +18,10 @@ * * **************************************************************************************/ +/// Bytes taken to look what key is pressed pub const BYTES: usize = 3; +/// Keys enum #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum Keys { Up, @@ -42,6 +44,7 @@ pub enum Keys { Null, } +/// Default keys pub const ARROWS_ENTER: [([u8; BYTES], Keys); 5] = [ ([0x1B, 0x5B, 0x41], Keys::Up), ([0x1B, 0x5B, 0x42], Keys::Down), @@ -50,6 +53,7 @@ pub const ARROWS_ENTER: [([u8; BYTES], Keys); 5] = [ ([0x0A, 0x00, 0x00], Keys::Enter), ]; +/// All special character keys #[cfg(any(feature = "standar", feature = "full"))] pub const STANDAR: [([u8; BYTES], Keys); 40] = [ ([0x1B, 0x5B, 0x48], Keys::Home), @@ -94,6 +98,7 @@ pub const STANDAR: [([u8; BYTES], Keys); 40] = [ ([0xc2, 0xb4, 0x00], Keys::Char('ยด')), ]; +/// Decimal numbers #[cfg(any(feature = "numbers", feature = "full"))] pub const NUMBERS: [([u8; BYTES], Keys); 10] = [ ([0x30, 0x00, 0x00], Keys::Char('0')), @@ -108,6 +113,7 @@ pub const NUMBERS: [([u8; BYTES], Keys); 10] = [ ([0x39, 0x00, 0x00], Keys::Char('9')), ]; +/// Lower letters #[cfg(any(feature = "lower_letter", feature = "full"))] pub const LOWER_LETTERS: [([u8; BYTES], Keys); 27] = [ ([0x61, 0x00, 0x00], Keys::Char('a')), @@ -139,6 +145,7 @@ pub const LOWER_LETTERS: [([u8; BYTES], Keys); 27] = [ ([0x7A, 0x00, 0x00], Keys::Char('z')), ]; +/// Upper letters #[cfg(any(feature = "upper_letter", feature = "full"))] pub const UPPER_LETTER: [([u8; BYTES], Keys); 27] = [ ([0x41, 0x00, 0x00], Keys::Char('A')), @@ -170,6 +177,7 @@ pub const UPPER_LETTER: [([u8; BYTES], Keys); 27] = [ ([0x5A, 0x00, 0x00], Keys::Char('Z')), ]; +/// F1, F2..F12 #[cfg(any(feature = "f", feature = "full"))] pub const F: [([u8; BYTES], Keys); 12] = [ ([0x1b, 0x4f, 0x50], Keys::F(1)), @@ -186,6 +194,7 @@ pub const F: [([u8; BYTES], Keys); 12] = [ ([0x34, 0x7E, 0x00], Keys::F(12)), ]; +/// Ctrl + lower letter #[cfg(any( feature = "ctrl_lower_letter", feature = "ctrl_upper_letter", @@ -218,6 +227,7 @@ pub const CTRL_LOWER_LETTER: [([u8; BYTES], Keys); 24] = [ ([0x1A, 0x00, 0x00], Keys::Ctrl('z')), ]; +/// Ctrl + upper letter #[cfg(any(feature = "ctrl_upper_letter", feature = "full"))] pub const CTRL_UPPER_LETTER: [([u8; BYTES], Keys); 24] = [ (CTRL_LOWER_LETTER[0].0, Keys::Ctrl('A')), @@ -246,12 +256,16 @@ pub const CTRL_UPPER_LETTER: [([u8; BYTES], Keys); 24] = [ (CTRL_LOWER_LETTER[23].0, Keys::Ctrl('Z')), ]; -#[cfg(any(feature = "ctrl_standar", feature = "full"))] +/// The Char('+') make a colision with Ctrl('+'), +/// so if you need the standar feature, know that is the same hex code +#[cfg(any(feature = "ctrl_standar", feature = "full",))] +#[cfg(not(feature = "standar"))] pub const CTRL_STANDAR: [([u8; BYTES], Keys); 2] = [ ([0x2b, 0x00, 0x00], Keys::Ctrl('+')), ([0x1f, 0x00, 0x00], Keys::Ctrl('-')), ]; +/// Ctrl + numbers #[cfg(any( feature = "ctrl_numbers", feature = "alt_numbers", @@ -271,6 +285,7 @@ pub const CTRL_NUMBERS: [([u8; BYTES], Keys); 10] = [ ([0x39, 0x00, 0x00], Keys::Ctrl('9')), ]; +/// Alt + lower letter #[cfg(any(feature = "alt_lower_letter", feature = "full"))] pub const ALT_LOWER_LETTER: [([u8; BYTES], Keys); 27] = [ ([0x1b, 0x61, 0x00], Keys::Alt('a')), @@ -302,6 +317,7 @@ pub const ALT_LOWER_LETTER: [([u8; BYTES], Keys); 27] = [ ([0x1b, 0x7a, 0x00], Keys::Alt('z')), ]; +/// Alt + upper letter #[cfg(any(feature = "alt_upper_letter", feature = "full"))] pub const ALT_UPPER_LETTER: [([u8; BYTES], Keys); 27] = [ ([0x1b, 0x41, 0x00], Keys::Alt('A')), @@ -333,6 +349,7 @@ pub const ALT_UPPER_LETTER: [([u8; BYTES], Keys); 27] = [ ([0x1b, 0x5A, 0x00], Keys::Alt('Z')), ]; +/// Alt + numbers #[cfg(any(feature = "alt_numbers", feature = "full"))] pub const ALT_NUMBERS: [([u8; BYTES], Keys); 10] = [ (CTRL_NUMBERS[0].0, Keys::Alt('0')), @@ -347,6 +364,7 @@ pub const ALT_NUMBERS: [([u8; BYTES], Keys); 10] = [ (CTRL_NUMBERS[9].0, Keys::Alt('9')), ]; +/// Alt Gr + lower letters #[cfg(any(feature = "alt_gr_lower_letter", feature = "full"))] pub const ALT_GR_LOWER_LETTER: [([u8; BYTES], Keys); 27] = [ ([0xc3, 0xa6, 0x00], Keys::AltGr('a')), @@ -378,6 +396,7 @@ pub const ALT_GR_LOWER_LETTER: [([u8; BYTES], Keys); 27] = [ ([0xc2, 0xab, 0x00], Keys::AltGr('z')), ]; +/// Alt Gr + upper letters #[cfg(any(feature = "alt_gr_upper_letter", feature = "full"))] pub const ALT_GR_UPPER_LETTER: [([u8; BYTES], Keys); 27] = [ ([0xc3, 0xa6, 0x00], Keys::AltGr('A')), @@ -409,6 +428,7 @@ pub const ALT_GR_UPPER_LETTER: [([u8; BYTES], Keys); 27] = [ ([0xc2, 0xab, 0x00], Keys::AltGr('z')), ]; +/// Alt Gr + numbers #[cfg(any(feature = "alt_gr_numbers", feature = "full"))] pub const ALT_GR_NUMBERS: [([u8; BYTES], Keys); 10] = [ (CTRL_NUMBERS[0].0, Keys::AltGr('0')), diff --git a/src/lib.rs b/src/lib.rs index a4ad02c..bc4fdef 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ /*************************************************************************************** * lib.rs -- This file is part of k_board. * * * - * Copyright (C) 2023 Mateo Lafalce * + * Copyright (C) 2024 Mateo Lafalce * * * * k_board is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published * @@ -59,153 +59,9 @@ //! ``` //! +/// Keyboard struct & impls pub mod keyboard; +/// All keys tables pub mod keys; +/// Termios raw ops (linux kernel) pub mod termio; - -use crate::{ - keys::{Keys, BYTES}, - termio::{restore, setup_raw_mode, termios}, -}; -use std::io::{Read, Write}; - -pub fn get_key_from_keyboard() -> Keys { - let termios_enviroment: termios = setup_raw_mode().unwrap(); - std::io::stdout().flush().unwrap(); - let mut buffer: [u8; BYTES] = [0; BYTES]; - let mut key: Keys = Keys::Null; - match std::io::stdin().read(&mut buffer) { - Ok(_) => (), - Err(err) => eprintln!("Error: {}", err), - } - - for &(ref pattern, keys) in crate::keys::ARROWS_ENTER.iter() { - if buffer == *pattern { - restore(&termios_enviroment); - key = keys; - } - } - - #[cfg(any(feature = "standar", feature = "full"))] - for &(ref pattern, keys) in crate::keys::STANDAR.iter() { - if buffer == *pattern { - restore(&termios_enviroment); - key = keys; - } - } - - #[cfg(any(feature = "numbers", feature = "full"))] - for &(ref pattern, keys) in crate::keys::NUMBERS.iter() { - if buffer == *pattern { - restore(&termios_enviroment); - key = keys; - } - } - - #[cfg(any(feature = "lower_letter", feature = "full"))] - for &(ref pattern, keys) in crate::keys::LOWER_LETTERS.iter() { - if buffer == *pattern { - restore(&termios_enviroment); - key = keys; - } - } - - #[cfg(any(feature = "upper_letter", feature = "full"))] - for &(ref pattern, keys) in crate::keys::UPPER_LETTER.iter() { - if buffer == *pattern { - restore(&termios_enviroment); - key = keys; - } - } - - #[cfg(any(feature = "f", feature = "full"))] - for &(ref pattern, keys) in crate::keys::F.iter() { - if buffer == *pattern { - restore(&termios_enviroment); - key = keys; - } - } - - #[cfg(any(feature = "ctrl_lower_letter", feature = "full"))] - for &(ref pattern, keys) in crate::keys::CTRL_LOWER_LETTER.iter() { - if buffer == *pattern { - restore(&termios_enviroment); - key = keys; - } - } - - #[cfg(any(feature = "ctrl_upper_letter", feature = "full"))] - for &(ref pattern, keys) in crate::keys::CTRL_UPPER_LETTER.iter() { - if buffer == *pattern { - restore(&termios_enviroment); - key = keys; - } - } - - #[cfg(any(feature = "ctrl_standar", feature = "full"))] - for &(ref pattern, keys) in crate::keys::CTRL_STANDAR.iter() { - if buffer == *pattern { - restore(&termios_enviroment); - key = keys; - } - } - - #[cfg(any(feature = "ctrl_numbers", feature = "full"))] - for &(ref pattern, keys) in crate::keys::CTRL_NUMBERS.iter() { - if buffer == *pattern { - restore(&termios_enviroment); - key = keys; - } - } - - #[cfg(any(feature = "alt_lower_letter", feature = "full"))] - for &(ref pattern, keys) in crate::keys::ALT_LOWER_LETTER.iter() { - if buffer == *pattern { - restore(&termios_enviroment); - key = keys; - } - } - - #[cfg(any(feature = "alt_upper_letter", feature = "full"))] - for &(ref pattern, keys) in crate::keys::ALT_UPPER_LETTER.iter() { - if buffer == *pattern { - restore(&termios_enviroment); - key = keys; - } - } - - #[cfg(any(feature = "alt_numbers", feature = "full"))] - for &(ref pattern, keys) in crate::keys::ALT_NUMBERS.iter() { - if buffer == *pattern { - restore(&termios_enviroment); - key = keys; - } - } - - #[cfg(any(feature = "alt_gr_lower_letter", feature = "full"))] - for &(ref pattern, keys) in crate::keys::ALT_GR_LOWER_LETTER.iter() { - if buffer == *pattern { - restore(&termios_enviroment); - key = keys; - } - } - - #[cfg(any(feature = "alt_gr_upper_letter", feature = "full"))] - for &(ref pattern, keys) in crate::keys::ALT_GR_UPPER_LETTER.iter() { - if buffer == *pattern { - restore(&termios_enviroment); - key = keys; - } - } - - #[cfg(any(feature = "alt_gr_numbers", feature = "full"))] - for &(ref pattern, keys) in crate::keys::ALT_GR_NUMBERS.iter() { - if buffer == *pattern { - restore(&termios_enviroment); - key = keys; - } - } - - restore(&termios_enviroment); - key -} diff --git a/src/termio.rs b/src/termio.rs index f926c58..da02ba2 100644 --- a/src/termio.rs +++ b/src/termio.rs @@ -1,7 +1,7 @@ /*************************************************************************************** * termio.rs -- This file is part of k_board. * * * - * Copyright (C) 2023 Mateo Lafalce * + * Copyright (C) 2024 Mateo Lafalce * * * * k_board is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published * @@ -18,22 +18,46 @@ * * **************************************************************************************/ -use std::io::Write; +use std::{ + ffi::{c_int, c_uint}, + io::{stdout, Error, Result, Write}, + mem::zeroed, +}; +#[cfg(any( + feature = "ctrl_lower_letter", + feature = "ctrl_upper_letter", + feature = "full" +))] +use crate::keyboard::CTRL_C; + +#[allow(non_camel_case_types)] +type size_t = usize; #[allow(non_camel_case_types)] -type tcflag_t = std::ffi::c_uint; +type tcflag_t = c_uint; +#[allow(non_camel_case_types)] +type sighandler_t = size_t; + +/// Interrupt from keyboard +#[cfg(any( + feature = "ctrl_lower_letter", + feature = "ctrl_upper_letter", + feature = "full" +))] +pub const SIGINT: c_int = 2; -const TCSANOW: std::ffi::c_int = 0; -const TCSADRAIN: std::ffi::c_int = 0; +const TCSANOW: c_int = 0; +const TCSADRAIN: c_int = 0; const ICANON: tcflag_t = 0x00000002; const ECHO: tcflag_t = 0x00000008; const IXON: tcflag_t = 0x00000400; const IXANY: tcflag_t = 0x00000800; -pub fn setup_raw_mode() -> std::io::Result { - let mut termios: termios = unsafe { std::mem::zeroed() }; +/// Setup the raw mode in the console to take the termios struct +pub fn setup_raw_mode() -> Result { + let mut termios: termios = unsafe { zeroed() }; if unsafe { tcgetattr(TCSANOW, &mut termios) } < 0 { - return Err(std::io::Error::last_os_error()); + return Err(Error::last_os_error()); } let original_termios = termios.clone(); termios.c_lflag &= !(ICANON | ECHO); @@ -41,24 +65,33 @@ pub fn setup_raw_mode() -> std::io::Result { termios.c_cc[6] = 0; termios.c_cc[5] = 1; if unsafe { tcsetattr(TCSANOW, TCSADRAIN, &termios) } < 0 { - return Err(std::io::Error::last_os_error()); + return Err(Error::last_os_error()); } Ok(original_termios) } -pub fn restore_termios(original_termios: &termios) -> std::io::Result<()> { - if unsafe { tcsetattr(TCSANOW, TCSADRAIN, original_termios) } < 0 { - return Err(std::io::Error::last_os_error()); +/// Restore the termios enviroment +pub fn restore(termios_enviroment: &termios) -> Result<()> { + stdout().flush().unwrap(); + if unsafe { tcsetattr(TCSANOW, TCSADRAIN, termios_enviroment) } < 0 { + return Err(Error::last_os_error()); } Ok(()) } -pub fn restore(termios_enviroment: &termios) { - std::io::stdout().flush().unwrap(); - restore_termios(termios_enviroment).unwrap(); +/// Modify `CTRL_C` -> true, then the iterator get the change & +/// return the `Keys::Ctrl('c')` || `Keys::Ctrl('C')` +#[cfg(any( + feature = "ctrl_lower_letter", + feature = "ctrl_upper_letter", + feature = "full" +))] +pub fn sig_handler() { + let mut ctrl_c_handler = CTRL_C.lock().unwrap(); + *ctrl_c_handler = true; } -/// look more at https://linux.die.net/man/3/termios +/// look more at #[derive(Clone)] #[repr(C)] pub struct termios { @@ -74,18 +107,18 @@ pub struct termios { #[link(name = "c")] extern "C" { - /// tcsetattr() sets the parameters associated with the terminal + /// `tcsetattr()` sets the parameters associated with the terminal /// (unless support is required from the underlying hardware that is /// not available) from the termios structure referred to by termios_p. /// optional_actions specifies when the changes take effect - pub fn tcsetattr( - fd: std::ffi::c_int, - optional_actions: std::ffi::c_int, - termios_p: *const termios, - ) -> std::ffi::c_int; - /// tcgetattr() gets the parameters associated with the object referred + pub fn tcsetattr(fd: c_int, optional_actions: c_int, termios_p: *const termios) -> c_int; + /// `tcgetattr()` gets the parameters associated with the object referred /// by fd and stores them in the termios structure referenced by termios_p. /// This function may be invoked from a background process; however, the terminal /// attributes may be subsequently changed by a foreground process. - pub fn tcgetattr(fd: std::ffi::c_int, termios: *mut termios) -> std::ffi::c_int; + pub fn tcgetattr(fd: c_int, termios: *mut termios) -> c_int; + /// `signal()` sets the disposition of the signal signum to handler, + /// which is either SIG_IGN, SIG_DFL, or the address of a programmer- + /// defined function (a "signal handler"). + pub fn signal(signum: c_int, handler: sighandler_t) -> sighandler_t; }