Cache parsed save as session options spec

This commit is contained in:
Kovid Goyal 2025-08-16 09:46:03 +05:30
parent ca715c4cae
commit 0fb1835af1
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
3 changed files with 36 additions and 17 deletions

View file

@ -601,6 +601,17 @@ def apply_preparsed_cli_flags(preparsed_from_c: PreparsedCLIFlags, ans: Any, cre
return preparsed_from_c[1]
def parse_cmdline_inner(
args: list[str], oc: Options, disabled: OptionSpecSeq, names_map: dict[str, OptionDict], values_map: dict[str, OptionDict], ans: Any
) -> list[str]:
preparsed = parse_cli_from_spec(args, names_map, values_map)
leftover_args = apply_preparsed_cli_flags(preparsed, ans, lambda: oc)
for opt in disabled:
if not isinstance(opt, str):
setattr(ans, opt['dest'], defval_for_opt(opt))
return leftover_args
def parse_cmdline(oc: Options, disabled: OptionSpecSeq, ans: Any, args: list[str] | None = None) -> list[str]:
names_map = oc.names_map.copy()
values_map = oc.values_map.copy()
@ -611,18 +622,24 @@ def parse_cmdline(oc: Options, disabled: OptionSpecSeq, ans: Any, args: list[str
names_map['version'] = {'type': 'bool-set', 'aliases': ('--version', '-v')} # type: ignore
values_map['version'] = False
try:
preparsed = parse_cli_from_spec(sys.argv[1:] if args is None else args, names_map, values_map)
return parse_cmdline_inner(sys.argv[1:] if args is None else args, oc, disabled, names_map, values_map, ans)
except Exception as e:
raise SystemExit(str(e))
leftover_args = apply_preparsed_cli_flags(preparsed, ans, lambda: oc)
for opt in disabled:
if not isinstance(opt, str):
setattr(ans, opt['dest'], defval_for_opt(opt))
spec_cache: dict[str, tuple[Options, OptionSpecSeq]] = {}
def cached_parse_cmdline(spec: str, args: list[str], ans: Any) -> list[str]:
if (x := spec_cache.get(spec)) is None:
seq, disabled = parse_option_spec(spec)
oc = Options(seq, '', '', '')
x = spec_cache[spec] = oc, disabled
oc, disabled = x
leftover_args = parse_cmdline_inner(args, oc, disabled, oc.names_map, oc.values_map, ans)
return leftover_args
def options_for_completion() -> OptionSpecSeq:
raw = '--help -h\ntype=bool-set\nShow help for {appname} command line options\n\n{raw}'.format(
appname=appname, raw=kitty_options_spec())

View file

@ -467,17 +467,19 @@ def save_as_session_part2(boss: BossType, opts: SaveAsSessionOptions, path: str)
boss.edit_file(path)
def parse_save_as_options_spec_args(args: list[str]) -> tuple[SaveAsSessionOptions, list[str]]:
from kitty.cli import cached_parse_cmdline
ans = SaveAsSessionOptions()
leftover_args = cached_parse_cmdline(save_as_session_options(), args, ans)
return ans, leftover_args
def default_save_as_session_opts() -> SaveAsSessionOptions:
from kitty.cli import parse_args
return parse_args(
[], save_as_session_options, result_class=SaveAsSessionOptions)[0]
return parse_save_as_options_spec_args([])[0]
def save_as_session(boss: BossType, cmdline: Sequence[str]) -> None:
from kitty.cli import parse_args
opts: SaveAsSessionOptions
opts, args = parse_args(
list(cmdline), save_as_session_options, result_class=SaveAsSessionOptions)
opts, args = parse_save_as_options_spec_args(list(cmdline))
path = args[0] if args else ''
if path:
save_as_session_part2(boss, opts, path)

View file

@ -8,7 +8,7 @@ import re
import sys
from dataclasses import dataclass
from enum import Enum, auto
from typing import Any, Iterator, TypedDict
from typing import Any, Iterator, Sequence, TypedDict
try:
from kitty.constants import appname, is_macos
@ -118,7 +118,7 @@ class OptionDict(TypedDict):
completion: CompletionSpec
OptionSpecSeq = list[str | OptionDict]
OptionSpecSeq = Sequence[str | OptionDict]
def parse_option_spec(spec: str | None = None) -> tuple[OptionSpecSeq, OptionSpecSeq]:
@ -129,8 +129,8 @@ def parse_option_spec(spec: str | None = None) -> tuple[OptionSpecSeq, OptionSpe
lines = spec.splitlines()
prev_line = ''
prev_indent = 0
seq: OptionSpecSeq = []
disabled: OptionSpecSeq = []
seq: list[str | OptionDict] = []
disabled: list[str | OptionDict] = []
mpat = re.compile('([a-z]+)=(.+)')
current_cmd: OptionDict = {
'dest': '', 'aliases': (), 'help': '', 'choices': (),