From c505e877053e59549e73b784f3f04bb59b12fdf3 Mon Sep 17 00:00:00 2001 From: Sergei Zharinov Date: Mon, 12 Jan 2026 23:05:15 -0300 Subject: [PATCH] feat: Add `sync-langs.py` script to automate arborium feature sync --- .github/renovate.json | 3 +- .github/workflows/sync-langs.yml | 24 ++++ Cargo.lock | 24 ++-- crates/plotnik-cli/Cargo.toml | 10 +- crates/plotnik-langs/Cargo.toml | 208 ++++++++++++++-------------- crates/plotnik-langs/src/builtin.rs | 16 +-- scripts/sync-langs.py | 154 ++++++++++++++++++++ 7 files changed, 314 insertions(+), 125 deletions(-) create mode 100644 .github/workflows/sync-langs.yml create mode 100644 scripts/sync-langs.py diff --git a/.github/renovate.json b/.github/renovate.json index 47adda46..4263b8b0 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -6,7 +6,8 @@ { "matchManagers": ["cargo"], "groupName": "arborium crates", - "matchPackageNames": ["/^arborium-/"] + "matchPackageNames": ["/^arborium/"], + "rangeStrategy": "bump" } ] } diff --git a/.github/workflows/sync-langs.yml b/.github/workflows/sync-langs.yml new file mode 100644 index 00000000..5b1162ab --- /dev/null +++ b/.github/workflows/sync-langs.yml @@ -0,0 +1,24 @@ +name: Sync arborium languages + +on: + push: + branches: + - 'renovate/arborium-crates' + +jobs: + sync: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Sync language features + run: python scripts/sync-langs.py + + - name: Commit if changed + run: | + git diff --quiet crates/*/Cargo.toml && exit 0 + git config user.name github-actions[bot] + git config user.email github-actions[bot]@users.noreply.github.com + git add crates/*/Cargo.toml + git commit -m "chore: Sync arborium language features" + git push diff --git a/Cargo.lock b/Cargo.lock index f1827367..1a99df0c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -571,17 +571,6 @@ dependencies = [ "tree-sitter-language", ] -[[package]] -name = "arborium-kdl" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c612bc9e6722e220891ae7ddefc7a2e0092814e9d85941e78f095fc57500d284" -dependencies = [ - "arborium-sysroot", - "cc", - "tree-sitter-language", -] - [[package]] name = "arborium-kotlin" version = "2.9.0" @@ -873,6 +862,17 @@ dependencies = [ "tree-sitter-language", ] +[[package]] +name = "arborium-solidity" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9c15dfc46eac8f5ea4fe97f7a9658be60eb641aeabe17bd4226e1c8e252b199" +dependencies = [ + "arborium-sysroot", + "cc", + "tree-sitter-language", +] + [[package]] name = "arborium-sparql" version = "2.9.0" @@ -1682,7 +1682,6 @@ dependencies = [ "arborium-jq", "arborium-json", "arborium-julia", - "arborium-kdl", "arborium-kotlin", "arborium-lean", "arborium-lua", @@ -1709,6 +1708,7 @@ dependencies = [ "arborium-scala", "arborium-scheme", "arborium-scss", + "arborium-solidity", "arborium-sparql", "arborium-sql", "arborium-ssh-config", diff --git a/crates/plotnik-cli/Cargo.toml b/crates/plotnik-cli/Cargo.toml index c6deccea..f67c3fe1 100644 --- a/crates/plotnik-cli/Cargo.toml +++ b/crates/plotnik-cli/Cargo.toml @@ -34,6 +34,7 @@ default = [ "lang-yaml", ] all-languages = [ +# @generated:all-languages:begin "lang-ada", "lang-agda", "lang-asciidoc", @@ -79,7 +80,6 @@ all-languages = [ "lang-jq", "lang-json", "lang-julia", - "lang-kdl", "lang-kotlin", "lang-lean", "lang-lua", @@ -106,6 +106,7 @@ all-languages = [ "lang-scala", "lang-scheme", "lang-scss", + "lang-solidity", "lang-sparql", "lang-sql", "lang-ssh-config", @@ -132,7 +133,9 @@ all-languages = [ "lang-yuri", "lang-zig", "lang-zsh", +# @generated:all-languages:end ] +# @generated:lang-features:begin lang-ada = ["plotnik-langs/lang-ada"] lang-agda = ["plotnik-langs/lang-agda"] lang-asciidoc = ["plotnik-langs/lang-asciidoc"] @@ -178,7 +181,6 @@ lang-jinja2 = ["plotnik-langs/lang-jinja2"] lang-jq = ["plotnik-langs/lang-jq"] lang-json = ["plotnik-langs/lang-json"] lang-julia = ["plotnik-langs/lang-julia"] -lang-kdl = ["plotnik-langs/lang-kdl"] lang-kotlin = ["plotnik-langs/lang-kotlin"] lang-lean = ["plotnik-langs/lang-lean"] lang-lua = ["plotnik-langs/lang-lua"] @@ -205,6 +207,7 @@ lang-rust = ["plotnik-langs/lang-rust"] lang-scala = ["plotnik-langs/lang-scala"] lang-scheme = ["plotnik-langs/lang-scheme"] lang-scss = ["plotnik-langs/lang-scss"] +lang-solidity = ["plotnik-langs/lang-solidity"] lang-sparql = ["plotnik-langs/lang-sparql"] lang-sql = ["plotnik-langs/lang-sql"] lang-ssh-config = ["plotnik-langs/lang-ssh-config"] @@ -231,13 +234,14 @@ lang-yaml = ["plotnik-langs/lang-yaml"] lang-yuri = ["plotnik-langs/lang-yuri"] lang-zig = ["plotnik-langs/lang-zig"] lang-zsh = ["plotnik-langs/lang-zsh"] +# @generated:lang-features:end [dependencies] clap = { version = "4.5", features = ["derive"] } plotnik-core.workspace = true plotnik-langs = { path = "../plotnik-langs", version = "0.2.2", default-features = false } plotnik-lib.workspace = true -arborium-tree-sitter = "2.5.0" +arborium-tree-sitter = "2.7.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" thiserror = "2.0" diff --git a/crates/plotnik-langs/Cargo.toml b/crates/plotnik-langs/Cargo.toml index 289b4341..3c7354cd 100644 --- a/crates/plotnik-langs/Cargo.toml +++ b/crates/plotnik-langs/Cargo.toml @@ -31,6 +31,7 @@ default = [ # All languages all-languages = [ +# @generated:all-languages:begin "lang-ada", "lang-agda", "lang-asciidoc", @@ -76,7 +77,6 @@ all-languages = [ "lang-jq", "lang-json", "lang-julia", - "lang-kdl", "lang-kotlin", "lang-lean", "lang-lua", @@ -103,6 +103,7 @@ all-languages = [ "lang-scala", "lang-scheme", "lang-scss", + "lang-solidity", "lang-sparql", "lang-sql", "lang-ssh-config", @@ -129,9 +130,11 @@ all-languages = [ "lang-yuri", "lang-zig", "lang-zsh", +# @generated:all-languages:end ] # Individual language features +# @generated:lang-features:begin lang-ada = ["dep:arborium-ada"] lang-agda = ["dep:arborium-agda"] lang-asciidoc = ["dep:arborium-asciidoc"] @@ -177,7 +180,6 @@ lang-jinja2 = ["dep:arborium-jinja2"] lang-jq = ["dep:arborium-jq"] lang-json = ["dep:arborium-json"] lang-julia = ["dep:arborium-julia"] -lang-kdl = ["dep:arborium-kdl"] lang-kotlin = ["dep:arborium-kotlin"] lang-lean = ["dep:arborium-lean"] lang-lua = ["dep:arborium-lua"] @@ -204,6 +206,7 @@ lang-rust = ["dep:arborium-rust"] lang-scala = ["dep:arborium-scala"] lang-scheme = ["dep:arborium-scheme"] lang-scss = ["dep:arborium-scss"] +lang-solidity = ["dep:arborium-solidity"] lang-sparql = ["dep:arborium-sparql"] lang-sql = ["dep:arborium-sql"] lang-ssh-config = ["dep:arborium-ssh-config"] @@ -230,110 +233,113 @@ lang-yaml = ["dep:arborium-yaml"] lang-yuri = ["dep:arborium-yuri"] lang-zig = ["dep:arborium-zig"] lang-zsh = ["dep:arborium-zsh"] +# @generated:lang-features:end [dependencies] paste = "1.0" plotnik-core.workspace = true postcard = { version = "1", features = ["alloc"] } -arborium-tree-sitter = "2.5.0" -arborium-ada = { version = "2.5.0", optional = true } -arborium-agda = { version = "2.5.0", optional = true } -arborium-asciidoc = { version = "2.5.0", optional = true } -arborium-asm = { version = "2.5.0", optional = true } -arborium-awk = { version = "2.5.0", optional = true } -arborium-bash = { version = "2.5.0", optional = true } -arborium-batch = { version = "2.5.0", optional = true } -arborium-c = { version = "2.5.0", optional = true } -arborium-c-sharp = { version = "2.5.0", optional = true } -arborium-caddy = { version = "2.5.0", optional = true } -arborium-capnp = { version = "2.5.0", optional = true } -arborium-clojure = { version = "2.5.0", optional = true } -arborium-cmake = { version = "2.5.0", optional = true } -arborium-commonlisp = { version = "2.5.0", optional = true } -arborium-cpp = { version = "2.5.0", optional = true } -arborium-css = { version = "2.5.0", optional = true } -arborium-d = { version = "2.5.0", optional = true } -arborium-dart = { version = "2.5.0", optional = true } -arborium-devicetree = { version = "2.5.0", optional = true } -arborium-diff = { version = "2.5.0", optional = true } -arborium-dockerfile = { version = "2.5.0", optional = true } -arborium-dot = { version = "2.5.0", optional = true } -arborium-elisp = { version = "2.5.0", optional = true } -arborium-elixir = { version = "2.5.0", optional = true } -arborium-elm = { version = "2.5.0", optional = true } -arborium-erlang = { version = "2.5.0", optional = true } -arborium-fish = { version = "2.5.0", optional = true } -arborium-fsharp = { version = "2.5.0", optional = true } -arborium-gleam = { version = "2.5.0", optional = true } -arborium-glsl = { version = "2.5.0", optional = true } -arborium-go = { version = "2.5.0", optional = true } -arborium-graphql = { version = "2.5.0", optional = true } -arborium-groovy = { version = "2.5.0", optional = true } -arborium-haskell = { version = "2.5.0", optional = true } -arborium-hcl = { version = "2.5.0", optional = true } -arborium-hlsl = { version = "2.5.0", optional = true } -arborium-html = { version = "2.5.0", optional = true } -arborium-idris = { version = "2.5.0", optional = true } -arborium-ini = { version = "2.5.0", optional = true } -arborium-java = { version = "2.5.0", optional = true } -arborium-javascript = { version = "2.5.0", optional = true } -arborium-jinja2 = { version = "2.5.0", optional = true } -arborium-jq = { version = "2.5.0", optional = true } -arborium-json = { version = "2.5.0", optional = true } -arborium-julia = { version = "2.5.0", optional = true } -arborium-kdl = { version = "2.5.0", optional = true } -arborium-kotlin = { version = "2.5.0", optional = true } -arborium-lean = { version = "2.5.0", optional = true } -arborium-lua = { version = "2.5.0", optional = true } -arborium-markdown = { version = "2.5.0", optional = true } -arborium-matlab = { version = "2.5.0", optional = true } -arborium-meson = { version = "2.5.0", optional = true } -arborium-nginx = { version = "2.5.0", optional = true } -arborium-ninja = { version = "2.5.0", optional = true } -arborium-nix = { version = "2.5.0", optional = true } -arborium-objc = { version = "2.5.0", optional = true } -arborium-ocaml = { version = "2.5.0", optional = true } -arborium-perl = { version = "2.5.0", optional = true } -arborium-php = { version = "2.5.0", optional = true } -arborium-postscript = { version = "2.5.0", optional = true } -arborium-powershell = { version = "2.5.0", optional = true } -arborium-prolog = { version = "2.5.0", optional = true } -arborium-python = { version = "2.5.0", optional = true } -arborium-query = { version = "2.5.0", optional = true } -arborium-r = { version = "2.5.0", optional = true } -arborium-rescript = { version = "2.5.0", optional = true } -arborium-ron = { version = "2.5.0", optional = true } -arborium-ruby = { version = "2.5.0", optional = true } -arborium-rust = { version = "2.5.0", optional = true } -arborium-scala = { version = "2.5.0", optional = true } -arborium-scheme = { version = "2.5.0", optional = true } -arborium-scss = { version = "2.5.0", optional = true } -arborium-sparql = { version = "2.5.0", optional = true } -arborium-sql = { version = "2.5.0", optional = true } -arborium-ssh-config = { version = "2.5.0", optional = true } -arborium-starlark = { version = "2.5.0", optional = true } -arborium-svelte = { version = "2.5.0", optional = true } -arborium-swift = { version = "2.5.0", optional = true } -arborium-textproto = { version = "2.5.0", optional = true } -arborium-thrift = { version = "2.5.0", optional = true } -arborium-tlaplus = { version = "2.5.0", optional = true } -arborium-toml = { version = "2.5.0", optional = true } -arborium-tsx = { version = "2.5.0", optional = true } -arborium-typescript = { version = "2.5.0", optional = true } -arborium-typst = { version = "2.5.0", optional = true } -arborium-uiua = { version = "2.5.0", optional = true } -arborium-vb = { version = "2.5.0", optional = true } -arborium-verilog = { version = "2.5.0", optional = true } -arborium-vhdl = { version = "2.5.0", optional = true } -arborium-vim = { version = "2.5.0", optional = true } -arborium-vue = { version = "2.5.0", optional = true } -arborium-wit = { version = "2.5.0", optional = true } -arborium-x86asm = { version = "2.5.0", optional = true } -arborium-xml = { version = "2.5.0", optional = true } -arborium-yaml = { version = "2.5.0", optional = true } -arborium-yuri = { version = "2.5.0", optional = true } -arborium-zig = { version = "2.5.0", optional = true } -arborium-zsh = { version = "2.5.0", optional = true } +arborium-tree-sitter = "2.7.0" +# @generated:lang-deps:begin +arborium-ada = { version = "2.7.0", optional = true } +arborium-agda = { version = "2.7.0", optional = true } +arborium-asciidoc = { version = "2.7.0", optional = true } +arborium-asm = { version = "2.7.0", optional = true } +arborium-awk = { version = "2.7.0", optional = true } +arborium-bash = { version = "2.7.0", optional = true } +arborium-batch = { version = "2.7.0", optional = true } +arborium-c = { version = "2.7.0", optional = true } +arborium-c-sharp = { version = "2.7.0", optional = true } +arborium-caddy = { version = "2.7.0", optional = true } +arborium-capnp = { version = "2.7.0", optional = true } +arborium-clojure = { version = "2.7.0", optional = true } +arborium-cmake = { version = "2.7.0", optional = true } +arborium-commonlisp = { version = "2.7.0", optional = true } +arborium-cpp = { version = "2.7.0", optional = true } +arborium-css = { version = "2.7.0", optional = true } +arborium-d = { version = "2.7.0", optional = true } +arborium-dart = { version = "2.7.0", optional = true } +arborium-devicetree = { version = "2.7.0", optional = true } +arborium-diff = { version = "2.7.0", optional = true } +arborium-dockerfile = { version = "2.7.0", optional = true } +arborium-dot = { version = "2.7.0", optional = true } +arborium-elisp = { version = "2.7.0", optional = true } +arborium-elixir = { version = "2.7.0", optional = true } +arborium-elm = { version = "2.7.0", optional = true } +arborium-erlang = { version = "2.7.0", optional = true } +arborium-fish = { version = "2.7.0", optional = true } +arborium-fsharp = { version = "2.7.0", optional = true } +arborium-gleam = { version = "2.7.0", optional = true } +arborium-glsl = { version = "2.7.0", optional = true } +arborium-go = { version = "2.7.0", optional = true } +arborium-graphql = { version = "2.7.0", optional = true } +arborium-groovy = { version = "2.7.0", optional = true } +arborium-haskell = { version = "2.7.0", optional = true } +arborium-hcl = { version = "2.7.0", optional = true } +arborium-hlsl = { version = "2.7.0", optional = true } +arborium-html = { version = "2.7.0", optional = true } +arborium-idris = { version = "2.7.0", optional = true } +arborium-ini = { version = "2.7.0", optional = true } +arborium-java = { version = "2.7.0", optional = true } +arborium-javascript = { version = "2.7.0", optional = true } +arborium-jinja2 = { version = "2.7.0", optional = true } +arborium-jq = { version = "2.7.0", optional = true } +arborium-json = { version = "2.7.0", optional = true } +arborium-julia = { version = "2.7.0", optional = true } +arborium-kotlin = { version = "2.7.0", optional = true } +arborium-lean = { version = "2.7.0", optional = true } +arborium-lua = { version = "2.7.0", optional = true } +arborium-markdown = { version = "2.7.0", optional = true } +arborium-matlab = { version = "2.7.0", optional = true } +arborium-meson = { version = "2.7.0", optional = true } +arborium-nginx = { version = "2.7.0", optional = true } +arborium-ninja = { version = "2.7.0", optional = true } +arborium-nix = { version = "2.7.0", optional = true } +arborium-objc = { version = "2.7.0", optional = true } +arborium-ocaml = { version = "2.7.0", optional = true } +arborium-perl = { version = "2.7.0", optional = true } +arborium-php = { version = "2.7.0", optional = true } +arborium-postscript = { version = "2.7.0", optional = true } +arborium-powershell = { version = "2.7.0", optional = true } +arborium-prolog = { version = "2.7.0", optional = true } +arborium-python = { version = "2.7.0", optional = true } +arborium-query = { version = "2.7.0", optional = true } +arborium-r = { version = "2.7.0", optional = true } +arborium-rescript = { version = "2.7.0", optional = true } +arborium-ron = { version = "2.7.0", optional = true } +arborium-ruby = { version = "2.7.0", optional = true } +arborium-rust = { version = "2.7.0", optional = true } +arborium-scala = { version = "2.7.0", optional = true } +arborium-scheme = { version = "2.7.0", optional = true } +arborium-scss = { version = "2.7.0", optional = true } +arborium-solidity = { version = "2.7.0", optional = true } +arborium-sparql = { version = "2.7.0", optional = true } +arborium-sql = { version = "2.7.0", optional = true } +arborium-ssh-config = { version = "2.7.0", optional = true } +arborium-starlark = { version = "2.7.0", optional = true } +arborium-svelte = { version = "2.7.0", optional = true } +arborium-swift = { version = "2.7.0", optional = true } +arborium-textproto = { version = "2.7.0", optional = true } +arborium-thrift = { version = "2.7.0", optional = true } +arborium-tlaplus = { version = "2.7.0", optional = true } +arborium-toml = { version = "2.7.0", optional = true } +arborium-tsx = { version = "2.7.0", optional = true } +arborium-typescript = { version = "2.7.0", optional = true } +arborium-typst = { version = "2.7.0", optional = true } +arborium-uiua = { version = "2.7.0", optional = true } +arborium-vb = { version = "2.7.0", optional = true } +arborium-verilog = { version = "2.7.0", optional = true } +arborium-vhdl = { version = "2.7.0", optional = true } +arborium-vim = { version = "2.7.0", optional = true } +arborium-vue = { version = "2.7.0", optional = true } +arborium-wit = { version = "2.7.0", optional = true } +arborium-x86asm = { version = "2.7.0", optional = true } +arborium-xml = { version = "2.7.0", optional = true } +arborium-yaml = { version = "2.7.0", optional = true } +arborium-yuri = { version = "2.7.0", optional = true } +arborium-zig = { version = "2.7.0", optional = true } +arborium-zsh = { version = "2.7.0", optional = true } +# @generated:lang-deps:end [build-dependencies] cargo_metadata = "0.23" diff --git a/crates/plotnik-langs/src/builtin.rs b/crates/plotnik-langs/src/builtin.rs index fb23f6e2..f4e167e0 100644 --- a/crates/plotnik-langs/src/builtin.rs +++ b/crates/plotnik-langs/src/builtin.rs @@ -465,14 +465,6 @@ define_langs! { names: ["julia", "jl"], extensions: ["jl"], }, - kdl => { - feature: "lang-kdl", - name: "kdl", - ts_lang: arborium_kdl::language(), - lang_key: "KDL", - names: ["kdl"], - extensions: ["kdl"], - }, kotlin => { feature: "lang-kotlin", name: "kotlin", @@ -681,6 +673,14 @@ define_langs! { names: ["scss", "sass"], extensions: ["scss", "sass"], }, + solidity => { + feature: "lang-solidity", + name: "solidity", + ts_lang: arborium_solidity::language(), + lang_key: "SOLIDITY", + names: ["solidity", "sol"], + extensions: ["sol"], + }, sparql => { feature: "lang-sparql", name: "sparql", diff --git a/scripts/sync-langs.py b/scripts/sync-langs.py new file mode 100644 index 00000000..7ccdf132 --- /dev/null +++ b/scripts/sync-langs.py @@ -0,0 +1,154 @@ +#!/usr/bin/env python3 +"""Sync arborium language features from crates.io. + +Fetches available lang-* features from arborium crate and updates: +- crates/plotnik-langs/Cargo.toml (features + dependencies) +- crates/plotnik-cli/Cargo.toml (feature re-exports) + +Usage: + python scripts/sync-langs.py [--version VERSION] [--dry-run] +""" + +import argparse +import json +import re +import urllib.request +from pathlib import Path + + +def fetch_lang_features(version: str | None) -> tuple[str, list[str]]: + """Fetch lang-* features from crates.io API.""" + url = "https://crates.io/api/v1/crates/arborium" + req = urllib.request.Request(url, headers={"User-Agent": "plotnik-sync-langs"}) + with urllib.request.urlopen(req) as resp: + data = json.load(resp) + + versions = data["versions"] + if version: + ver = next((v for v in versions if v["num"] == version), None) + if not ver: + available = [v["num"] for v in versions[:10]] + raise ValueError(f"Version {version} not found. Available: {available}") + else: + ver = versions[0] + + features = ver["features"] + langs = sorted(k for k in features if k.startswith("lang-")) + return ver["num"], langs + + +def replace_section(content: str, start_marker: str, end_marker: str, new_content: str) -> str: + """Replace content between markers (exclusive of markers).""" + pattern = rf"({re.escape(start_marker)}\n).*?(\n{re.escape(end_marker)})" + replacement = rf"\g<1>{new_content}\g<2>" + result, count = re.subn(pattern, replacement, content, flags=re.DOTALL) + if count == 0: + raise ValueError(f"Markers not found: {start_marker!r} ... {end_marker!r}") + return result + + +def update_plotnik_langs(path: Path, version: str, langs: list[str], dry_run: bool) -> bool: + """Update plotnik-langs/Cargo.toml.""" + content = path.read_text() + original = content + + # Generate all-languages array + all_langs_items = "\n".join(f' "{lang}",' for lang in langs) + content = replace_section( + content, + "# @generated:all-languages:begin", + "# @generated:all-languages:end", + all_langs_items, + ) + + # Generate individual features + features = "\n".join(f'{lang} = ["dep:arborium-{lang[5:]}"]' for lang in langs) + content = replace_section( + content, + "# @generated:lang-features:begin", + "# @generated:lang-features:end", + features, + ) + + # Generate dependencies + deps = "\n".join( + f'arborium-{lang[5:]} = {{ version = "{version}", optional = true }}' + for lang in langs + ) + content = replace_section( + content, + "# @generated:lang-deps:begin", + "# @generated:lang-deps:end", + deps, + ) + + if content == original: + print(f" {path}: no changes") + return False + + if dry_run: + print(f" {path}: would update") + else: + path.write_text(content) + print(f" {path}: updated") + return True + + +def update_plotnik_cli(path: Path, langs: list[str], dry_run: bool) -> bool: + """Update plotnik-cli/Cargo.toml.""" + content = path.read_text() + original = content + + # Generate all-languages array + all_langs_items = "\n".join(f' "{lang}",' for lang in langs) + content = replace_section( + content, + "# @generated:all-languages:begin", + "# @generated:all-languages:end", + all_langs_items, + ) + + # Generate individual features (re-exports) + features = "\n".join(f'{lang} = ["plotnik-langs/{lang}"]' for lang in langs) + content = replace_section( + content, + "# @generated:lang-features:begin", + "# @generated:lang-features:end", + features, + ) + + if content == original: + print(f" {path}: no changes") + return False + + if dry_run: + print(f" {path}: would update") + else: + path.write_text(content) + print(f" {path}: updated") + return True + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--version", help="arborium version (default: latest)") + parser.add_argument("--dry-run", action="store_true", help="print changes without writing") + args = parser.parse_args() + + version, langs = fetch_lang_features(args.version) + print(f"Found {len(langs)} languages in arborium {version}") + + root = Path(__file__).resolve().parent.parent + langs_toml = root / "crates/plotnik-langs/Cargo.toml" + cli_toml = root / "crates/plotnik-cli/Cargo.toml" + + changed = False + changed |= update_plotnik_langs(langs_toml, version, langs, args.dry_run) + changed |= update_plotnik_cli(cli_toml, langs, args.dry_run) + + if args.dry_run and changed: + print("\nRun without --dry-run to apply changes") + + +if __name__ == "__main__": + main()