//! A module for constructing and writing the hunk header. //! //! The structure of the hunk header output by delta is //! ``` //! (file):(line-number): (code-fragment) //! ``` //! //! The code fragment and line number derive from a line of git/diff output that looks like //! ``` //! @@ -119,12 +119,7 @@ fn write_to_output_buffer( //! ``` //! //! Whether or not file and line-number are included is controlled by the presence of the special //! style attributes 'file' and 'line-number' in the hunk-header-style string. For example, delta //! might output the above hunk header as //! ``` //! ───────────────────────────────────────────────────┐ //! src/hunk_header.rs:119: fn write_to_output_buffer( │ //! ───────────────────────────────────────────────────┘ //! ``` use std::fmt::Write as FmtWrite; use crate::config::Config; use crate::delta; use crate::draw; use crate::features; use crate::paint::Painter; use crate::style::DecorationStyle; pub fn write_hunk_header_raw( painter: &mut Painter, line: &str, raw_line: &str, config: &Config, ) -> std::io::Result<()> { let (mut draw_fn, pad, decoration_ansi_term_style) = draw::get_draw_function(config.hunk_header_style.decoration_style); if config.hunk_header_style.decoration_style != DecorationStyle::NoDecoration { writeln!(painter.writer)?; } draw_fn( painter.writer, &format!("{}{}", line, if pad { " " } else { "" }), &format!("{}{}", raw_line, if pad { " " } else { "" }), &config.decorations_width, config.hunk_header_style, decoration_ansi_term_style, )?; Ok(()) } pub fn write_hunk_header( code_fragment: &str, line_numbers: &[(usize, usize)], painter: &mut Painter, line: &str, plus_file: &str, config: &Config, ) -> std::io::Result<()> { let (mut draw_fn, _, decoration_ansi_term_style) = draw::get_draw_function(config.hunk_header_style.decoration_style); let line = if config.color_only { format!(" {}", &line) } else if !code_fragment.is_empty() { format!("{} ", code_fragment) } else { "".to_string() }; let file_with_line_number = get_painted_file_with_line_number(line_numbers, plus_file, config); if !line.is_empty() || !file_with_line_number.is_empty() { write_to_output_buffer(&file_with_line_number, line, painter, config); draw_fn( painter.writer, &painter.output_buffer, &painter.output_buffer, &config.decorations_width, config.null_style, decoration_ansi_term_style, )?; painter.output_buffer.clear(); } Ok(()) } fn get_painted_file_with_line_number( line_numbers: &[(usize, usize)], plus_file: &str, config: &Config, ) -> String { let mut file_with_line_number = Vec::new(); let plus_line_number = line_numbers[line_numbers.len() - 1].0; if config.hunk_header_style_include_file_path { file_with_line_number.push(config.hunk_header_file_style.paint(plus_file)) }; if config.hunk_header_style_include_line_number && !config.hunk_header_style.is_raw && !config.color_only { if !file_with_line_number.is_empty() { file_with_line_number.push(ansi_term::ANSIString::from(":")); } file_with_line_number.push( config .hunk_header_line_number_style .paint(format!("{}", plus_line_number)), ) } let file_with_line_number = ansi_term::ANSIStrings(&file_with_line_number).to_string(); if config.hyperlinks { features::hyperlinks::format_osc8_file_hyperlink( plus_file, Some(plus_line_number), &file_with_line_number, config, ) .into() } else { file_with_line_number } } fn write_to_output_buffer( file_with_line_number: &str, line: String, painter: &mut Painter, config: &Config, ) { if !file_with_line_number.is_empty() { let _ = write!(&mut painter.output_buffer, "{}: ", file_with_line_number); } if !line.is_empty() { let lines = vec![(line, delta::State::HunkHeader)]; let syntax_style_sections = Painter::get_syntax_style_sections_for_lines( &lines, &delta::State::HunkHeader, &mut painter.highlighter, &painter.config, ); Painter::paint_lines( syntax_style_sections, vec![vec![(config.hunk_header_style, &lines[0].0)]], // TODO: compute style from state [delta::State::HunkHeader].iter(), &mut painter.output_buffer, config, &mut None, None, None, Some(false), ); painter.output_buffer.pop(); // trim newline } }