mirror of
https://github.com/neovide/neovide.git
synced 2026-09-10 07:16:25 -04:00
fix: harden neovim restart handling
This commit is contained in:
parent
ba8c41f423
commit
c80d2c83e2
|
|
@ -28,6 +28,20 @@ pub type NeovimWriter = Box<dyn futures::AsyncWrite + Send + Unpin + 'static>;
|
|||
type BoxedReader = Box<dyn AsyncRead + Send + Unpin + 'static>;
|
||||
type BoxedWriter = Box<dyn AsyncWrite + Send + Unpin + 'static>;
|
||||
|
||||
#[cfg(any(target_os = "windows", test))]
|
||||
fn normalize_windows_pipe_address(address: String) -> String {
|
||||
const PIPE_PREFIX: &str = r"\\.\pipe\";
|
||||
const FORWARD_SLASH_PIPE_PREFIX: &str = "//./pipe/";
|
||||
|
||||
if address.starts_with(PIPE_PREFIX) {
|
||||
address
|
||||
} else if let Some(name) = address.strip_prefix(FORWARD_SLASH_PIPE_PREFIX) {
|
||||
format!("{PIPE_PREFIX}{name}")
|
||||
} else {
|
||||
format!("{PIPE_PREFIX}{address}")
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NeovimSession {
|
||||
pub neovim: Neovim<NeovimWriter>,
|
||||
pub io_handle: JoinHandle<std::result::Result<(), Box<LoopError>>>,
|
||||
|
|
@ -193,12 +207,7 @@ impl NeovimInstance {
|
|||
|
||||
#[cfg(windows)]
|
||||
{
|
||||
// Fixup the address if the pipe on windows does not start with \\.\pipe\.
|
||||
let address = if address.starts_with("\\\\.\\pipe\\") {
|
||||
address
|
||||
} else {
|
||||
format!("\\\\.\\pipe\\{address}")
|
||||
};
|
||||
let address = normalize_windows_pipe_address(address);
|
||||
Ok(Self::split(
|
||||
tokio::net::windows::named_pipe::ClientOptions::new().open(address)?,
|
||||
))
|
||||
|
|
@ -246,3 +255,27 @@ impl NeovimInstance {
|
|||
(Box::new(reader), Box::new(writer))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::normalize_windows_pipe_address;
|
||||
|
||||
#[test]
|
||||
fn preserves_canonical_windows_pipe_address() {
|
||||
let address = r"\\.\pipe\nvim.123".to_string();
|
||||
assert_eq!(normalize_windows_pipe_address(address.clone()), address);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn normalizes_neovim_forward_slash_pipe_address() {
|
||||
assert_eq!(
|
||||
normalize_windows_pipe_address("//./pipe/nvim.123".to_string()),
|
||||
r"\\.\pipe\nvim.123"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn prefixes_bare_windows_pipe_name() {
|
||||
assert_eq!(normalize_windows_pipe_address("nvim.123".to_string()), r"\\.\pipe\nvim.123");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -861,12 +861,6 @@ impl ApplicationHandler<EventPayload> for Application {
|
|||
return;
|
||||
};
|
||||
self.window_wrapper.queue_restart_route(route_id, details);
|
||||
if let Some(window_id) = self.window_wrapper.window_id_for_route(route_id)
|
||||
&& let Some(state) = self.render_states.get_mut(&window_id)
|
||||
{
|
||||
state.pending_draw_commands.clear();
|
||||
state.should_render = ShouldRender::Immediately;
|
||||
}
|
||||
}
|
||||
payload => {
|
||||
self.window_wrapper.handle_user_event(EventPayload { payload, target });
|
||||
|
|
|
|||
|
|
@ -1984,27 +1984,34 @@ impl WinitWindowWrapper {
|
|||
}
|
||||
|
||||
pub fn queue_restart_route(&mut self, route_id: RouteId, details: RestartDetails) {
|
||||
// The restart notification arrives before the old channel closes. Keep the current
|
||||
// renderer untouched because Neovim may still abort the restart (for example with E37).
|
||||
let grid_size = if let Some(window_id) = self.window_id_for_route(route_id) {
|
||||
let grid_size = match self.routes.get(&window_id) {
|
||||
match self.routes.get(&window_id) {
|
||||
Some(route) => route.window.renderer.borrow().get_grid_size(),
|
||||
None => return,
|
||||
}
|
||||
} else {
|
||||
let Some(route_core) = self.route_cores.get(&route_id) else {
|
||||
return;
|
||||
};
|
||||
route_core.renderer.borrow().get_grid_size()
|
||||
};
|
||||
|
||||
self.pending_restart.insert(route_id, RestartRequest { details, grid_size });
|
||||
}
|
||||
|
||||
fn prepare_route_for_restart(&mut self, route_id: RouteId) {
|
||||
// This is called only after the old Neovim channel has actually closed.
|
||||
if let Some(window_id) = self.window_id_for_route(route_id) {
|
||||
self.clear_renderer(window_id);
|
||||
if let Some(route) = self.routes.get_mut(&window_id) {
|
||||
route.window.last_synced_grid_size = None;
|
||||
}
|
||||
grid_size
|
||||
} else {
|
||||
let Some(route_core) = self.route_cores.get_mut(&route_id) else {
|
||||
return;
|
||||
};
|
||||
let grid_size = route_core.renderer.borrow().get_grid_size();
|
||||
} else if let Some(route_core) = self.route_cores.get_mut(&route_id) {
|
||||
route_core.renderer.borrow_mut().clear();
|
||||
route_core.last_synced_grid_size = None;
|
||||
grid_size
|
||||
};
|
||||
|
||||
self.pending_restart.insert(route_id, RestartRequest { details, grid_size });
|
||||
}
|
||||
}
|
||||
|
||||
fn restart_neovim_route(
|
||||
|
|
@ -2015,6 +2022,11 @@ impl WinitWindowWrapper {
|
|||
) -> Result<(), ()> {
|
||||
let handler = self.neovim_handler_for_route(route_id).ok_or(())?;
|
||||
let cwd = self.route_cwd(route_id);
|
||||
if self.runtime.is_none() {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
self.prepare_route_for_restart(route_id);
|
||||
let runtime = self.runtime.as_mut().ok_or(())?;
|
||||
|
||||
runtime
|
||||
|
|
|
|||
Loading…
Reference in a new issue