diff --git a/pyproject.toml b/pyproject.toml index d758f84..150a000 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "pdm.backend" [project] name = "typstar" -version = "1.1.0" +version = "1.1.1" description = "Neovim plugin for efficient note taking in Typst" authors = [ { name = "arne314" } @@ -14,10 +14,20 @@ requires-python = ">=3.11.10" dependencies = [ "aiohttp>=3.11.11", "appdirs>=1.4.4", - "tree-sitter-language-pack>=0.2.0", + "tree-sitter>=0.23.2", "typer>=0.15.1", + "tree-sitter-typst @ git+https://github.com/uben0/tree-sitter-typst" ] [project.scripts] typstar-anki = "anki.main:main" +[tool.ruff] +lint.extend-select = ["I"] +line-length = 100 + +[dependency-groups] +dev = [ + "ruff>=0.8.5", +] + diff --git a/src/anki/anki_api.py b/src/anki/anki_api.py index 5fd2ee4..b211d12 100644 --- a/src/anki/anki_api.py +++ b/src/anki/anki_api.py @@ -42,11 +42,17 @@ class AnkiConnectApi: update[card.deck].append(card) n_update += 1 - print(f"Pushing {n_add} new flashcards and {n_update} updated flashcards to Anki...", flush=True) + print( + f"Pushing {n_add} new flashcards and {n_update} updated flashcards to Anki...", + flush=True, + ) await self._create_required_decks({*add.keys(), *update.keys()}) await self._add_new_cards(add) await _gather_exceptions( - [*self._update_cards_requests(add), *self._update_cards_requests(update, True)] + [ + *self._update_cards_requests(add), + *self._update_cards_requests(update, True), + ] ) async def _request_api(self, action, **params): @@ -71,12 +77,16 @@ class AnkiConnectApi: await self._request_api("updateNoteModel", note=card.as_anki_model()) async def _store_media(self, card): - await self._request_api("storeMediaFile", - filename=card.svg_filename(True), - data=base64.b64encode(card.svg_front).decode()) - await self._request_api("storeMediaFile", - filename=card.svg_filename(False), - data=base64.b64encode(card.svg_back).decode()) + await self._request_api( + "storeMediaFile", + filename=card.svg_filename(True), + data=base64.b64encode(card.svg_front).decode(), + ) + await self._request_api( + "storeMediaFile", + filename=card.svg_filename(False), + data=base64.b64encode(card.svg_back).decode(), + ) async def _change_deck(self, deck: str, cards: List[int]): await self._request_api("changeDeck", deck=deck, cards=cards) @@ -107,7 +117,9 @@ class AnkiConnectApi: requests.append(self._request_api("createDeck", deck=deck)) await _gather_exceptions(requests) - def _update_cards_requests(self, cards_map: dict[str, List[Flashcard]], update_deck: bool = True): + def _update_cards_requests( + self, cards_map: dict[str, List[Flashcard]], update_deck: bool = True + ): requests = [] for deck, cards in cards_map.items(): card_ids = [] diff --git a/src/anki/file_handler.py b/src/anki/file_handler.py index 07726b6..dc31438 100644 --- a/src/anki/file_handler.py +++ b/src/anki/file_handler.py @@ -1,5 +1,4 @@ import hashlib - from pathlib import Path from typing import List @@ -8,7 +7,7 @@ import tree_sitter class FileHandler: file_path: Path - file_content: List[str] + file_content: List[bytes] def __init__(self, path: Path): self.file_path = path @@ -19,32 +18,39 @@ class FileHandler: return self.file_path.parent def get_bytes(self) -> bytes: - return bytes("".join(self.file_content), encoding="utf-8") + return b"".join(self.file_content) def get_file_hash(self) -> str: - return hashlib.md5("".join(self.file_content).encode(), usedforsecurity=False).hexdigest() + return hashlib.md5(self.get_bytes(), usedforsecurity=False).hexdigest() - def get_node_content(self, node: tree_sitter.Node, remove_outer=False): - content = "".join( - self.file_content[node.start_point.row:node.end_point.row + 1] - )[node.start_point.column:-(len(self.file_content[node.end_point.row]) - node.end_point.column)] + def get_node_content(self, node: tree_sitter.Node, remove_outer=False) -> str: + content = ( + b"".join(self.file_content[node.start_point.row : node.end_point.row + 1])[ + node.start_point.column : -( + len(self.file_content[node.end_point.row]) - node.end_point.column + ) + ] + ).decode() return content[1:-1] if remove_outer else content def update_node_content(self, node: tree_sitter.Node, value): - new_lines = self.file_content[:node.start_point.row] - first_line = self.file_content[node.start_point.row][:node.start_point.column] - last_line = self.file_content[node.end_point.row][node.end_point.column:] - new_lines.extend(( - line + "\n" for line in (first_line + str(value) + last_line).split("\n") - if line != "" - )) - new_lines.extend(self.file_content[node.end_point.row + 1:]) + new_lines = self.file_content[: node.start_point.row] + first_line = self.file_content[node.start_point.row][: node.start_point.column] + last_line = self.file_content[node.end_point.row][node.end_point.column :] + new_lines.extend( + ( + line + b"\n" + for line in (first_line + str(value).encode() + last_line).split(b"\n") + if line != b"" + ) + ) + new_lines.extend(self.file_content[node.end_point.row + 1 :]) self.file_content = new_lines def read(self): - with self.file_path.open(encoding="utf-8") as f: + with self.file_path.open("rb") as f: self.file_content = f.readlines() def write(self): - with self.file_path.open("w", encoding="utf-8") as f: + with self.file_path.open("wb") as f: f.writelines(self.file_content) diff --git a/src/anki/flashcard.py b/src/anki/flashcard.py index 8975192..ec8e23a 100644 --- a/src/anki/flashcard.py +++ b/src/anki/flashcard.py @@ -10,7 +10,7 @@ class Flashcard: deck: str id_updated: bool - preamble: str + preamble: str | None file_handler: FileHandler note_id_node: tree_sitter.Node @@ -20,7 +20,15 @@ class Flashcard: svg_front: bytes svg_back: bytes - def __init__(self, front: str, back: str, deck: str | None, note_id: int, preamble: str, file_handler: FileHandler): + def __init__( + self, + front: str, + back: str, + deck: str | None, + note_id: int, + preamble: str | None, + file_handler: FileHandler, + ): if deck is None: deck = "Default" if not note_id: @@ -51,7 +59,7 @@ class Flashcard: "Front": f"tmp typst: {self.front}" if tmp else self.as_html(True), "Back": f"tmp typst: {self.back}" if tmp else self.as_html(False), }, - "tags": ["typst"] + "tags": ["typst"], } if not self.is_new(): model["id"] = self.note_id @@ -63,7 +71,9 @@ class Flashcard: def is_new(self) -> bool: return self.note_id == 0 or self.note_id is None - def set_ts_nodes(self, front: tree_sitter.Node, back: tree_sitter.Node, note_id: tree_sitter.Node): + def set_ts_nodes( + self, front: tree_sitter.Node, back: tree_sitter.Node, note_id: tree_sitter.Node + ): self.front_node = front self.back_node = back self.note_id_node = note_id diff --git a/src/anki/main.py b/src/anki/main.py index 327fb86..6098a76 100644 --- a/src/anki/main.py +++ b/src/anki/main.py @@ -36,16 +36,33 @@ async def export_flashcards(root_dir, force_scan, clear_cache, typst_cmd, anki_u @cli.command() -def cmd(root_dir: Annotated[ - Path, typer.Option(help="Directory scanned for flashcards and passed over to typst compile command")] = os.getcwd(), - force_scan: Annotated[Path, typer.Option(help="File/directory to scan for flashcards while ignoring stored " - "file hashes (e.g. on preamble change)")] = None, - clear_cache: Annotated[bool, typer.Option(help="Clear all stored file hashes (more aggressive than force-scan " - "as it clears hashes regardless of their path)")] = False, - typst_cmd: Annotated[str, typer.Option(help="Typst command used for flashcard compilation")] = "typst", - anki_url: Annotated[str, typer.Option(help="Url for Anki-Connect")] = "http://127.0.0.1:8765", - anki_key: Annotated[str, typer.Option(help="Api key for Anki-Connect")] = None, - ): +def cmd( + root_dir: Annotated[ + Path, + typer.Option( + help="Directory scanned for flashcards and passed over to typst compile command" + ), + ] = Path(os.getcwd()), + force_scan: Annotated[ + Path | None, + typer.Option( + help="File/directory to scan for flashcards while ignoring stored " + "file hashes (e.g. on preamble change)" + ), + ] = None, + clear_cache: Annotated[ + bool, + typer.Option( + help="Clear all stored file hashes (more aggressive than force-scan " + "as it clears hashes regardless of their path)" + ), + ] = False, + typst_cmd: Annotated[ + str, typer.Option(help="Typst command used for flashcard compilation") + ] = "typst", + anki_url: Annotated[str, typer.Option(help="Url for Anki-Connect")] = "http://127.0.0.1:8765", + anki_key: Annotated[str | None, typer.Option(help="Api key for Anki-Connect")] = None, +): asyncio.run(export_flashcards(root_dir, force_scan, clear_cache, typst_cmd, anki_url, anki_key)) diff --git a/src/anki/parser.py b/src/anki/parser.py index b1c7c80..dd33158 100644 --- a/src/anki/parser.py +++ b/src/anki/parser.py @@ -1,14 +1,13 @@ import glob import json import re - from functools import cache from pathlib import Path from typing import List, Tuple import appdirs import tree_sitter -from tree_sitter_language_pack import get_language, get_parser +from tree_sitter_typst import language as get_typst_language from .file_handler import FileHandler from .flashcard import Flashcard @@ -36,7 +35,7 @@ ts_flashcard_query = """ ts_deck_query = """ ((comment) @deck) """ -deck_regex = re.compile(r"\W+ANKI:\s*(\S*)") +deck_regex = re.compile(r"\W+ANKI:\s*([\S ]*)") class FlashcardParser: @@ -50,14 +49,14 @@ class FlashcardParser: file_hashes_store_path: Path = Path(appdirs.user_state_dir("typstar") + "/file_hashes.json") def __init__(self): - self.typst_language = get_language("typst") - self.typst_parser = get_parser("typst") + self.typst_language = tree_sitter.Language(get_typst_language()) + self.typst_parser = tree_sitter.Parser(self.typst_language) self.flashcard_query = self.typst_language.query(ts_flashcard_query) self.deck_query = self.typst_language.query(ts_deck_query) self.file_handlers = [] self._load_file_hashes() - def _parse_file(self, file: FileHandler, preamble: str) -> List[Flashcard]: + def _parse_file(self, file: FileHandler, preamble: str | None) -> List[Flashcard]: cards = [] tree = self.typst_parser.parse(file.get_bytes(), encoding="utf8") card_captures = self.flashcard_query.captures(tree.root_node) @@ -72,17 +71,27 @@ class FlashcardParser: card_captures["front"].sort(key=row_compare) card_captures["back"].sort(key=row_compare) - deck_refs: List[Tuple[int, str]] = [] + deck_refs: List[Tuple[int, str | None]] = [] deck_refs_idx = -1 current_deck = None if deck_captures: deck_captures["deck"].sort(key=row_compare) for comment in deck_captures["deck"]: if match := deck_regex.match(file.get_node_content(comment)): - deck_refs.append((comment.start_point.row, None if match[1].isspace() else match[1])) + deck_refs.append( + ( + comment.start_point.row, + None if match[1].isspace() else match[1], + ) + ) - for note_id, front, back in zip(card_captures["id"], card_captures["front"], card_captures["back"]): - while deck_refs_idx < len(deck_refs) - 1 and back.end_point.row >= deck_refs[deck_refs_idx + 1][0]: + for note_id, front, back in zip( + card_captures["id"], card_captures["front"], card_captures["back"] + ): + while ( + deck_refs_idx < len(deck_refs) - 1 + and back.end_point.row >= deck_refs[deck_refs_idx + 1][0] + ): deck_refs_idx += 1 current_deck = deck_refs[deck_refs_idx][1] @@ -98,7 +107,7 @@ class FlashcardParser: cards.append(card) return cards - def parse_directory(self, root_dir: Path, force_scan: Path = None): + def parse_directory(self, root_dir: Path, force_scan: Path | None = None): single_file = None is_force_scan = force_scan is not None if is_force_scan: @@ -110,7 +119,10 @@ class FlashcardParser: else: scan_dir = root_dir - print(f"Parsing flashcards in {scan_dir if single_file is None else single_file} ...", flush=True) + print( + f"Parsing flashcards in {scan_dir if single_file is None else single_file} ...", + flush=True, + ) preambles = {} flashcards = [] @@ -121,12 +133,12 @@ class FlashcardParser: return preamble path = path.parent - for file in sorted(glob.glob(f"{root_dir}/**/.anki.typ", include_hidden=True, recursive=True)): + for file in glob.glob(f"{root_dir}/**/.anki.typ", include_hidden=True, recursive=True): file = Path(file) if file.name == ".anki.typ": preambles[file.parent] = file.read_text(encoding="utf-8") - for file in sorted(glob.glob(f"{scan_dir}/**/**.typ", recursive=True)): + for file in glob.glob(f"{scan_dir}/**/**.typ", recursive=True): file = Path(file) if single_file is not None and file != single_file: continue diff --git a/src/anki/typst_compiler.py b/src/anki/typst_compiler.py index 784552a..6a72e84 100644 --- a/src/anki/typst_compiler.py +++ b/src/anki/typst_compiler.py @@ -31,7 +31,11 @@ class TypstCompiler: def __init__(self, typst_root_dir: Path, typst_cmd: str): self.typst_cmd = typst_cmd self.typst_root_dir = typst_root_dir - self.max_processes = round(os.cpu_count() * 1.5) + n_cpus = os.cpu_count() + if n_cpus is None: + self.max_processes = 10 + else: + self.max_processes = round(1.5 * n_cpus) async def _compile(self, src: str, directory: Path) -> bytes: tmp_path = f"{directory}/tmp_{random.randint(1, 1000000000)}.typ" @@ -50,8 +54,12 @@ class TypstCompiler: async def _compile_flashcard(self, card: Flashcard): preamble = default_preamble if card.preamble is None else card.preamble - front = await self._compile(preamble + "\n" + card.as_typst(True), card.file_handler.directory_path) - back = await self._compile(preamble + "\n" + card.as_typst(False), card.file_handler.directory_path) + front = await self._compile( + preamble + "\n" + card.as_typst(True), card.file_handler.directory_path + ) + back = await self._compile( + preamble + "\n" + card.as_typst(False), card.file_handler.directory_path + ) card.set_svgs(front, back) async def compile_flashcards(self, cards: List[Flashcard]): @@ -62,7 +70,9 @@ class TypstCompiler: async with semaphore: return await self._compile_flashcard(card) - results = await asyncio.gather(*(compile_coro(card) for card in cards), return_exceptions=True) + results = await asyncio.gather( + *(compile_coro(card) for card in cards), return_exceptions=True + ) for result in results: if isinstance(result, Exception): raise result diff --git a/uv.lock b/uv.lock index 4d8237e..c2e72a0 100644 --- a/uv.lock +++ b/uv.lock @@ -340,6 +340,31 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90", size = 242424 }, ] +[[package]] +name = "ruff" +version = "0.8.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/25/5d/4b5403f3e89837decfd54c51bea7f94b7d3fae77e08858603d0e04d7ad17/ruff-0.8.5.tar.gz", hash = "sha256:1098d36f69831f7ff2a1da3e6407d5fbd6dfa2559e4f74ff2d260c5588900317", size = 3454835 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/73/f8/03391745a703ce11678eb37c48ae89ec60396ea821e9d0bcea7c8e88fd91/ruff-0.8.5-py3-none-linux_armv6l.whl", hash = "sha256:5ad11a5e3868a73ca1fa4727fe7e33735ea78b416313f4368c504dbeb69c0f88", size = 10626889 }, + { url = "https://files.pythonhosted.org/packages/55/74/83bb74a44183b904216f3edfb9995b89830c83aaa6ce84627f74da0e0cf8/ruff-0.8.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:f69ab37771ea7e0715fead8624ec42996d101269a96e31f4d31be6fc33aa19b7", size = 10398233 }, + { url = "https://files.pythonhosted.org/packages/e8/7a/a162a4feb3ef85d594527165e366dde09d7a1e534186ff4ba5d127eda850/ruff-0.8.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:b5462d7804558ccff9c08fe8cbf6c14b7efe67404316696a2dde48297b1925bb", size = 10001843 }, + { url = "https://files.pythonhosted.org/packages/e7/9f/5ee5dcd135411402e35b6ec6a8dfdadbd31c5cd1c36a624d356a38d76090/ruff-0.8.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d56de7220a35607f9fe59f8a6d018e14504f7b71d784d980835e20fc0611cd50", size = 10872507 }, + { url = "https://files.pythonhosted.org/packages/b6/67/db2df2dd4a34b602d7f6ebb1b3744c8157f0d3579973ffc58309c9c272e8/ruff-0.8.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9d99cf80b0429cbebf31cbbf6f24f05a29706f0437c40413d950e67e2d4faca4", size = 10377200 }, + { url = "https://files.pythonhosted.org/packages/fe/ff/fe3a6a73006bced73e60d171d154a82430f61d97e787f511a24bd6302611/ruff-0.8.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b75ac29715ac60d554a049dbb0ef3b55259076181c3369d79466cb130eb5afd", size = 11433155 }, + { url = "https://files.pythonhosted.org/packages/e3/95/c1d1a1fe36658c1f3e1b47e1cd5f688b72d5786695b9e621c2c38399a95e/ruff-0.8.5-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:c9d526a62c9eda211b38463528768fd0ada25dad524cb33c0e99fcff1c67b5dc", size = 12139227 }, + { url = "https://files.pythonhosted.org/packages/1b/fe/644b70d473a27b5112ac7a3428edcc1ce0db775c301ff11aa146f71886e0/ruff-0.8.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:587c5e95007612c26509f30acc506c874dab4c4abbacd0357400bd1aa799931b", size = 11697941 }, + { url = "https://files.pythonhosted.org/packages/00/39/4f83e517ec173e16a47c6d102cd22a1aaebe80e1208a1f2e83ab9a0e4134/ruff-0.8.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:622b82bf3429ff0e346835ec213aec0a04d9730480cbffbb6ad9372014e31bbd", size = 12967686 }, + { url = "https://files.pythonhosted.org/packages/1a/f6/52a2973ff108d74b5da706a573379eea160bece098f7cfa3f35dc4622710/ruff-0.8.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f99be814d77a5dac8a8957104bdd8c359e85c86b0ee0e38dca447cb1095f70fb", size = 11253788 }, + { url = "https://files.pythonhosted.org/packages/ce/1f/3b30f3c65b1303cb8e268ec3b046b77ab21ed8e26921cfc7e8232aa57f2c/ruff-0.8.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:c01c048f9c3385e0fd7822ad0fd519afb282af9cf1778f3580e540629df89725", size = 10860360 }, + { url = "https://files.pythonhosted.org/packages/a5/a8/2a3ea6bacead963f7aeeba0c61815d9b27b0d638e6a74984aa5cc5d27733/ruff-0.8.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:7512e8cb038db7f5db6aae0e24735ff9ea03bb0ed6ae2ce534e9baa23c1dc9ea", size = 10457922 }, + { url = "https://files.pythonhosted.org/packages/17/47/8f9514b670969aab57c5fc826fb500a16aee8feac1bcf8a91358f153a5ba/ruff-0.8.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:762f113232acd5b768d6b875d16aad6b00082add40ec91c927f0673a8ec4ede8", size = 10958347 }, + { url = "https://files.pythonhosted.org/packages/0d/d6/78a9af8209ad99541816d74f01ce678fc01ebb3f37dd7ab8966646dcd92b/ruff-0.8.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:03a90200c5dfff49e4c967b405f27fdfa81594cbb7c5ff5609e42d7fe9680da5", size = 11328882 }, + { url = "https://files.pythonhosted.org/packages/54/77/5c8072ec7afdfdf42c7a4019044486a2b6c85ee73617f8875ec94b977fed/ruff-0.8.5-py3-none-win32.whl", hash = "sha256:8710ffd57bdaa6690cbf6ecff19884b8629ec2a2a2a2f783aa94b1cc795139ed", size = 8802515 }, + { url = "https://files.pythonhosted.org/packages/bc/b6/47d2b06784de8ae992c45cceb2a30f3f205b3236a629d7ca4c0c134839a2/ruff-0.8.5-py3-none-win_amd64.whl", hash = "sha256:4020d8bf8d3a32325c77af452a9976a9ad6455773bcb94991cf15bd66b347e47", size = 9684231 }, + { url = "https://files.pythonhosted.org/packages/bf/5e/ffee22bf9f9e4b2669d1f0179ae8804584939fb6502b51f2401e26b1e028/ruff-0.8.5-py3-none-win_arm64.whl", hash = "sha256:134ae019ef13e1b060ab7136e7828a6d83ea727ba123381307eb37c6bd5e01cb", size = 9124741 }, +] + [[package]] name = "shellingham" version = "1.5.4" @@ -382,109 +407,9 @@ wheels = [ ] [[package]] -name = "tree-sitter-c-sharp" -version = "0.23.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/22/85/a61c782afbb706a47d990eaee6977e7c2bd013771c5bf5c81c617684f286/tree_sitter_c_sharp-0.23.1.tar.gz", hash = "sha256:322e2cfd3a547a840375276b2aea3335fa6458aeac082f6c60fec3f745c967eb", size = 1317728 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/58/04/f6c2df4c53a588ccd88d50851155945cff8cd887bd70c175e00aaade7edf/tree_sitter_c_sharp-0.23.1-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2b612a6e5bd17bb7fa2aab4bb6fc1fba45c94f09cb034ab332e45603b86e32fd", size = 372235 }, - { url = "https://files.pythonhosted.org/packages/99/10/1aa9486f1e28fc22810fa92cbdc54e1051e7f5536a5e5b5e9695f609b31e/tree_sitter_c_sharp-0.23.1-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:1a8b98f62bc53efcd4d971151950c9b9cd5cbe3bacdb0cd69fdccac63350d83e", size = 419046 }, - { url = "https://files.pythonhosted.org/packages/0f/21/13df29f8fcb9ba9f209b7b413a4764b673dfd58989a0dd67e9c7e19e9c2e/tree_sitter_c_sharp-0.23.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:986e93d845a438ec3c4416401aa98e6a6f6631d644bbbc2e43fcb915c51d255d", size = 415999 }, - { url = "https://files.pythonhosted.org/packages/ca/72/fc6846795bcdae2f8aa94cc8b1d1af33d634e08be63e294ff0d6794b1efc/tree_sitter_c_sharp-0.23.1-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8024e466b2f5611c6dc90321f232d8584893c7fb88b75e4a831992f877616d2", size = 402830 }, - { url = "https://files.pythonhosted.org/packages/fe/3a/b6028c5890ce6653807d5fa88c72232c027c6ceb480dbeb3b186d60e5971/tree_sitter_c_sharp-0.23.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:7f9bf876866835492281d336b9e1f9626ab668737f74e914c31d285261507da7", size = 397880 }, - { url = "https://files.pythonhosted.org/packages/47/d2/4facaa34b40f8104d8751746d0e1cd2ddf0beb9f1404b736b97f372bd1f3/tree_sitter_c_sharp-0.23.1-cp39-abi3-win_amd64.whl", hash = "sha256:ae9a9e859e8f44e2b07578d44f9a220d3fa25b688966708af6aa55d42abeebb3", size = 377562 }, - { url = "https://files.pythonhosted.org/packages/d8/88/3cf6bd9959d94d1fec1e6a9c530c5f08ff4115a474f62aedb5fedb0f7241/tree_sitter_c_sharp-0.23.1-cp39-abi3-win_arm64.whl", hash = "sha256:c81548347a93347be4f48cb63ec7d60ef4b0efa91313330e69641e49aa5a08c5", size = 375157 }, -] - -[[package]] -name = "tree-sitter-embedded-template" -version = "0.23.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/28/d6/5a58ea2f0480f5ed188b733114a8c275532a2fd1568b3898793b13d28af5/tree_sitter_embedded_template-0.23.2.tar.gz", hash = "sha256:7b24dcf2e92497f54323e617564d36866230a8bfb719dbb7b45b461510dcddaa", size = 8471 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ef/c1/be0c48ed9609b720e74ade86f24ea086e353fe9c7405ee9630c3d52d09a2/tree_sitter_embedded_template-0.23.2-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:a505c2d2494464029d79db541cab52f6da5fb326bf3d355e69bf98b84eb89ae0", size = 9554 }, - { url = "https://files.pythonhosted.org/packages/6d/a5/7c12f5d302525ee36d1eafc28a68e4454da5bad208436d547326bee4ed76/tree_sitter_embedded_template-0.23.2-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:28028b93b42cc3753261ae7ce066675d407f59de512417524f9c3ab7792b1d37", size = 10051 }, - { url = "https://files.pythonhosted.org/packages/cd/87/95aaba8b64b849200bd7d4ae510cc394ecaef46a031499cbff301766970d/tree_sitter_embedded_template-0.23.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec399d59ce93ffb60759a2d96053eed529f3c3f6a27128f261710d0d0de60e10", size = 17532 }, - { url = "https://files.pythonhosted.org/packages/13/f8/8c837b898f00b35f9f3f76a4abc525e80866a69343083c9ff329e17ecb03/tree_sitter_embedded_template-0.23.2-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bcfa01f62b88d50dbcb736cc23baec8ddbfe08daacfdc613eee8c04ab65efd09", size = 17394 }, - { url = "https://files.pythonhosted.org/packages/89/9b/893adf9e465d2d7f14870871bf2f3b30045e5ac417cb596f667a72eda493/tree_sitter_embedded_template-0.23.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6debd24791466f887109a433c31aa4a5deeba2b217817521c745a4e748a944ed", size = 16439 }, - { url = "https://files.pythonhosted.org/packages/40/96/e79934572723673db9f867000500c6eea61a37705e02c7aee9ee031bbb6f/tree_sitter_embedded_template-0.23.2-cp39-abi3-win_amd64.whl", hash = "sha256:158fecb38be5b15db0190ef7238e5248f24bf32ae3cab93bc1197e293a5641eb", size = 12572 }, - { url = "https://files.pythonhosted.org/packages/63/06/27f678b9874e4e2e39ddc6f5cce3374c8c60e6046ea8588a491ab6fc9fcb/tree_sitter_embedded_template-0.23.2-cp39-abi3-win_arm64.whl", hash = "sha256:9f1f3b79fe273f3d15a5b64c85fc6ebfb48decfbe8542accd05f5b7694860df0", size = 11232 }, -] - -[[package]] -name = "tree-sitter-language-pack" -version = "0.2.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "tree-sitter" }, - { name = "tree-sitter-c-sharp" }, - { name = "tree-sitter-embedded-template" }, - { name = "tree-sitter-php" }, - { name = "tree-sitter-typescript" }, - { name = "tree-sitter-xml" }, - { name = "tree-sitter-yaml" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/4a/5f/1f237a4e19770b015961ce90c75b161c39ea1495f6cb4de7d5cd46c1e138/tree_sitter_language_pack-0.2.0.tar.gz", hash = "sha256:14c83c43a2f7236a2c39c1c196fd0a2415305dee97263aa80c653623fa23ef13", size = 35706652 } - -[[package]] -name = "tree-sitter-php" -version = "0.23.11" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/db/65/9d5ec24a9494770c65324923f7a2ae205b7537575e7f0533b88955b63373/tree_sitter_php-0.23.11.tar.gz", hash = "sha256:8aabb262ad97299c1004f619458091d64187414e54215e152585c097c7a415e5", size = 422853 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/04/f2/8c940f82ea7f1f6864fa987a1dd7d18a7dd6a0967939c46fa194b4754931/tree_sitter_php-0.23.11-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:f46b741fd4843a7287e46505c35b4712cf2bea8481ce5236d2a32add45921c42", size = 179667 }, - { url = "https://files.pythonhosted.org/packages/66/dd/2522c074504d414135b522be5586f03a087601c7d23714d6db76c4bb2f02/tree_sitter_php-0.23.11-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:315f5da5ad8f9ed014008da481ed49a88db21e03e9f723f1c631eec36b6b3691", size = 177478 }, - { url = "https://files.pythonhosted.org/packages/9d/72/889dfb1154ecfc96e009b1f6c14ec8b44f4a2b81d09a7087f3c8c2f8ba47/tree_sitter_php-0.23.11-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da1f515e5875efe492b8970962cd70cab7de4dac90f20229c52360815b4e60f2", size = 258418 }, - { url = "https://files.pythonhosted.org/packages/a8/49/b40635d3281729cb81b1874e62ccae2826831b56d79fd353222cb9dbdf25/tree_sitter_php-0.23.11-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6076af83f549361390be5875c695fe50c319ce2e0388cb8127e6e6529d98dd48", size = 251469 }, - { url = "https://files.pythonhosted.org/packages/a9/db/e47b00ca732eddf22c1795dea1be3f3130da29dfd4985212c6335ccef5fd/tree_sitter_php-0.23.11-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:29bb2450714d2a6911a939e5c20913f17e497cfc8b1dc5a751b15dc6fe6af2b7", size = 245437 }, - { url = "https://files.pythonhosted.org/packages/df/c2/6861b8d013d25697d995b270a0a0d842311439dc1bff22680c125a36abad/tree_sitter_php-0.23.11-cp39-abi3-win_amd64.whl", hash = "sha256:7799d56dfb557414b5172044dbe75bf33f877976dd0193e0775dc7f1f2f7cf8e", size = 168021 }, - { url = "https://files.pythonhosted.org/packages/0f/38/dfa82ffd66810323d0d20d19a8e5d318fe1a65001ee654fa3e80b0871d05/tree_sitter_php-0.23.11-cp39-abi3-win_arm64.whl", hash = "sha256:c4869a6dd13faec316cea19ed8551416da35ccabd0811b9880ad54dbbc24867b", size = 166472 }, -] - -[[package]] -name = "tree-sitter-typescript" -version = "0.23.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1e/fc/bb52958f7e399250aee093751e9373a6311cadbe76b6e0d109b853757f35/tree_sitter_typescript-0.23.2.tar.gz", hash = "sha256:7b167b5827c882261cb7a50dfa0fb567975f9b315e87ed87ad0a0a3aedb3834d", size = 773053 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/28/95/4c00680866280e008e81dd621fd4d3f54aa3dad1b76b857a19da1b2cc426/tree_sitter_typescript-0.23.2-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:3cd752d70d8e5371fdac6a9a4df9d8924b63b6998d268586f7d374c9fba2a478", size = 286677 }, - { url = "https://files.pythonhosted.org/packages/8f/2f/1f36fda564518d84593f2740d5905ac127d590baf5c5753cef2a88a89c15/tree_sitter_typescript-0.23.2-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:c7cc1b0ff5d91bac863b0e38b1578d5505e718156c9db577c8baea2557f66de8", size = 302008 }, - { url = "https://files.pythonhosted.org/packages/96/2d/975c2dad292aa9994f982eb0b69cc6fda0223e4b6c4ea714550477d8ec3a/tree_sitter_typescript-0.23.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b1eed5b0b3a8134e86126b00b743d667ec27c63fc9de1b7bb23168803879e31", size = 351987 }, - { url = "https://files.pythonhosted.org/packages/49/d1/a71c36da6e2b8a4ed5e2970819b86ef13ba77ac40d9e333cb17df6a2c5db/tree_sitter_typescript-0.23.2-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e96d36b85bcacdeb8ff5c2618d75593ef12ebaf1b4eace3477e2bdb2abb1752c", size = 344960 }, - { url = "https://files.pythonhosted.org/packages/7f/cb/f57b149d7beed1a85b8266d0c60ebe4c46e79c9ba56bc17b898e17daf88e/tree_sitter_typescript-0.23.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:8d4f0f9bcb61ad7b7509d49a1565ff2cc363863644a234e1e0fe10960e55aea0", size = 340245 }, - { url = "https://files.pythonhosted.org/packages/8b/ab/dd84f0e2337296a5f09749f7b5483215d75c8fa9e33738522e5ed81f7254/tree_sitter_typescript-0.23.2-cp39-abi3-win_amd64.whl", hash = "sha256:3f730b66396bc3e11811e4465c41ee45d9e9edd6de355a58bbbc49fa770da8f9", size = 278015 }, - { url = "https://files.pythonhosted.org/packages/9f/e4/81f9a935789233cf412a0ed5fe04c883841d2c8fb0b7e075958a35c65032/tree_sitter_typescript-0.23.2-cp39-abi3-win_arm64.whl", hash = "sha256:05db58f70b95ef0ea126db5560f3775692f609589ed6f8dd0af84b7f19f1cbb7", size = 274052 }, -] - -[[package]] -name = "tree-sitter-xml" -version = "0.7.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/41/ba/77a92dbb4dfb374fb99863a07f938de7509ceeaa74139933ac2bd306eeb1/tree_sitter_xml-0.7.0.tar.gz", hash = "sha256:ab0ff396f20230ad8483d968151ce0c35abe193eb023b20fbd8b8ce4cf9e9f61", size = 54635 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/36/1d/6b8974c493973c0c9df2bbf220a1f0a96fa785da81a5a13461faafd1441c/tree_sitter_xml-0.7.0-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:cc3e516d4c1e0860fb22172c172148debb825ba638971bc48bad15b22e5b0bae", size = 35404 }, - { url = "https://files.pythonhosted.org/packages/75/f5/31013d04c4e3b9a55e90168cc222a601c84235ba4953a5a06b5cdf8353c4/tree_sitter_xml-0.7.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:0674fdf4cc386e4d323cb287d3b072663de0f20a9e9af5d5e09821aae56a9e5c", size = 35488 }, - { url = "https://files.pythonhosted.org/packages/c8/e6/e7493217f950a7c5969e3f3f057664142fa948abefd2dba5acea25719d55/tree_sitter_xml-0.7.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c0fe5f2d6cc09974c8375c8ea9b24909f493b5bf04aacdc4c694b5d2ae6b040", size = 74199 }, - { url = "https://files.pythonhosted.org/packages/94/27/1dd6815592489de51fa7b5fffc1160cd385ade7fa06f07b998742ac18020/tree_sitter_xml-0.7.0-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd3209516a4d84dff90bc91d2ad2ce246de8504cede4358849687fa8e71536e7", size = 76244 }, - { url = "https://files.pythonhosted.org/packages/20/10/2e4e84c50b2175cb53d255ef154aa893cb82cc9d035d7a1a73be9d2d2db4/tree_sitter_xml-0.7.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:87578e15fa55f44ecd9f331233b6f8a2cbde3546b354c830ecb862a632379455", size = 75112 }, - { url = "https://files.pythonhosted.org/packages/ae/91/77c348568bccb179eca21062c923f6f54026900b09fe0cf1aae89d78a0c8/tree_sitter_xml-0.7.0-cp39-abi3-win_amd64.whl", hash = "sha256:9ba2dafc6ce9feaf4ccc617d3aeea57f8e0ca05edad34953e788001ebff79133", size = 36558 }, - { url = "https://files.pythonhosted.org/packages/be/cc/6b4de230770d7be87b2a415583121ac565ce1ff7d9a1ad7fec11f8e613fc/tree_sitter_xml-0.7.0-cp39-abi3-win_arm64.whl", hash = "sha256:fc759f710a8fd7a01c23e2d7cb013679199045bea3dc0e5151650a11322aaf40", size = 34610 }, -] - -[[package]] -name = "tree-sitter-yaml" -version = "0.7.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/93/04/6de8be8112c50450cab753fcd6b74d8368c60f6099bf551cee0bec69563a/tree_sitter_yaml-0.7.0.tar.gz", hash = "sha256:9c8bb17d9755c3b0e757260917240c0d19883cd3b59a5d74f205baa8bf8435a4", size = 85085 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/69/1d/243dbdf59fae8a4109e19f0994e2627ddedb2e16b7cf99bd42be64367742/tree_sitter_yaml-0.7.0-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:e21553ac190ae05bf82796df8beb4d9158ba195b5846018cb36fbc3a35bd0679", size = 43335 }, - { url = "https://files.pythonhosted.org/packages/e2/63/e5d5868a1498e20fd07e7db62933766fd64950279862e3e7f150b88ec69d/tree_sitter_yaml-0.7.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:c022054f1f9b54201082ea83073a6c24c42d0436ad8ee99ff2574cba8f928c28", size = 44574 }, - { url = "https://files.pythonhosted.org/packages/f5/ba/9cff9a3fddb1b6b38bc71ce1dfdb8892ab15a4042c104f4582e30318b412/tree_sitter_yaml-0.7.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cd1725142f19e41c51d27c99cfc60780f596e069eb181cfa6433d993a19aa3d", size = 93088 }, - { url = "https://files.pythonhosted.org/packages/19/09/39d29d9a22cee0b3c3e4f3fdbd23e4534b9c2a84b5f962f369eafcfbf88c/tree_sitter_yaml-0.7.0-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d1b268378254f75bb27396d83c96d886ccbfcda6bd8c2778e94e3e1d2459085", size = 91367 }, - { url = "https://files.pythonhosted.org/packages/b0/b7/285653b894b351436917b5fe5e738eecaeb2128b4e4bf72bfe0c6043f62e/tree_sitter_yaml-0.7.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:27c2e7f4f49ddf410003abbb82a7b00ec77ea263d8ef08dbce1a15d293eed2fd", size = 87405 }, - { url = "https://files.pythonhosted.org/packages/bb/73/0cdc82ea653c190475a4f63dd4a1f4efd5d1c7d09d2668b8d84008a4c4f8/tree_sitter_yaml-0.7.0-cp39-abi3-win_amd64.whl", hash = "sha256:98dce0d6bc376f842cfb1d3c32512eea95b37e61cd2c87074bb4b05c999917c8", size = 45360 }, - { url = "https://files.pythonhosted.org/packages/2e/32/af2d676b0176a958f22a75b04be836e09476a10844baab78c018a5030297/tree_sitter_yaml-0.7.0-cp39-abi3-win_arm64.whl", hash = "sha256:f0f8d8e05fa8e70f08d0f18a209d6026e171844f4ea7090e7c779b9c375b3a31", size = 43650 }, -] +name = "tree-sitter-typst" +version = "0.0.1" +source = { git = "https://github.com/uben0/tree-sitter-typst#26dfb4b94a99cc9d6044342b7ad0ba761da77d60" } [[package]] name = "typer" @@ -517,18 +442,28 @@ source = { editable = "." } dependencies = [ { name = "aiohttp" }, { name = "appdirs" }, - { name = "tree-sitter-language-pack" }, + { name = "tree-sitter" }, + { name = "tree-sitter-typst" }, { name = "typer" }, ] +[package.dev-dependencies] +dev = [ + { name = "ruff" }, +] + [package.metadata] requires-dist = [ { name = "aiohttp", specifier = ">=3.11.11" }, { name = "appdirs", specifier = ">=1.4.4" }, - { name = "tree-sitter-language-pack", specifier = ">=0.2.0" }, + { name = "tree-sitter", specifier = ">=0.23.2" }, + { name = "tree-sitter-typst", git = "https://github.com/uben0/tree-sitter-typst" }, { name = "typer", specifier = ">=0.15.1" }, ] +[package.metadata.requires-dev] +dev = [{ name = "ruff", specifier = ">=0.8.5" }] + [[package]] name = "yarl" version = "1.18.3"