Copy button (#271)

* Update diff.rs

* Fixes

* More fixes

* More fixes...

* Cargo fmt

* fmt

* Trim extra

* cargo +nightly fmt

* Update 'Copy ASM' button text to include emoji
This commit is contained in:
Franco M
2025-11-19 02:00:20 -03:00
committed by GitHub
parent 67b237eab6
commit b2dcecc5d8

View File

@@ -1,12 +1,18 @@
use std::cmp::Ordering;
use egui::{Id, Layout, RichText, ScrollArea, TextEdit, Ui, Widget, text::LayoutJob};
use objdiff_core::{
build::BuildStatus,
diff::{
DiffObjConfig, ObjectDiff, SymbolDiff,
data::BYTES_PER_ROW,
display::{ContextItem, HoverItem, HoverItemColor, SymbolFilter, SymbolNavigationKind},
display::{
ContextItem, DiffText, HoverItem, HoverItemColor, SymbolFilter, SymbolNavigationKind,
display_row,
},
},
obj::{Object, Symbol},
obj::{InstructionArgValue, Object, Symbol},
util::ReallySigned,
};
use time::format_description;
@@ -64,6 +70,51 @@ impl<'a> DiffColumnContext<'a> {
pub fn id(&self) -> Option<&str> { self.symbol.map(|(symbol, _, _)| symbol.name.as_str()) }
}
/// Obtains the assembly text for a given symbol diff, suitable for copying to clipboard.
fn get_asm_text(
obj: &Object,
symbol_diff: &SymbolDiff,
symbol_idx: usize,
diff_config: &DiffObjConfig,
) -> String {
let mut asm_text = String::new();
for ins_row in &symbol_diff.instruction_rows {
let mut line = String::new();
let result = display_row(obj, symbol_idx, ins_row, diff_config, |segment| {
let text = match segment.text {
DiffText::Basic(text) => text.to_string(),
DiffText::Line(num) => format!("{num} "),
DiffText::Address(addr) => format!("{addr:x}:"),
DiffText::Opcode(mnemonic, _op) => format!("{mnemonic} "),
DiffText::Argument(arg) => match arg {
InstructionArgValue::Signed(v) => format!("{:#x}", ReallySigned(v)),
InstructionArgValue::Unsigned(v) => format!("{v:#x}"),
InstructionArgValue::Opaque(v) => v.into_owned(),
},
DiffText::BranchDest(addr) => format!("{addr:x}"),
DiffText::Symbol(sym) => sym.demangled_name.as_ref().unwrap_or(&sym.name).clone(),
DiffText::Addend(addend) => match addend.cmp(&0i64) {
Ordering::Greater => format!("+{addend:#x}"),
Ordering::Less => format!("-{:#x}", -addend),
_ => String::new(),
},
DiffText::Spacing(n) => " ".repeat(n.into()),
DiffText::Eol => "\n".to_string(),
};
line.push_str(&text);
Ok(())
});
if result.is_ok() {
asm_text.push_str(line.trim_end());
asm_text.push('\n');
}
}
asm_text
}
#[must_use]
pub fn diff_view_ui(
ui: &mut Ui,
@@ -208,16 +259,33 @@ pub fn diff_view_ui(
// Third row
if left_ctx.has_symbol() && right_ctx.has_symbol() {
if (state.current_view == View::FunctionDiff
&& ui
.button("Change target")
.on_hover_text_at_pointer("Choose a different symbol to use as the target")
.clicked()
|| hotkeys::consume_change_target_shortcut(ui.ctx()))
&& let Some(symbol_ref) = state.symbol_state.right_symbol.as_ref()
{
ret = Some(DiffViewAction::SelectingLeft(symbol_ref.clone()));
}
ui.horizontal(|ui| {
if (state.current_view == View::FunctionDiff
&& ui
.button("Change target")
.on_hover_text_at_pointer(
"Choose a different symbol to use as the target",
)
.clicked()
|| hotkeys::consume_change_target_shortcut(ui.ctx()))
&& let Some(symbol_ref) = state.symbol_state.right_symbol.as_ref()
{
ret = Some(DiffViewAction::SelectingLeft(symbol_ref.clone()));
}
// Copy target ASM button.
if state.current_view == View::FunctionDiff
&& let Some((_, symbol_diff, symbol_idx)) = left_ctx.symbol
&& let Some((obj, _)) = left_ctx.obj
&& ui
.button("📋 Copy ASM")
.on_hover_text_at_pointer("Copy assembly to clipboard")
.clicked()
{
let asm_text = get_asm_text(obj, symbol_diff, symbol_idx, diff_config);
ui.ctx().copy_text(asm_text);
}
});
} else if left_ctx.status.success && !left_ctx.has_symbol() {
ui.horizontal(|ui| {
let mut search = state.search.clone();
@@ -374,6 +442,18 @@ pub fn diff_view_ui(
{
ret = Some(DiffViewAction::SelectingRight(symbol_ref.clone()));
}
// Copy base ASM button.
if let Some((_, symbol_diff, symbol_idx)) = right_ctx.symbol
&& let Some((obj, _)) = right_ctx.obj
&& ui
.button("📋 Copy ASM")
.on_hover_text_at_pointer("Copy assembly to clipboard")
.clicked()
{
let asm_text = get_asm_text(obj, symbol_diff, symbol_idx, diff_config);
ui.ctx().copy_text(asm_text);
}
}
} else if right_ctx.status.success && !right_ctx.has_symbol() {
let mut search = state.search.clone();