diff --git a/src/main.rs b/src/main.rs index d8dd61db..a30525da 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,7 @@ use futures::future::join_all; use ::std::fmt::{self, Display, Formatter}; use std::cmp::max; use std::io::{Read, Write}; -use std::collections::{VecDeque}; +use std::collections::{VecDeque, HashMap}; use nix::pty::Winsize; use std::os::unix::io::RawFd; use ::std::thread; @@ -133,7 +133,7 @@ impl TerminalOutput { linebreak_indices: Vec::new(), display_rows: ws.ws_row, display_cols: ws.ws_col, - should_render: false, + should_render: true, pending_ansi_code: None, x_coords, } @@ -189,6 +189,12 @@ impl TerminalOutput { self.reflow_lines(); self.should_render = true; } + pub fn change_size(&mut self, ws: &Winsize) { + self.display_cols = ws.ws_col; + self.display_rows = ws.ws_row; + self.reflow_lines(); + self.should_render = true; + } fn reflow_lines (&mut self) { self.linebreak_indices.clear(); @@ -235,7 +241,15 @@ impl TerminalOutput { return vec![]; } if self.characters.len() == 0 { - return vec![]; + let mut output = vec![]; + let mut empty_line = vec![]; + for _ in 0..self.display_cols { + empty_line.push(&EMPTY_TERMINAL_CHARACTER); + } + for _ in 0..self.display_rows as usize { + output.push(Vec::from(empty_line.clone())); + } + return output } let mut output: VecDeque> = VecDeque::new(); let mut i = self.characters.len(); @@ -247,14 +261,10 @@ impl TerminalOutput { let mut next_newline_index = newline_indices.next(); let mut next_linebreak_index = linebreak_indices.next(); - let mut debug_messages = String::new(); loop { - debug_messages.push_str(&format!("\r\n*** i {:?}", i)); i -= 1; if let Some(newline_index) = next_newline_index { - debug_messages.push_str(&format!("Some(newline_index): {:?} == {:?}", newline_index, i)); if *newline_index == i + 1 { - debug_messages.push_str(&format!("equals i")); // pad line for _ in current_line.len()..self.display_cols as usize { current_line.push_back(&EMPTY_TERMINAL_CHARACTER); @@ -264,9 +274,7 @@ impl TerminalOutput { } } if let Some(linebreak_index) = next_linebreak_index { - debug_messages.push_str(&format!("Some(linebreak_index): {:?}", linebreak_index)); if *linebreak_index == i + 1 { - debug_messages.push_str(&format!("equals i")); // pad line for _ in current_line.len()..self.display_cols as usize { current_line.push_back(&EMPTY_TERMINAL_CHARACTER); @@ -295,18 +303,15 @@ impl TerminalOutput { } } - let mut debug_output = String::new(); - for line in output.iter() { - for t_char in line.iter() { - debug_output.push(t_char.character); - } - debug_output.push('\n'); - } Vec::from(output) } pub fn cursor_position_in_last_line (&self) -> usize { if self.cursor_position < self.characters.len() { let start_of_last_line = self.index_of_beginning_of_last_line(); + if self.cursor_position < start_of_last_line { + // TODO: why does this happen? + return self.display_cols as usize + }; let difference_from_last_newline = self.cursor_position - start_of_last_line; difference_from_last_newline } else { @@ -644,7 +649,7 @@ fn split_horizontally_with_gap (rect: &Winsize) -> (Winsize, Winsize) { enum ScreenInstruction { Pty(RawFd, VteEvent), Render, - AddTerminal(RawFd, Winsize), + AddTerminal(RawFd), WriteCharacter(u8), ResizeLeft, ResizeRight, @@ -653,12 +658,11 @@ enum ScreenInstruction { struct Screen { pub receiver: Receiver, - pub sender: Sender, + pub send_screen_instructions: Sender, full_screen_ws: Winsize, vertical_separator: TerminalCharacter, // TODO: better + terminals: HashMap, active_terminal: Option, - terminal1_output: Option, - terminal2_output: Option, os_api: Box, } @@ -667,130 +671,311 @@ impl Screen { let (sender, receiver): (Sender, Receiver) = channel(); Screen { receiver, - sender, + send_screen_instructions: sender, full_screen_ws: full_screen_ws.clone(), - vertical_separator: TerminalCharacter::new('|').ansi_code(String::from("\u{1b}[m")), // TODO: better - terminal1_output: None, - terminal2_output: None, + vertical_separator: TerminalCharacter::new('│').ansi_code(String::from("\u{1b}[m")), // TODO: better + terminals: HashMap::new(), active_terminal: None, os_api, } } - pub fn add_terminal(&mut self, pid: RawFd, ws: Winsize) { - if self.terminal1_output.is_none() { - let terminal1_x = 0; - self.terminal1_output = Some(TerminalOutput::new(pid, ws, terminal1_x)); + pub fn add_terminal(&mut self, pid: RawFd) { + if self.terminals.is_empty() { + let x = 0; + let new_terminal = TerminalOutput::new(pid, self.full_screen_ws.clone(), x); + self.os_api.set_terminal_size_using_fd(new_terminal.pid, new_terminal.display_cols, new_terminal.display_rows); + self.terminals.insert(pid, new_terminal); self.active_terminal = Some(pid); - } else if self.terminal2_output.is_none() { - let terminal2_x = self.terminal1_output.as_ref().unwrap().display_cols + 1; - self.terminal2_output = Some(TerminalOutput::new(pid, ws, terminal2_x)); } else { - panic!("cannot support more than 2 terminals atm"); + // TODO: check minimum size of active terminal + let (active_terminal_ws, active_terminal_x_coords) = { + let active_terminal = &self.get_active_terminal().unwrap(); + ( + Winsize { + ws_row: active_terminal.display_rows, + ws_col: active_terminal.display_cols, + ws_xpixel: 0, + ws_ypixel: 0, + }, + active_terminal.x_coords + ) + }; + let (left_winszie, right_winsize) = split_horizontally_with_gap(&active_terminal_ws); + let right_side_x = active_terminal_x_coords + left_winszie.ws_col + 1; + let new_terminal = TerminalOutput::new(pid, right_winsize, right_side_x); + self.os_api.set_terminal_size_using_fd(new_terminal.pid, right_winsize.ws_col, right_winsize.ws_row); + + { + let active_terminal_id = &self.get_active_terminal_id().unwrap(); + let active_terminal = &mut self.terminals.get_mut(&active_terminal_id).unwrap(); + active_terminal.change_size(&left_winszie); + } + + self.terminals.insert(pid, new_terminal); + let active_terminal_pid = self.get_active_terminal_id().unwrap(); + self.os_api.set_terminal_size_using_fd(active_terminal_pid, left_winszie.ws_col, left_winszie.ws_row); + self.active_terminal = Some(pid); + self.render(); + } + } + fn get_active_terminal (&self) -> Option<&TerminalOutput> { + match self.active_terminal { + Some(active_terminal) => self.terminals.get(&active_terminal), + None => None + } + } + fn get_active_terminal_id (&self) -> Option { + match self.active_terminal { + Some(active_terminal) => Some(self.terminals.get(&active_terminal).unwrap().pid), + None => None } } pub fn handle_pty_event(&mut self, pid: RawFd, event: VteEvent) { - if let Some(terminal_output) = self.terminal1_output.as_mut() { - if terminal_output.pid == pid { - terminal_output.handle_event(event); - return; - } - } - if let Some(terminal_output) = self.terminal2_output.as_mut() { - if terminal_output.pid == pid { - terminal_output.handle_event(event); - return; - } - } + let terminal_output = self.terminals.get_mut(&pid).unwrap(); + terminal_output.handle_event(event); } pub fn write_to_active_terminal(&self, byte: u8) { - if let Some(active_terminal) = &self.active_terminal { + if let Some(active_terminal_id) = &self.get_active_terminal_id() { let mut buffer = [byte]; - self.os_api.write(*active_terminal, &mut buffer).expect("failed to write to terminal"); - self.os_api.tcdrain(*active_terminal).expect("failed to drain terminal"); + self.os_api.write(*active_terminal_id, &mut buffer).expect("failed to write to terminal"); + self.os_api.tcdrain(*active_terminal_id).expect("failed to drain terminal"); } } + fn get_active_terminal_cursor_position(&self) -> usize { + let active_terminal = &self.get_active_terminal().unwrap(); + active_terminal.x_coords as usize + active_terminal.cursor_position_in_last_line() + } pub fn render (&mut self) { - let vte_output_terminal1 = self.terminal1_output.as_mut().unwrap().buffer_as_vte_output(); - let vte_output_terminal2 = self.terminal2_output.as_mut().unwrap().buffer_as_vte_output(); - - let mut vte_output_boundaries = String::new(); - for row in 0..self.full_screen_ws.ws_row { - vte_output_boundaries.push_str(&format!("\u{1b}[{};{}H\u{1b}[m", row + 1, self.terminal1_output.as_ref().unwrap().display_cols + 1)); // goto row/col - vte_output_boundaries.push_str(&self.vertical_separator.to_string()); + for (_pid, terminal) in self.terminals.iter_mut() { + if let Some(vte_output) = terminal.buffer_as_vte_output() { + if terminal.x_coords + terminal.display_cols < self.full_screen_ws.ws_col { + let boundary_x_coords = terminal.x_coords + terminal.display_cols; + let mut vte_output_boundaries = String::new(); + for row in 0..self.full_screen_ws.ws_row { + vte_output_boundaries.push_str(&format!("\u{1b}[{};{}H\u{1b}[m", row + 1, boundary_x_coords + 1)); // goto row/col + vte_output_boundaries.push_str(&self.vertical_separator.to_string()); + } + ::std::io::stdout().write_all(&vte_output_boundaries.as_bytes()).expect("cannot write to stdout"); + } + ::std::io::stdout().write_all(&vte_output.as_bytes()).expect("cannot write to stdout"); + } } - let left_terminal_cursor_position = self.terminal1_output.as_ref().unwrap().cursor_position_in_last_line(); - let right_terminal_cursor_position = self.terminal2_output.as_ref().unwrap().cursor_position_in_last_line(); - - let active_terminal = self.active_terminal.unwrap(); - if active_terminal == self.terminal1_output.as_ref().unwrap().pid { - let goto_cursor_position = format!("\r\u{1b}[{}C", left_terminal_cursor_position); - vte_output_boundaries.push_str(&goto_cursor_position); - } else { - let goto_cursor_position = format!("\r\u{1b}[{}C", right_terminal_cursor_position + (self.terminal1_output.as_ref().unwrap().display_cols + 1) as usize); - vte_output_boundaries.push_str(&goto_cursor_position); - } - if let Some(vte_output_terminal1) = vte_output_terminal1 { - ::std::io::stdout().write_all(&vte_output_terminal1.as_bytes()).expect("cannot write to stdout"); - } - if let Some(vte_output_terminal2) = vte_output_terminal2 { - ::std::io::stdout().write_all(&vte_output_terminal2.as_bytes()).expect("cannot write to stdout"); - } - // ::std::io::stdout().write_all(&vte_output_terminal2.as_bytes()).expect("cannot write to stdout"); - ::std::io::stdout().write_all(&vte_output_boundaries.as_bytes()).expect("cannot write to stdout"); + let active_terminal_cursor_position = self.get_active_terminal_cursor_position(); + let goto_cursor_position = format!("\r\u{1b}[{}C", active_terminal_cursor_position); + ::std::io::stdout().write_all(&goto_cursor_position.as_bytes()).expect("cannot write to stdout"); ::std::io::stdout().flush().expect("could not flush"); } + fn terminal_ids_directly_left_of(&self, id: &RawFd) -> Option> { + let mut ids = vec![]; + let terminal_to_check = self.terminals.get(id).unwrap(); + if terminal_to_check.x_coords == 0 { + return None; + } + for (pid, terminal) in self.terminals.iter() { + if terminal.x_coords + terminal.display_cols == terminal_to_check.x_coords - 1 { + ids.push(*pid); + } + } + if ids.is_empty() { + None + } else { + Some(ids) + } + } + fn terminal_ids_directly_right_of(&self, id: &RawFd) -> Option> { + let mut ids = vec![]; + let terminal_to_check = self.terminals.get(id).unwrap(); + for (pid, terminal) in self.terminals.iter() { + if terminal.x_coords == terminal_to_check.x_coords + terminal_to_check.display_cols + 1 { + ids.push(*pid); + } + } + if ids.is_empty() { + None + } else { + Some(ids) + } + } pub fn resize_left (&mut self) { - let terminal1_output = self.terminal1_output.as_mut().unwrap(); - let terminal2_output = self.terminal2_output.as_mut().unwrap(); - terminal1_output.reduce_width_left(10); - terminal2_output.increase_width_left(10); - self.os_api.set_terminal_size_using_fd(terminal1_output.pid, terminal1_output.display_cols, terminal1_output.display_rows); - self.os_api.set_terminal_size_using_fd(terminal2_output.pid, terminal2_output.display_cols, terminal2_output.display_rows); + // TODO: find out by how much we actually reduced and only reduce by that much + let count = 10; + if let Some(active_terminal_id) = self.get_active_terminal_id() { + let terminals_to_the_left = self.terminal_ids_directly_left_of(&active_terminal_id); + let terminals_to_the_right = self.terminal_ids_directly_right_of(&active_terminal_id); + match (terminals_to_the_left, terminals_to_the_right) { + (Some(terminals_to_the_left), Some(_terminals_to_the_right)) => { + let active_terminal = self.terminals.get_mut(&active_terminal_id).unwrap(); + active_terminal.increase_width_left(count); + self.os_api.set_terminal_size_using_fd( + active_terminal.pid, + active_terminal.display_cols, + active_terminal.display_rows + ); + for terminal_id in terminals_to_the_left { + let terminal = self.terminals.get_mut(&terminal_id).unwrap(); + terminal.reduce_width_left(count); + self.os_api.set_terminal_size_using_fd( + terminal.pid, + terminal.display_cols, + terminal.display_rows + ); + } + }, + (Some(terminals_to_the_left), None) => { + let active_terminal = self.terminals.get_mut(&active_terminal_id).unwrap(); + active_terminal.increase_width_left(count); + self.os_api.set_terminal_size_using_fd( + active_terminal.pid, + active_terminal.display_cols, + active_terminal.display_rows + ); + for terminal_id in terminals_to_the_left { + let terminal = self.terminals.get_mut(&terminal_id).unwrap(); + terminal.reduce_width_left(count); + self.os_api.set_terminal_size_using_fd( + terminal.pid, + terminal.display_cols, + terminal.display_rows + ); + } + }, + (None, Some(terminals_to_the_right)) => { + let active_terminal = self.terminals.get_mut(&active_terminal_id).unwrap(); + active_terminal.reduce_width_left(count); + self.os_api.set_terminal_size_using_fd( + active_terminal.pid, + active_terminal.display_cols, + active_terminal.display_rows + ); + for terminal_id in terminals_to_the_right { + let terminal = self.terminals.get_mut(&terminal_id).unwrap(); + terminal.increase_width_left(count); + self.os_api.set_terminal_size_using_fd( + terminal.pid, + terminal.display_cols, + terminal.display_rows + ); + } + }, + _ => {} + } + } } pub fn resize_right (&mut self) { - let terminal1_output = self.terminal1_output.as_mut().unwrap(); - let terminal2_output = self.terminal2_output.as_mut().unwrap(); - terminal1_output.increase_width_right(10); - terminal2_output.reduce_width_right(10); - self.os_api.set_terminal_size_using_fd(terminal1_output.pid, terminal1_output.display_cols, terminal1_output.display_rows); - self.os_api.set_terminal_size_using_fd(terminal2_output.pid, terminal2_output.display_cols, terminal2_output.display_rows); + let count = 10; + if let Some(active_terminal_id) = self.get_active_terminal_id() { + let terminals_to_the_left = self.terminal_ids_directly_left_of(&active_terminal_id); + let terminals_to_the_right = self.terminal_ids_directly_right_of(&active_terminal_id); + match (terminals_to_the_left, terminals_to_the_right) { + (Some(_terminals_to_the_left), Some(terminals_to_the_right)) => { + let active_terminal = self.terminals.get_mut(&active_terminal_id).unwrap(); + active_terminal.increase_width_right(count); + self.os_api.set_terminal_size_using_fd( + active_terminal.pid, + active_terminal.display_cols, + active_terminal.display_rows + ); + for terminal_id in terminals_to_the_right { + let terminal = self.terminals.get_mut(&terminal_id).unwrap(); + terminal.reduce_width_right(count); + self.os_api.set_terminal_size_using_fd( + terminal.pid, + terminal.display_cols, + terminal.display_rows + ); + } + }, + (Some(terminals_to_the_left), None) => { + let active_terminal = self.terminals.get_mut(&active_terminal_id).unwrap(); + active_terminal.reduce_width_right(count); + self.os_api.set_terminal_size_using_fd( + active_terminal.pid, + active_terminal.display_cols, + active_terminal.display_rows + ); + for terminal_id in terminals_to_the_left { + let terminal = self.terminals.get_mut(&terminal_id).unwrap(); + terminal.increase_width_right(count); + self.os_api.set_terminal_size_using_fd( + terminal.pid, + terminal.display_cols, + terminal.display_rows + ); + } + }, + (None, Some(terminals_to_the_right)) => { + let active_terminal = self.terminals.get_mut(&active_terminal_id).unwrap(); + active_terminal.increase_width_right(count); + self.os_api.set_terminal_size_using_fd( + active_terminal.pid, + active_terminal.display_cols, + active_terminal.display_rows + ); + for terminal_id in terminals_to_the_right { + let terminal = self.terminals.get_mut(&terminal_id).unwrap(); + terminal.reduce_width_right(count); + self.os_api.set_terminal_size_using_fd( + terminal.pid, + terminal.display_cols, + terminal.display_rows + ); + } + }, + _ => {} + } + } } pub fn move_focus(&mut self) { - let terminal1_output = self.terminal1_output.as_ref().unwrap(); - let terminal2_output = self.terminal2_output.as_ref().unwrap(); - let active_terminal = self.active_terminal.unwrap(); - if active_terminal == terminal1_output.pid { - self.active_terminal = Some(terminal2_output.pid); - } else { - self.active_terminal = Some(terminal1_output.pid); + if self.terminals.is_empty() { + return; } + let active_terminal = self.get_active_terminal().unwrap(); + let mut first_terminal = active_terminal.pid; + for (terminal_pid, terminal_output) in self.terminals.iter() { + if terminal_output.x_coords == 0 { + first_terminal = terminal_output.pid + } else if active_terminal.x_coords + active_terminal.display_cols == terminal_output.x_coords - 1 { + self.active_terminal = Some(*terminal_pid); + self.render(); + return; + } + } + self.active_terminal = Some(first_terminal); self.render(); } } +enum PtyInstruction { + SpawnTerminal +} + struct PtyBus { - sender: Sender, + receive_pty_instructions: Receiver, + send_pty_instructions: Sender, + send_screen_instructions: Sender, active_ptys: Vec>, os_input: Box, } impl PtyBus { - pub fn new (sender: Sender, os_input: Box) -> Self { + pub fn new (send_screen_instructions: Sender, os_input: Box) -> Self { + let (send_pty_instructions, receive_pty_instructions): (Sender, Receiver) = channel(); PtyBus { - sender, + send_pty_instructions, + send_screen_instructions, + receive_pty_instructions, active_ptys: Vec::new(), os_input, } } - pub fn spawn_terminal(&mut self, ws: &Winsize) { - let ws = *ws; - let (pid_primary, _pid_secondary): (RawFd, RawFd) = self.os_input.spawn_terminal(&ws); + pub fn spawn_terminal(&mut self) { + let (pid_primary, _pid_secondary): (RawFd, RawFd) = self.os_input.spawn_terminal(); let task_handle = task::spawn({ - let sender = self.sender.clone(); + let send_screen_instructions = self.send_screen_instructions.clone(); let os_input = self.os_input.clone(); async move { let mut vte_parser = vte::Parser::new(); - let mut vte_event_sender = VteEventSender::new(pid_primary, sender.clone()); + let mut vte_event_sender = VteEventSender::new(pid_primary, send_screen_instructions.clone()); let mut first_terminal_bytes = ReadFromPid::new(&pid_primary, os_input); while let Some(bytes) = first_terminal_bytes.next().await { let bytes_is_empty = bytes.is_empty(); @@ -798,15 +983,15 @@ impl PtyBus { vte_parser.advance(&mut vte_event_sender, byte); } if !bytes_is_empty { - sender.send(ScreenInstruction::Render).unwrap(); + send_screen_instructions.send(ScreenInstruction::Render).unwrap(); } } } }); - self.sender.send(ScreenInstruction::AddTerminal(pid_primary, ws)).unwrap(); + self.send_screen_instructions.send(ScreenInstruction::AddTerminal(pid_primary)).unwrap(); self.active_ptys.push(task_handle); } - pub async fn wait_for_tasks(&mut self) { + pub async fn _wait_for_tasks(&mut self) { // let task1 = self.active_ptys.get_mut(0).unwrap(); // task1.await; let mut v = vec![]; @@ -831,25 +1016,28 @@ fn start(os_input: OsInputOutput) { let full_screen_ws = os_input.get_terminal_size_using_fd(0); os_input.into_raw_mode(0); let mut screen = Screen::new(&full_screen_ws, Box::new(os_input.clone())); - let send_screen_instructions = screen.sender.clone(); + let send_screen_instructions = screen.send_screen_instructions.clone(); + let mut pty_bus = PtyBus::new(send_screen_instructions.clone(), Box::new(os_input.clone())); + let send_pty_instructions = pty_bus.send_pty_instructions.clone(); active_threads.push( thread::Builder::new() .name("pty".to_string()) .spawn({ - let (first_terminal_ws, second_terminal_ws) = split_horizontally_with_gap(&full_screen_ws); - let first_terminal_ws = first_terminal_ws.clone(); - let second_terminal_ws = second_terminal_ws.clone(); - let send_screen_instructions = send_screen_instructions.clone(); - let os_input = os_input.clone(); move || { - let mut pty_bus = PtyBus::new(send_screen_instructions, Box::new(os_input)); - // this is done here so that we can add terminals dynamically on a different - // thread later - pty_bus.spawn_terminal(&first_terminal_ws); - pty_bus.spawn_terminal(&second_terminal_ws); - task::block_on(pty_bus.wait_for_tasks()); - + pty_bus.spawn_terminal(); + loop { + let event = pty_bus.receive_pty_instructions + .recv() + .expect("failed to receive event on channel"); + match event { + PtyInstruction::SpawnTerminal => { + pty_bus.spawn_terminal(); + } + } + } + // TODO: do this when we exit + // task::block_on(pty_bus.wait_for_tasks()); } }).unwrap() ); @@ -870,8 +1058,8 @@ fn start(os_input: OsInputOutput) { ScreenInstruction::Render => { screen.render(); }, - ScreenInstruction::AddTerminal(pid, ws) => { - screen.add_terminal(pid, ws); + ScreenInstruction::AddTerminal(pid) => { + screen.add_terminal(pid); } ScreenInstruction::WriteCharacter(byte) => { screen.write_to_active_terminal(byte); @@ -905,6 +1093,9 @@ fn start(os_input: OsInputOutput) { } else if buffer[0] == 16 { // ctrl-p send_screen_instructions.send(ScreenInstruction::MoveFocus).unwrap(); continue; + } else if buffer[0] == 14 { // ctrl-n + send_pty_instructions.send(PtyInstruction::SpawnTerminal).unwrap(); + continue; } } send_screen_instructions.send(ScreenInstruction::WriteCharacter(buffer[0])).unwrap(); diff --git a/src/os_input_output.rs b/src/os_input_output.rs index b6ae5c0a..22a507a4 100644 --- a/src/os_input_output.rs +++ b/src/os_input_output.rs @@ -53,9 +53,9 @@ pub fn set_terminal_size_using_fd(fd: RawFd, columns: u16, rows: u16) { unsafe { ioctl(fd, TIOCSWINSZ.into(), &winsize) }; } -fn spawn_terminal (ws: &Winsize) -> (RawFd, RawFd) { +fn spawn_terminal () -> (RawFd, RawFd) { let (pid_primary, pid_secondary): (RawFd, RawFd) = { - match forkpty(Some(ws), None) { + match forkpty(None, None) { Ok(fork_pty_res) => { let pid_primary = fork_pty_res.master; let pid_secondary = match fork_pty_res.fork_result { @@ -92,7 +92,7 @@ pub trait OsApi: Send + Sync { fn get_terminal_size_using_fd(&self, pid: RawFd) -> Winsize; fn set_terminal_size_using_fd(&self, pid: RawFd, cols: u16, rows: u16); fn into_raw_mode(&self, pid: RawFd); - fn spawn_terminal(&self, ws: &Winsize) -> (RawFd, RawFd); + fn spawn_terminal(&self) -> (RawFd, RawFd); fn read(&self, pid: RawFd, buf: &mut [u8]) -> Result; fn write(&self, pid: RawFd, buf: &mut [u8]) -> Result; fn tcdrain(&self, pid: RawFd) -> Result<(), nix::Error>; @@ -110,8 +110,8 @@ impl OsApi for OsInputOutput { fn into_raw_mode(&self, pid: RawFd) { into_raw_mode(pid); } - fn spawn_terminal(&self, ws: &Winsize) -> (RawFd, RawFd) { - spawn_terminal(ws) + fn spawn_terminal(&self) -> (RawFd, RawFd) { + spawn_terminal() } fn read(&self, pid: RawFd, buf: &mut [u8]) -> Result { read(pid, buf)