Allow reloading conf in all kitty instances as well
This commit is contained in:
parent
a49f6799de
commit
ca9143bebc
@ -12,12 +12,15 @@ import signal
|
|||||||
import tempfile
|
import tempfile
|
||||||
import zipfile
|
import zipfile
|
||||||
from contextlib import suppress
|
from contextlib import suppress
|
||||||
from typing import Any, Callable, Dict, Iterator, Match, Optional, Tuple, Union
|
from typing import (
|
||||||
|
Any, Callable, Dict, Iterable, Iterator, List, Match, Optional, Tuple,
|
||||||
|
Union
|
||||||
|
)
|
||||||
from urllib.error import HTTPError
|
from urllib.error import HTTPError
|
||||||
from urllib.request import Request, urlopen
|
from urllib.request import Request, urlopen
|
||||||
|
|
||||||
from kitty.config import atomic_save, parse_config
|
from kitty.config import atomic_save, parse_config
|
||||||
from kitty.constants import cache_dir, config_dir
|
from kitty.constants import cache_dir, config_dir, is_macos
|
||||||
from kitty.options.types import Options as KittyOptions
|
from kitty.options.types import Options as KittyOptions
|
||||||
from kitty.rgb import Color
|
from kitty.rgb import Color
|
||||||
|
|
||||||
@ -27,6 +30,28 @@ MARK_BEFORE = '\033[33m'
|
|||||||
MARK_AFTER = '\033[39m'
|
MARK_AFTER = '\033[39m'
|
||||||
|
|
||||||
|
|
||||||
|
def is_kitty_gui(cmd: List[str]) -> bool:
|
||||||
|
if not cmd:
|
||||||
|
return False
|
||||||
|
if os.path.basename(cmd[0]) != 'kitty':
|
||||||
|
return False
|
||||||
|
if len(cmd) == 1:
|
||||||
|
return True
|
||||||
|
if '+' in cmd or '@' in cmd or cmd[1].startswith('+') or cmd[1].startswith('@'):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def get_all_processes() -> Iterable[int]:
|
||||||
|
if is_macos:
|
||||||
|
from kitty.fast_data_types import get_all_processes as f
|
||||||
|
yield from f()
|
||||||
|
else:
|
||||||
|
for c in os.listdir('/proc'):
|
||||||
|
if c.isdigit():
|
||||||
|
yield int(c)
|
||||||
|
|
||||||
|
|
||||||
def patch_conf(raw: str) -> str:
|
def patch_conf(raw: str) -> str:
|
||||||
addition = '# BEGIN_KITTY_THEME\ninclude current-theme.conf\n# END_KITTY_THEME'
|
addition = '# BEGIN_KITTY_THEME\ninclude current-theme.conf\n# END_KITTY_THEME'
|
||||||
nraw, num = re.subn(r'^# BEGIN_KITTY_THEME.+?# END_KITTY_THEME', addition, raw, flags=re.MULTILINE | re.DOTALL)
|
nraw, num = re.subn(r'^# BEGIN_KITTY_THEME.+?# END_KITTY_THEME', addition, raw, flags=re.MULTILINE | re.DOTALL)
|
||||||
@ -254,7 +279,7 @@ class Theme:
|
|||||||
def save_in_dir(self, dirpath: str) -> None:
|
def save_in_dir(self, dirpath: str) -> None:
|
||||||
atomic_save(self.raw.encode('utf-8'), os.path.join(dirpath, f'{self.name}.conf'))
|
atomic_save(self.raw.encode('utf-8'), os.path.join(dirpath, f'{self.name}.conf'))
|
||||||
|
|
||||||
def save_in_conf(self, confdir: str) -> None:
|
def save_in_conf(self, confdir: str, reload_in: str) -> None:
|
||||||
atomic_save(self.raw.encode('utf-8'), os.path.join(confdir, 'current-theme.conf'))
|
atomic_save(self.raw.encode('utf-8'), os.path.join(confdir, 'current-theme.conf'))
|
||||||
confpath = os.path.join(confdir, 'kitty.conf')
|
confpath = os.path.join(confdir, 'kitty.conf')
|
||||||
try:
|
try:
|
||||||
@ -267,8 +292,18 @@ class Theme:
|
|||||||
with open(confpath + '.bak', 'w') as f:
|
with open(confpath + '.bak', 'w') as f:
|
||||||
f.write(raw)
|
f.write(raw)
|
||||||
atomic_save(nraw.encode('utf-8'), confpath)
|
atomic_save(nraw.encode('utf-8'), confpath)
|
||||||
if 'KITTY_PID' in os.environ:
|
if reload_in == 'parent':
|
||||||
os.kill(int(os.environ['KITTY_PID']), signal.SIGUSR1)
|
if 'KITTY_PID' in os.environ:
|
||||||
|
os.kill(int(os.environ['KITTY_PID']), signal.SIGUSR1)
|
||||||
|
elif reload_in == 'all':
|
||||||
|
from kitty.child import cmdline_of_process # type: ignore
|
||||||
|
for pid in get_all_processes():
|
||||||
|
try:
|
||||||
|
cmd = cmdline_of_process(pid)
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
if cmd and is_kitty_gui(cmd):
|
||||||
|
os.kill(pid, signal.SIGUSR1)
|
||||||
|
|
||||||
|
|
||||||
class Themes:
|
class Themes:
|
||||||
|
|||||||
@ -466,7 +466,7 @@ class ThemesHandler(Handler):
|
|||||||
self.quit_loop(0)
|
self.quit_loop(0)
|
||||||
return
|
return
|
||||||
if key_event.matches('m'):
|
if key_event.matches('m'):
|
||||||
self.themes_list.current_theme.save_in_conf(config_dir)
|
self.themes_list.current_theme.save_in_conf(config_dir, self.cli_opts.reload_in)
|
||||||
self.update_recent()
|
self.update_recent()
|
||||||
self.quit_loop(0)
|
self.quit_loop(0)
|
||||||
return
|
return
|
||||||
@ -520,6 +520,20 @@ for new themes, instead raising an error if a local copy of the themes
|
|||||||
is not available.
|
is not available.
|
||||||
|
|
||||||
|
|
||||||
|
--reload-in
|
||||||
|
default=parent
|
||||||
|
choices=none,parent,all
|
||||||
|
By default, this kitten will signal only the parent kitty instance it is
|
||||||
|
running in to reload its config, after making changes. Use this option
|
||||||
|
to instead either not reload the config at all or in all running
|
||||||
|
kitty instances.
|
||||||
|
|
||||||
|
|
||||||
|
--dump-theme
|
||||||
|
type=bool-set
|
||||||
|
default=false
|
||||||
|
When running non-interactively, dump the specified theme to STDOUT
|
||||||
|
instead of changing kitty.conf.
|
||||||
'''.format
|
'''.format
|
||||||
|
|
||||||
|
|
||||||
@ -536,7 +550,10 @@ def non_interactive(cli_opts: ThemesCLIOptions, theme_name: str) -> None:
|
|||||||
theme = themes[theme_name]
|
theme = themes[theme_name]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise SystemExit(f'No theme named: {theme_name}')
|
raise SystemExit(f'No theme named: {theme_name}')
|
||||||
theme.save_in_conf(config_dir)
|
if cli_opts.dump_theme:
|
||||||
|
print(theme.raw)
|
||||||
|
return
|
||||||
|
theme.save_in_conf(config_dir, cli_opts.reload_in)
|
||||||
|
|
||||||
|
|
||||||
def main(args: List[str]) -> None:
|
def main(args: List[str]) -> None:
|
||||||
@ -548,7 +565,7 @@ def main(args: List[str]) -> None:
|
|||||||
input(_('Press Enter to quit'))
|
input(_('Press Enter to quit'))
|
||||||
return None
|
return None
|
||||||
if len(items) > 1:
|
if len(items) > 1:
|
||||||
raise SystemExit('At most one theme name must be specified')
|
items = [' '.join(items[1:])]
|
||||||
if len(items) == 1:
|
if len(items) == 1:
|
||||||
return non_interactive(cli_opts, items[0])
|
return non_interactive(cli_opts, items[0])
|
||||||
|
|
||||||
|
|||||||
@ -1213,3 +1213,7 @@ class OSWindowSize(TypedDict):
|
|||||||
|
|
||||||
def get_os_window_size(os_window_id: int) -> Optional[OSWindowSize]:
|
def get_os_window_size(os_window_id: int) -> Optional[OSWindowSize]:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def get_all_processes() -> Tuple[int, ...]:
|
||||||
|
pass
|
||||||
|
|||||||
@ -34,6 +34,25 @@ get_argmax() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
get_all_processes(PyObject *self UNUSED, PyObject *args UNUSED) {
|
||||||
|
pid_t num = proc_listallpids(NULL, 0);
|
||||||
|
if (num <= 0) return PyTuple_New(0);
|
||||||
|
size_t sz = sizeof(pid_t) * num * 2;
|
||||||
|
pid_t *buf = malloc(sz);
|
||||||
|
if (!buf) return PyErr_NoMemory();
|
||||||
|
num = proc_listallpids(buf, sz);
|
||||||
|
if (num <= 0) { free(buf); return PyTuple_New(0); }
|
||||||
|
PyObject *ans = PyTuple_New(num);
|
||||||
|
if (!ans) { free(buf); return NULL; }
|
||||||
|
for (pid_t i = 0; i < num; i++) {
|
||||||
|
long long pid = buf[i];
|
||||||
|
PyObject *t = PyLong_FromLongLong(pid);
|
||||||
|
if (!t) { free(buf); Py_CLEAR(ans); return NULL; }
|
||||||
|
PyTuple_SET_ITEM(ans, i, t);
|
||||||
|
}
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
cmdline_of_process(PyObject *self UNUSED, PyObject *pid_) {
|
cmdline_of_process(PyObject *self UNUSED, PyObject *pid_) {
|
||||||
@ -255,6 +274,7 @@ static PyMethodDef module_methods[] = {
|
|||||||
{"cwd_of_process", (PyCFunction)cwd_of_process, METH_O, ""},
|
{"cwd_of_process", (PyCFunction)cwd_of_process, METH_O, ""},
|
||||||
{"cmdline_of_process", (PyCFunction)cmdline_of_process, METH_O, ""},
|
{"cmdline_of_process", (PyCFunction)cmdline_of_process, METH_O, ""},
|
||||||
{"environ_of_process", (PyCFunction)environ_of_process, METH_O, ""},
|
{"environ_of_process", (PyCFunction)environ_of_process, METH_O, ""},
|
||||||
|
{"get_all_processes", (PyCFunction)get_all_processes, METH_NOARGS, ""},
|
||||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user