diff options
author | Dan Davison <dandavison7@gmail.com> | 2023-07-08 17:59:29 -0400 |
---|---|---|
committer | Dan Davison <dandavison7@gmail.com> | 2023-07-09 12:33:54 -0400 |
commit | 177985e258f7d176d5642546d2386788f20f7cee (patch) | |
tree | 85898d5c20c337071c24790eab728307b3cdad53 | |
parent | 5767a8a9483619843fd83e4213162d8882a43a11 (diff) |
WIP: map-line-numbersline-map
-rw-r--r-- | src/cli.rs | 9 | ||||
-rw-r--r-- | src/config.rs | 8 | ||||
-rw-r--r-- | src/features/line_numbers.rs | 15 | ||||
-rw-r--r-- | src/main.rs | 4 | ||||
-rw-r--r-- | src/options/set.rs | 1 | ||||
-rw-r--r-- | src/subcommands/map_line_numbers.rs | 32 | ||||
-rw-r--r-- | src/subcommands/mod.rs | 1 | ||||
-rw-r--r-- | src/wrapping.rs | 6 |
8 files changed, 73 insertions, 3 deletions
@@ -697,6 +697,15 @@ pub struct Opt { /// An example is --map-styles='bold purple => red "#eeeeee", bold cyan => syntax "#eeeeee"' pub map_styles: Option<String>, + #[arg(long = "map-line-numbers")] + /// Output a line numbers map instead of the usual delta output. + /// + /// The output is a JSON document attempting to identify, for each file, for + /// each line in the old version of the file, the number of the + /// corresponding line in the new version of the file, if there is a + /// corresponding line. + pub map_line_numbers: bool, + #[arg(long = "max-line-distance", default_value = "0.6", value_name = "DIST")] /// Maximum line pair distance parameter in within-line diff algorithm. /// diff --git a/src/config.rs b/src/config.rs index cab21eb7..da4ac16c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -94,6 +94,7 @@ pub struct Config { pub line_numbers_zero_style: Style, pub line_numbers: bool, pub styles_map: Option<HashMap<style::AnsiTermStyleEqualityKey, Style>>, + pub map_line_numbers: bool, pub max_line_distance_for_naively_paired_lines: f64, pub max_line_distance: f64, pub max_line_length: usize, @@ -345,7 +346,8 @@ impl From<cli::Opt> for Config { } else { line_fill_method }, - line_numbers: opt.line_numbers && !handlers::hunk::is_word_diff(), + line_numbers: (opt.line_numbers || opt.map_line_numbers) + && !handlers::hunk::is_word_diff(), line_numbers_format: LeftRight::new( opt.line_numbers_left_format, opt.line_numbers_right_format, @@ -360,6 +362,7 @@ impl From<cli::Opt> for Config { ), line_numbers_zero_style: styles["line-numbers-zero-style"], line_buffer_size: opt.line_buffer_size, + map_line_numbers: opt.map_line_numbers, max_line_distance: opt.max_line_distance, max_line_distance_for_naively_paired_lines, max_line_length: if opt.side_by_side { @@ -395,7 +398,8 @@ impl From<cli::Opt> for Config { git_plus_style: styles["git-plus-style"], relative_paths: opt.relative_paths, show_themes: opt.show_themes, - side_by_side: opt.side_by_side && !handlers::hunk::is_word_diff(), + side_by_side: (opt.side_by_side || opt.map_line_numbers) + && !handlers::hunk::is_word_diff(), side_by_side_data, styles_map, syntax_dummy_theme: SyntaxTheme::default(), diff --git a/src/features/line_numbers.rs b/src/features/line_numbers.rs index 1c674b0f..f6498f96 100644 --- a/src/features/line_numbers.rs +++ b/src/features/line_numbers.rs @@ -120,6 +120,12 @@ pub fn format_and_paint_line_numbers<'a>( }; if emit_left { + if config.map_line_numbers { + assert!(config.side_by_side && config.wrap_config.max_lines == 1); + if let Some(n) = line_numbers[Minus] { + print!("{},{}", line_numbers_data.plus_file, n) + } + } formatted_numbers.extend(format_and_paint_line_number_field( line_numbers_data, Minus, @@ -130,6 +136,15 @@ pub fn format_and_paint_line_numbers<'a>( } if emit_right { + if config.map_line_numbers && line_numbers[Minus].is_some() { + println!( + ",{}", + line_numbers[Plus] + .map(|n| n.to_string()) + .as_deref() + .unwrap_or("null") + ) + } formatted_numbers.extend(format_and_paint_line_number_field( line_numbers_data, Plus, diff --git a/src/main.rs b/src/main.rs index caf94cac..413ded4b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -112,6 +112,7 @@ fn run_app() -> std::io::Result<i32> { }; let _show_config = opt.show_config; + let _map_line_numbers = opt.map_line_numbers; let config = config::Config::from(opt); if _show_config { @@ -119,6 +120,9 @@ fn run_app() -> std::io::Result<i32> { let mut stdout = stdout.lock(); subcommands::show_config::show_config(&config, &mut stdout)?; return Ok(0); + } else if _map_line_numbers { + subcommands::map_line_numbers::map_line_numbers(&config)?; + return Ok(0); } let mut output_type = diff --git a/src/options/set.rs b/src/options/set.rs index 732806a7..e0026aa8 100644 --- a/src/options/set.rs +++ b/src/options/set.rs @@ -170,6 +170,7 @@ pub fn set_options( inspect_raw_lines, keep_plus_minus_markers, line_buffer_size, + map_line_numbers, map_styles, max_line_distance, max_line_length, diff --git a/src/subcommands/map_line_numbers.rs b/src/subcommands/map_line_numbers.rs new file mode 100644 index 00000000..8b3f272e --- /dev/null +++ b/src/subcommands/map_line_numbers.rs @@ -0,0 +1,32 @@ +use crate::config::Config; +use crate::delta::delta; +use bytelines::ByteLinesReader; +use std::io::{self, ErrorKind, Write}; + +#[cfg(not(tarpaulin_include))] +pub fn map_line_numbers(config: &Config) -> std::io::Result<()> { + let mut writer = NullWriter {}; + if let Err(error) = delta(io::stdin().lock().byte_lines(), &mut writer, &config) { + match error.kind() { + ErrorKind::BrokenPipe => return Ok(()), + _ => eprintln!("{error}"), + } + }; + Ok(()) +} + +struct NullWriter {} + +impl Write for NullWriter { + fn write(&mut self, _buf: &[u8]) -> io::Result<usize> { + Ok(0) + } + + fn write_all(&mut self, mut _buf: &[u8]) -> io::Result<()> { + Ok(()) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} diff --git a/src/subcommands/mod.rs b/src/subcommands/mod.rs index 26f04233..901ddb98 100644 --- a/src/subcommands/mod.rs +++ b/src/subcommands/mod.rs @@ -1,5 +1,6 @@ pub mod diff; pub mod list_syntax_themes; +pub mod map_line_numbers; pub mod parse_ansi; mod sample_diff; pub mod show_colors; diff --git a/src/wrapping.rs b/src/wrapping.rs index 40eff4f2..c327fb00 100644 --- a/src/wrapping.rs +++ b/src/wrapping.rs @@ -59,7 +59,11 @@ impl WrapConfig { fatal("Invalid value for wrap-right-percent, not between 0 and 100.") } }, - max_lines: adapt_wrap_max_lines_argument(opt.wrap_max_lines.clone()), + max_lines: adapt_wrap_max_lines_argument(if opt.map_line_numbers { + "0".to_string() + } else { + opt.wrap_max_lines.clone() + }), inline_hint_syntect_style: SyntectStyle::from_delta_style(inline_hint_style), } } |