use ratatui::text::Span;
#[derive(Debug, Clone, Copy)]
pub(super) struct RenderGeometry {
pub(super) effective_show_ln: bool,
pub(super) ln_gutter: LineNumberGutter,
pub(super) body_width: usize,
pub(super) wrap_body_width: Option<usize>,
pub(super) nowrap_body_width: usize,
}
impl RenderGeometry {
pub(super) fn for_diff(
viewport_width: usize,
show_line_numbers: bool,
stream_mode: bool,
wrap_lines: bool,
max_line_number: usize,
) -> Self {
let wants_ln = show_line_numbers && !stream_mode;
let (effective_show_ln, ln_gutter_width, ln_gutter) =
resolve_ln_gutter(wants_ln, max_line_number, viewport_width);
let body_width = body_width_after_gutter(viewport_width, ln_gutter_width);
Self {
effective_show_ln,
ln_gutter,
body_width,
wrap_body_width: wrap_lines.then_some(body_width),
nowrap_body_width: body_width,
}
}
pub(super) fn for_file_view(
viewport_width: usize,
show_line_numbers: bool,
max_line_number: usize,
) -> Self {
let (effective_show_ln, ln_gutter_width, ln_gutter) =
resolve_ln_gutter(show_line_numbers, max_line_number, viewport_width);
let body_width = body_width_after_gutter(viewport_width, ln_gutter_width);
Self {
effective_show_ln,
ln_gutter,
body_width,
wrap_body_width: Some(body_width),
nowrap_body_width: body_width,
}
}
}
fn body_width_after_gutter(viewport_width: usize, ln_gutter_width: usize) -> usize {
viewport_width.saturating_sub(5 + ln_gutter_width).max(1)
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct LineNumberGutter {
pub total_width: usize,
pub col_width: usize,
}
impl LineNumberGutter {
pub fn single(col_width: usize) -> Self {
Self {
total_width: 1 + col_width + 1,
col_width,
}
}
pub(super) fn blank_span(&self) -> Span<'static> {
Span::raw(" ".repeat(self.total_width))
}
}
pub(crate) fn line_number_digits(max: usize) -> usize {
let mut n = max.max(10);
let mut digits = 0;
while n > 0 {
n /= 10;
digits += 1;
}
digits
}
pub(super) fn resolve_ln_gutter(
show_ln: bool,
max_line_number: usize,
viewport_width: usize,
) -> (bool, usize, LineNumberGutter) {
let digits = line_number_digits(max_line_number);
let raw_width = if show_ln {
LineNumberGutter::single(digits).total_width
} else {
0
};
if show_ln && viewport_width >= 5 + raw_width + 4 {
(true, raw_width, LineNumberGutter::single(digits))
} else {
(false, 0, LineNumberGutter::single(0))
}
}