summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2017-12-17 02:30:53 -0800
committeriximeow <me@iximeow.net>2017-12-17 02:30:53 -0800
commitc35796ef070e6b33c5cf3e961a6c55fe817fb72d (patch)
treedbc6ecfb2d094c6d7ed756093ad719287d857daf
parent582351d837cb25680a3d7ae7345cf82479a3adf8 (diff)
add simultaneous binary/hex views, notion of selected view
-rw-r--r--main.rs157
1 files changed, 126 insertions, 31 deletions
diff --git a/main.rs b/main.rs
index 9792daf..b46cb48 100644
--- a/main.rs
+++ b/main.rs
@@ -166,12 +166,46 @@ impl Edits {
}
trait EditMode {
- fn render_bytes(&self, cursor: u64, width: u16, start: u64, bytes: std::slice::Iter<u8>) -> String;
+ fn render_bytes(&self, cursor: u64, width: u16, selected: bool, start: u64, bytes: std::slice::Iter<u8>) -> String;
// translates from the width of the display (terminal)
// to the number of bytes this edit mode can display
fn element_width(&self, display_width: u16) -> u64;
fn dec_sub_elem(&mut self, amount: u64);
fn inc_sub_elem(&mut self, amount: u64);
+ fn name(&self) -> &str;
+}
+
+struct ASCIIMode {
+}
+
+impl EditMode for ASCIIMode {
+ fn render_bytes(&self, cursor: u64, width: u16, selected: bool, start: u64, bytes: std::slice::Iter<u8>) -> String {
+ let mut ascii_text = "".to_owned();
+ let mut i: usize = 0;
+ for b in bytes {
+ if cursor == start + i as u64 {
+ ascii_text.push_str(&format!("{}", color::Fg(color::Yellow)));
+ if selected {
+ ascii_text.push_str(&format!("{}", termion::style::Bold));
+ }
+ ascii_text.push_str(&format!("{}", ascii_or_dot(b.to_owned()) as char));
+ if selected {
+ ascii_text.push_str(&format!("{}", termion::style::Reset));
+ }
+ ascii_text.push_str(&format!("{}", color::Fg(color::Reset)));
+ } else {
+ ascii_text.push_str(&format!("{}", ascii_or_dot(b.to_owned()) as char));
+ }
+ i = i + 1;
+ }
+ ascii_text
+ }
+ fn element_width(&self, display_width: u16) -> u64 {
+ display_width as u64
+ }
+ fn dec_sub_elem(&mut self, amount: u64) { }
+ fn inc_sub_elem(&mut self, amount: u64) { }
+ fn name(&self) -> &str { &"ASCII" }
}
struct BinaryMode {
@@ -179,22 +213,23 @@ struct BinaryMode {
}
impl EditMode for BinaryMode {
- fn render_bytes(&self, cursor: u64, width: u16, start: u64, bytes: std::slice::Iter<u8>) -> String {
+ fn render_bytes(&self, cursor: u64, width: u16, selected: bool, start: u64, bytes: std::slice::Iter<u8>) -> String {
let mut text = "".to_owned();
-// let mut ascii_text = "".to_owned();
let col_size = 1;
let mut i: usize = 0;
for b in bytes {
if cursor == start + i as u64 {
text.push_str(&format!("{}", color::Fg(color::Yellow)));
-// ascii_text.push_str(&format!("{}", color::Fg(color::Yellow)));
+ if selected {
+ text.push_str(&format!("{}", termion::style::Bold));
+ }
text.push_str(&format!("{:08b}", b));
-// ascii_text.push_str(&format!("{}", ascii_or_dot(b.to_owned()) as char));
+ if selected {
+ text.push_str(&format!("{}", termion::style::Reset));
+ }
text.push_str(&format!("{}", color::Fg(color::Reset)));
-// ascii_text.push_str(&format!("{}", color::Fg(color::Reset)));
} else {
text.push_str(&format!("{:08b}", b));
-// ascii_text.push_str(&format!("{}", ascii_or_dot(b.to_owned()) as char));
}
if i % col_size == (col_size - 1) {
text.push_str(" ");
@@ -215,6 +250,7 @@ impl EditMode for BinaryMode {
fn inc_sub_elem(&mut self, amount: u64) {
self.sub_elem_idx = self.sub_elem_idx + amount as u8;
}
+ fn name(&self) -> &str { &"Binary" }
}
struct HexMode {
@@ -222,29 +258,24 @@ struct HexMode {
}
impl EditMode for HexMode {
- fn render_bytes(&self, cursor: u64, width: u16, start: u64, bytes: std::slice::Iter<u8>) -> String {
+ fn render_bytes(&self, cursor: u64, width: u16, selected: bool, start: u64, bytes: std::slice::Iter<u8>) -> String {
let mut text = "".to_owned();
let mut ascii_text = "".to_owned();
- let col_size = 4;
+ let col_size = 8;
let mut i: usize = 0;
- let selected = true;
for b in bytes {
if cursor == start + i as u64 {
text.push_str(&format!("{}", color::Fg(color::Yellow)));
- ascii_text.push_str(&format!("{}", color::Fg(color::Yellow)));
if selected {
text.push_str(&format!("{}", termion::style::Bold));
}
text.push_str(&format!("{:02x}", b));
- ascii_text.push_str(&format!("{}", ascii_or_dot(b.to_owned()) as char));
if selected {
text.push_str(&format!("{}", termion::style::Reset));
}
text.push_str(&format!("{}", color::Fg(color::Reset)));
- ascii_text.push_str(&format!("{}", color::Fg(color::Reset)));
} else {
text.push_str(&format!("{:02x}", b));
- ascii_text.push_str(&format!("{}", ascii_or_dot(b.to_owned()) as char));
}
if i % col_size == (col_size - 1) {
text.push_str(" ");
@@ -253,15 +284,7 @@ impl EditMode for HexMode {
}
i = i + 1;
}
- /*
- * 12 == "<address>: "
- * i / col_size for the extra space between columns
- * i * 3 for 3 characters per byte
- * + 1 for padding..
- */
- let hex_line_width = 12 + i / col_size + i * 3 + 1;
- let padding = format!("{: >line_width$}", "", line_width = width as usize - hex_line_width - i);
- format!("0x{:08x}: {}{}{}", start, text, padding, ascii_text).to_owned()
+ format!("0x{:08x}: {}", start, text).to_owned()
}
fn element_width(&self, display_width: u16) -> u64 {
(display_width as u64 - 13) / 17 * 4
@@ -272,6 +295,7 @@ impl EditMode for HexMode {
fn inc_sub_elem(&mut self, amount: u64) {
self.sub_elem_idx = self.sub_elem_idx + amount as u8;
}
+ fn name(&self) -> &str { &"Hex" }
}
struct Program<'a, 'b> {
@@ -289,13 +313,14 @@ struct Program<'a, 'b> {
edits: Edits,
status: String,
edit_views: Vec<&'b mut EditMode>,
- current_edit_idx: usize
+ current_edit_idx: usize,
+ ascii_mode: &'b mut EditMode
//screen: AlternateScreen<termion::raw::RawTerminal<std::io::Stdout>>
}
impl <'a, 'b> Program<'a, 'b> {
fn lines_to_draw(&self) -> u64 {
- self.view_byte_height() / self.edit_views.len() as u64
+ self.view_byte_height() / (self.edit_views.len() as u64)
}
fn seek_to(&mut self, dest: u64) {
self.cursor = dest;
@@ -357,6 +382,15 @@ impl <'a, 'b> Program<'a, 'b> {
self.seek = self.cursor - (self.cursor % bytes_per_line);
}
}
+
+ fn current_edit_view(&self) -> &EditMode {
+ if self.current_edit_idx == self.edit_views.len() {
+ self.ascii_mode
+ } else {
+ self.edit_views[self.current_edit_idx]
+// *self.edit_views.get_mut(self.current_edit_idx).unwrap()
+ }
+ }
}
fn launch_interface(w: u16, h: u16, filename: String) {
@@ -394,7 +428,8 @@ fn launch_interface(w: u16, h: u16, filename: String) {
&mut hexmode,
&mut binmode
],
- current_edit_idx: 0
+ current_edit_idx: 0,
+ ascii_mode: &mut ASCIIMode {}
};
tcsetattr(0, TCSANOW, &state.new_term).unwrap();
@@ -412,7 +447,8 @@ fn launch_interface(w: u16, h: u16, filename: String) {
enum Mode {
Edit,
- ReadAddress
+ ReadAddress,
+ ViewSelection
}
fn interface_loop(state: &mut Program) {
@@ -422,6 +458,23 @@ fn interface_loop(state: &mut Program) {
for input in stdin.events() {
match state.state {
+ Mode::ViewSelection => {
+ match input.unwrap() {
+ Event::Key(Key::Up) => {
+
+ }
+ Event::Key(Key::Down) => {
+
+ }
+ Event::Key(Key::Char(' ')) => {
+
+ }
+ Event::Key(Key::Esc) => {
+ state.state = Mode::Edit
+ }
+ _ => { }
+ }
+ }
Mode::Edit => {
match input.unwrap() {
Event::Key(Key::Char('\n')) => {
@@ -467,17 +520,27 @@ fn interface_loop(state: &mut Program) {
state.seek -= amount;
}
}
+ Event::Key(Key::Ctrl('a')) => {
+ state.status = "asf".to_string();
+ state.state = Mode::ViewSelection;
+ }
Event::Key(Key::Char('q')) => {
break;
}
+ // nahhhh..
+ Event::Key(Key::Ctrl('c')) => {
+ state.status = "caught ctrl-c?".to_string();
+ }
Event::Key(Key::Ctrl('\t')) => {
- // switch to previous edit mode
+ state.current_edit_idx -= 1;
+ state.current_edit_idx = state.current_edit_idx % (state.edit_views.len() + 1);
}
Event::Key(Key::Ctrl(x)) => {
state.status = format!("ctrl {}", x);
}
Event::Key(Key::Char('\t')) => {
- // switch to next edit mode
+ state.current_edit_idx += 1;
+ state.current_edit_idx = state.current_edit_idx % (state.edit_views.len() + 1);
}
// would prefer shift+t
Event::Unsupported(vec) => {
@@ -628,10 +691,36 @@ fn render_interface(state: &mut Program) {
for i in 0..state.lines_to_draw() {
for j in 0..state.edit_views.len() {
- let view = &state.edit_views[j];
+ let view = state.edit_views.get(j).unwrap();
let slice_start = width * i;
let slice_end = slice_start + width;
- write!(iface, "{}", view.render_bytes(state.cursor, state.width, start as u64 + slice_start, buffer[(slice_start as usize)..(slice_end as usize)].iter())).unwrap();
+ let line = view.render_bytes(
+ state.cursor,
+ state.width,
+ view.name() == state.current_edit_view().name(),
+ start as u64 + slice_start,
+ buffer[(slice_start as usize)..(slice_end as usize)].iter()
+ );
+ write!(iface, "{}", line).unwrap();
+ if j == 0 {
+ // ripped from HexMode display
+ /*
+ * 12 == "<address>: "
+ * i / col_size for the extra space between columns
+ * i * 3 for 3 characters per byte
+ * + 1 for padding..
+ */
+ let hex_line_width = 12 + width / 4 + width * 3 + 1;
+ let padding = format!("{: >line_width$}", "", line_width = state.width as usize - hex_line_width as usize - width as usize);
+ write!(iface, "{}", padding);
+ write!(iface, " {}", state.ascii_mode.render_bytes(
+ state.cursor,
+ state.width,
+ state.ascii_mode.name() == state.current_edit_view().name(),
+ start as u64 + slice_start,
+ buffer[(slice_start as usize)..(slice_end as usize)].iter()
+ ));
+ }
if i < state.lines_to_draw() - 1 || j < (state.edit_views.len() - 1) {
write!(iface, "\n").unwrap();
}
@@ -650,6 +739,12 @@ fn render_interface(state: &mut Program) {
write!(state.screen, "{}{:-^2$}", cursor::Goto(xmid-12, ymid+2), "", MODAL_WIDTH).unwrap();
write!(state.screen, "{}{}", cursor::Goto(xmid-9, ymid-0), state.input_buf.iter().cloned().collect::<String>()).unwrap();
}
+ Mode::ViewSelection => {
+ let xmid = state.width as u16 / 2;
+ let ymid = state.height as u16 / 2;
+ write!(state.screen, "{}{:-^2$}", cursor::Goto(xmid-12, ymid - 4), "", MODAL_WIDTH).unwrap();
+ write!(state.screen, "{}|{:-^2$}|", cursor::Goto(xmid-12, ymid - 3), "Select views", MODAL_WIDTH - 2).unwrap();
+ }
_ => {}
}
state.screen.flush().unwrap();