Skip to content

Commit

Permalink
Merge pull request #356 from gwenn/tty_tests
Browse files Browse the repository at this point in the history
Tty tests
  • Loading branch information
gwenn authored Apr 1, 2020
2 parents ec5c72a + 0828e31 commit cbedcf1
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 37 deletions.
24 changes: 3 additions & 21 deletions src/edit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,27 +151,9 @@ impl<'out, 'prompt, H: Helper> State<'out, 'prompt, H> {
None
};

// calculate the desired position of the cursor
let pos = self.line.pos();
let cursor = self.out.calculate_position(&self.line[..pos], prompt_size);
// calculate the position of the end of the input line
let mut end = if pos == self.line.len() {
cursor
} else {
self.out.calculate_position(&self.line[pos..], cursor)
};
if let Some(info) = info {
end = self.out.calculate_position(&info, end);
}

let new_layout = Layout {
prompt_size,
default_prompt,
cursor,
end,
};
debug_assert!(new_layout.prompt_size <= new_layout.cursor);
debug_assert!(new_layout.cursor <= new_layout.end);
let new_layout = self
.out
.compute_layout(prompt_size, default_prompt, &self.line, info);

debug!(target: "rustyline", "old layout: {:?}", self.layout);
debug!(target: "rustyline", "new layout: {:?}", new_layout);
Expand Down
68 changes: 52 additions & 16 deletions src/tty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,40 @@ pub trait Renderer {
highlighter: Option<&dyn Highlighter>,
) -> Result<()>;

/// Compute layout for rendering prompt + line + some info (either hint,
/// validation msg, ...). on the screen. Depending on screen width, line
/// wrapping may be applied.
fn compute_layout(
&self,
prompt_size: Position,
default_prompt: bool,
line: &LineBuffer,
info: Option<&str>,
) -> Layout {
// calculate the desired position of the cursor
let pos = line.pos();
let cursor = self.calculate_position(&line[..pos], prompt_size);
// calculate the position of the end of the input line
let mut end = if pos == line.len() {
cursor
} else {
self.calculate_position(&line[pos..], cursor)
};
if let Some(info) = info {
end = self.calculate_position(&info, end);
}

let new_layout = Layout {
prompt_size,
default_prompt,
cursor,
end,
};
debug_assert!(new_layout.prompt_size <= new_layout.cursor);
debug_assert!(new_layout.cursor <= new_layout.end);
new_layout
}

/// Calculate the number of columns and rows used to display `s` on a
/// `cols` width terminal starting at `orig`.
fn calculate_position(&self, s: &str, orig: Position) -> Position;
Expand Down Expand Up @@ -156,19 +190,21 @@ pub trait Term {
fn create_writer(&self) -> Self::Writer;
}

cfg_if::cfg_if! {
if #[cfg(any(test, target_arch = "wasm32"))] {
mod test;
pub use self::test::*;
} else if #[cfg(windows)] {
// If on Windows platform import Windows TTY module
// and re-export into mod.rs scope
mod windows;
pub use self::windows::*;
} else if #[cfg(unix)] {
// If on Unix platform import Unix TTY module
// and re-export into mod.rs scope
mod unix;
pub use self::unix::*;
}
}
// If on Windows platform import Windows TTY module
// and re-export into mod.rs scope
#[cfg(all(windows, not(target_arch = "wasm32")))]
mod windows;
#[cfg(all(windows, not(target_arch = "wasm32")))]
pub use self::windows::*;

// If on Unix platform import Unix TTY module
// and re-export into mod.rs scope
#[cfg(all(unix, not(target_arch = "wasm32")))]
mod unix;
#[cfg(all(unix, not(target_arch = "wasm32")))]
pub use self::unix::*;

#[cfg(any(test, target_arch = "wasm32"))]
mod test;
#[cfg(any(test, target_arch = "wasm32"))]
pub use self::test::*;
30 changes: 30 additions & 0 deletions src/tty/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ nix::ioctl_read_bad!(win_size, libc::TIOCGWINSZ, libc::winsize);
fn get_win_size<T: AsRawFd + ?Sized>(fileno: &T) -> (usize, usize) {
use std::mem::zeroed;

if cfg!(test) {
return (80, 24);
}

unsafe {
let mut size: libc::winsize = zeroed();
match win_size(fileno.as_raw_fd(), &mut size) {
Expand Down Expand Up @@ -920,6 +924,7 @@ fn write_and_flush(out: OutputStreamType, buf: &[u8]) -> Result<()> {
mod test {
use super::{Position, PosixRenderer, PosixTerminal, Renderer};
use crate::config::{BellStyle, OutputStreamType};
use crate::line_buffer::LineBuffer;

#[test]
#[ignore]
Expand Down Expand Up @@ -950,4 +955,29 @@ mod test {
fn assert_sync<T: Sync>() {}
assert_sync::<PosixTerminal>();
}

#[test]
fn test_line_wrap() {
let mut out = PosixRenderer::new(OutputStreamType::Stdout, 4, true, BellStyle::default());
let prompt = "> ";
let default_prompt = true;
let prompt_size = out.calculate_position(prompt, Position::default());

let mut line = LineBuffer::init("", 0, None);
let old_layout = out.compute_layout(prompt_size, default_prompt, &line, None);
assert_eq!(Position { col: 2, row: 0 }, old_layout.cursor);
assert_eq!(old_layout.cursor, old_layout.end);

assert_eq!(Some(true), line.insert('a', out.cols - prompt_size.col + 1));
let new_layout = out.compute_layout(prompt_size, default_prompt, &line, None);
assert_eq!(Position { col: 1, row: 1 }, new_layout.cursor);
assert_eq!(new_layout.cursor, new_layout.end);
out.refresh_line(prompt, &line, None, &old_layout, &new_layout, None)
.unwrap();
#[rustfmt::skip]
assert_eq!(
"\r\u{1b}[0K> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\r\u{1b}[1C",
out.buffer
);
}
}

0 comments on commit cbedcf1

Please sign in to comment.