clan: implement OSC8 hyperlinks for help output
The name of the terminal help output stays the same to keep compatibility with legacy terminal implementations.
This commit is contained in:
@@ -28,6 +28,7 @@ from . import (
|
|||||||
from .custom_logger import setup_logging
|
from .custom_logger import setup_logging
|
||||||
from .dirs import get_clan_flake_toplevel_or_env
|
from .dirs import get_clan_flake_toplevel_or_env
|
||||||
from .errors import ClanCmdError, ClanError
|
from .errors import ClanCmdError, ClanError
|
||||||
|
from .hyperlink import help_hyperlink
|
||||||
from .profiler import profile
|
from .profiler import profile
|
||||||
from .ssh import cli as ssh_cli
|
from .ssh import cli as ssh_cli
|
||||||
|
|
||||||
@@ -89,9 +90,9 @@ def create_parser(prog: str | None = None) -> argparse.ArgumentParser:
|
|||||||
prog=prog,
|
prog=prog,
|
||||||
description="The clan cli tool.",
|
description="The clan cli tool.",
|
||||||
epilog=(
|
epilog=(
|
||||||
"""
|
f"""
|
||||||
Online reference for the clan cli tool: https://docs.clan.lol/reference/cli/
|
Online reference for the clan cli tool: {help_hyperlink("cli reference", "https://docs.clan.lol/reference/cli/")}
|
||||||
For more detailed information, visit: https://docs.clan.lol
|
For more detailed information, visit: {help_hyperlink("docs", "https://docs.clan.lol")}
|
||||||
"""
|
"""
|
||||||
),
|
),
|
||||||
formatter_class=argparse.RawTextHelpFormatter,
|
formatter_class=argparse.RawTextHelpFormatter,
|
||||||
@@ -127,7 +128,7 @@ Note: The meta results from clan/meta.json and manual flake arguments. It may no
|
|||||||
help="manage backups of clan machines",
|
help="manage backups of clan machines",
|
||||||
description="manage backups of clan machines",
|
description="manage backups of clan machines",
|
||||||
epilog=(
|
epilog=(
|
||||||
"""
|
f"""
|
||||||
This subcommand provides an interface to backups that clan machines expose.
|
This subcommand provides an interface to backups that clan machines expose.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
@@ -142,7 +143,7 @@ Examples:
|
|||||||
The backup to restore for the machine [MACHINE] with the configured [PROVIDER]
|
The backup to restore for the machine [MACHINE] with the configured [PROVIDER]
|
||||||
with the name [NAME].
|
with the name [NAME].
|
||||||
|
|
||||||
For more detailed information, visit: https://docs.clan.lol/getting-started/backups/
|
For more detailed information visit: {help_hyperlink("backups", "https://docs.clan.lol/getting-started/backups")}.
|
||||||
"""
|
"""
|
||||||
),
|
),
|
||||||
formatter_class=argparse.RawTextHelpFormatter,
|
formatter_class=argparse.RawTextHelpFormatter,
|
||||||
@@ -154,13 +155,13 @@ For more detailed information, visit: https://docs.clan.lol/getting-started/back
|
|||||||
help="create a clan flake inside the current directory",
|
help="create a clan flake inside the current directory",
|
||||||
description="create a clan flake inside the current directory",
|
description="create a clan flake inside the current directory",
|
||||||
epilog=(
|
epilog=(
|
||||||
"""
|
f"""
|
||||||
Examples:
|
Examples:
|
||||||
$ clan flakes create [DIR]
|
$ clan flakes create [DIR]
|
||||||
Will create a new clan flake in the specified directory and create it if it
|
Will create a new clan flake in the specified directory and create it if it
|
||||||
doesn't exist yet. The flake will be created from a default template.
|
doesn't exist yet. The flake will be created from a default template.
|
||||||
|
|
||||||
For more detailed information, visit: https://docs.clan.lol/getting-started
|
For more detailed information, visit: {help_hyperlink("getting-started", "https://docs.clan.lol/getting-started")}
|
||||||
"""
|
"""
|
||||||
),
|
),
|
||||||
formatter_class=argparse.RawTextHelpFormatter,
|
formatter_class=argparse.RawTextHelpFormatter,
|
||||||
@@ -185,7 +186,7 @@ For more detailed information, visit: https://docs.clan.lol/getting-started
|
|||||||
help="ssh to a remote machine",
|
help="ssh to a remote machine",
|
||||||
description="ssh to a remote machine",
|
description="ssh to a remote machine",
|
||||||
epilog=(
|
epilog=(
|
||||||
"""
|
f"""
|
||||||
This subcommand allows seamless ssh access to the nixos-image builders.
|
This subcommand allows seamless ssh access to the nixos-image builders.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
@@ -195,7 +196,7 @@ Examples:
|
|||||||
the json string. [JSON] can either be a json formatted string itself, or point
|
the json string. [JSON] can either be a json formatted string itself, or point
|
||||||
towards a file containing the deployment information
|
towards a file containing the deployment information
|
||||||
|
|
||||||
For more detailed information, visit: https://docs.clan.lol/getting-started/deploy
|
For more detailed information, visit: {help_hyperlink("deploy", "https://docs.clan.lol/getting-started/deploy")}
|
||||||
"""
|
"""
|
||||||
),
|
),
|
||||||
formatter_class=argparse.RawTextHelpFormatter,
|
formatter_class=argparse.RawTextHelpFormatter,
|
||||||
@@ -207,7 +208,7 @@ For more detailed information, visit: https://docs.clan.lol/getting-started/depl
|
|||||||
help="manage secrets",
|
help="manage secrets",
|
||||||
description="manage secrets",
|
description="manage secrets",
|
||||||
epilog=(
|
epilog=(
|
||||||
"""
|
f"""
|
||||||
This subcommand provides an interface to secret facts.
|
This subcommand provides an interface to secret facts.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
@@ -219,7 +220,7 @@ Examples:
|
|||||||
$ clan secrets get [SECRET]
|
$ clan secrets get [SECRET]
|
||||||
Will display the content of the specified secret.
|
Will display the content of the specified secret.
|
||||||
|
|
||||||
For more detailed information, visit: https://docs.clan.lol/getting-started/secrets/
|
For more detailed information, visit: {help_hyperlink("secrets", "https://docs.clan.lol/getting-started/secrets")}
|
||||||
"""
|
"""
|
||||||
),
|
),
|
||||||
formatter_class=argparse.RawTextHelpFormatter,
|
formatter_class=argparse.RawTextHelpFormatter,
|
||||||
@@ -231,7 +232,7 @@ For more detailed information, visit: https://docs.clan.lol/getting-started/secr
|
|||||||
help="manage facts",
|
help="manage facts",
|
||||||
description="manage facts",
|
description="manage facts",
|
||||||
epilog=(
|
epilog=(
|
||||||
"""
|
f"""
|
||||||
|
|
||||||
This subcommand provides an interface to facts of clan machines.
|
This subcommand provides an interface to facts of clan machines.
|
||||||
Facts are artifacts that a service can generate.
|
Facts are artifacts that a service can generate.
|
||||||
@@ -256,7 +257,7 @@ Examples:
|
|||||||
This is especially useful for resetting certain passwords while leaving the rest
|
This is especially useful for resetting certain passwords while leaving the rest
|
||||||
of the facts for a machine in place.
|
of the facts for a machine in place.
|
||||||
|
|
||||||
For more detailed information, visit: https://docs.clan.lol/getting-started/secrets/
|
For more detailed information, visit: {help_hyperlink("secrets", "https://docs.clan.lol/getting-started/secrets")}
|
||||||
"""
|
"""
|
||||||
),
|
),
|
||||||
formatter_class=argparse.RawTextHelpFormatter,
|
formatter_class=argparse.RawTextHelpFormatter,
|
||||||
@@ -268,7 +269,7 @@ For more detailed information, visit: https://docs.clan.lol/getting-started/secr
|
|||||||
help="manage machines and their configuration",
|
help="manage machines and their configuration",
|
||||||
description="manage machines and their configuration",
|
description="manage machines and their configuration",
|
||||||
epilog=(
|
epilog=(
|
||||||
"""
|
f"""
|
||||||
This subcommand provides an interface to machines managed by clan.
|
This subcommand provides an interface to machines managed by clan.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
@@ -283,7 +284,7 @@ Examples:
|
|||||||
$ clan machines install [MACHINES] [TARGET_HOST]
|
$ clan machines install [MACHINES] [TARGET_HOST]
|
||||||
Will install the specified machine [MACHINE], to the specified [TARGET_HOST].
|
Will install the specified machine [MACHINE], to the specified [TARGET_HOST].
|
||||||
|
|
||||||
For more detailed information, visit: https://docs.clan.lol/getting-started/deploy
|
For more detailed information, visit: {help_hyperlink("deploy", "https://docs.clan.lol/deploy")}
|
||||||
"""
|
"""
|
||||||
),
|
),
|
||||||
formatter_class=argparse.RawTextHelpFormatter,
|
formatter_class=argparse.RawTextHelpFormatter,
|
||||||
@@ -314,7 +315,7 @@ For more detailed information, visit: https://docs.clan.lol/getting-started/depl
|
|||||||
help="query state information about machines",
|
help="query state information about machines",
|
||||||
description="query state information about machines",
|
description="query state information about machines",
|
||||||
epilog=(
|
epilog=(
|
||||||
"""
|
f"""
|
||||||
This subcommand provides an interface to the state managed by clan.
|
This subcommand provides an interface to the state managed by clan.
|
||||||
|
|
||||||
State can be folders and databases that modules depend on managed by clan.
|
State can be folders and databases that modules depend on managed by clan.
|
||||||
@@ -334,7 +335,7 @@ Examples:
|
|||||||
$ clan state list [MACHINE]
|
$ clan state list [MACHINE]
|
||||||
List state of the machines managed by clan.
|
List state of the machines managed by clan.
|
||||||
|
|
||||||
For more detailed information, visit: https://docs.clan.lol/getting-started/backups
|
For more detailed information, visit: {help_hyperlink("getting-started", "https://docs.clan.lol/backups")}
|
||||||
"""
|
"""
|
||||||
),
|
),
|
||||||
formatter_class=argparse.RawTextHelpFormatter,
|
formatter_class=argparse.RawTextHelpFormatter,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
# !/usr/bin/env python3
|
# !/usr/bin/env python3
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
|
from ..hyperlink import help_hyperlink
|
||||||
from .check import register_check_parser
|
from .check import register_check_parser
|
||||||
from .generate import register_generate_parser
|
from .generate import register_generate_parser
|
||||||
from .list import register_list_parser
|
from .list import register_list_parser
|
||||||
@@ -20,7 +21,7 @@ def register_parser(parser: argparse.ArgumentParser) -> None:
|
|||||||
"check",
|
"check",
|
||||||
help="check if facts are up to date",
|
help="check if facts are up to date",
|
||||||
epilog=(
|
epilog=(
|
||||||
"""
|
f"""
|
||||||
This subcommand allows checking if all facts are up to date.
|
This subcommand allows checking if all facts are up to date.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
@@ -29,7 +30,7 @@ Examples:
|
|||||||
Will check facts for the specified machine.
|
Will check facts for the specified machine.
|
||||||
|
|
||||||
|
|
||||||
For more detailed information, visit: https://docs.clan.lol/getting-started/secrets/
|
For more detailed information, visit: {help_hyperlink("secrets", "https://docs.clan.lol/getting-started/secrets")}
|
||||||
"""
|
"""
|
||||||
),
|
),
|
||||||
formatter_class=argparse.RawTextHelpFormatter,
|
formatter_class=argparse.RawTextHelpFormatter,
|
||||||
@@ -40,7 +41,7 @@ For more detailed information, visit: https://docs.clan.lol/getting-started/secr
|
|||||||
"list",
|
"list",
|
||||||
help="list all facts",
|
help="list all facts",
|
||||||
epilog=(
|
epilog=(
|
||||||
"""
|
f"""
|
||||||
This subcommand allows listing all public facts for a specific machine.
|
This subcommand allows listing all public facts for a specific machine.
|
||||||
|
|
||||||
The resulting list will be a json string with the name of the fact as its key
|
The resulting list will be a json string with the name of the fact as its key
|
||||||
@@ -48,9 +49,9 @@ and the fact itself as it's value.
|
|||||||
|
|
||||||
This is how an example output might look like:
|
This is how an example output might look like:
|
||||||
```
|
```
|
||||||
{
|
\u007b
|
||||||
"[FACT_NAME]": "[FACT]"
|
"[FACT_NAME]": "[FACT]"
|
||||||
}
|
\u007d
|
||||||
```
|
```
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
@@ -59,7 +60,7 @@ Examples:
|
|||||||
Will list facts for the specified machine.
|
Will list facts for the specified machine.
|
||||||
|
|
||||||
|
|
||||||
For more detailed information, visit: https://docs.clan.lol/getting-started/secrets/
|
For more detailed information, visit: {help_hyperlink("secrets", "https://docs.clan.lol/getting-started/secrets")}
|
||||||
"""
|
"""
|
||||||
),
|
),
|
||||||
formatter_class=argparse.RawTextHelpFormatter,
|
formatter_class=argparse.RawTextHelpFormatter,
|
||||||
@@ -70,7 +71,7 @@ For more detailed information, visit: https://docs.clan.lol/getting-started/secr
|
|||||||
"generate",
|
"generate",
|
||||||
help="generate public and secret facts for machines",
|
help="generate public and secret facts for machines",
|
||||||
epilog=(
|
epilog=(
|
||||||
"""
|
f"""
|
||||||
This subcommand allows control of the generation of facts.
|
This subcommand allows control of the generation of facts.
|
||||||
Often this function will be invoked automatically on deploying machines,
|
Often this function will be invoked automatically on deploying machines,
|
||||||
but there are situations the user may want to have more granular control,
|
but there are situations the user may want to have more granular control,
|
||||||
@@ -99,7 +100,7 @@ Examples:
|
|||||||
This is especially useful for resetting certain passwords while leaving the rest
|
This is especially useful for resetting certain passwords while leaving the rest
|
||||||
of the facts for a machine in place.
|
of the facts for a machine in place.
|
||||||
|
|
||||||
For more detailed information, visit: https://docs.clan.lol/getting-started/secrets/
|
For more detailed information, visit: {help_hyperlink("secrets", "https://docs.clan.lol/getting-started/secrets")}
|
||||||
"""
|
"""
|
||||||
),
|
),
|
||||||
formatter_class=argparse.RawTextHelpFormatter,
|
formatter_class=argparse.RawTextHelpFormatter,
|
||||||
@@ -110,7 +111,7 @@ For more detailed information, visit: https://docs.clan.lol/getting-started/secr
|
|||||||
"upload",
|
"upload",
|
||||||
help="upload secrets for machines",
|
help="upload secrets for machines",
|
||||||
epilog=(
|
epilog=(
|
||||||
"""
|
f"""
|
||||||
This subcommand allows uploading secrets to remote machines.
|
This subcommand allows uploading secrets to remote machines.
|
||||||
|
|
||||||
If using sops as a secret backend it will upload the private key to the machine.
|
If using sops as a secret backend it will upload the private key to the machine.
|
||||||
@@ -123,7 +124,7 @@ Examples:
|
|||||||
$ clan facts upload [MACHINE]
|
$ clan facts upload [MACHINE]
|
||||||
Will upload secrets to a specific machine.
|
Will upload secrets to a specific machine.
|
||||||
|
|
||||||
For more detailed information, visit: https://docs.clan.lol/getting-started/secrets/
|
For more detailed information, visit: {help_hyperlink("secrets", "https://docs.clan.lol/getting-started/secrets")}
|
||||||
"""
|
"""
|
||||||
),
|
),
|
||||||
formatter_class=argparse.RawTextHelpFormatter,
|
formatter_class=argparse.RawTextHelpFormatter,
|
||||||
|
|||||||
41
pkgs/clan-cli/clan_cli/hyperlink.py
Normal file
41
pkgs/clan-cli/clan_cli/hyperlink.py
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# Implementation of OSC8
|
||||||
|
def hyperlink(text: str, url: str) -> str:
|
||||||
|
"""
|
||||||
|
Generate OSC8 escape sequence for hyperlinks.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
url (str): The URL to link to.
|
||||||
|
text (str): The text to display.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: The formatted string with an embedded hyperlink.
|
||||||
|
"""
|
||||||
|
esc = "\033"
|
||||||
|
return f"{esc}]8;;{url}{esc}\\{text}{esc}]8;;{esc}\\"
|
||||||
|
|
||||||
|
|
||||||
|
def hyperlink_same_text_and_url(url: str) -> str:
|
||||||
|
"""
|
||||||
|
Keep the description and the link the same to support legacy terminals.
|
||||||
|
"""
|
||||||
|
return hyperlink(url, url)
|
||||||
|
|
||||||
|
|
||||||
|
def help_hyperlink(description: str, url: str) -> str:
|
||||||
|
import sys
|
||||||
|
|
||||||
|
"""
|
||||||
|
Keep the description and the link the same to support legacy terminals.
|
||||||
|
"""
|
||||||
|
if sys.argv[0].__contains__("docs.py"):
|
||||||
|
return docs_hyperlink(description, url)
|
||||||
|
|
||||||
|
else:
|
||||||
|
return hyperlink_same_text_and_url(url)
|
||||||
|
|
||||||
|
|
||||||
|
def docs_hyperlink(description: str, url: str) -> str:
|
||||||
|
"""
|
||||||
|
Returns a markdown hyperlink
|
||||||
|
"""
|
||||||
|
return f"[{description}]({url})"
|
||||||
@@ -105,8 +105,9 @@ def epilog_to_md(text: str) -> str:
|
|||||||
md += "\n"
|
md += "\n"
|
||||||
md += "\n"
|
md += "\n"
|
||||||
else:
|
else:
|
||||||
if contains_https_link(line):
|
# TODO: check, if the link is already a markdown link, only convert if not
|
||||||
line = convert_to_markdown_link(line)
|
# if contains_https_link(line):
|
||||||
|
# line = convert_to_markdown_link(line)
|
||||||
md += line
|
md += line
|
||||||
md += "\n"
|
md += "\n"
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user