Source code for maestral.cli.dialogs

"""
This module provides interactive commandline dialogs which are based on the
:mod:`survey` Python library.
"""
from __future__ import annotations

from typing import Callable, Sequence

import click


def _style_message(message: str) -> str:
    return f"{message} "


def _style_hint(hint: str) -> str:
    return f"{hint} " if hint else ""


[docs]def prompt( message: str, default: str | None = None, validate: Callable | None = None ) -> str: import survey styled_message = _style_message(message) def check(value: str) -> bool: if validate is not None: return validate(value) else: return True res = survey.input(styled_message, default=default, check=check) return res
[docs]def confirm(message: str, default: bool | None = True) -> bool: import survey styled_message = _style_message(message) return survey.confirm(styled_message, default=default)
[docs]def select(message: str, options: Sequence[str], hint="") -> int: import survey try: styled_hint = _style_hint(hint) styled_message = _style_message(message) index = survey.select(options, styled_message, hint=styled_hint) return index except (KeyboardInterrupt, SystemExit): survey.respond() raise
[docs]def select_multiple(message: str, options: Sequence[str], hint="") -> list[int]: import survey try: styled_hint = _style_hint(hint) styled_message = _style_message(message) kwargs = {"hint": styled_hint} if hint else {} indices = survey.select( options, styled_message, multi=True, pin="[✓] ", unpin="[ ] ", **kwargs ) chosen = [options[index] for index in indices] response = ", ".join(chosen) if len(indices) == 0 or len(response) > 50: response = f"[{len(indices)} chosen]" survey.respond(response) return indices except (KeyboardInterrupt, SystemExit): survey.respond() raise
[docs]def select_path( message: str, default: str | None = None, validate: Callable = lambda x: True, exists: bool = False, files_allowed: bool = True, dirs_allowed: bool = True, ) -> str: import os import survey import wrapio track = wrapio.Track() styled_message = _style_message(message) failed = False def check(value: str) -> bool: nonlocal failed if value == "" and default: return True full_path = os.path.expanduser(value) forbidden_dir = os.path.isdir(full_path) and not dirs_allowed forbidden_file = os.path.isfile(full_path) and not files_allowed exist_condition = os.path.exists(full_path) or not exists if not exist_condition: survey.update(click.style("(not found) ", fg="red")) elif forbidden_dir: survey.update(click.style("(not a file) ", fg="red")) elif forbidden_file: survey.update(click.style("(not a folder) ", fg="red")) failed = ( not exist_condition or forbidden_dir or forbidden_file or not validate(value) ) return not failed res = survey.input( styled_message, default=default, callback=track.invoke, check=check, ) return res