summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDan Davison <dandavison7@gmail.com>2021-08-23 00:24:49 -0700
committerGitHub <noreply@github.com>2021-08-23 00:24:49 -0700
commitbffa1efded7359b57d862a25422ef6b386ff9e4c (patch)
tree6bd5e5f1f0819a0c5df789d155a19fb17f49c8bb /src
parent5e02d340a8b3f3184f84a34434d7ad170988331f (diff)
More minimalistic display of submodule (short) diffs (#700)
* Rename state machine state: Submodule -> SubmoduleLog * More minimalistic display of submodule log diffs Partially fixes #662 * Defer emitting hunk header until first true hunk line A consequence is that we do not emit the (pseudo) hunk header in submodule (short) state; see #662.
Diffstat (limited to 'src')
-rw-r--r--src/config.rs4
-rw-r--r--src/delta.rs60
-rw-r--r--src/hunk_header.rs6
-rw-r--r--src/paint.rs2
-rw-r--r--src/parse.rs12
-rw-r--r--src/tests/test_example_diffs.rs2
6 files changed, 64 insertions, 22 deletions
diff --git a/src/config.rs b/src/config.rs
index acf7d0c9..9b1c23ce 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -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."),
}
}
diff --git a/src/delta.rs b/src/delta.rs
index c42ba9f1..fca76ff8 100644
--- a/src/delta.rs
+++ b/src/delta.rs
@@ -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,
}
@@ -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(_)
)
}
}
@@ -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.
@@ -415,14 +422,39 @@ 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
@@ -430,12 +462,7 @@ impl<'a> StateMachine<'a> {
}
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 {
@@ -449,7 +476,7 @@ impl<'a> StateMachine<'a> {
&code_fragment,
&line_numbers,
&mut self.painter,
- &self.line,
+ line,
&self.plus_file,
self.config,
)?;
@@ -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 {
diff --git a/src/hunk_header.rs b/src/hunk_header.rs
index c076041c..b3c596cf 100644
--- a/src/hunk_header.rs
+++ b/src/hunk_header.rs
@@ -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,
diff --git a/src/paint.rs b/src/paint.rs
index 88f26bfa..2236ec2d 100644
--- a/src/paint.rs
+++ b/src/paint.rs
@@ -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 {:?}",
diff --git a/src/parse.rs b/src/parse.rs
index a62d486c..c6a0860f 100644
--- a/src/parse.rs
+++ b/src/parse.rs
@@ -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::*;
diff --git a/src/tests/test_example_diffs.rs b/src/tests/test_example_diffs.rs
index 3b249eff..d60067b6 100644
--- a/src/tests/test_example_diffs.rs
+++ b/src/tests/test_example_diffs.rs
@@ -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, "─────────────────────────────┘");