Use a full window object rather than a child PID to get cwd

This allows implementation of more sophisticated algorithmhs
for getting the cwd
This commit is contained in:
Kovid Goyal 2022-03-15 07:58:57 +05:30
parent 7224363639
commit 8f77cc65e2
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
5 changed files with 33 additions and 32 deletions

View File

@ -17,7 +17,7 @@ from typing import (
from weakref import WeakValueDictionary from weakref import WeakValueDictionary
from .child import ( from .child import (
cached_process_data, cwd_of_process, default_env, set_default_env cached_process_data, default_env, set_default_env
) )
from .cli import create_opts, parse_args from .cli import create_opts, parse_args
from .cli_stub import CLIOptions from .cli_stub import CLIOptions
@ -440,7 +440,7 @@ class Boss:
return os_window_id return os_window_id
return None return None
def _new_os_window(self, args: Union[SpecialWindowInstance, Iterable[str]], cwd_from: Optional[int] = None) -> int: def _new_os_window(self, args: Union[SpecialWindowInstance, Iterable[str]], cwd_from: Optional[Window] = None) -> int:
if isinstance(args, SpecialWindowInstance): if isinstance(args, SpecialWindowInstance):
sw: Optional[SpecialWindowInstance] = args sw: Optional[SpecialWindowInstance] = args
else: else:
@ -462,8 +462,7 @@ class Boss:
@ac('win', 'New OS Window with the same working directory as the currently active window') @ac('win', 'New OS Window with the same working directory as the currently active window')
def new_os_window_with_cwd(self, *args: str) -> None: def new_os_window_with_cwd(self, *args: str) -> None:
w = self.active_window_for_cwd w = self.active_window_for_cwd
cwd_from = w.child.pid_for_cwd if w is not None else None self._new_os_window(args, w)
self._new_os_window(args, cwd_from)
def new_os_window_with_wd(self, wd: str) -> None: def new_os_window_with_wd(self, wd: str) -> None:
special_window = SpecialWindow(None, cwd=wd) special_window = SpecialWindow(None, cwd=wd)
@ -1719,7 +1718,7 @@ class Boss:
self, cmd: List[str], self, cmd: List[str],
window: Optional[Window] = None, window: Optional[Window] = None,
stdin: Optional[str] = None, stdin: Optional[str] = None,
cwd_from: Optional[int] = None, cwd_from: Optional[Window] = None,
as_overlay: bool = False as_overlay: bool = False
) -> SpecialWindowInstance: ) -> SpecialWindowInstance:
w = window or self.active_window w = window or self.active_window
@ -1741,7 +1740,7 @@ class Boss:
cwd: Optional[str] = None, cwd: Optional[str] = None,
env: Optional[Dict[str, str]] = None, env: Optional[Dict[str, str]] = None,
stdin: Optional[bytes] = None, stdin: Optional[bytes] = None,
cwd_from: Optional[int] = None cwd_from: Optional[Window] = None
) -> None: ) -> None:
import subprocess import subprocess
env = env or None env = env or None
@ -1751,7 +1750,7 @@ class Boss:
env = env_ env = env_
if cwd_from: if cwd_from:
with suppress(Exception): with suppress(Exception):
cwd = cwd_of_process(cwd_from) cwd = cwd_from.cwd_of_child
if stdin: if stdin:
r, w = safe_pipe(False) r, w = safe_pipe(False)
@ -1768,8 +1767,7 @@ class Boss:
def pipe(self, source: str, dest: str, exe: str, *args: str) -> Optional[Window]: def pipe(self, source: str, dest: str, exe: str, *args: str) -> Optional[Window]:
cmd = [exe] + list(args) cmd = [exe] + list(args)
window = self.active_window window = cwd_from = self.active_window
cwd_from = window.child.pid_for_cwd if window else None
def create_window() -> SpecialWindowInstance: def create_window() -> SpecialWindowInstance:
return self.special_window_for_cmd( return self.special_window_for_cmd(
@ -1797,7 +1795,7 @@ class Boss:
self.run_background_process(cmd, cwd_from=cwd_from, stdin=stdin, env=env) self.run_background_process(cmd, cwd_from=cwd_from, stdin=stdin, env=env)
return None return None
def args_to_special_window(self, args: Iterable[str], cwd_from: Optional[int] = None) -> SpecialWindowInstance: def args_to_special_window(self, args: Iterable[str], cwd_from: Optional[Window] = None) -> SpecialWindowInstance:
args = list(args) args = list(args)
stdin = None stdin = None
w = self.active_window w = self.active_window
@ -1818,7 +1816,7 @@ class Boss:
cmd.append(arg) cmd.append(arg)
return SpecialWindow(cmd, stdin, cwd_from=cwd_from) return SpecialWindow(cmd, stdin, cwd_from=cwd_from)
def _new_tab(self, args: Union[SpecialWindowInstance, Iterable[str]], cwd_from: Optional[int] = None, as_neighbor: bool = False) -> Optional[Tab]: def _new_tab(self, args: Union[SpecialWindowInstance, Iterable[str]], cwd_from: Optional[Window] = None, as_neighbor: bool = False) -> Optional[Tab]:
special_window = None special_window = None
if args: if args:
if isinstance(args, SpecialWindowInstance): if isinstance(args, SpecialWindowInstance):
@ -1830,7 +1828,7 @@ class Boss:
return tm.new_tab(special_window=special_window, cwd_from=cwd_from, as_neighbor=as_neighbor) return tm.new_tab(special_window=special_window, cwd_from=cwd_from, as_neighbor=as_neighbor)
return None return None
def _create_tab(self, args: List[str], cwd_from: Optional[int] = None) -> None: def _create_tab(self, args: List[str], cwd_from: Optional[Window] = None) -> None:
as_neighbor = False as_neighbor = False
if args and args[0].startswith('!'): if args and args[0].startswith('!'):
as_neighbor = 'neighbor' in args[0][1:].split(',') as_neighbor = 'neighbor' in args[0][1:].split(',')
@ -1843,9 +1841,7 @@ class Boss:
@ac('tab', 'Create a new tab with working directory for the window in it set to the same as the active window') @ac('tab', 'Create a new tab with working directory for the window in it set to the same as the active window')
def new_tab_with_cwd(self, *args: str) -> None: def new_tab_with_cwd(self, *args: str) -> None:
w = self.active_window_for_cwd self._create_tab(list(args), cwd_from=self.active_window_for_cwd)
cwd_from = w.child.pid_for_cwd if w is not None else None
self._create_tab(list(args), cwd_from=cwd_from)
def new_tab_with_wd(self, wd: str) -> None: def new_tab_with_wd(self, wd: str) -> None:
if not self.os_window_map: if not self.os_window_map:
@ -1853,7 +1849,7 @@ class Boss:
special_window = SpecialWindow(None, cwd=wd) special_window = SpecialWindow(None, cwd=wd)
self._new_tab(special_window) self._new_tab(special_window)
def _new_window(self, args: List[str], cwd_from: Optional[int] = None) -> Optional[Window]: def _new_window(self, args: List[str], cwd_from: Optional[Window] = None) -> Optional[Window]:
tab = self.active_tab tab = self.active_tab
if tab is None: if tab is None:
return None return None
@ -1881,8 +1877,7 @@ class Boss:
w = self.active_window_for_cwd w = self.active_window_for_cwd
if w is None: if w is None:
return self.new_window(*args) return self.new_window(*args)
cwd_from = w.child.pid_for_cwd self._new_window(list(args), cwd_from=w)
self._new_window(list(args), cwd_from=cwd_from)
@ac('misc', ''' @ac('misc', '''
Launch the specified program in a new window/tab/etc. Launch the specified program in a new window/tab/etc.

View File

@ -7,7 +7,7 @@ import sys
from collections import defaultdict from collections import defaultdict
from contextlib import contextmanager, suppress from contextlib import contextmanager, suppress
from typing import ( from typing import (
DefaultDict, Dict, Generator, List, Optional, Sequence, Tuple DefaultDict, Dict, Generator, List, Optional, Sequence, Tuple, TYPE_CHECKING
) )
import kitty.fast_data_types as fast_data_types import kitty.fast_data_types as fast_data_types
@ -20,6 +20,8 @@ try:
from typing import TypedDict from typing import TypedDict
except ImportError: except ImportError:
TypedDict = dict TypedDict = dict
if TYPE_CHECKING:
from .window import Window
if is_macos: if is_macos:
@ -192,14 +194,14 @@ class Child:
cwd: str, cwd: str,
stdin: Optional[bytes] = None, stdin: Optional[bytes] = None,
env: Optional[Dict[str, str]] = None, env: Optional[Dict[str, str]] = None,
cwd_from: Optional[int] = None, cwd_from: Optional['Window'] = None,
allow_remote_control: bool = False allow_remote_control: bool = False
): ):
self.allow_remote_control = allow_remote_control self.allow_remote_control = allow_remote_control
self.argv = list(argv) self.argv = list(argv)
if cwd_from is not None: if cwd_from is not None:
try: try:
cwd = cwd_of_process(cwd_from) cwd = cwd_from.cwd_of_child or cwd
except Exception as err: except Exception as err:
log_error(f'Failed to read cwd of {cwd_from} with error: {err}') log_error(f'Failed to read cwd of {cwd_from} with error: {err}')
else: else:

View File

@ -290,7 +290,7 @@ def load_watch_modules(watchers: Iterable[str]) -> Optional[Watchers]:
class LaunchKwds(TypedDict): class LaunchKwds(TypedDict):
allow_remote_control: bool allow_remote_control: bool
cwd_from: Optional[int] cwd_from: Optional[Window]
cwd: Optional[str] cwd: Optional[str]
location: Optional[str] location: Optional[str]
override_title: Optional[str] override_title: Optional[str]
@ -357,8 +357,8 @@ def launch(
} }
if opts.cwd: if opts.cwd:
if opts.cwd == 'current': if opts.cwd == 'current':
if active_child: if active:
kw['cwd_from'] = active_child.pid_for_cwd kw['cwd_from'] = active
else: else:
kw['cwd'] = opts.cwd kw['cwd'] = opts.cwd
if opts.location != 'default': if opts.location != 'default':

