plugin/efmls-configs: init + tests (#542)

This commit is contained in:
traxys 2023-08-27 20:49:23 +02:00 committed by GitHub
parent c4354ea9ec
commit 4cd3707e00
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 630 additions and 0 deletions

View file

@ -1,5 +1,6 @@
pkgs: rec {
rust-analyzer-config = pkgs.callPackage ./rust-analyzer {};
efmls-configs-tools = pkgs.callPackage ./efmls-configs {};
autogenerated-configs = pkgs.callPackage ({stdenv}:
stdenv.mkDerivation {
pname = "autogenerated-configs";
@ -11,6 +12,7 @@ pkgs: rec {
installPhase = ''
mkdir -p $out
cp ${rust-analyzer-config}/share/* $out
cp ${efmls-configs-tools}/share/* $out
'';
}) {};
}

View file

@ -0,0 +1,37 @@
{
stdenv,
python3,
vimPlugins,
}: let
extract = stdenv.mkDerivation {
pname = "extract_efmls_tools";
version = "1";
src = ./extract.py;
dontUnpack = true;
dontBuild = true;
buildInputs = [python3];
installPhase = ''
mkdir -p $out/bin
cp $src $out/bin/extract_efmls_tools.py
'';
};
in
stdenv.mkDerivation {
pname = "efmls-configs-tools";
inherit (vimPlugins.efmls-configs-nvim) version src;
nativeBuildInputs = [extract];
buildPhase = ''
extract_efmls_tools.py ./lua/efmls-configs > efmls-configs-tools.json
'';
installPhase = ''
mkdir -p $out/share
cp efmls-configs-tools.json $out/share
'';
}

View file

@ -0,0 +1,25 @@
#!/usr/bin/env python
import sys
import os
import json
tool_path = sys.argv[1]
tools = {
"linters": {},
"formatters": {},
}
for kind in ["linters", "formatters"]:
for file in os.listdir(tool_path + "/" + kind):
tool_name = file.removesuffix(".lua")
languages = []
with open(tool_path + "/" + kind + "/" + file) as f:
for line in f.readlines():
if line.startswith("-- languages:"):
languages = line.split(":")[1].strip().split(",")
break
tools[kind][tool_name] = languages
print(json.dumps(tools, indent=4))

View file

@ -537,5 +537,6 @@ in {
./ccls.nix
./pylsp.nix
./svelte.nix
./efmls-configs.nix
];
}

View file

@ -0,0 +1,330 @@
{
"linters": {
"alex": [
"misc"
],
"ameba": [
"crystal"
],
"ansible_lint": [
"yaml"
],
"bashate": [
"bash"
],
"clang_tidy": [
"c",
"c++"
],
"clazy": [
"c++"
],
"clj_kondo": [
"clojure"
],
"cppcheck": [
"c",
"c++"
],
"cpplint": [
"c",
"c++"
],
"dartanalyzer": [
"dart"
],
"debride": [
"ruby"
],
"djlint": [
"python",
"go",
"php",
"html"
],
"dmd": [
"d"
],
"eslint": [
"javascript",
"typescript"
],
"eslint_d": [
"javascript",
"typescript"
],
"fecs": [
"javascript"
],
"fish": [
"fish"
],
"flake8": [
"python"
],
"flawfinder": [
"c"
],
"gcc": [
"c",
"c++"
],
"go_revive": [
"go"
],
"golangci_lint": [
"go"
],
"golint": [
"go"
],
"hadolint": [
"docker"
],
"joker": [
"clojure"
],
"js_standard": [
"javascript"
],
"languagetool": [
"misc"
],
"luacheck": [
"lua"
],
"mcs": [
"c#"
],
"phan": [
"php"
],
"php": [
"php"
],
"phpcs": [
"php"
],
"phpstan": [
"php"
],
"proselint": [
"misc"
],
"psalm": [
"php"
],
"pylint": [
"python"
],
"redpen": [
"misc"
],
"reek": [
"ruby"
],
"rubocop": [
"ruby"
],
"shellcheck": [
"sh",
"bash"
],
"slither": [
"solidity"
],
"solhint": [
"solidity"
],
"sorbet": [
"ruby"
],
"staticcheck": [
"go"
],
"statix": [
"nix"
],
"stylelint": [
"css",
"scss",
"sass",
"less"
],
"textlint": [
"misc"
],
"vale": [
"misc"
],
"vint": [
"vim"
],
"vulture": [
"python"
],
"write_good": [
"misc"
],
"xo": [
"javascript",
"typescript"
],
"yamllint": [
"yaml"
]
},
"formatters": {
"astyle": [
"c",
"c++"
],
"autopep8": [
"python"
],
"black": [
"python"
],
"cbfmt": [
"markdown"
],
"clang_format": [
"c",
"c++"
],
"clang_tidy": [
"c",
"c++"
],
"dartfmt": [
"dart"
],
"dfmt": [
"d"
],
"dotnet_format": [
"c#"
],
"dprint": [
"javascript",
"typescript",
"json",
"markdown",
"toml",
"rust",
"roslyn"
],
"eslint": [
"javascript",
"typescript"
],
"eslint_d": [
"javascript",
"typescript"
],
"fecs": [
"javascript",
"typescript",
"css",
"html"
],
"fish_indent": [
"fish"
],
"forge_fmt": [
"solidity"
],
"gofmt": [
"go"
],
"goimports": [
"go"
],
"golines": [
"go"
],
"joker": [
"clojure"
],
"js_standard": [
"javascript"
],
"lua_format": [
"lua"
],
"nixfmt": [
"nix"
],
"php_cs_fixer": [
"php"
],
"phpcbf": [
"php"
],
"pint": [
"php"
],
"prettier": [
"javascript",
"typescript",
"css",
"scss",
"sass",
"less",
"html",
"json"
],
"prettier_d": [
"javascript",
"typescript",
"css",
"scss",
"sass",
"less",
"html",
"json"
],
"prettier_eslint": [
"javascript",
"typescript"
],
"prettier_standard": [
"javascript",
"typescript"
],
"rustfmt": [
"rust"
],
"shfmt": [
"sh",
"bash"
],
"smlfmt": [
"sml"
],
"stylua": [
"lua"
],
"terraform_fmt": [
"terraform"
],
"uncrustify": [
"c",
"c++",
"c#",
"d",
"java",
"objective-c",
"objective-c++",
"pawn",
"vala"
],
"xo": [
"javascript",
"typescript"
],
"yapf": [
"python"
]
}
}

View file

@ -0,0 +1,198 @@
{
config,
pkgs,
lib,
...
}:
with lib; let
helpers = import ../../helpers.nix {inherit lib;};
tools = trivial.importJSON ./efmls-configs-tools.json;
inherit (tools) linters formatters;
searchLanguages = tools: (lists.unique (builtins.concatLists (builtins.attrValues tools)));
languages =
lists.filter
(v: v != "misc") (lists.unique ((searchLanguages linters) ++ (searchLanguages formatters)));
in {
options.plugins.efmls-configs = {
enable = mkEnableOption "efmls-configs, premade configurations for efm-langserver";
package = helpers.mkPackageOption "efmls-configs-nvim" pkgs.vimPlugins.efmls-configs-nvim;
/*
Users can set the options as follows:
{
c = {
linter = "cppcheck";
formatter = ["clang-format" "uncrustify"];
};
go = {
linter = ["djlint" "golangci_lint"];
};
}
*/
setup = let
languageTools = lang: tools:
builtins.attrNames (attrsets.filterAttrs (_: lists.any (e: e == lang)) tools);
miscLinters = languageTools "misc" linters;
miscFormatters = languageTools "misc" formatters;
mkChooseOption = lang: kind: possible: let
toolType = with types; either (enum possible) helpers.rawType;
in
mkOption {
type = with types; either toolType (listOf toolType);
default = [];
description = "${kind} tools for ${lang}";
};
in
mkOption {
type = types.submodule {
freeformType = types.attrs;
options =
(builtins.listToAttrs (builtins.map (lang: let
langTools = languageTools lang;
in {
name = lang;
value = {
linter = mkChooseOption lang "linter" ((langTools linters) ++ miscLinters);
formatter = mkChooseOption lang "formatter" ((langTools formatters) ++ miscFormatters);
};
})
languages))
// {
all = {
linter = mkChooseOption "all languages" "linter" miscLinters;
formatter = mkChooseOption "all languages" "formatter" miscFormatters;
};
};
};
description = "Configuration for each filetype. Use `all` to match any filetype.";
default = {};
};
};
config = let
cfg = config.plugins.efmls-configs;
# Mapping of tool name to the nixpkgs package (if any)
toolPkgs = {
inherit
(pkgs)
ameba
astyle
bashate
black
cbfmt
clazy
cppcheck
cpplint
dmd
dprint
fish
flawfinder
gcc
golines
golint
hadolint
joker
languagetool
nixfmt
php
prettierd
proselint
pylint
rubocop
rustfmt
shellcheck
shfmt
smlfmt
statix
stylua
uncrustify
vale
yamllint
yapf
;
inherit (pkgs.python3.pkgs) autopep8 flake8 vulture;
inherit (pkgs.nodePackages) eslint eslint_d prettier alex stylelint textlint write-good;
inherit (pkgs.phpPackages) phpcbf phan phpcs phpstan psalm;
inherit (pkgs.luaPackages) luacheck;
ansible_lint = pkgs.ansible-lint;
clang_format = pkgs.clang-tools;
clang_tidy = pkgs.clang-tools;
clj_kondo = pkgs.clj-kondo;
dartfmt = pkgs.dart;
dotnet_format = pkgs.dotnet-runtime;
fish_indent = pkgs.fish;
gofmt = pkgs.go;
goimports = pkgs.go-tools;
golangci_lint = pkgs.golangci-lint;
go_revive = pkgs.revive;
lua_format = pkgs.luaformatter;
mcs = pkgs.mono;
php_cs_fixer = pkgs.phpPackages.php-cs-fixer;
slither = pkgs.slither-analyzer;
staticcheck = pkgs.go-tools;
terraform_fmt = pkgs.terraform;
vint = pkgs.vim-vint;
};
toolAsList = tools:
if builtins.isList tools
then tools
else [tools];
# Tools that have been selected by the user
tools = lists.unique (builtins.filter builtins.isString (
builtins.concatLists (
builtins.map ({
linter ? [],
formatter ? [],
}:
(toolAsList linter) ++ (toolAsList formatter))
(builtins.attrValues cfg.setup)
)
));
pkgsToInstall =
builtins.map (v: toolPkgs.${v})
(builtins.filter (v: builtins.hasAttr v toolPkgs) tools);
mkToolOption = kind: opt:
builtins.map
(tool:
if builtins.isString tool
then helpers.mkRaw "require 'efmls-configs.${kind}.${tool}'"
else tool)
(toolAsList opt);
setupOptions =
(builtins.mapAttrs (
_: {
linter ? [],
formatter ? [],
}:
(mkToolOption "linters" linter)
++ (mkToolOption "formatters" formatter)
)
(attrsets.filterAttrs (v: _: v != "all") cfg.setup))
// {
"=" =
(mkToolOption "linters" cfg.setup.all.linter)
++ (mkToolOption "formatters" cfg.setup.all.formatter);
};
in
mkIf cfg.enable {
extraPlugins = [cfg.package];
plugins.lsp.servers.efm = {
enable = true;
extraOptions.settings.languages = setupOptions;
};
extraPackages = [pkgs.efm-langserver] ++ pkgsToInstall;
};
}

View file

@ -0,0 +1,37 @@
{
empty = {
plugins.efmls-configs.enable = true;
};
example = {
extraConfigLuaPre = ''
local efm_fs = require('efmls-configs.fs')
local djlint_fmt = {
formatCommand = string.format('%s --reformat ''${INPUT} -', efm_fs.executable('djlint')),
formatStdin = true,
}
'';
plugins.efmls-configs = {
enable = true;
setup = {
# Setup for all languages
all = {
linter = "vale";
};
# Only accepts known tools, or raw strings
html = {
formatter = ["prettier" {__raw = "djlint_fmt";}];
};
# Unknown filetype, accepts anything
htmldjango = {
formatter = [{__raw = "djlint_fmt";}];
linter = "djlint";
};
};
};
};
}