Skip to content

Commit

Permalink
fix: inputs get messed up when a line overflows
Browse files Browse the repository at this point in the history
  • Loading branch information
roele committed Feb 2, 2024
1 parent b7c600a commit 0940523
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 7 deletions.
19 changes: 19 additions & 0 deletions src/common.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use console::Term;

/// Returns a tuple with the height of the output and the number of lines that overflow the terminal width
pub fn get_height(term: &Term, output: String) -> (usize, usize) {
let max_width = term.size().1 as usize;
let height = output.lines().count() - 1;
// calculate potential overflow of lines overflowing terminal width
let overflow = output
.lines()
.map(|l| {
if l.chars().count() > max_width {
l.chars().count() / max_width
} else {
0
}
})
.sum::<usize>();
(height, overflow)
}
18 changes: 16 additions & 2 deletions src/confirm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use std::io::Write;
use console::{Key, Term};
use termcolor::{Buffer, WriteColor};

use crate::theme;
use crate::theme::Theme;
use crate::{common, theme};

/// Select multiple options from a list
///
Expand Down Expand Up @@ -34,6 +34,7 @@ pub struct Confirm<'a> {
pub selected: bool,
term: Term,
height: usize,
overflow: usize,
}

impl<'a> Confirm<'a> {
Expand All @@ -48,6 +49,7 @@ impl<'a> Confirm<'a> {
negative: "No".to_string(),
selected: true,
height: 0,
overflow: 0,
}
}

Expand Down Expand Up @@ -88,25 +90,29 @@ impl<'a> Confirm<'a> {
loop {
self.clear()?;
let output = self.render()?;
self.height = output.lines().count() - 1;
self.term.write_all(output.as_bytes())?;
self.term.flush()?;
match self.term.read_key()? {
Key::ArrowLeft | Key::Char('h') => self.handle_left(),
Key::ArrowRight | Key::Char('l') => self.handle_right(),
Key::Char(c) if c == affirmative_char => {
self.selected = true;
self.update_height(output)?;
return self.handle_submit();
}
Key::Char(c) if c == negative_char => {
self.selected = false;
self.update_height(output)?;
return self.handle_submit();
}
Key::Enter => {
self.update_height(output)?;
return self.handle_submit();
}
_ => {}
}

self.update_height(output)?;
}
}

Expand Down Expand Up @@ -193,7 +199,15 @@ impl<'a> Confirm<'a> {
Ok(std::str::from_utf8(out.as_slice()).unwrap().to_string())
}

fn update_height(&mut self, output: String) -> io::Result<()> {
let (height, overflow) = common::get_height(&self.term, output);
self.height = height;
self.overflow = overflow;
Ok(())
}

fn clear(&mut self) -> io::Result<()> {
self.term.move_cursor_up(self.overflow)?;
self.term.clear_to_end_of_screen()?;
self.term.clear_last_lines(self.height)?;
self.height = 0;
Expand Down
17 changes: 14 additions & 3 deletions src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::{
use console::{measure_text_width, Key, Term};
use termcolor::{Buffer, WriteColor};

use crate::{theme, Theme};
use crate::{common, theme, Theme};

/// Single line text input
///
Expand Down Expand Up @@ -41,6 +41,7 @@ pub struct Input<'a> {

cursor: usize,
height: usize,
overflow: usize,
term: Term,
err: Option<String>,
}
Expand All @@ -65,6 +66,7 @@ impl<'a> Input<'a> {
validation: |_| Ok(()),
cursor: 0,
height: 0,
overflow: 0,
term: Term::stderr(),
err: None,
}
Expand Down Expand Up @@ -130,8 +132,6 @@ impl<'a> Input<'a> {
loop {
self.clear()?;
let output = self.render()?;

self.height = output.lines().count() - 1;
self.term.write_all(output.as_bytes())?;
self.term.flush()?;
self.set_cursor()?;
Expand All @@ -150,6 +150,7 @@ impl<'a> Input<'a> {
self.clear_err()?;
self.validate()?;
if self.err.is_none() {
self.update_height(output)?;
return self.handle_submit();
}
}
Expand All @@ -158,6 +159,8 @@ impl<'a> Input<'a> {
if key != Key::Enter {
self.clear_err()?;
}

self.update_height(output)?;
}
}

Expand Down Expand Up @@ -320,6 +323,13 @@ impl<'a> Input<'a> {
.unwrap_or(self.input.len())
}

fn update_height(&mut self, output: String) -> io::Result<()> {
let (height, overflow) = common::get_height(&self.term, output);
self.height = height;
self.overflow = overflow;
Ok(())
}

fn set_cursor(&mut self) -> io::Result<()> {
if !self.placeholder.is_empty() && self.input.is_empty() {
self.term
Expand Down Expand Up @@ -359,6 +369,7 @@ impl<'a> Input<'a> {
}

fn clear(&mut self) -> io::Result<()> {
self.term.move_cursor_up(self.overflow)?;
self.term.clear_to_end_of_screen()?;
self.term.clear_last_lines(self.height)?;
self.height = 0;
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub use spinner::Spinner;
pub use spinner::SpinnerStyle;
pub use theme::Theme;

mod common;
mod confirm;
mod input;
mod multiselect;
Expand Down
14 changes: 12 additions & 2 deletions src/spinner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use console::Term;
use once_cell::sync::Lazy;
use termcolor::{Buffer, WriteColor};

use crate::{theme, Theme};
use crate::{common, theme, Theme};

/// Show a spinner
///
Expand Down Expand Up @@ -36,6 +36,7 @@ pub struct Spinner<'a> {
term: Term,
frame: usize,
height: usize,
overflow: usize,
}

impl<'a> Spinner<'a> {
Expand All @@ -48,6 +49,7 @@ impl<'a> Spinner<'a> {
term: Term::stderr(),
frame: 0,
height: 0,
overflow: 0,
}
}

Expand Down Expand Up @@ -76,14 +78,14 @@ impl<'a> Spinner<'a> {
loop {
self.clear()?;
let output = self.render()?;
self.height = output.lines().count() - 1;
self.term.write_all(output.as_bytes())?;
sleep(self.style.fps);
if handle.is_finished() {
self.clear()?;
self.term.show_cursor()?;
break;
}
self.update_height(output)?;
}
Ok(())
}
Expand All @@ -107,7 +109,15 @@ impl<'a> Spinner<'a> {
Ok(std::str::from_utf8(out.as_slice()).unwrap().to_string())
}

fn update_height(&mut self, output: String) -> io::Result<()> {
let (height, overflow) = common::get_height(&self.term, output);
self.height = height;
self.overflow = overflow;
Ok(())
}

fn clear(&mut self) -> io::Result<()> {
self.term.move_cursor_up(self.overflow)?;
self.term.clear_to_end_of_screen()?;
self.term.clear_last_lines(self.height)?;
self.height = 0;
Expand Down

0 comments on commit 0940523

Please sign in to comment.