View File

@ -3,7 +3,7 @@
import shlex import shlex
import sys import sys
from typing import Generator, List, Optional, Union from typing import Generator, List, Optional, Union, TYPE_CHECKING
from .cli_stub import CLIOptions from .cli_stub import CLIOptions
from .options.utils import to_layout_names, window_size from .options.utils import to_layout_names, window_size
@ -15,6 +15,10 @@ from .typing import SpecialWindowInstance
from .utils import log_error, resolved_shell from .utils import log_error, resolved_shell
if TYPE_CHECKING:
from .window import Window
def get_os_window_sizing_data(opts: Options, session: Optional['Session'] = None) -> WindowSizeData: def get_os_window_sizing_data(opts: Options, session: Optional['Session'] = None) -> WindowSizeData:
if session is None or session.os_window_size is None: if session is None or session.os_window_size is None:
sizes = WindowSizes(WindowSize(*opts.initial_window_width), WindowSize(*opts.initial_window_height)) sizes = WindowSizes(WindowSize(*opts.initial_window_width), WindowSize(*opts.initial_window_height))
@ -146,7 +150,7 @@ def create_sessions(
opts: Options, opts: Options,
args: Optional[CLIOptions] = None, args: Optional[CLIOptions] = None,
special_window: Optional['SpecialWindowInstance'] = None, special_window: Optional['SpecialWindowInstance'] = None,
cwd_from: Optional[int] = None, cwd_from: Optional['Window'] = None,
respect_cwd: bool = False, respect_cwd: bool = False,
default_session: Optional[str] = None default_session: Optional[str] = None
) -> Generator[Session, None, None]: ) -> Generator[Session, None, None]:

