Command line tools shouldnt need to resolve documentation refs
Instead use a new kitty+doc protocol and have kitty navigate to the docs. Uses a default open action for the protocol, which can be overriden by the user should they so desire.
This commit is contained in:
parent
0b66f20934
commit
314dd97059
@ -64,6 +64,10 @@ some special variables, documented below:
|
||||
``FRAGMENT``
|
||||
The fragment (unquoted), if any of the URL or the empty string.
|
||||
|
||||
``URL_PATH``
|
||||
The path, query and fragment portions of the URL, without any
|
||||
unquoting.
|
||||
|
||||
|
||||
.. note::
|
||||
You can use the :opt:`action_alias` option just as in :file:`kitty.conf` to
|
||||
|
||||
26
kitty/cli.py
26
kitty/cli.py
@ -11,12 +11,12 @@ from typing import (
|
||||
)
|
||||
|
||||
from .cli_stub import CLIOptions
|
||||
from .conf.types import resolve_ref
|
||||
from .conf.utils import resolve_config
|
||||
from .constants import (
|
||||
appname, clear_handled_signals, defconf, is_macos, str_version, website_url
|
||||
)
|
||||
from .options.types import Options as KittyOpts
|
||||
from .types import run_once
|
||||
from .typing import BadLineType, TypedDict
|
||||
|
||||
|
||||
@ -171,22 +171,26 @@ def doc(x: str) -> str:
|
||||
return website_url(x)
|
||||
|
||||
|
||||
@run_once
|
||||
def hostname() -> str:
|
||||
import socket
|
||||
return socket.gethostname() or 'localhost'
|
||||
|
||||
|
||||
def ref_hyperlink(x: str, prefix: str = '') -> str:
|
||||
t, q = text_and_target(x)
|
||||
url = f'kitty+doc://{hostname()}/#ref={prefix}{q}'
|
||||
return hyperlink_for_url(url, t)
|
||||
|
||||
|
||||
@role
|
||||
def ref(x: str) -> str:
|
||||
t, q = text_and_target(x)
|
||||
url = resolve_ref(q)
|
||||
if url:
|
||||
return hyperlink_for_url(url, t)
|
||||
return t
|
||||
return ref_hyperlink(x)
|
||||
|
||||
|
||||
@role
|
||||
def ac(x: str) -> str:
|
||||
t, q = text_and_target(x)
|
||||
url = resolve_ref(q)
|
||||
if url:
|
||||
return hyperlink_for_url(url, t)
|
||||
return t
|
||||
return ref_hyperlink(x, 'action-')
|
||||
|
||||
|
||||
OptionSpecSeq = List[Union[str, OptionDict]]
|
||||
|
||||
@ -75,7 +75,7 @@ def parse(lines: Iterable[str]) -> Iterator[OpenAction]:
|
||||
entries.append((tuple(match_criteria), tuple(raw_actions)))
|
||||
|
||||
with to_cmdline_implementation.filter_env_vars(
|
||||
'URL', 'FILE_PATH', 'FILE', 'FRAGMENT',
|
||||
'URL', 'FILE_PATH', 'FILE', 'FRAGMENT', 'URL_PATH',
|
||||
EDITOR=shlex.join(get_editor()),
|
||||
SHELL=shlex.join(resolved_shell(get_options()))
|
||||
):
|
||||
@ -97,7 +97,7 @@ def url_matches_criterion(purl: 'ParseResult', url: str, unquoted_path: str, mc:
|
||||
|
||||
if mc.type == 'mime':
|
||||
import fnmatch
|
||||
mt = guess_type(unquoted_path, allow_filesystem_access=True)
|
||||
mt = guess_type(unquoted_path, allow_filesystem_access=purl.scheme in ('', 'file'))
|
||||
if not mt:
|
||||
return False
|
||||
mt = mt.lower()
|
||||
@ -169,10 +169,16 @@ def actions_for_url_from_list(url: str, actions: Iterable[OpenAction]) -> Iterat
|
||||
except Exception:
|
||||
return
|
||||
path = unquote(purl.path)
|
||||
up = purl.path
|
||||
if purl.query:
|
||||
up += f'?{purl.query}'
|
||||
if purl.fragment:
|
||||
up += f'#{purl.fragment}'
|
||||
|
||||
env = {
|
||||
'URL': url,
|
||||
'FILE_PATH': path,
|
||||
'URL_PATH': up,
|
||||
'FILE': posixpath.basename(path),
|
||||
'FRAGMENT': unquote(purl.fragment)
|
||||
}
|
||||
@ -215,6 +221,15 @@ def load_launch_actions() -> Tuple[OpenAction, ...]:
|
||||
return tuple(parse(f))
|
||||
|
||||
|
||||
@run_once
|
||||
def default_open_actions() -> Tuple[OpenAction, ...]:
|
||||
return tuple(parse('''\
|
||||
# Open kitty HTML docs links
|
||||
protocol kitty+doc
|
||||
action show_kitty_doc $URL_PATH
|
||||
'''.splitlines()))
|
||||
|
||||
|
||||
@run_once
|
||||
def default_launch_actions() -> Tuple[OpenAction, ...]:
|
||||
SHELL = resolved_shell(get_options())
|
||||
@ -260,7 +275,12 @@ def actions_for_url(url: str, actions_spec: Optional[str] = None) -> Iterator[Ke
|
||||
actions = load_open_actions()
|
||||
else:
|
||||
actions = tuple(parse(actions_spec.splitlines()))
|
||||
yield from actions_for_url_from_list(url, actions)
|
||||
found = False
|
||||
for action in actions_for_url_from_list(url, actions):
|
||||
found = True
|
||||
yield action
|
||||
if not found:
|
||||
yield from actions_for_url_from_list(url, default_open_actions())
|
||||
|
||||
|
||||
def actions_for_launch(url: str) -> Iterator[KeyAction]:
|
||||
|
||||
@ -1074,8 +1074,15 @@ def safer_fork() -> int:
|
||||
def docs_url(which: str = '', local_docs_root: str = '') -> str:
|
||||
from urllib.parse import quote
|
||||
from .constants import local_docs, website_url
|
||||
from .conf.types import resolve_ref
|
||||
ld = local_docs_root or local_docs()
|
||||
base, frag = which.partition('#')[::2]
|
||||
base = base.strip('/')
|
||||
if frag.startswith('ref='):
|
||||
ref = frag[4:]
|
||||
which = resolve_ref(ref, lambda x: x)
|
||||
base, frag = which.partition('#')[::2]
|
||||
base = base.strip('/')
|
||||
if ld:
|
||||
base = base or 'index'
|
||||
url = f'file://{ld}/' + quote(base) + '.html'
|
||||
|
||||
@ -81,6 +81,7 @@ class TestBuild(BaseTest):
|
||||
self.ae(p(), 'file:///docs/index.html')
|
||||
self.ae(p('conf'), 'file:///docs/conf.html')
|
||||
self.ae(p('kittens/ssh#frag'), 'file:///docs/kittens/ssh.html#frag')
|
||||
self.ae(p('#ref=confloc'), 'file:///docs/conf.html#confloc')
|
||||
|
||||
|
||||
def main() -> None:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user