1
1
mirror of https://github.com/wez/wezterm.git synced 2024-12-23 05:12:40 +03:00

expose the tty name associated with a pane

This commit is contained in:
Wez Furlong 2023-04-06 17:13:07 -07:00
parent 889390a448
commit 0ca050e09d
No known key found for this signature in database
GPG Key ID: 7A7F66A31EC9B387
16 changed files with 126 additions and 1 deletions

View File

@ -431,7 +431,7 @@ macro_rules! pdu {
/// The overall version of the codec.
/// This must be bumped when backwards incompatible changes
/// are made to the types and protocol.
pub const CODEC_VERSION: usize = 40;
pub const CODEC_VERSION: usize = 41;
// Defines the Pdu enum.
// Each struct has an explicit identifying number.

View File

@ -64,6 +64,9 @@ As features stabilize some brief notes about them will accumulate here.
* [wezterm cli rename-workspace](cli/cli/rename-workspace.md). #2787
* [wezterm.mux.rename_workspace](config/lua/wezterm.mux/rename_workspace.md). #2787
* [wezterm cli get-pane-direction](cli/cli/get-pane-direction.md)
* [pane:get_tty_name()](config/lua/pane/get_tty_name.md) and
[PaneInformation.tty_name](config/lua/PaneInformation.md) to reason about the
tty name on local unix systems.
#### Fixed
* mux: Stale remote window mapping could prevent spawning new tabs in remote domain. #2759

View File

@ -126,3 +126,7 @@ end)
return config
```
{{since('nightly')}}
The `tty_name` field returns the tty name with the same constraints as described
in [pane:get_tty_name()](../pane/get_tty_name.md).

View File

@ -0,0 +1,27 @@
# `pane:get_tty_name()`
{{since('nightly')}}
Returns the tty device name, or `nil` if the name is unavailable.
* This information is only available for local panes. Multiplexer panes do not report this information. Similarly, if you are using eg: `ssh` to connect to a remote host, you won't be able to access the name of the remote process that is running.
* This information is only available on unix systems. Windows systems do not have an equivalent concept.
This example sets the right status to show the tty name:
```lua
local wezterm = require 'wezterm'
wezterm.on('update-status', function(window, pane)
local tty = pane:get_tty_name()
if tty then
window:set_right_status(tty)
else
window:set_right_status ''
end
end)
return {}
```

View File

@ -403,6 +403,12 @@ impl UserData for MuxPane {
tab.set_active_pane(&pane);
Ok(())
});
methods.add_method("get_tty_name", move |_lua, this, ()| {
let mux = Mux::get();
let pane = this.resolve(&mux)?;
Ok(pane.tty_name())
});
}
}

View File

@ -457,6 +457,11 @@ impl Pane for LocalPane {
.or_else(|| self.divine_current_working_dir())
}
fn tty_name(&self) -> Option<String> {
let name = self.pty.lock().tty_name()?;
Some(name.to_string_lossy().into_owned())
}
fn get_foreground_process_info(&self) -> Option<LocalProcessInfo> {
#[cfg(unix)]
if let Some(pid) = self.pty.lock().process_group_leader() {

View File

@ -345,6 +345,10 @@ pub trait Pane: Downcast + Send + Sync {
None
}
fn tty_name(&self) -> Option<String> {
None
}
fn trickle_paste(&self, text: String) -> anyhow::Result<()> {
if text.len() <= PASTE_CHUNK_SIZE {
// Send it all now

View File

@ -996,6 +996,11 @@ impl portable_pty::MasterPty for WrappedSshPty {
fn as_raw_fd(&self) -> Option<std::os::fd::RawFd> {
None
}
#[cfg(unix)]
fn tty_name(&self) -> Option<std::path::PathBuf> {
None
}
}
impl std::io::Write for PtyWriter {

View File

@ -277,6 +277,7 @@ fn pane_tree(
physical_top: dims.physical_top,
left_col,
top_row,
tty_name: pane.tty_name(),
})
}
}
@ -2110,6 +2111,7 @@ pub struct PaneEntry {
pub physical_top: StableRowIndex,
pub top_row: usize,
pub left_col: usize,
pub tty_name: Option<String>,
}
#[derive(Deserialize, Clone, Serialize, PartialEq, Debug)]

View File

@ -161,4 +161,9 @@ impl MasterPty for TmuxPty {
fn as_raw_fd(&self) -> Option<std::os::fd::RawFd> {
None
}
#[cfg(unix)]
fn tty_name(&self) -> Option<std::path::PathBuf> {
None
}
}

View File

@ -113,6 +113,9 @@ pub trait MasterPty {
#[cfg(unix)]
fn as_raw_fd(&self) -> Option<unix::RawFd>;
#[cfg(unix)]
fn tty_name(&self) -> Option<std::path::PathBuf>;
/// If applicable to the type of the tty, return the termios
/// associated with the stream
#[cfg(unix)]

View File

@ -17,6 +17,7 @@ use serial::{
use std::cell::RefCell;
use std::ffi::{OsStr, OsString};
use std::io::{Read, Result as IoResult, Write};
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
use std::time::Duration;
@ -245,6 +246,11 @@ impl MasterPty for Master {
fn as_raw_fd(&self) -> Option<crate::unix::RawFd> {
None
}
#[cfg(unix)]
fn tty_name(&self) -> Option<PathBuf> {
None
}
}
struct Reader {

View File

@ -5,9 +5,12 @@ use anyhow::{bail, Error};
use filedescriptor::FileDescriptor;
use libc::{self, winsize};
use std::cell::RefCell;
use std::ffi::OsStr;
use std::io::{Read, Write};
use std::os::unix::ffi::OsStrExt;
use std::os::unix::io::{AsRawFd, FromRawFd};
use std::os::unix::process::CommandExt;
use std::path::PathBuf;
use std::{io, mem, ptr};
pub use std::os::unix::io::RawFd;
@ -42,9 +45,12 @@ fn openpty(size: PtySize) -> anyhow::Result<(UnixMasterPty, UnixSlavePty)> {
bail!("failed to openpty: {:?}", io::Error::last_os_error());
}
let tty_name = tty_name(slave);
let master = UnixMasterPty {
fd: PtyFd(unsafe { FileDescriptor::from_raw_fd(master) }),
took_writer: RefCell::new(false),
tty_name,
};
let slave = UnixSlavePty {
fd: PtyFd(unsafe { FileDescriptor::from_raw_fd(slave) }),
@ -98,6 +104,33 @@ impl Read for PtyFd {
}
}
fn tty_name(fd: RawFd) -> Option<PathBuf> {
let mut buf = vec![0 as std::ffi::c_char; 128];
loop {
let res = unsafe { libc::ttyname_r(fd, buf.as_mut_ptr(), buf.len()) };
if res == libc::ERANGE {
if buf.len() > 64 * 1024 {
// on macOS, if the buf is "too big", ttyname_r can
// return ERANGE, even though that is supposed to
// indicate buf is "too small".
return None;
}
buf.resize(buf.len() * 2, 0 as std::ffi::c_char);
continue;
}
return if res == 0 {
let cstr = unsafe { std::ffi::CStr::from_ptr(buf.as_ptr()) };
let osstr = OsStr::from_bytes(cstr.to_bytes());
Some(PathBuf::from(osstr))
} else {
None
};
}
}
/// On Big Sur, Cocoa leaks various file descriptors to child processes,
/// so we need to make a pass through the open descriptors beyond just the
/// stdio descriptors and close them all out.
@ -269,6 +302,7 @@ impl PtyFd {
struct UnixMasterPty {
fd: PtyFd,
took_writer: RefCell<bool>,
tty_name: Option<PathBuf>,
}
/// Represents the slave end of a pty.
@ -332,6 +366,10 @@ impl MasterPty for UnixMasterPty {
Some(self.fd.0.as_raw_fd())
}
fn tty_name(&self) -> Option<PathBuf> {
self.tty_name.clone()
}
fn process_group_leader(&self) -> Option<libc::pid_t> {
match unsafe { libc::tcgetpgrp(self.fd.0.as_raw_fd()) } {
pid if pid > 0 => Some(pid),

View File

@ -289,6 +289,15 @@ impl UserData for PaneInformation {
None => Ok("".to_string()),
}
});
fields.add_field_method_get("tty_name", |_, this| {
let mut name = None;
if let Some(mux) = Mux::try_get() {
if let Some(pane) = mux.get_pane(this.pane_id) {
name = pane.tty_name();
}
}
Ok(name)
});
fields.add_field_method_get("current_working_dir", |_, this| {
let mut name = None;
if let Some(mux) = Mux::try_get() {

View File

@ -82,6 +82,11 @@ impl portable_pty::MasterPty for SshPty {
fn as_raw_fd(&self) -> Option<std::os::fd::RawFd> {
None
}
#[cfg(unix)]
fn tty_name(&self) -> Option<std::path::PathBuf> {
None
}
}
#[derive(Debug)]

View File

@ -138,6 +138,7 @@ struct CliListResultItem {
window_title: String,
is_active: bool,
is_zoomed: bool,
tty_name: Option<String>,
}
impl CliListResultItem {
@ -155,6 +156,7 @@ impl CliListResultItem {
top_row,
is_active_pane,
is_zoomed_pane,
tty_name,
size:
TerminalSize {
rows,
@ -194,6 +196,7 @@ impl CliListResultItem {
window_title: window_title.to_string(),
is_active: is_active_pane,
is_zoomed: is_zoomed_pane,
tty_name,
}
}
}