ok/jj
1
0
Fork 0
forked from mirrors/jj

cli: make log word-wrapping helper calculate width eagerly

Multiple graphs will be nested in "op log" output, and things would be messy if
we had to calculate graph widths lazily. Let's simply make LogContentFormat
track the current available width no matter if ui.log-word-wrap is off.
This commit is contained in:
Yuya Nishihara 2024-09-08 13:32:52 +09:00
parent d9c68e08b1
commit 6154827129
5 changed files with 58 additions and 70 deletions

View file

@ -2330,47 +2330,46 @@ fn load_template_aliases(
/// Helper to reformat content of log-like commands.
#[derive(Clone, Debug)]
pub enum LogContentFormat {
NoWrap,
Wrap { term_width: usize },
pub struct LogContentFormat {
width: usize,
word_wrap: bool,
}
impl LogContentFormat {
/// Creates new formatting helper for the terminal.
pub fn new(ui: &Ui, settings: &UserSettings) -> Result<Self, config::ConfigError> {
if settings.config().get_bool("ui.log-word-wrap")? {
let term_width = ui.term_width();
Ok(LogContentFormat::Wrap { term_width })
} else {
Ok(LogContentFormat::NoWrap)
Ok(LogContentFormat {
width: ui.term_width(),
word_wrap: settings.config().get_bool("ui.log-word-wrap")?,
})
}
/// Subtracts the given `width` and returns new formatting helper.
#[must_use]
pub fn sub_width(&self, width: usize) -> Self {
LogContentFormat {
width: self.width.saturating_sub(width),
word_wrap: self.word_wrap,
}
}
/// Current width available to content.
pub fn width(&self) -> usize {
self.width
}
/// Writes content which will optionally be wrapped at the current width.
pub fn write(
&self,
formatter: &mut dyn Formatter,
content_fn: impl FnOnce(&mut dyn Formatter) -> std::io::Result<()>,
) -> std::io::Result<()> {
self.write_graph_text(formatter, content_fn, || 0)
}
pub fn write_graph_text(
&self,
formatter: &mut dyn Formatter,
content_fn: impl FnOnce(&mut dyn Formatter) -> std::io::Result<()>,
graph_width_fn: impl FnOnce() -> usize,
) -> std::io::Result<()> {
match self {
LogContentFormat::NoWrap => content_fn(formatter),
LogContentFormat::Wrap { term_width } => {
let mut recorder = FormatRecorder::new();
content_fn(&mut recorder)?;
text_util::write_wrapped(
formatter,
&recorder,
term_width.saturating_sub(graph_width_fn()),
)?;
Ok(())
}
if self.word_wrap {
let mut recorder = FormatRecorder::new();
content_fn(&mut recorder)?;
text_util::write_wrapped(formatter, &recorder, self.width)
} else {
content_fn(formatter)
}
}
}

View file

@ -147,27 +147,24 @@ pub(crate) fn cmd_evolog(
.iter()
.map(|id| Edge::Direct(id.clone()))
.collect_vec();
let graph_width = || graph.width(commit.id(), &edges);
let mut buffer = vec![];
with_content_format.write_graph_text(
ui.new_formatter(&mut buffer).as_mut(),
|formatter| template.format(&commit, formatter),
graph_width,
)?;
let within_graph = with_content_format.sub_width(graph.width(commit.id(), &edges));
within_graph.write(ui.new_formatter(&mut buffer).as_mut(), |formatter| {
template.format(&commit, formatter)
})?;
if !buffer.ends_with(b"\n") {
buffer.push(b'\n');
}
if let Some(renderer) = &diff_renderer {
let predecessors: Vec<_> = commit.predecessors().try_collect()?;
let mut formatter = ui.new_formatter(&mut buffer);
let width = usize::saturating_sub(ui.term_width(), graph_width());
renderer.show_inter_diff(
ui,
formatter.as_mut(),
&predecessors,
&commit,
&EverythingMatcher,
width,
within_graph.width(),
)?;
}
let node_symbol = format_template(ui, &Some(commit.clone()), &node_template);

View file

@ -205,24 +205,22 @@ pub(crate) fn cmd_log(
let mut buffer = vec![];
let key = (commit_id, false);
let commit = store.get_commit(&key.0)?;
let graph_width = || graph.width(&key, &graphlog_edges);
with_content_format.write_graph_text(
ui.new_formatter(&mut buffer).as_mut(),
|formatter| template.format(&commit, formatter),
graph_width,
)?;
let within_graph =
with_content_format.sub_width(graph.width(&key, &graphlog_edges));
within_graph.write(ui.new_formatter(&mut buffer).as_mut(), |formatter| {
template.format(&commit, formatter)
})?;
if !buffer.ends_with(b"\n") {
buffer.push(b'\n');
}
if let Some(renderer) = &diff_renderer {
let mut formatter = ui.new_formatter(&mut buffer);
let width = usize::saturating_sub(ui.term_width(), graph_width());
renderer.show_patch(
ui,
formatter.as_mut(),
&commit,
matcher.as_ref(),
width,
within_graph.width(),
)?;
}
@ -238,11 +236,11 @@ pub(crate) fn cmd_log(
let real_key = (elided_key.0.clone(), false);
let edges = [Edge::Direct(real_key)];
let mut buffer = vec![];
with_content_format.write_graph_text(
ui.new_formatter(&mut buffer).as_mut(),
|formatter| writeln!(formatter.labeled("elided"), "(elided revisions)"),
|| graph.width(&elided_key, &edges),
)?;
let within_graph =
with_content_format.sub_width(graph.width(&elided_key, &edges));
within_graph.write(ui.new_formatter(&mut buffer).as_mut(), |formatter| {
writeln!(formatter.labeled("elided"), "(elided revisions)")
})?;
let node_symbol = format_template(ui, &None, &node_template);
graph.add_node(
&elided_key,

View file

@ -244,33 +244,28 @@ pub fn show_op_diff(
.iter()
.map(|edge| Edge::Direct(edge.target.clone()))
.collect_vec();
let graph_width = || graph.width(&change_id, &edges);
let mut buffer = vec![];
with_content_format.write_graph_text(
ui.new_formatter(&mut buffer).as_mut(),
|formatter| {
write_modified_change_summary(
formatter,
commit_summary_template,
&change_id,
modified_change,
)
},
graph_width,
)?;
let within_graph = with_content_format.sub_width(graph.width(&change_id, &edges));
within_graph.write(ui.new_formatter(&mut buffer).as_mut(), |formatter| {
write_modified_change_summary(
formatter,
commit_summary_template,
&change_id,
modified_change,
)
})?;
if !buffer.ends_with(b"\n") {
buffer.push(b'\n');
}
if let Some(diff_renderer) = &diff_renderer {
let mut formatter = ui.new_formatter(&mut buffer);
let width = usize::saturating_sub(ui.term_width(), graph_width());
show_change_diff(
ui,
formatter.as_mut(),
diff_renderer,
modified_change,
width,
within_graph.width(),
)?;
}

View file

@ -134,11 +134,10 @@ fn do_op_log(
edges.push(Edge::Direct(id.clone()));
}
let mut buffer = vec![];
with_content_format.write_graph_text(
ui.new_formatter(&mut buffer).as_mut(),
|formatter| template.format(&op, formatter),
|| graph.width(op.id(), &edges),
)?;
let within_graph = with_content_format.sub_width(graph.width(op.id(), &edges));
within_graph.write(ui.new_formatter(&mut buffer).as_mut(), |formatter| {
template.format(&op, formatter)
})?;
if !buffer.ends_with(b"\n") {
buffer.push(b'\n');
}