Skip to content

CLI

elva.cli

Module providing the main command line interface functionality.

Subcommands are defined in the respective app module.

Functions:

  • find_config_path

    Find the next ELVA configuration file.

  • resolve_configs

    Hook sanitizing configuration file paths on invoking the ELVA command.

  • resolve_log

    Hook sanitizing the log file path on invoking the ELVA command.

  • elva

    ELVA - A suite of real-time collaboration TUI apps.

  • context

    Print the parameters passed to apps and other subcommands.

Attributes:

  • APP_NAME

    Default app name.

  • CONFIG_NAME

    Default ELVA configuration file name.

  • LEVEL

    Logging levels sorted by verbosity.

  • CONFIG_PATHS

    List containing all found default ELVA configuration file paths.

  • USER_HOME_CONFIG

    Path to the calling system user's ELVA configuration file.

  • PROJECT_PATH

    The path to the current active project.

APP_NAME = 'elva' module-attribute

Default app name.

CONFIG_NAME = APP_NAME + '.toml' module-attribute

Default ELVA configuration file name.

LEVEL = [None, logging.CRITICAL, logging.ERROR, logging.WARNING, logging.INFO, logging.DEBUG] module-attribute

Logging levels sorted by verbosity.

CONFIG_PATHS = list() module-attribute

List containing all found default ELVA configuration file paths.

USER_HOME_CONFIG = Path(platformdirs.user_config_dir(APP_NAME)) / CONFIG_NAME module-attribute

Path to the calling system user's ELVA configuration file.

PROJECT_PATH = None module-attribute

The path to the current active project.

find_config_path()

Find the next ELVA configuration file.

This function searches the directory tree from bottom to top.

Source code in src/elva/cli.py
def find_config_path():
    """
    Find the next ELVA configuration file.

    This function searches the directory tree from bottom to top.
    """
    cwd = Path.cwd()
    for path in [cwd] + list(cwd.parents):
        config = path / CONFIG_NAME
        if config.exists():
            return config

resolve_configs(ctx, param, paths)

Hook sanitizing configuration file paths on invoking the ELVA command.

Parameters:

  • ctx (Context) –

    the click context of the current invokation.

  • param (Parameter) –

    the parameter currently being parsed.

  • paths (None | list[Path]) –

    the paths given to the parameter.

Returns:

  • list[Path]

    a list of paths to all given and found ELVA configuration files.

Source code in src/elva/cli.py
def resolve_configs(
    ctx: click.Context, param: click.Parameter, paths: None | list[Path]
) -> list[Path]:
    """
    Hook sanitizing configuration file paths on invoking the ELVA command.

    Arguments:
        ctx: the click context of the current invokation.
        param: the parameter currently being parsed.
        paths: the paths given to the parameter.

    Returns:
        a list of paths to all given and found ELVA configuration files.
    """
    if paths is not None:
        paths = [path.resolve() for path in paths]
        param_source = ctx.get_parameter_source(param.name)
        if not param_source == ParameterSource.DEFAULT:
            paths.extend(CONFIG_PATHS)

    return paths

resolve_log(ctx, param, log)

Hook sanitizing the log file path on invoking the ELVA command.

Parameters:

  • ctx (Context) –

    the click context of the current invokation.

  • param (Parameter) –

    the parameter currently being parsed.

  • log (None | Path) –

    the path of the log file given to the parameter.

Returns:

  • None | Path

    the resolved path of the log file if one was given, else None.

Source code in src/elva/cli.py
def resolve_log(
    ctx: click.Context, param: click.Parameter, log: None | Path
) -> None | Path:
    """
    Hook sanitizing the log file path on invoking the ELVA command.

    Arguments:
        ctx: the click context of the current invokation.
        param: the parameter currently being parsed.
        log: the path of the log file given to the parameter.

    Returns:
       the resolved path of the log file if one was given, else `None`.
    """
    if log is not None:
        log = log.resolve()

    return log

elva(ctx, configs, log, verbose, name, user, password, server, identifier, messages)

ELVA - A suite of real-time collaboration TUI apps.

Parameters:

  • ctx (Context) –

    the click context holding the configuration parameter object.

  • configs (list[Path]) –

    list of configuration files to parse.

  • log (Path) –

    path of the log file.

  • verbose (int) –

    verbosity, i.e. log level, indicator from 0 (no logging) to 5 (log everything).

  • name (str) –

    the name to display instead of the user name.

  • user (str) –

    the user name to login with.

  • password (str) –

    the password to login with.

  • server (str | None) –

    the address of the remote server for synchronization.

  • identifier (str | None) –

    the identifier of the Y document.

  • messages (str) –

    the type of messages to use for synchronization.

