wip: pr file diffing

This commit is contained in:
2026-05-18 22:30:46 +08:00
parent aa99ba2596
commit 553af0290f
32 changed files with 1523 additions and 164 deletions

108
src/component/code_view.rs Normal file
View File

@@ -0,0 +1,108 @@
use std::{rc::Rc, sync::Arc};
use gpui::{IntoElement, ParentElement, Styled, div, list, px, rems};
use crate::app;
#[derive(gpui::IntoElement, Clone)]
pub(crate) struct Line {
line_number_col_width: gpui::Pixels,
line_number: usize,
content: gpui::SharedString,
diff_marker: DiffMarker,
}
#[derive(Clone)]
enum DiffMarker {
Added,
Deleted,
Unchanged,
}
#[derive(Clone)]
struct CodeViewState(gpui::ListState);
#[derive(Clone)]
struct Lines(Rc<Vec<Line>>);
struct CodeView {
state: CodeViewState,
lines: Lines,
}
pub(crate) fn line(
line_number: usize,
content: impl Into<Arc<str>>,
diff_marker: DiffMarker,
) -> Line {
Line {
line_number,
diff_marker,
content: gpui::SharedString::new(content),
line_number_col_width: px(0.),
}
}
pub(crate) fn code_view(state: CodeViewState, lines: Lines) -> CodeView {
CodeView { state, lines }
}
impl FromIterator<Line> for Lines {
fn from_iter<T: IntoIterator<Item = Line>>(iter: T) -> Self {
Lines(Rc::new(iter.into_iter().collect()))
}
}
impl gpui::RenderOnce for CodeView {
fn render(self, window: &mut gpui::Window, cx: &mut gpui::App) -> impl gpui::IntoElement {
let digits = self
.lines
.0
.last()
.map(|l| l.line_number.to_string().len())
.unwrap_or(0);
let text_style = window.text_style();
let font_size = text_style.font_size.to_pixels(window.rem_size());
let font_id = window.text_system().resolve_font(&gpui::font("Menlo"));
let line_number_col_width = window
.text_system()
.ch_advance(font_id, font_size)
.unwrap_or(px(7.2))
* digits;
list(self.state.0, move |i, _window, _app| {
let mut line = self.lines.0[i].clone();
line.line_number_col_width = line_number_col_width;
div()
.flex()
.flex_row()
.items_start()
.w_full()
.child(line)
.into_any_element()
})
}
}
impl gpui::RenderOnce for Line {
fn render(self, _window: &mut gpui::Window, cx: &mut gpui::App) -> impl IntoElement {
let theme = app::current_theme(cx);
div()
.flex()
.flex_row()
.font_family("Menlo")
.text_color(theme.colors.text)
.child(
div()
.bg(theme.colors.surface)
.w(self.line_number_col_width)
.text_align(gpui::TextAlign::Right)
.child(self.line_number.to_string()),
)
.child(self.content)
}
}