Report the current foreground processes as well as the original child process, when using kitty @ ls
This commit is contained in:
parent
d9c69f0a54
commit
c4aeb1adba
@ -10,6 +10,9 @@ Changelog
|
|||||||
are formatted. In particular the template can be used to display
|
are formatted. In particular the template can be used to display
|
||||||
the tab number next to the title (:iss:`1223`)
|
the tab number next to the title (:iss:`1223`)
|
||||||
|
|
||||||
|
- Report the current foreground processes as well as the original child process,
|
||||||
|
when using `kitty @ ls`
|
||||||
|
|
||||||
- Fix setting :opt:`background_opacity` causing window margins/padding to be slightly
|
- Fix setting :opt:`background_opacity` causing window margins/padding to be slightly
|
||||||
different shade from background (:iss:`1221`)
|
different shade from background (:iss:`1221`)
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,7 @@ from functools import partial
|
|||||||
from gettext import gettext as _
|
from gettext import gettext as _
|
||||||
from weakref import WeakValueDictionary
|
from weakref import WeakValueDictionary
|
||||||
|
|
||||||
|
from .child import cached_process_data
|
||||||
from .cli import create_opts, parse_args
|
from .cli import create_opts, parse_args
|
||||||
from .conf.utils import to_cmdline
|
from .conf.utils import to_cmdline
|
||||||
from .config import initial_window_size_func, prepare_config_file_for_editing
|
from .config import initial_window_size_func, prepare_config_file_for_editing
|
||||||
@ -150,14 +151,15 @@ class Boss:
|
|||||||
return os_window_id
|
return os_window_id
|
||||||
|
|
||||||
def list_os_windows(self):
|
def list_os_windows(self):
|
||||||
active_tab, active_window = self.active_tab, self.active_window
|
with cached_process_data():
|
||||||
active_tab_manager = self.active_tab_manager
|
active_tab, active_window = self.active_tab, self.active_window
|
||||||
for os_window_id, tm in self.os_window_map.items():
|
active_tab_manager = self.active_tab_manager
|
||||||
yield {
|
for os_window_id, tm in self.os_window_map.items():
|
||||||
'id': os_window_id,
|
yield {
|
||||||
'is_focused': tm is active_tab_manager,
|
'id': os_window_id,
|
||||||
'tabs': list(tm.list_tabs(active_tab, active_window)),
|
'is_focused': tm is active_tab_manager,
|
||||||
}
|
'tabs': list(tm.list_tabs(active_tab, active_window)),
|
||||||
|
}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def all_tab_managers(self):
|
def all_tab_managers(self):
|
||||||
|
|||||||
@ -4,17 +4,28 @@
|
|||||||
|
|
||||||
import fcntl
|
import fcntl
|
||||||
import os
|
import os
|
||||||
|
from collections import defaultdict
|
||||||
|
from contextlib import contextmanager
|
||||||
|
|
||||||
import kitty.fast_data_types as fast_data_types
|
import kitty.fast_data_types as fast_data_types
|
||||||
|
|
||||||
from .constants import is_macos, shell_path, terminfo_dir
|
from .constants import is_macos, shell_path, terminfo_dir
|
||||||
|
|
||||||
if is_macos:
|
if is_macos:
|
||||||
from kitty.fast_data_types import cmdline_of_process, cwd_of_process as _cwd, environ_of_process as _environ_of_process
|
from kitty.fast_data_types import (
|
||||||
|
cmdline_of_process, cwd_of_process as _cwd, environ_of_process as _environ_of_process,
|
||||||
|
process_group_map as _process_group_map
|
||||||
|
)
|
||||||
|
|
||||||
def cwd_of_process(pid):
|
def cwd_of_process(pid):
|
||||||
return os.path.realpath(_cwd(pid))
|
return os.path.realpath(_cwd(pid))
|
||||||
|
|
||||||
|
def process_group_map():
|
||||||
|
ans = defaultdict(list)
|
||||||
|
for pid, pgid in _process_group_map():
|
||||||
|
ans[pgid].append(pid)
|
||||||
|
return ans
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
def cmdline_of_process(pid):
|
def cmdline_of_process(pid):
|
||||||
@ -27,6 +38,46 @@ else:
|
|||||||
def _environ_of_process(pid):
|
def _environ_of_process(pid):
|
||||||
return open('/proc/{}/environ'.format(pid), 'rb').read().decode('utf-8')
|
return open('/proc/{}/environ'.format(pid), 'rb').read().decode('utf-8')
|
||||||
|
|
||||||
|
def process_group_map():
|
||||||
|
ans = defaultdict(list)
|
||||||
|
for x in os.listdir('/proc'):
|
||||||
|
try:
|
||||||
|
pid = int(x)
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
raw = open('/proc/' + x + '/stat', 'rb').read().decode('utf-8')
|
||||||
|
except EnvironmentError:
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
q = int(raw.split(' ', 5)[4])
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
ans[q].append(pid)
|
||||||
|
return ans
|
||||||
|
|
||||||
|
|
||||||
|
def processes_in_group(grp):
|
||||||
|
gmap = getattr(process_group_map, 'cached_map', None)
|
||||||
|
if gmap is None:
|
||||||
|
try:
|
||||||
|
gmap = process_group_map()
|
||||||
|
except Exception:
|
||||||
|
gmap = {}
|
||||||
|
return gmap.get(grp, [])
|
||||||
|
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def cached_process_data():
|
||||||
|
try:
|
||||||
|
process_group_map.cached_map = process_group_map()
|
||||||
|
except Exception:
|
||||||
|
process_group_map.cached_map = {}
|
||||||
|
try:
|
||||||
|
yield
|
||||||
|
finally:
|
||||||
|
process_group_map.cached_map = None
|
||||||
|
|
||||||
|
|
||||||
def parse_environ_block(data):
|
def parse_environ_block(data):
|
||||||
"""Parse a C environ block of environment variables into a dictionary."""
|
"""Parse a C environ block of environment variables into a dictionary."""
|
||||||
@ -142,6 +193,24 @@ class Child:
|
|||||||
os.close(self.terminal_ready_fd)
|
os.close(self.terminal_ready_fd)
|
||||||
self.terminal_ready_fd = -1
|
self.terminal_ready_fd = -1
|
||||||
|
|
||||||
|
@property
|
||||||
|
def foreground_processes(self):
|
||||||
|
try:
|
||||||
|
pgrp = os.tcgetpgrp(self.child_fd)
|
||||||
|
foreground_processes = processes_in_group(pgrp) if pgrp >= 0 else []
|
||||||
|
|
||||||
|
def process_desc(pid):
|
||||||
|
ans = {'pid': pid}
|
||||||
|
try:
|
||||||
|
ans['cmdline'] = cmdline_of_process(pid)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return ans
|
||||||
|
|
||||||
|
return list(map(process_desc, foreground_processes))
|
||||||
|
except Exception:
|
||||||
|
return []
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def cmdline(self):
|
def cmdline(self):
|
||||||
try:
|
try:
|
||||||
|
|||||||
@ -40,6 +40,7 @@
|
|||||||
#define NS_TO_US (1000)
|
#define NS_TO_US (1000)
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
|
#include <libproc.h>
|
||||||
#include <mach/mach_time.h>
|
#include <mach/mach_time.h>
|
||||||
static mach_timebase_info_data_t timebase = {0};
|
static mach_timebase_info_data_t timebase = {0};
|
||||||
|
|
||||||
@ -54,6 +55,25 @@ user_cache_dir() {
|
|||||||
return PyUnicode_FromString(buf);
|
return PyUnicode_FromString(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
process_group_map() {
|
||||||
|
int num_of_processes = proc_listallpids(NULL, 0);
|
||||||
|
size_t bufsize = sizeof(pid_t) * (num_of_processes + 1024);
|
||||||
|
pid_t *buf = malloc(bufsize);
|
||||||
|
if (!buf) return PyErr_NoMemory();
|
||||||
|
num_of_processes = proc_listallpids(buf, (int)bufsize);
|
||||||
|
PyObject *ans = PyTuple_New(num_of_processes);
|
||||||
|
if (ans == NULL) { free(buf); return PyErr_NoMemory(); }
|
||||||
|
for (int i = 0; i < num_of_processes; i++) {
|
||||||
|
long pid = buf[i], pgid = getpgid(buf[i]);
|
||||||
|
PyObject *t = Py_BuildValue("ll", pid, pgid);
|
||||||
|
if (t == NULL) { free(buf); Py_DECREF(ans); return NULL; }
|
||||||
|
PyTuple_SET_ITEM(ans, i, t);
|
||||||
|
}
|
||||||
|
free(buf);
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
static inline double monotonic_() {
|
static inline double monotonic_() {
|
||||||
@ -177,6 +197,7 @@ static PyMethodDef module_methods[] = {
|
|||||||
{"redirect_std_streams", (PyCFunction)redirect_std_streams, METH_VARARGS, ""},
|
{"redirect_std_streams", (PyCFunction)redirect_std_streams, METH_VARARGS, ""},
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
METHODB(user_cache_dir, METH_NOARGS),
|
METHODB(user_cache_dir, METH_NOARGS),
|
||||||
|
METHODB(process_group_map, METH_NOARGS),
|
||||||
#endif
|
#endif
|
||||||
#ifdef WITH_PROFILER
|
#ifdef WITH_PROFILER
|
||||||
{"start_profiler", (PyCFunction)start_profiler, METH_VARARGS, ""},
|
{"start_profiler", (PyCFunction)start_profiler, METH_VARARGS, ""},
|
||||||
|
|||||||
@ -168,6 +168,7 @@ class Window:
|
|||||||
cwd=self.child.current_cwd or self.child.cwd,
|
cwd=self.child.current_cwd or self.child.cwd,
|
||||||
cmdline=self.child.cmdline,
|
cmdline=self.child.cmdline,
|
||||||
env=self.child.environ,
|
env=self.child.environ,
|
||||||
|
foreground_processes=self.child.foreground_processes
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user