mirror of
https://github.com/wez/wezterm.git
synced 2024-11-22 04:56:12 +03:00
Add get_foreground_process_name, expose it and cwd in PaneInformation
Add `get_foreground_process_name` to both Pane and the lua wrapper. Add `foreground_process_name` and `current_working_dir` fields to `PaneInformation`. In order for those to be dynamically fetched, switch the lua conversion for `PaneInformation` to be a UserData with field access methods. It's a little more verbose but allows us to lazily compute these two new fields. refs: https://github.com/wez/wezterm/discussions/1421 refs: https://github.com/wez/wezterm/issues/915 refs: https://github.com/wez/wezterm/issues/876
This commit is contained in:
parent
38087755e1
commit
1d064e0913
13
Cargo.lock
generated
13
Cargo.lock
generated
@ -2247,20 +2247,21 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mlua"
|
||||
version = "0.5.4"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd448d3e7018f2ff38dd732a374045f5b037eb4ee477d9241d9bb8c209528c1c"
|
||||
checksum = "871831bd7c53c48b85db47a03e5974915679a91ddd5f897dece6ce030e5191d2"
|
||||
dependencies = [
|
||||
"bstr 0.2.17",
|
||||
"cc",
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
"lazy_static",
|
||||
"lua-src",
|
||||
"luajit-src",
|
||||
"num-traits",
|
||||
"once_cell",
|
||||
"pkg-config",
|
||||
"rustc-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3430,6 +3431,12 @@ version = "0.1.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.2.3"
|
||||
|
@ -25,7 +25,7 @@ lazy_static = "1.4"
|
||||
libc = "0.2"
|
||||
log = "0.4"
|
||||
luahelper = { path = "../luahelper" }
|
||||
mlua = {version="0.5", features=["vendored", "lua54", "async", "send"]}
|
||||
mlua = {version="0.7", features=["vendored", "lua54", "async", "send"]}
|
||||
# file change notification
|
||||
notify = "4.0"
|
||||
open = "2.0"
|
||||
|
@ -22,6 +22,7 @@ As features stabilize some brief notes about them will accumulate here.
|
||||
* [ActivateTabRelativeNoWrap](config/lua/keyassignment/ActivateTabRelativeNoWrap.md) key assignment [#1414](https://github.com/wez/wezterm/issues/1414)
|
||||
* [QuickSelectArgs](config/lua/keyassignment/QuickSelectArgs.md) key assignment [#846](https://github.com/wez/wezterm/issues/846) [#1362](https://github.com/wez/wezterm/issues/1362)
|
||||
* [wezterm.open_wth](config/lua/wezterm/open_with.md) function for opening URLs/documents with the default or a specific application [#1362](https://github.com/wez/wezterm/issues/1362)
|
||||
* [pane:get_foreground_process_name()](config/lua/pane/get_foreground_process_name.md) method, [PaneInformation](config/lua/PaneInformation.md) now has `foreground_process_name` and `current_working_dir` fields. [#1421](https://github.com/wez/wezterm/discussions/1421) [#915](https://github.com/wez/wezterm/issues/915) [#876](https://github.com/wez/wezterm/issues/876)
|
||||
|
||||
#### Changed
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
# PaneInformation
|
||||
|
||||
The `PaneInformation` struct describes a pane. Unlike [the Pane
|
||||
object](pane/index.md), `PaneInformation` is purely a snapshot of some of
|
||||
object](pane/index.md), `PaneInformation` is a snapshot of some of
|
||||
the key characteristics of the pane, intended for use in synchronous, fast,
|
||||
event callbacks that format GUI elements such as the window and tab title bars.
|
||||
|
||||
@ -20,3 +20,34 @@ The `PaneInformation` struct contains the following fields:
|
||||
* `title` - the title of the pane, per [pane:get_title()](pane/get_title.md) at the time the pane information was captured
|
||||
* `user_vars` - the user variables defined for the pane, per [pane:get_user_vars()](pane/get_user_vars.md) at the time the pane information was captured.
|
||||
|
||||
*Since: nightly builds only*
|
||||
|
||||
Additional fields are available; note that accessing these may not be cheap to
|
||||
compute and may slow down wezterm. Unlike the fields listed above, these are
|
||||
not pre-computed snapshots of information, so if you don't use them, you won't
|
||||
pay the cost of computing them.
|
||||
|
||||
* `foreground_process_name` - the path to the executable image per [pane:get_foreground_process_name()](pane/get_foreground_process_name.md), or an empty string if unavailable.
|
||||
* `current_working_dir` - the current working directory, per [pane:get_current_working_dir()](pane/get_current_working_dir.md).
|
||||
|
||||
This example places the executable name in the tab titles:
|
||||
|
||||
```lua
|
||||
local wezterm = require 'wezterm'
|
||||
|
||||
wezterm.on("format-tab-title", function(tab, tabs, panes, config, hover, max_width)
|
||||
local pane = tab.active_pane
|
||||
local title = pane.foreground_process_name .. " " .. pane.pane_id
|
||||
local color = "navy"
|
||||
if tab.is_active then
|
||||
color = "blue"
|
||||
end
|
||||
return {
|
||||
{Background={Color=color}},
|
||||
{Text=" " .. title .. " "},
|
||||
}
|
||||
end)
|
||||
|
||||
return {
|
||||
}
|
||||
```
|
||||
|
28
docs/config/lua/pane/get_foreground_process_name.md
Normal file
28
docs/config/lua/pane/get_foreground_process_name.md
Normal file
@ -0,0 +1,28 @@
|
||||
# `pane:get_foreground_process_name()`
|
||||
|
||||
*Since: nightly builds only*
|
||||
|
||||
Returns the path to the executable image for the pane.
|
||||
|
||||
This method has some restrictions and caveats:
|
||||
|
||||
* 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.
|
||||
* On unix systems, the *process group leader* (the foreground process) will be queried, but that concept doesn't exist on Windows, so instead, the program that was used to launch the pane will be used
|
||||
* On Linux, macOS and Windows, the process can be queried to determine this path. Other operating systems (notably, FreeBSD and other unix systems) are not currently supported
|
||||
* Querying the path may fail for a variety of reasons outside of the control of WezTerm
|
||||
* Querying process information has some runtime overhead, which may cause wezterm to slow down if over-used.
|
||||
|
||||
If the path is not known then this method returns `nil`.
|
||||
|
||||
This example sets the right status are to the executable path:
|
||||
|
||||
```lua
|
||||
local wezterm = require 'wezterm'
|
||||
|
||||
wezterm.on("update-right-status", function(window, pane)
|
||||
window:set_right_status(pane:get_foreground_process_name())
|
||||
end)
|
||||
|
||||
return {
|
||||
}
|
||||
```
|
@ -9,7 +9,7 @@ edition = "2018"
|
||||
[dependencies]
|
||||
bstr = "0.2"
|
||||
log = "0.4"
|
||||
mlua = "0.5"
|
||||
mlua = "0.7"
|
||||
serde = {version="1.0", features = ["rc", "derive"]}
|
||||
serde_json = "1.0"
|
||||
strsim = "0.10"
|
||||
|
@ -20,7 +20,7 @@ libc = "0.2"
|
||||
log = "0.4"
|
||||
luahelper = { path = "../luahelper" }
|
||||
metrics = { version="0.17", features=["std"]}
|
||||
mlua = "0.5"
|
||||
mlua = "0.7"
|
||||
portable-pty = { path = "../pty", features = ["serde_support"]}
|
||||
promise = { path = "../promise" }
|
||||
rangeset = { path = "../rangeset" }
|
||||
|
@ -320,6 +320,36 @@ impl Pane for LocalPane {
|
||||
.or_else(|| self.divine_current_working_dir())
|
||||
}
|
||||
|
||||
#[cfg(not(any(windows, target_os = "linux", target_os = "macos")))]
|
||||
fn get_foreground_process_name(&self) -> Option<String> {
|
||||
None
|
||||
}
|
||||
|
||||
#[cfg(any(windows, target_os = "linux", target_os = "macos"))]
|
||||
fn get_foreground_process_name(&self) -> Option<String> {
|
||||
use sysinfo::{Pid, ProcessExt, ProcessRefreshKind, RefreshKind, System, SystemExt};
|
||||
let leader;
|
||||
|
||||
#[cfg(unix)]
|
||||
{
|
||||
leader = self.pty.borrow().process_group_leader()?;
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
if let ProcessState::Running { pid: Some(pid), .. } = &*self.process.borrow() {
|
||||
leader = *pid;
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
let system = System::new_with_specifics(
|
||||
RefreshKind::new().with_processes(ProcessRefreshKind::new()),
|
||||
);
|
||||
let proc = system.process(leader as Pid)?;
|
||||
Some(proc.exe().to_string_lossy().to_string())
|
||||
}
|
||||
|
||||
fn can_close_without_prompting(&self, _reason: CloseReason) -> bool {
|
||||
if let Some(proc_list) = self.divine_process_list() {
|
||||
log::trace!(
|
||||
|
@ -370,6 +370,9 @@ pub trait Pane: Downcast {
|
||||
}
|
||||
|
||||
fn get_current_working_dir(&self) -> Option<Url>;
|
||||
fn get_foreground_process_name(&self) -> Option<String> {
|
||||
None
|
||||
}
|
||||
|
||||
fn trickle_paste(&self, text: String) -> anyhow::Result<()> {
|
||||
if text.len() <= PASTE_CHUNK_SIZE {
|
||||
|
@ -42,7 +42,7 @@ log = "0.4"
|
||||
lru = "0.7"
|
||||
luahelper = { path = "../luahelper" }
|
||||
metrics = { version="0.17", features=["std"]}
|
||||
mlua = "0.5"
|
||||
mlua = "0.7"
|
||||
mux = { path = "../mux" }
|
||||
open = "2.0"
|
||||
ordered-float = "2.8"
|
||||
|
@ -38,6 +38,9 @@ impl UserData for PaneObject {
|
||||
.get_current_working_dir()
|
||||
.map(|u| u.to_string()))
|
||||
});
|
||||
methods.add_method("get_foreground_process_name", |_, this, _: ()| {
|
||||
Ok(this.pane()?.get_foreground_process_name())
|
||||
});
|
||||
methods.add_method("paste", |_, this, text: String| {
|
||||
this.pane()?.send_paste(&text).map_err(luaerr)?;
|
||||
Ok(())
|
||||
|
@ -26,8 +26,7 @@ use config::{
|
||||
configuration, AudibleBell, ConfigHandle, DimensionContext, GradientOrientation, TermConfig,
|
||||
WindowCloseConfirmation,
|
||||
};
|
||||
use luahelper::impl_lua_conversion;
|
||||
use mlua::FromLua;
|
||||
use mlua::{FromLua, UserData, UserDataFields};
|
||||
use mux::domain::{DomainId, DomainState};
|
||||
use mux::pane::{CloseReason, Pane, PaneId};
|
||||
use mux::renderable::RenderableDimensions;
|
||||
@ -35,7 +34,6 @@ use mux::tab::{PositionedPane, PositionedSplit, SplitDirection, Tab, TabId};
|
||||
use mux::window::WindowId as MuxWindowId;
|
||||
use mux::{Mux, MuxNotification};
|
||||
use portable_pty::PtySize;
|
||||
use serde::*;
|
||||
use smol::channel::Sender;
|
||||
use smol::Timer;
|
||||
use std::cell::{RefCell, RefMut};
|
||||
@ -157,17 +155,31 @@ pub struct PaneState {
|
||||
}
|
||||
|
||||
/// Data used when synchronously formatting pane and window titles
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TabInformation {
|
||||
pub tab_id: TabId,
|
||||
pub tab_index: usize,
|
||||
pub is_active: bool,
|
||||
pub active_pane: Option<PaneInformation>,
|
||||
}
|
||||
impl_lua_conversion!(TabInformation);
|
||||
|
||||
impl UserData for TabInformation {
|
||||
fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("tab_id", |_, this| Ok(this.tab_id));
|
||||
fields.add_field_method_get("tab_index", |_, this| Ok(this.tab_index));
|
||||
fields.add_field_method_get("is_active", |_, this| Ok(this.is_active));
|
||||
fields.add_field_method_get("active_pane", |_, this| {
|
||||
if let Some(pane) = &this.active_pane {
|
||||
Ok(Some(pane.clone()))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Data used when synchronously formatting pane and window titles
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PaneInformation {
|
||||
pub pane_id: PaneId,
|
||||
pub pane_index: usize,
|
||||
@ -182,7 +194,47 @@ pub struct PaneInformation {
|
||||
pub title: String,
|
||||
pub user_vars: HashMap<String, String>,
|
||||
}
|
||||
impl_lua_conversion!(PaneInformation);
|
||||
|
||||
impl UserData for PaneInformation {
|
||||
fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("pane_id", |_, this| Ok(this.pane_id));
|
||||
fields.add_field_method_get("pane_index", |_, this| Ok(this.pane_index));
|
||||
fields.add_field_method_get("is_active", |_, this| Ok(this.is_active));
|
||||
fields.add_field_method_get("is_zoomed", |_, this| Ok(this.is_zoomed));
|
||||
fields.add_field_method_get("left", |_, this| Ok(this.left));
|
||||
fields.add_field_method_get("top", |_, this| Ok(this.top));
|
||||
fields.add_field_method_get("width", |_, this| Ok(this.width));
|
||||
fields.add_field_method_get("height", |_, this| Ok(this.height));
|
||||
fields.add_field_method_get("pixel_width", |_, this| Ok(this.pixel_width));
|
||||
fields.add_field_method_get("pixel_height", |_, this| Ok(this.pixel_width));
|
||||
fields.add_field_method_get("title", |_, this| Ok(this.title.clone()));
|
||||
fields.add_field_method_get("user_vars", |_, this| Ok(this.user_vars.clone()));
|
||||
fields.add_field_method_get("foreground_process_name", |_, this| {
|
||||
let mut name = None;
|
||||
if let Some(mux) = Mux::get() {
|
||||
if let Some(pane) = mux.get_pane(this.pane_id) {
|
||||
name = pane.get_foreground_process_name();
|
||||
}
|
||||
}
|
||||
match name {
|
||||
Some(name) => Ok(name),
|
||||
None => Ok("".to_string()),
|
||||
}
|
||||
});
|
||||
fields.add_field_method_get("current_working_dir", |_, this| {
|
||||
let mut name = None;
|
||||
if let Some(mux) = Mux::get() {
|
||||
if let Some(pane) = mux.get_pane(this.pane_id) {
|
||||
name = pane.get_current_working_dir().map(|u| u.to_string());
|
||||
}
|
||||
}
|
||||
match name {
|
||||
Some(name) => Ok(name),
|
||||
None => Ok("".to_string()),
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct TabState {
|
||||
|
Loading…
Reference in New Issue
Block a user