diff --git a/kitty/child.py b/kitty/child.py index 75dafa7d4..4c16837b4 100644 --- a/kitty/child.py +++ b/kitty/child.py @@ -11,7 +11,7 @@ import kitty.fast_data_types as fast_data_types from .constants import handled_signals, is_freebsd, is_macos, kitten_exe, kitty_base_dir, shell_path, terminfo_dir from .types import run_once -from .utils import log_error, which +from .utils import cmdline_for_hold, log_error, which try: from typing import TypedDict @@ -200,6 +200,7 @@ class Child: cwd_from: Optional['CwdRequest'] = None, is_clone_launch: str = '', add_listen_on_env_var: bool = True, + hold: bool = False, ): self.is_clone_launch = is_clone_launch self.add_listen_on_env_var = add_listen_on_env_var @@ -217,6 +218,7 @@ class Child: self.final_env:Dict[str, str] = {} self.is_default_shell = bool(self.argv and self.argv[0] == shell_path) self.should_run_via_run_shell_kitten = is_macos and self.is_default_shell + self.hold = hold def get_final_env(self) -> Dict[str, str]: from kitty.options.utils import DELETE_ENV_VAR @@ -309,11 +311,14 @@ class Child: argv.append('--cwd=' + cwd) cwd = os.path.expanduser('~') argv = ['/usr/bin/login', '-f', '-l', '-p', user] + argv - self.final_exe = which(argv[0]) or argv[0] + self.final_exe = final_exe = which(argv[0]) or argv[0] self.final_argv0 = argv[0] + if self.hold: + argv = cmdline_for_hold(argv) + final_exe = argv[0] env = tuple(f'{k}={v}' for k, v in self.final_env.items()) pid = fast_data_types.spawn( - self.final_exe, cwd, tuple(argv), env, master, slave, stdin_read_fd, stdin_write_fd, + final_exe, cwd, tuple(argv), env, master, slave, stdin_read_fd, stdin_write_fd, ready_read_fd, ready_write_fd, tuple(handled_signals), kitten_exe(), opts.forward_stdio) os.close(slave) self.pid = pid diff --git a/kitty/launch.py b/kitty/launch.py index 95cc15af8..613f2cc0f 100644 --- a/kitty/launch.py +++ b/kitty/launch.py @@ -16,7 +16,7 @@ from .fast_data_types import add_timer, get_boss, get_options, get_os_window_tit from .options.utils import env as parse_env from .tabs import Tab, TabManager from .types import OverlayType, run_once -from .utils import cmdline_for_hold, get_editor, log_error, resolve_custom_file, resolved_shell, which +from .utils import get_editor, log_error, resolve_custom_file, which from .window import CwdRequest, CwdRequestType, Watchers, Window try: @@ -423,6 +423,7 @@ class LaunchKwds(TypedDict): cmd: Optional[List[str]] overlay_for: Optional[int] stdin: Optional[bytes] + hold: bool def apply_colors(window: Window, spec: Sequence[str]) -> None: @@ -504,7 +505,8 @@ def _launch( 'marker': opts.marker or None, 'cmd': None, 'overlay_for': None, - 'stdin': None + 'stdin': None, + 'hold': False, } spacing = {} if opts.spacing: @@ -607,11 +609,7 @@ def _launch( else: set_primary_selection(stdin) else: - if opts.hold: - cmd = kw['cmd'] or resolved_shell() - if not os.path.isabs(cmd[0]): - cmd[0] = which(cmd[0]) or cmd[0] - kw['cmd'] = cmdline_for_hold(cmd) + kw['hold'] = opts.hold if force_target_tab: tab = target_tab else: diff --git a/kitty/session.py b/kitty/session.py index 9123c4f4c..bf1d9efbf 100644 --- a/kitty/session.py +++ b/kitty/session.py @@ -14,7 +14,7 @@ from .options.types import Options from .options.utils import resize_window, to_layout_names, window_size from .os_window_size import WindowSize, WindowSizeData, WindowSizes from .typing import SpecialWindowInstance -from .utils import cmdline_for_hold, expandvars, log_error, resolve_custom_file, resolved_shell, shlex_split, which +from .utils import expandvars, log_error, resolve_custom_file, resolved_shell, shlex_split if TYPE_CHECKING: from .launch import LaunchSpec @@ -237,11 +237,8 @@ def create_sessions( ans.tabs[-1].layout = current_layout if special_window is None: cmd = args.args if args and args.args else resolved_shell(opts) - if args and args.hold: - cmd[0] = which(cmd[0]) or cmd[0] - cmd = cmdline_for_hold(cmd) from kitty.tabs import SpecialWindow cwd: Optional[str] = args.directory if respect_cwd and args else None - special_window = SpecialWindow(cmd, cwd_from=cwd_from, cwd=cwd) + special_window = SpecialWindow(cmd, cwd_from=cwd_from, cwd=cwd, hold=bool(args and args.hold)) ans.add_special_window(special_window) yield ans diff --git a/kitty/tabs.py b/kitty/tabs.py index 32971230c..e5eafc402 100644 --- a/kitty/tabs.py +++ b/kitty/tabs.py @@ -95,6 +95,7 @@ class SpecialWindowInstance(NamedTuple): env: Optional[Dict[str, str]] watchers: Optional[Watchers] overlay_behind: bool + hold: bool def SpecialWindow( @@ -106,9 +107,10 @@ def SpecialWindow( overlay_for: Optional[int] = None, env: Optional[Dict[str, str]] = None, watchers: Optional[Watchers] = None, - overlay_behind: bool = False + overlay_behind: bool = False, + hold: bool = False, ) -> SpecialWindowInstance: - return SpecialWindowInstance(cmd, stdin, override_title, cwd_from, cwd, overlay_for, env, watchers, overlay_behind) + return SpecialWindowInstance(cmd, stdin, override_title, cwd_from, cwd, overlay_for, env, watchers, overlay_behind, hold) def add_active_id_to_history(items: Deque[int], item_id: int, maxlen: int = 64) -> None: @@ -440,6 +442,7 @@ class Tab: # {{{ env: Optional[Dict[str, str]] = None, is_clone_launch: str = '', add_listen_on_env_var: bool = True, + hold: bool = False, ) -> Child: check_for_suitability = True if cmd is None: @@ -487,7 +490,7 @@ class Tab: # {{{ pwid = platform_window_id(self.os_window_id) if pwid is not None: fenv['WINDOWID'] = str(pwid) - ans = Child(cmd, cwd or self.cwd, stdin, fenv, cwd_from, is_clone_launch=is_clone_launch, add_listen_on_env_var=add_listen_on_env_var) + ans = Child(cmd, cwd or self.cwd, stdin, fenv, cwd_from, is_clone_launch=is_clone_launch, add_listen_on_env_var=add_listen_on_env_var, hold=hold) ans.fork() return ans @@ -514,10 +517,12 @@ class Tab: # {{{ overlay_behind: bool = False, is_clone_launch: str = '', remote_control_passwords: Optional[Dict[str, Sequence[str]]] = None, + hold: bool = False, ) -> Window: child = self.launch_child( use_shell=use_shell, cmd=cmd, stdin=stdin, cwd_from=cwd_from, cwd=cwd, env=env, - is_clone_launch=is_clone_launch, add_listen_on_env_var=False if allow_remote_control and remote_control_passwords else True + is_clone_launch=is_clone_launch, add_listen_on_env_var=False if allow_remote_control and remote_control_passwords else True, + hold=hold, ) window = Window( self, child, self.args, override_title=override_title, @@ -547,7 +552,8 @@ class Tab: # {{{ override_title=special_window.override_title, cwd_from=special_window.cwd_from, cwd=special_window.cwd, overlay_for=special_window.overlay_for, env=special_window.env, location=location, copy_colors_from=copy_colors_from, - allow_remote_control=allow_remote_control, watchers=special_window.watchers, overlay_behind=special_window.overlay_behind + allow_remote_control=allow_remote_control, watchers=special_window.watchers, overlay_behind=special_window.overlay_behind, + hold=special_window.hold, ) @ac('win', 'Close all windows in the tab other than the currently active window')