use std::io::Write;
use itertools::Itertools;
use syntect::easy::HighlightLines;
use syntect::highlighting::Style as SyntectStyle;
use syntect::parsing::{SyntaxReference, SyntaxSet};
use unicode_segmentation::UnicodeSegmentation;
use crate::ansi;
use crate::config::{self, delta_unreachable};
use crate::delta::State;
use crate::edits;
use crate::features::line_numbers;
use crate::features::side_by_side::ansifill;
use crate::features::side_by_side::{self, available_line_width, LineSegments, PanelSide};
use crate::minusplus::*;
use crate::paint::superimpose_style_sections::superimpose_style_sections;
use crate::style::Style;
use crate::wrapping::wrap_minusplus_block;
pub struct Painter<'a> {
pub minus_lines: Vec<(String, State)>,
pub plus_lines: Vec<(String, State)>,
pub writer: &'a mut dyn Write,
pub syntax: &'a SyntaxReference,
pub highlighter: Option<HighlightLines<'a>>,
pub config: &'a config::Config,
pub output_buffer: String,
// If config.line_numbers is true, then the following is always Some().
// In side-by-side mode it is always Some (but possibly an empty one), even
// if config.line_numbers is false. See `UseFullPanelWidth` as well.
pub line_numbers_data: Option<line_numbers::LineNumbersData<'a>>,
}
// How the background of a line is filled up to the end
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum BgFillMethod {
// Fill the background with ANSI spaces if possible,
// but might fallback to Spaces (e.g. in the left side-by-side panel),
// also see `UseFullPanelWidth`
TryAnsiSequence,
Spaces,
}
// If the background of a line extends to the end, and if configured to do so, how.
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum BgShouldFill {
With(BgFillMethod),
No,
}
impl Default for BgShouldFill {
fn default() -> Self {
BgShouldFill::With(BgFillMethod::TryAnsiSequence)
}
}
impl<'a> Painter<'a> {
pub fn new(writer: &'a mut dyn Write, config: &'a config::Config) -> Self {
let default_syntax = Self::get_syntax(&config.syntax_set, None);
let panel_width_fix = ansifill::UseFullPanelWidth::new(config);
let line_numbers_data = if config.line_numbers {
Some(line_numbers::LineNumbersData::from_format_strings(
&config.line_numbers_format,
panel_width_fix,
))
} else if config.side_by_side {
// If line numbers are disabled in side-by-side then the data is still used
// for width calculaction and to pad odd width to even, see `UseFullPanelWidth