feat: support comments in ordinary source buffers

This commit is contained in:
2026-10-22 22:30:16 +02:00
parent ac5c64981d
commit e6d94dcb41
16 changed files with 1005 additions and 600 deletions
+80 -9
View File
@@ -807,6 +807,7 @@ impl BufferViewports {
editor.file_navigation_hint(),
&mut self.panels,
Some(editor),
Some(&editor.local_review),
);
} else {
draw_overlays(
@@ -1009,6 +1010,7 @@ impl BufferViewports {
view.whitespace_scope(),
view.resolver(),
true,
None,
);
if view.render_pane_focused()
&& !view.file_picker().is_some_and(|picker| picker.focused)
@@ -1823,7 +1825,14 @@ fn chrome_items<'a>(
tab: None,
accent: !matches!(
name.as_str(),
"path" | "language" | "diagnostics" | "selections" | "count" | "pending" | "buffer" | "diff"
"path"
| "language"
| "diagnostics"
| "selections"
| "count"
| "pending"
| "buffer"
| "diff"
),
bold: false,
first: true,
@@ -2236,6 +2245,7 @@ fn draw_document(
editor.file_navigation_hint(),
panels,
Some(editor),
Some(&editor.local_review),
);
return;
}
@@ -2275,6 +2285,17 @@ fn draw_document(
let mut document_caret = None;
let carets = editor.carets();
let selections = editor.selections();
let review_comments: Vec<_> = editor
.local_review
.document
.comments
.iter()
.filter_map(|comment| {
editor
.source_review_anchor_range(&comment.anchor)
.map(|range| (comment, range))
})
.collect();
let wrapped = editor.word_wrap();
let presentation = (editor.buffer_id(), wrapped, width, height);
let identity = (editor.buffer_id(), editor.text_revision(), cursor);
@@ -2576,6 +2597,25 @@ fn draw_document(
})
.collect();
frame.render_widget(Paragraph::new(numbers), gutter);
for (screen, &(row, continuation, _)) in document.visible.iter().enumerate() {
if continuation != 0 {
continue;
}
if let Some((comment, _)) = review_comments
.iter()
.filter(|(_, range)| {
let end = range.end.row
- usize::from(range.end.column == 0 && range.end.row > range.start.row);
(range.start.row..=end).contains(&row)
})
.max_by_key(|(comment, _)| editor.local_review.selected == Some(comment.id))
{
let selected = editor.local_review.selected == Some(comment.id);
frame.buffer_mut()[(gutter.right() - 1, gutter.y + screen as u16)]
.set_symbol(if selected { "●" } else { "○" })
.set_fg(Color::Magenta);
}
}
}
let lines: Vec<Line> = document
.visible
@@ -2627,6 +2667,33 @@ fn draw_document(
if editor.highlight_trailing_whitespace() {
paint_trailing_whitespace(frame, line, area, segment.start);
}
if let Some((_, range)) = review_comments
.iter()
.find(|(comment, _)| editor.local_review.selected == Some(comment.id))
{
let end_row = range.end.row
- usize::from(range.end.column == 0 && range.end.row > range.start.row);
if (range.start.row..=end_row).contains(&row) {
let start = if row == range.start.row {
range.start.column
} else {
0
};
let end = if row == range.end.row {
range.end.column
} else {
usize::MAX
};
paint_grapheme_range(
frame,
area,
segment.start,
line,
start..end,
Style::default().bg(Color::Magenta),
);
}
}
paint_editor_line(
frame,
editor,
@@ -3337,6 +3404,7 @@ fn draw_diff_popups(
}
}
#[allow(clippy::too_many_arguments)]
fn draw_diff(
frame: &mut Frame,
diff: &DiffState,
@@ -3345,6 +3413,7 @@ fn draw_diff(
file_navigation_hint: &str,
panels: &mut WheelPanels,
editor: Option<&Editor>,
review: Option<&crate::review::ReviewState>,
) {
if let Some(editor) = editor {
panels.picker_scroll.distance = editor.scroll_distance();
@@ -3814,7 +3883,7 @@ fn draw_diff(
comparison.map(|comparison| (comparison.files.as_slice(), &diff.reviewed_files)),
);
}
let document_caret = panels.draw_documents(frame, diff, panes, navigator, editor);
let document_caret = panels.draw_documents(frame, diff, panes, navigator, editor, review);
if let Some(editor) = editor {
draw_diff_popups(frame, editor, area, document_caret, panels);
}
@@ -3839,6 +3908,7 @@ impl WheelPanels {
panes: Rect,
navigator: Option<Rect>,
editor: Option<&Editor>,
review: Option<&crate::review::ReviewState>,
) -> Option<(Rect, Position)> {
self.cached_diff_error(Some(diff));
let selected = diff
@@ -4087,6 +4157,7 @@ impl WheelPanels {
editor.map_or(WhitespaceScope::All, Editor::whitespace_scope),
resolver,
false,
review,
);
text_widths[0] = text_area.width;
if let Some(editor) =
@@ -4127,6 +4198,7 @@ impl WheelPanels {
editor.map_or(WhitespaceScope::All, Editor::whitespace_scope),
resolver,
false,
review,
);
text_widths[1] = text_area.width;
if let Some(editor) =
@@ -4464,6 +4536,7 @@ fn draw_diff_pane(
whitespace_scope: WhitespaceScope,
resolver: Option<&ResolverWorkspace>,
content_only: bool,
review: Option<&crate::review::ReviewState>,
) -> Rect {
if area.width == 0 || area.height == 0 {
return area;
@@ -4487,11 +4560,9 @@ fn draw_diff_pane(
*left = diff.bound_horizontal(focus, *left, width);
}
let left = *left;
let review_comments = diff
.local_review
.document
.comments
.iter()
let review_comments = review
.into_iter()
.flat_map(|review| review.document.comments.iter())
.filter_map(|comment| {
let before = comment.anchor.side == crate::review::Side::Before;
let path = if before {
@@ -4502,7 +4573,7 @@ fn draw_diff_pane(
if !(unified || before == (focus == Focus::Before)) || comment.anchor.path != *path {
return None;
}
diff.review_anchor_range(&comment.anchor)
diff.review_anchor_range(&comment.anchor, review.unwrap())
.map(|range| (comment, range))
});
paint_diff_content(
@@ -4518,7 +4589,7 @@ fn draw_diff_pane(
whitespace_characters,
whitespace_scope,
review_comments,
diff.local_review.selected,
review.and_then(|review| review.selected),
)
}