fix: retain alternate screen across executable restart
This commit is contained in:
+39
-15
@@ -1,7 +1,10 @@
|
||||
use std::{env, path::PathBuf};
|
||||
use std::{env, io, path::PathBuf};
|
||||
|
||||
use vamp::{session::EditorSession, tui};
|
||||
|
||||
// Only the first argument can be this process-to-process terminal handoff marker.
|
||||
const INHERITED_SCREEN: &str = "--vamp-inherit-alternate-screen";
|
||||
|
||||
const HELP: &str = "vamp — modal editor with isolated Ruby plugins
|
||||
|
||||
Usage: vamp [--config PATH | --no-config] [FILE]
|
||||
@@ -86,8 +89,8 @@ struct Options {
|
||||
config: Option<PathBuf>,
|
||||
}
|
||||
|
||||
fn options() -> Result<Option<Options>, String> {
|
||||
let mut args = env::args_os().skip(1);
|
||||
fn options(inherited_screen: bool) -> Result<Option<Options>, String> {
|
||||
let mut args = env::args_os().skip(1 + usize::from(inherited_screen));
|
||||
let mut file = None;
|
||||
let mut config = None;
|
||||
let mut config_selected = false;
|
||||
@@ -129,7 +132,25 @@ fn options() -> Result<Option<Options>, String> {
|
||||
}
|
||||
|
||||
fn run() -> Result<(), String> {
|
||||
let Some(options) = options()? else {
|
||||
let inherited_screen = env::args_os()
|
||||
.nth(1)
|
||||
.is_some_and(|arg| arg == INHERITED_SCREEN);
|
||||
if inherited_screen {
|
||||
return tui::TerminalSession::run(true, || {
|
||||
run_editor(options(true).map_err(io::Error::other)?, true)
|
||||
})
|
||||
.map_err(|error| error.to_string());
|
||||
}
|
||||
let options = options(false)?;
|
||||
if options.is_none() {
|
||||
return Ok(());
|
||||
}
|
||||
tui::TerminalSession::run(false, || run_editor(options, false))
|
||||
.map_err(|error| error.to_string())
|
||||
}
|
||||
|
||||
fn run_editor(options: Option<Options>, inherited_screen: bool) -> io::Result<()> {
|
||||
let Some(options) = options else {
|
||||
return Ok(());
|
||||
};
|
||||
let mut session = EditorSession::open(
|
||||
@@ -137,34 +158,37 @@ fn run() -> Result<(), String> {
|
||||
tui::CAPABILITIES.iter().map(|s| (*s).to_owned()).collect(),
|
||||
options.config.as_deref(),
|
||||
)
|
||||
.map_err(|error| format!("cannot open file: {error}"))?;
|
||||
tui::run(&mut session).map_err(|error| format!("terminal error: {error}"))?;
|
||||
.map_err(|error| io::Error::other(format!("cannot open file: {error}")))?;
|
||||
tui::run(&mut session, inherited_screen)?;
|
||||
let restart = session.editor().should_restart();
|
||||
drop(session);
|
||||
if restart {
|
||||
restart_editor()?;
|
||||
tui::TerminalSession::prepare_restart()?;
|
||||
restart_editor(inherited_screen)
|
||||
.map_err(|error| io::Error::other(format!("Restart failed: {error}")))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn restart_editor() -> Result<(), String> {
|
||||
let executable = env::current_exe().map_err(|error| format!("Restart failed: {error}"))?;
|
||||
fn restart_editor(inherited_screen: bool) -> io::Result<()> {
|
||||
let executable = env::current_exe()?;
|
||||
let mut command = std::process::Command::new(executable);
|
||||
command.args(env::args_os().skip(1));
|
||||
command.arg(INHERITED_SCREEN);
|
||||
command.args(env::args_os().skip(1 + usize::from(inherited_screen)));
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::os::unix::process::CommandExt;
|
||||
Err(format!("Restart failed: {}", command.exec()))
|
||||
Err(command.exec())
|
||||
}
|
||||
#[cfg(not(unix))]
|
||||
{
|
||||
let status = command
|
||||
.status()
|
||||
.map_err(|error| format!("Restart failed: {error}"))?;
|
||||
let status = command.status()?;
|
||||
if status.success() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(format!("Restarted editor exited with {status}"))
|
||||
Err(io::Error::other(format!(
|
||||
"Restarted editor exited with {status}"
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user