Getting cursor position panicks a lot
Created by: donaldpipowitch
Hi there, it looks like cursor_pos()
panicks a lot and I don't really know why. I tried the same functionality with term_cursor
and it seems to work without problems. Any idea why? (Tested with the Windows Subshell for Linux using Ubuntu and Rust 1.25.)
The example should capitalize every key you write. Both examples should technically result in the same experience as far as I can tell. (Code is not cleaned up a lot.)
termion
Example which panicks with extern crate termion;
use termion::cursor::DetectCursorPos;
use termion::event::Key;
use termion::color;
use termion::input::TermRead;
use termion::raw::IntoRawMode;
use std::io::{stdin, stdout, Write};
#[derive(Debug)]
struct State {
value: String,
pos: u16,
}
impl State {
fn new() -> State {
State {
value: String::new(),
// ! Goto is one-based.
pos: 1,
}
}
}
fn main() {
let mut state = State::new();
let stdin = stdin();
let mut stdout = stdout().into_raw_mode().unwrap();
// Greeting
write!(
stdout,
"{grey}Start typing...{reset}",
grey = color::Fg(color::LightBlack),
reset = color::Fg(color::Reset)
).unwrap();
stdout.flush().unwrap();
for key in stdin.keys() {
match key.unwrap() {
Key::Ctrl('c') => break,
Key::Char(key) => {
if state.value.is_empty() {
let (_x, y) = stdout.cursor_pos().unwrap();
write!(stdout, "{}{}", termion::clear::CurrentLine, termion::cursor::Goto(1, y)).unwrap();
}
// update state
state.value.push(key);
state.pos += 1;
// render
let (_x, y) = stdout.cursor_pos().unwrap();
write!(stdout, "{}{}", termion::clear::CurrentLine, termion::cursor::Goto(1, y)).unwrap();
let (_x, y) = stdout.cursor_pos().unwrap();
write!(
stdout,
"{value}{cursor}{grey}{uppercase}{reset}",
value = state.value,
cursor = termion::cursor::Goto(state.pos, y),
uppercase = state.value.to_uppercase(),
grey = color::Fg(color::LightBlack),
reset = color::Fg(color::Reset)
).unwrap();
}
_ => {}
}
stdout.flush().unwrap();
}
}
term_cursor
Example which works with extern crate term_cursor;
extern crate termion;
use termion::event::Key;
use termion::color;
use termion::input::TermRead;
use termion::raw::IntoRawMode;
use std::io::{stdin, stdout, Write};
#[derive(Debug)]
struct State {
value: String,
pos: i32,
}
impl State {
fn new() -> State {
State {
value: String::new(),
// ! Goto is one-based.
pos: 1,
}
}
}
fn main() {
let mut state = State::new();
let stdin = stdin();
let mut stdout = stdout().into_raw_mode().unwrap();
// Greeting
write!(
stdout,
"{grey}Start typing...{reset}",
grey = color::Fg(color::LightBlack),
reset = color::Fg(color::Reset)
).unwrap();
stdout.flush().unwrap();
for key in stdin.keys() {
match key.unwrap() {
Key::Ctrl('c') => break,
Key::Char(key) => {
if state.value.is_empty() {
let (_x, y) = term_cursor::get_cursor_pos().unwrap();
write!(stdout, "{}{}", termion::clear::CurrentLine, term_cursor::Goto(1, y)).unwrap();
}
// update state
state.value.push(key);
state.pos += 1;
// render
let (_x, y) = term_cursor::get_cursor_pos().unwrap();
write!(stdout, "{}{}", termion::clear::CurrentLine, term_cursor::Goto(1, y)).unwrap();
let (_x, y) = term_cursor::get_cursor_pos().unwrap();
write!(
stdout,
"{value}{cursor}{grey}{uppercase}{reset}",
value = state.value,
cursor = term_cursor::Goto(state.pos, y),
uppercase = state.value.to_uppercase(),
grey = color::Fg(color::LightBlack),
reset = color::Fg(color::Reset)
).unwrap();
}
_ => {}
}
stdout.flush().unwrap();
}
}