Unify the PATH searching algorithm for launch and running children
This commit is contained in:
parent
62dbc1129c
commit
32768e7939
@ -20,7 +20,7 @@ from kitty.typing import (
|
||||
GRT_C, CompletedProcess, GRT_a, GRT_d, GRT_f, GRT_m, GRT_o, GRT_t,
|
||||
HandlerType
|
||||
)
|
||||
from kitty.utils import ScreenSize, find_exe, fit_image
|
||||
from kitty.utils import ScreenSize, fit_image, which
|
||||
|
||||
from .operations import cursor
|
||||
|
||||
@ -148,7 +148,7 @@ def run_imagemagick(path: str, cmd: Sequence[str], keep_stdout: bool = True) ->
|
||||
def identify(path: str) -> ImageData:
|
||||
import json
|
||||
q = '{"fmt":"%m","canvas":"%g","transparency":"%A","gap":"%T","index":"%p","size":"%wx%h","dpi":"%xx%y","dispose":"%D","orientation":"%[EXIF:Orientation]"}'
|
||||
exe = find_exe('magick')
|
||||
exe = which('magick')
|
||||
if exe:
|
||||
cmd = [exe, 'identify']
|
||||
else:
|
||||
@ -190,11 +190,11 @@ def render_image(
|
||||
import tempfile
|
||||
has_multiple_frames = len(m) > 1
|
||||
get_multiple_frames = has_multiple_frames and not only_first_frame
|
||||
exe = find_exe('magick')
|
||||
exe = which('magick')
|
||||
if exe:
|
||||
cmd = [exe, 'convert']
|
||||
else:
|
||||
exe = find_exe('convert')
|
||||
exe = which('convert')
|
||||
if exe is None:
|
||||
raise OSError('Failed to find the ImageMagick convert executable, make sure it is present in PATH')
|
||||
cmd = [exe]
|
||||
|
||||
@ -12,6 +12,7 @@ from typing import (
|
||||
|
||||
import kitty.fast_data_types as fast_data_types
|
||||
|
||||
from .utils import which
|
||||
from .constants import is_macos, kitty_base_dir, shell_path, terminfo_dir
|
||||
from .types import run_once
|
||||
|
||||
@ -269,6 +270,7 @@ class Child:
|
||||
# xterm, urxvt, konsole and gnome-terminal do not do it in my
|
||||
# testing.
|
||||
argv[0] = ('-' + exe.split('/')[-1])
|
||||
exe = which(exe) or exe
|
||||
pid = fast_data_types.spawn(exe, self.cwd, tuple(argv), env, master, slave, stdin_read_fd, stdin_write_fd, ready_read_fd, ready_write_fd)
|
||||
os.close(slave)
|
||||
self.pid = pid
|
||||
|
||||
@ -9,13 +9,11 @@ from .child import Child
|
||||
from .cli import parse_args
|
||||
from .cli_stub import LaunchCLIOptions
|
||||
from .constants import resolve_custom_file
|
||||
from .fast_data_types import (
|
||||
get_options, patch_color_profiles, set_clipboard_string
|
||||
)
|
||||
from .fast_data_types import patch_color_profiles, set_clipboard_string
|
||||
from .options.utils import env as parse_env
|
||||
from .tabs import Tab
|
||||
from .types import run_once
|
||||
from .utils import find_exe, read_shell_environment, set_primary_selection, log_error
|
||||
from .utils import log_error, set_primary_selection, which
|
||||
from .window import Watchers, Window
|
||||
|
||||
try:
|
||||
@ -379,12 +377,7 @@ def launch(
|
||||
elif x == '@cursor-y':
|
||||
x = str(screen.cursor.y + 1)
|
||||
final_cmd.append(x)
|
||||
exe = find_exe(final_cmd[0])
|
||||
if not exe:
|
||||
xenv = read_shell_environment(get_options())
|
||||
if 'PATH' in xenv:
|
||||
import shutil
|
||||
exe = shutil.which(final_cmd[0], path=xenv['PATH'])
|
||||
exe = which(final_cmd[0])
|
||||
if exe:
|
||||
final_cmd[0] = exe
|
||||
kw['cmd'] = final_cmd
|
||||
|
||||
@ -512,7 +512,7 @@ def resolve_editor_cmd(editor: str, shell_env: Mapping[str, str]) -> Optional[st
|
||||
return ' '.join(map(shlex.quote, editor_cmd))
|
||||
|
||||
if shell_env is os.environ:
|
||||
q = find_exe(editor_exe)
|
||||
q = which(editor_exe, only_system=True)
|
||||
if q:
|
||||
return patched(q)
|
||||
elif 'PATH' in shell_env:
|
||||
@ -602,7 +602,7 @@ def resolved_shell(opts: Optional[Options] = None) -> List[str]:
|
||||
|
||||
|
||||
@run_once
|
||||
def system_paths_on_macos() -> List[str]:
|
||||
def system_paths_on_macos() -> Tuple[str, ...]:
|
||||
entries, seen = [], set()
|
||||
|
||||
def add_from_file(x: str) -> None:
|
||||
@ -624,23 +624,51 @@ def system_paths_on_macos() -> List[str]:
|
||||
for name in sorted(files):
|
||||
add_from_file(os.path.join('/etc/paths.d', name))
|
||||
add_from_file('/etc/paths')
|
||||
return entries
|
||||
return tuple(entries)
|
||||
|
||||
|
||||
@lru_cache(maxsize=32)
|
||||
def find_exe(name: str) -> Optional[str]:
|
||||
def which(name: str, only_system: bool = False) -> Optional[str]:
|
||||
import shutil
|
||||
ans = shutil.which(name)
|
||||
if ans is None:
|
||||
# In case PATH is messed up
|
||||
if is_macos:
|
||||
paths = system_paths_on_macos()
|
||||
else:
|
||||
paths = ['/usr/local/bin', '/opt/bin', '/usr/bin', '/bin', '/usr/sbin', '/sbin']
|
||||
paths.insert(0, os.path.expanduser('~/.local/bin'))
|
||||
path = os.pathsep.join(paths) + os.pathsep + os.defpath
|
||||
ans = shutil.which(name, path=path)
|
||||
return ans
|
||||
if os.sep in name:
|
||||
return name
|
||||
paths = []
|
||||
ep = os.environ.get('PATH')
|
||||
if ep:
|
||||
paths = os.pathsep.split(ep)
|
||||
paths.append(os.path.expanduser('~/.local/bin'))
|
||||
paths.append(os.path.expanduser('~/bin'))
|
||||
ans = shutil.which(name, path=os.pathsep.join(paths))
|
||||
if ans:
|
||||
return ans
|
||||
# In case PATH is messed up try a default set of paths
|
||||
if is_macos:
|
||||
system_paths = system_paths_on_macos()
|
||||
else:
|
||||
system_paths = ('/usr/local/bin', '/opt/bin', '/usr/bin', '/bin', '/usr/sbin', '/sbin')
|
||||
tried_paths = set(paths)
|
||||
system_paths = tuple(x for x in system_paths if x not in tried_paths)
|
||||
if system_paths:
|
||||
ans = shutil.which(name, path=os.pathsep.join(system_paths))
|
||||
if ans:
|
||||
return ans
|
||||
tried_paths |= set(system_paths)
|
||||
if only_system:
|
||||
return None
|
||||
from .fast_data_types import get_options
|
||||
try:
|
||||
opts = get_options()
|
||||
except RuntimeError:
|
||||
return None
|
||||
shell_env = read_shell_environment(opts)
|
||||
for xenv in (shell_env, opts.env):
|
||||
q = xenv.get('PATH')
|
||||
if q:
|
||||
paths = [x for x in xenv['PATH'].split(os.pathsep) if x not in tried_paths]
|
||||
ans = shutil.which(name, path=os.pathsep.join(paths))
|
||||
if ans:
|
||||
return ans
|
||||
tried_paths |= set(paths)
|
||||
return None
|
||||
|
||||
|
||||
def read_shell_environment(opts: Optional[Options] = None) -> Dict[str, str]:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user