mirror of
https://github.com/apognu/tuigreet.git
synced 2024-09-11 15:38:04 +03:00
Fixed tuigreet not exiting on success (#40).
Changed terminal backend to allow for async stdin reading without blocking program termination.
This commit is contained in:
parent
546d7fb75b
commit
d2974d288b
213
Cargo.lock
generated
213
Cargo.lock
generated
@ -108,6 +108,48 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossterm"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0ebde6a9dd5e331cd6c6f48253254d117642c31653baa475e394657c59c1f7d"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"crossterm_winapi",
|
||||
"libc",
|
||||
"mio",
|
||||
"parking_lot",
|
||||
"signal-hook",
|
||||
"signal-hook-mio",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossterm"
|
||||
version = "0.21.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "486d44227f71a1ef39554c0dc47e44b9f4139927c75043312690c3f476d1d788"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"crossterm_winapi",
|
||||
"futures-core",
|
||||
"libc",
|
||||
"mio",
|
||||
"parking_lot",
|
||||
"signal-hook",
|
||||
"signal-hook-mio",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossterm_winapi"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a6966607622438301997d3dac0d2f6e9a90c68bb6bc1785ea98456ab93c0507"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dashmap"
|
||||
version = "4.0.2"
|
||||
@ -189,6 +231,100 @@ dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a12aa0eb539080d55c3f2d45a67c3b58b6b0773c1a3ca2dfec66d58c97fd66ca"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-executor",
|
||||
"futures-io",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5da6ba8c3bb3c165d3c7319fc1cc8304facf1fb8db99c5de877183c08a273888"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d"
|
||||
|
||||
[[package]]
|
||||
name = "futures-executor"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45025be030969d763025784f7f355043dc6bc74093e4ecc5000ca4dc50d8745c"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "522de2a0fe3e380f1bc577ba0474108faf3f6b18321dbf60b3b9c39a75073377"
|
||||
|
||||
[[package]]
|
||||
name = "futures-macro"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18e4a4b95cea4b4ccbcf1c5675ca7c4ee4e9e75eb79944d07defde18068f79bb"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"proc-macro-hack",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "36ea153c13024fe480590b3e3d4cad89a0cfacecc24577b68f86c6ced9c2bc11"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d3d00f4eddb73e498a54394f228cd55853bdf059259e8e7bc6e69d408892e99"
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "36568465210a3a6ee45e1f165136d68671471a501e632e9a98d96872222b5481"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"futures-macro",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"memchr",
|
||||
"pin-project-lite",
|
||||
"pin-utils",
|
||||
"proc-macro-hack",
|
||||
"proc-macro-nested",
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.4"
|
||||
@ -494,12 +630,6 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "numtoa"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
|
||||
|
||||
[[package]]
|
||||
name = "objc"
|
||||
version = "0.2.7"
|
||||
@ -605,6 +735,12 @@ version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.10"
|
||||
@ -635,6 +771,18 @@ dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-hack"
|
||||
version = "0.5.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-nested"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.29"
|
||||
@ -708,15 +856,6 @@ dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_termios"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8440d8acb4fd3d277125b4bd01a6f38aee8d814b3b5fc09b3f2b825d37d3fe8f"
|
||||
dependencies = [
|
||||
"redox_syscall",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.5.4"
|
||||
@ -849,6 +988,27 @@ dependencies = [
|
||||
"opaque-debug",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook"
|
||||
version = "0.3.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c98891d737e271a2954825ef19e46bd16bdb98e2746f2eec4f7a4ef7946efd1"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"signal-hook-registry",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-mio"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29fd5867f1c4f2c5be079aee7a2adf1152ebb04a4bc4d341f504b7dece607ed4"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"mio",
|
||||
"signal-hook",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.4.0"
|
||||
@ -858,6 +1018,12 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c307a32c1c5c437f38c7fd45d753050587732ba8628319fbdf12a7e289ccc590"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.7.0"
|
||||
@ -904,18 +1070,6 @@ dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termion"
|
||||
version = "1.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "077185e2eac69c3f8379a4298e1e07cd36beb962290d4a51199acf0fdc10607e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"numtoa",
|
||||
"redox_syscall",
|
||||
"redox_termios",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.14.2"
|
||||
@ -1011,7 +1165,7 @@ checksum = "39c8ce4e27049eed97cfa363a5048b09d995e209994634a0efc26a14ab6c0c23"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cassowary",
|
||||
"termion",
|
||||
"crossterm 0.20.0",
|
||||
"unicode-segmentation",
|
||||
"unicode-width",
|
||||
]
|
||||
@ -1021,6 +1175,8 @@ name = "tuigreet"
|
||||
version = "0.7.1"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"crossterm 0.21.0",
|
||||
"futures",
|
||||
"getopts",
|
||||
"greetd_ipc",
|
||||
"i18n-embed",
|
||||
@ -1030,7 +1186,6 @@ dependencies = [
|
||||
"rust-embed",
|
||||
"rust-ini",
|
||||
"smart-default",
|
||||
"termion",
|
||||
"textwrap",
|
||||
"tokio",
|
||||
"tui",
|
||||
|
@ -7,14 +7,15 @@ build = "build.rs"
|
||||
|
||||
[dependencies]
|
||||
chrono = { version = "^0.4.19", features = ["unstable-locales"] }
|
||||
crossterm = { version = "0.21.0", features = ["event-stream"] }
|
||||
futures = "0.3.17"
|
||||
getopts = "^0.2.21"
|
||||
greetd_ipc = { version = "0.8.0", features = ["tokio-codec"] }
|
||||
i18n-embed = { version = "^0.13.0", features = ["desktop-requester", "fluent-system"] }
|
||||
i18n-embed-fl = "^0.6.0"
|
||||
lazy_static = "^1.4.0"
|
||||
nix = "^0.23.0"
|
||||
termion = "^1.5.6"
|
||||
tui = "^0.16.0"
|
||||
tui = { version = "^0.16.0", default-features = false, features = ["crossterm"] }
|
||||
rust-embed = "^6.2"
|
||||
rust-ini = "^0.17.0"
|
||||
smart-default = "0.6.0"
|
||||
|
57
src/event.rs
57
src/event.rs
@ -1,60 +1,45 @@
|
||||
use std::{io, time::Duration};
|
||||
use std::time::Duration;
|
||||
|
||||
use termion::{event::Key, input::TermRead};
|
||||
use tokio::sync::mpsc;
|
||||
use crossterm::event::{Event as TermEvent, EventStream, KeyEvent};
|
||||
use futures::{future::FutureExt, StreamExt};
|
||||
use tokio::{sync::mpsc, time};
|
||||
|
||||
pub enum Event<I> {
|
||||
Input(I),
|
||||
const TICK_RATE: u64 = 250;
|
||||
|
||||
pub enum Event {
|
||||
Key(KeyEvent),
|
||||
Tick,
|
||||
}
|
||||
|
||||
pub struct Events {
|
||||
rx: mpsc::Receiver<Event<Key>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Config {
|
||||
pub tick_rate: Duration,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Config {
|
||||
Config {
|
||||
tick_rate: Duration::from_millis(250),
|
||||
}
|
||||
}
|
||||
rx: mpsc::Receiver<Event>,
|
||||
}
|
||||
|
||||
impl Events {
|
||||
pub async fn new() -> Events {
|
||||
let mut stream = EventStream::new();
|
||||
let (tx, rx) = mpsc::channel(10);
|
||||
|
||||
{
|
||||
let tx = tx.clone();
|
||||
|
||||
tokio::task::spawn(async move {
|
||||
let stdin = io::stdin();
|
||||
|
||||
for key in stdin.keys().flatten() {
|
||||
if tx.send(Event::Input(key)).await.is_err() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
tokio::task::spawn(async move {
|
||||
loop {
|
||||
let _ = tx.send(Event::Tick).await;
|
||||
let timeout = time::sleep(Duration::from_millis(TICK_RATE));
|
||||
|
||||
tokio::time::sleep(Duration::from_millis(250)).await;
|
||||
tokio::select! {
|
||||
event = stream.next().fuse() => {
|
||||
if let Some(Ok(TermEvent::Key(event))) = event {
|
||||
let _ = tx.send(Event::Key(event)).await;
|
||||
}
|
||||
}
|
||||
|
||||
_ = timeout => { let _ = tx.send(Event::Tick).await; },
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Events { rx }
|
||||
}
|
||||
|
||||
pub async fn next(&mut self) -> Option<Event<Key>> {
|
||||
pub async fn next(&mut self) -> Option<Event> {
|
||||
self.rx.recv().await
|
||||
}
|
||||
}
|
||||
|
@ -14,10 +14,7 @@ use i18n_embed::DesktopLanguageRequester;
|
||||
use tokio::{
|
||||
net::UnixStream,
|
||||
process::Command,
|
||||
sync::{
|
||||
oneshot::{Receiver, Sender},
|
||||
RwLock, RwLockWriteGuard,
|
||||
},
|
||||
sync::{RwLock, RwLockWriteGuard},
|
||||
};
|
||||
use zeroize::Zeroize;
|
||||
|
||||
@ -94,8 +91,7 @@ pub struct Greeter {
|
||||
|
||||
pub working: bool,
|
||||
pub done: bool,
|
||||
pub exit_tx: Option<Sender<AuthStatus>>,
|
||||
pub exit_rx: Option<Receiver<AuthStatus>>,
|
||||
pub exit: Option<AuthStatus>,
|
||||
}
|
||||
|
||||
impl Drop for Greeter {
|
||||
@ -130,10 +126,6 @@ impl Greeter {
|
||||
|
||||
greeter.selected_session = greeter.sessions.iter().position(|(_, command)| Some(command) == greeter.command.as_ref()).unwrap_or(0);
|
||||
|
||||
let (exit_tx, exit_rx) = tokio::sync::oneshot::channel::<AuthStatus>();
|
||||
greeter.exit_tx = Some(exit_tx);
|
||||
greeter.exit_rx = Some(exit_rx);
|
||||
|
||||
greeter
|
||||
}
|
||||
|
||||
|
@ -106,6 +106,7 @@ impl Ipc {
|
||||
crate::exit(&mut greeter, AuthStatus::Success).await;
|
||||
} else if let Some(command) = &greeter.command {
|
||||
greeter.done = true;
|
||||
greeter.mode = Mode::Processing;
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
self.send(Request::StartSession { cmd: vec![command.clone()] }).await;
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::{error::Error, sync::Arc};
|
||||
|
||||
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
|
||||
use greetd_ipc::Request;
|
||||
use termion::event::Key;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use crate::{
|
||||
@ -14,19 +14,39 @@ use crate::{
|
||||
};
|
||||
|
||||
pub async fn handle(greeter: Arc<RwLock<Greeter>>, events: &mut Events, ipc: Ipc) -> Result<(), Box<dyn Error>> {
|
||||
if let Some(Event::Input(input)) = events.next().await {
|
||||
if let Some(Event::Key(input)) = events.next().await {
|
||||
let mut greeter = greeter.write().await;
|
||||
|
||||
match input {
|
||||
Key::Esc => {
|
||||
KeyEvent {
|
||||
code: KeyCode::Char('u'),
|
||||
modifiers: KeyModifiers::CONTROL,
|
||||
} => match greeter.mode {
|
||||
Mode::Username => greeter.username = String::new(),
|
||||
Mode::Password => greeter.answer = String::new(),
|
||||
Mode::Command => greeter.new_command = String::new(),
|
||||
_ => {}
|
||||
},
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
KeyEvent {
|
||||
code: KeyCode::Char('x'),
|
||||
modifiers: KeyModifiers::CONTROL,
|
||||
} => {
|
||||
use crate::greeter::AuthStatus;
|
||||
|
||||
crate::exit(&mut greeter, AuthStatus::Cancel).await;
|
||||
}
|
||||
|
||||
KeyEvent { code: KeyCode::Esc, .. } => {
|
||||
Ipc::cancel(&mut greeter).await;
|
||||
greeter.reset().await;
|
||||
}
|
||||
|
||||
Key::Left => greeter.cursor_offset -= 1,
|
||||
Key::Right => greeter.cursor_offset += 1,
|
||||
KeyEvent { code: KeyCode::Left, .. } => greeter.cursor_offset -= 1,
|
||||
KeyEvent { code: KeyCode::Right, .. } => greeter.cursor_offset += 1,
|
||||
|
||||
Key::F(2) => {
|
||||
KeyEvent { code: KeyCode::F(2), .. } => {
|
||||
greeter.previous_mode = match greeter.mode {
|
||||
Mode::Command | Mode::Sessions | Mode::Power => greeter.previous_mode,
|
||||
_ => greeter.mode,
|
||||
@ -36,7 +56,7 @@ pub async fn handle(greeter: Arc<RwLock<Greeter>>, events: &mut Events, ipc: Ipc
|
||||
greeter.mode = Mode::Command;
|
||||
}
|
||||
|
||||
Key::F(3) => {
|
||||
KeyEvent { code: KeyCode::F(3), .. } => {
|
||||
greeter.previous_mode = match greeter.mode {
|
||||
Mode::Command | Mode::Sessions | Mode::Power => greeter.previous_mode,
|
||||
_ => greeter.mode,
|
||||
@ -45,7 +65,7 @@ pub async fn handle(greeter: Arc<RwLock<Greeter>>, events: &mut Events, ipc: Ipc
|
||||
greeter.mode = Mode::Sessions;
|
||||
}
|
||||
|
||||
Key::F(12) => {
|
||||
KeyEvent { code: KeyCode::F(12), .. } => {
|
||||
greeter.previous_mode = match greeter.mode {
|
||||
Mode::Command | Mode::Sessions | Mode::Power => greeter.previous_mode,
|
||||
_ => greeter.mode,
|
||||
@ -54,7 +74,7 @@ pub async fn handle(greeter: Arc<RwLock<Greeter>>, events: &mut Events, ipc: Ipc
|
||||
greeter.mode = Mode::Power;
|
||||
}
|
||||
|
||||
Key::Up => {
|
||||
KeyEvent { code: KeyCode::Up, .. } => {
|
||||
if let Mode::Sessions = greeter.mode {
|
||||
if greeter.selected_session > 0 {
|
||||
greeter.selected_session -= 1;
|
||||
@ -68,7 +88,7 @@ pub async fn handle(greeter: Arc<RwLock<Greeter>>, events: &mut Events, ipc: Ipc
|
||||
}
|
||||
}
|
||||
|
||||
Key::Down => {
|
||||
KeyEvent { code: KeyCode::Down, .. } => {
|
||||
if let Mode::Sessions = greeter.mode {
|
||||
if greeter.selected_session < greeter.sessions.len() - 1 {
|
||||
greeter.selected_session += 1;
|
||||
@ -82,7 +102,10 @@ pub async fn handle(greeter: Arc<RwLock<Greeter>>, events: &mut Events, ipc: Ipc
|
||||
}
|
||||
}
|
||||
|
||||
Key::Ctrl('a') => {
|
||||
KeyEvent {
|
||||
code: KeyCode::Char('a'),
|
||||
modifiers: KeyModifiers::CONTROL,
|
||||
} => {
|
||||
let value = {
|
||||
match greeter.mode {
|
||||
Mode::Username => greeter.username.clone(),
|
||||
@ -93,9 +116,12 @@ pub async fn handle(greeter: Arc<RwLock<Greeter>>, events: &mut Events, ipc: Ipc
|
||||
greeter.cursor_offset = -(value.chars().count() as i16);
|
||||
}
|
||||
|
||||
Key::Ctrl('e') => greeter.cursor_offset = 0,
|
||||
KeyEvent {
|
||||
code: KeyCode::Char('e'),
|
||||
modifiers: KeyModifiers::CONTROL,
|
||||
} => greeter.cursor_offset = 0,
|
||||
|
||||
Key::Char('\n') | Key::Char('\t') => match greeter.mode {
|
||||
KeyEvent { code: KeyCode::Enter, .. } | KeyEvent { code: KeyCode::Char('\t'), .. } => match greeter.mode {
|
||||
Mode::Username => {
|
||||
greeter.working = true;
|
||||
greeter.message = None;
|
||||
@ -158,23 +184,9 @@ pub async fn handle(greeter: Arc<RwLock<Greeter>>, events: &mut Events, ipc: Ipc
|
||||
Mode::Processing => {}
|
||||
},
|
||||
|
||||
Key::Char(c) => insert_key(&mut greeter, c).await,
|
||||
KeyEvent { code: KeyCode::Char(c), .. } => insert_key(&mut greeter, c).await,
|
||||
|
||||
Key::Backspace | Key::Delete => delete_key(&mut greeter, input).await,
|
||||
|
||||
Key::Ctrl('u') => match greeter.mode {
|
||||
Mode::Username => greeter.username = String::new(),
|
||||
Mode::Password => greeter.answer = String::new(),
|
||||
Mode::Command => greeter.new_command = String::new(),
|
||||
_ => {}
|
||||
},
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
Key::Ctrl('x') => {
|
||||
use crate::greeter::AuthStatus;
|
||||
|
||||
crate::exit(&mut greeter, AuthStatus::Cancel).await;
|
||||
}
|
||||
KeyEvent { code: KeyCode::Backspace, .. } | KeyEvent { code: KeyCode::Delete, .. } => delete_key(&mut greeter, input.code).await,
|
||||
|
||||
_ => {}
|
||||
}
|
||||
@ -206,7 +218,7 @@ async fn insert_key(greeter: &mut Greeter, c: char) {
|
||||
};
|
||||
}
|
||||
|
||||
async fn delete_key(greeter: &mut Greeter, key: Key) {
|
||||
async fn delete_key(greeter: &mut Greeter, key: KeyCode) {
|
||||
let value = match greeter.mode {
|
||||
Mode::Username => greeter.username.clone(),
|
||||
Mode::Password => greeter.answer.clone(),
|
||||
@ -215,8 +227,8 @@ async fn delete_key(greeter: &mut Greeter, key: Key) {
|
||||
};
|
||||
|
||||
let index = match key {
|
||||
Key::Backspace => (value.chars().count() as i16 + greeter.cursor_offset - 1) as usize,
|
||||
Key::Delete => (value.chars().count() as i16 + greeter.cursor_offset) as usize,
|
||||
KeyCode::Backspace => (value.chars().count() as i16 + greeter.cursor_offset - 1) as usize,
|
||||
KeyCode::Delete => (value.chars().count() as i16 + greeter.cursor_offset) as usize,
|
||||
_ => 0,
|
||||
};
|
||||
|
||||
@ -233,7 +245,7 @@ async fn delete_key(greeter: &mut Greeter, key: Key) {
|
||||
Mode::Sessions | Mode::Power | Mode::Processing => return,
|
||||
};
|
||||
|
||||
if let Key::Delete = key {
|
||||
if let KeyCode::Delete = key {
|
||||
greeter.cursor_offset += 1;
|
||||
}
|
||||
}
|
||||
|
32
src/main.rs
32
src/main.rs
@ -14,10 +14,13 @@ mod ui;
|
||||
|
||||
use std::{error::Error, io, process, sync::Arc};
|
||||
|
||||
use crossterm::{
|
||||
execute,
|
||||
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen},
|
||||
};
|
||||
use greetd_ipc::Request;
|
||||
use termion::raw::IntoRawMode;
|
||||
use tokio::sync::RwLock;
|
||||
use tui::{backend::TermionBackend, Terminal};
|
||||
use tui::{backend::CrosstermBackend, Terminal};
|
||||
|
||||
pub use self::greeter::*;
|
||||
use self::{event::Events, ipc::Ipc};
|
||||
@ -36,8 +39,13 @@ async fn main() {
|
||||
async fn run() -> Result<(), Box<dyn Error>> {
|
||||
let greeter = Greeter::new().await;
|
||||
|
||||
let stdout = io::stdout().into_raw_mode()?;
|
||||
let backend = TermionBackend::new(stdout);
|
||||
enable_raw_mode()?;
|
||||
|
||||
let mut stdout = io::stdout();
|
||||
|
||||
execute!(stdout, EnterAlternateScreen)?;
|
||||
|
||||
let backend = CrosstermBackend::new(stdout);
|
||||
let mut terminal = Terminal::new(backend)?;
|
||||
|
||||
terminal.clear()?;
|
||||
@ -94,10 +102,8 @@ async fn run() -> Result<(), Box<dyn Error>> {
|
||||
});
|
||||
|
||||
loop {
|
||||
if let Some(ref mut rx) = greeter.write().await.exit_rx {
|
||||
if let Ok(status) = rx.try_recv() {
|
||||
return Err(status.into());
|
||||
}
|
||||
if let Some(status) = greeter.read().await.exit {
|
||||
return Err(status.into());
|
||||
}
|
||||
|
||||
ui::draw(greeter.clone(), &mut terminal).await?;
|
||||
@ -112,14 +118,13 @@ pub async fn exit(mut greeter: &mut Greeter, status: AuthStatus) {
|
||||
}
|
||||
|
||||
clear_screen();
|
||||
let _ = disable_raw_mode();
|
||||
|
||||
if let Some(tx) = greeter.exit_tx.take() {
|
||||
let _ = tx.send(status);
|
||||
}
|
||||
greeter.exit = Some(status);
|
||||
}
|
||||
|
||||
pub fn clear_screen() {
|
||||
let backend = TermionBackend::new(io::stdout());
|
||||
let backend = CrosstermBackend::new(io::stdout());
|
||||
|
||||
if let Ok(mut terminal) = Terminal::new(backend) {
|
||||
let _ = terminal.clear();
|
||||
@ -130,7 +135,10 @@ pub fn clear_screen() {
|
||||
pub fn log(msg: &str) {
|
||||
use std::io::Write;
|
||||
|
||||
let time = chrono::Utc::now();
|
||||
|
||||
let mut file = std::fs::OpenOptions::new().create(true).append(true).open("/tmp/tuigreet.log").unwrap();
|
||||
file.write_all(format!("{:?} - ", time).as_ref()).unwrap();
|
||||
file.write_all(msg.as_ref()).unwrap();
|
||||
file.write_all("\n".as_bytes()).unwrap();
|
||||
}
|
||||
|
@ -1,8 +1,7 @@
|
||||
use std::{error::Error, io};
|
||||
|
||||
use termion::raw::RawTerminal;
|
||||
use tui::{
|
||||
backend::TermionBackend,
|
||||
backend::CrosstermBackend,
|
||||
layout::{Constraint, Direction, Layout, Rect},
|
||||
text::Span,
|
||||
widgets::{Block, BorderType, Borders, Paragraph},
|
||||
@ -12,7 +11,7 @@ use tui::{
|
||||
use super::prompt_value;
|
||||
use crate::{ui::util::*, Greeter};
|
||||
|
||||
pub fn draw(mut greeter: &mut Greeter, f: &mut Frame<'_, TermionBackend<RawTerminal<io::Stdout>>>) -> Result<(u16, u16), Box<dyn Error>> {
|
||||
pub fn draw(mut greeter: &mut Greeter, f: &mut Frame<'_, CrosstermBackend<io::Stdout>>) -> Result<(u16, u16), Box<dyn Error>> {
|
||||
let size = f.size();
|
||||
|
||||
let width = greeter.width();
|
||||
|
@ -13,10 +13,9 @@ use std::{
|
||||
};
|
||||
|
||||
use chrono::prelude::*;
|
||||
use termion::raw::RawTerminal;
|
||||
use tokio::sync::RwLock;
|
||||
use tui::{
|
||||
backend::TermionBackend,
|
||||
backend::CrosstermBackend,
|
||||
layout::{Alignment, Constraint, Direction, Layout},
|
||||
style::{Modifier, Style},
|
||||
text::{Span, Spans},
|
||||
@ -37,7 +36,7 @@ const STATUSBAR_INDEX: usize = 3;
|
||||
const STATUSBAR_LEFT_INDEX: usize = 1;
|
||||
const STATUSBAR_RIGHT_INDEX: usize = 2;
|
||||
|
||||
type Term = Terminal<TermionBackend<RawTerminal<io::Stdout>>>;
|
||||
type Term = Terminal<CrosstermBackend<io::Stdout>>;
|
||||
|
||||
pub async fn draw(greeter: Arc<RwLock<Greeter>>, terminal: &mut Term) -> Result<(), Box<dyn Error>> {
|
||||
let mut greeter = greeter.write().await;
|
||||
|
@ -1,9 +1,8 @@
|
||||
use std::{error::Error, io};
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
use termion::raw::RawTerminal;
|
||||
use tui::{
|
||||
backend::TermionBackend,
|
||||
backend::CrosstermBackend,
|
||||
layout::Rect,
|
||||
style::{Modifier, Style},
|
||||
text::Span,
|
||||
@ -23,7 +22,7 @@ lazy_static! {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn draw(greeter: &mut Greeter, f: &mut Frame<'_, TermionBackend<RawTerminal<io::Stdout>>>) -> Result<(u16, u16), Box<dyn Error>> {
|
||||
pub fn draw(greeter: &mut Greeter, f: &mut Frame<'_, CrosstermBackend<io::Stdout>>) -> Result<(u16, u16), Box<dyn Error>> {
|
||||
let size = f.size();
|
||||
|
||||
let width = greeter.width();
|
||||
|
@ -1,8 +1,7 @@
|
||||
use std::{error::Error, io};
|
||||
|
||||
use termion::raw::RawTerminal;
|
||||
use tui::{
|
||||
backend::TermionBackend,
|
||||
backend::CrosstermBackend,
|
||||
layout::{Alignment, Constraint, Direction, Layout, Rect},
|
||||
text::Span,
|
||||
widgets::{Block, BorderType, Borders, Paragraph},
|
||||
@ -12,7 +11,7 @@ use tui::{
|
||||
use super::util::*;
|
||||
use crate::Greeter;
|
||||
|
||||
pub fn draw(greeter: &mut Greeter, f: &mut Frame<'_, TermionBackend<RawTerminal<io::Stdout>>>) -> Result<(u16, u16), Box<dyn Error>> {
|
||||
pub fn draw(greeter: &mut Greeter, f: &mut Frame<'_, CrosstermBackend<io::Stdout>>) -> Result<(u16, u16), Box<dyn Error>> {
|
||||
let size = f.size();
|
||||
|
||||
let width = greeter.width();
|
||||
|
@ -1,8 +1,7 @@
|
||||
use std::{error::Error, io};
|
||||
|
||||
use termion::raw::RawTerminal;
|
||||
use tui::{
|
||||
backend::TermionBackend,
|
||||
backend::CrosstermBackend,
|
||||
layout::{Alignment, Constraint, Direction, Layout, Rect},
|
||||
text::{Span, Text},
|
||||
widgets::{Block, BorderType, Borders, Paragraph},
|
||||
@ -16,7 +15,7 @@ const GREETING_INDEX: usize = 0;
|
||||
const USERNAME_INDEX: usize = 1;
|
||||
const ANSWER_INDEX: usize = 2;
|
||||
|
||||
pub fn draw(mut greeter: &mut Greeter, f: &mut Frame<'_, TermionBackend<RawTerminal<io::Stdout>>>) -> Result<(u16, u16), Box<dyn Error>> {
|
||||
pub fn draw(mut greeter: &mut Greeter, f: &mut Frame<'_, CrosstermBackend<io::Stdout>>) -> Result<(u16, u16), Box<dyn Error>> {
|
||||
let size = f.size();
|
||||
|
||||
let width = greeter.width();
|
||||
|
@ -1,8 +1,7 @@
|
||||
use std::{error::Error, io};
|
||||
|
||||
use termion::raw::RawTerminal;
|
||||
use tui::{
|
||||
backend::TermionBackend,
|
||||
backend::CrosstermBackend,
|
||||
layout::Rect,
|
||||
style::{Modifier, Style},
|
||||
text::Span,
|
||||
@ -13,7 +12,7 @@ use tui::{
|
||||
use super::util::*;
|
||||
use crate::Greeter;
|
||||
|
||||
pub fn draw(greeter: &mut Greeter, f: &mut Frame<'_, TermionBackend<RawTerminal<io::Stdout>>>) -> Result<(u16, u16), Box<dyn Error>> {
|
||||
pub fn draw(greeter: &mut Greeter, f: &mut Frame<'_, CrosstermBackend<io::Stdout>>) -> Result<(u16, u16), Box<dyn Error>> {
|
||||
let size = f.size();
|
||||
|
||||
let width = greeter.width();
|
||||
|
Loading…
Reference in New Issue
Block a user