Dont maintain ref_map manually
This commit is contained in:
parent
6f6e23bf61
commit
5deed81737
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,6 +3,7 @@
|
|||||||
*.pyo
|
*.pyo
|
||||||
*_stub.pyi
|
*_stub.pyi
|
||||||
*_generated.go
|
*_generated.go
|
||||||
|
*_generated.h
|
||||||
/.dmypy.json
|
/.dmypy.json
|
||||||
/tags
|
/tags
|
||||||
/build/
|
/build/
|
||||||
|
|||||||
35
docs/extract-rst-targets.py
Executable file
35
docs/extract-rst-targets.py
Executable file
@ -0,0 +1,35 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# License: GPLv3 Copyright: 2022, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
from typing import Dict, Iterator
|
||||||
|
|
||||||
|
tgt_pat = re.compile(r'^.. _(\S+?):$', re.MULTILINE)
|
||||||
|
|
||||||
|
|
||||||
|
def find_explicit_targets(text: str) -> Iterator[str]:
|
||||||
|
for m in tgt_pat.finditer(text):
|
||||||
|
yield m.group(1)
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> Dict[str, str]:
|
||||||
|
refs = {'github_discussions': 'https://github.com/kovidgoyal/kitty/discussions'}
|
||||||
|
base = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
for dirpath, dirnames, filenames in os.walk(base):
|
||||||
|
if 'generated' in dirnames:
|
||||||
|
dirnames.remove('generated')
|
||||||
|
for f in filenames:
|
||||||
|
if f.endswith('.rst'):
|
||||||
|
with open(os.path.join(dirpath, f)) as stream:
|
||||||
|
raw = stream.read()
|
||||||
|
href = os.path.relpath(stream.name, base).replace(os.sep, '/')
|
||||||
|
href = href.rpartition('.')[0] + '/'
|
||||||
|
for explicit_target in find_explicit_targets(raw):
|
||||||
|
refs[explicit_target] = href + f'#{explicit_target}'
|
||||||
|
return {'ref': refs}
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import json
|
||||||
|
print(json.dumps(main(), indent=2))
|
||||||
19
kitty/cli.py
19
kitty/cli.py
@ -11,7 +11,7 @@ from typing import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
from .cli_stub import CLIOptions
|
from .cli_stub import CLIOptions
|
||||||
from .conf.types import ref_map
|
from .conf.types import resolve_ref
|
||||||
from .conf.utils import resolve_config
|
from .conf.utils import resolve_config
|
||||||
from .constants import (
|
from .constants import (
|
||||||
appname, clear_handled_signals, defconf, is_macos, str_version, website_url
|
appname, clear_handled_signals, defconf, is_macos, str_version, website_url
|
||||||
@ -131,9 +131,15 @@ def code(x: str) -> str:
|
|||||||
return cyan(x)
|
return cyan(x)
|
||||||
|
|
||||||
|
|
||||||
|
def text_and_target(x: str) -> Tuple[str, str]:
|
||||||
|
parts = x.split('<')
|
||||||
|
return parts[0].strip(), parts[-1].rstrip('>')
|
||||||
|
|
||||||
|
|
||||||
@role
|
@role
|
||||||
def term(x: str) -> str:
|
def term(x: str) -> str:
|
||||||
return italic(x.split('<', 1)[0])
|
t, q = text_and_target(x)
|
||||||
|
return italic(t)
|
||||||
|
|
||||||
|
|
||||||
@role
|
@role
|
||||||
@ -165,11 +171,10 @@ def doc(x: str) -> str:
|
|||||||
|
|
||||||
@role
|
@role
|
||||||
def ref(x: str) -> str:
|
def ref(x: str) -> str:
|
||||||
parts = x.split('<')
|
t, q = text_and_target(x)
|
||||||
t = parts[0].strip()
|
url = resolve_ref(q)
|
||||||
q = parts[-1].rstrip('>')
|
if url:
|
||||||
if q in ref_map():
|
return hyperlink_for_url(url, t)
|
||||||
return hyperlink_for_url(ref_map()[q], t)
|
|
||||||
return t
|
return t
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -45,24 +45,29 @@ def expand_opt_references(conf_name: str, text: str) -> str:
|
|||||||
|
|
||||||
|
|
||||||
@run_once
|
@run_once
|
||||||
def ref_map() -> Dict[str, str]:
|
def ref_map() -> Dict[str, Dict[str, str]]:
|
||||||
from kitty.actions import get_all_actions
|
import json
|
||||||
ref_map = {
|
from ..fast_data_types import get_docs_ref_map
|
||||||
'layouts': f'{website_url("overview")}#layouts',
|
ans: Dict[str, Dict[str, str]] = json.loads(get_docs_ref_map())
|
||||||
'include': f'{website_url("conf")}#include',
|
return ans
|
||||||
'watchers': f'{website_url("launch")}#watchers',
|
|
||||||
'sessions': f'{website_url("overview")}#startup-sessions',
|
|
||||||
'functional': f'{website_url("keyboard-protocol")}#functional-key-definitions',
|
def resolve_ref(ref: str) -> str:
|
||||||
'ssh_copy_command': f'{website_url("kittens/ssh")}#ssh-copy-command',
|
m = ref_map()
|
||||||
'shell_integration': website_url("shell-integration"),
|
href = m['ref'].get(ref, '')
|
||||||
'rc_custom_auth': f'{website_url("remote-control")}#rc-custom-auth',
|
if href:
|
||||||
'clone_shell': f'{website_url("shell-integration")}#clone-shell',
|
return href
|
||||||
'github_discussions': 'https://github.com/kovidgoyal/kitty/discussions',
|
if ref.startswith('conf-'):
|
||||||
}
|
base = 'generated/' + ref.rpartition('-')[0]
|
||||||
for actions in get_all_actions().values():
|
href = f'{website_url(base)}#{ref}'
|
||||||
for ac in actions:
|
elif ref.startswith('at_'):
|
||||||
ref_map[f'action-{ac.name}'] = f'{website_url("actions")}#' + ac.name.replace('_', '-')
|
href = f'{website_url("generated/cli-kitty-at")}#{ref}'
|
||||||
return ref_map
|
elif ref.startswith('action-group-'):
|
||||||
|
href = f'{website_url("generated/actions")}#{ref}'
|
||||||
|
elif ref.startswith('action-'):
|
||||||
|
frag = ref.partition('-')[-1]
|
||||||
|
href = f'{website_url("generated/actions")}#{frag}'
|
||||||
|
return href
|
||||||
|
|
||||||
|
|
||||||
def remove_markup(text: str) -> str:
|
def remove_markup(text: str) -> str:
|
||||||
@ -76,7 +81,10 @@ def remove_markup(text: str) -> str:
|
|||||||
def sub(m: 'Match[str]') -> str:
|
def sub(m: 'Match[str]') -> str:
|
||||||
if m.group(1) == 'ref':
|
if m.group(1) == 'ref':
|
||||||
t, q = extract(m)
|
t, q = extract(m)
|
||||||
return f'{t} <{ref_map()[q]}>'
|
url = resolve_ref(q)
|
||||||
|
if not url:
|
||||||
|
raise KeyError(f'Failed to resolve :ref: {q}')
|
||||||
|
return f'{t} <{url}>'
|
||||||
if m.group(1) == 'doc':
|
if m.group(1) == 'doc':
|
||||||
t, q = extract(m)
|
t, q = extract(m)
|
||||||
return f'{t} <{website_url(q.lstrip("/"))}>'
|
return f'{t} <{website_url(q.lstrip("/"))}>'
|
||||||
@ -91,7 +99,7 @@ def remove_markup(text: str) -> str:
|
|||||||
return t
|
return t
|
||||||
if m.group(1) == 'disc':
|
if m.group(1) == 'disc':
|
||||||
t, q = extract(m)
|
t, q = extract(m)
|
||||||
return f'{t} {ref_map()["github_discussions"]}/{q}'
|
return f'{t} {resolve_ref("github_discussions")}/{q}'
|
||||||
return str(m.group(2))
|
return str(m.group(2))
|
||||||
|
|
||||||
return re.sub(r':([a-zA-Z0-9]+):`(.+?)`', sub, text, flags=re.DOTALL)
|
return re.sub(r':([a-zA-Z0-9]+):`(.+?)`', sub, text, flags=re.DOTALL)
|
||||||
|
|||||||
@ -209,10 +209,16 @@ py_getpeereid(PyObject *self UNUSED, PyObject *args) {
|
|||||||
return Py_BuildValue("ii", u, g);
|
return Py_BuildValue("ii", u, g);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "docs_ref_map_generated.h"
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
get_docs_ref_map(PyObject *self UNUSED, PyObject *args UNUSED) {
|
||||||
|
return PyBytes_FromStringAndSize(docs_ref_map, sizeof(docs_ref_map));
|
||||||
|
}
|
||||||
|
|
||||||
static PyMethodDef module_methods[] = {
|
static PyMethodDef module_methods[] = {
|
||||||
{"wcwidth", (PyCFunction)wcwidth_wrap, METH_O, ""},
|
{"wcwidth", (PyCFunction)wcwidth_wrap, METH_O, ""},
|
||||||
|
{"get_docs_ref_map", (PyCFunction)get_docs_ref_map, METH_NOARGS, ""},
|
||||||
{"getpeereid", (PyCFunction)py_getpeereid, METH_VARARGS, ""},
|
{"getpeereid", (PyCFunction)py_getpeereid, METH_VARARGS, ""},
|
||||||
{"wcswidth", (PyCFunction)wcswidth_std, METH_O, ""},
|
{"wcswidth", (PyCFunction)wcswidth_std, METH_O, ""},
|
||||||
{"open_tty", open_tty, METH_VARARGS, ""},
|
{"open_tty", open_tty, METH_VARARGS, ""},
|
||||||
|
|||||||
@ -1486,3 +1486,4 @@ class SingleKey:
|
|||||||
|
|
||||||
|
|
||||||
def set_use_os_log(yes: bool) -> None: ...
|
def set_use_os_log(yes: bool) -> None: ...
|
||||||
|
def get_docs_ref_map() -> bytes: ...
|
||||||
|
|||||||
18
setup.py
18
setup.py
@ -14,6 +14,7 @@ import subprocess
|
|||||||
import sys
|
import sys
|
||||||
import sysconfig
|
import sysconfig
|
||||||
import tempfile
|
import tempfile
|
||||||
|
import textwrap
|
||||||
import time
|
import time
|
||||||
from contextlib import suppress
|
from contextlib import suppress
|
||||||
from functools import lru_cache, partial
|
from functools import lru_cache, partial
|
||||||
@ -839,10 +840,25 @@ def init_env_from_args(args: Options, native_optimizations: bool = False) -> Non
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def build_ref_map() -> str:
|
||||||
|
m = runpy.run_path('docs/extract-rst-targets.py')
|
||||||
|
d = m['main']()
|
||||||
|
h = 'static const char docs_ref_map[] = {\n' + textwrap.fill(', '.join(map(str, bytearray(json.dumps(d).encode('utf-8'))))) + '\n};'
|
||||||
|
dest = 'kitty/docs_ref_map_generated.h'
|
||||||
|
q = ''
|
||||||
|
with suppress(FileNotFoundError), open(dest) as f:
|
||||||
|
q = f.read()
|
||||||
|
if q != h:
|
||||||
|
with open(dest, 'w') as f:
|
||||||
|
f.write(h)
|
||||||
|
return dest
|
||||||
|
|
||||||
|
|
||||||
def build(args: Options, native_optimizations: bool = True, call_init: bool = True) -> None:
|
def build(args: Options, native_optimizations: bool = True, call_init: bool = True) -> None:
|
||||||
if call_init:
|
if call_init:
|
||||||
init_env_from_args(args, native_optimizations)
|
init_env_from_args(args, native_optimizations)
|
||||||
sources, headers = find_c_files()
|
sources, headers = find_c_files()
|
||||||
|
headers.append(build_ref_map())
|
||||||
compile_c_extension(
|
compile_c_extension(
|
||||||
kitty_env(), 'kitty/fast_data_types', args.compilation_database, sources, headers
|
kitty_env(), 'kitty/fast_data_types', args.compilation_database, sources, headers
|
||||||
)
|
)
|
||||||
@ -1375,7 +1391,7 @@ def clean() -> None:
|
|||||||
safe_remove(
|
safe_remove(
|
||||||
'build', 'compile_commands.json', 'link_commands.json',
|
'build', 'compile_commands.json', 'link_commands.json',
|
||||||
'linux-package', 'kitty.app', 'asan-launcher',
|
'linux-package', 'kitty.app', 'asan-launcher',
|
||||||
'kitty-profile')
|
'kitty-profile', 'docs/generated')
|
||||||
clean_launcher_dir('kitty/launcher')
|
clean_launcher_dir('kitty/launcher')
|
||||||
|
|
||||||
def excluded(root: str, d: str) -> bool:
|
def excluded(root: str, d: str) -> bool:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user