keyfork-prompt: use raw mode for input
This commit is contained in:
parent
c232828290
commit
35e0eb57a0
|
@ -1,26 +1,15 @@
|
|||
#![allow(missing_docs)]
|
||||
|
||||
use keyfork_prompt::{
|
||||
prompt_validated_wordlist,
|
||||
validators::{mnemonic, Validator},
|
||||
Message,
|
||||
default_handler,
|
||||
};
|
||||
|
||||
use keyfork_mnemonic::English;
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut handler = default_handler().unwrap();
|
||||
let transport_validator = mnemonic::MnemonicSetValidator {
|
||||
word_lengths: [24],
|
||||
};
|
||||
let mut handler = default_handler()?;
|
||||
|
||||
let mnemonics = prompt_validated_wordlist::<English, _>(
|
||||
&mut *handler,
|
||||
"Enter a 24-word mnemonic: ",
|
||||
3,
|
||||
&*transport_validator.to_fn(),
|
||||
)?;
|
||||
assert_eq!(mnemonics[0].as_bytes().len(), 32);
|
||||
let output = handler.prompt_input("Test message: ")?;
|
||||
handler.prompt_message(Message::Text(format!("Result: {output}")))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -217,9 +217,9 @@ pub fn default_handler() -> Result<Box<dyn PromptHandler>, DefaultHandlerError>
|
|||
}
|
||||
}
|
||||
|
||||
// stdout can be not-a-terminal and we'll just override it anyways, stdin is the
|
||||
// important one.
|
||||
if std::io::stdin().is_terminal() {
|
||||
// we can revert stdin to a readable input by using raw mode, but we can't do the more
|
||||
// significant operations if we don't have access to a terminal stderr
|
||||
if std::io::stderr().is_terminal() {
|
||||
// because this is a "guessed" handler, let's take the nice route and not error, just skip.
|
||||
if let Ok(terminal) = default_terminal() {
|
||||
return Ok(Box::new(terminal));
|
||||
|
|
|
@ -178,12 +178,14 @@ where
|
|||
W: Write + AsRawFd + Sized,
|
||||
{
|
||||
fn prompt_input(&mut self, prompt: &str) -> Result<String> {
|
||||
let mut terminal = self.lock().alternate_screen()?;
|
||||
let mut terminal = self.lock().alternate_screen()?.raw_mode()?;
|
||||
terminal
|
||||
.queue(terminal::Clear(terminal::ClearType::All))?
|
||||
.queue(cursor::MoveTo(0, 0))?;
|
||||
let mut lines = prompt.lines().peekable();
|
||||
let mut prefix_length = 0;
|
||||
while let Some(line) = lines.next() {
|
||||
prefix_length = line.len();
|
||||
terminal.queue(Print(line))?;
|
||||
if lines.peek().is_some() {
|
||||
terminal
|
||||
|
@ -193,9 +195,66 @@ where
|
|||
}
|
||||
terminal.flush()?;
|
||||
|
||||
let mut line = String::new();
|
||||
terminal.read.read_line(&mut line)?;
|
||||
Ok(line)
|
||||
let (mut cols, mut _rows) = terminal.size()?;
|
||||
|
||||
let mut input = String::new();
|
||||
loop {
|
||||
let input_len = input.len();
|
||||
match read()? {
|
||||
Event::Resize(new_cols, new_rows) => {
|
||||
cols = new_cols;
|
||||
_rows = new_rows;
|
||||
}
|
||||
Event::Key(k) => match k.code {
|
||||
KeyCode::Enter => {
|
||||
break;
|
||||
}
|
||||
KeyCode::Backspace => {
|
||||
if input.pop().is_some() && prefix_length + input_len < cols as usize {
|
||||
terminal
|
||||
.queue(cursor::MoveLeft(1))?
|
||||
.queue(Print(" "))?
|
||||
.queue(cursor::MoveLeft(1))?
|
||||
.flush()?;
|
||||
}
|
||||
}
|
||||
KeyCode::Char('w') if k.modifiers.contains(KeyModifiers::CONTROL) => {
|
||||
let mut has_deleted_text = true;
|
||||
while input.pop().is_some_and(char::is_whitespace) {
|
||||
has_deleted_text = false;
|
||||
}
|
||||
while input.pop().is_some_and(|c| !c.is_whitespace()) {
|
||||
has_deleted_text = true;
|
||||
}
|
||||
if !input.is_empty() && has_deleted_text {
|
||||
input.push(' ');
|
||||
}
|
||||
}
|
||||
KeyCode::Char('c') if k.modifiers.contains(KeyModifiers::CONTROL) => {
|
||||
return Err(Error::CtrlC);
|
||||
}
|
||||
KeyCode::Char(c) => {
|
||||
input.push(c);
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let printable_start = if prefix_length + input.len() < cols as usize {
|
||||
0
|
||||
} else {
|
||||
let printable_space = (cols as usize) - prefix_length;
|
||||
input.len() - (printable_space - 1)
|
||||
};
|
||||
terminal
|
||||
.queue(cursor::MoveToColumn(prefix_length as u16))?
|
||||
.queue(terminal::Clear(terminal::ClearType::UntilNewLine))?
|
||||
.queue(Print(&input[printable_start..]))?
|
||||
.flush()?;
|
||||
}
|
||||
|
||||
Ok(input)
|
||||
}
|
||||
|
||||
fn prompt_validated_wordlist(
|
||||
|
|
Loading…
Reference in New Issue