-
Notifications
You must be signed in to change notification settings - Fork 287
/
Copy pathunix.rs
56 lines (51 loc) · 1.62 KB
/
unix.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
use std::{
io::{self, Error, ErrorKind, Write},
time::Duration,
};
use crate::{
event::{filter::CursorPositionFilter, poll_internal, read_internal, InternalEvent},
terminal::{disable_raw_mode, enable_raw_mode, sys::is_raw_mode_enabled},
};
/// Returns the cursor position (column, row).
///
/// The top left cell is represented as `(0, 0)`.
///
/// On unix systems, this function will block and possibly time out while
/// [`crossterm::event::read`](crate::event::read) or [`crossterm::event::poll`](crate::event::poll) are being called.
pub fn position() -> io::Result<(u16, u16)> {
if is_raw_mode_enabled() {
read_position_raw()
} else {
read_position()
}
}
fn read_position() -> io::Result<(u16, u16)> {
enable_raw_mode()?;
let pos = read_position_raw();
disable_raw_mode()?;
pos
}
fn read_position_raw() -> io::Result<(u16, u16)> {
// Use `ESC [ 6 n` to and retrieve the cursor position.
let mut stdout = io::stdout();
stdout.write_all(b"\x1B[6n")?;
stdout.flush()?;
loop {
match poll_internal(Some(Duration::from_millis(2000)), &CursorPositionFilter) {
Ok(true) => {
if let Ok(InternalEvent::CursorPosition(x, y)) =
read_internal(&CursorPositionFilter)
{
return Ok((x, y));
}
}
Ok(false) => {
return Err(Error::new(
ErrorKind::Other,
"The cursor position could not be read within a normal duration",
));
}
Err(_) => {}
}
}
}