nix-community.nixvim/flake/dev/new-plugin.py
2025-05-23 22:37:41 +10:00

233 lines
6.3 KiB
Python

#!/usr/bin/env python3
import os
import re
from argparse import ArgumentParser
# Template for default.nix
# TODO: conditionally include parts of the template based on args
default_nix_template = """{{ lib, ... }}:
lib.nixvim.plugins.mkNeovimPlugin {{
name = "{name}";
moduleName = "LUA_MODULE_NAME"; # TODO replace (or remove entirely if it is the same as `name`)
packPathName = "{originalName}";
package = "{package}";
{maintainer_todo}maintainers = [ lib.maintainers.{maintainer} ];
# TODO provide an example for the `settings` option (or remove entirely if there is no useful example)
# NOTE you can use `lib.literalExpression` or `lib.literalMD` if needed
settingsExample = {{
foo = 42;
bar.__raw = "function() print('hello') end";
}};
}}
"""
# Template for test file
test_nix_template = """{{
empty = {{
plugins.{name}.enable = true;
}};
defaults = {{
plugins.{name} = {{
enable = true;
settings = {{
foo = 42;
bar.__raw = "function() print('hello') end";
}};
}};
}};
}}
"""
def to_kebab_case(input_string):
"""
Convert a string to kebab-case.
Args:
input_string (str): The input string to convert.
Returns:
str: The converted kebab-case string.
"""
# Replace non-alphanumeric characters with hyphens
input_string = re.sub(r"[\W_]+", "-", input_string).lower()
return input_string.strip("-")
def strip_nvim(input_string):
"""
Remove 'nvim' prefix or suffix from a string.
Args:
input_string (str): The input string to process.
Returns:
str: The string with 'nvim' removed from start or end.
"""
# Remove leading and trailing standalone 'nvim'
input_string = re.sub(r"(^nvim-|-nvim$|^nvim$)", "", input_string)
return input_string.strip("-")
def create_nix_file(
file_path,
template,
name,
originalName,
package,
maintainer,
is_default_maintainer=False,
dry_run=False,
):
"""
Create a nix file from a template.
Args:
file_path (str): The path to the file to create.
template (str): The template string to use for the file content.
name (str): The name of the plugin.
originalName (str): The original name of the plugin.
package (str): The package name of the plugin.
maintainer (str): The maintainer name from lib.maintainers.
is_default_maintainer (bool): Whether the maintainer is the default value.
dry_run (bool): If True, only print what would be written instead of actually writing.
"""
# Add a TODO comment if using the default maintainer
maintainer_todo = (
"# TODO replace with your name \n " if is_default_maintainer else ""
)
content = template.format(
name=name,
originalName=originalName,
package=package,
maintainer=maintainer,
maintainer_todo=maintainer_todo,
)
write_to_file(file_path, content, dry_run)
def create_test_file(file_path, template, name, dry_run=False):
"""
Create a test file from a template.
Args:
file_path (str): The path to the file to create.
template (str): The template string to use for the file content.
name (str): The name of the plugin.
dry_run (bool): If True, only print what would be written instead of actually writing.
"""
content = template.format(name=name)
write_to_file(file_path, content, dry_run)
def write_to_file(file_path, content: str, dry_run=False):
"""
Makes sure directories exist and write content to a file.
Args:
file_path (str): The path to the file to write.
content (str): The content to write to the file.
dry_run (bool): If True, only print what would be written instead of actually writing.
"""
if dry_run:
print(f"Would write to {file_path}:")
print("=" * 40)
print(content)
print("=" * 40)
return
os.makedirs(os.path.dirname(file_path), exist_ok=True)
with open(file_path, "w") as f:
f.write(content)
def find_project_root(root_identifier):
current_path = os.getcwd()
while True:
if root_identifier in os.listdir(current_path):
return current_path
parent_path = os.path.dirname(current_path)
if parent_path == current_path:
return None
os.chdir("..")
current_path = os.getcwd()
# TODO: support interactive unmanaged args
def main():
"""
Main function to generate default.nix and test files for a new plugin.
"""
DEFAULT_MAINTAINER = "YOUR_NAME"
parser = ArgumentParser(
description="Generate default.nix and test files for a new plugin"
)
parser.add_argument(
"originalName", type=str, help="Original name of the new plugin"
)
parser.add_argument(
"--package",
"-p",
type=str,
help="Package name of the new plugin (defaults to normalized version of originalName)",
)
parser.add_argument(
"--maintainer",
"-m",
type=str,
help="Maintainer name (from lib.maintainers)",
default=DEFAULT_MAINTAINER,
)
parser.add_argument(
"--dry-run",
"-d",
action="store_true",
help="Show what would be written without actually creating files",
)
args = parser.parse_args()
# Calculate name - convert to kebab case and strip nvim
name = strip_nvim(to_kebab_case(args.originalName))
# Use provided package name or default to normalized original name
package = args.package if args.package else to_kebab_case(args.originalName)
# Check if user provided a maintainer or we're using the default
is_default_maintainer = args.maintainer == DEFAULT_MAINTAINER
# Define paths
root_identifier = "flake.nix"
root_dir = find_project_root(root_identifier)
plugin_path = f"{root_dir}/plugins/by-name/{name}/default.nix"
test_path = f"{root_dir}/tests/test-sources/plugins/by-name/{name}/default.nix"
# Create files
create_nix_file(
plugin_path,
default_nix_template,
name,
args.originalName,
package,
args.maintainer,
is_default_maintainer,
args.dry_run,
)
create_test_file(
test_path,
test_nix_template,
name,
args.dry_run,
)
if __name__ == "__main__":
main()