fn generate_text(
        app_info: &mut Data,
        bytes_per_line: usize,
        lines_per_screen: usize,
    ) -> (Text, Text, Text) {
        let content_lines = app_info.contents.len() / bytes_per_line + 1;
        let start_row = app_info.start_address / bytes_per_line;

        // Generate address lines
        let address_text = (0..cmp::min(lines_per_screen, content_lines - start_row))
            .map(|i| {
                let row_address = app_info.start_address + i * bytes_per_line;
                let mut span = Span::from(format!("{row_address:08X?}\n"));
                // Highlight the address row that the cursor is in for visibility
                if (row_address..row_address + bytes_per_line).contains(&app_info.offset) {
                    span.style = span.style.fg(Color::Black).bg(Color::White);
                }
                Line::from(span)
            })
            .collect::<Vec<Line>>();

        let hex_text = generate_hex(app_info, bytes_per_line, lines_per_screen);
        let decoded_text = generate_decoded(app_info, bytes_per_line, lines_per_screen);

        (address_text.into(), hex_text.into(), decoded_text.into())
    }
Generates all the visuals of the file contents to be displayed to user by calling
[`generate_hex`] and [`generate_decoded`].
src/screen.rs