Source code in src/elva/cli.py
@click.group(
    context_settings=dict(
        ignore_unknown_options=True,
        allow_extra_args=True,
    )
)
@click.pass_context
#
# paths
#
@click.option(
    "--config",
    "-c",
    "configs",
    help="Path to config file or directory. Can be specified multiple times.",
    envvar="ELVA_CONFIG_PATH",
    multiple=True,
    show_envvar=True,
    # a list, as multiple=True
    default=CONFIG_PATHS,
    show_default=True,
    type=click.Path(path_type=Path),
    callback=resolve_configs,
)
@click.option(
    "--log",
    "-l",
    "log",
    help="Path to logging file.",
    envvar="ELVA_LOG",
    show_envvar=True,
    type=click.Path(path_type=Path, dir_okay=False),
    callback=resolve_log,
)
# logging
@click.option(
    "--verbose",
    "-v",
    "verbose",
    help="Verbosity of logging output.",
    count=True,
    default=LEVEL.index(logging.INFO),
    type=click.IntRange(0, 5, clamp=True),
)
#
# connection information
#
@click.option(
    "--name",
    "-n",
    "name",
    help="User display username.",
    envvar="ELVA_NAME",
    show_envvar=True,
)
@click.option(
    "--user",
    "-u",
    "user",
    help="Username for authentication.",
    envvar="ELVA_USER",
    show_envvar=True,
)
@click.option(
    "--password",
    "-p",
    "password",
    help="Password for authentication",
    # we don't support bad secret management,
    # so the password is not settable via an envvar
)
@click.option(
    "--server",
    "-s",
    "server",
    help="URI of the syncing server.",
    envvar="ELVA_SERVER",
    show_envvar=True,
)
@click.option(
    "--identifier",
    "-i",
    "identifier",
    help="Unique identifier of the shared document.",
    envvar="ELVA_IDENTIFIER",
    show_envvar=True,
)
@click.option(
    "--messages",
    "-m",
    "messages",
    help="Protocol used to connect to the syncing server.",
    envvar="ELVA_MESSAGES",
    show_envvar=True,
    type=click.Choice(["yjs", "elva"], case_sensitive=False),
)
#
# function definition
#
def elva(
    ctx: click.Context,
    configs: list[Path],
    log: Path,
    verbose: int,
    name: str,
    user: str,
    password: str,
    server: str | None,
    identifier: str | None,
    messages: str,
):
    """
    ELVA - A suite of real-time collaboration TUI apps.
    \f

    Arguments:
        ctx: the click context holding the configuration parameter object.
        configs: list of configuration files to parse.
        log: path of the log file.
        verbose: verbosity, i.e. log level, indicator from 0 (no logging) to 5 (log everything).
        name: the name to display instead of the user name.
        user: the user name to login with.
        password: the password to login with.
        server: the address of the remote server for synchronization.
        identifier: the identifier of the Y document.
        messages: the type of messages to use for synchronization.
    """

    ctx.ensure_object(dict)
    c = ctx.obj

    # paths
    c["project"] = PROJECT_PATH
    c["configs"] = configs
    c["file"] = None
    c["render"] = None
    c["log"] = log

    # logging
    c["level"] = LEVEL[verbose]

    # connection
    c["name"] = name
    c["user"] = user
    c["password"] = password
    c["identifier"] = identifier
    c["server"] = server
    c["messages"] = messages

context(ctx, file, app)

Print the parameters passed to apps and other subcommands.

Parameters:

  • ctx (Context) –

    the click context holding the configuration parameter object.

  • file (None | Path) –

    the path to the ELVA SQLite database file.

  • app (None | str) –

    the app section to take additional configuration parameters from.

Source code in src/elva/cli.py
@elva.command
@click.pass_context
@click.argument(
    "file",
    required=False,
    type=click.Path(path_type=Path, dir_okay=False),
)
@click.option(
    "--app",
    "-a",
    "app",
    metavar="APP",
    help="Include the parameters defined in the app.APP config file section.",
)
def context(ctx: click.Context, file: None | Path, app: None | str):
    """
    Print the parameters passed to apps and other subcommands.

    Arguments:
        ctx: the click context holding the configuration parameter object.
        file: the path to the ELVA SQLite database file.
        app: the app section to take additional configuration parameters from.
    """
    c = ctx.obj

    gather_context_information(ctx, file, app)

    # sanitize password output
    if c["password"] is not None:
        c["password"] = "[REDACTED]"

    # TODO: print config in TOML syntax, so that it can be piped directly
    print(c)