dotfiles/home/dot_vscode/executable_vsext

155 lines
4.4 KiB
Text

#!/usr/bin/env -S viv run rich 'git+https://github.com/usu-dev/usu-py.git' -s
import argparse
import shlex
import subprocess
import sys
from pathlib import Path
import usu
from rich.align import Align
from rich.columns import Columns
from rich.console import Console
from rich.panel import Panel
from rich.prompt import Confirm
from rich.table import Table
console = Console()
def run(cmd, capture=True, returncode=False):
result = subprocess.run(
shlex.split(cmd),
stdout=subprocess.PIPE if capture else None,
text=True,
shell=False,
)
if returncode:
return result.returncode
elif capture:
return result.stdout.strip()
def parse_exts(usu_file):
exts = usu.loads(Path(usu_file).read_text())
all = [v for ext_list in exts.values() for v in ext_list]
return exts, sorted(all)
class SubcommandHelpFormatter(argparse.RawDescriptionHelpFormatter):
def _format_action(self, action):
parts = super(argparse.RawDescriptionHelpFormatter, self)._format_action(action)
if action.nargs == argparse.PARSER:
parts = "\n".join(parts.split("\n")[1:])
return parts
def get_args():
p = argparse.ArgumentParser(formatter_class=SubcommandHelpFormatter)
sp = p.add_subparsers(title="commands", metavar="", dest="command", required=True)
check = sp.add_parser(
"check",
help="check the extensions which have already been installed",
aliases=["c"],
)
check.add_argument("--verbose", help="show more information", action="store_true")
install = sp.add_parser(
"install", help="install the extensions from the spec", aliases=["i"]
)
install.add_argument(
"-f", "--force", help="force the installation of exts", action="store_true"
)
sp.add_parser("remove", help="remove all extra packages", aliases=["r"])
p.add_argument(
"-s",
"--spec",
help="mardown spec list (default ./exts.usu)",
default=Path.cwd() / "exts.usu",
)
if len(sys.argv) < 2:
p.print_help()
sys.exit(1)
return p.parse_args()
def get_extra_exts(spec, installed):
# sanitize lists
spec = [ext.lower() for ext in spec]
installed = [ext.lower() for ext in installed]
return [ext for ext in spec if ext not in installed], [
ext for ext in installed if ext not in spec
]
def code(flag, exts, force=False):
cmd = "code " + " ".join([f"{flag} {ext}" for ext in exts])
if force:
cmd += " --force"
run(cmd, capture=False)
def header():
console.print(
Panel(
Align("[yellow]VS Code Extensions Installer", align="center"),
style="magenta",
)
)
def installed_table(head, exts, not_installed):
table = Table(title=head)
table.add_column("extension")
table.add_column("installed?")
for ext in exts:
installed = ext.lower() not in not_installed
table.add_row(
ext, "Y" if installed else "N", style = 'green' if installed else "red"
)
return table
def main():
args = get_args()
header()
spec_sections, spec_list = parse_exts(args.spec)
not_installed, extra_installed = get_extra_exts(
spec_list, run("code --list-extensions").splitlines()
)
if args.command == "check" or args.command == "c":
tables = (
installed_table(head, exts, not_installed)
for head, exts in spec_sections.items()
)
console.print(Columns(tables))
if not_installed:
console.print(f"[yellow]missing {len(not_installed)} extensions")
if extra_installed:
console.print(f"[red]{len(extra_installed)} extra extensions installed")
if not args.verbose:
console.print("[dim]run with --verbose to see extra extensions")
else:
console.print(Columns(extra_installed))
elif args.command == "install" or args.command == "i":
console.print("[bold]Installing extensions from spec list")
code("--install-extension", spec_list, args.force)
elif args.command == "remove" or args.command == "r":
console.print("[red]Removing unspecified extensions")
console.print(Columns(extra_installed))
if Confirm.ask(f"Remove the above {len(extra_installed)} packages?"):
code("--uninstall-extension", extra_installed)
if __name__ == "__main__":
main()