From 3af1940192245f96f0b7c8e2d2d5c4a5d8eb98a1 Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Thu, 23 Dec 2021 10:23:06 +0000 Subject: Fix CreateNewWindow CLI fallback The existing behavior for the new CreateNewWindow actions was to always pass in their own options, which would discard the existing options configured on the terminal's PTY config. To fix this the behavior for CreateNewWindow is now the same as for the initial window creation, the config values are overwritten conditionally based on their individual presence in the CLI options. However all temporary CLI options set on the "master" Alacritty instance are discarded by all future windows. Fixes #5659. --- alacritty/src/cli.rs | 49 ++++++++++++++++++----------------------- alacritty/src/display/hint.rs | 3 +-- alacritty/src/event.rs | 31 +++++++++++++------------- alacritty/src/input.rs | 9 +++----- alacritty/src/ipc.rs | 4 ++-- alacritty/src/main.rs | 5 ++++- alacritty/src/window_context.rs | 10 +++------ 7 files changed, 51 insertions(+), 60 deletions(-) (limited to 'alacritty/src') diff --git a/alacritty/src/cli.rs b/alacritty/src/cli.rs index 9b1b8e6c..21062fce 100644 --- a/alacritty/src/cli.rs +++ b/alacritty/src/cli.rs @@ -100,21 +100,6 @@ impl Options { /// Override configuration file with options from the CLI. pub fn override_config(&self, config: &mut UiConfig) { - if let Some(working_directory) = &self.terminal_options.working_directory { - if working_directory.is_dir() { - config.terminal_config.pty_config.working_directory = - Some(working_directory.to_owned()); - } else { - error!("Invalid working directory: {:?}", working_directory); - } - } - - if let Some(command) = self.terminal_options.command() { - config.terminal_config.pty_config.shell = Some(command); - } - - config.terminal_config.pty_config.hold = self.terminal_options.hold; - if let Some(title) = self.title.clone() { config.window.title = title } @@ -218,27 +203,37 @@ pub struct TerminalOptions { } impl TerminalOptions { - pub fn new() -> Self { - Default::default() - } - - pub fn is_empty(&self) -> bool { - self.working_directory.is_none() && !self.hold && self.command.is_empty() - } - /// Shell override passed through the CLI. pub fn command(&self) -> Option { let (program, args) = self.command.split_first()?; Some(Program::WithArgs { program: program.clone(), args: args.to_vec() }) } + + /// Override the [`PtyConfig`]'s fields with the [`TerminalOptions`]. + pub fn override_pty_config(&self, pty_config: &mut PtyConfig) { + if let Some(working_directory) = &self.working_directory { + if working_directory.is_dir() { + pty_config.working_directory = Some(working_directory.to_owned()); + } else { + error!("Invalid working directory: {:?}", working_directory); + } + } + + if let Some(command) = self.command() { + pty_config.shell = Some(command); + } + + pty_config.hold |= self.hold; + } } impl From for PtyConfig { fn from(mut options: TerminalOptions) -> Self { - let working_directory = options.working_directory.take(); - let shell = options.command(); - let hold = options.hold; - PtyConfig { shell, working_directory, hold } + PtyConfig { + working_directory: options.working_directory.take(), + shell: options.command(), + hold: options.hold, + } } } diff --git a/alacritty/src/display/hint.rs b/alacritty/src/display/hint.rs index c318fc09..d554993b 100644 --- a/alacritty/src/display/hint.rs +++ b/alacritty/src/display/hint.rs @@ -78,8 +78,7 @@ impl HintState { if hint.post_processing { matches .drain(..) - .map(|rm| HintPostProcessor::new(term, regex, rm).collect::>()) - .flatten() + .flat_map(|rm| HintPostProcessor::new(term, regex, rm).collect::>()) .collect() } else { matches.0 diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs index 8ce3b2e0..c2baddf8 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -34,7 +34,7 @@ use alacritty_terminal::selection::{Selection, SelectionType}; use alacritty_terminal::term::search::{Match, RegexSearch}; use alacritty_terminal::term::{ClipboardType, SizeInfo, Term, TermMode}; -use crate::cli::{Options as CliOptions, TerminalOptions as TerminalCliOptions}; +use crate::cli::{Options as CliOptions, TerminalOptions}; use crate::clipboard::Clipboard; use crate::config::ui_config::{HintAction, HintInternalAction}; use crate::config::{self, UiConfig}; @@ -88,7 +88,7 @@ pub enum EventType { ConfigReload(PathBuf), Message(Message), Scroll(Scroll), - CreateWindow(Option), + CreateWindow(TerminalOptions), BlinkCursor, SearchNext, } @@ -379,21 +379,19 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext for ActionCon #[cfg(not(windows))] fn create_new_window(&mut self) { - let cwd = foreground_process_path(self.master_fd, self.shell_pid); - let options = if let Ok(working_directory) = cwd { - let mut options = TerminalCliOptions::new(); + let mut options = TerminalOptions::default(); + if let Ok(working_directory) = foreground_process_path(self.master_fd, self.shell_pid) { options.working_directory = Some(working_directory); - Some(options) - } else { - None - }; + } let _ = self.event_proxy.send_event(Event::new(EventType::CreateWindow(options), None)); } #[cfg(windows)] fn create_new_window(&mut self) { - let _ = self.event_proxy.send_event(Event::new(EventType::CreateWindow(None), None)); + let _ = self + .event_proxy + .send_event(Event::new(EventType::CreateWindow(TerminalOptions::default()), None)); } fn spawn_daemon(&self, program: &str, args: I) @@ -753,7 +751,7 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext for ActionCon } } else if self.terminal().mode().contains(TermMode::BRACKETED_PASTE) { self.write_to_pty(&b"\x1b[200~"[..]); - self.write_to_pty(text.replace("\x1b", "").into_bytes()); + self.write_to_pty(text.replace('\x1b', "").into_bytes()); self.write_to_pty(&b"\x1b[201~"[..]); } else { // In non-bracketed (ie: normal) mode, terminal applications cannot distinguish @@ -762,7 +760,7 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext for ActionCon // pasting... since that's neither practical nor sensible (and probably an impossible // task to solve in a general way), we'll just replace line breaks (windows and unix // style) with a single carriage return (\r, which is what the Enter key produces). - self.write_to_pty(text.replace("\r\n", "\r").replace("\n", "\r").into_bytes()); + self.write_to_pty(text.replace("\r\n", "\r").replace('\n', "\r").into_bytes()); } } @@ -1207,12 +1205,15 @@ impl Processor { pub fn create_window( &mut self, event_loop: &EventLoopWindowTarget, - options: Option, proxy: EventLoopProxy, + options: TerminalOptions, ) -> Result<(), Box> { + let mut pty_config = self.config.terminal_config.pty_config.clone(); + options.override_pty_config(&mut pty_config); + let window_context = WindowContext::new( &self.config, - options, + &pty_config, event_loop, proxy, #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] @@ -1320,7 +1321,7 @@ impl Processor { GlutinEvent::UserEvent(Event { payload: EventType::CreateWindow(options), .. }) => { - if let Err(err) = self.create_window(event_loop, options, proxy.clone()) { + if let Err(err) = self.create_window(event_loop, proxy.clone(), options) { error!("Could not open window: {:?}", err); } }, diff --git a/alacritty/src/input.rs b/alacritty/src/input.rs index 40b18ca2..466fe130 100644 --- a/alacritty/src/input.rs +++ b/alacritty/src/input.rs @@ -802,11 +802,8 @@ impl> Processor { self.ctx.clear_selection(); let utf8_len = c.len_utf8(); - let mut bytes = Vec::with_capacity(utf8_len); - unsafe { - bytes.set_len(utf8_len); - c.encode_utf8(&mut bytes[..]); - } + let mut bytes = vec![0; utf8_len]; + c.encode_utf8(&mut bytes[..]); if self.ctx.config().alt_send_esc && *self.ctx.received_count() == 0 @@ -1007,7 +1004,7 @@ mod tests { } fn terminal_mut(&mut self) -> &mut Term { - &mut self.terminal + self.terminal } fn size_info(&self) -> SizeInfo { diff --git a/alacritty/src/ipc.rs b/alacritty/src/ipc.rs index 6f02e757..a71b5139 100644 --- a/alacritty/src/ipc.rs +++ b/alacritty/src/ipc.rs @@ -58,8 +58,8 @@ pub fn spawn_ipc_socket(options: &Options, event_proxy: EventLoopProxy) - // Handle IPC events. match message { - SocketMessage::CreateWindow(terminal_options) => { - let event = Event::new(EventType::CreateWindow(Some(terminal_options)), None); + SocketMessage::CreateWindow(options) => { + let event = Event::new(EventType::CreateWindow(options), None); let _ = event_proxy.send_event(event); }, } diff --git a/alacritty/src/main.rs b/alacritty/src/main.rs index a5624a7b..0af1c01b 100644 --- a/alacritty/src/main.rs +++ b/alacritty/src/main.rs @@ -178,11 +178,14 @@ fn alacritty(options: Options) -> Result<(), String> { }; // Event processor. + let cli_options = options.terminal_options.clone(); let mut processor = Processor::new(config, options, &window_event_loop); // Create the first Alacritty window. let proxy = window_event_loop.create_proxy(); - processor.create_window(&window_event_loop, None, proxy).map_err(|err| err.to_string())?; + processor + .create_window(&window_event_loop, proxy, cli_options) + .map_err(|err| err.to_string())?; info!("Initialisation complete"); diff --git a/alacritty/src/window_context.rs b/alacritty/src/window_context.rs index d7a6b41e..130f42d6 100644 --- a/alacritty/src/window_context.rs +++ b/alacritty/src/window_context.rs @@ -1,6 +1,5 @@ //! Terminal window context. -use std::borrow::Cow; use std::error::Error; use std::fs::File; use std::io::Write; @@ -20,6 +19,7 @@ use serde_json as json; #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] use wayland_client::EventQueue; +use alacritty_terminal::config::PtyConfig; use alacritty_terminal::event::Event as TerminalEvent; use alacritty_terminal::event_loop::{EventLoop as PtyEventLoop, Msg, Notifier}; use alacritty_terminal::grid::{Dimensions, Scroll}; @@ -28,7 +28,6 @@ use alacritty_terminal::sync::FairMutex; use alacritty_terminal::term::{Term, TermMode}; use alacritty_terminal::tty; -use crate::cli::TerminalOptions as TerminalCliOptions; use crate::clipboard::Clipboard; use crate::config::UiConfig; use crate::display::Display; @@ -61,7 +60,7 @@ impl WindowContext { /// Create a new terminal window context. pub fn new( config: &UiConfig, - options: Option, + pty_config: &PtyConfig, window_event_loop: &EventLoopWindowTarget, proxy: EventLoopProxy, #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] @@ -98,10 +97,7 @@ impl WindowContext { // The PTY forks a process to run the shell on the slave side of the // pseudoterminal. A file descriptor for the master side is retained for // reading/writing to the shell. - let pty_config = options - .map(|o| Cow::Owned(o.into())) - .unwrap_or(Cow::Borrowed(&config.terminal_config.pty_config)); - let pty = tty::new(&pty_config, &display.size_info, display.window.x11_window_id())?; + let pty = tty::new(pty_config, &display.size_info, display.window.x11_window_id())?; #[cfg(not(windows))] let master_fd = pty.file().as_raw_fd(); -- cgit