diff --git a/Cargo.lock b/Cargo.lock index 27c91846..8713a3f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -890,11 +890,12 @@ dependencies = [ "serde_json", "serde_yaml", "signal-hook", + "strip-ansi-escapes", "structopt", "termios", "unicode-truncate", "unicode-width", - "vte", + "vte 0.8.0", "wasmer", "wasmer-wasi", ] @@ -1349,6 +1350,15 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "strip-ansi-escapes" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d63676e2abafa709460982ddc02a3bb586b6d15a49b75c212e06edd3933acee" +dependencies = [ + "vte 0.3.3", +] + [[package]] name = "strsim" version = "0.8.0" @@ -1559,6 +1569,12 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" +[[package]] +name = "utf8parse" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8772a4ccbb4e89959023bc5b7cb8623a795caa7092d99f3aa9501b9484d4557d" + [[package]] name = "utf8parse" version = "0.2.0" @@ -1583,6 +1599,15 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +[[package]] +name = "vte" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f42f536e22f7fcbb407639765c8fd78707a33109301f834a594758bedd6e8cf" +dependencies = [ + "utf8parse 0.1.1", +] + [[package]] name = "vte" version = "0.8.0" @@ -1590,7 +1615,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96cc8a191608603611e78c6ec11dafef37e3cca0775aeef1931824753e81711d" dependencies = [ "arrayvec", - "utf8parse", + "utf8parse 0.2.0", "vte_generate_state_changes", ] diff --git a/Cargo.toml b/Cargo.toml index 3becb4da..add92d48 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" serde_yaml = "0.8" signal-hook = "0.1.10" +strip-ansi-escapes = "0.1.0" structopt = "0.3" termios = "0.3" unicode-truncate = "0.1.1" diff --git a/src/main.rs b/src/main.rs index fdf4d585..ab2ae809 100644 --- a/src/main.rs +++ b/src/main.rs @@ -466,13 +466,7 @@ pub fn start(mut os_input: Box, opts: Opt) { draw.call(&[Value::I32(rows as i32), Value::I32(cols as i32)]).unwrap(); - buf_tx.send(format!( - "{}\n\r", - wasi_stdout(&wasi_env) - .lines() - .collect::>() - .join("\n\r") - )).unwrap(); + buf_tx.send(wasi_stdout(&wasi_env)).unwrap(); } PluginInstruction::Quit => break, i => panic!("Yo, dawg, nice job calling the wasm thread!\n {:?} is defo not implemented yet...", i), diff --git a/src/tab.rs b/src/tab.rs index 5d77d56a..2677e373 100644 --- a/src/tab.rs +++ b/src/tab.rs @@ -1,8 +1,8 @@ -use crate::os_input_output::OsApi; use crate::pty_bus::{PtyInstruction, VteEvent}; use crate::terminal_pane::{PositionAndSize, TerminalPane}; use crate::{boundaries::Boundaries, terminal_pane::PluginPane}; use crate::{layout::Layout, wasm_vm::PluginInstruction}; +use crate::{os_input_output::OsApi, utils::shared::pad_to_size}; use crate::{AppInstruction, SenderWithContext}; use std::collections::{BTreeMap, HashSet}; use std::os::unix::io::RawFd; @@ -215,10 +215,8 @@ impl Tab { } let mut new_pids = new_pids.iter(); for (layout, position_and_size) in positions_and_size { - dbg!("Loopy", &layout.plugin, position_and_size); // Just a regular terminal if let Some(plugin) = &layout.plugin { - dbg!("Starting here!"); let (pid_tx, pid_rx) = channel(); self.send_plugin_instructions .send(PluginInstruction::Load(pid_tx, plugin.clone())) @@ -229,13 +227,12 @@ impl Tab { *position_and_size, self.send_plugin_instructions.clone(), ); - dbg!(pid, position_and_size, plugin); self.panes .insert(PaneKind::PluginPane(pid), Box::new(new_plugin)); } else { // there are still panes left to fill, use the pids we received in this method let pid = new_pids.next().unwrap(); // if this crashes it means we got less pids than there are panes in this layout - let mut new_terminal = TerminalPane::new(*pid, *position_and_size); + let new_terminal = TerminalPane::new(*pid, *position_and_size); self.os_api.set_terminal_size_using_fd( new_terminal.pid, new_terminal.columns() as u16, @@ -547,31 +544,19 @@ impl Tab { self.full_screen_ws.columns as u16, self.full_screen_ws.rows as u16, ); - for (pane_kind, terminal) in self.panes.iter_mut() { - match pane_kind { - PaneKind::Terminal(pid) => { - if !self.panes_to_hide.contains(pid) { - boundaries.add_rect(&terminal); - if let Some(vte_output) = terminal.render() { - stdout - .write_all(&vte_output.as_bytes()) - .expect("cannot write to stdout"); - } - } - } - PaneKind::BuiltInPane(builtin_id) => { - // TBD - } - PaneKind::PluginPane(_) => { - boundaries.add_rect(&terminal); - if let Some(output) = terminal.render() { - write!( - stdout, - "{}\n\r", - output.lines().collect::>().join("\n\r") - ) - .unwrap(); - } + for (_, terminal) in self.panes.iter_mut() { + if !self.panes_to_hide.contains(&terminal.pid()) { + boundaries.add_rect(&terminal); + if let Some(vte_output) = terminal.render() { + // FIXME: Use Termion for cursor and style clearing? + write!( + stdout, + "\u{1b}[{};{}H\u{1b}[m{}", + terminal.y() + 1, + terminal.x() + 1, + pad_to_size(&vte_output, terminal.rows(), terminal.columns()) + ) + .expect("cannot write to stdout"); } } } diff --git a/src/terminal_pane/plugin_pane.rs b/src/terminal_pane/plugin_pane.rs index 3da072eb..3d525fa7 100644 --- a/src/terminal_pane/plugin_pane.rs +++ b/src/terminal_pane/plugin_pane.rs @@ -1,8 +1,10 @@ #![allow(clippy::clippy::if_same_then_else)] -use crate::{pty_bus::VteEvent, tab::Pane, wasm_vm::PluginInstruction, SenderWithContext}; +use crate::{ + pty_bus::VteEvent, tab::Pane, utils::shared::*, wasm_vm::PluginInstruction, SenderWithContext, +}; -use std::{os::unix::prelude::RawFd, sync::mpsc::channel}; +use std::{iter, os::unix::prelude::RawFd, sync::mpsc::channel}; use crate::terminal_pane::PositionAndSize; @@ -111,9 +113,10 @@ impl Pane for PluginPane { .unwrap(); self.should_render = false; - let goto_plugin_coordinates = format!("\u{1b}[{};{}H", self.position_and_size.y + 1, self.position_and_size.x + 1); // goto row/col and reset styles + let goto_plugin_coordinates = format!("\u{1b}[{};{}H", self.y() + 1, self.x() + 1); // goto row/col and reset styles let reset_styles = "\u{1b}[m"; - let vte_output = format!("{}{}{}", goto_plugin_coordinates, reset_styles, buf_rx.recv().unwrap()); + let buf = pad_to_size(&buf_rx.recv().unwrap(), self.rows(), self.columns()); + let vte_output = format!("{}{}{}", goto_plugin_coordinates, reset_styles, buf); Some(vte_output) } else { None @@ -121,7 +124,8 @@ impl Pane for PluginPane { } // FIXME: Really shouldn't be in this trait... fn pid(&self) -> RawFd { - todo!() + // FIXME: This looks like a really bad idea! + 100 + self.pid as RawFd } fn reduce_height_down(&mut self, count: usize) { self.position_and_size.y += count; diff --git a/src/terminal_pane/terminal_pane.rs b/src/terminal_pane/terminal_pane.rs index 70711a0e..fda74c2a 100644 --- a/src/terminal_pane/terminal_pane.rs +++ b/src/terminal_pane/terminal_pane.rs @@ -193,6 +193,7 @@ impl Pane for TerminalPane { } } character_styles.clear(); + vte_output.push('\n'); } self.mark_for_rerender(); Some(vte_output) diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 140eec18..0ea4c76f 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,2 +1,3 @@ pub mod consts; pub mod logging; +pub mod shared; diff --git a/src/utils/shared.rs b/src/utils/shared.rs new file mode 100644 index 00000000..3b8b5fbd --- /dev/null +++ b/src/utils/shared.rs @@ -0,0 +1,17 @@ +use std::iter; + +use strip_ansi_escapes::strip; + +// FIXME: Should this be an extension trait? Or here at all? +pub fn ansi_len(s: &str) -> usize { + strip(s.as_bytes()).unwrap().len() +} + +pub fn pad_to_size(s: &str, rows: usize, columns: usize) -> String { + s.lines() + .map(|l| [l, &str::repeat(" ", dbg!(columns) - dbg!(ansi_len(l)))].concat()) + .chain(iter::repeat(str::repeat(" ", columns))) + .take(rows) + .collect::>() + .join("\n\r") +}