Source code for cli2.interactive

""" Interactive user inputs """
import cli2
import os
import shlex
import subprocess
import tempfile
from pathlib import Path

from .log import log


def confirm(question, default=None):
    return choice(question, default=default) == 'y'


[docs] def choice(question, choices=None, default=None): """ Ask user to make a choice. .. code-block:: accepted = cli2.choice('Accept terms?') == 'y' :param question: String question to ask :param choices: List of acceptable choices, y/n by default :param default: Default value for when the user does not add a value. """ choices = [c.lower() for c in choices or ['y', 'n']] if default: choices_display = [ c.upper() if c == default.lower() else c for c in choices ] else: choices_display = choices question = question + f' ({"/".join(choices_display)})' tries = 30 while tries: answer = input(question) if not answer and default: return default if answer.lower() in choices: return answer.lower() tries -= 1
[docs] def editor(content=None, path=None): """ Open $EDITOR with content, return the result. Like git rebase -i does! - If a file path is given, edit in place. - Otherwise, write to a temporary file. - Anyway: return the written contents. :param content: Initial content if any :param path: Path to edit or write content into :return: The edited content after $EDITOR exit """ editor = os.getenv('EDITOR', 'vim') tmp_file = None if path and path.exists(): edit_path = path else: suffix = 'txt' if not path else path.name.split('.')[-1] tmp = tempfile.NamedTemporaryFile( mode='w+', delete=False, suffix=f'.{suffix}', ) edit_path = tmp.name if content: with tmp as f: cli2.log.debug('writing', path=f.name) f.write(str(content)) f.flush() tmp_file = Path(f.name) cli2.log.debug('editing', path=edit_path) command = f"{editor} {shlex.quote(str(edit_path))}" try: subprocess.run(shlex.split(command), check=True) except subprocess.CalledProcessError as e: log.error(f"Error running Vim: {e}") return None except FileNotFoundError: log.warn(f"Temporary file gone?? {path}") return None else: with open(edit_path, 'r') as f: cli2.log.debug('reading', path=edit_path) content = f.read() if path and not path.exists(): path.parent.mkdir(exist_ok=True, parents=True) with path.open('w') as f: cli2.log.debug('writing', path=path) f.write(content) return content finally: if tmp_file: try: os.remove(tmp_file) except OSError as e: log.warn(f"Error deleting temporary file {tmp_file}: {e}")