diff --git a/kitty/cli.py b/kitty/cli.py index d645af813..71f1388d1 100644 --- a/kitty/cli.py +++ b/kitty/cli.py @@ -3,7 +3,6 @@ import os import re -import shlex import sys from collections import deque from dataclasses import dataclass @@ -17,6 +16,7 @@ from .fast_data_types import wcswidth from .options.types import Options as KittyOpts from .types import run_once from .typing import BadLineType, TypedDict +from .utils import shlex_split class CompletionType(Enum): @@ -45,7 +45,7 @@ class CompletionSpec: @staticmethod def from_string(raw: str) -> 'CompletionSpec': self = CompletionSpec() - for x in shlex.split(raw): + for x in shlex_split(raw): ck, vv = x.split(':', 1) if ck == 'type': self.type = getattr(CompletionType, vv) diff --git a/kitty/conf/utils.py b/kitty/conf/utils.py index ff36fcb73..da70eb6fe 100644 --- a/kitty/conf/utils.py +++ b/kitty/conf/utils.py @@ -3,7 +3,6 @@ import os import re -import shlex import sys from contextlib import contextmanager from typing import ( @@ -29,7 +28,7 @@ from ..fast_data_types import Color from ..rgb import to_color as as_color from ..types import ConvertibleToNumbers, ParsedShortcut, run_once from ..typing import Protocol -from ..utils import expandvars, log_error +from ..utils import expandvars, log_error, shlex_split key_pat = re.compile(r'([a-zA-Z][a-zA-Z0-9_-]*)\s+(.+)$') ItemParser = Callable[[str, str, Dict[str, Any]], bool] @@ -94,7 +93,6 @@ class ToCmdline: return self def __call__(self, x: str, expand: bool = True) -> List[str]: - ans = shlex.split(x) if expand: ans = list( map( @@ -103,9 +101,11 @@ class ToCmdline: os.environ if self.override_env is None else self.override_env, fallback_to_os_env=False ), - ans + shlex_split(x) ) ) + else: + ans = list(shlex_split(x)) return ans diff --git a/kitty/main.py b/kitty/main.py index c844b93ac..f9c6a7767 100644 --- a/kitty/main.py +++ b/kitty/main.py @@ -59,6 +59,7 @@ from .utils import ( log_error, parse_os_window_state, safe_mtime, + shlex_split, single_instance, startup_notification_handler, unix_socket_paths, @@ -358,9 +359,8 @@ def macos_cmdline(argv_args: List[str]) -> List[str]: raw = f.read() except FileNotFoundError: return argv_args - import shlex raw = raw.strip() - ans = shlex.split(raw) + ans = list(shlex_split(raw)) if ans and ans[0] == 'kitty': del ans[0] return ans diff --git a/kitty/options/utils.py b/kitty/options/utils.py index d87131625..0463cf34f 100644 --- a/kitty/options/utils.py +++ b/kitty/options/utils.py @@ -31,7 +31,7 @@ from kitty.fonts import FontFeature, FontModification, ModificationType, Modific from kitty.key_names import character_key_name_aliases, functional_key_name_aliases, get_key_name_lookup from kitty.rgb import color_as_int from kitty.types import FloatEdges, MouseEvent -from kitty.utils import expandvars, log_error, resolve_abs_or_config_path +from kitty.utils import expandvars, log_error, resolve_abs_or_config_path, shlex_split KeyMap = Dict[SingleKey, List['KeyDefinition']] MouseMap = Dict[MouseEvent, str] @@ -262,8 +262,7 @@ def move_window(func: str, rest: str) -> FuncArgsType: @func_with_args('pipe') def pipe(func: str, rest: str) -> FuncArgsType: - import shlex - r = shlex.split(rest) + r = list(shlex_split(rest)) if len(r) < 3: log_error('Too few arguments to pipe function') r = ['none', 'none', 'true'] @@ -272,8 +271,7 @@ def pipe(func: str, rest: str) -> FuncArgsType: @func_with_args('set_colors') def set_colors(func: str, rest: str) -> FuncArgsType: - import shlex - r = shlex.split(rest) + r = list(shlex_split(rest)) if len(r) < 1: log_error('Too few arguments to set_colors function') return func, r @@ -366,12 +364,11 @@ def parse_marker_spec(ftype: str, parts: Sequence[str]) -> Tuple[str, Union[str, @func_with_args('toggle_marker') def toggle_marker(func: str, rest: str) -> FuncArgsType: - import shlex parts = rest.split(maxsplit=1) if len(parts) != 2: raise ValueError(f'{rest} is not a valid marker specification') ftype, spec = parts - parts = shlex.split(spec) + parts = list(shlex_split(spec)) return func, list(parse_marker_spec(ftype, parts)) @@ -411,8 +408,7 @@ def mouse_selection(func: str, rest: str) -> FuncArgsType: @func_with_args('load_config_file') def load_config_file(func: str, rest: str) -> FuncArgsType: - import shlex - return func, shlex.split(rest) + return func, list(shlex_split(rest)) # }}} diff --git a/kitty/session.py b/kitty/session.py index 0ef440ef8..9123c4f4c 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, which +from .utils import cmdline_for_hold, expandvars, log_error, resolve_custom_file, resolved_shell, shlex_split, which if TYPE_CHECKING: from .launch import LaunchSpec @@ -83,7 +83,7 @@ class Session: needs_expandvars = False if isinstance(cmd, str): needs_expandvars = True - cmd = shlex.split(cmd) + cmd = list(shlex_split(cmd)) spec = parse_launch_args(cmd) if needs_expandvars: assert isinstance(cmd, list) diff --git a/kitty/tabs.py b/kitty/tabs.py index 42d5fdb32..666d0dc11 100644 --- a/kitty/tabs.py +++ b/kitty/tabs.py @@ -58,7 +58,7 @@ from .layout.interface import create_layout_object_for, evict_cached_layouts from .tab_bar import TabBar, TabBarData from .types import ac from .typing import EdgeLiteral, SessionTab, SessionType, TypedDict -from .utils import cmdline_for_hold, log_error, platform_window_id, resolved_shell +from .utils import cmdline_for_hold, log_error, platform_window_id, resolved_shell, shlex_split from .window import CwdRequest, Watchers, Window, WindowDict from .window_list import WindowList @@ -472,14 +472,11 @@ class Tab: # {{{ cwd = old_exe cmd = resolved_shell(get_options()) elif not is_executable: - import shlex - - from .utils import which with suppress(OSError): with open(old_exe) as f: if f.read(2) == '#!': line = f.read(4096).splitlines()[0] - cmd[:0] = shlex.split(line) + cmd[:0] = shlex_split(line) else: cmd[:0] = [resolved_shell(get_options())[0]] cmd[0] = which(cmd[0]) or cmd[0] diff --git a/kitty/utils.py b/kitty/utils.py index ae88599bc..2f5b6cb5f 100644 --- a/kitty/utils.py +++ b/kitty/utils.py @@ -629,7 +629,7 @@ def get_hostname(fallback: str = '') -> str: def resolve_editor_cmd(editor: str, shell_env: Mapping[str, str]) -> Optional[str]: import shlex - editor_cmd = shlex.split(editor) + editor_cmd = list(shlex_split(editor)) editor_exe = (editor_cmd or ('',))[0] if editor_exe and os.path.isabs(editor_exe): return editor @@ -663,19 +663,17 @@ def get_editor_from_env(env: Mapping[str, str]) -> Optional[str]: def get_editor_from_env_vars(opts: Optional[Options] = None) -> List[str]: - import shlex - editor = get_editor_from_env(os.environ) if not editor: shell_env = read_shell_environment(opts) editor = get_editor_from_env(shell_env) for ans in (editor, 'vim', 'nvim', 'vi', 'emacs', 'hx', 'kak', 'micro', 'nano', 'vis'): - if ans and which(shlex.split(ans)[0], only_system=True): + if ans and which(next(shlex_split(ans)), only_system=True): break else: ans = 'vim' - return shlex.split(ans) + return list(shlex_split(ans)) def get_editor(opts: Optional[Options] = None, path_to_edit: str = '', line_number: int = 0) -> List[str]: @@ -689,8 +687,7 @@ def get_editor(opts: Optional[Options] = None, path_to_edit: str = '', line_numb if opts.editor == '.': ans = get_editor_from_env_vars() else: - import shlex - ans = shlex.split(opts.editor) + ans = list(shlex_split(opts.editor)) ans[0] = os.path.expanduser(ans[0]) if path_to_edit: if line_number: @@ -770,7 +767,6 @@ def resolved_shell(opts: Optional[Options] = None) -> List[str]: if q == '.': ans = [shell_path] else: - import shlex env = {} if opts is not None: env['TERM'] = opts.term @@ -783,7 +779,7 @@ def resolved_shell(opts: Optional[Options] = None) -> List[str]: env['USER'] = pwd.getpwuid(os.geteuid()).pw_name def expand(x: str) -> str: return expandvars(x, env) - ans = list(map(expand, shlex.split(q))) + ans = list(map(expand, shlex_split(q))) return ans