use syntect::highlighting::Style as SyntectStyle;
use unicode_segmentation::UnicodeSegmentation;
use crate::config::INLINE_SYMBOL_WIDTH_1;
use crate::config::Config;
use crate::delta::DiffType;
use crate::delta::State;
use crate::features::line_numbers::{self, SideBySideLineWidth};
use crate::features::side_by_side::{available_line_width, line_is_too_long, Left, Right};
use crate::minusplus::*;
use crate::paint::LineSections;
use crate::style::Style;
/// See [`wrap_line`] for documentation.
#[derive(Clone, Debug)]
pub struct WrapConfig {
pub left_symbol: String,
pub right_symbol: String,
pub right_prefix_symbol: String,
// In fractions of 1000 so that a >100 wide panel can
// still be configured down to a single character.
pub use_wrap_right_permille: usize,
// This value is --wrap-max-lines + 1, and unlimited is 0, see
// adapt_wrap_max_lines_argument()
pub max_lines: usize,
pub inline_hint_syntect_style: SyntectStyle,
}
#[derive(PartialEq)]
enum Stop {
StackEmpty,
LineLimit,
}
/// Wrap the given `line` if it is longer than `line_width`. Wrap to at most
/// [Config::WrapConfig::max_lines](WrapConfig::max_lines) lines,
/// then truncate again - but never truncate if it is `0`. Place
/// [left_symbol](WrapConfig::left_symbol) at the end of wrapped lines.
/// If wrapping results in only *one* extra line and if the width of the wrapped
/// line is less than [use_wrap_right_permille](WrapConfig::use_wrap_right_permille)
/// then right-align the second line and use the symbols
/// [right_symbol](WrapConfig::right_symbol) and
/// on the next line [right_prefix_symbol](WrapConfig::right_prefix_symbol).
/// The inserted characters will follow the
/// [inline_hint_syntect_style](WrapConfig::inline_hint_syntect_style).
pub fn wrap_line<'a, I, S>(
config: &'a Config,
line: I,
line_width: usize,
fill_style: &S,
inline_hint_style: &Option<S>,
) -> Vec<LineSections<'a, S>>
where
I: IntoIterator<Item = (S, &'a str)> + std::fmt::Debug,
<I as IntoIterator>::IntoIter: DoubleEndedIterator,
S: Copy + Default + std::fmt::Debug,
{
let mut result = Vec::new();
let wrap_config = &config.wrap_config;
// The current line being assembled from the input to fit exactly into the given width.
// A somewhat leaky abstraction as the fields are also accessed directly.
struct CurrLine<'a, S: Default> {
line_segments: LineSections<'a, S>,
len: usize,
}
impl<'a, S: Default> CurrLine<'a, S> {
fn reset() -> Self {
CurrLine {
line_segments: Vec::new(),
len: 0,
}
}
fn push_and_set_len(&mut self, text: (S, &'a str), len: