pub(crate) fn write_lines(
    out: &mut impl io::Write,
    mut pager: &mut Pager,
) -> Result<(), AlternateScreenPagingError> {
    let line_count = pager.num_lines();
    // Reduce one row for prompt
    let rows = pager.rows.saturating_sub(1);
    //
    // Calculate the lower_mark by adding either the rows or line_count depending
    // on the minimality
    let lower_mark = pager.upper_mark.saturating_add(rows.min(line_count));

    // If lower_mark is more than line_count, there could be two cases
    if lower_mark > line_count {
        // There is not enough text to fill even a single page.
        // In this case, set upper_mark = 0
        pager.upper_mark = if line_count < pager.rows {
            0
        } else {
            // Else we set it to line_count - rows, equalling to the upper_mark of last page
            line_count.saturating_sub(rows)
        };
    }

    // We use the `Iterator::skip` and `Iterator::take` method extensively in this
    // block
    // This may be too high but the `Iterator::take` call below will limit this
    // anyway while allowing us to display as much lines as possible.

    let displayed_lines = match pager.line_numbers {
        LineNumbers::AlwaysOff | LineNumbers::Disabled => {
            // Get the unnested (flattened) lines and display them
            #[cfg_attr(not(feature = "search"), allow(unused_mut))]
            let mut lines = pager
                .get_flattened_lines()
                .skip(pager.upper_mark)
                .take(rows.min(line_count))
                .collect::<Vec<String>>();
            // If search is enabled and there is a query, then highlight the matches
            #[cfg(feature = "search")]
            if let Some(st) = &pager.search_term {
                for mut line in &mut lines {
                    highlight_line_matches(&mut line, st);
                }
            }
            lines
        }
        LineNumbers::AlwaysOn | LineNumbers::Enabled => {
            // Compute the length of a number as a string without allocating.
            //
            // While this may in theory lose data, it will only do so if
            // `line_count` is bigger than 2^52, which will probably never
            // happen. Let's worry about that only if someone reports a bug
            // for it.
            #[allow(
                clippy::cast_possible_truncation,
                clippy::cast_sign_loss,
                clippy::cast_precision_loss
            )]
            let len_line_number = (line_count as f64).log10().floor() as usize + 1;
            // Get the line number annotated lines, optionally with search highlights, if
            // there is a search query
            annotate_line_numbers(
                pager.get_lines(),
                len_line_number,
                pager.cols,
                #[cfg(feature = "search")]
                &pager.search_term,
            )
            .iter()
            .skip(pager.upper_mark)
            .take(rows.min(line_count))
            .map(ToOwned::to_owned)
            .collect()
        }
    };
    // Join the lines and display them at once
    // This is because, writing to console is slow
    //
    // Add \r to ensure cursor is placed at the beginning of each row
    writeln!(out, "\r{}", displayed_lines.join("\n\r"))?;

    Ok(())
}
// Write the lines to the terminal
Write the lines to the terminal
Write the lines to the terminal
pub(crate) fn write_lines(
    out: &mut impl io::Write,
    mut pager: &mut Pager,
) -> Result<(), AlternateScreenPagingError> {
    let line_count = pager.num_lines();
    // Reduce one row for prompt
    let rows = pager.rows.saturating_sub(1);
    //
    // Calculate the lower_mark by adding either the rows or line_count depending
    // on the minimality
    let lower_mark = pager.upper_mark.saturating_add(rows.min(line_count));
    // If lower_mark is more than line_count, there could be two cases
    if lower_mark > line_count {
        // There is not enough text to fill even a single page.
        // In this case, set upper_mark = 0
        pager.upper_mark = if line_count < pager.rows {
            0
        } else {
            // Else we set it to line_count - rows, equalling to the upper_mark of last page
            line_count.saturating_sub(rows)
        };
    }
    // We use the `Iterator::skip` and `Iterator::take` method extensively in this
    // block
    // This may be too high but the `Iterator::take` call below will limit this
    // anyway while allowing us to display as much lines as possible.
    let displayed_lines = match pager.line_numbers {
        LineNumbers::AlwaysOff | LineNumbers::Disabled => {
            // Get the unnested (flattened) lines and display them
            #[cfg_attr(not(feature = "search"), allow(unused_mut))]
            let mut lines = pager
                .get_flattened_lines()
                .skip(pager.upper_mark)
                .take(rows.min(line_count))
                .collect::<Vec<String>>();
            // If search is enabled and there is a query, then highlight the matches
            #[cfg(feature = "search")]
            if let Some(st) = &pager.search_term {
                for mut line in &mut lines {
                    highlight_line_matches(&mut line, st);
                }
            }
            lines
        }
        LineNumbers::AlwaysOn | LineNumbers::Enabled => {
            // Compute the length of a number as a string without allocating.
            //
            // While this may in theory lose data, it will only do so if
            // `line_count` is bigger than 2^52, which will probably never
            // happen. Let's worry about that only if someone reports a bug
            // for it.
            #[allow(
                clippy::cast_possible_truncation,
                clippy::cast_sign_loss,
                clippy::cast_precision_loss
            )]
            let len_line_number = (line_count as f64).log10().floor() as usize + 1;
            // Get the line number annotated lines, optionally with search highlights, if
            // there is a search query
            annotate_line_numbers(
                pager.get_lines(),
                len_line_number,
                pager.cols,
                #[cfg(feature = "search")]
                &pager.search_term,
            )
            .iter()
            .skip(pager.upper_mark)
            .take(rows.min(line_count))
            .map(ToOwned::to_owned)
            .collect()
        }
    };
    // Join the lines and display them at once
    // This is because, writing to console is slow
    //
    // Add \r to ensure cursor is placed at the beginning of each row
    writeln!(out, "\r{}", displayed_lines.join("\n\r"))?;
    Ok(())
}
pub ( crate ) fn write_lines ( out : & mut impl io :: Write , mut pager : & mut Pager , ) -> Result < ( ) , AlternateScreenPagingError > { let line_count = pager . num_lines ( ) ; // Reduce one row for prompt let rows = pager . rows . saturating_sub ( 1 ) ; // // Calculate the lower_mark by adding either the rows or line_count depending // on the minimality let lower_mark = pager . upper_mark . saturating_add ( rows . min ( line_count ) ) ; // If lower_mark is more than line_count, there could be two cases if lower_mark > line_count { // There is not enough text to fill even a single page. // In this case, set upper_mark = 0 pager . upper_mark = if line_count < pager . rows { 0 } else { // Else we set it to line_count - rows, equalling to the upper_mark of last page line_count . saturating_sub ( rows ) } ; } // We use the `Iterator::skip` and `Iterator::take` method extensively in this // block // This may be too high but the `Iterator::take` call below will limit this // anyway while allowing us to display as much lines as possible. let displayed_lines = match pager . line_numbers { LineNumbers :: AlwaysOff | LineNumbers :: Disabled => { // Get the unnested (flattened) lines and display them # [ cfg_attr ( not ( feature " " ) allow ( unused_mut ) ) ] let mut lines = pager . get_flattened_lines ( ) . skip ( pager . upper_mark ) . take ( rows . min ( line_count ) ) . collect :: < Vec < String > > ( ) ; // If search is enabled and there is a query, then highlight the matches # [ cfg ( feature " " ) ] if let Some ( st ) = & pager . search_term { for mut line in & mut lines { highlight_line_matches ( & mut line , st ) ; } } lines } LineNumbers :: AlwaysOn | LineNumbers :: Enabled => { // Compute the length of a number as a string without allocating. // // While this may in theory lose data, it will only do so if // `line_count` is bigger than 2^52, which will probably never // happen. Let's worry about that only if someone reports a bug // for it. # [ allow ( clippy cast_possible_truncation clippy cast_sign_loss clippy cast_precision_loss ) ] let len_line_number = ( line_count as f64 ) . log10 ( ) . floor ( ) as usize + 1 ; // Get the line number annotated lines, optionally with search highlights, if // there is a search query annotate_line_numbers ( pager . get_lines ( ) , len_line_number , pager . cols , # [ cfg ( feature " " ) ] & pager . search_term , ) . iter ( ) . skip ( pager . upper_mark ) . take ( rows . min ( line_count ) ) . map ( ToOwned :: to_owned ) . collect ( ) } } ; // Join the lines and display them at once // This is because, writing to console is slow // // Add \r to ensure cursor is placed at the beginning of each row writeln ! ( out " \r " displayed_lines join ( " \n \r " ) ) ? ; Ok ( ( ) ) }
Write the lines to the terminal
Write the lines to the terminal
out
&mut impl io::Write
pager
&mut Pager
out
&mut impl io::Write
pager
&mut Pager