Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Visual mode support #97

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@ members = [
"rair",
"test_file",
"trees",
"visual",
]

[workspace.dependencies]
base64 = "0.22.1"
bitflags = "2.6.0"
clap = "4.5.17"
cli-clipboard = "0.4.0"
copypasta = "0.10.1"
directories = "5.0.1"
err-derive = "0.3.1"
flate2 = "1.0.33"
Expand All @@ -24,22 +27,25 @@ nom = "7.1.3"
parking_lot="0.12.3"
pest = "2.7.12"
pest_derive = "2.7.12"
ratatui = "0.28.1"
rustyline = "14.0.0"
rustyline-derive = "0.10.0"
serde = "1.0"
serde_cbor = "0.11.2"
serde_json = "1.0"
tempfile = "3.12.0"
winit = "0.30.5"
yansi = "1.0.1"

rair = {path = "./rair"}
rair-cmd = {path = "./cmd"}
rair-core = {path = "./core"}
rair-env = {path = "./env"}
rair-eval = {path = "./eval"}
test_file = {path = "./test_file"}
rair-io = {path = "./io"}
rair-trees = {path = "./trees"}

rair-visual = {path = "./visual"}
[profile.release]
codegen-units = 1
lto = "fat"
Expand Down
1 change: 0 additions & 1 deletion core/src/helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ pub struct CmdFunctions {
}

