vectorify

This commit is contained in:
mtgmonkey 2025-07-09 23:26:44 -04:00
parent b8cb2d07e4
commit 16b93fe88c

View file

@ -17,7 +17,6 @@
)] )]
use crate::enums::*; use crate::enums::*;
use crate::parsers::*;
use bpaf::Bpaf; use bpaf::Bpaf;
@ -150,25 +149,22 @@ pub struct Flags {
/// .subscription(Model::subscription) /// .subscription(Model::subscription)
/// .run() /// .run()
/// ``` /// ```
pub struct Model<'a> { pub struct Model {
/// location of cursor in user input line /// location of cursor in user input line
cursor_index: usize, cursor_index: usize,
/// fd of pty /// fd of pty
fd: Option<OwnedFd>, fd: Option<OwnedFd>,
/// user input line /// user input line
input: String, input: String,
/// all chars on screen
screen_buffer: [u8; 0x4000],
/// length of `screen_buffer`'s filled area
screen_buffer_index: usize,
/// path to shell /// path to shell
shell: String, shell: String,
screen: Vec<&'a str>, screen: Vec<Vec<String>>,
cursor: (usize, usize), cursor: (usize, usize),
dimensions: (usize, usize),
} }
impl Model<'_> { impl Model {
/// applies needed side effects when taking an input char /// applies needed side effects when taking an input char
#[expect( #[expect(
clippy::arithmetic_side_effects, clippy::arithmetic_side_effects,
@ -261,7 +257,7 @@ impl Model<'_> {
let red = read_from_option_fd(self.fd.as_ref()); let red = read_from_option_fd(self.fd.as_ref());
match red { match red {
Ok(red) => { Ok(red) => {
if let Err(error) = self.update_screen_buffer(&red) { if let Err(error) = self.update_screen(red) {
print_err(&error); print_err(&error);
} }
} }
@ -271,25 +267,74 @@ impl Model<'_> {
} }
} }
} }
/*
/// reads from the pty and adds it to the buffer /// reads from the pty and adds it to the buffer
#[expect( #[expect(
clippy::arithmetic_side_effects, clippy::arithmetic_side_effects,
clippy::indexing_slicing, clippy::indexing_slicing,
reason = "all is bound checked" reason = "all is bound checked"
)] )]
fn update_screen_buffer(&mut self, vec: &[u8]) -> Result<(), Error> { fn update_screen_buffer(&mut self, vec: Vec<u8>) -> Result<(), Error> {
for chr in String::from_utf8_lossy(vec).ansi_parse() { for chr in String::from_utf8_lossy(&vec).ansi_parse() {
match chr { match chr {
Token::Text(txt) => { Token::Text(txt) => {
print_debug(&(String::from("[CHR]") + txt)); print_debug(&(String::from("[CHR]") + txt));
if self.screen_buffer_index < self.screen_buffer.len() { if self.screen_buffer_index < self.screen_buffer.len() {
self.screen_buffer[self.screen_buffer_index] = self.screen_buffer[self.screen_buffer_index] =
*txt.as_bytes().get(0).unwrap_or(&b'_'); *txt.as_bytes().get(0).unwrap_or(&b'_');
self.screen_buffer_index += 1; self.screen_buffer_index += 1;
}
}
Token::C0(c0) => print_debug(&(String::from("[C0]") + &format!("{:?}", c0))),
Token::EscapeSequence(seq) => {
print_debug(&(String::from("[SEQ]") + &format!("{:?}", seq)))
}
}
}
return Ok(());
}
*/
fn update_screen(&mut self, vec: Vec<u8>) -> Result<(), Error> {
for chr in String::from_utf8_lossy(&vec).ansi_parse() {
match chr {
Token::Text(chr) => {
print_debug(&(String::from("[CHR]") + chr));
if self.cursor.1 < self.dimensions.1 {
self.cursor.1 += 1;
} else {
if self.cursor.0 < self.dimensions.0 {
self.cursor.0 += 1;
self.cursor.1 = 1;
} else {
self.screen.remove(0);
self.cursor.1 = 1;
}
}
let res = self.write_chr_to_screen(chr);
}
Token::C0(c0) => {
print_debug(&(String::from("[C0]") + &format!("{:?}", c0)));
match c0 {
C0::SP => {
if self.cursor.1 < self.dimensions.1 {
self.cursor.1 += 1;
} else {
self.cursor.0 += 1;
self.cursor.1 = 1;
}
let res = self.write_chr_to_screen(" ");
}
C0::CR => self.cursor.1 = 1,
C0::LF => {
if self.cursor.0 < self.dimensions.0 {
self.cursor.0 += 1;
} else {
self.screen.remove(0);
}
}
_ => (),
} }
} }
Token::C0(c0) => print_debug(&(String::from("[C0]") + &format!("{:?}", c0))),
Token::EscapeSequence(seq) => { Token::EscapeSequence(seq) => {
print_debug(&(String::from("[SEQ]") + &format!("{:?}", seq))) print_debug(&(String::from("[SEQ]") + &format!("{:?}", seq)))
} }
@ -298,6 +343,22 @@ impl Model<'_> {
return Ok(()); return Ok(());
} }
fn write_chr_to_screen(&mut self, chr: &str) -> Result<(), Error> {
if self.dimensions.0 >= self.cursor.0 && self.dimensions.1 >= self.cursor.1 {
while self.screen.len() < self.cursor.0 {
self.screen.push(vec![]);
}
while self.screen[self.cursor.0 - 1].len() < self.cursor.1 {
self.screen[self.cursor.0 - 1].push("_".to_string());
}
self.screen[self.cursor.0 - 1].remove(self.cursor.1 - 1);
self.screen[self.cursor.0 - 1].insert(self.cursor.1 - 1, chr.to_string());
} else {
return Err(Error::IndexOutOfBounds);
}
Ok(())
}
/// view logic for model\ /// view logic for model\
/// TODO add wide char support\ /// TODO add wide char support\
/// TODO bound check /// TODO bound check
@ -309,6 +370,7 @@ impl Model<'_> {
reason = "TODO" reason = "TODO"
)] )]
pub fn view(&self) -> Element<'_, Msg> { pub fn view(&self) -> Element<'_, Msg> {
/*
let (left, right) = let (left, right) =
String::from_utf8_lossy(&self.screen_buffer[..self.screen_buffer_index]) String::from_utf8_lossy(&self.screen_buffer[..self.screen_buffer_index])
.rsplit_once('\n') .rsplit_once('\n')
@ -326,10 +388,15 @@ impl Model<'_> {
return (tup.0.to_owned(), tup.1.to_owned()); return (tup.0.to_owned(), tup.1.to_owned());
}, },
); );
*/
let mut body = String::new();
for row in &self.screen {
body += &row.iter().map(|a| a.to_owned()).collect::<String>();
body += "\n";
}
return scrollable(column![ return scrollable(column![
text(left), text(body),
row![ row![
text(right),
text(&self.input[..(self.cursor_index)]), text(&self.input[..(self.cursor_index)]),
if self.cursor_index < self.input.len() { if self.cursor_index < self.input.len() {
row![ row![
@ -357,13 +424,11 @@ impl Model<'_> {
} }
} }
impl Default for Model<'_> { impl Default for Model {
#[inline] #[inline]
#[expect(clippy::undocumented_unsafe_blocks, reason = "clippy be trippin")] #[expect(clippy::undocumented_unsafe_blocks, reason = "clippy be trippin")]
fn default() -> Self { fn default() -> Self {
let mut me = Self { let mut me = Self {
screen_buffer: [0; 0x4000],
screen_buffer_index: 0,
cursor_index: 0, cursor_index: 0,
fd: None, fd: None,
input: String::new(), input: String::new(),
@ -374,6 +439,7 @@ impl Default for Model<'_> {
), ),
screen: vec![], screen: vec![],
cursor: (1, 1), cursor: (1, 1),
dimensions: (25, 80),
}; };
me.fd = spawn_pty_with_shell(&me.shell).ok(); me.fd = spawn_pty_with_shell(&me.shell).ok();
let mut nored = true; let mut nored = true;
@ -381,7 +447,7 @@ impl Default for Model<'_> {
let red = read_from_option_fd(me.fd.as_ref()); let red = read_from_option_fd(me.fd.as_ref());
if let Ok(red) = red { if let Ok(red) = red {
nored = false; nored = false;
if let Err(error) = me.update_screen_buffer(&red) { if let Err(error) = me.update_screen(red) {
print_err(&error); print_err(&error);
} }
} }