mirror of
https://github.com/nix-community/nixvim.git
synced 2025-06-21 00:25:42 +02:00
* nvim-lsp: Add settings for rust-analyzer Because the settings are quite complex they are auto-generated. This commit adds the script creating it & the generated options. * Update flake.nix Co-authored-by: Pedro Alves <pta2002@users.noreply.github.com>
229 lines
5.8 KiB
Python
Executable file
229 lines
5.8 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
|
|
import sys
|
|
import json
|
|
|
|
ra_package_json = sys.argv[1]
|
|
with open(ra_package_json) as f:
|
|
ra_package = json.load(f)
|
|
|
|
config = ra_package["contributes"]["configuration"]["properties"]
|
|
|
|
config_dict = {}
|
|
|
|
in_common_block = False
|
|
|
|
|
|
def py_to_nix(obj):
|
|
if obj is None:
|
|
return "null"
|
|
|
|
if obj is False:
|
|
return "false"
|
|
|
|
if obj is True:
|
|
return "true"
|
|
|
|
if isinstance(obj, str):
|
|
s = f'"{obj}"'
|
|
if "${" in s:
|
|
s = s.replace("${", "$\\{")
|
|
return s
|
|
|
|
if isinstance(obj, int):
|
|
return f"{obj}"
|
|
|
|
if isinstance(obj, dict):
|
|
val = "{"
|
|
for key in obj:
|
|
key_val = py_to_nix(obj[key])
|
|
val += f'"{key}" = {key_val};\n'
|
|
val += "}"
|
|
|
|
return val
|
|
|
|
if isinstance(obj, list):
|
|
return "[" + " ".join(py_to_nix(val) for val in obj) + "]"
|
|
|
|
print(f"Unhandled value: {obj}")
|
|
sys.exit(1)
|
|
|
|
|
|
def ty_to_nix(ty):
|
|
if ty == "boolean":
|
|
return "types.bool"
|
|
|
|
if ty == "string":
|
|
return "types.str"
|
|
|
|
# This is an object without any additional properties
|
|
if ty == "object":
|
|
return "types.attrsOf types.anything"
|
|
|
|
if isinstance(ty, list) and ty[0] == "null":
|
|
if len(ty) > 2:
|
|
print("Unhandled type", ty)
|
|
sys.exit()
|
|
|
|
nullable_ty = ty_to_nix(ty[1])
|
|
return f"types.nullOr ({nullable_ty})"
|
|
|
|
if isinstance(ty, list):
|
|
either_types = (ty_to_nix(t) for t in ty)
|
|
either_types = " ".join(f"({t})" for t in either_types)
|
|
return f"types.oneOf ([{either_types}])"
|
|
|
|
print(f"Unhandled type: {ty}")
|
|
sys.exit(1)
|
|
|
|
|
|
def prop_ty_to_nix(prop_info):
|
|
if "type" in prop_info:
|
|
if "enum" in prop_info:
|
|
enum = "[" + " ".join(f'"{member}"' for member in prop_info["enum"]) + "]"
|
|
if prop_info["type"] == "string":
|
|
return f"types.enum {enum}"
|
|
|
|
print("TODO: with unknown enum type", prop_info["type"])
|
|
sys.exit()
|
|
|
|
if "additionalProperties" in prop_info or "properties" in prop_info:
|
|
print("TODO: with (additional)Properties", prop_info)
|
|
sys.exit()
|
|
|
|
if "minimum" in prop_info or "maximum" in prop_info:
|
|
can_be_null = False
|
|
if "null" in prop_info["type"]:
|
|
can_be_null = True
|
|
if len(prop_info["type"]) > 2:
|
|
print("Unhandled int type", prop_info["type"])
|
|
sys.exit()
|
|
prop_info["type"] = prop_info["type"][1]
|
|
|
|
if prop_info["type"] == "number":
|
|
int_ty = "types.number"
|
|
elif prop_info["type"] == "integer":
|
|
int_ty = "types.int"
|
|
else:
|
|
print("Unhandled int type", prop_info["type"])
|
|
sys.exit()
|
|
|
|
if "minimum" in prop_info and "maximum" in prop_info:
|
|
min = prop_info["minimum"]
|
|
max = prop_info["maximum"]
|
|
int_ty = f"{int_ty}s.between {min} {max}"
|
|
elif "minimum" in prop_info:
|
|
min = prop_info["minimum"]
|
|
int_ty = f"types.addCheck {int_ty} (x: x >= {min})"
|
|
else:
|
|
print("TODO: max number", prop_info)
|
|
sys.exit()
|
|
|
|
if can_be_null:
|
|
return f"types.nullOr ({int_ty})"
|
|
else:
|
|
return int_ty
|
|
|
|
if "array" in prop_info["type"] or prop_info["type"] == "array":
|
|
if "items" not in prop_info:
|
|
print("Array without items")
|
|
sys.exit()
|
|
|
|
items_ty = prop_ty_to_nix(prop_info["items"])
|
|
array_ty = f"types.listOf ({items_ty})"
|
|
if prop_info["type"] == "array":
|
|
return array_ty
|
|
elif prop_info["type"] == ["null", "array"]:
|
|
return f"types.nullOr ({array_ty})"
|
|
else:
|
|
print("Unhandled array type", prop_info)
|
|
sys.exit()
|
|
|
|
return ty_to_nix(prop_info["type"])
|
|
elif "anyOf" in prop_info:
|
|
can_be_null = False
|
|
if {"type": "null"} in prop_info["anyOf"]:
|
|
can_be_null = True
|
|
prop_info["anyOf"].remove({"type": "null"})
|
|
|
|
types = (prop_ty_to_nix(prop) for prop in prop_info["anyOf"])
|
|
one_of = " ".join(f"({ty})" for ty in types)
|
|
one_of_ty = f"types.oneOf ([{one_of}])"
|
|
|
|
if can_be_null:
|
|
return f"types.nullOr ({one_of_ty})"
|
|
else:
|
|
return one_of_ty
|
|
else:
|
|
print("TODO: no *type*", prop_info)
|
|
sys.exit()
|
|
|
|
|
|
for opt in config:
|
|
if opt.startswith("$"):
|
|
in_common_block = True
|
|
continue
|
|
|
|
if not in_common_block:
|
|
continue
|
|
|
|
opt_path = opt.split(".")
|
|
if opt_path[0] != "rust-analyzer":
|
|
print("ERROR: expected all options to start with 'rust-analyzer'")
|
|
sys.exit(1)
|
|
|
|
path = opt_path[1:-1]
|
|
option = opt_path[-1]
|
|
|
|
top_dict = config_dict
|
|
|
|
for p in path:
|
|
if not p in top_dict:
|
|
top_dict[p] = {}
|
|
top_dict = top_dict[p]
|
|
|
|
prop_info = config[opt]
|
|
|
|
is_optional = False
|
|
|
|
ty = prop_ty_to_nix(prop_info)
|
|
|
|
default = py_to_nix(prop_info["default"])
|
|
|
|
if "markdownDescription" in prop_info:
|
|
desc = prop_info["markdownDescription"]
|
|
else:
|
|
desc = prop_info["description"]
|
|
|
|
desc += f"\n\ndefault value is: \n```nix\n {default}\n```"
|
|
|
|
top_dict[
|
|
option
|
|
] = """
|
|
mkOption {{
|
|
type = types.nullOr ({ty});
|
|
default = null;
|
|
description = ''
|
|
{desc}
|
|
'';
|
|
}}
|
|
""".format(
|
|
ty=ty, default=default, desc=desc
|
|
)
|
|
|
|
|
|
def print_dict(d):
|
|
print("{")
|
|
for key in d:
|
|
print(f'"{key}" = ')
|
|
if isinstance(d[key], str):
|
|
print(d[key])
|
|
else:
|
|
print_dict(d[key])
|
|
print(";")
|
|
print("}")
|
|
|
|
|
|
print("# THIS FILE IS AUTOGENERATED DO NOT EDIT")
|
|
print("lib: with lib;")
|
|
print_dict(config_dict)
|