Spawn children from foreground working directory
To allow applications spawned by Alacritty to make use of the shell/foreground process' working directory, it is now set for all new processes spawned by Alacritty on Unix platforms. Fixes #5616. Co-authored-by: Christian Duerr <contact@christianduerr.com>
This commit is contained in:
parent
cded85a2f2
commit
f1802c1cda
|
@ -25,6 +25,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Reload configuration files when their symbolic link is replaced
|
- Reload configuration files when their symbolic link is replaced
|
||||||
- Strip trailing whitespaces when yanking from a block selection
|
- Strip trailing whitespaces when yanking from a block selection
|
||||||
- Display area keeps history position when viewport is cleared
|
- Display area keeps history position when viewport is cleared
|
||||||
|
- Commands spawn from the current directory of the foreground shell in Unix-like systems
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,28 @@
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
use std::error::Error;
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
#[cfg(not(any(target_os = "macos", windows)))]
|
||||||
|
use std::fs;
|
||||||
use std::io;
|
use std::io;
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
use std::os::unix::process::CommandExt;
|
use std::os::unix::process::CommandExt;
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
use std::os::windows::process::CommandExt;
|
use std::os::windows::process::CommandExt;
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
|
|
||||||
use log::{debug, warn};
|
use log::{debug, warn};
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
use winapi::um::winbase::{CREATE_NEW_PROCESS_GROUP, CREATE_NO_WINDOW};
|
use winapi::um::winbase::{CREATE_NEW_PROCESS_GROUP, CREATE_NO_WINDOW};
|
||||||
|
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
use alacritty_terminal::tty;
|
||||||
|
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
use crate::macos;
|
||||||
|
|
||||||
/// Start the daemon and log error on failure.
|
/// Start the daemon and log error on failure.
|
||||||
pub fn start_daemon<I, S>(program: &str, args: I)
|
pub fn start_daemon<I, S>(program: &str, args: I)
|
||||||
where
|
where
|
||||||
|
@ -43,18 +55,41 @@ where
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get working directory of controlling process.
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
pub fn foreground_process_path() -> Result<PathBuf, Box<dyn Error>> {
|
||||||
|
let mut pid = unsafe { libc::tcgetpgrp(tty::master_fd()) };
|
||||||
|
if pid < 0 {
|
||||||
|
pid = tty::child_pid();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(target_os = "macos", target_os = "freebsd")))]
|
||||||
|
let link_path = format!("/proc/{}/cwd", pid);
|
||||||
|
#[cfg(target_os = "freebsd")]
|
||||||
|
let link_path = format!("/compat/linux/proc/{}/cwd", pid);
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "macos"))]
|
||||||
|
let cwd = fs::read_link(link_path)?;
|
||||||
|
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
let cwd = macos::proc::cwd(pid)?;
|
||||||
|
|
||||||
|
Ok(cwd)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
fn spawn_daemon<I, S>(program: &str, args: I) -> io::Result<()>
|
fn spawn_daemon<I, S>(program: &str, args: I) -> io::Result<()>
|
||||||
where
|
where
|
||||||
I: IntoIterator<Item = S> + Copy,
|
I: IntoIterator<Item = S> + Copy,
|
||||||
S: AsRef<OsStr>,
|
S: AsRef<OsStr>,
|
||||||
{
|
{
|
||||||
|
let mut command = Command::new(program);
|
||||||
|
command.args(args).stdin(Stdio::null()).stdout(Stdio::null()).stderr(Stdio::null());
|
||||||
|
if let Ok(cwd) = foreground_process_path() {
|
||||||
|
command.current_dir(cwd);
|
||||||
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
Command::new(program)
|
command
|
||||||
.args(args)
|
|
||||||
.stdin(Stdio::null())
|
|
||||||
.stdout(Stdio::null())
|
|
||||||
.stderr(Stdio::null())
|
|
||||||
.pre_exec(|| {
|
.pre_exec(|| {
|
||||||
match libc::fork() {
|
match libc::fork() {
|
||||||
-1 => return Err(io::Error::last_os_error()),
|
-1 => return Err(io::Error::last_os_error()),
|
||||||
|
|
|
@ -30,20 +30,18 @@ use alacritty_terminal::index::{Boundary, Column, Direction, Line, Point, Side};
|
||||||
use alacritty_terminal::selection::{Selection, SelectionType};
|
use alacritty_terminal::selection::{Selection, SelectionType};
|
||||||
use alacritty_terminal::term::search::{Match, RegexSearch};
|
use alacritty_terminal::term::search::{Match, RegexSearch};
|
||||||
use alacritty_terminal::term::{ClipboardType, SizeInfo, Term, TermMode};
|
use alacritty_terminal::term::{ClipboardType, SizeInfo, Term, TermMode};
|
||||||
#[cfg(not(windows))]
|
|
||||||
use alacritty_terminal::tty;
|
|
||||||
|
|
||||||
use crate::cli::{Options as CliOptions, TerminalOptions as TerminalCliOptions};
|
use crate::cli::{Options as CliOptions, TerminalOptions as TerminalCliOptions};
|
||||||
use crate::clipboard::Clipboard;
|
use crate::clipboard::Clipboard;
|
||||||
use crate::config::ui_config::{HintAction, HintInternalAction};
|
use crate::config::ui_config::{HintAction, HintInternalAction};
|
||||||
use crate::config::{self, UiConfig};
|
use crate::config::{self, UiConfig};
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
use crate::daemon::foreground_process_path;
|
||||||
use crate::daemon::start_daemon;
|
use crate::daemon::start_daemon;
|
||||||
use crate::display::hint::HintMatch;
|
use crate::display::hint::HintMatch;
|
||||||
use crate::display::window::Window;
|
use crate::display::window::Window;
|
||||||
use crate::display::{self, Display};
|
use crate::display::{self, Display};
|
||||||
use crate::input::{self, ActionContext as _, FONT_SIZE_STEP};
|
use crate::input::{self, ActionContext as _, FONT_SIZE_STEP};
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
use crate::macos;
|
|
||||||
use crate::message_bar::{Message, MessageBuffer};
|
use crate::message_bar::{Message, MessageBuffer};
|
||||||
use crate::scheduler::{Scheduler, TimerId, Topic};
|
use crate::scheduler::{Scheduler, TimerId, Topic};
|
||||||
use crate::window_context::WindowContext;
|
use crate::window_context::WindowContext;
|
||||||
|
@ -354,27 +352,19 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon
|
||||||
let mut env_args = env::args();
|
let mut env_args = env::args();
|
||||||
let alacritty = env_args.next().unwrap();
|
let alacritty = env_args.next().unwrap();
|
||||||
|
|
||||||
// Use working directory of controlling process, or fallback to initial shell, then add it
|
let mut args: Vec<String> = Vec::new();
|
||||||
// as working-directory parameter.
|
|
||||||
#[cfg(unix)]
|
|
||||||
let mut args = foreground_process_path()
|
|
||||||
.map(|path| vec!["--working-directory".into(), path])
|
|
||||||
.unwrap_or_default();
|
|
||||||
|
|
||||||
#[cfg(not(unix))]
|
|
||||||
let mut args: Vec<PathBuf> = Vec::new();
|
|
||||||
|
|
||||||
let working_directory_set = !args.is_empty();
|
|
||||||
|
|
||||||
// Reuse the arguments passed to Alacritty for the new instance.
|
// Reuse the arguments passed to Alacritty for the new instance.
|
||||||
|
#[allow(clippy::while_let_on_iterator)]
|
||||||
while let Some(arg) = env_args.next() {
|
while let Some(arg) = env_args.next() {
|
||||||
// Drop working directory from existing parameters.
|
// On unix, the working directory of the foreground shell is used by `start_daemon`.
|
||||||
if working_directory_set && arg == "--working-directory" {
|
#[cfg(not(windows))]
|
||||||
|
if arg == "--working-directory" {
|
||||||
let _ = env_args.next();
|
let _ = env_args.next();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
args.push(arg.into());
|
args.push(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
start_daemon(&alacritty, &args);
|
start_daemon(&alacritty, &args);
|
||||||
|
@ -1389,24 +1379,3 @@ impl EventListener for EventProxy {
|
||||||
let _ = self.proxy.send_event(Event::new(event.into(), self.window_id));
|
let _ = self.proxy.send_event(Event::new(event.into(), self.window_id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(windows))]
|
|
||||||
pub fn foreground_process_path() -> Result<PathBuf, Box<dyn Error>> {
|
|
||||||
let mut pid = unsafe { libc::tcgetpgrp(tty::master_fd()) };
|
|
||||||
if pid < 0 {
|
|
||||||
pid = tty::child_pid();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(any(target_os = "macos", target_os = "freebsd")))]
|
|
||||||
let link_path = format!("/proc/{}/cwd", pid);
|
|
||||||
#[cfg(target_os = "freebsd")]
|
|
||||||
let link_path = format!("/compat/linux/proc/{}/cwd", pid);
|
|
||||||
|
|
||||||
#[cfg(not(target_os = "macos"))]
|
|
||||||
let cwd = std::fs::read_link(link_path)?;
|
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
let cwd = macos::proc::cwd(pid)?;
|
|
||||||
|
|
||||||
Ok(cwd)
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue