mirror of
https://github.com/encounter/objdiff.git
synced 2026-07-10 12:18:36 -07:00
Implement go to next/previous difference (#313)
This commit is contained in:
@@ -50,9 +50,9 @@ pub fn end_pressed(ctx: &Context) -> bool { ctx.input_mut(|i| i.key_pressed(Key:
|
||||
|
||||
pub fn check_scroll_hotkeys(ui: &mut egui::Ui, include_small_increments: bool) {
|
||||
let ui_height = ui.available_rect_before_wrap().height();
|
||||
if up_pressed(ui.ctx()) && include_small_increments {
|
||||
if include_small_increments && consume_up_key(ui.ctx()) {
|
||||
ui.scroll_with_delta_animation(vec2(0.0, ui_height / 10.0), ScrollAnimation::none());
|
||||
} else if down_pressed(ui.ctx()) && include_small_increments {
|
||||
} else if include_small_increments && consume_down_key(ui.ctx()) {
|
||||
ui.scroll_with_delta_animation(vec2(0.0, -ui_height / 10.0), ScrollAnimation::none());
|
||||
} else if page_up_pressed(ui.ctx()) {
|
||||
ui.scroll_with_delta_animation(vec2(0.0, ui_height), ScrollAnimation::none());
|
||||
@@ -106,3 +106,15 @@ const CHANGE_BASE_SHORTCUT: KeyboardShortcut = KeyboardShortcut::new(Modifiers::
|
||||
pub fn consume_change_base_shortcut(ctx: &Context) -> bool {
|
||||
ctx.input_mut(|i| i.consume_shortcut(&CHANGE_BASE_SHORTCUT))
|
||||
}
|
||||
|
||||
const PREV_DIFF_SHORTCUT: KeyboardShortcut = KeyboardShortcut::new(Modifiers::CTRL, Key::ArrowUp);
|
||||
|
||||
pub fn consume_prev_diff_shortcut(ctx: &Context) -> bool {
|
||||
ctx.input_mut(|i| i.consume_shortcut(&PREV_DIFF_SHORTCUT))
|
||||
}
|
||||
|
||||
const NEXT_DIFF_SHORTCUT: KeyboardShortcut = KeyboardShortcut::new(Modifiers::CTRL, Key::ArrowDown);
|
||||
|
||||
pub fn consume_next_diff_shortcut(ctx: &Context) -> bool {
|
||||
ctx.input_mut(|i| i.consume_shortcut(&NEXT_DIFF_SHORTCUT))
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ use egui::{Id, Layout, RichText, ScrollArea, TextEdit, Ui, Widget, text::LayoutJ
|
||||
use objdiff_core::{
|
||||
build::BuildStatus,
|
||||
diff::{
|
||||
DiffObjConfig, ObjectDiff, SymbolDiff,
|
||||
DataDiffKind, DiffObjConfig, InstructionDiffKind, ObjectDiff, SymbolDiff,
|
||||
data::BYTES_PER_ROW,
|
||||
display::{
|
||||
ContextItem, DiffText, HoverItem, HoverItemColor, SymbolFilter, SymbolNavigationKind,
|
||||
@@ -185,6 +185,9 @@ pub fn diff_view_ui(
|
||||
let available_width = ui.available_width();
|
||||
let mut open_sections = (None, None);
|
||||
|
||||
let mut scroll_to_prev_diff = false;
|
||||
let mut scroll_to_next_diff = false;
|
||||
|
||||
render_header(ui, available_width, 2, |ui, column| {
|
||||
if column == 0 {
|
||||
// Left column
|
||||
@@ -450,6 +453,31 @@ pub fn diff_view_ui(
|
||||
{
|
||||
ret = Some(DiffViewAction::SelectingRight(symbol_ref.clone()));
|
||||
}
|
||||
needs_separator = true;
|
||||
}
|
||||
|
||||
if state.current_view == View::FunctionDiff
|
||||
|| state.current_view == View::DataDiff
|
||||
{
|
||||
if needs_separator {
|
||||
ui.separator();
|
||||
}
|
||||
if ui
|
||||
.button("⏴ Prev diff")
|
||||
.on_hover_text_at_pointer("Scroll to the previous difference (Ctrl+Up)")
|
||||
.clicked()
|
||||
|| hotkeys::consume_prev_diff_shortcut(ui.ctx())
|
||||
{
|
||||
scroll_to_prev_diff = true;
|
||||
}
|
||||
if ui
|
||||
.button("Next diff ⏵")
|
||||
.on_hover_text_at_pointer("Scroll to the next difference (Ctrl+Down)")
|
||||
.clicked()
|
||||
|| hotkeys::consume_next_diff_shortcut(ui.ctx())
|
||||
{
|
||||
scroll_to_next_diff = true;
|
||||
}
|
||||
}
|
||||
} else if right_ctx.status.success && !right_ctx.has_symbol() {
|
||||
let mut search = state.search.clone();
|
||||
@@ -493,14 +521,21 @@ pub fn diff_view_ui(
|
||||
return;
|
||||
}
|
||||
let instructions_len = left_symbol_diff.instruction_rows.len();
|
||||
let mut min_row = None;
|
||||
let mut max_row = None;
|
||||
render_table(
|
||||
ui,
|
||||
available_width,
|
||||
2,
|
||||
appearance.code_font.size,
|
||||
instructions_len,
|
||||
state.function_state.scroll_to_row,
|
||||
state.scroll_to_diff_row,
|
||||
|row, column| {
|
||||
if min_row.is_none() {
|
||||
min_row = Some(row.index());
|
||||
}
|
||||
max_row = Some(row.index());
|
||||
|
||||
if column == 0 {
|
||||
if let Some(action) = asm_col_ui(
|
||||
row,
|
||||
@@ -537,6 +572,27 @@ pub fn diff_view_ui(
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if scroll_to_prev_diff && let Some(min_row) = min_row {
|
||||
for (ins_idx, ins_diff) in
|
||||
right_diff.symbols[right_symbol_idx].instruction_rows.iter().enumerate().rev()
|
||||
{
|
||||
if ins_idx <= min_row && ins_diff.kind != InstructionDiffKind::None {
|
||||
ret = Some(DiffViewAction::ScrollToRow(ins_idx));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if scroll_to_next_diff && let Some(max_row) = max_row {
|
||||
for (ins_idx, ins_diff) in
|
||||
right_diff.symbols[right_symbol_idx].instruction_rows.iter().enumerate()
|
||||
{
|
||||
if ins_idx >= max_row - 1 && ins_diff.kind != InstructionDiffKind::None {
|
||||
ret = Some(DiffViewAction::ScrollToRow(ins_idx));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if let (
|
||||
View::DataDiff,
|
||||
Some((left_obj, _left_diff)),
|
||||
@@ -556,14 +612,21 @@ pub fn diff_view_ui(
|
||||
if total_rows == 0 {
|
||||
return;
|
||||
}
|
||||
let mut min_row = None;
|
||||
let mut max_row = None;
|
||||
render_table(
|
||||
ui,
|
||||
available_width,
|
||||
2,
|
||||
appearance.code_font.size,
|
||||
total_rows,
|
||||
None,
|
||||
state.scroll_to_diff_row,
|
||||
|row, column| {
|
||||
if min_row.is_none() {
|
||||
min_row = Some(row.index());
|
||||
}
|
||||
max_row = Some(row.index());
|
||||
|
||||
let i = row.index();
|
||||
let row_offset = i as u64 * BYTES_PER_ROW as u64;
|
||||
row.col(|ui| {
|
||||
@@ -591,6 +654,29 @@ pub fn diff_view_ui(
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
if scroll_to_prev_diff && let Some(min_row) = min_row {
|
||||
for (row_idx, diff_row) in right_symbol_diff.data_rows.iter().enumerate().rev() {
|
||||
if row_idx <= min_row
|
||||
&& (diff_row.segments.iter().any(|dd| dd.kind != DataDiffKind::None)
|
||||
|| diff_row.relocations.iter().any(|rd| rd.kind != DataDiffKind::None))
|
||||
{
|
||||
ret = Some(DiffViewAction::ScrollToRow(row_idx));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if scroll_to_next_diff && let Some(max_row) = max_row {
|
||||
for (row_idx, diff_row) in right_symbol_diff.data_rows.iter().enumerate() {
|
||||
if row_idx >= max_row - 1
|
||||
&& (diff_row.segments.iter().any(|dd| dd.kind != DataDiffKind::None)
|
||||
|| diff_row.relocations.iter().any(|rd| rd.kind != DataDiffKind::None))
|
||||
{
|
||||
ret = Some(DiffViewAction::ScrollToRow(row_idx));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Split view
|
||||
render_strips(ui, available_width, 2, |ui, column| {
|
||||
@@ -693,7 +779,7 @@ fn diff_col_ui(
|
||||
1,
|
||||
appearance.code_font.size,
|
||||
total_rows,
|
||||
None,
|
||||
state.scroll_to_diff_row,
|
||||
|row, _column| {
|
||||
let i = row.index();
|
||||
let row_offset = i as u64 * BYTES_PER_ROW as u64;
|
||||
@@ -717,7 +803,7 @@ fn diff_col_ui(
|
||||
1,
|
||||
appearance.code_font.size,
|
||||
symbol_diff.instruction_rows.len(),
|
||||
state.function_state.scroll_to_row,
|
||||
state.scroll_to_diff_row,
|
||||
|row, column| {
|
||||
if let Some(action) = asm_col_ui(
|
||||
row,
|
||||
|
||||
@@ -24,7 +24,6 @@ use crate::views::{
|
||||
pub struct FunctionViewState {
|
||||
left_highlight: HighlightKind,
|
||||
right_highlight: HighlightKind,
|
||||
pub scroll_to_row: Option<usize>,
|
||||
}
|
||||
|
||||
impl FunctionViewState {
|
||||
|
||||
@@ -118,6 +118,7 @@ pub struct DiffViewState {
|
||||
pub function_state: FunctionViewState,
|
||||
pub search: String,
|
||||
pub search_regex: Option<Regex>,
|
||||
pub scroll_to_diff_row: Option<usize>,
|
||||
pub build_running: bool,
|
||||
pub scratch_available: bool,
|
||||
pub scratch_running: bool,
|
||||
@@ -197,7 +198,7 @@ impl DiffViewState {
|
||||
|
||||
// Clear the scroll flags to prevent it from scrolling continuously.
|
||||
self.symbol_state.autoscroll_to_highlighted_symbols = false;
|
||||
self.function_state.scroll_to_row = None;
|
||||
self.scroll_to_diff_row = None;
|
||||
|
||||
let Some(action) = action else {
|
||||
return;
|
||||
@@ -366,7 +367,7 @@ impl DiffViewState {
|
||||
state.config.diff_obj_config.show_data_flow = value;
|
||||
}
|
||||
DiffViewAction::ScrollToRow(row) => {
|
||||
self.function_state.scroll_to_row = Some(row);
|
||||
self.scroll_to_diff_row = Some(row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user