Skip to content

Commit

Permalink
Add side-by-side line wrapping mode
Browse files Browse the repository at this point in the history
If the current line does not fit into the panel, then
it is not truncated but split into multiple lines. A
wrapping symbol is placed at the end of the line. If
the new line is short enought, it is right-aligned.

Wrapping is limited to a certain number of lines, if this
is exceeded the line is truncated by a now highlighted
truncation symbol.

Commandline argument `-S` / `--side-by-side-wrapped`.

Also adapted `--keep-plus-minus-markers` logic, required
to calculate the exact remaining panel width.
  • Loading branch information
th1000s committed Apr 12, 2021
1 parent b8600f3 commit 5542912
Show file tree
Hide file tree
Showing 14 changed files with 1,073 additions and 35 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ itertools = "0.10.0"
lazy_static = "1.4"
regex = "1.4.5"
shell-words = "1.0.0"
static_assertions = "1.1.0"
structopt = "0.3.21"
unicode-segmentation = "1.7.1"
unicode-width = "0.1.8"
Expand Down
1 change: 1 addition & 0 deletions src/ansi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use iterator::{AnsiElementIterator, Element};
pub const ANSI_CSI_CLEAR_TO_EOL: &str = "\x1b[0K";
pub const ANSI_CSI_CLEAR_TO_BOL: &str = "\x1b[1K";
pub const ANSI_SGR_RESET: &str = "\x1b[0m";
pub const ANSI_SGR_REVERSE: &str = "\x1b[7m";

