def uninstall(TPLDIR: Path, force: bool, template: str) -> None: repo = Repository(TPLDIR) if repo.is_installed(template): rm = force if not force: rm = console.question( f"Do you really want to uninstall template {Fore.CYAN}{template}{Style.RESET_ALL}", color=Fore.YELLOW, echo=click.confirm, ) if rm: try: repo.uninstall(template) console.success( f"Removed template {Style.BRIGHT}{template}{Style.RESET_ALL}" ) except OSError: console.error( f"Error while uninstalling template {Fore.CYAN}{template}{Style.RESET_ALL}" ) console.indent( "You might need to manually delete the template directory at" ) console.indent(f"{Style.BRIGHT}{repo.root}{Style.RESET_ALL}") else: console.warn( f"Template {Fore.CYAN}{template}{Style.RESET_ALL} does not exist")
def field_choice( key: str, project: "Project", default: int = 1, value: t.Optional[int] = None, choices: t.List[str] = list(), ) -> t.Any: if value and value < len(choices): console.info( f'Used prefilled value for "{Fore.MAGENTA}{key}{Style.RESET_ALL}"') project.variables[f"{key}_index"] = value return choices[value] else: if len(choices) > 1: console.question( f'Chose a value for "{Fore.MAGENTA}{key}{Style.RESET_ALL}"', echo=click.echo, ) for n, choice in enumerate(choices): console.indent( f'{Style.BRIGHT}{n+1}{Style.RESET_ALL} - "{choice}"') n = click.prompt( console.indent(f"Select from 1..{len(choices)}", echo=None), default=default, ) if n > len(choices): console.warn(f"{n} is not a valid choice. Using default.") n = default else: n = 1 project.variables[f"{key}_index"] = n - 1 return choices[n - 1]
def field_file_select( key: str, project: "Project", default: int = 1, value: t.Optional[str] = None, choices: t.List[str] = list(), filename: t.Optional[str] = None, ) -> t.Any: if value and value in choices: console.info( f'Used prefilled value for "{Fore.MAGENTA}{key}{Style.RESET_ALL}"') else: if len(choices) > 1: console.question( f'Chose a value for "{Fore.MAGENTA}{key}{Style.RESET_ALL}"', echo=click.echo, ) for n, choice in enumerate(choices): console.indent( f'{Style.BRIGHT}{n+1}{Style.RESET_ALL} - "{choice}"') n = click.prompt( console.indent(f"Select from 1..{len(choices)}", echo=None), default=default, ) if n > len(choices): console.warn(f"{n} is not a valid choice. Using default.") n = default value = choices[n - 1] else: value = choices[0] project.templates.append(f"includes:{value}") if filename: project.files[value] = {"filename": filename} return value
def list(TPLDIR: Path, plain: bool) -> None: """ Lists all templates in the current local repository. """ repo = Repository(TPLDIR) if repo.exists(): if len(repo) > 0: if plain: for project_name in repo: click.echo(project_name) else: console.info( f"Listing templates in {Style.BRIGHT}{TPLDIR}{Style.RESET_ALL}." ) print() console.indent( f'⎪ {"name":^12} ⎪ {"created":^24} ⎪ {"updated":^24} ⎪') console.indent(f'|{"-"*14}⎪{"-"*26}⎪{"-"*26}|') for project in repo.projects(): project.setup(load_project=True) name = project.name created = "unknown" updated = "never" if project.is_symlinked(): name = project.name + "*" created = "-" updated = "-" else: if "updated" in project.meta: updated = time.ctime(int(project.meta["updated"])) if "created" in project.meta: created = time.ctime(int(project.meta["created"])) console.indent( f"| {Fore.CYAN}{name:<12}{Style.RESET_ALL} | {created:>24} | {updated:>24} |" ) print() else: console.info("No templates installed yet.") else: console.warn("Template folder does not exist.") exit(1)
def field_dict( key: str, project: "Project", default: int = 1, value: t.Optional[t.Union[str, int]] = None, choices: t.Dict[str, t.Any] = dict(), ) -> t.Any: _keys: t.List[str] = list(choices.keys()) _keys_len = len(_keys) if value and (value in choices or int(value) < _keys_len): console.info( f'Used prefilled value for "{Fore.MAGENTA}{key}{Style.RESET_ALL}"') project.variables[f"{key}_key"] = value if value in choices: return choices[str(value)] else: return choices[_keys[int(value)]] return choices[value] else: if _keys_len > 1: console.question( f'Chose a value for "{Fore.MAGENTA}{key}{Style.RESET_ALL}"', echo=click.echo, ) for n, choice in enumerate(_keys): console.indent( f'{Style.BRIGHT}{n+1}{Style.RESET_ALL} - "{choice}"') n = click.prompt( console.indent(f"Select from 1..{_keys_len}", echo=None), default=default, ) if n > _keys_len: console.warn(f"{n} is not a valid choice. Using default.") if default in choices: k = str(default) else: k = _keys[int(default)] else: k = _keys[0] project.variables[f"{key}_key"] = k return choices[k]
def use( ctx: click.Context, template: str, out: t.Union[str, Path], hard: bool, value: t.List[t.Tuple[str, str]], dev: bool, ) -> None: """ Generate a new project from TEMPLATE. If OUT is given and a directory, the template is created there. Otherwise the cwd is used. """ cfg = ctx.obj # Check teamplate and read configuration project = Project(template, cfg["TPLDIR"]) try: project.setup(load_project=True) except FileNotFoundError: console.warn( f"No valid template found for key {Fore.CYAN}{template}{Style.RESET_ALL}" ) ctx.exit(1) # Prepare output directory if out == ".": out = Path.cwd() else: out = Path(out) if out.exists() and len(os.listdir(out)) > 0: if hard: shutil.rmtree(out) out.mkdir(parents=True) console.success(f"Cleared {Style.BRIGHT}{out}{Style.RESET_ALL}") elif not out.exists(): out.mkdir(parents=True) console.success(f"Created {Style.BRIGHT}{out}{Style.RESET_ALL}") # Read user input (if necessary) if project.fields: # Prepare dict for prefilled values prefilled = cfg["prefilled"] if "prefilled" in cfg else dict() if value: for k, v in value: prefilled[k] = v project.fill(prefilled) for success, file_in, file_out in project.compile(out): if success: console.success( f"Created {Style.BRIGHT}{file_out}{Style.RESET_ALL}") else: console.warn( f"Skipped {Style.BRIGHT}{file_out}{Style.RESET_ALL} due to empty content" ) console.success( f'Generated project template "{Fore.CYAN}{template}{Style.RESET_ALL}" in {Style.BRIGHT}{out}{Style.RESET_ALL}' )