Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More minimalistic display of submodule (short) diffs #700

Merged
merged 3 commits into from
Aug 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ impl Config {
State::HunkPlus(_) => &self.plus_style,
State::CommitMeta => &self.commit_style,
State::FileMeta => &self.file_style,
State::HunkHeader => &self.hunk_header_style,
State::Submodule => &self.file_style,
State::HunkHeader(_, _) => &self.hunk_header_style,
State::SubmoduleLog => &self.file_style,
_ => delta_unreachable("Unreachable code reached in get_style."),
}
}
Expand Down
60 changes: 45 additions & 15 deletions src/delta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@ use crate::style::{self, DecorationStyle};

#[derive(Clone, Debug, PartialEq)]
pub enum State {
CommitMeta, // In commit metadata section
CommitMeta, // In commit metadata section
FileMeta, // In diff metadata section, between (possible) commit metadata and first hunk
HunkHeader, // In hunk metadata line
HunkHeader(String, String), // In hunk metadata line (line, raw_line)
HunkZero, // In hunk; unchanged line
HunkMinus(Option<String>), // In hunk; removed line (raw_line)
HunkPlus(Option<String>), // In hunk; added line (raw_line)
Submodule,
SubmoduleLog, // In a submodule section, with gitconfig diff.submodule = log
SubmoduleShort(String), // In a submodule section, with gitconfig diff.submodule = short
Unknown,
}

Expand All @@ -39,7 +40,7 @@ impl State {
fn is_in_hunk(&self) -> bool {
matches!(
*self,
State::HunkHeader | State::HunkZero | State::HunkMinus(_) | State::HunkPlus(_)
State::HunkHeader(_, _) | State::HunkZero | State::HunkMinus(_) | State::HunkPlus(_)
)
}
}
Expand Down Expand Up @@ -145,7 +146,13 @@ impl<'a> StateMachine<'a> {
{
self.handle_additional_cases(State::FileMeta)?
} else if line.starts_with("Submodule ") {
self.handle_additional_cases(State::Submodule)?
self.handle_additional_cases(State::SubmoduleLog)?
} else if (matches!(self.state, State::HunkHeader(_, _))
&& line.starts_with("-Subproject commit "))
|| (matches!(self.state, State::SubmoduleShort(_))
&& line.starts_with("+Subproject commit "))
{
self.handle_submodule_short_line()?
} else if self.state.is_in_hunk() {
// A true hunk line should start with one of: '+', '-', ' '. However, handle_hunk_line
// handles all lines until the state transitions away from the hunk states.
Expand Down Expand Up @@ -415,27 +422,47 @@ impl<'a> StateMachine<'a> {
Ok(handled_line)
}

/// Emit the hunk header, with any requested decoration.
fn handle_submodule_short_line(&mut self) -> std::io::Result<bool> {
if let Some(commit) = parse::get_submodule_short_commit(&self.line) {
if let State::HunkHeader(_, _) = self.state {
self.state = State::SubmoduleShort(commit.to_owned());
} else if let State::SubmoduleShort(minus_commit) = &self.state {
self.painter.emit()?;
writeln!(
self.painter.writer,
"{} ⟶ {}",
self.config
.minus_style
.paint(minus_commit.chars().take(7).collect::<String>()),
self.config
.plus_style
.paint(commit.chars().take(7).collect::<String>()),
)?;
}
}
Ok(true)
}

fn handle_hunk_header_line(&mut self) -> std::io::Result<bool> {
self.state = State::HunkHeader(self.line.clone(), self.raw_line.clone());
Ok(true)
}

/// Emit the hunk header, with any requested decoration.
fn emit_hunk_header_line(&mut self, line: &str, raw_line: &str) -> std::io::Result<bool> {
self.painter.paint_buffered_minus_and_plus_lines();
self.state = State::HunkHeader;
self.painter.set_highlighter();
self.painter.emit()?;

let (code_fragment, line_numbers) = parse::parse_hunk_header(&self.line);
let (code_fragment, line_numbers) = parse::parse_hunk_header(line);
if self.config.line_numbers {
self.painter
.line_numbers_data
.initialize_hunk(&line_numbers, self.plus_file.to_string());
}

if self.config.hunk_header_style.is_raw {
hunk_header::write_hunk_header_raw(
&mut self.painter,
&self.line,
&self.raw_line,
self.config,
)?;
hunk_header::write_hunk_header_raw(&mut self.painter, line, raw_line, self.config)?;
} else if self.config.hunk_header_style.is_omitted {
writeln!(self.painter.writer)?;
} else {
Expand All @@ -449,7 +476,7 @@ impl<'a> StateMachine<'a> {
&code_fragment,
&line_numbers,
&mut self.painter,
&self.line,
line,
&self.plus_file,
self.config,
)?;
Expand All @@ -473,6 +500,9 @@ impl<'a> StateMachine<'a> {
{
self.painter.paint_buffered_minus_and_plus_lines();
}
if let State::HunkHeader(line, raw_line) = &self.state.clone() {
self.emit_hunk_header_line(line, raw_line)?;
}
self.state = match self.line.chars().next() {
Some('-') => {
if let State::HunkPlus(_) = self.state {
Expand Down
6 changes: 3 additions & 3 deletions src/hunk_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,18 +142,18 @@ fn write_to_output_buffer(
if !line.is_empty() {
let lines = vec![(
painter.expand_tabs(line.graphemes(true)),
delta::State::HunkHeader,
delta::State::HunkHeader("".to_owned(), "".to_owned()),
)];
let syntax_style_sections = Painter::get_syntax_style_sections_for_lines(
&lines,
&delta::State::HunkHeader,
&delta::State::HunkHeader("".to_owned(), "".to_owned()),
painter.highlighter.as_mut(),
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(),
[delta::State::HunkHeader("".to_owned(), "".to_owned())].iter(),
&mut painter.output_buffer,
config,
&mut None,
Expand Down
2 changes: 1 addition & 1 deletion src/paint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ impl<'a> Painter<'a> {
config.plus_style.is_syntax_highlighted
|| config.plus_emph_style.is_syntax_highlighted
}
State::HunkHeader => true,
State::HunkHeader(_, _) => true,
State::HunkMinus(Some(_)) | State::HunkPlus(Some(_)) => false,
_ => panic!(
"should_compute_syntax_highlighting is undefined for state {:?}",
Expand Down
12 changes: 12 additions & 0 deletions src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,18 @@ fn get_extension(s: &str) -> Option<&str> {
.or_else(|| path.file_name().and_then(|s| s.to_str()))
}

lazy_static! {
static ref SUBMODULE_SHORT_LINE_REGEX: Regex =
Regex::new("^[-+]Subproject commit ([0-9a-f]{40})$").unwrap();
}

pub fn get_submodule_short_commit(line: &str) -> Option<&str> {
match SUBMODULE_SHORT_LINE_REGEX.captures(line) {
Some(caps) => Some(caps.get(1).unwrap().as_str()),
None => None,
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
2 changes: 1 addition & 1 deletion src/tests/test_example_diffs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1386,7 +1386,7 @@ src/align.rs:71: impl<'a> Alignment<'a> { │
4,
"impl<'a> Alignment<'a> { ",
"rs",
State::HunkHeader,
State::HunkHeader("".to_owned(), "".to_owned()),
&config,
);
ansi_test_utils::assert_line_has_no_color(&output, 12, "─────────────────────────────┘");
Expand Down