~hime/linetest

9239b6cdc6b203267405a0c04890078c6790e292 — drbawb 4 years ago 4a1c17e
(ui) input buffer resizing logic

The input buffer consists of the line being edited as well
as the span of space available in the terminal to display the line.
This commit includes basic operations for manipulating the buffer,
including:

- The ability to move the cursor forwards & backwards within
  the range of the edited text (`cursor_left` & `cursor_right`.)

- The ability to render the input buffer at a given position and
  console width with automatic resizing behavior.
2 files changed, 53 insertions(+), 11 deletions(-)

M src/app.rs
M src/main.rs
M src/app.rs => src/app.rs +39 -4
@@ 97,10 97,43 @@ impl InputBuffer {
        // adjust viewspan to match current terminal width (less the prompt)
        if self.span_len() > width_with_prompt {
            // shrink the view span
            self.end -= self.span_len() - width_with_prompt;
            let delta = self.span_len() - width_with_prompt;

            let trailing_width = self.buffer.len() - self.pos;
            
            if self.pos + trailing_width > width_with_prompt {
                let start_to_pos = self.pos - self.start;
                self.start = self.pos;

                if start_to_pos < delta {
                    self.end -= delta - start_to_pos;
                }
            } else {
                self.end -= delta;
            }
        } else if self.span_len() < width_with_prompt {
            // grow the view span
            self.end += width_with_prompt - self.span_len();
            let mut delta = width_with_prompt - self.span_len();

            // consume delta to display tail of the buffer outside the viewport.
            if self.buffer.len() > self.end {
                let overhang = cmp::min(delta, self.buffer.len() - self.end);
                self.end += overhang;
                delta -= overhang;
            }

            // repeat the same for the head of the buffer outside the viewport.
            if self.start > 0 {
                let overhang = cmp::min(delta, self.start);
                self.start -= overhang;
                delta -= overhang;
            }

            // if we still have new columns place them on the end.
            //
            // this should only be the case if the input span is larger than
            // the current buffer.
            self.end += delta;
        }

        // draw status info on line 2


@@ 123,10 156,12 @@ impl InputBuffer {
            .queue(Clear(ClearType::CurrentLine))?
            .queue(Print(prompt.to_string()))?;

        // draw the current viewport
        // render the current viewport & update the cursor
        let beg = self.start;
        let end = cmp::min(self.buffer.len(), self.end);
        let relative_cursor_pos = (self.pos - self.start) + prompt.len() + 1;
        stdout
            .queue(Print(&self.buffer[self.start..]))?
            .queue(Print(&self.buffer[beg..end]))?
            .queue(cursor::MoveToColumn(relative_cursor_pos as u16))?;

        Ok(stdout.flush()?)

M src/main.rs => src/main.rs +14 -7
@@ 16,8 16,19 @@ mod app;


fn main() -> anyhow::Result<()> {

	crossterm::terminal::enable_raw_mode()?;

	let res = std::panic::catch_unwind(|| {
		ui_thread()
	});

	crossterm::terminal::disable_raw_mode()?;
	println!("panic: {:?}", res);
	
	Ok(())
}

fn ui_thread() -> anyhow::Result<()> {
	
	let mut shell = app::Shell::new()?;
	let poll_hz = Duration::from_millis(1000 / 120);


@@ 47,10 58,6 @@ fn main() -> anyhow::Result<()> {
		.execute(LeaveAlternateScreen)?
		.execute(cursor::Show)?;
	crossterm::terminal::disable_raw_mode()?;
	Ok(())
}





	Ok(())
}
\ No newline at end of file