summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Otto <th1000s@posteo.net>2021-01-30 12:05:41 +0100
committerDan Davison <dandavison7@gmail.com>2021-09-19 19:39:50 -0400
commitdb04d5e4ec02ea30e208c64f6f77e1cbfccb2688 (patch)
tree812b4bc6e5b4a7ae46e78d62320b76eb407e4ec7
parentceab1baa9382676bb4916ed9378065863d2e16de (diff)
General PlusMinus data structure
Can be indexed with Minus/Plus or in a side-by-side context with Left/Right to represent the left/right Panels.
-rw-r--r--src/config.rs2
-rw-r--r--src/features/line_numbers.rs57
-rw-r--r--src/features/side_by_side.rs85
-rw-r--r--src/main.rs1
-rw-r--r--src/paint.rs21
-rw-r--r--src/plusminus.rs51
6 files changed, 147 insertions, 70 deletions
diff --git a/src/config.rs b/src/config.rs
index 326153b2..1b035f2b 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -166,7 +166,7 @@ impl From<cli::Opt> for Config {
process::exit(1);
});
- let side_by_side_data = side_by_side::SideBySideData::new(
+ let side_by_side_data = side_by_side::SideBySideData::new_sbs(
&opt.computed.decorations_width,
&opt.computed.available_terminal_width,
);
diff --git a/src/features/line_numbers.rs b/src/features/line_numbers.rs
index c464f8c7..3032bc00 100644
--- a/src/features/line_numbers.rs
+++ b/src/features/line_numbers.rs
@@ -6,9 +6,10 @@ use regex::Regex;
use crate::config;
use crate::delta::State;
use crate::features::hyperlinks;
-use crate::features::side_by_side;
+use crate::features::side_by_side::PanelSide;
use crate::features::OptionValueFunction;
use crate::format;
+use crate::plusminus::*;
use crate::style::Style;
pub fn make_feature() -> Vec<(String, OptionValueFunction)> {
@@ -65,11 +66,11 @@ pub fn make_feature() -> Vec<(String, OptionValueFunction)> {
pub fn format_and_paint_line_numbers<'a>(
line_numbers_data: &'a mut LineNumbersData,
state: &State,
- side_by_side_panel: Option<side_by_side::PanelSide>,
+ side_by_side_panel: Option<PanelSide>,
config: &'a config::Config,
) -> Vec<ansi_term::ANSIGenericString<'a, str>> {
- let m_ref = &mut line_numbers_data.hunk_minus_line_number;
- let p_ref = &mut line_numbers_data.hunk_plus_line_number;
+ let nr_left = line_numbers_data.line_number[Minus];
+ let nr_right = line_numbers_data.line_number[Plus];
let (minus_style, zero_style, plus_style) = (
config.line_numbers_minus_style,
config.line_numbers_zero_style,
@@ -77,20 +78,17 @@ pub fn format_and_paint_line_numbers<'a>(
);
let ((minus_number, plus_number), (minus_style, plus_style)) = match state {
State::HunkMinus(_) => {
- let m = *m_ref;
- *m_ref += 1;
- ((Some(m), None), (minus_style, plus_style))
+ line_numbers_data.line_number[Minus] += 1;
+ ((Some(nr_left), None), (minus_style, plus_style))
}
State::HunkZero => {
- let (m, p) = (*m_ref, *p_ref);
- *m_ref += 1;
- *p_ref += 1;
- ((Some(m), Some(p)), (zero_style, zero_style))
+ line_numbers_data.line_number[Minus] += 1;
+ line_numbers_data.line_number[Plus] += 1;
+ ((Some(nr_left), Some(nr_right)), (zero_style, zero_style))
}
State::HunkPlus(_) => {
- let p = *p_ref;
- *p_ref += 1;
- ((None, Some(p)), (minus_style, plus_style))
+ line_numbers_data.line_number[Plus] += 1;
+ ((None, Some(nr_right)), (minus_style, plus_style))
}
_ => return Vec::new(),
};
@@ -99,14 +97,14 @@ pub fn format_and_paint_line_numbers<'a>(
let (emit_left, emit_right) = match (config.side_by_side, side_by_side_panel) {
(false, _) => (true, true),
- (true, Some(side_by_side::PanelSide::Left)) => (true, false),
- (true, Some(side_by_side::PanelSide::Right)) => (false, true),
+ (true, Some(PanelSide::Left)) => (true, false),
+ (true, Some(PanelSide::Right)) => (false, true),
(true, None) => unreachable!(),
};
if emit_left {
formatted_numbers.extend(format_and_paint_line_number_field(
- &line_numbers_data.left_format_data,
+ &line_numbers_data.format_data[PanelSide::Left],
&config.line_numbers_left_style,
minus_number,
plus_number,
@@ -120,7 +118,7 @@ pub fn format_and_paint_line_numbers<'a>(
if emit_right {
formatted_numbers.extend(format_and_paint_line_number_field(
- &line_numbers_data.right_format_data,
+ &line_numbers_data.format_data[PanelSide::Right],
&config.line_numbers_right_style,
minus_number,
plus_number,
@@ -140,10 +138,8 @@ lazy_static! {
#[derive(Default)]
pub struct LineNumbersData<'a> {
- pub left_format_data: format::FormatStringData<'a>,
- pub right_format_data: format::FormatStringData<'a>,
- pub hunk_minus_line_number: usize,
- pub hunk_plus_line_number: usize,
+ pub format_data: PlusMinus<format::FormatStringData<'a>>,
+ pub line_number: PlusMinus<usize>,
pub hunk_max_line_number_width: usize,
pub plus_file: String,
}
@@ -153,16 +149,11 @@ pub struct LineNumbersData<'a> {
impl<'a> LineNumbersData<'a> {
pub fn from_format_strings(left_format: &'a str, right_format: &'a str) -> LineNumbersData<'a> {
Self {
- left_format_data: format::parse_line_number_format(
- left_format,
- &*LINE_NUMBERS_PLACEHOLDER_REGEX,
+ format_data: PlusMinus::new(
+ format::parse_line_number_format(left_format, &*LINE_NUMBERS_PLACEHOLDER_REGEX),
+ format::parse_line_number_format(right_format, &*LINE_NUMBERS_PLACEHOLDER_REGEX),
),
- right_format_data: format::parse_line_number_format(
- right_format,
- &*LINE_NUMBERS_PLACEHOLDER_REGEX,
- ),
- hunk_minus_line_number: 0,
- hunk_plus_line_number: 0,
+ line_number: PlusMinus::new(0, 0),
hunk_max_line_number_width: 0,
plus_file: "".to_string(),
}
@@ -172,8 +163,8 @@ impl<'a> LineNumbersData<'a> {
pub fn initialize_hunk(&mut self, line_numbers: &[(usize, usize)], plus_file: String) {
// Typically, line_numbers has length 2: an entry for the minus file, and one for the plus
// file. In the case of merge commits, it may be longer.
- self.hunk_minus_line_number = line_numbers[0].0;
- self.hunk_plus_line_number = line_numbers[line_numbers.len() - 1].0;
+ self.line_number =
+ PlusMinus::new(line_numbers[0].0, line_numbers[line_numbers.len() - 1].0);
let hunk_max_line_number = line_numbers.iter().map(|(n, d)| n + d).max().unwrap();
self.hunk_max_line_number_width =
1 + (hunk_max_line_number as f64).log10().floor() as usize;
diff --git a/src/features/side_by_side.rs b/src/features/side_by_side.rs
index 77f48933..ae5911ef 100644
--- a/src/features/side_by_side.rs
+++ b/src/features/side_by_side.rs
@@ -1,3 +1,5 @@
+use std::ops::{Index, IndexMut};
+
use itertools::Itertools;
use syntect::highlighting::Style as SyntectStyle;
@@ -8,6 +10,7 @@ use crate::delta::State;
use crate::features::line_numbers;
use crate::features::OptionValueFunction;
use crate::paint::Painter;
+use crate::plusminus::*;
use crate::style::Style;
pub fn make_feature() -> Vec<(String, OptionValueFunction)> {
@@ -24,49 +27,67 @@ pub fn make_feature() -> Vec<(String, OptionValueFunction)> {
])
}
+pub struct Panel {
+ pub width: usize,
+ pub offset: usize,
+}
+
+// Same as plusminus::PlusMinusIndex but with Left/Right instead
+// of Minus/Plus enum names. Only used in a side-by-side context.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PanelSide {
Left,
Right,
}
-pub struct SideBySideData {
- pub left_panel: Panel,
- pub right_panel: Panel,
+use PanelSide::*;
+
+impl<T> Index<PanelSide> for PlusMinus<T> {
+ type Output = T;
+ fn index(&self, side: PanelSide) -> &Self::Output {
+ match side {
+ PanelSide::Left => &self.minus,
+ PanelSide::Right => &self.plus,
+ }
+ }
}
-pub struct Panel {
- pub width: usize,
- pub offset: usize,
+impl<T> IndexMut<PanelSide> for PlusMinus<T> {
+ fn index_mut(&mut self, side: PanelSide) -> &mut Self::Output {
+ match side {
+ PanelSide::Left => &mut self.minus,
+ PanelSide::Right => &mut self.plus,
+ }
+ }
}
+pub type SideBySideData = PlusMinus<Panel>;
+
impl SideBySideData {
- pub fn new(decorations_width: &cli::Width, available_terminal_width: &usize) -> Self {
+ pub fn new_sbs(decorations_width: &cli::Width, available_terminal_width: &usize) -> Self {
let panel_width = match decorations_width {
cli::Width::Fixed(w) => w / 2,
_ => available_terminal_width / 2,
};
- Self {
- left_panel: Panel {
+ SideBySideData::new(
+ Panel {
width: panel_width,
offset: 0,
},
- right_panel: Panel {
+ Panel {
width: panel_width,
offset: 0,
},
- }
+ )
}
}
/// Emit a sequence of minus and plus lines in side-by-side mode.
#[allow(clippy::too_many_arguments)]
pub fn paint_minus_and_plus_lines_side_by_side<'a>(
- minus_syntax_style_sections: Vec<Vec<(SyntectStyle, &str)>>,
- minus_diff_style_sections: Vec<Vec<(Style, &str)>>,
- minus_states: Vec<&'a State>,
- plus_syntax_style_sections: Vec<Vec<(SyntectStyle, &str)>>,
- plus_diff_style_sections: Vec<Vec<(Style, &str)>>,
- plus_states: Vec<&'a State>,
+ syntax_left_right: PlusMinus<Vec<Vec<(SyntectStyle, &str)>>>,
+ diff_left_right: PlusMinus<Vec<Vec<(Style, &str)>>>,
+ states_left_right: PlusMinus<Vec<&'a State>>,
line_alignment: Vec<(Option<usize>, Option<usize>)>,
output_buffer: &mut String,
config: &Config,
@@ -76,10 +97,10 @@ pub fn paint_minus_and_plus_lines_side_by_side<'a>(
for (minus_line_index, plus_line_index) in line_alignment {
output_buffer.push_str(&paint_left_panel_minus_line(
minus_line_index,
- &minus_syntax_style_sections,
- &minus_diff_style_sections,
+ &syntax_left_right[Left],
+ &diff_left_right[Left],
match minus_line_index {
- Some(i) => minus_states[i],
+ Some(i) => states_left_right[Left][i],
None => &State::HunkMinus(None),
},
line_numbers_data,
@@ -93,10 +114,10 @@ pub fn paint_minus_and_plus_lines_side_by_side<'a>(
));
output_buffer.push_str(&paint_right_panel_plus_line(
plus_line_index,
- &plus_syntax_style_sections,
- &plus_diff_style_sections,
+ &syntax_left_right[Right],
+ &diff_left_right[Right],
match plus_line_index {
- Some(i) => plus_states[i],
+ Some(i) => states_left_right[Right][i],
None => &State::HunkPlus(None),
},
line_numbers_data,
@@ -140,8 +161,8 @@ pub fn paint_zero_lines_side_by_side(
// TODO: Avoid doing the superimpose_style_sections work twice.
// HACK: These are getting incremented twice, so knock them back down once.
if let Some(d) = line_numbers_data.as_mut() {
- d.hunk_minus_line_number -= 1;
- d.hunk_plus_line_number -= 1;
+ d.line_number[Left] -= 1;
+ d.line_number[Right] -= 1;
}
right_pad_left_panel_line(
&mut left_panel_line,
@@ -194,7 +215,7 @@ fn paint_left_panel_minus_line<'a>(
diff_style_sections,
state,
line_numbers_data,
- PanelSide::Left,
+ Left,
painted_prefix,
config,
);
@@ -228,7 +249,7 @@ fn paint_right_panel_plus_line<'a>(
diff_style_sections,
state,
line_numbers_data,
- PanelSide::Right,
+ Right,
painted_prefix,
config,
);
@@ -341,12 +362,12 @@ fn paint_minus_or_plus_panel_line(
(s, t) if s == t => {}
(State::HunkPlus(_), State::HunkMinus(_)) => {
if let Some(d) = line_numbers_data.as_mut() {
- d.hunk_minus_line_number -= 1;
+ d.line_number[Left] -= 1;
}
}
(State::HunkMinus(_), State::HunkPlus(_)) => {
if let Some(d) = line_numbers_data.as_mut() {
- d.hunk_plus_line_number -= 1;
+ d.line_number[Right] -= 1;
}
}
_ => unreachable!(),
@@ -385,7 +406,7 @@ fn right_pad_left_panel_line(
};
// Pad with (maybe painted) spaces to the panel width.
let text_width = ansi::measure_text_width(panel_line);
- let panel_width = config.side_by_side_data.left_panel.width;
+ let panel_width = config.side_by_side_data[Left].width;
if text_width < panel_width {
let fill_style = get_right_fill_style_for_left_panel(
panel_line_is_empty,
@@ -420,8 +441,8 @@ fn right_fill_right_panel_line(
config: &Config,
) {
*panel_line = ansi::truncate_str(
- panel_line,
- config.side_by_side_data.right_panel.width,
+ &panel_line,
+ config.side_by_side_data[Right].width,
&config.truncation_symbol,
)
.to_string();
diff --git a/src/main.rs b/src/main.rs
index 08d31fd8..1fdf9365 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -20,6 +20,7 @@ mod handlers;
mod options;
mod paint;
mod parse_style;
+mod plusminus;
mod style;
mod subcommands;
mod syntect_color;
diff --git a/src/paint.rs b/src/paint.rs
index a575d3bf..7b31047d 100644
--- a/src/paint.rs
+++ b/src/paint.rs
@@ -12,7 +12,9 @@ use crate::delta::State;
use crate::edits;
use crate::features::line_numbers;
use crate::features::side_by_side;
+use crate::features::side_by_side::PanelSide;
use crate::paint::superimpose_style_sections::superimpose_style_sections;
+use crate::plusminus::*;
use crate::style::Style;
pub struct Painter<'a> {
@@ -138,13 +140,24 @@ impl<'a> Painter<'a> {
Self::get_diff_style_sections(&self.minus_lines, &self.plus_lines, self.config);
if self.config.side_by_side {
- side_by_side::paint_minus_and_plus_lines_side_by_side(
+ let syntax_left_right = PlusMinus::new(
minus_line_syntax_style_sections,
- minus_line_diff_style_sections,
- self.minus_lines.iter().map(|(_, state)| state).collect(),
plus_line_syntax_style_sections,
+ );
+ let diff_left_right = PlusMinus::new(
+ minus_line_diff_style_sections,
plus_line_diff_style_sections,
+ );
+
+ let states_left_right = PlusMinus::new(
+ self.minus_lines.iter().map(|(_, state)| state).collect(),
self.plus_lines.iter().map(|(_, state)| state).collect(),
+ );
+
+ side_by_side::paint_minus_and_plus_lines_side_by_side(
+ syntax_left_right,
+ diff_left_right,
+ states_left_right,
line_alignment,
&mut self.output_buffer,
self.config,
@@ -405,7 +418,7 @@ impl<'a> Painter<'a> {
diff_sections: &[(Style, &str)],
state: &State,
line_numbers_data: &mut Option<&mut line_numbers::LineNumbersData>,
- side_by_side_panel: Option<side_by_side::PanelSide>,
+ side_by_side_panel: Option<PanelSide>,
painted_prefix: Option<ansi_term::ANSIString>,
config: &config::Config,
) -> (String, bool) {
diff --git a/src/plusminus.rs b/src/plusminus.rs
new file mode 100644
index 00000000..0cdeaea9
--- /dev/null
+++ b/src/plusminus.rs
@@ -0,0 +1,51 @@
+use std::ops::{Index, IndexMut};
+
+// Struct to represent data related to removed/minus and added/plus lines
+// which can be indexed with PlusMinusIndex::{Minus, Plus}.
+#[derive(Debug, PartialEq, Eq)]
+pub struct PlusMinus<T> {
+ pub minus: T,
+ pub plus: T,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum PlusMinusIndex {
+ Minus,
+ Plus,
+}
+
+pub use PlusMinusIndex::*;
+
+impl<T> Index<PlusMinusIndex> for PlusMinus<T> {
+ type Output = T;
+ fn index(&self, side: PlusMinusIndex) -> &Self::Output {
+ match side {
+ Minus => &self.minus,
+ Plus => &self.plus,
+ }
+ }
+}
+
+impl<T> IndexMut<PlusMinusIndex> for PlusMinus<T> {
+ fn index_mut(&mut self, side: PlusMinusIndex) -> &mut Self::Output {
+ match side {
+ Minus => &mut self.minus,
+ Plus => &mut self.plus,
+ }
+ }
+}
+
+impl<T> PlusMinus<T> {
+ pub fn new(minus: T, plus: T) -> Self {
+ PlusMinus { minus, plus }
+ }
+}
+
+impl<T: Default> Default for PlusMinus<T> {
+ fn default() -> Self {
+ Self {
+ minus: T::default(),
+ plus: T::default(),
+ }
+ }
+}