#[derive(Copy, Clone, PartialEq, Debug, Serialize, Deserialize)]
#[non_exhaustive]
pub enum AddrMode {
Vir,
Phy,
Expand Down
4 changes: 2 additions & 2 deletions core/src/hex/hex_env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{is_color, Core, Writer};
use std::io::Write;
use yansi::Paint;

#[derive(Clone)]
#[derive(Clone, Default)]
pub struct HexEnv {
// color for banner and offsets
pub banner: (u8, u8, u8),
Expand Down Expand Up @@ -89,7 +89,7 @@ impl HexEnv {
separator: String::new(),
}
}
pub(super) fn get_env(&mut self, core: &mut Core) -> &Self {
pub fn get_env(&mut self, core: &mut Core) -> &Self {
let env = core.env.read();
let color = env.get_str("hex.headerColor").unwrap();
self.banner = env.get_color(color).unwrap();
Expand Down
1 change: 1 addition & 0 deletions core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ pub use self::commands::*;
pub use self::core::*;
pub use self::diff::*;
pub use self::helper::*;
pub use self::hex::*;
pub use self::io::*;
pub use self::writer::*;
23 changes: 15 additions & 8 deletions eval/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use core::mem;
use core::mem::{replace, swap, take};
use rair_cmd::{Argument, Cmd, ParseTree, RedPipe};
use rair_core::{Core, Writer};
use std::{
Expand All @@ -7,6 +7,13 @@
process::{Child, Command, Stdio},
};

pub fn rair_eval_no_out(core: &mut Core, line: &str) {
let stdout = take(&mut core.stdout);
let stderr = take(&mut core.stderr);
rair_eval(core, line);
core.stdout = stdout;
core.stderr = stderr;

Check warning on line 15 in eval/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

eval/src/lib.rs#L10-L15

Added lines #L10 - L15 were not covered by tests
}
pub fn rair_eval(core: &mut Core, line: &str) {
match ParseTree::construct(line) {
Ok(tree) => evaluate(core, tree),
Expand Down Expand Up @@ -37,17 +44,17 @@
let mut child: Option<Child> = None;
match *cmd.red_pipe {
RedPipe::Redirect(arg) => match create_redirect(core, *arg) {
Ok(out) => stdout = Some(mem::replace(&mut core.stdout, out)),
Ok(out) => stdout = Some(replace(&mut core.stdout, out)),

Check warning on line 47 in eval/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

eval/src/lib.rs#L47

Added line #L47 was not covered by tests
Err(e) => return writeln!(core.stderr, "{e}").unwrap(),
},
RedPipe::RedirectCat(arg) => match create_redirect_cat(core, *arg) {
Ok(out) => stdout = Some(mem::replace(&mut core.stdout, out)),
Ok(out) => stdout = Some(replace(&mut core.stdout, out)),

Check warning on line 51 in eval/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

eval/src/lib.rs#L51

Added line #L51 was not covered by tests
Err(e) => return writeln!(core.stderr, "{e}").unwrap(),
},
RedPipe::Pipe(arg) => match create_pipe(core, arg) {
Ok((process, writer)) => {
child = Some(process);
stdout = Some(mem::replace(&mut core.stdout, writer));
stdout = Some(replace(&mut core.stdout, writer));

Check warning on line 57 in eval/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

eval/src/lib.rs#L57

Added line #L57 was not covered by tests
}
Err(e) => return writeln!(core.stderr, "{e}").unwrap(),
},
Expand Down Expand Up @@ -123,13 +130,13 @@
// change stderr and stdout
let mut stderr = Writer::new_buf();
let mut stdout = Writer::new_buf();
mem::swap(&mut core.stderr, &mut stderr);
mem::swap(&mut core.stdout, &mut stdout);
swap(&mut core.stderr, &mut stderr);
swap(&mut core.stdout, &mut stdout);

Check warning on line 134 in eval/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

eval/src/lib.rs#L133-L134

Added lines #L133 - L134 were not covered by tests
// run command
run_cmd(core, cmd);
// restore stderr and stdout
mem::swap(&mut core.stderr, &mut stderr);
mem::swap(&mut core.stdout, &mut stdout);
swap(&mut core.stderr, &mut stderr);
swap(&mut core.stdout, &mut stdout);

Check warning on line 139 in eval/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

eval/src/lib.rs#L138-L139

Added lines #L138 - L139 were not covered by tests

let err = stderr.utf8_string().unwrap();
if err.is_empty() {
Expand Down
1 change: 1 addition & 0 deletions rair/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ rair-core = {workspace = true}
rair-eval = {workspace = true}
rair-io = {workspace = true}
rair-trees = {workspace = true}
rair-visual = {workspace = true}
rustyline = {workspace = true}
rustyline-derive = {workspace = true}
yansi = {workspace = true}
Expand Down
2 changes: 2 additions & 0 deletions rair/src/rair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@
use core::mem;
use init::init_editor_from_core;
use rair_core::{panic_msg, Core, Writer};
use rair_visual::register_commands;
use rpel::prompt_read_parse_evaluate_loop;

fn main() {
let mut core = Core::new();
register_commands(&mut core);

Check warning on line 19 in rair/src/rair.rs

View check run for this annotation

Codecov / codecov/patch

rair/src/rair.rs#L19

Added line #L19 was not covered by tests
let editor = init_editor_from_core(&mut core);
let args = Args::parse().unwrap_or_else(|e| panic_msg(&mut core, &e, ""));
match args {
Expand Down
13 changes: 13 additions & 0 deletions visual/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "rair-visual"
version = "0.1.0"
edition = "2021"

[dependencies]
cli-clipboard = { workspace = true}
parking_lot = {workspace = true}
rair-core ={workspace = true}
rair-eval = {workspace = true}
rair-env = {workspace = true}
rair-io = {workspace = true}
ratatui = {workspace = true}
9 changes: 9 additions & 0 deletions visual/src/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
mod visual_hex;

use rair_core::Core;
use visual_hex::VisualHex;

pub fn register_commands(core: &mut Core) {
let vx = VisualHex::new(core);
core.add_command(vx);

Check warning on line 8 in visual/src/commands/mod.rs

View check run for this annotation

Codecov / codecov/patch

visual/src/commands/mod.rs#L6-L8

Added lines #L6 - L8 were not covered by tests
}
35 changes: 35 additions & 0 deletions visual/src/commands/visual_hex/addresses.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use crate::visual_hex::VisualHexEnv;

use super::VisualHex;
use rair_core::Core;
use ratatui::prelude::*;
use std::iter::once;

impl VisualHex {
/// Finds the maximum width of any address that will be currently rendered
pub(super) fn max_address_str_width(&mut self, core: &mut Core, chunk: &Rect) -> u16 {
let loc = core.get_loc();
let size = self.calculate_bytes_to_render(chunk);

Check warning on line 12 in visual/src/commands/visual_hex/addresses.rs

View check run for this annotation

Codecov / codecov/patch

visual/src/commands/visual_hex/addresses.rs#L10-L12

Added lines #L10 - L12 were not covered by tests
// we don't put the address of the last bytes, but we put the address
// and then the last byte is 16 + that address.
let max_loc = loc.saturating_add(size).saturating_sub(16);
format!("0x{:08x} ", max_loc).len() as u16

Check warning on line 16 in visual/src/commands/visual_hex/addresses.rs

View check run for this annotation

Codecov / codecov/patch

visual/src/commands/visual_hex/addresses.rs#L15-L16

Added lines #L15 - L16 were not covered by tests
}
/// renders the column of all addresses + header
pub(super) fn render_addresses(

Check warning on line 19 in visual/src/commands/visual_hex/addresses.rs

View check run for this annotation

Codecov / codecov/patch

visual/src/commands/visual_hex/addresses.rs#L19

Added line #L19 was not covered by tests
&mut self,
f: &mut Frame,
chunk: Rect,
core: &mut Core,
env: &VisualHexEnv,
) {
// TODO center the header
let banner = env.render_addresses_banner(core);
let loc = core.get_loc();

Check warning on line 28 in visual/src/commands/visual_hex/addresses.rs

View check run for this annotation

Codecov / codecov/patch

visual/src/commands/visual_hex/addresses.rs#L27-L28

Added lines #L27 - L28 were not covered by tests
// TODO overflow here
let addresses = (1..chunk.height as u64).map(|i| env.render_addresses(loc + 16 * (i - 1)));
let lines: Vec<_> = once(banner).chain(addresses).collect();
let text = Text::from(lines);
f.render_widget(text, chunk);

Check warning on line 33 in visual/src/commands/visual_hex/addresses.rs

View check run for this annotation

Codecov / codecov/patch

visual/src/commands/visual_hex/addresses.rs#L30-L33

Added lines #L30 - L33 were not covered by tests
}
}
47 changes: 47 additions & 0 deletions visual/src/commands/visual_hex/ascii.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use crate::visual_hex::VisualHexEnv;

use super::{mode::Mode, VisualHex};
use rair_core::Core;
use ratatui::prelude::*;
use std::collections::BTreeMap;

impl VisualHex {
fn ascii_line<'a>(

Check warning on line 9 in visual/src/commands/visual_hex/ascii.rs

View check run for this annotation

Codecov / codecov/patch

visual/src/commands/visual_hex/ascii.rs#L9

Added line #L9 was not covered by tests
&self,
loc: u64,
data: &BTreeMap<u64, u8>,
env: &'a VisualHexEnv,
) -> Line<'a> {
let mut spans = Vec::with_capacity(16);
for j in 0..16 {
let byte = data.get(&(j + loc)).copied();
let span = env.render_ascii(byte);
let span = match &self.mode {
Mode::Edit(editor) => editor.span_ascii(span, loc + j),
Mode::Select(selector) => selector.span_ascii(span, loc + j),
_ => span,

Check warning on line 22 in visual/src/commands/visual_hex/ascii.rs

View check run for this annotation

Codecov / codecov/patch

visual/src/commands/visual_hex/ascii.rs#L15-L22

Added lines #L15 - L22 were not covered by tests
};
spans.push(span);

Check warning on line 24 in visual/src/commands/visual_hex/ascii.rs

View check run for this annotation

Codecov / codecov/patch

visual/src/commands/visual_hex/ascii.rs#L24

Added line #L24 was not covered by tests
}
Line::default().spans(spans)

Check warning on line 26 in visual/src/commands/visual_hex/ascii.rs

View check run for this annotation

Codecov / codecov/patch

visual/src/commands/visual_hex/ascii.rs#L26

Added line #L26 was not covered by tests
}
pub(super) fn render_ascii(

Check warning on line 28 in visual/src/commands/visual_hex/ascii.rs

View check run for this annotation

Codecov / codecov/patch

visual/src/commands/visual_hex/ascii.rs#L28

Added line #L28 was not covered by tests
&self,
f: &mut Frame,
chunk: Rect,
core: &Core,
data: &BTreeMap<u64, u8>,
env: &VisualHexEnv,
) {
let mut lines: Vec<Line<'_>> = Vec::with_capacity(chunk.height as usize + 1);
lines.push(env.render_ascii_banner());

Check warning on line 37 in visual/src/commands/visual_hex/ascii.rs

View check run for this annotation

Codecov / codecov/patch

visual/src/commands/visual_hex/ascii.rs#L36-L37

Added lines #L36 - L37 were not covered by tests

let loc = core.get_loc();

Check warning on line 39 in visual/src/commands/visual_hex/ascii.rs

View check run for this annotation

Codecov / codecov/patch

visual/src/commands/visual_hex/ascii.rs#L39

Added line #L39 was not covered by tests

for i in 0..chunk.height as u64 {
lines.push(self.ascii_line(loc + i * 16, data, env));

Check warning on line 42 in visual/src/commands/visual_hex/ascii.rs

View check run for this annotation

Codecov / codecov/patch

visual/src/commands/visual_hex/ascii.rs#L41-L42

Added lines #L41 - L42 were not covered by tests
}
let txt = Text::from(lines);
f.render_widget(txt, chunk);

Check warning on line 45 in visual/src/commands/visual_hex/ascii.rs

View check run for this annotation

Codecov / codecov/patch

visual/src/commands/visual_hex/ascii.rs#L44-L45

Added lines #L44 - L45 were not covered by tests
}
}
51 changes: 51 additions & 0 deletions visual/src/commands/visual_hex/command.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use ratatui::{
layout::{Position, Rect},
text::Line,
Frame,
};
use std::cmp::max;

#[derive(Default)]
pub struct Command {
input: String,
cursor: usize,
}

impl Command {
pub fn move_cursor_left(&mut self) {
self.cursor = self.cursor.saturating_sub(1);

Check warning on line 16 in visual/src/commands/visual_hex/command.rs

View check run for this annotation

Codecov / codecov/patch

visual/src/commands/visual_hex/command.rs#L15-L16

Added lines #L15 - L16 were not covered by tests
}
pub fn move_cursor_right(&mut self) {
self.cursor = max(self.cursor.saturating_add(1), self.input.len())

Check warning on line 19 in visual/src/commands/visual_hex/command.rs

View check run for this annotation

Codecov / codecov/patch

visual/src/commands/visual_hex/command.rs#L18-L19

Added lines #L18 - L19 were not covered by tests
}
pub fn delete_char(&mut self) {
if self.cursor == 0 {

Check warning on line 22 in visual/src/commands/visual_hex/command.rs

View check run for this annotation

Codecov / codecov/patch

visual/src/commands/visual_hex/command.rs#L21-L22

Added lines #L21 - L22 were not covered by tests
return;
}
let from_left_to_custor = self.cursor - 1;

Check warning on line 25 in visual/src/commands/visual_hex/command.rs

View check run for this annotation

Codecov / codecov/patch

visual/src/commands/visual_hex/command.rs#L25

Added line #L25 was not covered by tests
// Getting all characters before the selected character.
let before_char_to_delete = self.input.chars().take(from_left_to_custor);

Check warning on line 27 in visual/src/commands/visual_hex/command.rs

View check run for this annotation

Codecov / codecov/patch

visual/src/commands/visual_hex/command.rs#L27

Added line #L27 was not covered by tests
// Getting all characters after selected character.
let after_char_to_delete = self.input.chars().skip(self.cursor);
self.input = before_char_to_delete.chain(after_char_to_delete).collect();
self.move_cursor_left();

Check warning on line 31 in visual/src/commands/visual_hex/command.rs

View check run for this annotation

Codecov / codecov/patch

visual/src/commands/visual_hex/command.rs#L29-L31

Added lines #L29 - L31 were not covered by tests
}
pub fn enter_char(&mut self, c: char) {
let index = self

Check warning on line 34 in visual/src/commands/visual_hex/command.rs

View check run for this annotation

Codecov / codecov/patch

visual/src/commands/visual_hex/command.rs#L33-L34

Added lines #L33 - L34 were not covered by tests
.input
.char_indices()
.map(|(i, _)| i)
.nth(self.cursor)
.unwrap_or(self.input.len());
self.input.insert(index, c);
self.move_cursor_right();

Check warning on line 41 in visual/src/commands/visual_hex/command.rs

View check run for this annotation

Codecov / codecov/patch

visual/src/commands/visual_hex/command.rs#L37-L41

Added lines #L37 - L41 were not covered by tests
}
pub fn get_str(&self) -> &str {
&self.input

Check warning on line 44 in visual/src/commands/visual_hex/command.rs

View check run for this annotation

Codecov / codecov/patch

visual/src/commands/visual_hex/command.rs#L43-L44

Added lines #L43 - L44 were not covered by tests
}
pub fn render(&self, f: &mut Frame, chunk: Rect) {
let input = Line::from(format!(":{}", self.input));
f.render_widget(input, chunk);
f.set_cursor_position(Position::new(chunk.x + self.cursor as u16 + 1, chunk.y));

Check warning on line 49 in visual/src/commands/visual_hex/command.rs

View check run for this annotation

Codecov / codecov/patch

visual/src/commands/visual_hex/command.rs#L46-L49

Added lines #L46 - L49 were not covered by tests
}
}
Loading
Loading