at master 126 lines 3.6 kB view raw
1#!/usr/bin/env nix-shell 2#!nix-shell ./update-shell.nix -i python 3 4import json 5import logging 6import os 7import subprocess 8from concurrent.futures import ThreadPoolExecutor 9from pathlib import Path 10 11import requests 12 13log = logging.getLogger("vim-updater") 14 15NURR_JSON_URL = ( 16 "https://raw.githubusercontent.com/nvim-neorocks/nurr/main/tree-sitter-parsers.json" 17) 18 19 20def generate_grammar(lang, parser_info): 21 """Generate grammar for a language based on the parser info""" 22 if "install_info" not in parser_info: 23 log.warning(f"Parser {lang} does not have install_info, skipping") 24 return "" 25 26 install_info = parser_info["install_info"] 27 28 url = install_info["url"] 29 rev = install_info["revision"] 30 31 generated = f""" {lang} = buildGrammar {{ 32 language = "{lang}"; 33 version = "0.0.0+rev={rev[:7]}"; 34 src = """ 35 36 generated += subprocess.check_output( 37 ["nurl", url, rev, "--indent=4"], text=True 38 ) 39 generated += ";" 40 41 location = install_info.get("location", "") 42 if location: 43 generated += f""" 44 location = "{location}";""" 45 46 if install_info.get("generate", False): 47 generated += """ 48 generate = true;""" 49 50 generated += f""" 51 meta.homepage = "{url}"; 52 }}; 53""" 54 55 return generated 56 57 58def fetch_nurr_parsers(): 59 """Fetch the parser information from nurr repository""" 60 log.info("Fetching parser data from %s", NURR_JSON_URL) 61 62 headers = {} 63 github_token = os.environ.get("GITHUB_TOKEN") 64 if github_token: 65 log.info("Using GITHUB_TOKEN for authentication") 66 headers["Authorization"] = f"token {github_token}" 67 else: 68 log.warning("No GITHUB_TOKEN found. GitHub API requests may be rate-limited.") 69 70 response = requests.get(NURR_JSON_URL, headers=headers, timeout=30) 71 response.raise_for_status() 72 data = response.json() 73 74 try: 75 parsers = data["parsers"] 76 except KeyError: 77 raise ValueError( 78 "Unexpected response from NURR:\n" + json.dumps(data, indent=2) 79 ) 80 log.info(f"Successfully fetched {len(parsers)} parsers") 81 return parsers 82 83 84def process_parser_info(parser_info): 85 """Process a single parser info entry and generate grammar for it""" 86 return generate_grammar(parser_info["lang"], parser_info) 87 88 89def update_grammars(): 90 """Update grammar definitions using nurr's parser information""" 91 parsers_info = fetch_nurr_parsers() 92 93 generated_file = """# generated by pkgs/applications/editors/vim/plugins/utils/nvim-treesitter/update.py 94# Using parser data from https://github.com/nvim-neorocks/nurr/blob/main/tree-sitter-parsers.json 95 96{ 97 buildGrammar, 98 """ 99 100 nurl_output = subprocess.check_output(["nurl", "-Ls", ","], text=True).strip() 101 indented_output = nurl_output.replace(",", ",\n ") 102 generated_file += indented_output 103 generated_file += """, 104}: 105 106{ 107""" 108 109 # Process parsers in parallel for better performance 110 with ThreadPoolExecutor(max_workers=5) as executor: 111 for generated in executor.map(process_parser_info, parsers_info): 112 generated_file += generated 113 114 generated_file += "}\n" 115 return generated_file 116 117 118if __name__ == "__main__": 119 logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s") 120 121 generated = update_grammars() 122 output_path = Path(__file__).parent.parent.parent / "nvim-treesitter/generated.nix" 123 log.info("Writing output to %s", output_path) 124 with open(output_path, "w") as f: 125 f.write(generated) 126 log.info("Successfully updated grammar definitions")