diff --git a/kittens/hints/main.py b/kittens/hints/main.py index d8d4dd93d..f0c528206 100644 --- a/kittens/hints/main.py +++ b/kittens/hints/main.py @@ -19,7 +19,9 @@ from kitty.constants import website_url from kitty.fast_data_types import get_options, set_clipboard_string from kitty.key_encoding import KeyEvent from kitty.typing import BossType, KittyCommonOpts -from kitty.utils import ScreenSize, screen_size_function, set_primary_selection +from kitty.utils import ( + ScreenSize, resolve_custom_file, screen_size_function, set_primary_selection +) from ..tui.handler import Handler, result_handler from ..tui.loop import Loop @@ -414,7 +416,6 @@ def load_custom_processor(customize_processing: str) -> Any: return {k: getattr(m, k) for k in dir(m)} if customize_processing == '::linenum::': return {'mark': linenum_marks, 'handle_result': linenum_handle_result} - from kitty.constants import resolve_custom_file custom_path = resolve_custom_file(customize_processing) import runpy return runpy.run_path(custom_path, run_name='__main__') diff --git a/kittens/runner.py b/kittens/runner.py index 27d0b6fc8..2cf1a0492 100644 --- a/kittens/runner.py +++ b/kittens/runner.py @@ -10,6 +10,7 @@ from functools import partial from typing import TYPE_CHECKING, Any, Dict, FrozenSet, Generator, List, cast from kitty.types import run_once +from kitty.utils import resolve_abs_or_config_path aliases = {'url_hints': 'hints'} @@ -27,11 +28,8 @@ def resolved_kitten(k: str) -> str: def path_to_custom_kitten(config_dir: str, kitten: str) -> str: - path = os.path.expanduser(kitten) - if not os.path.isabs(path): - path = os.path.join(config_dir, path) - path = os.path.abspath(path) - return path + path = resolve_abs_or_config_path(kitten, None, config_dir) + return os.path.abspath(path) @contextmanager diff --git a/kitty/constants.py b/kitty/constants.py index 98362561c..cbd0d5963 100644 --- a/kitty/constants.py +++ b/kitty/constants.py @@ -173,13 +173,6 @@ def running_in_kitty(set_val: Optional[bool] = None) -> bool: return bool(getattr(running_in_kitty, 'ans', False)) -def resolve_custom_file(path: str) -> str: - path = os.path.expandvars(os.path.expanduser(path)) - if not os.path.isabs(path): - path = os.path.join(config_dir, path) - return path - - def list_kitty_resources(package: str = 'kitty') -> Iterable[str]: from importlib.resources import contents return contents(package) diff --git a/kitty/launch.py b/kitty/launch.py index 85fe9627c..38c3038f6 100644 --- a/kitty/launch.py +++ b/kitty/launch.py @@ -8,12 +8,11 @@ from .boss import Boss 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 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 log_error, set_primary_selection, which +from .utils import log_error, resolve_custom_file, set_primary_selection, which from .window import Watchers, Window try: diff --git a/kitty/marks.py b/kitty/marks.py index e7e53eaee..13daa7c2f 100644 --- a/kitty/marks.py +++ b/kitty/marks.py @@ -1,12 +1,11 @@ #!/usr/bin/env python # License: GPLv3 Copyright: 2020, Kovid Goyal -import os import re from ctypes import POINTER, c_uint, c_void_p, cast from typing import Callable, Generator, Iterable, Pattern, Tuple, Union, Sequence -from .constants import config_dir +from .utils import resolve_custom_file pointer_to_uint = POINTER(c_uint) @@ -87,8 +86,6 @@ def marker_from_spec(ftype: str, spec: Union[str, Sequence[Tuple[int, str]]], fl if ftype == 'function': import runpy assert isinstance(spec, str) - path = spec - if not os.path.isabs(path): - path = os.path.join(config_dir, path) + path = resolve_custom_file(spec) return marker_from_function(runpy.run_path(path, run_name='__marker__')["marker"]) raise ValueError(f'Unknown marker type: {ftype}') diff --git a/kitty/options/utils.py b/kitty/options/utils.py index bf3a6dc44..f665f443c 100644 --- a/kitty/options/utils.py +++ b/kitty/options/utils.py @@ -2,7 +2,6 @@ # License: GPLv3 Copyright: 2021, Kovid Goyal -import os import re import sys from functools import lru_cache @@ -17,7 +16,7 @@ from kitty.conf.utils import ( positive_float, positive_int, python_string, to_bool, to_cmdline, to_color, uniq, unit_float ) -from kitty.constants import config_dir, is_macos +from kitty.constants import is_macos from kitty.fast_data_types import ( CURSOR_BEAM, CURSOR_BLOCK, CURSOR_UNDERLINE, Color ) @@ -28,7 +27,7 @@ from kitty.key_names import ( ) from kitty.rgb import color_as_int from kitty.types import FloatEdges, MouseEvent, SingleKey -from kitty.utils import expandvars, log_error +from kitty.utils import expandvars, log_error, resolve_abs_or_config_path KeyMap = Dict[SingleKey, str] MouseMap = Dict[MouseEvent, str] @@ -660,13 +659,9 @@ def active_tab_title_template(x: str) -> Optional[str]: def config_or_absolute_path(x: str, env: Optional[Dict[str, str]] = None) -> Optional[str]: - if x.lower() == 'none': + if not x or x.lower() == 'none': return None - x = os.path.expanduser(x) - x = expandvars(x, env or {}) - if not os.path.isabs(x): - x = os.path.join(config_dir, x) - return x + return resolve_abs_or_config_path(x, env) def allow_remote_control(x: str) -> str: diff --git a/kitty/utils.py b/kitty/utils.py index ab108e1e1..f6b1619da 100644 --- a/kitty/utils.py +++ b/kitty/utils.py @@ -18,7 +18,7 @@ from typing import ( ) from .constants import ( - appname, is_macos, is_wayland, read_kitty_resource, shell_path, + appname, config_dir, is_macos, is_wayland, read_kitty_resource, shell_path, supports_primary_selection ) from .rgb import to_color @@ -582,6 +582,22 @@ def is_path_in_temp_dir(path: str) -> bool: return False +def resolve_abs_or_config_path(path: str, env: Optional[Mapping[str, str]] = None, conf_dir: Optional[str] = None) -> str: + path = os.path.expanduser(path) + path = expandvars(path, env or {}) + if not os.path.isabs(path): + path = os.path.join(conf_dir or config_dir, path) + return path + + +def resolve_custom_file(path: str) -> str: + from .fast_data_types import get_options + opts: Optional[Options] = None + with suppress(RuntimeError): + opts = get_options() + return resolve_abs_or_config_path(path, opts.env if opts else {}) + + def func_name(f: Any) -> str: if hasattr(f, '__name__'): return str(f.__name__) diff --git a/kitty/window.py b/kitty/window.py index 17fc05c90..769fd2475 100644 --- a/kitty/window.py +++ b/kitty/window.py @@ -43,7 +43,7 @@ from .types import MouseEvent, WindowGeometry, ac from .typing import BossType, ChildType, EdgeLiteral, TabType, TypedDict from .utils import ( get_primary_selection, load_shaders, log_error, open_cmd, open_url, - parse_color_set, sanitize_title, set_primary_selection + parse_color_set, resolve_custom_file, sanitize_title, set_primary_selection ) MatchPatternType = Union[Pattern[str], Tuple[Pattern[str], Optional[Pattern[str]]]] @@ -1069,8 +1069,7 @@ class Window: } def set_logo(self, path: str, position: str = '', alpha: float = -1) -> None: - from .options.utils import config_or_absolute_path - path = (config_or_absolute_path(path, get_options().env) or path) if path else '' + path = resolve_custom_file(path) if path else '' set_window_logo(self.os_window_id, self.tab_id, self.id, path, position or '', alpha) # actions {{{