2024-08-12 21:25:24 +01:00
|
|
|
//
|
2024-08-31 13:33:45 +01:00
|
|
|
use git_next_core::git::graph::Log;
|
2024-08-12 21:25:24 +01:00
|
|
|
use ratatui::{
|
2024-08-31 22:31:49 +01:00
|
|
|
style::{Color, Style},
|
2024-08-31 17:45:43 +01:00
|
|
|
text::{Line, Span, Text},
|
2024-08-12 21:25:24 +01:00
|
|
|
widgets::{Paragraph, Widget},
|
|
|
|
};
|
2024-08-31 17:45:43 +01:00
|
|
|
use regex::Regex;
|
2024-08-12 21:25:24 +01:00
|
|
|
|
2024-08-28 09:14:02 +01:00
|
|
|
use super::HeightContraintLength;
|
2024-08-28 07:53:56 +01:00
|
|
|
|
2024-08-12 21:25:24 +01:00
|
|
|
pub struct CommitLog<'a> {
|
|
|
|
pub log: &'a Log,
|
|
|
|
}
|
2024-08-28 09:14:02 +01:00
|
|
|
impl<'a> HeightContraintLength for CommitLog<'a> {
|
|
|
|
fn height_constraint_length(&self) -> u16 {
|
|
|
|
u16::try_from(self.log.len()).unwrap_or(u16::MAX)
|
2024-08-28 07:53:56 +01:00
|
|
|
}
|
|
|
|
}
|
2024-08-12 21:25:24 +01:00
|
|
|
impl<'a> Widget for CommitLog<'a> {
|
|
|
|
fn render(self, area: ratatui::prelude::Rect, buf: &mut ratatui::prelude::Buffer)
|
|
|
|
where
|
|
|
|
Self: Sized,
|
|
|
|
{
|
|
|
|
Paragraph::new(Text::from(
|
|
|
|
self.log
|
|
|
|
.iter()
|
2024-08-31 13:33:45 +01:00
|
|
|
.map(LogLine::new)
|
2024-08-12 21:25:24 +01:00
|
|
|
.map(Line::from)
|
|
|
|
.collect::<Vec<_>>(),
|
|
|
|
))
|
|
|
|
.render(area, buf);
|
|
|
|
}
|
|
|
|
}
|
2024-08-31 13:33:45 +01:00
|
|
|
|
|
|
|
struct LogLine {
|
|
|
|
raw: String,
|
|
|
|
}
|
|
|
|
impl LogLine {
|
|
|
|
fn new(raw: impl Into<String>) -> Self {
|
|
|
|
Self { raw: raw.into() }
|
|
|
|
}
|
|
|
|
}
|
2024-08-31 17:45:43 +01:00
|
|
|
lazy_static::lazy_static! {
|
|
|
|
static ref RE: Regex =
|
|
|
|
#[allow(clippy::unwrap_used)]
|
|
|
|
Regex::new(
|
|
|
|
r"^(?<pre>.*)\s(?<hash>[0-9a-f]{7})\s\((?<branches>.*?)\)\s(?<message>.*)",
|
|
|
|
).unwrap();
|
|
|
|
|
|
|
|
static ref BRANCHES: Regex =
|
|
|
|
#[allow(clippy::unwrap_used)]
|
|
|
|
Regex::new(
|
|
|
|
r"origin\/(?<branch>[^,]+)",
|
|
|
|
).unwrap();
|
|
|
|
}
|
2024-08-31 13:33:45 +01:00
|
|
|
impl From<LogLine> for Line<'_> {
|
|
|
|
fn from(value: LogLine) -> Self {
|
2024-08-31 17:45:43 +01:00
|
|
|
if let Some(caps) = RE.captures(&value.raw) {
|
|
|
|
let pre = caps["pre"].to_owned();
|
|
|
|
let hash = caps["hash"].to_owned();
|
|
|
|
let message = caps["message"].to_owned();
|
|
|
|
let mut branches = BRANCHES
|
|
|
|
.captures_iter(&caps["branches"])
|
|
|
|
.map(|captures| captures["branch"].to_owned())
|
2024-08-31 17:54:43 +01:00
|
|
|
.filter(|branch| branch != "HEAD")
|
2024-08-31 17:45:43 +01:00
|
|
|
.collect::<Vec<_>>();
|
|
|
|
if branches.is_empty() {
|
|
|
|
// line without branches
|
|
|
|
Line::from(vec![
|
|
|
|
pre.into(),
|
|
|
|
" ".into(),
|
|
|
|
hash.into(),
|
|
|
|
" ".into(),
|
|
|
|
message.into(),
|
|
|
|
])
|
|
|
|
} else {
|
|
|
|
// line withbranches
|
|
|
|
let mut spans = vec![pre.into(), " ".into(), hash.into(), " ".into()];
|
|
|
|
branches.sort();
|
|
|
|
branches
|
|
|
|
.into_iter()
|
2024-08-31 19:20:50 +01:00
|
|
|
.map(|branch| format!("({branch})"))
|
|
|
|
.map(Span::from)
|
|
|
|
.map(|span| span.style(Style::default().fg(Color::White).bg(Color::Blue)))
|
|
|
|
.for_each(|span| spans.push(span));
|
2024-08-31 17:45:43 +01:00
|
|
|
spans.push(" ".into());
|
|
|
|
spans.push(message.into());
|
|
|
|
Line::from(spans)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// non-commit line
|
|
|
|
Line::from(value.raw.clone())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use tracing::info;
|
|
|
|
|
|
|
|
use super::RE;
|
|
|
|
|
|
|
|
#[test_log::test]
|
|
|
|
fn parse_log_line() -> Result<(), Box<dyn std::error::Error>> {
|
|
|
|
let line = "* 97b6853 (origin/next, origin/main, origin/dev, origin/HEAD) refactor(tui): simplify repo identity widget";
|
|
|
|
RE.captures(line).map_or_else(
|
|
|
|
|| Err("Failed to capture".into()),
|
|
|
|
|caps| {
|
|
|
|
info!(?caps, "");
|
|
|
|
assert_eq!(&caps["pre"], "*");
|
|
|
|
assert_eq!(&caps["hash"], "97b6853");
|
|
|
|
assert_eq!(
|
|
|
|
&caps["branches"],
|
|
|
|
"origin/next, origin/main, origin/dev, origin/HEAD"
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
&caps["message"],
|
|
|
|
"refactor(tui): simplify repo identity widget"
|
|
|
|
);
|
|
|
|
Ok(())
|
|
|
|
},
|
|
|
|
)
|
2024-08-31 13:33:45 +01:00
|
|
|
}
|
|
|
|
}
|