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