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.
diff --git a/alacritty/src/cli.rs b/alacritty/src/cli.rs
index 9b1b8e6..21062fc 100644
--- a/alacritty/src/cli.rs
+++ b/alacritty/src/cli.rs
@@ -100,21 +100,6 @@
 
     /// 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 @@
 }
 
 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<Program> {
         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<TerminalOptions> 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 c318fc0..d554993 100644
--- a/alacritty/src/display/hint.rs
+++ b/alacritty/src/display/hint.rs
@@ -78,8 +78,7 @@
             if hint.post_processing {
                 matches
                     .drain(..)
-                    .map(|rm| HintPostProcessor::new(term, regex, rm).collect::<Vec<_>>())
-                    .flatten()
+                    .flat_map(|rm| HintPostProcessor::new(term, regex, rm).collect::<Vec<_>>())
                     .collect()
             } else {
                 matches.0
diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs
index 8ce3b2e..c2baddf 100644
--- a/alacritty/src/event.rs
+++ b/alacritty/src/event.rs
@@ -34,7 +34,7 @@
 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 @@
     ConfigReload(PathBuf),
     Message(Message),
     Scroll(Scroll),
-    CreateWindow(Option<TerminalCliOptions>),
+    CreateWindow(TerminalOptions),
     BlinkCursor,
     SearchNext,
 }
@@ -379,21 +379,19 @@
 
     #[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<I, S>(&self, program: &str, args: I)
@@ -753,7 +751,7 @@
             }
         } 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 @@
             // 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 @@
     pub fn create_window(
         &mut self,
         event_loop: &EventLoopWindowTarget<Event>,
-        options: Option<TerminalCliOptions>,
         proxy: EventLoopProxy<Event>,
+        options: TerminalOptions,
     ) -> Result<(), Box<dyn Error>> {
+        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 @@
                 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 40b18ca..466fe13 100644
--- a/alacritty/src/input.rs
+++ b/alacritty/src/input.rs
@@ -802,11 +802,8 @@
         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 @@
         }
 
         fn terminal_mut(&mut self) -> &mut Term<T> {
-            &mut self.terminal
+            self.terminal
         }
 
         fn size_info(&self) -> SizeInfo {
diff --git a/alacritty/src/ipc.rs b/alacritty/src/ipc.rs
index 6f02e75..a71b513 100644
--- a/alacritty/src/ipc.rs
+++ b/alacritty/src/ipc.rs
@@ -58,8 +58,8 @@
 
             // 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 a5624a7..0af1c01 100644
--- a/alacritty/src/main.rs
+++ b/alacritty/src/main.rs
@@ -178,11 +178,14 @@
     };
 
     // 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 d7a6b41..130f42d 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 @@
 #[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::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 @@
     /// Create a new terminal window context.
     pub fn new(
         config: &UiConfig,
-        options: Option<TerminalCliOptions>,
+        pty_config: &PtyConfig,
         window_event_loop: &EventLoopWindowTarget<Event>,
         proxy: EventLoopProxy<Event>,
         #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))]
@@ -98,10 +97,7 @@
         // 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();
diff --git a/alacritty_terminal/src/ansi.rs b/alacritty_terminal/src/ansi.rs
index 55492d3..25ea8af 100644
--- a/alacritty_terminal/src/ansi.rs
+++ b/alacritty_terminal/src/ansi.rs
@@ -697,6 +697,7 @@
 }
 
 impl NamedColor {
+    #[must_use]
     pub fn to_bright(self) -> Self {
         match self {
             NamedColor::Foreground => NamedColor::BrightForeground,
@@ -721,6 +722,7 @@
         }
     }
 
+    #[must_use]
     pub fn to_dim(self) -> Self {
         match self {
             NamedColor::Black => NamedColor::DimBlack,
diff --git a/alacritty_terminal/src/index.rs b/alacritty_terminal/src/index.rs
index 29b3eb1..e672c75 100644
--- a/alacritty_terminal/src/index.rs
+++ b/alacritty_terminal/src/index.rs
@@ -20,6 +20,7 @@
 }
 
 impl Direction {
+    #[must_use]
     pub fn opposite(self) -> Self {
         match self {
             Side::Right => Side::Left,
@@ -133,6 +134,7 @@
 
 impl Line {
     /// Clamp a line to a grid boundary.
+    #[must_use]
     pub fn grid_clamp<D: Dimensions>(self, dimensions: &D, boundary: Boundary) -> Self {
         match boundary {
             Boundary::Cursor => max(Line(0), min(dimensions.bottommost_line(), self)),