Spawn new alacritty processes in CWD on macOS
On macOS we can use 'proc_pidinfo' to determine the working directory of the terminal foreground process. Fixes #1979.
This commit is contained in:
parent
43d1afbeeb
commit
4fc35f6038
|
@ -31,7 +31,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||
### Changed
|
||||
|
||||
- Cursors are now inverted when their fixed color is similar to the cell's background
|
||||
- Use working directory of active process instead of shell for SpawnNewInstance action
|
||||
- Use the working directory of the terminal foreground process, instead of the shell's working
|
||||
directory, for `SpawnNewInstance` action
|
||||
- Fallback to normal underline for unsupported underline types in `CSI 4 : ? m` escapes
|
||||
- The user's background color is now used as the foreground for the render timer
|
||||
- Use yellow/red from the config for error and warning messages instead of fixed colors
|
||||
|
@ -39,6 +40,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||
- Wayland's Client side decorations now use the search bar colors
|
||||
- Reduce memory usage by up to at least 30% with a full scrollback buffer
|
||||
- The number of zerowidth characters per cell is no longer limited to 5
|
||||
- `SpawnNewInstance` is now using the working directory of the terminal foreground process on macOS
|
||||
|
||||
### Fixed
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ use std::borrow::Cow;
|
|||
use std::cmp::{max, min};
|
||||
use std::env;
|
||||
use std::fmt::Debug;
|
||||
#[cfg(unix)]
|
||||
#[cfg(not(any(target_os = "macos", windows)))]
|
||||
use std::fs;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
|
@ -45,6 +45,8 @@ use crate::config::Config;
|
|||
use crate::daemon::start_daemon;
|
||||
use crate::display::{Display, DisplayUpdate};
|
||||
use crate::input::{self, ActionContext as _, FONT_SIZE_STEP};
|
||||
#[cfg(target_os = "macos")]
|
||||
use crate::macos;
|
||||
use crate::message_bar::{Message, MessageBuffer};
|
||||
use crate::scheduler::{Scheduler, TimerId};
|
||||
use crate::url::{Url, Urls};
|
||||
|
@ -309,15 +311,17 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon
|
|||
pid = tty::child_pid();
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "freebsd"))]
|
||||
#[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);
|
||||
|
||||
// Add the current working directory as parameter.
|
||||
fs::read_link(link_path)
|
||||
.map(|path| vec!["--working-directory".into(), path])
|
||||
.unwrap_or_default()
|
||||
cwd.map(|path| vec!["--working-directory".into(), path]).unwrap_or_default()
|
||||
};
|
||||
|
||||
#[cfg(not(unix))]
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
pub mod locale;
|
||||
pub mod proc;
|
|
@ -0,0 +1,160 @@
|
|||
use std::ffi::{CStr, CString, IntoStringError};
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
use std::io;
|
||||
use std::mem::{self, MaybeUninit};
|
||||
use std::os::raw::{c_int, c_void};
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// Error during working directory retrieval.
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
Io(io::Error),
|
||||
|
||||
/// Error converting into utf8 string.
|
||||
IntoString(IntoStringError),
|
||||
|
||||
/// Expected return size didn't match libproc's.
|
||||
InvalidSize,
|
||||
}
|
||||
|
||||
impl std::error::Error for Error {
|
||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||
match self {
|
||||
Error::InvalidSize => None,
|
||||
Error::Io(err) => err.source(),
|
||||
Error::IntoString(err) => err.source(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Error::InvalidSize => write!(f, "Invalid proc_pidinfo return size"),
|
||||
Error::Io(err) => write!(f, "Error getting current working directory: {}", err),
|
||||
Error::IntoString(err) => {
|
||||
write!(f, "Error when parsing current working directory: {}", err)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<io::Error> for Error {
|
||||
fn from(val: io::Error) -> Self {
|
||||
Error::Io(val)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<IntoStringError> for Error {
|
||||
fn from(val: IntoStringError) -> Self {
|
||||
Error::IntoString(val)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cwd(pid: c_int) -> Result<PathBuf, Error> {
|
||||
let mut info = MaybeUninit::<sys::proc_vnodepathinfo>::uninit();
|
||||
let info_ptr = info.as_mut_ptr() as *mut c_void;
|
||||
let size = mem::size_of::<sys::proc_vnodepathinfo>() as c_int;
|
||||
|
||||
let c_str = unsafe {
|
||||
let pidinfo_size = sys::proc_pidinfo(pid, sys::PROC_PIDVNODEPATHINFO, 0, info_ptr, size);
|
||||
match pidinfo_size {
|
||||
c if c < 0 => return Err(io::Error::last_os_error().into()),
|
||||
s if s != size => return Err(Error::InvalidSize),
|
||||
_ => CStr::from_ptr(info.assume_init().pvi_cdir.vip_path.as_ptr()),
|
||||
}
|
||||
};
|
||||
|
||||
Ok(CString::from(c_str).into_string().map(PathBuf::from)?)
|
||||
}
|
||||
|
||||
/// Bindings for libproc.
|
||||
#[allow(non_camel_case_types)]
|
||||
mod sys {
|
||||
use std::os::raw::{c_char, c_int, c_longlong, c_void};
|
||||
|
||||
pub const PROC_PIDVNODEPATHINFO: c_int = 9;
|
||||
|
||||
type gid_t = c_int;
|
||||
type off_t = c_longlong;
|
||||
type uid_t = c_int;
|
||||
type fsid_t = fsid;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct fsid {
|
||||
pub val: [i32; 2usize],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct vinfo_stat {
|
||||
pub vst_dev: u32,
|
||||
pub vst_mode: u16,
|
||||
pub vst_nlink: u16,
|
||||
pub vst_ino: u64,
|
||||
pub vst_uid: uid_t,
|
||||
pub vst_gid: gid_t,
|
||||
pub vst_atime: i64,
|
||||
pub vst_atimensec: i64,
|
||||
pub vst_mtime: i64,
|
||||
pub vst_mtimensec: i64,
|
||||
pub vst_ctime: i64,
|
||||
pub vst_ctimensec: i64,
|
||||
pub vst_birthtime: i64,
|
||||
pub vst_birthtimensec: i64,
|
||||
pub vst_size: off_t,
|
||||
pub vst_blocks: i64,
|
||||
pub vst_blksize: i32,
|
||||
pub vst_flags: u32,
|
||||
pub vst_gen: u32,
|
||||
pub vst_rdev: u32,
|
||||
pub vst_qspare: [i64; 2usize],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct vnode_info {
|
||||
pub vi_stat: vinfo_stat,
|
||||
pub vi_type: c_int,
|
||||
pub vi_pad: c_int,
|
||||
pub vi_fsid: fsid_t,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct vnode_info_path {
|
||||
pub vip_vi: vnode_info,
|
||||
pub vip_path: [c_char; 1024usize],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct proc_vnodepathinfo {
|
||||
pub pvi_cdir: vnode_info_path,
|
||||
pub pvi_rdir: vnode_info_path,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub fn proc_pidinfo(
|
||||
pid: c_int,
|
||||
flavor: c_int,
|
||||
arg: u64,
|
||||
buffer: *mut c_void,
|
||||
buffersize: c_int,
|
||||
) -> c_int;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use std::env;
|
||||
use std::process;
|
||||
|
||||
#[test]
|
||||
fn cwd_matches_current_dir() {
|
||||
assert_eq!(cwd(process::id() as i32).ok(), env::current_dir().ok());
|
||||
}
|
||||
}
|
|
@ -38,9 +38,9 @@ mod daemon;
|
|||
mod display;
|
||||
mod event;
|
||||
mod input;
|
||||
#[cfg(target_os = "macos")]
|
||||
mod locale;
|
||||
mod logging;
|
||||
#[cfg(target_os = "macos")]
|
||||
mod macos;
|
||||
mod message_bar;
|
||||
mod meter;
|
||||
#[cfg(windows)]
|
||||
|
@ -63,6 +63,8 @@ use crate::config::monitor;
|
|||
use crate::config::Config;
|
||||
use crate::display::Display;
|
||||
use crate::event::{Event, EventProxy, Processor};
|
||||
#[cfg(target_os = "macos")]
|
||||
use crate::macos::locale;
|
||||
use crate::message_bar::MessageBuffer;
|
||||
|
||||
fn main() {
|
||||
|
|
Loading…
Reference in New Issue