use ratatui::layout::Constraint;
use ratatui::prelude::Stylize;
use ratatui::widgets::block::Title;
use ratatui::widgets::{Block, Borders, Cell, Table, TableState};
use ratatui::{Frame, layout::Rect, style::Style, widgets::Row};
use super::{GREEN, ORANGE, PURPLE};
use crate::State;
pub fn draw_asm(state: &mut State, f: &mut Frame, asm: Rect) {
let mut rows = vec![];
let mut pc_index = None;
let mut function_name = None;
let mut tallest_function_len = 0;
for (index, a) in state.asm.iter().enumerate() {
if a.address == state.current_pc {
pc_index = Some(index);
if let Some(func_name) = &a.func_name {
function_name = Some(func_name.clone());
if func_name.len() > tallest_function_len {
tallest_function_len = func_name.len();
}
}
}
let addr_cell =
Cell::from(format!("0x{:02x}", a.address)).style(Style::default().fg(PURPLE));
let mut row = vec![addr_cell];
if let Some(function_name) = &a.func_name {
let function_cell = Cell::from(format!("{function_name}+{:02x}", a.offset))
.style(Style::default().fg(PURPLE));
row.push(function_cell);
} else {
row.push(Cell::from(""));
}
let inst = if a.inst.contains("\\t") {
let parts: Vec<&str> = a.inst.splitn(2, "\\t").collect();
format!("{:<8}{}", parts[0], parts[1])
} else {
a.inst.to_string()
};
let inst_cell = if let Some(pc_index) = pc_index {
if pc_index == index { Cell::from(inst).fg(GREEN) } else { Cell::from(inst).white() }
} else {
Cell::from(inst).dark_gray()
};
row.push(inst_cell);
rows.push(Row::new(row));
}
let title = if let Some(function_name) = function_name {
Title::from(format!("Instructions ({function_name})").fg(ORANGE))
} else {
Title::from("Instructions".fg(ORANGE))
};
if let Some(pc_index) = pc_index {
let widths = [
Constraint::Length(16),
Constraint::Length(tallest_function_len as u16 + 5),
Constraint::Fill(1),
];
let table = Table::new(rows, widths)
.block(Block::default().borders(Borders::TOP).title(title))
.row_highlight_style(Style::new().fg(GREEN))
.highlight_symbol(">>");
let start_offset = pc_index.saturating_sub(5);
let mut table_state =
TableState::default().with_offset(start_offset).with_selected(pc_index);
f.render_stateful_widget(table, asm, &mut table_state);
} else {
let block = Block::default().borders(Borders::TOP).title(title);
f.render_widget(block, asm);
}
}