View File

@ -58,7 +58,7 @@ class SpecialWindowInstance(NamedTuple):
cmd: Optional[List[str]] cmd: Optional[List[str]]
stdin: Optional[bytes] stdin: Optional[bytes]
override_title: Optional[str] override_title: Optional[str]
cwd_from: Optional[int] cwd_from: Optional[Window]
cwd: Optional[str] cwd: Optional[str]
overlay_for: Optional[int] overlay_for: Optional[int]
env: Optional[Dict[str, str]] env: Optional[Dict[str, str]]
@ -69,7 +69,7 @@ def SpecialWindow(
cmd: Optional[List[str]], cmd: Optional[List[str]],
stdin: Optional[bytes] = None, stdin: Optional[bytes] = None,
override_title: Optional[str] = None, override_title: Optional[str] = None,
cwd_from: Optional[int] = None, cwd_from: Optional[Window] = None,
cwd: Optional[str] = None, cwd: Optional[str] = None,
overlay_for: Optional[int] = None, overlay_for: Optional[int] = None,
env: Optional[Dict[str, str]] = None, env: Optional[Dict[str, str]] = None,
@ -98,7 +98,7 @@ class Tab: # {{{
tab_manager: 'TabManager', tab_manager: 'TabManager',
session_tab: Optional['SessionTab'] = None, session_tab: Optional['SessionTab'] = None,
special_window: Optional[SpecialWindowInstance] = None, special_window: Optional[SpecialWindowInstance] = None,
cwd_from: Optional[int] = None, cwd_from: Optional[Window] = None,
no_initial_window: bool = False no_initial_window: bool = False
): ):
self.tab_manager_ref = weakref.ref(tab_manager) self.tab_manager_ref = weakref.ref(tab_manager)
@ -347,7 +347,7 @@ class Tab: # {{{
use_shell: bool = False, use_shell: bool = False,
cmd: Optional[List[str]] = None, cmd: Optional[List[str]] = None,
stdin: Optional[bytes] = None, stdin: Optional[bytes] = None,
cwd_from: Optional[int] = None, cwd_from: Optional[Window] = None,
cwd: Optional[str] = None, cwd: Optional[str] = None,
env: Optional[Dict[str, str]] = None, env: Optional[Dict[str, str]] = None,
allow_remote_control: bool = False allow_remote_control: bool = False
@ -414,7 +414,7 @@ class Tab: # {{{
cmd: Optional[List[str]] = None, cmd: Optional[List[str]] = None,
stdin: Optional[bytes] = None, stdin: Optional[bytes] = None,
override_title: Optional[str] = None, override_title: Optional[str] = None,
cwd_from: Optional[int] = None, cwd_from: Optional[Window] = None,
cwd: Optional[str] = None, cwd: Optional[str] = None,
overlay_for: Optional[int] = None, overlay_for: Optional[int] = None,
env: Optional[Dict[str, str]] = None, env: Optional[Dict[str, str]] = None,
@ -942,7 +942,7 @@ class TabManager: # {{{
def new_tab( def new_tab(
self, self,
special_window: Optional[SpecialWindowInstance] = None, special_window: Optional[SpecialWindowInstance] = None,
cwd_from: Optional[int] = None, cwd_from: Optional[Window] = None,
as_neighbor: bool = False, as_neighbor: bool = False,
empty_tab: bool = False, empty_tab: bool = False,
location: str = 'last' location: str = 'last'