diff options
author | Dan Davison <dandavison7@gmail.com> | 2021-08-22 22:43:11 -0700 |
---|---|---|
committer | Dan Davison <dandavison7@gmail.com> | 2021-08-22 23:57:09 -0700 |
commit | 7293eca8b8384922927411604c1b5ea53e3468da (patch) | |
tree | 78b31c14e66a701dae195550cbb77fae2f506a9d | |
parent | e2dbcd12b4c934a18e7ee3b8f983be4a42c0b318 (diff) |
WIP
-rw-r--r-- | Cargo.lock | 33 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | src/delta.rs | 21 | ||||
-rw-r--r-- | src/parse.rs | 73 |
4 files changed, 127 insertions, 2 deletions
@@ -145,8 +145,20 @@ version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" dependencies = [ + "libc", "num-integer", "num-traits", + "time", + "winapi", +] + +[[package]] +name = "chrono-humanize" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eddc119501d583fd930cb92144e605f44e0252c38dd89d9247fffa1993375cb" +dependencies = [ + "chrono", ] [[package]] @@ -276,7 +288,7 @@ checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ "cfg-if 1.0.0", "libc", - "wasi", + "wasi 0.9.0+wasi-snapshot-preview1", ] [[package]] @@ -289,6 +301,8 @@ dependencies = [ "bitflags", "box_drawing", "bytelines", + "chrono", + "chrono-humanize", "console", "ctrlc", "dirs-next", @@ -834,6 +848,17 @@ dependencies = [ ] [[package]] +name = "time" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi", +] + +[[package]] name = "tinyvec" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -959,6 +984,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -15,6 +15,8 @@ name = "delta" path = "src/main.rs" [dependencies] +chrono = "0.4.19" +chrono-humanize = "0.2.1" ansi_colours = "1.0.4" ansi_term = "0.12.1" atty = "0.2.14" diff --git a/src/delta.rs b/src/delta.rs index e0a1e1c2..c9f23458 100644 --- a/src/delta.rs +++ b/src/delta.rs @@ -126,7 +126,8 @@ impl<'a> StateMachine<'a> { || self.handle_additional_file_meta_cases()? || self.handle_submodule_log_line()? || self.handle_submodule_short_line()? - || self.handle_hunk_line()?; + || self.handle_hunk_line()? + || self.handle_blame_line()?; if self.state == State::FileMeta && self.should_handle() && !self.config.color_only { // Skip file metadata lines unless a raw diff style has been requested. @@ -463,6 +464,24 @@ impl<'a> StateMachine<'a> { Ok(true) } + fn handle_blame_line(&mut self) -> std::io::Result<bool> { + let mut handled_line = false; + if let Some(blame) = parse::parse_git_blame_line(&self.line) { + writeln!( + self.painter.writer, + "{}: {} {} {}", + self.config.commit_style.paint(blame.commit), + blame.author, + chrono_humanize::HumanTime::from(blame.time), + // highlighter.highlight(&line[1..], &config.syntax_set); + blame.code, + )?; + + handled_line = true + } + Ok(handled_line) + } + fn _handle_additional_cases(&mut self, to_state: State) -> std::io::Result<bool> { let mut handled_line = false; diff --git a/src/parse.rs b/src/parse.rs index c6a0860f..31524536 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -4,6 +4,8 @@ use std::borrow::Cow; use std::path::Path; use unicode_segmentation::UnicodeSegmentation; +use chrono::{DateTime, FixedOffset}; + use crate::config::Config; use crate::features; @@ -280,6 +282,77 @@ pub fn get_submodule_short_commit(line: &str) -> Option<&str> { } } +pub struct BlameLine<'a> { + pub commit: &'a str, + pub author: &'a str, + pub time: DateTime<FixedOffset>, + pub line_number: usize, + pub code: &'a str, +} + +// E.g. +//ea82f2d0 (Dan Davison 2021-08-22 18:20:19 -0700 120) let mut handled_line = self.handle_commit_meta_header_line()? + +lazy_static! { + static ref BLAME_LINE_REGEX: Regex = Regex::new( + r"(?x) +^ +( + [0-9a-f]{8} # commit hash +) +[\ ] +\( # open ( +( + [^\ ].* # author name +) +[\ ]+ +( # timestamp + [0-9]{4}-[01][0-9]-[0123][0-9] [012][0-9]:[0-5][0-9]:[0-5][0-9] [-+][0-9]{4} +) +[\ ] +( + [0-9]+ # line number +) +\) # close ) +[\ ] +( + .* # code +) +" + ) + .unwrap(); +} + +pub fn parse_git_blame_line(line: &str) -> Option<BlameLine> { + if let Some(caps) = BLAME_LINE_REGEX.captures(line) { + let commit = caps.get(1).unwrap().as_str(); + let author = caps.get(2).unwrap().as_str(); + let timestamp = caps.get(3).unwrap().as_str(); + if let Ok(time) = DateTime::parse_from_str(timestamp, "%Y-%m-%d %H:%M:%S %z") { + let line_number_str = caps.get(4).unwrap().as_str(); + if let Ok(line_number) = line_number_str.parse::<usize>() { + let code = caps.get(5).unwrap().as_str(); + Some(BlameLine { + commit, + author, + time, + line_number, + code, + }) + } else { + eprintln!("Failed to parse line number: {}", line_number_str); + None + } + } else { + eprintln!("Failed to parse timestamp: {}", timestamp); + None + } + } else { + eprintln!("Failed to match:\n{}", line); + None + } +} + #[cfg(test)] mod tests { use super::*; |