vim-settings/install-helpers.py

334 lines
9.4 KiB
Python
Raw Normal View History

2024-07-19 19:36:35 +00:00
#!/usr/bin/env python3
import argparse
import os
import shutil
import subprocess
import sys
from enum import Enum
class Language(Enum):
2024-10-01 19:58:43 +00:00
ANSIBLE = "ansible"
BASH = "bash"
2024-07-19 19:36:35 +00:00
CSS = "css"
DOCKER = "docker"
2024-10-01 19:58:43 +00:00
GO = "go"
2024-07-19 19:36:35 +00:00
HTML = "html"
2024-10-01 19:58:43 +00:00
JAVASCRIPT = "javascript"
2024-07-19 19:36:35 +00:00
JSON = "json"
2024-10-01 19:58:43 +00:00
KOTLIN = "kotlin"
LUA = "lua"
NEOVIM = "neovim"
PYTHON = "python"
RUST = "rust"
TERRAFORM = "terraform"
TEXT = "text"
VIM = "vim"
2024-07-19 19:36:35 +00:00
WEB = "web"
2024-10-01 19:58:43 +00:00
YAML = "yaml"
2024-07-19 19:36:35 +00:00
2024-11-02 00:03:01 +00:00
META_LANGS: dict[Language, set[Language]] = {
Language.NEOVIM: {Language.VIM, Language.LUA},
Language.WEB: {Language.CSS, Language.JAVASCRIPT, Language.HTML},
}
2024-07-19 19:36:35 +00:00
def command_exists(command: str) -> bool:
return shutil.which(command) is not None
def maybe_run(*args: str) -> bool:
if command_exists(args[0]):
print("> " + " ".join(args))
result = subprocess.run(args)
return result.returncode == 0
else:
print(f"ERROR: {args[0]} does not exist. Could not run {' '.join(args)}")
return False
def should_install_user(command: str) -> bool:
bin_path = shutil.which(command)
if not bin_path:
return True
if bin_path.startswith(os.path.expanduser("~")):
return True
print("WARNING: Already installed by system. Skipping installation of", command)
return False
def maybe_pip_install(*args: str, library=False) -> bool:
user_bins = [arg for arg in args if should_install_user(arg)]
if not user_bins:
return True
if not library and command_exists("pipx"):
2024-11-02 00:03:01 +00:00
return all(
[maybe_run("pipx", "upgrade", "--install", bin) for bin in user_bins]
)
2024-07-19 19:36:35 +00:00
elif command_exists("pip3"):
return maybe_run(
"pip3",
"install",
"--user",
"--upgrade",
"--break-system-packages",
*user_bins,
)
else:
return maybe_run(
"pip",
"install",
"--user",
"--upgrade",
"--break-system-packages",
*user_bins,
)
def maybe_npm_install(*args: str) -> bool:
user_bins = [arg for arg in args if should_install_user(arg)]
if not user_bins:
return True
return maybe_run("npm", "install", "-g", *user_bins)
def maybe_go_install(**kwargs: str) -> bool:
urls = [url for name, url in kwargs.items() if should_install_user(name)]
if not urls:
return True
return maybe_run("go", "install", *urls)
def maybe_cargo_install(*args: str) -> bool:
user_bins = [arg for arg in args if should_install_user(arg)]
if not user_bins:
return True
return maybe_run("cargo", "install", *user_bins)
def maybe_release_gitter(**commands: list[str]) -> bool:
command_names = [key for key in commands.keys() if should_install_user(key)]
if not command_names:
return True
result = True
for command in command_names:
args = commands[command]
result = result and maybe_run("release-gitter", *args)
return result
2024-07-19 19:36:35 +00:00
def install_language_servers(langs: set[Language]):
if Language.PYTHON in langs:
maybe_npm_install("pyright")
if Language.RUST in langs:
maybe_run(
"rustup",
"component",
"add",
"rustfmt",
"rust-src",
"clippy",
"rust-analyzer",
)
if Language.GO in langs:
maybe_go_install(gopls="golang.org/x/tools/gopls@latest")
2024-07-19 19:36:35 +00:00
def install_linters(langs: set[Language]):
if Language.BASH in langs:
maybe_release_gitter(
shellcheck=[
"--git-url",
"https://github.com/koalaman/shellcheck",
"--extract-files",
"shellcheck-{version}/shellcheck",
"--exec",
os.path.expanduser(
"mv shellcheck-{version}/shellcheck ~/bin/ && chmod +x ~/bin/shellcheck"
),
"--use-temp-dir",
"shellcheck-{version}.{system}.{arch}.tar.xz",
]
)
2024-07-19 19:36:35 +00:00
if Language.PYTHON in langs:
maybe_pip_install("mypy")
2024-11-02 00:03:01 +00:00
if Language.CSS in langs:
2024-07-19 19:36:35 +00:00
maybe_npm_install("csslint")
2024-11-02 00:03:01 +00:00
if Language.VIM in langs:
2024-07-19 19:36:35 +00:00
maybe_pip_install("vim-vint")
if Language.YAML in langs:
maybe_pip_install("yamllint")
if Language.TEXT in langs:
maybe_npm_install("alex", "write-good")
maybe_pip_install("proselint")
2024-10-01 19:58:43 +00:00
if Language.ANSIBLE in langs:
maybe_pip_install("ansible-lint")
2024-07-19 19:36:35 +00:00
if Language.GO in langs:
# NOTE: Can't use maybe_release_gitter because name has a -
2024-07-19 19:36:35 +00:00
maybe_run(
"release-gitter",
"--git-url",
"https://github.com/golangci/golangci-lint",
"--extract-files",
"golangci-lint-{version}-{system}-{arch}/golangci-lint",
2024-07-19 19:36:35 +00:00
"--exec",
os.path.expanduser(
"mv golangci-lint-{version}-{system}-{arch}/golangci-lint ~/bin/"
),
"--use-temp-dir",
2024-07-19 19:36:35 +00:00
"golangci-lint-{version}-{system}-{arch}.tar.gz",
)
2024-11-02 00:03:01 +00:00
if Language.LUA in langs:
2024-11-11 21:00:48 +00:00
maybe_release_gitter(
selene=[
"--git-url",
"https://github.com/Kampfkarren/selene",
"--exec",
os.path.expanduser("chmod +x ~/bin/selene"),
"--extract-files",
"selene",
"selene-{version}-{system}.zip",
os.path.expanduser("~/bin"),
]
)
2024-07-19 19:36:35 +00:00
if Language.DOCKER in langs:
hadolint_arm64 = "arm64"
if sys.platform == "darwin":
hadolint_arm64 = "x86_64"
maybe_release_gitter(
hadolint=[
2024-07-19 19:36:35 +00:00
"--git-url",
"https://github.com/hadolint/hadolint",
"--map-arch",
f"aarch64={hadolint_arm64}",
"--map-arch",
f"arm64={hadolint_arm64}",
"--exec",
os.path.expanduser(
"mv ~/bin/{} ~/bin/hadolint && chmod +x ~/bin/hadolint"
),
2024-07-19 19:36:35 +00:00
"hadolint-{system}-{arch}",
os.path.expanduser("~/bin"),
]
2024-07-19 19:36:35 +00:00
)
if Language.TERRAFORM in langs:
maybe_release_gitter(
tfsec=[
"--git-url",
"https://github.com/aquasecurity/tfsec",
"--exec",
os.path.expanduser("mv ~/bin/{} ~/bin/tfsec && chmod +x ~/bin/tfsec"),
"tfsec-{system}-{arch}",
os.path.expanduser("~/bin"),
],
tflint=[
"--git-url",
"https://github.com/terraform-linters/tflint",
"--extract-all",
"--exec",
os.path.expanduser("chmod +x ~/bin/tflint"),
"tflint_{system}_{arch}.zip",
os.path.expanduser("~/bin"),
],
2024-07-19 19:36:35 +00:00
)
def install_fixers(langs: set[Language]):
if {
Language.PYTHON,
Language.HTML,
Language.CSS,
Language.WEB,
Language.JSON,
2024-11-02 00:03:01 +00:00
} & langs:
2024-07-19 19:36:35 +00:00
maybe_npm_install("prettier")
if Language.PYTHON in langs:
maybe_pip_install("black", "reorder-python-imports", "isort")
if Language.RUST in langs:
maybe_run("rustup", "component", "add", "rustfmt")
2024-11-02 00:03:01 +00:00
if Language.LUA in langs:
_ = maybe_release_gitter(
stylua=[
"--git-url",
"https://github.com/JohnnyMorganz/StyLua",
2024-11-02 00:03:10 +00:00
"--extract-files",
"stylua",
"--exec",
os.path.expanduser("chmod +x ~/bin/stylua"),
"stylua-{system}-{arch}.zip",
os.path.expanduser("~/bin"),
]
) or maybe_cargo_install("stylua")
if Language.GO in langs:
maybe_go_install(
gofumpt="mvdan.cc/gofumpt@latest",
goimports="golang.org/x/tools/cmd/goimports@latest",
)
2024-07-19 19:36:35 +00:00
def install_debuggers(langs):
if Language.PYTHON in langs:
maybe_pip_install("debugpy")
if Language.GO in langs:
maybe_go_install(dlv="github.com/go-delve/delve/cmd/dlv@latest")
2024-07-19 19:36:35 +00:00
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--ignore-missing", action="store_true")
parser.add_argument("langs", nargs="*", type=Language)
2024-11-02 00:03:21 +00:00
parser.add_argument("--no-language-servers", action="store_true")
2024-09-17 19:35:29 +00:00
parser.add_argument("--no-debuggers", action="store_true")
2024-07-19 19:36:35 +00:00
args = parser.parse_args()
2024-11-02 00:03:21 +00:00
# Release gitter is required for some tools
if not maybe_pip_install("release-gitter"):
# Manual install
maybe_run(
"wget",
"-O",
os.path.expanduser("~/bin/release-gitter"),
"https://git.iamthefij.com/iamthefij/release-gitter/raw/branch/main/release_gitter.py",
)
maybe_run("chmod", "+x", os.path.expanduser("~/bin/release-gitter"))
2024-07-19 19:36:35 +00:00
os.environ["PYTHONPATH"] = ""
if args.ignore_missing:
os.environ["set"] = "+e"
else:
os.environ["set"] = "-e"
langs = set(args.langs or Language)
2024-11-02 00:03:01 +00:00
# Expand meta languages
for lang, aliases in META_LANGS.items():
if lang in langs:
langs.update(aliases)
2024-11-02 00:03:21 +00:00
if not args.no_language_servers:
install_language_servers(langs)
2024-07-19 19:36:35 +00:00
install_linters(langs)
install_fixers(langs)
2024-09-17 19:35:29 +00:00
if not args.no_debuggers:
install_debuggers(langs)
2024-07-19 19:36:35 +00:00
print("DONE")
if __name__ == "__main__":
main()