pub fn strip_ansi_codes(s: &str) -> String {
strip_ansi_codes_from_strings_iterator(ansi_strings_iterator(s))
Expand Down
4 changes: 4 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,10 @@ pub struct Opt {
#[structopt(short = "s", long = "side-by-side")]
pub side_by_side: bool,

/// Display a side-by-side diff and wrap overlong lines instead of truncating them.
#[structopt(short = "S", long = "side-by-side-wrapped")]
pub side_by_side_wrapped: bool,

#[structopt(long = "diff-highlight")]
/// Emulate diff-highlight (https://github.com/git/git/tree/master/contrib/diff-highlight)
pub diff_highlight: bool,
Expand Down
30 changes: 29 additions & 1 deletion src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@ use syntect::highlighting::Style as SyntectStyle;
use syntect::highlighting::Theme as SyntaxTheme;
use syntect::parsing::SyntaxSet;

use crate::ansi;
use crate::bat_utils::output::PagingMode;
use crate::cli;
use crate::color;
use crate::delta::State;
use crate::env;
use crate::features::navigate;
use crate::features::side_by_side;
use crate::features::side_by_side_wrap;
use crate::git_config::GitConfigEntry;
use crate::style::{self, Style};
use crate::syntect_color;

pub struct Config {
pub available_terminal_width: usize,
Expand All @@ -39,6 +42,7 @@ pub struct Config {
pub hunk_header_style_include_line_number: bool,
pub hyperlinks: bool,
pub hyperlinks_file_link_format: String,
pub inline_hint_color: Option<SyntectStyle>,
pub inspect_raw_lines: cli::InspectRawLines,
pub keep_plus_minus_markers: bool,
pub line_numbers: bool,
Expand Down Expand Up @@ -72,6 +76,7 @@ pub struct Config {
pub git_plus_style: Style,
pub show_themes: bool,
pub side_by_side: bool,
pub side_by_side_wrapped: bool,
pub side_by_side_data: side_by_side::SideBySideData,
pub syntax_dummy_theme: SyntaxTheme,
pub syntax_set: SyntaxSet,
Expand All @@ -81,6 +86,7 @@ pub struct Config {
pub true_color: bool,
pub truncation_symbol: String,
pub whitespace_error_style: Style,
pub wrap_config: side_by_side_wrap::WrapConfig,
pub zero_style: Style,
}

Expand Down Expand Up @@ -205,6 +211,11 @@ impl From<cli::Opt> for Config {
hyperlinks: opt.hyperlinks,
hyperlinks_file_link_format: opt.hyperlinks_file_link_format,
inspect_raw_lines: opt.computed.inspect_raw_lines,
inline_hint_color: Some(SyntectStyle {
// TODO: color from theme?
foreground: syntect_color::syntect_color_from_ansi_name("blue").unwrap(),
..SyntectStyle::default()
}),
keep_plus_minus_markers: opt.keep_plus_minus_markers,
line_numbers: opt.line_numbers,
line_numbers_left_format: opt.line_numbers_left_format,
Expand Down Expand Up @@ -237,14 +248,31 @@ impl From<cli::Opt> for Config {
git_plus_style,
show_themes: opt.show_themes,
side_by_side: opt.side_by_side,
side_by_side_wrapped: opt.side_by_side_wrapped,
side_by_side_data,
syntax_dummy_theme: SyntaxTheme::default(),
syntax_set: opt.computed.syntax_set,
syntax_theme: opt.computed.syntax_theme,
tab_width: opt.tab_width,
tokenization_regex,
true_color: opt.computed.true_color,
truncation_symbol: "→".to_string(),
truncation_symbol: {
let sym = "→";
if opt.side_by_side_wrapped {
format!("{}{}{}", ansi::ANSI_SGR_REVERSE, sym, ansi::ANSI_SGR_RESET)
} else {
sym.to_string()
}
},
wrap_config: side_by_side_wrap::WrapConfig {
wrap_symbol: "↵".to_string(),
wrap_right_symbol: "↴".to_string(),
right_align_symbol: "…".to_string(),
// TODO, support multi-character symbols, and thus store
// right_align_symbol_len here?
use_wrap_right_permille: 370,
max_lines: 3,
},
whitespace_error_style,
zero_style,
}
Expand Down
4 changes: 4 additions & 0 deletions src/delta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ pub enum State {
HunkMinus(Option<String>), // In hunk; removed line (raw_line)
HunkPlus(Option<String>), // In hunk; added line (raw_line)
Unknown,
// The following elements are created when a line is wrapped to display it:
HunkZeroWrapped, // Wrapped unchanged line in side-by-side mode
HunkMinusWrapped, // Wrapped removed line in side-by-side mode
HunkPlusWrapped, // Wrapped added line in side-by-side mode
}

#[derive(Debug, PartialEq)]
Expand Down
5 changes: 4 additions & 1 deletion src/features/line_numbers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,15 +83,18 @@ pub fn format_and_paint_line_numbers<'a>(
line_numbers_data.line_number[Left] += 1;
((Some(nr_left), None), (minus_style, plus_style))
}
State::HunkMinusWrapped => ((None, None), (minus_style, plus_style)),
State::HunkZero => {
line_numbers_data.line_number[Left] += 1;
line_numbers_data.line_number[Right] += 1;
((Some(nr_left), Some(nr_right)), (zero_style, zero_style))
}
State::HunkZeroWrapped => ((None, None), (zero_style, zero_style)),
State::HunkPlus(_) => {
line_numbers_data.line_number[Right] += 1;
((None, Some(nr_right)), (minus_style, plus_style))
}
State::HunkPlusWrapped => ((None, None), (minus_style, plus_style)),
_ => return Vec::new(),
};

Expand Down Expand Up @@ -153,7 +156,7 @@ lazy_static! {
.unwrap();
}

#[derive(Default)]
#[derive(Default, Debug)]
pub struct LineNumbersData<'a> {
pub format_data: LeftRight<LineNumberFormatData<'a>>,
pub line_number: LeftRight<usize>,
Expand Down
5 changes: 5 additions & 0 deletions src/features/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ pub fn make_builtin_features() -> HashMap<String, BuiltinFeature> {
"side-by-side".to_string(),
side_by_side::make_feature().into_iter().collect(),
),
(
"side-by-side-wrapped".to_string(),
side_by_side_wrap::make_feature().into_iter().collect(),
),
]
.into_iter()
.collect()
Expand Down Expand Up @@ -90,6 +94,7 @@ pub mod line_numbers;
pub mod navigate;
pub mod raw;
pub mod side_by_side;
pub mod side_by_side_wrap;

#[cfg(test)]
pub mod tests {
Expand Down
Loading

0 comments on commit 5542912

Please sign in to comment.