Merge pull request #108363 from Flakebi/kakoune
kakounePlugins: use vim’s update.py script to generate plugins
This commit is contained in:
commit
e3e59d4ab7
526
maintainers/scripts/pluginupdate.py
Normal file
526
maintainers/scripts/pluginupdate.py
Normal file
@ -0,0 +1,526 @@
|
||||
# Used by pkgs/misc/vim-plugins/update.py and pkgs/applications/editors/kakoune/plugins/update.py
|
||||
|
||||
# format:
|
||||
# $ nix run nixpkgs.python3Packages.black -c black update.py
|
||||
# type-check:
|
||||
# $ nix run nixpkgs.python3Packages.mypy -c mypy update.py
|
||||
# linted:
|
||||
# $ nix run nixpkgs.python3Packages.flake8 -c flake8 --ignore E501,E265 update.py
|
||||
|
||||
import argparse
|
||||
import functools
|
||||
import http
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import traceback
|
||||
import urllib.error
|
||||
import urllib.parse
|
||||
import urllib.request
|
||||
import xml.etree.ElementTree as ET
|
||||
from datetime import datetime
|
||||
from functools import wraps
|
||||
from multiprocessing.dummy import Pool
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Optional, Tuple, Union, Any, Callable
|
||||
from urllib.parse import urljoin, urlparse
|
||||
from tempfile import NamedTemporaryFile
|
||||
|
||||
import git
|
||||
|
||||
ATOM_ENTRY = "{http://www.w3.org/2005/Atom}entry" # " vim gets confused here
|
||||
ATOM_LINK = "{http://www.w3.org/2005/Atom}link" # "
|
||||
ATOM_UPDATED = "{http://www.w3.org/2005/Atom}updated" # "
|
||||
|
||||
|
||||
def retry(ExceptionToCheck: Any, tries: int = 4, delay: float = 3, backoff: float = 2):
|
||||
"""Retry calling the decorated function using an exponential backoff.
|
||||
http://www.saltycrane.com/blog/2009/11/trying-out-retry-decorator-python/
|
||||
original from: http://wiki.python.org/moin/PythonDecoratorLibrary#Retry
|
||||
(BSD licensed)
|
||||
:param ExceptionToCheck: the exception on which to retry
|
||||
:param tries: number of times to try (not retry) before giving up
|
||||
:param delay: initial delay between retries in seconds
|
||||
:param backoff: backoff multiplier e.g. value of 2 will double the delay
|
||||
each retry
|
||||
"""
|
||||
|
||||
def deco_retry(f: Callable) -> Callable:
|
||||
@wraps(f)
|
||||
def f_retry(*args: Any, **kwargs: Any) -> Any:
|
||||
mtries, mdelay = tries, delay
|
||||
while mtries > 1:
|
||||
try:
|
||||
return f(*args, **kwargs)
|
||||
except ExceptionToCheck as e:
|
||||
print(f"{str(e)}, Retrying in {mdelay} seconds...")
|
||||
time.sleep(mdelay)
|
||||
mtries -= 1
|
||||
mdelay *= backoff
|
||||
return f(*args, **kwargs)
|
||||
|
||||
return f_retry # true decorator
|
||||
|
||||
return deco_retry
|
||||
|
||||
|
||||
def make_request(url: str) -> urllib.request.Request:
|
||||
token = os.getenv("GITHUB_API_TOKEN")
|
||||
headers = {}
|
||||
if token is not None:
|
||||
headers["Authorization"] = f"token {token}"
|
||||
return urllib.request.Request(url, headers=headers)
|
||||
|
||||
|
||||
class Repo:
|
||||
def __init__(
|
||||
self, owner: str, name: str, branch: str, alias: Optional[str]
|
||||
) -> None:
|
||||
self.owner = owner
|
||||
self.name = name
|
||||
self.branch = branch
|
||||
self.alias = alias
|
||||
self.redirect: Dict[str, str] = {}
|
||||
|
||||
def url(self, path: str) -> str:
|
||||
return urljoin(f"https://github.com/{self.owner}/{self.name}/", path)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Repo({self.owner}, {self.name})"
|
||||
|
||||
@retry(urllib.error.URLError, tries=4, delay=3, backoff=2)
|
||||
def has_submodules(self) -> bool:
|
||||
try:
|
||||
req = make_request(self.url(f"blob/{self.branch}/.gitmodules"))
|
||||
urllib.request.urlopen(req, timeout=10).close()
|
||||
except urllib.error.HTTPError as e:
|
||||
if e.code == 404:
|
||||
return False
|
||||
else:
|
||||
raise
|
||||
return True
|
||||
|
||||
@retry(urllib.error.URLError, tries=4, delay=3, backoff=2)
|
||||
def latest_commit(self) -> Tuple[str, datetime]:
|
||||
commit_url = self.url(f"commits/{self.branch}.atom")
|
||||
commit_req = make_request(commit_url)
|
||||
with urllib.request.urlopen(commit_req, timeout=10) as req:
|
||||
self.check_for_redirect(commit_url, req)
|
||||
xml = req.read()
|
||||
root = ET.fromstring(xml)
|
||||
latest_entry = root.find(ATOM_ENTRY)
|
||||
assert latest_entry is not None, f"No commits found in repository {self}"
|
||||
commit_link = latest_entry.find(ATOM_LINK)
|
||||
assert commit_link is not None, f"No link tag found feed entry {xml}"
|
||||
url = urlparse(commit_link.get("href"))
|
||||
updated_tag = latest_entry.find(ATOM_UPDATED)
|
||||
assert (
|
||||
updated_tag is not None and updated_tag.text is not None
|
||||
), f"No updated tag found feed entry {xml}"
|
||||
updated = datetime.strptime(updated_tag.text, "%Y-%m-%dT%H:%M:%SZ")
|
||||
return Path(str(url.path)).name, updated
|
||||
|
||||
def check_for_redirect(self, url: str, req: http.client.HTTPResponse):
|
||||
response_url = req.geturl()
|
||||
if url != response_url:
|
||||
new_owner, new_name = (
|
||||
urllib.parse.urlsplit(response_url).path.strip("/").split("/")[:2]
|
||||
)
|
||||
end_line = "\n" if self.alias is None else f" as {self.alias}\n"
|
||||
plugin_line = "{owner}/{name}" + end_line
|
||||
|
||||
old_plugin = plugin_line.format(owner=self.owner, name=self.name)
|
||||
new_plugin = plugin_line.format(owner=new_owner, name=new_name)
|
||||
self.redirect[old_plugin] = new_plugin
|
||||
|
||||
def prefetch_git(self, ref: str) -> str:
|
||||
data = subprocess.check_output(
|
||||
["nix-prefetch-git", "--fetch-submodules", self.url(""), ref]
|
||||
)
|
||||
return json.loads(data)["sha256"]
|
||||
|
||||
def prefetch_github(self, ref: str) -> str:
|
||||
data = subprocess.check_output(
|
||||
["nix-prefetch-url", "--unpack", self.url(f"archive/{ref}.tar.gz")]
|
||||
)
|
||||
return data.strip().decode("utf-8")
|
||||
|
||||
|
||||
class Plugin:
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
commit: str,
|
||||
has_submodules: bool,
|
||||
sha256: str,
|
||||
date: Optional[datetime] = None,
|
||||
) -> None:
|
||||
self.name = name
|
||||
self.commit = commit
|
||||
self.has_submodules = has_submodules
|
||||
self.sha256 = sha256
|
||||
self.date = date
|
||||
|
||||
@property
|
||||
def normalized_name(self) -> str:
|
||||
return self.name.replace(".", "-")
|
||||
|
||||
@property
|
||||
def version(self) -> str:
|
||||
assert self.date is not None
|
||||
return self.date.strftime("%Y-%m-%d")
|
||||
|
||||
def as_json(self) -> Dict[str, str]:
|
||||
copy = self.__dict__.copy()
|
||||
del copy["date"]
|
||||
return copy
|
||||
|
||||
|
||||
class Editor:
|
||||
"""The configuration of the update script."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
root: Path,
|
||||
get_plugins: str,
|
||||
generate_nix: Callable[[List[Tuple[str, str, Plugin]], str], None],
|
||||
default_in: Optional[Path] = None,
|
||||
default_out: Optional[Path] = None,
|
||||
deprecated: Optional[Path] = None,
|
||||
cache_file: Optional[str] = None,
|
||||
):
|
||||
self.name = name
|
||||
self.root = root
|
||||
self.get_plugins = get_plugins
|
||||
self.generate_nix = generate_nix
|
||||
self.default_in = default_in or root.joinpath(f"{name}-plugin-names")
|
||||
self.default_out = default_out or root.joinpath("generated.nix")
|
||||
self.deprecated = deprecated or root.joinpath("deprecated.json")
|
||||
self.cache_file = cache_file or f"{name}-plugin-cache.json"
|
||||
|
||||
|
||||
class CleanEnvironment(object):
|
||||
def __enter__(self) -> None:
|
||||
self.old_environ = os.environ.copy()
|
||||
local_pkgs = str(Path(__file__).parent.parent.parent)
|
||||
os.environ["NIX_PATH"] = f"localpkgs={local_pkgs}"
|
||||
self.empty_config = NamedTemporaryFile()
|
||||
self.empty_config.write(b"{}")
|
||||
self.empty_config.flush()
|
||||
os.environ["NIXPKGS_CONFIG"] = self.empty_config.name
|
||||
|
||||
def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None:
|
||||
os.environ.update(self.old_environ)
|
||||
self.empty_config.close()
|
||||
|
||||
|
||||
def get_current_plugins(editor: Editor) -> List[Plugin]:
|
||||
with CleanEnvironment():
|
||||
out = subprocess.check_output(["nix", "eval", "--json", editor.get_plugins])
|
||||
data = json.loads(out)
|
||||
plugins = []
|
||||
for name, attr in data.items():
|
||||
p = Plugin(name, attr["rev"], attr["submodules"], attr["sha256"])
|
||||
plugins.append(p)
|
||||
return plugins
|
||||
|
||||
|
||||
def prefetch_plugin(
|
||||
user: str,
|
||||
repo_name: str,
|
||||
branch: str,
|
||||
alias: Optional[str],
|
||||
cache: "Optional[Cache]" = None,
|
||||
) -> Tuple[Plugin, Dict[str, str]]:
|
||||
repo = Repo(user, repo_name, branch, alias)
|
||||
commit, date = repo.latest_commit()
|
||||
has_submodules = repo.has_submodules()
|
||||
cached_plugin = cache[commit] if cache else None
|
||||
if cached_plugin is not None:
|
||||
cached_plugin.name = alias or repo_name
|
||||
cached_plugin.date = date
|
||||
return cached_plugin, repo.redirect
|
||||
|
||||
print(f"prefetch {user}/{repo_name}")
|
||||
if has_submodules:
|
||||
sha256 = repo.prefetch_git(commit)
|
||||
else:
|
||||
sha256 = repo.prefetch_github(commit)
|
||||
|
||||
return (
|
||||
Plugin(alias or repo_name, commit, has_submodules, sha256, date=date),
|
||||
repo.redirect,
|
||||
)
|
||||
|
||||
|
||||
def fetch_plugin_from_pluginline(plugin_line: str) -> Plugin:
|
||||
plugin, _ = prefetch_plugin(*parse_plugin_line(plugin_line))
|
||||
return plugin
|
||||
|
||||
|
||||
def print_download_error(plugin: str, ex: Exception):
|
||||
print(f"{plugin}: {ex}", file=sys.stderr)
|
||||
ex_traceback = ex.__traceback__
|
||||
tb_lines = [
|
||||
line.rstrip("\n")
|
||||
for line in traceback.format_exception(ex.__class__, ex, ex_traceback)
|
||||
]
|
||||
print("\n".join(tb_lines))
|
||||
|
||||
|
||||
def check_results(
|
||||
results: List[Tuple[str, str, Union[Exception, Plugin], Dict[str, str]]]
|
||||
) -> Tuple[List[Tuple[str, str, Plugin]], Dict[str, str]]:
|
||||
failures: List[Tuple[str, Exception]] = []
|
||||
plugins = []
|
||||
redirects: Dict[str, str] = {}
|
||||
for (owner, name, result, redirect) in results:
|
||||
if isinstance(result, Exception):
|
||||
failures.append((name, result))
|
||||
else:
|
||||
plugins.append((owner, name, result))
|
||||
redirects.update(redirect)
|
||||
|
||||
print(f"{len(results) - len(failures)} plugins were checked", end="")
|
||||
if len(failures) == 0:
|
||||
print()
|
||||
return plugins, redirects
|
||||
else:
|
||||
print(f", {len(failures)} plugin(s) could not be downloaded:\n")
|
||||
|
||||
for (plugin, exception) in failures:
|
||||
print_download_error(plugin, exception)
|
||||
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def parse_plugin_line(line: str) -> Tuple[str, str, str, Optional[str]]:
|
||||
branch = "master"
|
||||
alias = None
|
||||
name, repo = line.split("/")
|
||||
if " as " in repo:
|
||||
repo, alias = repo.split(" as ")
|
||||
alias = alias.strip()
|
||||
if "@" in repo:
|
||||
repo, branch = repo.split("@")
|
||||
|
||||
return (name.strip(), repo.strip(), branch.strip(), alias)
|
||||
|
||||
|
||||
def load_plugin_spec(plugin_file: str) -> List[Tuple[str, str, str, Optional[str]]]:
|
||||
plugins = []
|
||||
with open(plugin_file) as f:
|
||||
for line in f:
|
||||
plugin = parse_plugin_line(line)
|
||||
if not plugin[0]:
|
||||
msg = f"Invalid repository {line}, must be in the format owner/repo[ as alias]"
|
||||
print(msg, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
plugins.append(plugin)
|
||||
return plugins
|
||||
|
||||
|
||||
def get_cache_path(cache_file_name: str) -> Optional[Path]:
|
||||
xdg_cache = os.environ.get("XDG_CACHE_HOME", None)
|
||||
if xdg_cache is None:
|
||||
home = os.environ.get("HOME", None)
|
||||
if home is None:
|
||||
return None
|
||||
xdg_cache = str(Path(home, ".cache"))
|
||||
|
||||
return Path(xdg_cache, cache_file_name)
|
||||
|
||||
|
||||
class Cache:
|
||||
def __init__(self, initial_plugins: List[Plugin], cache_file_name: str) -> None:
|
||||
self.cache_file = get_cache_path(cache_file_name)
|
||||
|
||||
downloads = {}
|
||||
for plugin in initial_plugins:
|
||||
downloads[plugin.commit] = plugin
|
||||
downloads.update(self.load())
|
||||
self.downloads = downloads
|
||||
|
||||
def load(self) -> Dict[str, Plugin]:
|
||||
if self.cache_file is None or not self.cache_file.exists():
|
||||
return {}
|
||||
|
||||
downloads: Dict[str, Plugin] = {}
|
||||
with open(self.cache_file) as f:
|
||||
data = json.load(f)
|
||||
for attr in data.values():
|
||||
p = Plugin(
|
||||
attr["name"], attr["commit"], attr["has_submodules"], attr["sha256"]
|
||||
)
|
||||
downloads[attr["commit"]] = p
|
||||
return downloads
|
||||
|
||||
def store(self) -> None:
|
||||
if self.cache_file is None:
|
||||
return
|
||||
|
||||
os.makedirs(self.cache_file.parent, exist_ok=True)
|
||||
with open(self.cache_file, "w+") as f:
|
||||
data = {}
|
||||
for name, attr in self.downloads.items():
|
||||
data[name] = attr.as_json()
|
||||
json.dump(data, f, indent=4, sort_keys=True)
|
||||
|
||||
def __getitem__(self, key: str) -> Optional[Plugin]:
|
||||
return self.downloads.get(key, None)
|
||||
|
||||
def __setitem__(self, key: str, value: Plugin) -> None:
|
||||
self.downloads[key] = value
|
||||
|
||||
|
||||
def prefetch(
|
||||
args: Tuple[str, str, str, Optional[str]], cache: Cache
|
||||
) -> Tuple[str, str, Union[Exception, Plugin], dict]:
|
||||
assert len(args) == 4
|
||||
owner, repo, branch, alias = args
|
||||
try:
|
||||
plugin, redirect = prefetch_plugin(owner, repo, branch, alias, cache)
|
||||
cache[plugin.commit] = plugin
|
||||
return (owner, repo, plugin, redirect)
|
||||
except Exception as e:
|
||||
return (owner, repo, e, {})
|
||||
|
||||
|
||||
def rewrite_input(
|
||||
input_file: Path,
|
||||
deprecated: Path,
|
||||
redirects: Dict[str, str] = None,
|
||||
append: Tuple = (),
|
||||
):
|
||||
with open(input_file, "r") as f:
|
||||
lines = f.readlines()
|
||||
|
||||
lines.extend(append)
|
||||
|
||||
if redirects:
|
||||
lines = [redirects.get(line, line) for line in lines]
|
||||
|
||||
cur_date_iso = datetime.now().strftime("%Y-%m-%d")
|
||||
with open(deprecated, "r") as f:
|
||||
deprecations = json.load(f)
|
||||
for old, new in redirects.items():
|
||||
old_plugin = fetch_plugin_from_pluginline(old)
|
||||
new_plugin = fetch_plugin_from_pluginline(new)
|
||||
if old_plugin.normalized_name != new_plugin.normalized_name:
|
||||
deprecations[old_plugin.normalized_name] = {
|
||||
"new": new_plugin.normalized_name,
|
||||
"date": cur_date_iso,
|
||||
}
|
||||
with open(deprecated, "w") as f:
|
||||
json.dump(deprecations, f, indent=4, sort_keys=True)
|
||||
|
||||
lines = sorted(lines, key=str.casefold)
|
||||
|
||||
with open(input_file, "w") as f:
|
||||
f.writelines(lines)
|
||||
|
||||
|
||||
def parse_args(editor: Editor):
|
||||
parser = argparse.ArgumentParser(
|
||||
description=(
|
||||
f"Updates nix derivations for {editor.name} plugins"
|
||||
f"By default from {editor.default_in} to {editor.default_out}"
|
||||
)
|
||||
)
|
||||
parser.add_argument(
|
||||
"--add",
|
||||
dest="add_plugins",
|
||||
default=[],
|
||||
action="append",
|
||||
help=f"Plugin to add to {editor.name}Plugins from Github in the form owner/repo",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--input-names",
|
||||
"-i",
|
||||
dest="input_file",
|
||||
default=editor.default_in,
|
||||
help="A list of plugins in the form owner/repo",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--out",
|
||||
"-o",
|
||||
dest="outfile",
|
||||
default=editor.default_out,
|
||||
help="Filename to save generated nix code",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--proc",
|
||||
"-p",
|
||||
dest="proc",
|
||||
type=int,
|
||||
default=30,
|
||||
help="Number of concurrent processes to spawn.",
|
||||
)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def commit(repo: git.Repo, message: str, files: List[Path]) -> None:
|
||||
repo.index.add([str(f.resolve()) for f in files])
|
||||
|
||||
if repo.index.diff("HEAD"):
|
||||
print(f'committing to nixpkgs "{message}"')
|
||||
repo.index.commit(message)
|
||||
else:
|
||||
print("no changes in working tree to commit")
|
||||
|
||||
|
||||
def get_update(input_file: str, outfile: str, proc: int, editor: Editor):
|
||||
cache: Cache = Cache(get_current_plugins(editor), editor.cache_file)
|
||||
_prefetch = functools.partial(prefetch, cache=cache)
|
||||
|
||||
def update() -> dict:
|
||||
plugin_names = load_plugin_spec(input_file)
|
||||
|
||||
try:
|
||||
pool = Pool(processes=proc)
|
||||
results = pool.map(_prefetch, plugin_names)
|
||||
finally:
|
||||
cache.store()
|
||||
|
||||
plugins, redirects = check_results(results)
|
||||
|
||||
editor.generate_nix(plugins, outfile)
|
||||
|
||||
return redirects
|
||||
|
||||
return update
|
||||
|
||||
|
||||
def update_plugins(editor: Editor):
|
||||
"""The main entry function of this module. All input arguments are grouped in the `Editor`."""
|
||||
|
||||
args = parse_args(editor)
|
||||
nixpkgs_repo = git.Repo(editor.root, search_parent_directories=True)
|
||||
update = get_update(args.input_file, args.outfile, args.proc, editor)
|
||||
|
||||
redirects = update()
|
||||
rewrite_input(args.input_file, editor.deprecated, redirects)
|
||||
commit(nixpkgs_repo, f"{editor.name}Plugins: update", [args.outfile])
|
||||
|
||||
if redirects:
|
||||
update()
|
||||
commit(
|
||||
nixpkgs_repo,
|
||||
f"{editor.name}Plugins: resolve github repository redirects",
|
||||
[args.outfile, args.input_file, editor.deprecated],
|
||||
)
|
||||
|
||||
for plugin_line in args.add_plugins:
|
||||
rewrite_input(args.input_fil, editor.deprecated, append=(plugin_line + "\n",))
|
||||
update()
|
||||
plugin = fetch_plugin_from_pluginline(plugin_line)
|
||||
commit(
|
||||
nixpkgs_repo,
|
||||
"{editor}Plugins.{name}: init at {version}".format(
|
||||
editor=editor.name, name=plugin.normalized_name, version=plugin.version
|
||||
),
|
||||
[args.outfile, args.input_file],
|
||||
)
|
46
pkgs/applications/editors/kakoune/plugins/aliases.nix
Normal file
46
pkgs/applications/editors/kakoune/plugins/aliases.nix
Normal file
@ -0,0 +1,46 @@
|
||||
# Deprecated aliases - for backward compatibility
|
||||
|
||||
lib: overriden:
|
||||
|
||||
with overriden;
|
||||
|
||||
let
|
||||
# Removing recurseForDerivation prevents derivations of aliased attribute
|
||||
# set to appear while listing all the packages available.
|
||||
removeRecurseForDerivations = alias: with lib;
|
||||
if alias.recurseForDerivations or false then
|
||||
removeAttrs alias ["recurseForDerivations"]
|
||||
else alias;
|
||||
|
||||
# Disabling distribution prevents top-level aliases for non-recursed package
|
||||
# sets from building on Hydra.
|
||||
removeDistribute = alias: with lib;
|
||||
if isDerivation alias then
|
||||
dontDistribute alias
|
||||
else alias;
|
||||
|
||||
# Make sure that we are not shadowing something from
|
||||
# all-packages.nix.
|
||||
checkInPkgs = n: alias: if builtins.hasAttr n overriden
|
||||
then throw "Alias ${n} is still in kakounePlugins"
|
||||
else alias;
|
||||
|
||||
mapAliases = aliases:
|
||||
lib.mapAttrs (n: alias: removeDistribute
|
||||
(removeRecurseForDerivations
|
||||
(checkInPkgs n alias)))
|
||||
aliases;
|
||||
|
||||
deprecations = lib.mapAttrs (old: info:
|
||||
throw "${old} was renamed to ${info.new} on ${info.date}. Please update to ${info.new}."
|
||||
) (builtins.fromJSON (builtins.readFile ./deprecated.json));
|
||||
|
||||
in
|
||||
mapAliases ({
|
||||
kak-auto-pairs = auto-pairs-kak; # backwards compat, added 2021-01-04
|
||||
kak-buffers = kakoune-buffers; # backwards compat, added 2021-01-04
|
||||
kak-fzf = fzf-kak; # backwards compat, added 2021-01-04
|
||||
kak-powerline = powerline-kak; # backwards compat, added 2021-01-04
|
||||
kak-prelude = prelude-kak; # backwards compat, added 2021-01-04
|
||||
kak-vertical-selection = kakoune-vertical-selection; # backwards compat, added 2021-01-04
|
||||
} // deprecations)
|
@ -0,0 +1,33 @@
|
||||
{ lib, stdenv, rtpPath ? "share/kak/autoload/plugins" }:
|
||||
rec {
|
||||
buildKakounePlugin = attrs@{
|
||||
name ? "${attrs.pname}-${attrs.version}",
|
||||
namePrefix ? "kakplugin-",
|
||||
src,
|
||||
unpackPhase ? "",
|
||||
configurePhase ? "",
|
||||
buildPhase ? "",
|
||||
preInstall ? "",
|
||||
postInstall ? "",
|
||||
path ? lib.getName name,
|
||||
...
|
||||
}:
|
||||
stdenv.mkDerivation ((builtins.removeAttrs attrs [ "namePrefix" "path" ]) // {
|
||||
name = namePrefix + name;
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
target=$out/${rtpPath}/${path}
|
||||
mkdir -p $out/${rtpPath}
|
||||
cp -r . $target
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
});
|
||||
|
||||
buildKakounePluginFrom2Nix = attrs: buildKakounePlugin ({
|
||||
buildPhase = ":";
|
||||
configurePhase = ":";
|
||||
} // attrs);
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
{ lib, stdenv, fetchFromGitLab }:
|
||||
|
||||
stdenv.mkDerivation {
|
||||
name = "case.kak";
|
||||
version = "unstable-2020-04-06";
|
||||
|
||||
src = fetchFromGitLab {
|
||||
owner = "FlyingWombat";
|
||||
repo = "case.kak";
|
||||
rev = "6f1511820aa3abfa118e0f856118adc8113e2185";
|
||||
sha256 = "002njrlwgakqgp74wivbppr9qyn57dn4n5bxkr6k6nglk9qndwdp";
|
||||
};
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/share/kak/autoload/plugins
|
||||
cp -r rc/case.kak $out/share/kak/autoload/plugins
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
description = "Case convention conversion for Kakoune";
|
||||
homepage = "https://gitlab.com/FlyingWombat/case.kak";
|
||||
license = licenses.unlicense;
|
||||
maintainers = with maintainers; [ eraserhd ];
|
||||
platform = platforms.all;
|
||||
};
|
||||
}
|
||||
|
@ -1,17 +1,25 @@
|
||||
{ pkgs, parinfer-rust, rep, kak-lsp }:
|
||||
{ callPackage, config, kakouneUtils, lib }:
|
||||
|
||||
{
|
||||
inherit parinfer-rust rep kak-lsp;
|
||||
let
|
||||
|
||||
case-kak = pkgs.callPackage ./case.kak.nix { };
|
||||
kak-ansi = pkgs.callPackage ./kak-ansi.nix { };
|
||||
kak-auto-pairs = pkgs.callPackage ./kak-auto-pairs.nix { };
|
||||
kak-buffers = pkgs.callPackage ./kak-buffers.nix { };
|
||||
kak-fzf = pkgs.callPackage ./kak-fzf.nix { };
|
||||
kak-plumb = pkgs.callPackage ./kak-plumb.nix { };
|
||||
kak-powerline = pkgs.callPackage ./kak-powerline.nix { };
|
||||
kak-prelude = pkgs.callPackage ./kak-prelude.nix { };
|
||||
kak-vertical-selection = pkgs.callPackage ./kak-vertical-selection.nix { };
|
||||
openscad-kak = pkgs.callPackage ./openscad.kak.nix { };
|
||||
quickscope-kak = pkgs.callPackage ./quickscope.kak.nix { };
|
||||
}
|
||||
inherit (kakouneUtils.override {}) buildKakounePluginFrom2Nix;
|
||||
|
||||
plugins = callPackage ./generated.nix {
|
||||
inherit buildKakounePluginFrom2Nix overrides;
|
||||
};
|
||||
|
||||
# TL;DR
|
||||
# * Add your plugin to ./kakoune-plugin-names
|
||||
# * run ./update.py
|
||||
#
|
||||
# If additional modifications to the build process are required,
|
||||
# add to ./overrides.nix.
|
||||
overrides = callPackage ./overrides.nix {
|
||||
inherit buildKakounePluginFrom2Nix;
|
||||
};
|
||||
|
||||
aliases = lib.optionalAttrs (config.allowAliases or true) (import ./aliases.nix lib plugins);
|
||||
|
||||
in
|
||||
|
||||
plugins // aliases
|
||||
|
@ -0,0 +1 @@
|
||||
{}
|
211
pkgs/applications/editors/kakoune/plugins/generated.nix
Normal file
211
pkgs/applications/editors/kakoune/plugins/generated.nix
Normal file
@ -0,0 +1,211 @@
|
||||
# This file has been generated by ./pkgs/applications/editors/kakoune/plugins/update.py. Do not edit!
|
||||
{ lib, buildKakounePluginFrom2Nix, fetchFromGitHub, overrides ? (self: super: {}) }:
|
||||
let
|
||||
packages = ( self:
|
||||
{
|
||||
active-window-kak = buildKakounePluginFrom2Nix {
|
||||
pname = "active-window-kak";
|
||||
version = "2020-05-13";
|
||||
src = fetchFromGitHub {
|
||||
owner = "greenfork";
|
||||
repo = "active-window.kak";
|
||||
rev = "988db69cfbb88bd741d089bb43b0be551693e7c1";
|
||||
sha256 = "1fv1cp9q212gamf9z2papl5xcl2w31fpcmbgdzbxcxdl1pvfsqp8";
|
||||
};
|
||||
meta.homepage = "https://github.com/greenfork/active-window.kak/";
|
||||
};
|
||||
|
||||
auto-pairs-kak = buildKakounePluginFrom2Nix {
|
||||
pname = "auto-pairs-kak";
|
||||
version = "2020-10-04";
|
||||
src = fetchFromGitHub {
|
||||
owner = "alexherbo2";
|
||||
repo = "auto-pairs.kak";
|
||||
rev = "fd735ec149ef0d9ca5f628a95b1e52858b5afbdc";
|
||||
sha256 = "07795kv9njlnp6mckwv141ny2ns6wyf5r0dfjaxh9ngd105zgif1";
|
||||
};
|
||||
meta.homepage = "https://github.com/alexherbo2/auto-pairs.kak/";
|
||||
};
|
||||
|
||||
connect-kak = buildKakounePluginFrom2Nix {
|
||||
pname = "connect-kak";
|
||||
version = "2021-02-13";
|
||||
src = fetchFromGitHub {
|
||||
owner = "alexherbo2";
|
||||
repo = "connect.kak";
|
||||
rev = "0858c0e50c6ca6d214fb088f052385a242548e83";
|
||||
sha256 = "1w4pwybg3v916hcyc49gz0blygv54ivv81x8fxp44ck0sy98idr3";
|
||||
};
|
||||
meta.homepage = "https://github.com/alexherbo2/connect.kak/";
|
||||
};
|
||||
|
||||
fzf-kak = buildKakounePluginFrom2Nix {
|
||||
pname = "fzf-kak";
|
||||
version = "2021-01-27";
|
||||
src = fetchFromGitHub {
|
||||
owner = "andreyorst";
|
||||
repo = "fzf.kak";
|
||||
rev = "e10de405e2a98e910d0808059200d206ba80f865";
|
||||
sha256 = "1hbsm1k8k0cgv7gxqicvnl22n2lb1plhkanniggk694gll22lq68";
|
||||
};
|
||||
meta.homepage = "https://github.com/andreyorst/fzf.kak/";
|
||||
};
|
||||
|
||||
kakoune-buffer-switcher = buildKakounePluginFrom2Nix {
|
||||
pname = "kakoune-buffer-switcher";
|
||||
version = "2020-12-27";
|
||||
src = fetchFromGitHub {
|
||||
owner = "occivink";
|
||||
repo = "kakoune-buffer-switcher";
|
||||
rev = "6a27c45db87a23070c34fab36d2f8d812cd002a6";
|
||||
sha256 = "1rmwy317908v8p54806m721bpzm8sgygb9abri34537ka6r05y5j";
|
||||
};
|
||||
meta.homepage = "https://github.com/occivink/kakoune-buffer-switcher/";
|
||||
};
|
||||
|
||||
kakoune-buffers = buildKakounePluginFrom2Nix {
|
||||
pname = "kakoune-buffers";
|
||||
version = "2020-06-11";
|
||||
src = fetchFromGitHub {
|
||||
owner = "Delapouite";
|
||||
repo = "kakoune-buffers";
|
||||
rev = "67959fbad727ba8470fe8cd6361169560f4fb532";
|
||||
sha256 = "09prhzz4yzf6ryw0npd1gpcfp77681vgawpp1ilfvbf25xgbbz33";
|
||||
};
|
||||
meta.homepage = "https://github.com/Delapouite/kakoune-buffers/";
|
||||
};
|
||||
|
||||
kakoune-easymotion = buildKakounePluginFrom2Nix {
|
||||
pname = "kakoune-easymotion";
|
||||
version = "2020-03-09";
|
||||
src = fetchFromGitHub {
|
||||
owner = "danr";
|
||||
repo = "kakoune-easymotion";
|
||||
rev = "0ca75450023a149efc70e8e383e459b571355c70";
|
||||
sha256 = "15czvl0qj2k767pysr6xk2v31mkhvcbmv76xs2a8yrslchms70b5";
|
||||
};
|
||||
meta.homepage = "https://github.com/danr/kakoune-easymotion/";
|
||||
};
|
||||
|
||||
kakoune-extra-filetypes = buildKakounePluginFrom2Nix {
|
||||
pname = "kakoune-extra-filetypes";
|
||||
version = "2021-01-15";
|
||||
src = fetchFromGitHub {
|
||||
owner = "kakoune-editor";
|
||||
repo = "kakoune-extra-filetypes";
|
||||
rev = "c6f8aaccd8c9cd6b487964c8943416e21fbe7c18";
|
||||
sha256 = "1vkff8xbycfgxv8x09cvc79qcg5fdzn2x77mbmifmkq236khrwrg";
|
||||
};
|
||||
meta.homepage = "https://github.com/kakoune-editor/kakoune-extra-filetypes/";
|
||||
};
|
||||
|
||||
kakoune-rainbow = buildKakounePluginFrom2Nix {
|
||||
pname = "kakoune-rainbow";
|
||||
version = "2020-09-01";
|
||||
src = fetchFromGitHub {
|
||||
owner = "listentolist";
|
||||
repo = "kakoune-rainbow";
|
||||
rev = "d09103e8d268cf4621215bf162a0244c9482be3c";
|
||||
sha256 = "1i3id7xw0j4z1a14mscr68ckpgvcwsjpl86lr864wy7w7qcmblx6";
|
||||
};
|
||||
meta.homepage = "https://github.com/listentolist/kakoune-rainbow/";
|
||||
};
|
||||
|
||||
kakoune-registers = buildKakounePluginFrom2Nix {
|
||||
pname = "kakoune-registers";
|
||||
version = "2020-06-19";
|
||||
src = fetchFromGitHub {
|
||||
owner = "Delapouite";
|
||||
repo = "kakoune-registers";
|
||||
rev = "9531947baecd83c1d4c3bea0adf10f4462f1e120";
|
||||
sha256 = "08v9ndghh7wvr8rsrqm05gksk9ai5vnwvw9gwqasbppb48cv4a8c";
|
||||
};
|
||||
meta.homepage = "https://github.com/Delapouite/kakoune-registers/";
|
||||
};
|
||||
|
||||
kakoune-vertical-selection = buildKakounePluginFrom2Nix {
|
||||
pname = "kakoune-vertical-selection";
|
||||
version = "2019-04-11";
|
||||
src = fetchFromGitHub {
|
||||
owner = "occivink";
|
||||
repo = "kakoune-vertical-selection";
|
||||
rev = "c420f8b867ce47375fac303886e31623669a42b7";
|
||||
sha256 = "13jdyd2j45wvgqvxdzw9zww14ly93bqjb6700zzxj7mkbiff6wsb";
|
||||
};
|
||||
meta.homepage = "https://github.com/occivink/kakoune-vertical-selection/";
|
||||
};
|
||||
|
||||
openscad-kak = buildKakounePluginFrom2Nix {
|
||||
pname = "openscad-kak";
|
||||
version = "2020-12-10";
|
||||
src = fetchFromGitHub {
|
||||
owner = "mayjs";
|
||||
repo = "openscad.kak";
|
||||
rev = "ba51bbdcd96ccf94bb9239bef1481b6f37125849";
|
||||
sha256 = "15dybd6dnnwla6mj8sw83nwd62para1syxzifznl6rz6kp8vqjjj";
|
||||
};
|
||||
meta.homepage = "https://github.com/mayjs/openscad.kak/";
|
||||
};
|
||||
|
||||
powerline-kak = buildKakounePluginFrom2Nix {
|
||||
pname = "powerline-kak";
|
||||
version = "2021-02-15";
|
||||
src = fetchFromGitHub {
|
||||
owner = "jdugan6240";
|
||||
repo = "powerline.kak";
|
||||
rev = "322a760daa099d519ff50d14c29b27f3e2af00d1";
|
||||
sha256 = "0mb8f8p6g75p05ifp45i0gbq2mib8c8giz7r1xfd0yrwspp4aksc";
|
||||
};
|
||||
meta.homepage = "https://github.com/jdugan6240/powerline.kak/";
|
||||
};
|
||||
|
||||
prelude-kak = buildKakounePluginFrom2Nix {
|
||||
pname = "prelude-kak";
|
||||
version = "2020-09-06";
|
||||
src = fetchFromGitHub {
|
||||
owner = "alexherbo2";
|
||||
repo = "prelude.kak";
|
||||
rev = "f1e0f4d5cb62a36924e3f8ba6824d6aed8c19d23";
|
||||
sha256 = "1pncr8azqvl2z9yvzhc68p1s9fld8cvak8yz88zgrp5ypx2cxl8c";
|
||||
};
|
||||
meta.homepage = "https://github.com/alexherbo2/prelude.kak/";
|
||||
};
|
||||
|
||||
replace-mode-kak = buildKakounePluginFrom2Nix {
|
||||
pname = "replace-mode-kak";
|
||||
version = "2020-10-07";
|
||||
src = fetchFromGitHub {
|
||||
owner = "alexherbo2";
|
||||
repo = "replace-mode.kak";
|
||||
rev = "5f4c73cdbaf5aeb964ee35ad4b9081b233af90c0";
|
||||
sha256 = "1cmylx99bm7jwfb4hclb69sdc4n8f29ssyy2byjiw53ni9rnc8q0";
|
||||
};
|
||||
meta.homepage = "https://github.com/alexherbo2/replace-mode.kak/";
|
||||
};
|
||||
|
||||
sleuth-kak = buildKakounePluginFrom2Nix {
|
||||
pname = "sleuth-kak";
|
||||
version = "2020-11-06";
|
||||
src = fetchFromGitHub {
|
||||
owner = "alexherbo2";
|
||||
repo = "sleuth.kak";
|
||||
rev = "911db8bd208ad0d289b8fa15a2ac665ff39bd6bd";
|
||||
sha256 = "0g41c0038fpmihqva71xl4vfbmvsp13i47gp6fnmaikajpynzc51";
|
||||
};
|
||||
meta.homepage = "https://github.com/alexherbo2/sleuth.kak/";
|
||||
};
|
||||
|
||||
tabs-kak = buildKakounePluginFrom2Nix {
|
||||
pname = "tabs-kak";
|
||||
version = "2021-02-16";
|
||||
src = fetchFromGitHub {
|
||||
owner = "enricozb";
|
||||
repo = "tabs.kak";
|
||||
rev = "1aaa8cd89e404cbbd76d44ff8089de0951612fbf";
|
||||
sha256 = "0dfz6j6yxl65jbh4xvpiy2abr2sdjyalynzhl28y7l1gzqv4ni3j";
|
||||
};
|
||||
meta.homepage = "https://github.com/enricozb/tabs.kak/";
|
||||
};
|
||||
|
||||
});
|
||||
in lib.fix' (lib.extends overrides packages)
|
@ -1,32 +0,0 @@
|
||||
{ lib, stdenv, fetchFromGitHub }:
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
name = "kak-ansi";
|
||||
version = "0.2.1";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "eraserhd";
|
||||
repo = "kak-ansi";
|
||||
rev = "v${version}";
|
||||
sha256 = "0ddjih8hfyf6s4g7y46p1355kklaw1ydzzh61141i0r45wyb2d0d";
|
||||
};
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin $out/share/kak/autoload/plugins/
|
||||
cp kak-ansi-filter $out/bin/
|
||||
# Hard-code path of filter and don't try to build when Kakoune boots
|
||||
sed '
|
||||
/^declare-option.* ansi_filter /i\
|
||||
declare-option -hidden str ansi_filter %{'"$out"'/bin/kak-ansi-filter}
|
||||
/^declare-option.* ansi_filter /,/^}/d
|
||||
' rc/ansi.kak >$out/share/kak/autoload/plugins/ansi.kak
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
description = "Kakoune support for rendering ANSI code";
|
||||
homepage = "https://github.com/eraserhd/kak-ansi";
|
||||
license = licenses.unlicense;
|
||||
maintainers = with maintainers; [ eraserhd ];
|
||||
platforms = platforms.all;
|
||||
};
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
{ lib, stdenv, fetchFromGitHub }:
|
||||
stdenv.mkDerivation {
|
||||
name = "kak-auto-pairs";
|
||||
version = "2020-07-14";
|
||||
src = fetchFromGitHub {
|
||||
owner = "alexherbo2";
|
||||
repo = "auto-pairs.kak";
|
||||
rev = "5b4b3b723c34c8b7f40cee60868204974349bf9f";
|
||||
sha256 = "1wgrv03f1lkzflbbaz8n23glij5rvfxf8pcqysd668mbx1hcrk9i";
|
||||
};
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/share/kak/autoload/plugins
|
||||
cp -r rc $out/share/kak/autoload/plugins/auto-pairs
|
||||
'';
|
||||
|
||||
meta = with lib;
|
||||
{ description = "Kakoune extension to enable automatic closing of pairs";
|
||||
homepage = "https://github.com/alexherbo2/auto-pairs.kak";
|
||||
license = licenses.unlicense;
|
||||
maintainers = with maintainers; [ nrdxp ];
|
||||
platform = platforms.all;
|
||||
};
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
{ stdenv, fetchFromGitHub, lib }:
|
||||
stdenv.mkDerivation {
|
||||
name = "kak-buffers";
|
||||
version = "2019-04-03";
|
||||
src = fetchFromGitHub {
|
||||
owner = "Delapouite";
|
||||
repo = "kakoune-buffers";
|
||||
rev = "3b35b23ac2be661a37c085d34dd04d066450f757";
|
||||
sha256 = "0f3g0v1sjinii3ig9753jjj35v2km4h9bcfw9xgzwz8b10d75bax";
|
||||
};
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/share/kak/autoload/plugins
|
||||
cp -r buffers.kak $out/share/kak/autoload/plugins
|
||||
'';
|
||||
|
||||
meta = with lib;
|
||||
{ description = "Ease navigation between opened buffers in Kakoune";
|
||||
homepage = "https://github.com/Delapouite/kakoune-buffers";
|
||||
license = licenses.mit;
|
||||
maintainers = with maintainers; [ nrdxp ];
|
||||
platform = platforms.all;
|
||||
};
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
{ lib, stdenv, fetchFromGitHub, fzf }:
|
||||
|
||||
assert lib.asserts.assertOneOf "fzf" fzf.pname [ "fzf" "skim" ];
|
||||
|
||||
stdenv.mkDerivation {
|
||||
name = "kak-fzf";
|
||||
version = "2020-07-26";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "andreyorst";
|
||||
repo = "fzf.kak";
|
||||
rev = "f23daa698ad95493fbd675ae153e3cac13ef34e9";
|
||||
hash = "sha256-BfXHTJ371ThOizMI/4BAbdJoaltGSP586hz4HqX1KWA=";
|
||||
};
|
||||
|
||||
configurePhase = ''
|
||||
if [[ -x "${fzf}/bin/fzf" ]]; then
|
||||
fzfImpl='${fzf}/bin/fzf'
|
||||
else
|
||||
fzfImpl='${fzf}/bin/sk'
|
||||
fi
|
||||
|
||||
substituteInPlace rc/fzf.kak \
|
||||
--replace \'fzf\' \'"$fzfImpl"\'
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/share/kak/autoload/plugins
|
||||
cp -r rc $out/share/kak/autoload/plugins/fzf
|
||||
'';
|
||||
|
||||
meta = with lib;
|
||||
{ description = "Kakoune plugin that brings integration with fzf";
|
||||
homepage = "https://github.com/andreyorst/fzf.kak";
|
||||
license = licenses.mit;
|
||||
maintainers = with maintainers; [ nrdxp ];
|
||||
platform = platforms.all;
|
||||
};
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
{ lib, stdenv, fetchFromGitHub, kakoune-unwrapped, plan9port, ... }:
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "kak-plumb";
|
||||
version = "0.1.1";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "eraserhd";
|
||||
repo = "kak-plumb";
|
||||
rev = "v${version}";
|
||||
sha256 = "1rz6pr786slnf1a78m3sj09axr4d2lb5rg7sfa4mfg1zcjh06ps6";
|
||||
};
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin $out/share/kak/autoload/plugins/
|
||||
substitute rc/plumb.kak $out/share/kak/autoload/plugins/plumb.kak \
|
||||
--replace '9 plumb' '${plan9port}/bin/9 plumb'
|
||||
substitute edit-client $out/bin/edit-client \
|
||||
--replace '9 9p' '${plan9port}/bin/9 9p' \
|
||||
--replace 'kak -p' '${kakoune-unwrapped}/bin/kak -p'
|
||||
chmod +x $out/bin/edit-client
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
description = "Kakoune integration with the Plan 9 plumber";
|
||||
homepage = "https://github.com/eraserhd/kak-plumb";
|
||||
license = licenses.unlicense;
|
||||
maintainers = with maintainers; [ eraserhd ];
|
||||
platforms = platforms.all;
|
||||
};
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
{ stdenv, git, fetchFromGitHub, lib }:
|
||||
stdenv.mkDerivation {
|
||||
name = "kak-powerline";
|
||||
version = "2020-08-22";
|
||||
src = fetchFromGitHub {
|
||||
owner = "jdugan6240";
|
||||
repo = "powerline.kak";
|
||||
rev = "d641b2cd8024f872bcda23f9256e7aff36da02ae";
|
||||
sha256 = "65948f5ef3ab2f46f6d186ad752665c251d887631d439949decc2654a67958a4";
|
||||
};
|
||||
|
||||
configurePhase = ''
|
||||
substituteInPlace rc/modules/git.kak \
|
||||
--replace \'git\' \'${git}/bin/git\'
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/share/kak/autoload/plugins
|
||||
cp -r rc $out/share/kak/autoload/plugins/powerline
|
||||
'';
|
||||
|
||||
meta = with lib;
|
||||
{ description = "Kakoune modeline, but with passion";
|
||||
homepage = "https://github.com/jdugan6240/powerline.kak";
|
||||
license = licenses.mit;
|
||||
maintainers = with maintainers; [ nrdxp ];
|
||||
platform = platforms.all;
|
||||
};
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
{ lib, stdenv, fetchFromGitHub }:
|
||||
stdenv.mkDerivation {
|
||||
name = "kak-prelude";
|
||||
version = "2020-06-09";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "alexherbo2";
|
||||
repo = "prelude.kak";
|
||||
rev = "f1e0f4d5cb62a36924e3f8ba6824d6aed8c19d23";
|
||||
sha256 = "1pncr8azqvl2z9yvzhc68p1s9fld8cvak8yz88zgrp5ypx2cxl8c";
|
||||
};
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/share/kak/autoload/plugins
|
||||
cp -r rc $out/share/kak/autoload/plugins/prelude
|
||||
'';
|
||||
|
||||
meta = with lib;
|
||||
{ description = "Prelude of shell blocks for Kakoune.";
|
||||
homepage = "https://github.com/alexherbo2/prelude.kak";
|
||||
license = licenses.unlicense;
|
||||
maintainers = with maintainers; [ buffet ];
|
||||
platform = platforms.all;
|
||||
};
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
{ stdenv, fetchFromGitHub, lib }:
|
||||
stdenv.mkDerivation {
|
||||
name = "kak-vertical-selection";
|
||||
version = "2019-04-11";
|
||||
src = fetchFromGitHub {
|
||||
owner = "occivink";
|
||||
repo = "kakoune-vertical-selection";
|
||||
rev = "c420f8b867ce47375fac303886e31623669a42b7";
|
||||
sha256 = "13jdyd2j45wvgqvxdzw9zww14ly93bqjb6700zzxj7mkbiff6wsb";
|
||||
};
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/share/kak/autoload/plugins
|
||||
cp -r vertical-selection.kak $out/share/kak/autoload/plugins
|
||||
'';
|
||||
|
||||
meta = with lib;
|
||||
{ description = "Select up and down lines that match the same pattern in Kakoune";
|
||||
homepage = "https://github.com/occivink/kakoune-vertical-selection";
|
||||
license = licenses.unlicense;
|
||||
maintainers = with maintainers; [ nrdxp ];
|
||||
platform = platforms.all;
|
||||
};
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
alexherbo2/auto-pairs.kak
|
||||
alexherbo2/connect.kak
|
||||
alexherbo2/prelude.kak
|
||||
alexherbo2/replace-mode.kak
|
||||
alexherbo2/sleuth.kak
|
||||
andreyorst/fzf.kak
|
||||
danr/kakoune-easymotion
|
||||
Delapouite/kakoune-buffers
|
||||
Delapouite/kakoune-registers
|
||||
enricozb/tabs.kak@main
|
||||
greenfork/active-window.kak
|
||||
jdugan6240/powerline.kak
|
||||
kakoune-editor/kakoune-extra-filetypes
|
||||
listentolist/kakoune-rainbow
|
||||
mayjs/openscad.kak
|
||||
occivink/kakoune-buffer-switcher
|
||||
occivink/kakoune-vertical-selection
|
@ -0,0 +1,4 @@
|
||||
{ lib, stdenv }:
|
||||
{
|
||||
inherit (import ./build-kakoune-plugin.nix { inherit lib stdenv; }) buildKakounePlugin buildKakounePluginFrom2Nix;
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
{ lib, stdenv, fetchFromGitHub }:
|
||||
|
||||
stdenv.mkDerivation {
|
||||
pname = "openscad.kak";
|
||||
version = "unstable-2019-11-08";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "mayjs";
|
||||
repo = "openscad.kak";
|
||||
rev = "d9143d5e7834e3356b49720664d5647cab9db7cc";
|
||||
sha256 = "0j4dqhrn56z77hdalfdxagwz8h6nwr8s9i4w0bs2644k72lsm2ix";
|
||||
};
|
||||
|
||||
installPhase = ''
|
||||
install -Dm644 rc/openscad.kak -t $out/share/kak/autoload/plugins/
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
description = "Syntax highlighting for OpenSCAD files";
|
||||
homepage = "https://github.com/mayjs/openscad.kak";
|
||||
license = licenses.unlicense;
|
||||
maintainers = with maintainers; [ eraserhd ];
|
||||
platforms = platforms.all;
|
||||
};
|
||||
}
|
161
pkgs/applications/editors/kakoune/plugins/overrides.nix
Normal file
161
pkgs/applications/editors/kakoune/plugins/overrides.nix
Normal file
@ -0,0 +1,161 @@
|
||||
{ lib, stdenv, fetchFromGitHub, fetchFromGitLab, fetchgit
|
||||
, buildKakounePluginFrom2Nix
|
||||
, kak-lsp, parinfer-rust, rep
|
||||
, fzf, git, guile, kakoune-unwrapped, lua5_3, plan9port
|
||||
}:
|
||||
|
||||
self: super: {
|
||||
inherit kak-lsp parinfer-rust rep;
|
||||
|
||||
case-kak = buildKakounePluginFrom2Nix {
|
||||
pname = "case-kak";
|
||||
version = "2020-04-06";
|
||||
src = fetchFromGitLab {
|
||||
owner = "FlyingWombat";
|
||||
repo = "case.kak";
|
||||
rev = "6f1511820aa3abfa118e0f856118adc8113e2185";
|
||||
sha256 = "002njrlwgakqgp74wivbppr9qyn57dn4n5bxkr6k6nglk9qndwdp";
|
||||
};
|
||||
meta.homepage = "https://gitlab.com/FlyingWombat/case.kak";
|
||||
};
|
||||
|
||||
fzf-kak = super.fzf-kak.overrideAttrs(oldAttrs: rec {
|
||||
preFixup = ''
|
||||
if [[ -x "${fzf}/bin/fzf" ]]; then
|
||||
fzfImpl='${fzf}/bin/fzf'
|
||||
else
|
||||
fzfImpl='${fzf}/bin/sk'
|
||||
fi
|
||||
|
||||
substituteInPlace $out/share/kak/autoload/plugins/fzf-kak/rc/fzf.kak \
|
||||
--replace \'fzf\' \'"$fzfImpl"\'
|
||||
'';
|
||||
});
|
||||
|
||||
kak-ansi = stdenv.mkDerivation rec {
|
||||
pname = "kak-ansi";
|
||||
version = "0.2.1";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "eraserhd";
|
||||
repo = "kak-ansi";
|
||||
rev = "v${version}";
|
||||
sha256 = "0ddjih8hfyf6s4g7y46p1355kklaw1ydzzh61141i0r45wyb2d0d";
|
||||
};
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin $out/share/kak/autoload/plugins/
|
||||
cp kak-ansi-filter $out/bin/
|
||||
# Hard-code path of filter and don't try to build when Kakoune boots
|
||||
sed '
|
||||
/^declare-option.* ansi_filter /i\
|
||||
declare-option -hidden str ansi_filter %{'"$out"'/bin/kak-ansi-filter}
|
||||
/^declare-option.* ansi_filter /,/^}/d
|
||||
' rc/ansi.kak >$out/share/kak/autoload/plugins/ansi.kak
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
description = "Kakoune support for rendering ANSI code";
|
||||
homepage = "https://github.com/eraserhd/kak-ansi";
|
||||
license = licenses.unlicense;
|
||||
maintainers = with maintainers; [ eraserhd ];
|
||||
platforms = platforms.all;
|
||||
};
|
||||
};
|
||||
|
||||
kak-plumb = stdenv.mkDerivation rec {
|
||||
pname = "kak-plumb";
|
||||
version = "0.1.1";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "eraserhd";
|
||||
repo = "kak-plumb";
|
||||
rev = "v${version}";
|
||||
sha256 = "1rz6pr786slnf1a78m3sj09axr4d2lb5rg7sfa4mfg1zcjh06ps6";
|
||||
};
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin $out/share/kak/autoload/plugins/
|
||||
substitute rc/plumb.kak $out/share/kak/autoload/plugins/plumb.kak \
|
||||
--replace '9 plumb' '${plan9port}/bin/9 plumb'
|
||||
substitute edit-client $out/bin/edit-client \
|
||||
--replace '9 9p' '${plan9port}/bin/9 9p' \
|
||||
--replace 'kak -p' '${kakoune-unwrapped}/bin/kak -p'
|
||||
chmod +x $out/bin/edit-client
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
description = "Kakoune integration with the Plan 9 plumber";
|
||||
homepage = "https://github.com/eraserhd/kak-plumb";
|
||||
license = licenses.unlicense;
|
||||
maintainers = with maintainers; [ eraserhd ];
|
||||
platforms = platforms.all;
|
||||
};
|
||||
};
|
||||
|
||||
kakoune-rainbow = super.kakoune-rainbow.overrideAttrs(oldAttrs: rec {
|
||||
preFixup = ''
|
||||
mkdir -p $out/bin
|
||||
mv $out/share/kak/autoload/plugins/kakoune-rainbow/bin/kak-rainbow.scm $out/bin
|
||||
substituteInPlace $out/bin/kak-rainbow.scm \
|
||||
--replace '/usr/bin/env -S guile' '${guile}/bin/guile'
|
||||
substituteInPlace $out/share/kak/autoload/plugins/kakoune-rainbow/rainbow.kak \
|
||||
--replace '%sh{dirname "$kak_source"}' "'$out'"
|
||||
'';
|
||||
});
|
||||
|
||||
kakoune-state-save = buildKakounePluginFrom2Nix {
|
||||
pname = "kakoune-state-save";
|
||||
version = "2020-02-09";
|
||||
|
||||
src = fetchFromGitLab {
|
||||
owner = "Screwtapello";
|
||||
repo = "kakoune-state-save";
|
||||
rev = "ab7c0c765326a4a80af78857469ee8c80814c52a";
|
||||
sha256 = "AAOCG0TY3G188NnkkwMCSbkkNe487F4gwiFWwG9Yo+A=";
|
||||
};
|
||||
|
||||
meta = with lib; {
|
||||
description = "Help Kakoune save and restore state between sessions";
|
||||
homepage = "https://gitlab.com/Screwtapello/kakoune-state-save";
|
||||
license = licenses.mit;
|
||||
maintainers = with maintainers; [ Flakebi ];
|
||||
platforms = platforms.all;
|
||||
};
|
||||
};
|
||||
|
||||
powerline-kak = super.powerline-kak.overrideAttrs(oldAttrs: rec {
|
||||
preFixup = ''
|
||||
substituteInPlace $out/share/kak/autoload/plugins/powerline-kak/rc/modules/git.kak \
|
||||
--replace ' git ' ' ${git}/bin/git '
|
||||
'';
|
||||
});
|
||||
|
||||
quickscope-kak = buildKakounePluginFrom2Nix rec {
|
||||
pname = "quickscope-kak";
|
||||
version = "1.0.0";
|
||||
|
||||
src = fetchgit {
|
||||
url = "https://git.sr.ht/~voroskoi/quickscope.kak";
|
||||
rev = "v${version}";
|
||||
sha256 = "0y1g3zpa2ql8l9rl5i2w84bka8a09kig9nq9zdchaff5pw660mcx";
|
||||
};
|
||||
|
||||
buildInputs = [ lua5_3 ];
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/share/kak/autoload/plugins/
|
||||
cp quickscope.* $out/share/kak/autoload/plugins/
|
||||
# substituteInPlace does not like the pipe
|
||||
sed -e 's,[|] *lua,|${lua5_3}/bin/lua,' quickscope.kak >$out/share/kak/autoload/plugins/quickscope.kak
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
description = "Highlight f and t jump positions";
|
||||
homepage = "https://sr.ht/~voroskoi/quickscope.kak/";
|
||||
license = licenses.unlicense;
|
||||
maintainers = with maintainers; [ eraserhd ];
|
||||
platforms = platforms.all;
|
||||
};
|
||||
};
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
{ lib, stdenv, fetchgit, lua5_3 }:
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "quickscope-kak";
|
||||
version = "1.0.0";
|
||||
|
||||
src = fetchgit {
|
||||
url = "https://git.sr.ht/~voroskoi/quickscope.kak";
|
||||
rev = "v${version}";
|
||||
sha256 = "0y1g3zpa2ql8l9rl5i2w84bka8a09kig9nq9zdchaff5pw660mcx";
|
||||
};
|
||||
|
||||
buildInputs = [ lua5_3 ];
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/share/kak/autoload/plugins/
|
||||
cp quickscope.* $out/share/kak/autoload/plugins/
|
||||
# substituteInPlace does not like the pipe
|
||||
sed -e 's,[|] *lua,|${lua5_3}/bin/lua,' quickscope.kak >$out/share/kak/autoload/plugins/quickscope.kak
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
description = "Highlight f and t jump positions";
|
||||
homepage = "https://sr.ht/~voroskoi/quickscope.kak/";
|
||||
license = licenses.unlicense;
|
||||
maintainers = with maintainers; [ eraserhd ];
|
||||
platforms = platforms.all;
|
||||
};
|
||||
}
|
91
pkgs/applications/editors/kakoune/plugins/update.py
Executable file
91
pkgs/applications/editors/kakoune/plugins/update.py
Executable file
@ -0,0 +1,91 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -p nix-prefetch-git -p python3 -p python3Packages.GitPython nix -i python3
|
||||
|
||||
# format:
|
||||
# $ nix run nixpkgs.python3Packages.black -c black update.py
|
||||
# type-check:
|
||||
# $ nix run nixpkgs.python3Packages.mypy -c mypy update.py
|
||||
# linted:
|
||||
# $ nix run nixpkgs.python3Packages.flake8 -c flake8 --ignore E501,E265,E402 update.py
|
||||
|
||||
import inspect
|
||||
import os
|
||||
import sys
|
||||
from typing import List, Tuple
|
||||
from pathlib import Path
|
||||
|
||||
# Import plugin update library from maintainers/scripts/pluginupdate.py
|
||||
ROOT = Path(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))))
|
||||
sys.path.insert(
|
||||
0, os.path.join(ROOT.parent.parent.parent.parent.parent, "maintainers", "scripts")
|
||||
)
|
||||
import pluginupdate
|
||||
|
||||
GET_PLUGINS = f"""(with import <localpkgs> {{}};
|
||||
let
|
||||
inherit (kakouneUtils.override {{}}) buildKakounePluginFrom2Nix;
|
||||
generated = callPackage {ROOT}/generated.nix {{
|
||||
inherit buildKakounePluginFrom2Nix;
|
||||
}};
|
||||
hasChecksum = value: lib.isAttrs value && lib.hasAttrByPath ["src" "outputHash"] value;
|
||||
getChecksum = name: value:
|
||||
if hasChecksum value then {{
|
||||
submodules = value.src.fetchSubmodules or false;
|
||||
sha256 = value.src.outputHash;
|
||||
rev = value.src.rev;
|
||||
}} else null;
|
||||
checksums = lib.mapAttrs getChecksum generated;
|
||||
in lib.filterAttrs (n: v: v != null) checksums)"""
|
||||
|
||||
HEADER = "# This file has been generated by ./pkgs/applications/editors/kakoune/plugins/update.py. Do not edit!"
|
||||
|
||||
|
||||
def generate_nix(plugins: List[Tuple[str, str, pluginupdate.Plugin]], outfile: str):
|
||||
sorted_plugins = sorted(plugins, key=lambda v: v[2].name.lower())
|
||||
|
||||
with open(outfile, "w+") as f:
|
||||
f.write(HEADER)
|
||||
f.write(
|
||||
"""
|
||||
{ lib, buildKakounePluginFrom2Nix, fetchFromGitHub, overrides ? (self: super: {}) }:
|
||||
let
|
||||
packages = ( self:
|
||||
{"""
|
||||
)
|
||||
for owner, repo, plugin in sorted_plugins:
|
||||
if plugin.has_submodules:
|
||||
submodule_attr = "\n fetchSubmodules = true;"
|
||||
else:
|
||||
submodule_attr = ""
|
||||
|
||||
f.write(
|
||||
f"""
|
||||
{plugin.normalized_name} = buildKakounePluginFrom2Nix {{
|
||||
pname = "{plugin.normalized_name}";
|
||||
version = "{plugin.version}";
|
||||
src = fetchFromGitHub {{
|
||||
owner = "{owner}";
|
||||
repo = "{repo}";
|
||||
rev = "{plugin.commit}";
|
||||
sha256 = "{plugin.sha256}";{submodule_attr}
|
||||
}};
|
||||
meta.homepage = "https://github.com/{owner}/{repo}/";
|
||||
}};
|
||||
"""
|
||||
)
|
||||
f.write(
|
||||
"""
|
||||
});
|
||||
in lib.fix' (lib.extends overrides packages)
|
||||
"""
|
||||
)
|
||||
print(f"updated {outfile}")
|
||||
|
||||
|
||||
def main():
|
||||
editor = pluginupdate.Editor("kakoune", ROOT, GET_PLUGINS, generate_nix)
|
||||
pluginupdate.update_plugins(editor)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -6,180 +6,18 @@
|
||||
# type-check:
|
||||
# $ nix run nixpkgs.python3Packages.mypy -c mypy update.py
|
||||
# linted:
|
||||
# $ nix run nixpkgs.python3Packages.flake8 -c flake8 --ignore E501,E265 update.py
|
||||
# $ nix run nixpkgs.python3Packages.flake8 -c flake8 --ignore E501,E265,E402 update.py
|
||||
|
||||
import argparse
|
||||
import functools
|
||||
import http
|
||||
import json
|
||||
import inspect
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import traceback
|
||||
import urllib.error
|
||||
import urllib.parse
|
||||
import urllib.request
|
||||
import xml.etree.ElementTree as ET
|
||||
from datetime import datetime
|
||||
from functools import wraps
|
||||
from multiprocessing.dummy import Pool
|
||||
from typing import List, Tuple
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Optional, Tuple, Union, Any, Callable
|
||||
from urllib.parse import urljoin, urlparse
|
||||
from tempfile import NamedTemporaryFile
|
||||
|
||||
import git
|
||||
|
||||
ATOM_ENTRY = "{http://www.w3.org/2005/Atom}entry" # " vim gets confused here
|
||||
ATOM_LINK = "{http://www.w3.org/2005/Atom}link" # "
|
||||
ATOM_UPDATED = "{http://www.w3.org/2005/Atom}updated" # "
|
||||
|
||||
ROOT = Path(__file__).parent
|
||||
DEFAULT_IN = ROOT.joinpath("vim-plugin-names")
|
||||
DEFAULT_OUT = ROOT.joinpath("generated.nix")
|
||||
DEPRECATED = ROOT.joinpath("deprecated.json")
|
||||
|
||||
def retry(ExceptionToCheck: Any, tries: int = 4, delay: float = 3, backoff: float = 2):
|
||||
"""Retry calling the decorated function using an exponential backoff.
|
||||
http://www.saltycrane.com/blog/2009/11/trying-out-retry-decorator-python/
|
||||
original from: http://wiki.python.org/moin/PythonDecoratorLibrary#Retry
|
||||
(BSD licensed)
|
||||
:param ExceptionToCheck: the exception on which to retry
|
||||
:param tries: number of times to try (not retry) before giving up
|
||||
:param delay: initial delay between retries in seconds
|
||||
:param backoff: backoff multiplier e.g. value of 2 will double the delay
|
||||
each retry
|
||||
"""
|
||||
|
||||
def deco_retry(f: Callable) -> Callable:
|
||||
@wraps(f)
|
||||
def f_retry(*args: Any, **kwargs: Any) -> Any:
|
||||
mtries, mdelay = tries, delay
|
||||
while mtries > 1:
|
||||
try:
|
||||
return f(*args, **kwargs)
|
||||
except ExceptionToCheck as e:
|
||||
print(f"{str(e)}, Retrying in {mdelay} seconds...")
|
||||
time.sleep(mdelay)
|
||||
mtries -= 1
|
||||
mdelay *= backoff
|
||||
return f(*args, **kwargs)
|
||||
|
||||
return f_retry # true decorator
|
||||
|
||||
return deco_retry
|
||||
|
||||
def make_request(url: str) -> urllib.request.Request:
|
||||
token = os.getenv("GITHUB_API_TOKEN")
|
||||
headers = {}
|
||||
if token is not None:
|
||||
headers["Authorization"] = f"token {token}"
|
||||
return urllib.request.Request(url, headers=headers)
|
||||
|
||||
class Repo:
|
||||
def __init__(
|
||||
self, owner: str, name: str, branch: str, alias: Optional[str]
|
||||
) -> None:
|
||||
self.owner = owner
|
||||
self.name = name
|
||||
self.branch = branch
|
||||
self.alias = alias
|
||||
self.redirect: Dict[str, str] = {}
|
||||
|
||||
def url(self, path: str) -> str:
|
||||
return urljoin(f"https://github.com/{self.owner}/{self.name}/", path)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Repo({self.owner}, {self.name})"
|
||||
|
||||
@retry(urllib.error.URLError, tries=4, delay=3, backoff=2)
|
||||
def has_submodules(self) -> bool:
|
||||
try:
|
||||
req = make_request(self.url(f"blob/{self.branch}/.gitmodules"))
|
||||
urllib.request.urlopen(req, timeout=10).close()
|
||||
except urllib.error.HTTPError as e:
|
||||
if e.code == 404:
|
||||
return False
|
||||
else:
|
||||
raise
|
||||
return True
|
||||
|
||||
@retry(urllib.error.URLError, tries=4, delay=3, backoff=2)
|
||||
def latest_commit(self) -> Tuple[str, datetime]:
|
||||
commit_url = self.url(f"commits/{self.branch}.atom")
|
||||
commit_req = make_request(commit_url)
|
||||
with urllib.request.urlopen(commit_req, timeout=10) as req:
|
||||
self.check_for_redirect(commit_url, req)
|
||||
xml = req.read()
|
||||
root = ET.fromstring(xml)
|
||||
latest_entry = root.find(ATOM_ENTRY)
|
||||
assert latest_entry is not None, f"No commits found in repository {self}"
|
||||
commit_link = latest_entry.find(ATOM_LINK)
|
||||
assert commit_link is not None, f"No link tag found feed entry {xml}"
|
||||
url = urlparse(commit_link.get("href"))
|
||||
updated_tag = latest_entry.find(ATOM_UPDATED)
|
||||
assert (
|
||||
updated_tag is not None and updated_tag.text is not None
|
||||
), f"No updated tag found feed entry {xml}"
|
||||
updated = datetime.strptime(updated_tag.text, "%Y-%m-%dT%H:%M:%SZ")
|
||||
return Path(str(url.path)).name, updated
|
||||
|
||||
def check_for_redirect(self, url: str, req: http.client.HTTPResponse):
|
||||
response_url = req.geturl()
|
||||
if url != response_url:
|
||||
new_owner, new_name = (
|
||||
urllib.parse.urlsplit(response_url).path.strip("/").split("/")[:2]
|
||||
)
|
||||
end_line = "\n" if self.alias is None else f" as {self.alias}\n"
|
||||
plugin_line = "{owner}/{name}" + end_line
|
||||
|
||||
old_plugin = plugin_line.format(owner=self.owner, name=self.name)
|
||||
new_plugin = plugin_line.format(owner=new_owner, name=new_name)
|
||||
self.redirect[old_plugin] = new_plugin
|
||||
|
||||
def prefetch_git(self, ref: str) -> str:
|
||||
data = subprocess.check_output(
|
||||
["nix-prefetch-git", "--fetch-submodules", self.url(""), ref]
|
||||
)
|
||||
return json.loads(data)["sha256"]
|
||||
|
||||
def prefetch_github(self, ref: str) -> str:
|
||||
data = subprocess.check_output(
|
||||
["nix-prefetch-url", "--unpack", self.url(f"archive/{ref}.tar.gz")]
|
||||
)
|
||||
return data.strip().decode("utf-8")
|
||||
|
||||
|
||||
class Plugin:
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
commit: str,
|
||||
has_submodules: bool,
|
||||
sha256: str,
|
||||
date: Optional[datetime] = None,
|
||||
) -> None:
|
||||
self.name = name
|
||||
self.commit = commit
|
||||
self.has_submodules = has_submodules
|
||||
self.sha256 = sha256
|
||||
self.date = date
|
||||
|
||||
@property
|
||||
def normalized_name(self) -> str:
|
||||
return self.name.replace(".", "-")
|
||||
|
||||
@property
|
||||
def version(self) -> str:
|
||||
assert self.date is not None
|
||||
return self.date.strftime("%Y-%m-%d")
|
||||
|
||||
def as_json(self) -> Dict[str, str]:
|
||||
copy = self.__dict__.copy()
|
||||
del copy["date"]
|
||||
return copy
|
||||
|
||||
# Import plugin update library from maintainers/scripts/pluginupdate.py
|
||||
ROOT = Path(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))))
|
||||
sys.path.insert(0, os.path.join(ROOT.parent.parent.parent, "maintainers", "scripts"))
|
||||
import pluginupdate
|
||||
|
||||
GET_PLUGINS = f"""(with import <localpkgs> {{}};
|
||||
let
|
||||
@ -197,204 +35,16 @@ let
|
||||
checksums = lib.mapAttrs getChecksum generated;
|
||||
in lib.filterAttrs (n: v: v != null) checksums)"""
|
||||
|
||||
|
||||
class CleanEnvironment(object):
|
||||
def __enter__(self) -> None:
|
||||
self.old_environ = os.environ.copy()
|
||||
local_pkgs = str(ROOT.joinpath("../../.."))
|
||||
os.environ["NIX_PATH"] = f"localpkgs={local_pkgs}"
|
||||
self.empty_config = NamedTemporaryFile()
|
||||
self.empty_config.write(b"{}")
|
||||
self.empty_config.flush()
|
||||
os.environ["NIXPKGS_CONFIG"] = self.empty_config.name
|
||||
|
||||
def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None:
|
||||
os.environ.update(self.old_environ)
|
||||
self.empty_config.close()
|
||||
|
||||
|
||||
def get_current_plugins() -> List[Plugin]:
|
||||
with CleanEnvironment():
|
||||
out = subprocess.check_output(["nix", "eval", "--json", GET_PLUGINS])
|
||||
data = json.loads(out)
|
||||
plugins = []
|
||||
for name, attr in data.items():
|
||||
p = Plugin(name, attr["rev"], attr["submodules"], attr["sha256"])
|
||||
plugins.append(p)
|
||||
return plugins
|
||||
|
||||
|
||||
def prefetch_plugin(
|
||||
user: str,
|
||||
repo_name: str,
|
||||
branch: str,
|
||||
alias: Optional[str],
|
||||
cache: "Optional[Cache]" = None,
|
||||
) -> Tuple[Plugin, Dict[str, str]]:
|
||||
repo = Repo(user, repo_name, branch, alias)
|
||||
commit, date = repo.latest_commit()
|
||||
has_submodules = repo.has_submodules()
|
||||
cached_plugin = cache[commit] if cache else None
|
||||
if cached_plugin is not None:
|
||||
cached_plugin.name = alias or repo_name
|
||||
cached_plugin.date = date
|
||||
return cached_plugin, repo.redirect
|
||||
|
||||
print(f"prefetch {user}/{repo_name}")
|
||||
if has_submodules:
|
||||
sha256 = repo.prefetch_git(commit)
|
||||
else:
|
||||
sha256 = repo.prefetch_github(commit)
|
||||
|
||||
return (
|
||||
Plugin(alias or repo_name, commit, has_submodules, sha256, date=date),
|
||||
repo.redirect,
|
||||
)
|
||||
|
||||
|
||||
def fetch_plugin_from_pluginline(plugin_line: str) -> Plugin:
|
||||
plugin, _ = prefetch_plugin(*parse_plugin_line(plugin_line))
|
||||
return plugin
|
||||
|
||||
|
||||
def print_download_error(plugin: str, ex: Exception):
|
||||
print(f"{plugin}: {ex}", file=sys.stderr)
|
||||
ex_traceback = ex.__traceback__
|
||||
tb_lines = [
|
||||
line.rstrip("\n")
|
||||
for line in traceback.format_exception(ex.__class__, ex, ex_traceback)
|
||||
]
|
||||
print("\n".join(tb_lines))
|
||||
|
||||
|
||||
def check_results(
|
||||
results: List[Tuple[str, str, Union[Exception, Plugin], Dict[str, str]]]
|
||||
) -> Tuple[List[Tuple[str, str, Plugin]], Dict[str, str]]:
|
||||
failures: List[Tuple[str, Exception]] = []
|
||||
plugins = []
|
||||
redirects: Dict[str, str] = {}
|
||||
for (owner, name, result, redirect) in results:
|
||||
if isinstance(result, Exception):
|
||||
failures.append((name, result))
|
||||
else:
|
||||
plugins.append((owner, name, result))
|
||||
redirects.update(redirect)
|
||||
|
||||
print(f"{len(results) - len(failures)} plugins were checked", end="")
|
||||
if len(failures) == 0:
|
||||
print()
|
||||
return plugins, redirects
|
||||
else:
|
||||
print(f", {len(failures)} plugin(s) could not be downloaded:\n")
|
||||
|
||||
for (plugin, exception) in failures:
|
||||
print_download_error(plugin, exception)
|
||||
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def parse_plugin_line(line: str) -> Tuple[str, str, str, Optional[str]]:
|
||||
branch = "master"
|
||||
alias = None
|
||||
name, repo = line.split("/")
|
||||
if " as " in repo:
|
||||
repo, alias = repo.split(" as ")
|
||||
alias = alias.strip()
|
||||
if "@" in repo:
|
||||
repo, branch = repo.split("@")
|
||||
|
||||
return (name.strip(), repo.strip(), branch.strip(), alias)
|
||||
|
||||
|
||||
def load_plugin_spec(plugin_file: str) -> List[Tuple[str, str, str, Optional[str]]]:
|
||||
plugins = []
|
||||
with open(plugin_file) as f:
|
||||
for line in f:
|
||||
plugin = parse_plugin_line(line)
|
||||
if not plugin[0]:
|
||||
msg = f"Invalid repository {line}, must be in the format owner/repo[ as alias]"
|
||||
print(msg, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
plugins.append(plugin)
|
||||
return plugins
|
||||
|
||||
|
||||
def get_cache_path() -> Optional[Path]:
|
||||
xdg_cache = os.environ.get("XDG_CACHE_HOME", None)
|
||||
if xdg_cache is None:
|
||||
home = os.environ.get("HOME", None)
|
||||
if home is None:
|
||||
return None
|
||||
xdg_cache = str(Path(home, ".cache"))
|
||||
|
||||
return Path(xdg_cache, "vim-plugin-cache.json")
|
||||
|
||||
|
||||
class Cache:
|
||||
def __init__(self, initial_plugins: List[Plugin]) -> None:
|
||||
self.cache_file = get_cache_path()
|
||||
|
||||
downloads = {}
|
||||
for plugin in initial_plugins:
|
||||
downloads[plugin.commit] = plugin
|
||||
downloads.update(self.load())
|
||||
self.downloads = downloads
|
||||
|
||||
def load(self) -> Dict[str, Plugin]:
|
||||
if self.cache_file is None or not self.cache_file.exists():
|
||||
return {}
|
||||
|
||||
downloads: Dict[str, Plugin] = {}
|
||||
with open(self.cache_file) as f:
|
||||
data = json.load(f)
|
||||
for attr in data.values():
|
||||
p = Plugin(
|
||||
attr["name"], attr["commit"], attr["has_submodules"], attr["sha256"]
|
||||
)
|
||||
downloads[attr["commit"]] = p
|
||||
return downloads
|
||||
|
||||
def store(self) -> None:
|
||||
if self.cache_file is None:
|
||||
return
|
||||
|
||||
os.makedirs(self.cache_file.parent, exist_ok=True)
|
||||
with open(self.cache_file, "w+") as f:
|
||||
data = {}
|
||||
for name, attr in self.downloads.items():
|
||||
data[name] = attr.as_json()
|
||||
json.dump(data, f, indent=4, sort_keys=True)
|
||||
|
||||
def __getitem__(self, key: str) -> Optional[Plugin]:
|
||||
return self.downloads.get(key, None)
|
||||
|
||||
def __setitem__(self, key: str, value: Plugin) -> None:
|
||||
self.downloads[key] = value
|
||||
|
||||
|
||||
def prefetch(
|
||||
args: Tuple[str, str, str, Optional[str]], cache: Cache
|
||||
) -> Tuple[str, str, Union[Exception, Plugin], dict]:
|
||||
assert len(args) == 4
|
||||
owner, repo, branch, alias = args
|
||||
try:
|
||||
plugin, redirect = prefetch_plugin(owner, repo, branch, alias, cache)
|
||||
cache[plugin.commit] = plugin
|
||||
return (owner, repo, plugin, redirect)
|
||||
except Exception as e:
|
||||
return (owner, repo, e, {})
|
||||
|
||||
|
||||
header = (
|
||||
HEADER = (
|
||||
"# This file has been generated by ./pkgs/misc/vim-plugins/update.py. Do not edit!"
|
||||
)
|
||||
|
||||
|
||||
def generate_nix(plugins: List[Tuple[str, str, Plugin]], outfile: str):
|
||||
def generate_nix(plugins: List[Tuple[str, str, pluginupdate.Plugin]], outfile: str):
|
||||
sorted_plugins = sorted(plugins, key=lambda v: v[2].name.lower())
|
||||
|
||||
with open(outfile, "w+") as f:
|
||||
f.write(header)
|
||||
f.write(HEADER)
|
||||
f.write(
|
||||
"""
|
||||
{ lib, buildVimPluginFrom2Nix, fetchFromGitHub, overrides ? (self: super: {}) }:
|
||||
@ -432,136 +82,9 @@ in lib.fix' (lib.extends overrides packages)
|
||||
print(f"updated {outfile}")
|
||||
|
||||
|
||||
def rewrite_input(
|
||||
input_file: Path, redirects: Dict[str, str] = None, append: Tuple = ()
|
||||
):
|
||||
with open(input_file, "r") as f:
|
||||
lines = f.readlines()
|
||||
|
||||
lines.extend(append)
|
||||
|
||||
if redirects:
|
||||
lines = [redirects.get(line, line) for line in lines]
|
||||
|
||||
cur_date_iso = datetime.now().strftime("%Y-%m-%d")
|
||||
with open(DEPRECATED, "r") as f:
|
||||
deprecations = json.load(f)
|
||||
for old, new in redirects.items():
|
||||
old_plugin = fetch_plugin_from_pluginline(old)
|
||||
new_plugin = fetch_plugin_from_pluginline(new)
|
||||
if old_plugin.normalized_name != new_plugin.normalized_name:
|
||||
deprecations[old_plugin.normalized_name] = {
|
||||
"new": new_plugin.normalized_name,
|
||||
"date": cur_date_iso,
|
||||
}
|
||||
with open(DEPRECATED, "w") as f:
|
||||
json.dump(deprecations, f, indent=4, sort_keys=True)
|
||||
|
||||
lines = sorted(lines, key=str.casefold)
|
||||
|
||||
with open(input_file, "w") as f:
|
||||
f.writelines(lines)
|
||||
|
||||
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser(
|
||||
description=(
|
||||
"Updates nix derivations for vim plugins"
|
||||
f"By default from {DEFAULT_IN} to {DEFAULT_OUT}"
|
||||
)
|
||||
)
|
||||
parser.add_argument(
|
||||
"--add",
|
||||
dest="add_plugins",
|
||||
default=[],
|
||||
action="append",
|
||||
help="Plugin to add to vimPlugins from Github in the form owner/repo",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--input-names",
|
||||
"-i",
|
||||
dest="input_file",
|
||||
default=DEFAULT_IN,
|
||||
help="A list of plugins in the form owner/repo",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--out",
|
||||
"-o",
|
||||
dest="outfile",
|
||||
default=DEFAULT_OUT,
|
||||
help="Filename to save generated nix code",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--proc",
|
||||
"-p",
|
||||
dest="proc",
|
||||
type=int,
|
||||
default=30,
|
||||
help="Number of concurrent processes to spawn.",
|
||||
)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def commit(repo: git.Repo, message: str, files: List[Path]) -> None:
|
||||
repo.index.add([str(f.resolve()) for f in files])
|
||||
|
||||
if repo.index.diff("HEAD"):
|
||||
print(f'committing to nixpkgs "{message}"')
|
||||
repo.index.commit(message)
|
||||
else:
|
||||
print("no changes in working tree to commit")
|
||||
|
||||
|
||||
def get_update(input_file: str, outfile: str, proc: int):
|
||||
cache: Cache = Cache(get_current_plugins())
|
||||
_prefetch = functools.partial(prefetch, cache=cache)
|
||||
|
||||
def update() -> dict:
|
||||
plugin_names = load_plugin_spec(input_file)
|
||||
|
||||
try:
|
||||
pool = Pool(processes=proc)
|
||||
results = pool.map(_prefetch, plugin_names)
|
||||
finally:
|
||||
cache.store()
|
||||
|
||||
plugins, redirects = check_results(results)
|
||||
|
||||
generate_nix(plugins, outfile)
|
||||
|
||||
return redirects
|
||||
|
||||
return update
|
||||
|
||||
|
||||
def main():
|
||||
args = parse_args()
|
||||
nixpkgs_repo = git.Repo(ROOT, search_parent_directories=True)
|
||||
update = get_update(args.input_file, args.outfile, args.proc)
|
||||
|
||||
redirects = update()
|
||||
rewrite_input(args.input_file, redirects)
|
||||
commit(nixpkgs_repo, "vimPlugins: update", [args.outfile])
|
||||
|
||||
if redirects:
|
||||
update()
|
||||
commit(
|
||||
nixpkgs_repo,
|
||||
"vimPlugins: resolve github repository redirects",
|
||||
[args.outfile, args.input_file, DEPRECATED],
|
||||
)
|
||||
|
||||
for plugin_line in args.add_plugins:
|
||||
rewrite_input(args.input_file, append=(plugin_line + "\n",))
|
||||
update()
|
||||
plugin = fetch_plugin_from_pluginline(plugin_line)
|
||||
commit(
|
||||
nixpkgs_repo,
|
||||
"vimPlugins.{name}: init at {version}".format(
|
||||
name=plugin.normalized_name, version=plugin.version
|
||||
),
|
||||
[args.outfile, args.input_file],
|
||||
)
|
||||
editor = pluginupdate.Editor("vim", ROOT, GET_PLUGINS, generate_nix)
|
||||
pluginupdate.update_plugins(editor)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@ -5583,11 +5583,13 @@ in
|
||||
kalibrate-hackrf = callPackage ../applications/radio/kalibrate-hackrf { };
|
||||
|
||||
wrapKakoune = kakoune: attrs: callPackage ../applications/editors/kakoune/wrapper.nix (attrs // { inherit kakoune; });
|
||||
kakounePlugins = callPackage ../applications/editors/kakoune/plugins { };
|
||||
kakounePlugins = recurseIntoAttrs (callPackage ../applications/editors/kakoune/plugins { });
|
||||
|
||||
kakoune-unwrapped = callPackage ../applications/editors/kakoune { };
|
||||
kakoune = wrapKakoune kakoune-unwrapped {
|
||||
plugins = [ ]; # override with the list of desired plugins
|
||||
};
|
||||
kakouneUtils = callPackage ../applications/editors/kakoune/plugins/kakoune-utils.nix { };
|
||||
|
||||
kak-lsp = callPackage ../tools/misc/kak-lsp {
|
||||
inherit (darwin.apple_sdk.frameworks) Security;
|
||||
|
Loading…
x
Reference in New Issue
Block a user