From bebd3aa7c7d35ca3e6feebdac79ca69d5846210b Mon Sep 17 00:00:00 2001 From: Billy Date: Sat, 7 Feb 2026 02:10:16 +0530 Subject: [PATCH 01/19] deps: Added tree-sitter --- poetry.lock | 191 ++++++++++++++++++++++++++++++++++++++++++------- pyproject.toml | 2 + 2 files changed, 166 insertions(+), 27 deletions(-) diff --git a/poetry.lock b/poetry.lock index d4664b88..1458c151 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.3.2 and should not be changed by hand. [[package]] name = "aiodns" @@ -3466,14 +3466,14 @@ scikit-build = "*" [[package]] name = "tkinterweb" -version = "4.17.6" +version = "4.18.1" description = "HTML/CSS viewer, editor, and app builder for Tkinter" optional = false python-versions = ">=3.2" groups = ["main"] files = [ - {file = "tkinterweb-4.17.6-py3-none-any.whl", hash = "sha256:e915cca9fbe4bd7ae56572cdfb3ab9b3db0b8e9a099d585733d362b69da04de4"}, - {file = "tkinterweb-4.17.6.tar.gz", hash = "sha256:1531c76f4c4b25b03daa6ea362d49acdcbcc1bc6d866c738d46678c49c14b516"}, + {file = "tkinterweb-4.18.1-py3-none-any.whl", hash = "sha256:36da65ebfb14db60f328c9c0e6c0b0b93ac51bd8729dd0c9aa9e232e399fdd99"}, + {file = "tkinterweb-4.18.1.tar.gz", hash = "sha256:a9f541bc59a1fca2721c196b61149fc892fd08a97bebd1ac403d7526108e6a42"}, ] [package.dependencies] @@ -3481,50 +3481,50 @@ brotli = {version = "*", optional = true, markers = "extra == \"full\""} cairosvg = {version = "*", optional = true, markers = "extra == \"full\""} pillow = {version = "*", optional = true, markers = "extra == \"full\""} pythonmonkey = {version = "*", optional = true, markers = "extra == \"full\""} -tkinterweb-tkhtml = ">=2.1.0" -tkinterweb-tkhtml-extras = {version = ">=1.2.0", optional = true, markers = "extra == \"full\""} +tkinterweb-tkhtml = ">=2.1.1" +tkinterweb-tkhtml-extras = {version = ">=1.3.0", optional = true, markers = "extra == \"full\""} [package.extras] -full = ["brotli", "cairosvg", "pillow", "pythonmonkey", "tkinterweb-tkhtml-extras (>=1.2.0)"] -html = ["tkinterweb-tkhtml-extras (>=1.2.0)"] +full = ["brotli", "cairosvg", "pillow", "pythonmonkey", "tkinterweb-tkhtml-extras (>=1.3.0)"] +html = ["tkinterweb-tkhtml-extras (>=1.3.0)"] images = ["pillow"] javascript = ["pythonmonkey"] -recommended = ["pillow", "tkinterweb-tkhtml-extras (>=1.2.0)"] +recommended = ["pillow", "tkinterweb-tkhtml-extras (>=1.3.0)"] requests = ["brotli"] -svg = ["cairosvg", "pillow", "tkinterweb-tkhtml-extras (>=1.2.0)"] +svg = ["cairosvg", "pillow", "tkinterweb-tkhtml-extras (>=1.3.0)"] [[package]] name = "tkinterweb-tkhtml" -version = "2.1.0" +version = "2.1.1" description = "HTML/CSS viewer for Tkinter" optional = false python-versions = ">=3.2" groups = ["main"] files = [ - {file = "tkinterweb_tkhtml-2.1.0-py3-none-any.whl", hash = "sha256:8b09650de74bd396692a7bc77f0d77e0fe571b9bd3b13b2930f649d57b0f1ae9"}, - {file = "tkinterweb_tkhtml-2.1.0-py3-none-linux_armv7l.whl", hash = "sha256:bda709e7bead0718977bd6e4bce3c7c630c38c92758a8f5001fce9cab64842ab"}, - {file = "tkinterweb_tkhtml-2.1.0-py3-none-macosx_10_6_x86_64.whl", hash = "sha256:2b69d1cedc58de38bc6036d78682d0757932a04e70bef28cf66794330a2e1204"}, - {file = "tkinterweb_tkhtml-2.1.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:3d0cb02b6559e7ffacafd76ab905101a1df241334a0fbf3784a09a2e77cce342"}, - {file = "tkinterweb_tkhtml-2.1.0-py3-none-manylinux1_i686.whl", hash = "sha256:e72cef8a008a190fe07c58f27a871ae8b2084bbadee76e930346d7d3d3ca3fbf"}, - {file = "tkinterweb_tkhtml-2.1.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:46930a9d2563d4936faee9e30d1cc1a84e8e640bdb3e3567446c08d36cb0c52b"}, - {file = "tkinterweb_tkhtml-2.1.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7fdb35cdb1b4e34a1d954efb6c9b611322aa424275207a90690473789451637b"}, - {file = "tkinterweb_tkhtml-2.1.0-py3-none-win32.whl", hash = "sha256:42f14a294b176dbfad05292fdd7894024fc8f3e44664982c6af2512a7f939677"}, - {file = "tkinterweb_tkhtml-2.1.0-py3-none-win_amd64.whl", hash = "sha256:f03ce10affe8f20aa52ed514bde0ade26cf647f8eb824988e38874d8e6f599a0"}, - {file = "tkinterweb_tkhtml-2.1.0.tar.gz", hash = "sha256:d0b0acf46ae841f665c1bcf5feaf47ab74bae40071d47b12fe7e3a694536b2ec"}, + {file = "tkinterweb_tkhtml-2.1.1-py3-none-any.whl", hash = "sha256:51541db4cb118ef06329777bada7b2464a05085f15d8712d0608cab0f48452ac"}, + {file = "tkinterweb_tkhtml-2.1.1-py3-none-linux_armv7l.whl", hash = "sha256:0f7d93d3e96aa57bbab2af2465f69d83870e0269877830b105873f5c391a8fad"}, + {file = "tkinterweb_tkhtml-2.1.1-py3-none-macosx_10_6_x86_64.whl", hash = "sha256:0cfb20bfa38a025f99127c43c2383ee37c38652620c055f26551b3080aa595a7"}, + {file = "tkinterweb_tkhtml-2.1.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:a55c1979ae7ff7f17bfbad9c67b5f2f9c463da2a20a7697eaa4a0fdb51052bc6"}, + {file = "tkinterweb_tkhtml-2.1.1-py3-none-manylinux1_i686.whl", hash = "sha256:38fc20afb50788f11a71d56db5982368b9c2b5bb5aaeb6bb8fda8b11c63812d8"}, + {file = "tkinterweb_tkhtml-2.1.1-py3-none-manylinux1_x86_64.whl", hash = "sha256:45de2140df75086d9b31ed4f326d8a0e24f849520de36883805d60ca8755d1e7"}, + {file = "tkinterweb_tkhtml-2.1.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:c737250ea9d6ff82a1fe325991a17c734444a5d992667eac082034cfaa0c7e9c"}, + {file = "tkinterweb_tkhtml-2.1.1-py3-none-win32.whl", hash = "sha256:bfe25007fb6b99ac74b4bda47a1ac99e79a73982bdcdbd56494b37abf8976771"}, + {file = "tkinterweb_tkhtml-2.1.1-py3-none-win_amd64.whl", hash = "sha256:5a1f9e5a49e8ff15488557377f3f25f8e7e781bea94f9d63884a887ddbd18d58"}, + {file = "tkinterweb_tkhtml-2.1.1.tar.gz", hash = "sha256:62b0db0fdb442d46e551c357e2d14de38c47b954ce93b670b6beb31fd75a548b"}, ] [[package]] name = "tkinterweb-tkhtml-extras" -version = "1.2.0" +version = "1.3.0" description = "HTML/CSS viewer for Tkinter" optional = false python-versions = ">=3.2" groups = ["main"] files = [ - {file = "tkinterweb_tkhtml_extras-1.2.0-py3-none-any.whl", hash = "sha256:6fa75a9bb99a1e59e375f6275e08bc1872ba696c03e8cbd09611e96879acf656"}, - {file = "tkinterweb_tkhtml_extras-1.2.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:250389aeec74b05e0384d63803803cc7bff30a43c1f8a61b72366cb16274d967"}, - {file = "tkinterweb_tkhtml_extras-1.2.0-py3-none-win_amd64.whl", hash = "sha256:faa0bf55b9ea6b5ce68b22289211c74c61d2b462b691d0ccf394b63389b3b422"}, - {file = "tkinterweb_tkhtml_extras-1.2.0.tar.gz", hash = "sha256:afae2fe9fd964fc0c51dcce605bb9ac7470a1731332b5c4add7b5bfdde607fe3"}, + {file = "tkinterweb_tkhtml_extras-1.3.0-py3-none-any.whl", hash = "sha256:9a91d8d30f2b521425271b4173fb377b9fdaf2d2fb086887245aed5b9729ce4e"}, + {file = "tkinterweb_tkhtml_extras-1.3.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:6f24a3616345b58b457c0a1019eb120114502491878ad2ead363c4f0176ffa93"}, + {file = "tkinterweb_tkhtml_extras-1.3.0-py3-none-win_amd64.whl", hash = "sha256:18a79da07a66af0e06b3fd97f2179dfdb54dc7443f0cd4c407b845338ae4fa0d"}, + {file = "tkinterweb_tkhtml_extras-1.3.0.tar.gz", hash = "sha256:ff34160b534aa388b7e416aa117225a1089c8e808fa9a03afcd8b0614a9f3090"}, ] [[package]] @@ -3597,6 +3597,143 @@ files = [ {file = "tomli-2.4.0.tar.gz", hash = "sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c"}, ] +[[package]] +name = "tree-sitter" +version = "0.25.2" +description = "Python bindings to the Tree-sitter parsing library" +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "tree-sitter-0.25.2.tar.gz", hash = "sha256:fe43c158555da46723b28b52e058ad444195afd1db3ca7720c59a254544e9c20"}, + {file = "tree_sitter-0.25.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72a510931c3c25f134aac2daf4eb4feca99ffe37a35896d7150e50ac3eee06c7"}, + {file = "tree_sitter-0.25.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:44488e0e78146f87baaa009736886516779253d6d6bac3ef636ede72bc6a8234"}, + {file = "tree_sitter-0.25.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c2f8e7d6b2f8489d4a9885e3adcaef4bc5ff0a275acd990f120e29c4ab3395c5"}, + {file = "tree_sitter-0.25.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:20b570690f87f1da424cd690e51cc56728d21d63f4abd4b326d382a30353acc7"}, + {file = "tree_sitter-0.25.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:a0ec41b895da717bc218a42a3a7a0bfcfe9a213d7afaa4255353901e0e21f696"}, + {file = "tree_sitter-0.25.2-cp310-cp310-win_amd64.whl", hash = "sha256:7712335855b2307a21ae86efe949c76be36c6068d76df34faa27ce9ee40ff444"}, + {file = "tree_sitter-0.25.2-cp310-cp310-win_arm64.whl", hash = "sha256:a925364eb7fbb9cdce55a9868f7525a1905af512a559303bd54ef468fd88cb37"}, + {file = "tree_sitter-0.25.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b8ca72d841215b6573ed0655b3a5cd1133f9b69a6fa561aecad40dca9029d75b"}, + {file = "tree_sitter-0.25.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cc0351cfe5022cec5a77645f647f92a936b38850346ed3f6d6babfbeeeca4d26"}, + {file = "tree_sitter-0.25.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1799609636c0193e16c38f366bda5af15b1ce476df79ddaae7dd274df9e44266"}, + {file = "tree_sitter-0.25.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3e65ae456ad0d210ee71a89ee112ac7e72e6c2e5aac1b95846ecc7afa68a194c"}, + {file = "tree_sitter-0.25.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:49ee3c348caa459244ec437ccc7ff3831f35977d143f65311572b8ba0a5f265f"}, + {file = "tree_sitter-0.25.2-cp311-cp311-win_amd64.whl", hash = "sha256:56ac6602c7d09c2c507c55e58dc7026b8988e0475bd0002f8a386cce5e8e8adc"}, + {file = "tree_sitter-0.25.2-cp311-cp311-win_arm64.whl", hash = "sha256:b3d11a3a3ac89bb8a2543d75597f905a9926f9c806f40fcca8242922d1cc6ad5"}, + {file = "tree_sitter-0.25.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ddabfff809ffc983fc9963455ba1cecc90295803e06e140a4c83e94c1fa3d960"}, + {file = "tree_sitter-0.25.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c0c0ab5f94938a23fe81928a21cc0fac44143133ccc4eb7eeb1b92f84748331c"}, + {file = "tree_sitter-0.25.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dd12d80d91d4114ca097626eb82714618dcdfacd6a5e0955216c6485c350ef99"}, + {file = "tree_sitter-0.25.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b43a9e4c89d4d0839de27cd4d6902d33396de700e9ff4c5ab7631f277a85ead9"}, + {file = "tree_sitter-0.25.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fbb1706407c0e451c4f8cc016fec27d72d4b211fdd3173320b1ada7a6c74c3ac"}, + {file = "tree_sitter-0.25.2-cp312-cp312-win_amd64.whl", hash = "sha256:6d0302550bbe4620a5dc7649517c4409d74ef18558276ce758419cf09e578897"}, + {file = "tree_sitter-0.25.2-cp312-cp312-win_arm64.whl", hash = "sha256:0c8b6682cac77e37cfe5cf7ec388844957f48b7bd8d6321d0ca2d852994e10d5"}, + {file = "tree_sitter-0.25.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0628671f0de69bb279558ef6b640bcfc97864fe0026d840f872728a86cd6b6cd"}, + {file = "tree_sitter-0.25.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f5ddcd3e291a749b62521f71fc953f66f5fd9743973fd6dd962b092773569601"}, + {file = "tree_sitter-0.25.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bd88fbb0f6c3a0f28f0a68d72df88e9755cf5215bae146f5a1bdc8362b772053"}, + {file = "tree_sitter-0.25.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b878e296e63661c8e124177cc3084b041ba3f5936b43076d57c487822426f614"}, + {file = "tree_sitter-0.25.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d77605e0d353ba3fe5627e5490f0fbfe44141bafa4478d88ef7954a61a848dae"}, + {file = "tree_sitter-0.25.2-cp313-cp313-win_amd64.whl", hash = "sha256:463c032bd02052d934daa5f45d183e0521ceb783c2548501cf034b0beba92c9b"}, + {file = "tree_sitter-0.25.2-cp313-cp313-win_arm64.whl", hash = "sha256:b3f63a1796886249bd22c559a5944d64d05d43f2be72961624278eff0dcc5cb8"}, + {file = "tree_sitter-0.25.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:65d3c931013ea798b502782acab986bbf47ba2c452610ab0776cf4a8ef150fc0"}, + {file = "tree_sitter-0.25.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:bda059af9d621918efb813b22fb06b3fe00c3e94079c6143fcb2c565eb44cb87"}, + {file = "tree_sitter-0.25.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eac4e8e4c7060c75f395feec46421eb61212cb73998dbe004b7384724f3682ab"}, + {file = "tree_sitter-0.25.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:260586381b23be33b6191a07cea3d44ecbd6c01aa4c6b027a0439145fcbc3358"}, + {file = "tree_sitter-0.25.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7d2ee1acbacebe50ba0f85fff1bc05e65d877958f00880f49f9b2af38dce1af0"}, + {file = "tree_sitter-0.25.2-cp314-cp314-win_amd64.whl", hash = "sha256:4973b718fcadfb04e59e746abfbb0288694159c6aeecd2add59320c03368c721"}, + {file = "tree_sitter-0.25.2-cp314-cp314-win_arm64.whl", hash = "sha256:b8d4429954a3beb3e844e2872610d2a4800ba4eb42bb1990c6a4b1949b18459f"}, +] + +[package.extras] +docs = ["sphinx (>=8.1,<9.0)", "sphinx-book-theme"] +tests = ["tree-sitter-html (>=0.23.2)", "tree-sitter-javascript (>=0.23.1)", "tree-sitter-json (>=0.24.8)", "tree-sitter-python (>=0.23.6)", "tree-sitter-rust (>=0.23.2)"] + +[[package]] +name = "tree-sitter-c-sharp" +version = "0.23.1" +description = "C# grammar for tree-sitter" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "tree_sitter_c_sharp-0.23.1-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2b612a6e5bd17bb7fa2aab4bb6fc1fba45c94f09cb034ab332e45603b86e32fd"}, + {file = "tree_sitter_c_sharp-0.23.1-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:1a8b98f62bc53efcd4d971151950c9b9cd5cbe3bacdb0cd69fdccac63350d83e"}, + {file = "tree_sitter_c_sharp-0.23.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:986e93d845a438ec3c4416401aa98e6a6f6631d644bbbc2e43fcb915c51d255d"}, + {file = "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"}, + {file = "tree_sitter_c_sharp-0.23.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:7f9bf876866835492281d336b9e1f9626ab668737f74e914c31d285261507da7"}, + {file = "tree_sitter_c_sharp-0.23.1-cp39-abi3-win_amd64.whl", hash = "sha256:ae9a9e859e8f44e2b07578d44f9a220d3fa25b688966708af6aa55d42abeebb3"}, + {file = "tree_sitter_c_sharp-0.23.1-cp39-abi3-win_arm64.whl", hash = "sha256:c81548347a93347be4f48cb63ec7d60ef4b0efa91313330e69641e49aa5a08c5"}, + {file = "tree_sitter_c_sharp-0.23.1.tar.gz", hash = "sha256:322e2cfd3a547a840375276b2aea3335fa6458aeac082f6c60fec3f745c967eb"}, +] + +[package.extras] +core = ["tree-sitter (>=0.22,<1.0)"] + +[[package]] +name = "tree-sitter-embedded-template" +version = "0.25.0" +description = "Embedded Template (ERB, EJS) grammar for tree-sitter" +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "tree_sitter_embedded_template-0.25.0-cp310-abi3-macosx_10_9_x86_64.whl", hash = "sha256:fa0d06467199aeb33fb3d6fa0665bf9b7d5a32621ffdaf37fd8249f8a8050649"}, + {file = "tree_sitter_embedded_template-0.25.0-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:fc7aacbc2985a5d7e7fe7334f44dffe24c38fb0a8295c4188a04cf21a3d64a73"}, + {file = "tree_sitter_embedded_template-0.25.0-cp310-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a7c88c3dd8b94b3c9efe8ae071ff6b1b936a27ac5f6e651845c3b9631fa4c1c2"}, + {file = "tree_sitter_embedded_template-0.25.0-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:025f7ca84218dcd8455efc901bdbcc2689fb694f3a636c0448e322a23d4bc96b"}, + {file = "tree_sitter_embedded_template-0.25.0-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b5dc1aef6ffa3fae621fe037d85dd98948b597afba20df29d779c426be813ee5"}, + {file = "tree_sitter_embedded_template-0.25.0-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:d0a35cfe634c44981a516243bc039874580e02a2990669313730187ce83a5bc6"}, + {file = "tree_sitter_embedded_template-0.25.0-cp310-abi3-win_amd64.whl", hash = "sha256:3e05a4ac013d54505e75ae48e1a0e9db9aab19949fe15d9f4c7345b11a84a069"}, + {file = "tree_sitter_embedded_template-0.25.0-cp310-abi3-win_arm64.whl", hash = "sha256:2751d402179ac0e83f2065b249d8fe6df0718153f1636bcb6a02bde3e5730db9"}, + {file = "tree_sitter_embedded_template-0.25.0.tar.gz", hash = "sha256:7d72d5e8a1d1d501a7c90e841b51f1449a90cc240be050e4fb85c22dab991d50"}, +] + +[package.extras] +core = ["tree-sitter (>=0.24,<1.0)"] + +[[package]] +name = "tree-sitter-language-pack" +version = "0.13.0" +description = "Comprehensive collection of 160+ tree-sitter language parsers" +optional = false +python-versions = ">=3.10.0" +groups = ["main"] +files = [ + {file = "tree_sitter_language_pack-0.13.0-cp310-abi3-macosx_10_15_universal2.whl", hash = "sha256:0e7eae812b40a2dc8a12eb2f5c55e130eb892706a0bee06215dd76affeb00d07"}, + {file = "tree_sitter_language_pack-0.13.0-cp310-abi3-manylinux2014_aarch64.whl", hash = "sha256:7fdacf383418a845b20772118fcb53ad245f9c5d409bd07dae16acec65151756"}, + {file = "tree_sitter_language_pack-0.13.0-cp310-abi3-manylinux2014_x86_64.whl", hash = "sha256:0d4f261fce387ae040dae7e4d1c1aca63d84c88320afcc0961c123bec0be8377"}, + {file = "tree_sitter_language_pack-0.13.0-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:78f369dc4d456c5b08d659939e662c2f9b9fba8c0ec5538a1f973e01edfcf04d"}, + {file = "tree_sitter_language_pack-0.13.0-cp310-abi3-win_amd64.whl", hash = "sha256:1cdbc88a03dacd47bec69e56cc20c48eace1fbb6f01371e89c3ee6a2e8f34db1"}, + {file = "tree_sitter_language_pack-0.13.0.tar.gz", hash = "sha256:032034c5e27b1f6e00730b9e7c2dbc8203b4700d0c681fd019d6defcf61183ec"}, +] + +[package.dependencies] +tree-sitter = ">=0.25.2" +tree-sitter-c-sharp = ">=0.23.1" +tree-sitter-embedded-template = ">=0.25.0" +tree-sitter-yaml = ">=0.7.2" + +[[package]] +name = "tree-sitter-yaml" +version = "0.7.2" +description = "YAML grammar for tree-sitter" +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "tree_sitter_yaml-0.7.2-cp310-abi3-macosx_10_9_x86_64.whl", hash = "sha256:7e269ddcfcab8edb14fbb1f1d34eed1e1e26888f78f94eedfe7cc98c60f8bc9f"}, + {file = "tree_sitter_yaml-0.7.2-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:0807b7966e23ddf7dddc4545216e28b5a58cdadedcecca86b8d8c74271a07870"}, + {file = "tree_sitter_yaml-0.7.2-cp310-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f1a5c60c98b6c4c037aae023569f020d0c489fad8dc26fdfd5510363c9c29a41"}, + {file = "tree_sitter_yaml-0.7.2-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:88636d19d0654fd24f4f242eaaafa90f6f5ebdba8a62e4b32d251ed156c51a2a"}, + {file = "tree_sitter_yaml-0.7.2-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1d2e8f0bb14aa4537320952d0f9607eef3021d5aada8383c34ebeece17db1e06"}, + {file = "tree_sitter_yaml-0.7.2-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:74ca712c50fc9d7dbc68cb36b4a7811d6e67a5466b5a789f19bf8dd6084ef752"}, + {file = "tree_sitter_yaml-0.7.2-cp310-abi3-win_amd64.whl", hash = "sha256:7587b5ca00fc4f9a548eff649697a3b395370b2304b399ceefa2087d8a6c9186"}, + {file = "tree_sitter_yaml-0.7.2-cp310-abi3-win_arm64.whl", hash = "sha256:f63c227b18e7ce7587bce124578f0bbf1f890ac63d3e3cd027417574273642c4"}, + {file = "tree_sitter_yaml-0.7.2.tar.gz", hash = "sha256:756db4c09c9d9e97c81699e8f941cb8ce4e51104927f6090eefe638ee567d32c"}, +] + +[package.extras] +core = ["tree-sitter (>=0.24,<1.0)"] + [[package]] name = "ttkwidgets" version = "0.13.0" @@ -3958,4 +4095,4 @@ propcache = ">=0.2.1" [metadata] lock-version = "2.1" python-versions = "^3.10" -content-hash = "809d30e09dab4675cfc1e562fbbd40e95b4afae6eac467c8d53d09903518a008" +content-hash = "ca5ed829cffdd2eb46bf84ec3b40cadc7433c4a55f958441fc263f3f97011ea6" diff --git a/pyproject.toml b/pyproject.toml index 5a336448..e0d6be58 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,6 +37,8 @@ editorconfig = "^0.17.0" tkextrafont = { version = "^0.6.3", platform = "win32" } ptyprocess = { version = "^0.7.0", platform = "linux" } anthropic = "^0.77.0" +tree-sitter = "^0.25.2" +tree-sitter-language-pack = "^0.13.0" [tool.poetry.group.dev.dependencies] pytest = ">=8.2.1,<10.0.0" From 38d21794e362fe6448cfdd4d9fc4c234d75e9fab Mon Sep 17 00:00:00 2001 From: Billy Date: Sat, 7 Feb 2026 02:10:36 +0530 Subject: [PATCH 02/19] fix: Debugger is now moved to secondary sidebar by default --- src/biscuit/debugger/base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/biscuit/debugger/base.py b/src/biscuit/debugger/base.py index 32bf4395..8473e9ce 100644 --- a/src/biscuit/debugger/base.py +++ b/src/biscuit/debugger/base.py @@ -26,8 +26,8 @@ def __init__(self, manager: DebuggerManager): super().__init__() self.manager = manager self.base = manager.base - self.variables = self.base.sidebar.debug.variables - self.callstack = self.base.sidebar.debug.callstack + self.variables = self.base.secondary_sidebar.debug.variables + self.callstack = self.base.secondary_sidebar.debug.callstack self.breakpoints: dict[str, set[int]] = {} # file_path -> set of line numbers def format_path(self, path: str) -> str: From e1d2ef70d7dc0ff3da31b2c1ff390310b8f0d8a6 Mon Sep 17 00:00:00 2001 From: Billy Date: Sat, 7 Feb 2026 02:11:20 +0530 Subject: [PATCH 03/19] feat: New tree-sitter highlighter implementation (commented out old pygments for now) --- src/biscuit/editor/text/highlighter.py | 306 +++++++------- src/biscuit/editor/text/ts_highlighter.py | 461 ++++++++++++++++++++++ 2 files changed, 624 insertions(+), 143 deletions(-) create mode 100644 src/biscuit/editor/text/ts_highlighter.py diff --git a/src/biscuit/editor/text/highlighter.py b/src/biscuit/editor/text/highlighter.py index 44a5b5cc..d59804f6 100644 --- a/src/biscuit/editor/text/highlighter.py +++ b/src/biscuit/editor/text/highlighter.py @@ -1,12 +1,8 @@ from __future__ import annotations -import os -import tkinter as tk import typing -from pygments import lex -from pygments.lexers import get_lexer_by_name, get_lexer_for_filename -from pygments.style import Style +from .ts_highlighter import TreeSitterHighlighter if typing.TYPE_CHECKING: from biscuit import App @@ -14,160 +10,184 @@ from .text import Text -class BiscuitStyle(Style): - name = "biscuit" - - def __init__(self, master: Highlighter) -> None: - self.base = master.base - self.styles = self.base.theme.syntax - self.background_color = self.base.theme.editors.background - - class Highlighter: - """Syntax Highlighter + """Syntax Highlighter — Tree-sitter backend. - This highlighter uses pygments to highlight the text content based on the lexer provided. - The lexer can be provided explicitly or it can be detected from the file extension. - If the file extension is not recognized, it will default to plain text. - - Supported languages and text formats: https://pygments.org/docs/lexers/ + Delegates to TreeSitterHighlighter for incremental, AST-based highlighting. + The original Pygments implementation is preserved below (commented out). """ def __init__(self, text: Text, language: str = None, *args, **kwargs) -> None: - """Highlighter based on pygments lexers - - If language is not given, it will try to detect the language from the file extension. - If the file extension is not recognized, it will default to plain text. - - Args: - text (Text): The text instance to be highlighted - language (str, optional): Language to highlight. Defaults to None.""" - self.text: Text = text self.base: App = text.base - self.language = language - - if language: - try: - self.lexer = get_lexer_by_name(language) - self.text.language = self.lexer.name - self.text.language_alias = self.lexer.aliases[0] - except: - self.lexer = None - self.text.language = "Plain Text" - self.text.language_alias = "text" - self.base.notifications.info("Selected lexer is not available.") - else: - try: - if os.path.basename(text.path).endswith("txt"): - raise Exception() - - self.lexer = get_lexer_for_filename( - os.path.basename(text.path), encoding=text.encoding - ) - self.text.language = self.lexer.name - self.text.language_alias = self.lexer.aliases[0] - except: - self.lexer = None - self.text.language = "Plain Text" - self.text.language_alias = "text" - - self.tag_colors = self.base.theme.syntax - self.setup_highlight_tags() + + self.ts = TreeSitterHighlighter(text, language) + + # Set language info for statusbar display + self.text.language = self.ts.get_display_name() + self.text.language_alias = self.ts.get_language_alias() def detect_language(self) -> None: - """Detect the language from the file extension and set the lexer - Refreshes language attribute of the text instance.""" - - try: - if os.path.basename(self.text.path).endswith("txt"): - raise Exception() - - self.lexer = get_lexer_for_filename( - os.path.basename(self.text.path), encoding=self.text.encoding - ) - self.text.language = self.lexer.name - self.text.language_alias = self.lexer.aliases[0] - self.highlight() - except: - self.lexer = None - self.text.language = "Plain Text" - self.text.language_alias = "text" + """Re-detect language from the file extension.""" + self.ts.detect_language() + self.text.language = self.ts.get_display_name() + self.text.language_alias = self.ts.get_language_alias() def change_language(self, language: str) -> None: - """Change the language of the highlighter - If language is not given, it will try to detect the language from the file extension. - If the file extension is not recognized, it will default to plain text. - - Args: - language (str): Language to highlight. Defaults to None.""" - - try: - self.lexer = get_lexer_by_name(language) - except: - self.lexer = None - self.text.language = "Plain Text" - self.text.language_alias = "text" - self.base.notifications.info("Selected lexer is not available.") - return - - self.text.language = self.lexer.name - self.text.language_alias = self.lexer.aliases[0] - self.tag_colors = self.base.theme.syntax + """Change the highlighting language.""" + self.ts.change_language(language) + self.text.language = self.ts.get_display_name() + self.text.language_alias = self.ts.get_language_alias() self.text.master.on_change() self.base.statusbar.on_open_file(self.text) def setup_highlight_tags(self) -> None: - """Setup the tags for highlighting the text content""" - - for token, props in self.tag_colors.items(): - if isinstance(props, dict): - if "font" in props and isinstance(props["font"], dict): - f = self.base.settings.font.copy() - f.config(**props["font"]) - props["font"] = f - - self.text.tag_configure(str(token), **props) - else: - self.text.tag_configure(str(token), foreground=props) + """Setup Tkinter text tags for highlighting.""" + self.ts.setup_highlight_tags() def clear(self) -> None: - """Clears the highlighting of the text content""" - - for token, _ in self.tag_colors.items(): - self.text.tag_remove(str(token), "1.0", tk.END) + """Clear all highlighting.""" + self.ts.clear() def highlight(self) -> None: - """Highlight the text content - - This method highlights the text content based on the lexer provided. - - TODO: As of now, it highlights the entire text content. - It needs to be optimized to highlight only the visible area.""" - - if not self.lexer or not self.tag_colors: - return - - for token, _ in self.tag_colors.items(): - self.text.tag_remove(str(token), "1.0", tk.END) - - text = self.text.get_all_text() - - # NOTE: Highlighting only visible area - # total_lines = int(self.text.index('end-1c').split('.')[0]) - # start_line = int(self.text.yview()[0] * total_lines) - # first_visible_index = f"{start_line}.0" - # last_visible_index =f"{self.text.winfo_height()}.end" - # for token, _ in self.tag_colors.items(): - # self.text.tag_remove(str(token), first_visible_index, last_visible_index) - # text = self.text.get(first_visible_index, last_visible_index) - - self.text.mark_set("range_start", "1.0") - for token, content in lex(text, self.lexer): - self.text.mark_set("range_end", f"range_start + {len(content)}c") - self.text.tag_add(str(token), "range_start", "range_end") - self.text.mark_set("range_start", "range_end") - - # DEBUG - # print(f"{content} is recognized as a <{str(token)}>") - # print("==================================") + """Full highlight (parse entire file).""" + self.ts.highlight() + + def incremental_highlight(self, edit_info: dict) -> None: + """Incremental highlight after an edit.""" + self.ts.incremental_highlight(edit_info) + + +# ============================================================================= +# ORIGINAL PYGMENTS IMPLEMENTATION (disabled — kept for reference) +# ============================================================================= +# +# import os +# import tkinter as tk +# +# from pygments import lex +# from pygments.lexers import get_lexer_by_name, get_lexer_for_filename +# from pygments.style import Style +# +# +# class BiscuitStyle(Style): +# name = "biscuit" +# +# def __init__(self, master: Highlighter) -> None: +# self.base = master.base +# self.styles = self.base.theme.syntax +# self.background_color = self.base.theme.editors.background +# +# +# class Highlighter: +# """Syntax Highlighter +# +# This highlighter uses pygments to highlight the text content based on +# the lexer provided. The lexer can be provided explicitly or it can be +# detected from the file extension. If the file extension is not +# recognized, it will default to plain text. +# +# Supported languages and text formats: https://pygments.org/docs/lexers/ +# """ +# +# def __init__(self, text: Text, language: str = None, *args, **kwargs): +# self.text: Text = text +# self.base: App = text.base +# self.language = language +# +# if language: +# try: +# self.lexer = get_lexer_by_name(language) +# self.text.language = self.lexer.name +# self.text.language_alias = self.lexer.aliases[0] +# except: +# self.lexer = None +# self.text.language = "Plain Text" +# self.text.language_alias = "text" +# self.base.notifications.info( +# "Selected lexer is not available." +# ) +# else: +# try: +# if os.path.basename(text.path).endswith("txt"): +# raise Exception() +# +# self.lexer = get_lexer_for_filename( +# os.path.basename(text.path), encoding=text.encoding +# ) +# self.text.language = self.lexer.name +# self.text.language_alias = self.lexer.aliases[0] +# except: +# self.lexer = None +# self.text.language = "Plain Text" +# self.text.language_alias = "text" +# +# self.tag_colors = self.base.theme.syntax +# self.setup_highlight_tags() +# +# def detect_language(self) -> None: +# try: +# if os.path.basename(self.text.path).endswith("txt"): +# raise Exception() +# +# self.lexer = get_lexer_for_filename( +# os.path.basename(self.text.path), encoding=self.text.encoding +# ) +# self.text.language = self.lexer.name +# self.text.language_alias = self.lexer.aliases[0] +# self.highlight() +# except: +# self.lexer = None +# self.text.language = "Plain Text" +# self.text.language_alias = "text" +# +# def change_language(self, language: str) -> None: +# try: +# self.lexer = get_lexer_by_name(language) +# except: +# self.lexer = None +# self.text.language = "Plain Text" +# self.text.language_alias = "text" +# self.base.notifications.info( +# "Selected lexer is not available." +# ) +# return +# +# self.text.language = self.lexer.name +# self.text.language_alias = self.lexer.aliases[0] +# self.tag_colors = self.base.theme.syntax +# self.text.master.on_change() +# self.base.statusbar.on_open_file(self.text) +# +# def setup_highlight_tags(self) -> None: +# for token, props in self.tag_colors.items(): +# if isinstance(props, dict): +# if "font" in props and isinstance(props["font"], dict): +# f = self.base.settings.font.copy() +# f.config(**props["font"]) +# props["font"] = f +# +# self.text.tag_configure(str(token), **props) +# else: +# self.text.tag_configure(str(token), foreground=props) +# +# def clear(self) -> None: +# for token, _ in self.tag_colors.items(): +# self.text.tag_remove(str(token), "1.0", tk.END) +# +# def highlight(self) -> None: +# if not self.lexer or not self.tag_colors: +# return +# +# for token, _ in self.tag_colors.items(): +# self.text.tag_remove(str(token), "1.0", tk.END) +# +# text = self.text.get_all_text() +# +# self.text.mark_set("range_start", "1.0") +# for token, content in lex(text, self.lexer): +# self.text.mark_set( +# "range_end", f"range_start + {len(content)}c" +# ) +# self.text.tag_add(str(token), "range_start", "range_end") +# self.text.mark_set("range_start", "range_end") diff --git a/src/biscuit/editor/text/ts_highlighter.py b/src/biscuit/editor/text/ts_highlighter.py new file mode 100644 index 00000000..b4b0b916 --- /dev/null +++ b/src/biscuit/editor/text/ts_highlighter.py @@ -0,0 +1,461 @@ +from __future__ import annotations + +import os +import tkinter as tk +import typing +from pathlib import Path + +if typing.TYPE_CHECKING: + from biscuit import App + + from .text import Text + +try: + from tree_sitter import Parser, Query, QueryCursor + from tree_sitter_language_pack import get_language, get_parser + + TREE_SITTER_AVAILABLE = True +except ImportError: + TREE_SITTER_AVAILABLE = False + +# File extension -> tree-sitter-language-pack language key +EXTENSION_MAP = { + ".py": "python", + ".pyw": "python", + ".pyi": "python", + ".js": "javascript", + ".mjs": "javascript", + ".cjs": "javascript", + ".jsx": "javascript", + ".ts": "typescript", + ".tsx": "tsx", + ".c": "c", + ".h": "c", + ".cpp": "cpp", + ".cc": "cpp", + ".cxx": "cpp", + ".hpp": "cpp", + ".hh": "cpp", + ".java": "java", + ".rs": "rust", + ".go": "go", + ".rb": "ruby", + ".erb": "ruby", + ".php": "php", + ".swift": "swift", + ".kt": "kotlin", + ".kts": "kotlin", + ".cs": "csharp", + ".lua": "lua", + ".html": "html", + ".htm": "html", + ".css": "css", + ".scss": "scss", + ".json": "json", + ".toml": "toml", + ".yaml": "yaml", + ".yml": "yaml", + ".md": "markdown", + ".markdown": "markdown", + ".sql": "sql", + ".sh": "bash", + ".bash": "bash", + ".zsh": "bash", + ".r": "r", + ".R": "r", + ".scala": "scala", + ".zig": "zig", + ".dart": "dart", + ".ex": "elixir", + ".exs": "elixir", + ".erl": "erlang", + ".hrl": "erlang", + ".hs": "haskell", + ".ml": "ocaml", + ".mli": "ocaml", + ".pl": "perl", + ".pm": "perl", + ".vim": "vim", + ".el": "elisp", + ".clj": "clojure", + ".cmake": "cmake", + ".dockerfile": "dockerfile", + ".make": "make", + ".mk": "make", + ".Makefile": "make", + ".proto": "proto", + ".xml": "xml", + ".svelte": "svelte", + ".vue": "vue", + ".tf": "hcl", + ".hcl": "hcl", + ".nix": "nix", + ".gleam": "gleam", + ".v": "v", + ".asm": "asm", + ".s": "asm", + ".S": "asm", + ".ini": "ini", + ".cfg": "ini", + ".reg": "ini", +} + +# Language alias -> tree-sitter-language-pack key +# Maps common names / Pygments aliases to tree-sitter keys +LANGUAGE_ALIAS_MAP = { + "python": "python", + "python3": "python", + "py": "python", + "javascript": "javascript", + "js": "javascript", + "typescript": "typescript", + "ts": "typescript", + "tsx": "tsx", + "c": "c", + "cpp": "cpp", + "c++": "cpp", + "java": "java", + "rust": "rust", + "go": "go", + "golang": "go", + "ruby": "ruby", + "rb": "ruby", + "php": "php", + "swift": "swift", + "kotlin": "kotlin", + "kt": "kotlin", + "csharp": "csharp", + "c#": "csharp", + "c_sharp": "csharp", + "lua": "lua", + "html": "html", + "css": "css", + "scss": "scss", + "json": "json", + "toml": "toml", + "yaml": "yaml", + "markdown": "markdown", + "md": "markdown", + "sql": "sql", + "bash": "bash", + "sh": "bash", + "shell": "bash", + "r": "r", + "scala": "scala", + "zig": "zig", + "dart": "dart", + "elixir": "elixir", + "erlang": "erlang", + "haskell": "haskell", + "ocaml": "ocaml", + "perl": "perl", + "vim": "vim", + "clojure": "clojure", + "cmake": "cmake", + "dockerfile": "dockerfile", + "docker": "dockerfile", + "make": "make", + "xml": "xml", + "svelte": "svelte", + "vue": "vue", + "hcl": "hcl", + "terraform": "hcl", + "nix": "nix", + "gleam": "gleam", + "v": "v", + "asm": "asm", + "ini": "ini", +} + +# Display names for statusbar +LANGUAGE_DISPLAY_NAMES = { + "python": "Python", + "javascript": "JavaScript", + "typescript": "TypeScript", + "tsx": "TSX", + "c": "C", + "cpp": "C++", + "java": "Java", + "rust": "Rust", + "go": "Go", + "ruby": "Ruby", + "php": "PHP", + "swift": "Swift", + "kotlin": "Kotlin", + "csharp": "C#", + "lua": "Lua", + "html": "HTML", + "css": "CSS", + "scss": "SCSS", + "json": "JSON", + "toml": "TOML", + "yaml": "YAML", + "markdown": "Markdown", + "sql": "SQL", + "bash": "Bash", + "r": "R", + "scala": "Scala", + "zig": "Zig", + "dart": "Dart", + "elixir": "Elixir", + "erlang": "Erlang", + "haskell": "Haskell", + "ocaml": "OCaml", + "perl": "Perl", + "vim": "Vim", + "clojure": "Clojure", + "cmake": "CMake", + "dockerfile": "Dockerfile", + "make": "Makefile", + "xml": "XML", + "svelte": "Svelte", + "vue": "Vue", + "hcl": "HCL", + "nix": "Nix", + "gleam": "Gleam", + "v": "V", + "asm": "Assembly", + "ini": "INI", +} + +QUERIES_DIR = Path(__file__).parent / "queries" + + +class TreeSitterHighlighter: + """Syntax highlighter using Tree-sitter for incremental parsing. + + Uses tree-sitter-language-pack for grammar bindings and bundled + highlights.scm query files for capture-based syntax highlighting. + Supports incremental re-parsing via tree.edit() for fast updates. + """ + + def __init__(self, text: Text, language: str = None, *args, **kwargs) -> None: + self.text: Text = text + self.base: App = text.base + self.parser: Parser | None = None + self.tree = None + self.query: Query | None = None + self.language_name: str | None = None + self.tag_colors: dict = self.base.theme.treesitter_syntax + + if not TREE_SITTER_AVAILABLE: + return + + self._setup_language(language) + self.setup_highlight_tags() + + def _setup_language(self, language: str = None) -> None: + """Initialize parser and highlight query for the given language.""" + lang_key = self._resolve_language(language) + if not lang_key: + return + + try: + self.parser = get_parser(lang_key) + ts_language = get_language(lang_key) + query_text = self._load_highlight_query(lang_key) + if query_text: + self.query = Query(ts_language, query_text) + self.language_name = lang_key + except Exception: + self.parser = None + self.query = None + self.language_name = None + + def _resolve_language(self, language: str = None) -> str | None: + """Map filename extension or language name to a language-pack key.""" + if language: + key = language.lower().strip() + if key in LANGUAGE_ALIAS_MAP: + return LANGUAGE_ALIAS_MAP[key] + # Try direct key (might already be a valid key) + return key if self._is_valid_language(key) else None + + # Auto-detect from file extension + if self.text.path: + _, ext = os.path.splitext(self.text.path) + if ext in EXTENSION_MAP: + return EXTENSION_MAP[ext] + # Special case: files like Makefile, Dockerfile (no extension) + basename = os.path.basename(self.text.path) + if basename == "Makefile" or basename == "makefile": + return "make" + if basename == "Dockerfile": + return "dockerfile" + if basename == "CMakeLists.txt": + return "cmake" + + return None + + def _is_valid_language(self, key: str) -> bool: + """Check if a language key is available in tree-sitter-language-pack.""" + try: + get_language(key) + return True + except Exception: + return False + + def _load_highlight_query(self, lang_key: str) -> str | None: + """Load highlights.scm from the bundled queries directory.""" + query_path = QUERIES_DIR / lang_key / "highlights.scm" + if query_path.exists(): + return query_path.read_text(encoding="utf-8") + return None + + def get_display_name(self) -> str: + """Get human-readable language name for statusbar.""" + if self.language_name and self.language_name in LANGUAGE_DISPLAY_NAMES: + return LANGUAGE_DISPLAY_NAMES[self.language_name] + if self.language_name: + return self.language_name.replace("_", " ").title() + return "Plain Text" + + def get_language_alias(self) -> str: + """Get language alias for internal use.""" + return self.language_name or "text" + + def setup_highlight_tags(self) -> None: + """Configure Tkinter text tags for each Tree-sitter capture name.""" + for capture_name, props in self.tag_colors.items(): + tag = f"ts.{capture_name}" + if isinstance(props, dict): + config = {} + for k, v in props.items(): + if k == "font" and isinstance(v, dict): + f = self.base.settings.font.copy() + f.config(**v) + config["font"] = f + else: + config[k] = v + self.text.tag_configure(tag, **config) + else: + self.text.tag_configure(tag, foreground=props) + + def clear(self) -> None: + """Remove all Tree-sitter highlight tags.""" + for capture_name in self.tag_colors: + self.text.tag_remove(f"ts.{capture_name}", "1.0", tk.END) + + def highlight(self) -> None: + """Full parse and highlight (used on file load / language change).""" + if not self.parser or not self.query: + return + + code = self.text.get_all_text() + code_bytes = code.encode("utf-8") + self.tree = self.parser.parse(code_bytes) + self._apply_highlights_full() + + def incremental_highlight(self, edit_info: dict) -> None: + """Incremental parse after an edit for fast updates. + + Args: + edit_info: dict with keys: start_byte, old_end_byte, new_end_byte, + start_point, old_end_point, new_end_point + """ + if not self.tree or not self.parser or not self.query: + self.highlight() + return + + self.tree.edit( + start_byte=edit_info["start_byte"], + old_end_byte=edit_info["old_end_byte"], + new_end_byte=edit_info["new_end_byte"], + start_point=edit_info["start_point"], + old_end_point=edit_info["old_end_point"], + new_end_point=edit_info["new_end_point"], + ) + + code_bytes = self.text.get_all_text().encode("utf-8") + new_tree = self.parser.parse(code_bytes, self.tree) + + changed_ranges = self.tree.changed_ranges(new_tree) + self.tree = new_tree + + if changed_ranges: + self._apply_highlights_incremental(changed_ranges) + # If no changed ranges detected, skip (nothing visually changed) + + def _apply_highlights_full(self) -> None: + """Clear all tags and re-apply highlights from scratch.""" + # Clear all existing tree-sitter tags + for capture_name in self.tag_colors: + self.text.tag_remove(f"ts.{capture_name}", "1.0", tk.END) + + if not self.tree or not self.query: + return + + cursor = QueryCursor(self.query) + captures = cursor.captures(self.tree.root_node) + + for capture_name, nodes in captures.items(): + tag = self._resolve_tag(capture_name) + if not tag: + continue + for node in nodes: + start = f"{node.start_point[0] + 1}.{node.start_point[1]}" + end = f"{node.end_point[0] + 1}.{node.end_point[1]}" + self.text.tag_add(tag, start, end) + + def _apply_highlights_incremental(self, changed_ranges) -> None: + """Re-highlight only the changed ranges for speed.""" + # Clear tags in changed regions + for r in changed_ranges: + start = f"{r.start_point[0] + 1}.{r.start_point[1]}" + end = f"{r.end_point[0] + 1}.{r.end_point[1]}" + for capture_name in self.tag_colors: + self.text.tag_remove(f"ts.{capture_name}", start, end) + + # Re-apply highlights in changed regions + for r in changed_ranges: + cursor = QueryCursor(self.query) + cursor.set_byte_range(r.start_byte, r.end_byte) + captures = cursor.captures(self.tree.root_node) + + for capture_name, nodes in captures.items(): + tag = self._resolve_tag(capture_name) + if not tag: + continue + for node in nodes: + start = f"{node.start_point[0] + 1}.{node.start_point[1]}" + end = f"{node.end_point[0] + 1}.{node.end_point[1]}" + self.text.tag_add(tag, start, end) + + def _resolve_tag(self, capture_name: str) -> str | None: + """Resolve a capture name to a Tkinter tag, with fallback to parent.""" + tag = f"ts.{capture_name}" + if capture_name in self.tag_colors: + return tag + + # Hierarchical fallback: "keyword.function" -> "keyword" + if "." in capture_name: + parent = capture_name.split(".")[0] + if parent in self.tag_colors: + return f"ts.{parent}" + + return None + + def detect_language(self) -> None: + """Re-detect language from filename and refresh highlighting.""" + old_lang = self.language_name + self.language_name = None + self.parser = None + self.query = None + self.tree = None + + self._setup_language(None) + self.setup_highlight_tags() + + if self.language_name != old_lang: + self.highlight() + + def change_language(self, language: str) -> None: + """Switch to a different language and re-highlight.""" + self.language_name = None + self.parser = None + self.query = None + self.tree = None + + self._setup_language(language) + self.setup_highlight_tags() + self.highlight() From ffed996bd4e468e6ff62e12ece61a9b9d97dfe5d Mon Sep 17 00:00:00 2001 From: Billy Date: Sat, 7 Feb 2026 02:11:47 +0530 Subject: [PATCH 04/19] feat: Tree sitter highlighter completed implementation & Color theming --- src/biscuit/editor/text/text.py | 203 ++++++++++++++++++++++++---- src/biscuit/settings/theme/theme.py | 59 ++++++++ 2 files changed, 232 insertions(+), 30 deletions(-) diff --git a/src/biscuit/editor/text/text.py b/src/biscuit/editor/text/text.py index f4bf067f..bde5acbc 100644 --- a/src/biscuit/editor/text/text.py +++ b/src/biscuit/editor/text/text.py @@ -95,6 +95,7 @@ def __init__( self.editorconfig = {} # self.last_change = Change(None, None, None, None, None) + self._pending_edit_info = None self.highlighter = Highlighter(self, language) if not self.standalone and not self.minimalist: self.base.statusbar.on_open_file(self) @@ -583,10 +584,10 @@ def uncomment_selection(self): for line in range(start_line, end_line + 1): # delete comment prefix with the trailing space if ( - self.get(f"{line}.0", f"{line}.{len(self.comment_prefix)+1}") + self.get(f"{line}.0", f"{line}.{len(self.comment_prefix) + 1}") == f"{self.comment_prefix} " ): - self.delete(f"{line}.0", f"{line}.{len(self.comment_prefix)+1}") + self.delete(f"{line}.0", f"{line}.{len(self.comment_prefix) + 1}") # trailing space not detected, delete the comment prefix elif ( self.get(f"{line}.0", f"{line}.{len(self.comment_prefix)}") @@ -656,7 +657,13 @@ def indent_selection(self): return "break" def refresh(self): - self.highlighter.highlight() + if self._pending_edit_info and hasattr( + self.highlighter, "incremental_highlight" + ): + self.highlighter.incremental_highlight(self._pending_edit_info) + self._pending_edit_info = None + else: + self.highlighter.highlight() self.highlight_current_word() if self.minimalist or self.standalone: @@ -1459,45 +1466,181 @@ def create_proxy(self): self.tk.call("rename", self._w, self._orig) self.tk.createcommand(self._w, self._proxy) - def _proxy(self, *args): - if ( - args[0] == "get" - and (args[1] == tk.SEL_FIRST and args[2] == tk.SEL_LAST) + def _is_sel_op_without_sel(self, args) -> bool: + """Check if this is a get/delete on selection when nothing is selected.""" + return ( + len(args) >= 3 + and args[1] == tk.SEL_FIRST + and args[2] == tk.SEL_LAST and not self.tag_ranges(tk.SEL) - ): - return - if ( - args[0] == "delete" - and (args[1] == tk.SEL_FIRST and args[2] == tk.SEL_LAST) - and not self.tag_ranges(tk.SEL) - ): + ) + + def _is_scroll_op(self, args) -> bool: + """Check if this is a scroll operation.""" + return args[0:2] in ( + ("xview", "moveto"), + ("yview", "moveto"), + ("xview", "scroll"), + ("yview", "scroll"), + ) + + def _notify_lsp_change(self): + """Notify LSP server of content change if active.""" + if self.lsp: + try: + self.base.language_server_manager.content_changed(self) + except Exception: + pass + + def _proxy(self, *args): + if args[0] in ("get", "delete") and self._is_sel_op_without_sel(args): return + is_edit = args[0] in ("insert", "replace", "delete") + edit_info = self._capture_edit_info_before(args) if is_edit else None + cmd = (self._orig,) + args try: result = self.tk.call(cmd) except Exception: return - if args[0] in ("insert", "replace", "delete"): + if is_edit: + if edit_info: + self._finalize_edit_info(edit_info, args) self.event_generate("<>", when="tail") - if self.lsp: - try: - self.base.language_server_manager.content_changed(self) - except Exception: - pass - - # if "insert" in args[0:3] and "get" in args[0:3]: - # print(temp) - + self._notify_lsp_change() elif args[0:3] == ("mark", "set", "insert"): self.event_generate("<>", when="tail") - elif ( - args[0:2] == ("xview", "moveto") - or args[0:2] == ("yview", "moveto") - or args[0:2] == ("xview", "scroll") - or args[0:2] == ("yview", "scroll") - ): + elif self._is_scroll_op(args): self.event_generate("<>", when="tail") return result + + def _tk_index_to_point(self, index: str) -> tuple[int, int]: + """Convert a Tk text index to a Tree-sitter (row, col) point.""" + try: + pos = self.tk.call(self._orig, "index", index) + line, col = str(pos).split(".") + return (int(line) - 1, int(col)) + except Exception: + return (0, 0) + + def _point_to_byte(self, point: tuple[int, int]) -> int: + """Compute byte offset from a (row, col) point. + + Gets all text from start to the position in a single Tk call, + then computes its UTF-8 byte length. + """ + try: + row, col = point + tk_index = f"{row + 1}.{col}" + text_before = self.tk.call(self._orig, "get", "1.0", tk_index) + return len(str(text_before).encode("utf-8")) + except Exception: + return 0 + + def _capture_edit_info_before(self, args) -> dict | None: + """Capture position info before an edit operation executes.""" + try: + if args[0] == "insert": + # args: ("insert", index, text, ?tags, ?text, ?tags, ...) + start_point = self._tk_index_to_point(args[1]) + start_byte = self._point_to_byte(start_point) + return { + "op": "insert", + "start_byte": start_byte, + "old_end_byte": start_byte, + "start_point": start_point, + "old_end_point": start_point, + } + elif args[0] == "delete": + # args: ("delete", start, ?end) + start_point = self._tk_index_to_point(args[1]) + start_byte = self._point_to_byte(start_point) + if len(args) > 2: + end_point = self._tk_index_to_point(args[2]) + else: + # Single char delete + end_point = self._tk_index_to_point(f"{args[1]} +1c") + end_byte = self._point_to_byte(end_point) + return { + "op": "delete", + "start_byte": start_byte, + "old_end_byte": end_byte, + "start_point": start_point, + "old_end_point": end_point, + } + elif args[0] == "replace": + # args: ("replace", start, end, text) + start_point = self._tk_index_to_point(args[1]) + start_byte = self._point_to_byte(start_point) + end_point = self._tk_index_to_point(args[2]) + end_byte = self._point_to_byte(end_point) + return { + "op": "replace", + "start_byte": start_byte, + "old_end_byte": end_byte, + "start_point": start_point, + "old_end_point": end_point, + } + except Exception: + pass + return None + + def _finalize_edit_info(self, edit_info: dict, args) -> None: + """Compute new_end after the edit and store as pending edit info.""" + try: + if edit_info["op"] == "insert": + # Compute new end from inserted text + # Collect all text parts (args may have: index, text, tags, text, tags, ...) + texts = [] + i = 2 + while i < len(args): + texts.append(str(args[i])) + i += 2 # skip tags + inserted = "".join(texts) + inserted_bytes = len(inserted.encode("utf-8")) + new_end_byte = edit_info["start_byte"] + inserted_bytes + # Compute new end point + lines = inserted.split("\n") + if len(lines) == 1: + new_end_point = ( + edit_info["start_point"][0], + edit_info["start_point"][1] + len(lines[0]), + ) + else: + new_end_point = ( + edit_info["start_point"][0] + len(lines) - 1, + len(lines[-1]), + ) + edit_info["new_end_byte"] = new_end_byte + edit_info["new_end_point"] = new_end_point + + elif edit_info["op"] == "delete": + # After delete, new end = start (deleted region collapsed) + edit_info["new_end_byte"] = edit_info["start_byte"] + edit_info["new_end_point"] = edit_info["start_point"] + + elif edit_info["op"] == "replace": + # Compute new end from replacement text + replacement = str(args[3]) if len(args) > 3 else "" + replacement_bytes = len(replacement.encode("utf-8")) + new_end_byte = edit_info["start_byte"] + replacement_bytes + lines = replacement.split("\n") + if len(lines) == 1: + new_end_point = ( + edit_info["start_point"][0], + edit_info["start_point"][1] + len(lines[0]), + ) + else: + new_end_point = ( + edit_info["start_point"][0] + len(lines) - 1, + len(lines[-1]), + ) + edit_info["new_end_byte"] = new_end_byte + edit_info["new_end_point"] = new_end_point + + self._pending_edit_info = edit_info + except Exception: + self._pending_edit_info = None diff --git a/src/biscuit/settings/theme/theme.py b/src/biscuit/settings/theme/theme.py index 51edf9d4..afb104ad 100644 --- a/src/biscuit/settings/theme/theme.py +++ b/src/biscuit/settings/theme/theme.py @@ -473,3 +473,62 @@ def __init__(self) -> None: Token.Punctuation: self.Punctuation, Token.Punctuation.Marker: self.Punctuation, } + + # Tree-sitter capture name -> color mapping + self.treesitter_syntax = { + "keyword": self.Keyword, + "keyword.function": self.Keyword, + "keyword.return": self.Keyword, + "keyword.operator": self.Keyword, + "keyword.import": self.Keyword, + "keyword.type": self.Keyword, + "keyword.conditional": self.Keyword, + "keyword.repeat": self.Keyword, + "keyword.exception": self.Keyword, + "keyword.directive": self.Keyword, + "function": self.Function, + "function.call": self.Function, + "function.method": self.Function, + "function.method.call": self.Function, + "function.builtin": self.Function, + "function.macro": self.Function, + "method": self.Function, + "constructor": self.Function, + "type": self.Name, + "type.builtin": self.Name, + "type.definition": self.Name, + "type.qualifier": self.Keyword, + "variable": self.Name, + "variable.builtin": self.Name, + "variable.parameter": self.Name, + "variable.member": self.Name, + "property": self.Name, + "attribute": self.Name, + "attribute.builtin": self.Name, + "constant": self.Name, + "constant.builtin": self.Name, + "string": self.String, + "string.special": self.String, + "string.escape": self.String, + "string.regexp": self.String, + "string.documentation": self.String, + "number": self.Number, + "number.float": self.Number, + "boolean": self.Keyword, + "float": self.Number, + "comment": self.Comment, + "comment.documentation": self.Comment, + "punctuation": self.Punctuation, + "punctuation.bracket": self.Punctuation, + "punctuation.delimiter": self.Punctuation, + "punctuation.special": self.Punctuation, + "operator": self.Punctuation, + "tag": self.Name, + "tag.attribute": self.Name, + "tag.delimiter": self.Punctuation, + "namespace": self.Name, + "module": self.Name, + "label": self.Name, + "decorator": self.Name, + "exception": self.Name, + } From 7b7d1377f0418e4f67557f4c01522b62613cbc45 Mon Sep 17 00:00:00 2001 From: Billy Date: Sat, 7 Feb 2026 02:12:56 +0530 Subject: [PATCH 05/19] feat: highlight queries for python --- .../editor/text/queries/python/highlights.scm | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 src/biscuit/editor/text/queries/python/highlights.scm diff --git a/src/biscuit/editor/text/queries/python/highlights.scm b/src/biscuit/editor/text/queries/python/highlights.scm new file mode 100644 index 00000000..af744484 --- /dev/null +++ b/src/biscuit/editor/text/queries/python/highlights.scm @@ -0,0 +1,137 @@ +; Identifier naming conventions + +(identifier) @variable + +((identifier) @constructor + (#match? @constructor "^[A-Z]")) + +((identifier) @constant + (#match? @constant "^[A-Z][A-Z_]*$")) + +; Function calls + +(decorator) @function +(decorator + (identifier) @function) + +(call + function: (attribute attribute: (identifier) @function.method)) +(call + function: (identifier) @function) + +; Builtin functions + +((call + function: (identifier) @function.builtin) + (#match? + @function.builtin + "^(abs|all|any|ascii|bin|bool|breakpoint|bytearray|bytes|callable|chr|classmethod|compile|complex|delattr|dict|dir|divmod|enumerate|eval|exec|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|isinstance|issubclass|iter|len|list|locals|map|max|memoryview|min|next|object|oct|open|ord|pow|print|property|range|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|vars|zip|__import__)$")) + +; Function definitions + +(function_definition + name: (identifier) @function) + +(attribute attribute: (identifier) @property) +(type (identifier) @type) + +; Literals + +[ + (none) + (true) + (false) +] @constant.builtin + +[ + (integer) + (float) +] @number + +(comment) @comment +(string) @string +(escape_sequence) @escape + +(interpolation + "{" @punctuation.special + "}" @punctuation.special) @embedded + +[ + "-" + "-=" + "!=" + "*" + "**" + "**=" + "*=" + "/" + "//" + "//=" + "/=" + "&" + "&=" + "%" + "%=" + "^" + "^=" + "+" + "->" + "+=" + "<" + "<<" + "<<=" + "<=" + "<>" + "=" + ":=" + "==" + ">" + ">=" + ">>" + ">>=" + "|" + "|=" + "~" + "@=" + "and" + "in" + "is" + "not" + "or" + "is not" + "not in" +] @operator + +[ + "as" + "assert" + "async" + "await" + "break" + "class" + "continue" + "def" + "del" + "elif" + "else" + "except" + "exec" + "finally" + "for" + "from" + "global" + "if" + "import" + "lambda" + "nonlocal" + "pass" + "print" + "raise" + "return" + "try" + "while" + "with" + "yield" + "match" + "case" +] @keyword From 0c6fd5f2abf89040f074ed65f6ebaa43e5cd4d92 Mon Sep 17 00:00:00 2001 From: Billy Date: Sat, 7 Feb 2026 02:13:10 +0530 Subject: [PATCH 06/19] feat: highlight queries for rust --- .../editor/text/queries/rust/highlights.scm | 161 ++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 src/biscuit/editor/text/queries/rust/highlights.scm diff --git a/src/biscuit/editor/text/queries/rust/highlights.scm b/src/biscuit/editor/text/queries/rust/highlights.scm new file mode 100644 index 00000000..48c7284e --- /dev/null +++ b/src/biscuit/editor/text/queries/rust/highlights.scm @@ -0,0 +1,161 @@ +; Identifiers + +(type_identifier) @type +(primitive_type) @type.builtin +(field_identifier) @property + +; Identifier conventions + +; Assume all-caps names are constants +((identifier) @constant + (#match? @constant "^[A-Z][A-Z\\d_]+$'")) + +; Assume uppercase names are enum constructors +((identifier) @constructor + (#match? @constructor "^[A-Z]")) + +; Assume that uppercase names in paths are types +((scoped_identifier + path: (identifier) @type) + (#match? @type "^[A-Z]")) +((scoped_identifier + path: (scoped_identifier + name: (identifier) @type)) + (#match? @type "^[A-Z]")) +((scoped_type_identifier + path: (identifier) @type) + (#match? @type "^[A-Z]")) +((scoped_type_identifier + path: (scoped_identifier + name: (identifier) @type)) + (#match? @type "^[A-Z]")) + +; Assume all qualified names in struct patterns are enum constructors. (They're +; either that, or struct names; highlighting both as constructors seems to be +; the less glaring choice of error, visually.) +(struct_pattern + type: (scoped_type_identifier + name: (type_identifier) @constructor)) + +; Function calls + +(call_expression + function: (identifier) @function) +(call_expression + function: (field_expression + field: (field_identifier) @function.method)) +(call_expression + function: (scoped_identifier + "::" + name: (identifier) @function)) + +(generic_function + function: (identifier) @function) +(generic_function + function: (scoped_identifier + name: (identifier) @function)) +(generic_function + function: (field_expression + field: (field_identifier) @function.method)) + +(macro_invocation + macro: (identifier) @function.macro + "!" @function.macro) + +; Function definitions + +(function_item (identifier) @function) +(function_signature_item (identifier) @function) + +(line_comment) @comment +(block_comment) @comment + +(line_comment (doc_comment)) @comment.documentation +(block_comment (doc_comment)) @comment.documentation + +"(" @punctuation.bracket +")" @punctuation.bracket +"[" @punctuation.bracket +"]" @punctuation.bracket +"{" @punctuation.bracket +"}" @punctuation.bracket + +(type_arguments + "<" @punctuation.bracket + ">" @punctuation.bracket) +(type_parameters + "<" @punctuation.bracket + ">" @punctuation.bracket) + +"::" @punctuation.delimiter +":" @punctuation.delimiter +"." @punctuation.delimiter +"," @punctuation.delimiter +";" @punctuation.delimiter + +(parameter (identifier) @variable.parameter) + +(lifetime (identifier) @label) + +"as" @keyword +"async" @keyword +"await" @keyword +"break" @keyword +"const" @keyword +"continue" @keyword +"default" @keyword +"dyn" @keyword +"else" @keyword +"enum" @keyword +"extern" @keyword +"fn" @keyword +"for" @keyword +"gen" @keyword +"if" @keyword +"impl" @keyword +"in" @keyword +"let" @keyword +"loop" @keyword +"macro_rules!" @keyword +"match" @keyword +"mod" @keyword +"move" @keyword +"pub" @keyword +"raw" @keyword +"ref" @keyword +"return" @keyword +"static" @keyword +"struct" @keyword +"trait" @keyword +"type" @keyword +"union" @keyword +"unsafe" @keyword +"use" @keyword +"where" @keyword +"while" @keyword +"yield" @keyword +(crate) @keyword +(mutable_specifier) @keyword +(use_list (self) @keyword) +(scoped_use_list (self) @keyword) +(scoped_identifier (self) @keyword) +(super) @keyword + +(self) @variable.builtin + +(char_literal) @string +(string_literal) @string +(raw_string_literal) @string + +(boolean_literal) @constant.builtin +(integer_literal) @constant.builtin +(float_literal) @constant.builtin + +(escape_sequence) @escape + +(attribute_item) @attribute +(inner_attribute_item) @attribute + +"*" @operator +"&" @operator +"'" @operator From 8fb018500e26d41ac1d8bf19d46362a003b1f729 Mon Sep 17 00:00:00 2001 From: Billy Date: Sat, 7 Feb 2026 02:13:21 +0530 Subject: [PATCH 07/19] feat: highlight queries for kotlin --- .../editor/text/queries/kotlin/highlights.scm | 380 ++++++++++++++++++ 1 file changed, 380 insertions(+) create mode 100644 src/biscuit/editor/text/queries/kotlin/highlights.scm diff --git a/src/biscuit/editor/text/queries/kotlin/highlights.scm b/src/biscuit/editor/text/queries/kotlin/highlights.scm new file mode 100644 index 00000000..6f1c9687 --- /dev/null +++ b/src/biscuit/editor/text/queries/kotlin/highlights.scm @@ -0,0 +1,380 @@ +;; Based on the nvim-treesitter highlighting, which is under the Apache license. +;; See https://github.com/nvim-treesitter/nvim-treesitter/blob/f8ab59861eed4a1c168505e3433462ed800f2bae/queries/kotlin/highlights.scm +;; +;; The only difference in this file is that queries using #lua-match? +;; have been removed. + +;;; Identifiers + +(simple_identifier) @variable + +; `it` keyword inside lambdas +; FIXME: This will highlight the keyword outside of lambdas since tree-sitter +; does not allow us to check for arbitrary nestation +((simple_identifier) @variable.builtin +(#eq? @variable.builtin "it")) + +; `field` keyword inside property getter/setter +; FIXME: This will highlight the keyword outside of getters and setters +; since tree-sitter does not allow us to check for arbitrary nestation +((simple_identifier) @variable.builtin +(#eq? @variable.builtin "field")) + +; `this` this keyword inside classes +(this_expression) @variable.builtin + +; `super` keyword inside classes +(super_expression) @variable.builtin + +(class_parameter + (simple_identifier) @property) + +(class_body + (property_declaration + (variable_declaration + (simple_identifier) @property))) + +; id_1.id_2.id_3: `id_2` and `id_3` are assumed as object properties +(_ + (navigation_suffix + (simple_identifier) @property)) + +(enum_entry + (simple_identifier) @constant) + +(type_identifier) @type + +((type_identifier) @type.builtin + (#any-of? @type.builtin + "Byte" + "Short" + "Int" + "Long" + "UByte" + "UShort" + "UInt" + "ULong" + "Float" + "Double" + "Boolean" + "Char" + "String" + "Array" + "ByteArray" + "ShortArray" + "IntArray" + "LongArray" + "UByteArray" + "UShortArray" + "UIntArray" + "ULongArray" + "FloatArray" + "DoubleArray" + "BooleanArray" + "CharArray" + "Map" + "Set" + "List" + "EmptyMap" + "EmptySet" + "EmptyList" + "MutableMap" + "MutableSet" + "MutableList" +)) + +(package_header + . (identifier)) @namespace + +(import_header + "import" @include) + + +; TODO: Seperate labeled returns/breaks/continue/super/this +; Must be implemented in the parser first +(label) @label + +;;; Function definitions + +(function_declaration + . (simple_identifier) @function) + +(getter + ("get") @function.builtin) +(setter + ("set") @function.builtin) + +(primary_constructor) @constructor +(secondary_constructor + ("constructor") @constructor) + +(constructor_invocation + (user_type + (type_identifier) @constructor)) + +(anonymous_initializer + ("init") @constructor) + +(parameter + (simple_identifier) @parameter) + +(parameter_with_optional_type + (simple_identifier) @parameter) + +; lambda parameters +(lambda_literal + (lambda_parameters + (variable_declaration + (simple_identifier) @parameter))) + +;;; Function calls + +; function() +(call_expression + . (simple_identifier) @function) + +; object.function() or object.property.function() +(call_expression + (navigation_expression + (navigation_suffix + (simple_identifier) @function) . )) + +(call_expression + . (simple_identifier) @function.builtin + (#any-of? @function.builtin + "arrayOf" + "arrayOfNulls" + "byteArrayOf" + "shortArrayOf" + "intArrayOf" + "longArrayOf" + "ubyteArrayOf" + "ushortArrayOf" + "uintArrayOf" + "ulongArrayOf" + "floatArrayOf" + "doubleArrayOf" + "booleanArrayOf" + "charArrayOf" + "emptyArray" + "mapOf" + "setOf" + "listOf" + "emptyMap" + "emptySet" + "emptyList" + "mutableMapOf" + "mutableSetOf" + "mutableListOf" + "print" + "println" + "error" + "TODO" + "run" + "runCatching" + "repeat" + "lazy" + "lazyOf" + "enumValues" + "enumValueOf" + "assert" + "check" + "checkNotNull" + "require" + "requireNotNull" + "with" + "suspend" + "synchronized" +)) + +;;; Literals + +[ + (line_comment) + (multiline_comment) + (shebang_line) +] @comment + +(real_literal) @float +[ + (integer_literal) + (long_literal) + (hex_literal) + (bin_literal) + (unsigned_literal) +] @number + +[ + (null_literal) ; should be highlighted the same as booleans + (boolean_literal) +] @boolean + +(character_literal) @character + +(string_literal) @string + +(character_escape_seq) @string.escape + +; There are 3 ways to define a regex +; - "[abc]?".toRegex() +(call_expression + (navigation_expression + ((string_literal) @string.regex) + (navigation_suffix + ((simple_identifier) @_function + (#eq? @_function "toRegex"))))) + +; - Regex("[abc]?") +(call_expression + ((simple_identifier) @_function + (#eq? @_function "Regex")) + (call_suffix + (value_arguments + (value_argument + (string_literal) @string.regex)))) + +; - Regex.fromLiteral("[abc]?") +(call_expression + (navigation_expression + ((simple_identifier) @_class + (#eq? @_class "Regex")) + (navigation_suffix + ((simple_identifier) @_function + (#eq? @_function "fromLiteral")))) + (call_suffix + (value_arguments + (value_argument + (string_literal) @string.regex)))) + +;;; Keywords + +(type_alias "typealias" @keyword) +[ + (class_modifier) + (member_modifier) + (function_modifier) + (property_modifier) + (platform_modifier) + (variance_modifier) + (parameter_modifier) + (visibility_modifier) + (reification_modifier) + (inheritance_modifier) +]@keyword + +[ + "val" + "var" + "enum" + "class" + "object" + "interface" +; "typeof" ; NOTE: It is reserved for future use +] @keyword + +("fun") @keyword.function + +(jump_expression) @keyword.return + +[ + "if" + "else" + "when" +] @conditional + +[ + "for" + "do" + "while" +] @repeat + +[ + "try" + "catch" + "throw" + "finally" +] @exception + + +(annotation + "@" @attribute (use_site_target)? @attribute) +(annotation + (user_type + (type_identifier) @attribute)) +(annotation + (constructor_invocation + (user_type + (type_identifier) @attribute))) + +(file_annotation + "@" @attribute "file" @attribute ":" @attribute) +(file_annotation + (user_type + (type_identifier) @attribute)) +(file_annotation + (constructor_invocation + (user_type + (type_identifier) @attribute))) + +;;; Operators & Punctuation + +[ + "!" + "!=" + "!==" + "=" + "==" + "===" + ">" + ">=" + "<" + "<=" + "||" + "&&" + "+" + "++" + "+=" + "-" + "--" + "-=" + "*" + "*=" + "/" + "/=" + "%" + "%=" + "?." + "?:" + "!!" + "is" + "!is" + "in" + "!in" + "as" + "as?" + ".." + "->" +] @operator + +[ + "(" ")" + "[" "]" + "{" "}" +] @punctuation.bracket + +[ + "." + "," + ";" + ":" + "::" +] @punctuation.delimiter + +; NOTE: `interpolated_identifier`s can be highlighted in any way +(string_literal + "$" @punctuation.special + (interpolated_identifier) @none) +(string_literal + "${" @punctuation.special + (interpolated_expression) @none + "}" @punctuation.special) From 321bdd56472c3b745353c645883777c747c22ec9 Mon Sep 17 00:00:00 2001 From: Billy Date: Sat, 7 Feb 2026 02:13:28 +0530 Subject: [PATCH 08/19] feat: highlight queries for cpp --- .../editor/text/queries/cpp/highlights.scm | 160 ++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 src/biscuit/editor/text/queries/cpp/highlights.scm diff --git a/src/biscuit/editor/text/queries/cpp/highlights.scm b/src/biscuit/editor/text/queries/cpp/highlights.scm new file mode 100644 index 00000000..b4f27aa5 --- /dev/null +++ b/src/biscuit/editor/text/queries/cpp/highlights.scm @@ -0,0 +1,160 @@ +(identifier) @variable + +((identifier) @constant + (#match? @constant "^[A-Z][A-Z\\d_]*$")) + +"break" @keyword +"case" @keyword +"const" @keyword +"continue" @keyword +"default" @keyword +"do" @keyword +"else" @keyword +"enum" @keyword +"extern" @keyword +"for" @keyword +"if" @keyword +"inline" @keyword +"return" @keyword +"sizeof" @keyword +"static" @keyword +"struct" @keyword +"switch" @keyword +"typedef" @keyword +"union" @keyword +"volatile" @keyword +"while" @keyword + +"#define" @keyword +"#elif" @keyword +"#else" @keyword +"#endif" @keyword +"#if" @keyword +"#ifdef" @keyword +"#ifndef" @keyword +"#include" @keyword +(preproc_directive) @keyword + +"--" @operator +"-" @operator +"-=" @operator +"->" @operator +"=" @operator +"!=" @operator +"*" @operator +"&" @operator +"&&" @operator +"+" @operator +"++" @operator +"+=" @operator +"<" @operator +"==" @operator +">" @operator +"||" @operator + +"." @delimiter +";" @delimiter + +(string_literal) @string +(system_lib_string) @string + +(null) @constant +(number_literal) @number +(char_literal) @number + +(field_identifier) @property +(statement_identifier) @label +(type_identifier) @type +(primitive_type) @type +(sized_type_specifier) @type + +(call_expression + function: (identifier) @function) +(call_expression + function: (field_expression + field: (field_identifier) @function)) +(function_declarator + declarator: (identifier) @function) +(preproc_function_def + name: (identifier) @function.special) + +(comment) @comment + +; C++-specific +; Functions + +(call_expression + function: (qualified_identifier + name: (identifier) @function)) + +(template_function + name: (identifier) @function) + +(template_method + name: (field_identifier) @function) + +(template_function + name: (identifier) @function) + +(function_declarator + declarator: (qualified_identifier + name: (identifier) @function)) + +(function_declarator + declarator: (field_identifier) @function) + +; Types + +((namespace_identifier) @type + (#match? @type "^[A-Z]")) + +(auto) @type + +; Constants + +(this) @variable.builtin +(null "nullptr" @constant) + +; Modules +(module_name + (identifier) @module) + +; Keywords + +[ + "catch" + "class" + "co_await" + "co_return" + "co_yield" + "constexpr" + "constinit" + "consteval" + "delete" + "explicit" + "final" + "friend" + "mutable" + "namespace" + "noexcept" + "new" + "override" + "private" + "protected" + "public" + "template" + "throw" + "try" + "typename" + "using" + "concept" + "requires" + "virtual" + "import" + "export" + "module" +] @keyword + +; Strings + +(raw_string_literal) @string From 4372dd7e535d4583b1b3381acef93b6ea9f4b207 Mon Sep 17 00:00:00 2001 From: Billy Date: Sat, 7 Feb 2026 02:13:37 +0530 Subject: [PATCH 09/19] feat: highlight queries for c# --- .../editor/text/queries/csharp/highlights.scm | 212 ++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 src/biscuit/editor/text/queries/csharp/highlights.scm diff --git a/src/biscuit/editor/text/queries/csharp/highlights.scm b/src/biscuit/editor/text/queries/csharp/highlights.scm new file mode 100644 index 00000000..dbfc6190 --- /dev/null +++ b/src/biscuit/editor/text/queries/csharp/highlights.scm @@ -0,0 +1,212 @@ +(identifier) @variable + +;; Methods + +(method_declaration name: (identifier) @function) +(local_function_statement name: (identifier) @function) + +;; Types + +(interface_declaration name: (identifier) @type) +(class_declaration name: (identifier) @type) +(enum_declaration name: (identifier) @type) +(struct_declaration (identifier) @type) +(record_declaration (identifier) @type) +(namespace_declaration name: (identifier) @module) + +(generic_name (identifier) @type) +(type_parameter (identifier) @property.definition) +(parameter type: (identifier) @type) +(type_argument_list (identifier) @type) +(as_expression right: (identifier) @type) +(is_expression right: (identifier) @type) + +(constructor_declaration name: (identifier) @constructor) +(destructor_declaration name: (identifier) @constructor) + +(_ type: (identifier) @type) + +(base_list (identifier) @type) + +(predefined_type) @type.builtin + +;; Enum +(enum_member_declaration (identifier) @property.definition) + +;; Literals + +[ + (real_literal) + (integer_literal) +] @number + +[ + (character_literal) + (string_literal) + (raw_string_literal) + (verbatim_string_literal) + (interpolated_string_expression) + (interpolation_start) + (interpolation_quote) + ] @string + +(escape_sequence) @string.escape + +[ + (boolean_literal) + (null_literal) +] @constant.builtin + +;; Comments + +(comment) @comment + +;; Tokens + +[ + ";" + "." + "," +] @punctuation.delimiter + +[ + "--" + "-" + "-=" + "&" + "&=" + "&&" + "+" + "++" + "+=" + "<" + "<=" + "<<" + "<<=" + "=" + "==" + "!" + "!=" + "=>" + ">" + ">=" + ">>" + ">>=" + ">>>" + ">>>=" + "|" + "|=" + "||" + "?" + "??" + "??=" + "^" + "^=" + "~" + "*" + "*=" + "/" + "/=" + "%" + "%=" + ":" +] @operator + +[ + "(" + ")" + "[" + "]" + "{" + "}" + (interpolation_brace) +] @punctuation.bracket + +;; Keywords + +[ + (modifier) + "this" + (implicit_type) +] @keyword + +[ + "add" + "alias" + "as" + "base" + "break" + "case" + "catch" + "checked" + "class" + "continue" + "default" + "delegate" + "do" + "else" + "enum" + "event" + "explicit" + "extern" + "finally" + "for" + "foreach" + "global" + "goto" + "if" + "implicit" + "interface" + "is" + "lock" + "namespace" + "notnull" + "operator" + "params" + "return" + "remove" + "sizeof" + "stackalloc" + "static" + "struct" + "switch" + "throw" + "try" + "typeof" + "unchecked" + "using" + "while" + "new" + "await" + "in" + "yield" + "get" + "set" + "when" + "out" + "ref" + "from" + "where" + "select" + "record" + "init" + "with" + "let" +] @keyword + +;; Attribute + +(attribute name: (identifier) @attribute) + +;; Parameters + +(parameter + name: (identifier) @variable.parameter) + +;; Type constraints + +(type_parameter_constraints_clause (identifier) @property.definition) + +;; Method calls + +(invocation_expression (member_access_expression name: (identifier) @function)) From 58411f787dfc0e4c82e130a323b298f4a6d95215 Mon Sep 17 00:00:00 2001 From: Billy Date: Sat, 7 Feb 2026 02:13:44 +0530 Subject: [PATCH 10/19] feat: highlight queries for css --- .../editor/text/queries/css/highlights.scm | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 src/biscuit/editor/text/queries/css/highlights.scm diff --git a/src/biscuit/editor/text/queries/css/highlights.scm b/src/biscuit/editor/text/queries/css/highlights.scm new file mode 100644 index 00000000..40c65861 --- /dev/null +++ b/src/biscuit/editor/text/queries/css/highlights.scm @@ -0,0 +1,76 @@ +(comment) @comment + +(tag_name) @tag +(nesting_selector) @tag +(universal_selector) @tag + +"~" @operator +">" @operator +"+" @operator +"-" @operator +"*" @operator +"/" @operator +"=" @operator +"^=" @operator +"|=" @operator +"~=" @operator +"$=" @operator +"*=" @operator + +"and" @operator +"or" @operator +"not" @operator +"only" @operator + +(attribute_selector (plain_value) @string) + +((property_name) @variable + (#match? @variable "^--")) +((plain_value) @variable + (#match? @variable "^--")) + +(class_name) @property +(id_name) @property +(namespace_name) @property +(property_name) @property +(feature_name) @property + +(pseudo_element_selector (tag_name) @attribute) +(pseudo_class_selector (class_name) @attribute) +(attribute_name) @attribute + +(function_name) @function + +"@media" @keyword +"@import" @keyword +"@charset" @keyword +"@namespace" @keyword +"@supports" @keyword +"@keyframes" @keyword +(at_keyword) @keyword +(to) @keyword +(from) @keyword +(important) @keyword + +(string_value) @string +(color_value) @string.special + +(integer_value) @number +(float_value) @number +(unit) @type + +[ + "#" + "," + "." + ":" + "::" + ";" +] @punctuation.delimiter + +[ + "{" + ")" + "(" + "}" +] @punctuation.bracket From 369e7f300e469c31aa93d7c3101189aab3204563 Mon Sep 17 00:00:00 2001 From: Billy Date: Sat, 7 Feb 2026 02:13:54 +0530 Subject: [PATCH 11/19] feat: highlight queries for js/ts --- .../text/queries/javascript/highlights.scm | 204 +++++++++++++++ .../text/queries/typescript/highlights.scm | 241 ++++++++++++++++++ 2 files changed, 445 insertions(+) create mode 100644 src/biscuit/editor/text/queries/javascript/highlights.scm create mode 100644 src/biscuit/editor/text/queries/typescript/highlights.scm diff --git a/src/biscuit/editor/text/queries/javascript/highlights.scm b/src/biscuit/editor/text/queries/javascript/highlights.scm new file mode 100644 index 00000000..9312d682 --- /dev/null +++ b/src/biscuit/editor/text/queries/javascript/highlights.scm @@ -0,0 +1,204 @@ +; Variables +;---------- + +(identifier) @variable + +; Properties +;----------- + +(property_identifier) @property + +; Function and method definitions +;-------------------------------- + +(function_expression + name: (identifier) @function) +(function_declaration + name: (identifier) @function) +(method_definition + name: (property_identifier) @function.method) + +(pair + key: (property_identifier) @function.method + value: [(function_expression) (arrow_function)]) + +(assignment_expression + left: (member_expression + property: (property_identifier) @function.method) + right: [(function_expression) (arrow_function)]) + +(variable_declarator + name: (identifier) @function + value: [(function_expression) (arrow_function)]) + +(assignment_expression + left: (identifier) @function + right: [(function_expression) (arrow_function)]) + +; Function and method calls +;-------------------------- + +(call_expression + function: (identifier) @function) + +(call_expression + function: (member_expression + property: (property_identifier) @function.method)) + +; Special identifiers +;-------------------- + +((identifier) @constructor + (#match? @constructor "^[A-Z]")) + +([ + (identifier) + (shorthand_property_identifier) + (shorthand_property_identifier_pattern) + ] @constant + (#match? @constant "^[A-Z_][A-Z\\d_]+$")) + +((identifier) @variable.builtin + (#match? @variable.builtin "^(arguments|module|console|window|document)$") + (#is-not? local)) + +((identifier) @function.builtin + (#eq? @function.builtin "require") + (#is-not? local)) + +; Literals +;--------- + +(this) @variable.builtin +(super) @variable.builtin + +[ + (true) + (false) + (null) + (undefined) +] @constant.builtin + +(comment) @comment + +[ + (string) + (template_string) +] @string + +(regex) @string.special +(number) @number + +; Tokens +;------- + +[ + ";" + (optional_chain) + "." + "," +] @punctuation.delimiter + +[ + "-" + "--" + "-=" + "+" + "++" + "+=" + "*" + "*=" + "**" + "**=" + "/" + "/=" + "%" + "%=" + "<" + "<=" + "<<" + "<<=" + "=" + "==" + "===" + "!" + "!=" + "!==" + "=>" + ">" + ">=" + ">>" + ">>=" + ">>>" + ">>>=" + "~" + "^" + "&" + "|" + "^=" + "&=" + "|=" + "&&" + "||" + "??" + "&&=" + "||=" + "??=" +] @operator + +[ + "(" + ")" + "[" + "]" + "{" + "}" +] @punctuation.bracket + +(template_substitution + "${" @punctuation.special + "}" @punctuation.special) @embedded + +[ + "as" + "async" + "await" + "break" + "case" + "catch" + "class" + "const" + "continue" + "debugger" + "default" + "delete" + "do" + "else" + "export" + "extends" + "finally" + "for" + "from" + "function" + "get" + "if" + "import" + "in" + "instanceof" + "let" + "new" + "of" + "return" + "set" + "static" + "switch" + "target" + "throw" + "try" + "typeof" + "var" + "void" + "while" + "with" + "yield" +] @keyword diff --git a/src/biscuit/editor/text/queries/typescript/highlights.scm b/src/biscuit/editor/text/queries/typescript/highlights.scm new file mode 100644 index 00000000..979efe11 --- /dev/null +++ b/src/biscuit/editor/text/queries/typescript/highlights.scm @@ -0,0 +1,241 @@ +; Variables +;---------- + +(identifier) @variable + +; Properties +;----------- + +(property_identifier) @property + +; Function and method definitions +;-------------------------------- + +(function_expression + name: (identifier) @function) +(function_declaration + name: (identifier) @function) +(method_definition + name: (property_identifier) @function.method) + +(pair + key: (property_identifier) @function.method + value: [(function_expression) (arrow_function)]) + +(assignment_expression + left: (member_expression + property: (property_identifier) @function.method) + right: [(function_expression) (arrow_function)]) + +(variable_declarator + name: (identifier) @function + value: [(function_expression) (arrow_function)]) + +(assignment_expression + left: (identifier) @function + right: [(function_expression) (arrow_function)]) + +; Function and method calls +;-------------------------- + +(call_expression + function: (identifier) @function) + +(call_expression + function: (member_expression + property: (property_identifier) @function.method)) + +; Special identifiers +;-------------------- + +((identifier) @constructor + (#match? @constructor "^[A-Z]")) + +([ + (identifier) + (shorthand_property_identifier) + (shorthand_property_identifier_pattern) + ] @constant + (#match? @constant "^[A-Z_][A-Z\\d_]+$")) + +((identifier) @variable.builtin + (#match? @variable.builtin "^(arguments|module|console|window|document)$") + (#is-not? local)) + +((identifier) @function.builtin + (#eq? @function.builtin "require") + (#is-not? local)) + +; Literals +;--------- + +(this) @variable.builtin +(super) @variable.builtin + +[ + (true) + (false) + (null) + (undefined) +] @constant.builtin + +(comment) @comment + +[ + (string) + (template_string) +] @string + +(regex) @string.special +(number) @number + +; Tokens +;------- + +[ + ";" + (optional_chain) + "." + "," +] @punctuation.delimiter + +[ + "-" + "--" + "-=" + "+" + "++" + "+=" + "*" + "*=" + "**" + "**=" + "/" + "/=" + "%" + "%=" + "<" + "<=" + "<<" + "<<=" + "=" + "==" + "===" + "!" + "!=" + "!==" + "=>" + ">" + ">=" + ">>" + ">>=" + ">>>" + ">>>=" + "~" + "^" + "&" + "|" + "^=" + "&=" + "|=" + "&&" + "||" + "??" + "&&=" + "||=" + "??=" +] @operator + +[ + "(" + ")" + "[" + "]" + "{" + "}" +] @punctuation.bracket + +(template_substitution + "${" @punctuation.special + "}" @punctuation.special) @embedded + +[ + "as" + "async" + "await" + "break" + "case" + "catch" + "class" + "const" + "continue" + "debugger" + "default" + "delete" + "do" + "else" + "export" + "extends" + "finally" + "for" + "from" + "function" + "get" + "if" + "import" + "in" + "instanceof" + "let" + "new" + "of" + "return" + "set" + "static" + "switch" + "target" + "throw" + "try" + "typeof" + "var" + "void" + "while" + "with" + "yield" +] @keyword + +; TypeScript-specific +; Types + +(type_identifier) @type +(predefined_type) @type.builtin + +((identifier) @type + (#match? @type "^[A-Z]")) + +(type_arguments + "<" @punctuation.bracket + ">" @punctuation.bracket) + +; Variables + +(required_parameter (identifier) @variable.parameter) +(optional_parameter (identifier) @variable.parameter) + +; Keywords + +[ "abstract" + "declare" + "enum" + "export" + "implements" + "interface" + "keyof" + "namespace" + "private" + "protected" + "public" + "type" + "readonly" + "override" + "satisfies" +] @keyword From bb50124d8f82944aa6c65703d21bda4d994aaf48 Mon Sep 17 00:00:00 2001 From: Billy Date: Sat, 7 Feb 2026 02:14:10 +0530 Subject: [PATCH 12/19] feat: highlight queries for tsx/html --- .../editor/text/queries/html/highlights.scm | 13 + .../editor/text/queries/tsx/highlights.scm | 241 ++++++++++++++++++ 2 files changed, 254 insertions(+) create mode 100644 src/biscuit/editor/text/queries/html/highlights.scm create mode 100644 src/biscuit/editor/text/queries/tsx/highlights.scm diff --git a/src/biscuit/editor/text/queries/html/highlights.scm b/src/biscuit/editor/text/queries/html/highlights.scm new file mode 100644 index 00000000..ea0ff4e3 --- /dev/null +++ b/src/biscuit/editor/text/queries/html/highlights.scm @@ -0,0 +1,13 @@ +(tag_name) @tag +(erroneous_end_tag_name) @tag.error +(doctype) @constant +(attribute_name) @attribute +(attribute_value) @string +(comment) @comment + +[ + "<" + ">" + "" +] @punctuation.bracket diff --git a/src/biscuit/editor/text/queries/tsx/highlights.scm b/src/biscuit/editor/text/queries/tsx/highlights.scm new file mode 100644 index 00000000..979efe11 --- /dev/null +++ b/src/biscuit/editor/text/queries/tsx/highlights.scm @@ -0,0 +1,241 @@ +; Variables +;---------- + +(identifier) @variable + +; Properties +;----------- + +(property_identifier) @property + +; Function and method definitions +;-------------------------------- + +(function_expression + name: (identifier) @function) +(function_declaration + name: (identifier) @function) +(method_definition + name: (property_identifier) @function.method) + +(pair + key: (property_identifier) @function.method + value: [(function_expression) (arrow_function)]) + +(assignment_expression + left: (member_expression + property: (property_identifier) @function.method) + right: [(function_expression) (arrow_function)]) + +(variable_declarator + name: (identifier) @function + value: [(function_expression) (arrow_function)]) + +(assignment_expression + left: (identifier) @function + right: [(function_expression) (arrow_function)]) + +; Function and method calls +;-------------------------- + +(call_expression + function: (identifier) @function) + +(call_expression + function: (member_expression + property: (property_identifier) @function.method)) + +; Special identifiers +;-------------------- + +((identifier) @constructor + (#match? @constructor "^[A-Z]")) + +([ + (identifier) + (shorthand_property_identifier) + (shorthand_property_identifier_pattern) + ] @constant + (#match? @constant "^[A-Z_][A-Z\\d_]+$")) + +((identifier) @variable.builtin + (#match? @variable.builtin "^(arguments|module|console|window|document)$") + (#is-not? local)) + +((identifier) @function.builtin + (#eq? @function.builtin "require") + (#is-not? local)) + +; Literals +;--------- + +(this) @variable.builtin +(super) @variable.builtin + +[ + (true) + (false) + (null) + (undefined) +] @constant.builtin + +(comment) @comment + +[ + (string) + (template_string) +] @string + +(regex) @string.special +(number) @number + +; Tokens +;------- + +[ + ";" + (optional_chain) + "." + "," +] @punctuation.delimiter + +[ + "-" + "--" + "-=" + "+" + "++" + "+=" + "*" + "*=" + "**" + "**=" + "/" + "/=" + "%" + "%=" + "<" + "<=" + "<<" + "<<=" + "=" + "==" + "===" + "!" + "!=" + "!==" + "=>" + ">" + ">=" + ">>" + ">>=" + ">>>" + ">>>=" + "~" + "^" + "&" + "|" + "^=" + "&=" + "|=" + "&&" + "||" + "??" + "&&=" + "||=" + "??=" +] @operator + +[ + "(" + ")" + "[" + "]" + "{" + "}" +] @punctuation.bracket + +(template_substitution + "${" @punctuation.special + "}" @punctuation.special) @embedded + +[ + "as" + "async" + "await" + "break" + "case" + "catch" + "class" + "const" + "continue" + "debugger" + "default" + "delete" + "do" + "else" + "export" + "extends" + "finally" + "for" + "from" + "function" + "get" + "if" + "import" + "in" + "instanceof" + "let" + "new" + "of" + "return" + "set" + "static" + "switch" + "target" + "throw" + "try" + "typeof" + "var" + "void" + "while" + "with" + "yield" +] @keyword + +; TypeScript-specific +; Types + +(type_identifier) @type +(predefined_type) @type.builtin + +((identifier) @type + (#match? @type "^[A-Z]")) + +(type_arguments + "<" @punctuation.bracket + ">" @punctuation.bracket) + +; Variables + +(required_parameter (identifier) @variable.parameter) +(optional_parameter (identifier) @variable.parameter) + +; Keywords + +[ "abstract" + "declare" + "enum" + "export" + "implements" + "interface" + "keyof" + "namespace" + "private" + "protected" + "public" + "type" + "readonly" + "override" + "satisfies" +] @keyword From d4e92ad2ff2c5dec0c3aee340f6e0ebd07e27be5 Mon Sep 17 00:00:00 2001 From: Billy Date: Sat, 7 Feb 2026 02:14:35 +0530 Subject: [PATCH 13/19] feat: highlight queries for json/toml/yaml --- .../editor/text/queries/json/highlights.scm | 16 ++++ .../editor/text/queries/toml/highlights.scm | 33 ++++++++ .../editor/text/queries/yaml/highlights.scm | 79 +++++++++++++++++++ 3 files changed, 128 insertions(+) create mode 100644 src/biscuit/editor/text/queries/json/highlights.scm create mode 100644 src/biscuit/editor/text/queries/toml/highlights.scm create mode 100644 src/biscuit/editor/text/queries/yaml/highlights.scm diff --git a/src/biscuit/editor/text/queries/json/highlights.scm b/src/biscuit/editor/text/queries/json/highlights.scm new file mode 100644 index 00000000..ece8392f --- /dev/null +++ b/src/biscuit/editor/text/queries/json/highlights.scm @@ -0,0 +1,16 @@ +(pair + key: (_) @string.special.key) + +(string) @string + +(number) @number + +[ + (null) + (true) + (false) +] @constant.builtin + +(escape_sequence) @escape + +(comment) @comment diff --git a/src/biscuit/editor/text/queries/toml/highlights.scm b/src/biscuit/editor/text/queries/toml/highlights.scm new file mode 100644 index 00000000..e4d6966f --- /dev/null +++ b/src/biscuit/editor/text/queries/toml/highlights.scm @@ -0,0 +1,33 @@ +; Properties +;----------- + +(bare_key) @property +(quoted_key) @string + +; Literals +;--------- + +(boolean) @constant.builtin +(comment) @comment +(string) @string +(integer) @number +(float) @number +(offset_date_time) @string.special +(local_date_time) @string.special +(local_date) @string.special +(local_time) @string.special + +; Punctuation +;------------ + +"." @punctuation.delimiter +"," @punctuation.delimiter + +"=" @operator + +"[" @punctuation.bracket +"]" @punctuation.bracket +"[[" @punctuation.bracket +"]]" @punctuation.bracket +"{" @punctuation.bracket +"}" @punctuation.bracket diff --git a/src/biscuit/editor/text/queries/yaml/highlights.scm b/src/biscuit/editor/text/queries/yaml/highlights.scm new file mode 100644 index 00000000..cb9dcc62 --- /dev/null +++ b/src/biscuit/editor/text/queries/yaml/highlights.scm @@ -0,0 +1,79 @@ +(boolean_scalar) @boolean + +(null_scalar) @constant.builtin + +[ + (double_quote_scalar) + (single_quote_scalar) + (block_scalar) + (string_scalar) +] @string + +[ + (integer_scalar) + (float_scalar) +] @number + +(comment) @comment + +[ + (anchor_name) + (alias_name) +] @label + +(tag) @type + +[ + (yaml_directive) + (tag_directive) + (reserved_directive) +] @attribute + +(block_mapping_pair + key: (flow_node + [ + (double_quote_scalar) + (single_quote_scalar) + ] @property)) + +(block_mapping_pair + key: (flow_node + (plain_scalar + (string_scalar) @property))) + +(flow_mapping + (_ + key: (flow_node + [ + (double_quote_scalar) + (single_quote_scalar) + ] @property))) + +(flow_mapping + (_ + key: (flow_node + (plain_scalar + (string_scalar) @property)))) + +[ + "," + "-" + ":" + ">" + "?" + "|" +] @punctuation.delimiter + +[ + "[" + "]" + "{" + "}" +] @punctuation.bracket + +[ + "*" + "&" + "---" + "..." +] @punctuation.special From c851a1cbcff15197eca27600188655ee5f2f984f Mon Sep 17 00:00:00 2001 From: Billy Date: Sat, 7 Feb 2026 02:14:43 +0530 Subject: [PATCH 14/19] feat: highlight queries for go --- .../editor/text/queries/go/highlights.scm | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 src/biscuit/editor/text/queries/go/highlights.scm diff --git a/src/biscuit/editor/text/queries/go/highlights.scm b/src/biscuit/editor/text/queries/go/highlights.scm new file mode 100644 index 00000000..6a3c0ac8 --- /dev/null +++ b/src/biscuit/editor/text/queries/go/highlights.scm @@ -0,0 +1,123 @@ +; Function calls + +(call_expression + function: (identifier) @function) + +(call_expression + function: (identifier) @function.builtin + (#match? @function.builtin "^(append|cap|close|complex|copy|delete|imag|len|make|new|panic|print|println|real|recover)$")) + +(call_expression + function: (selector_expression + field: (field_identifier) @function.method)) + +; Function definitions + +(function_declaration + name: (identifier) @function) + +(method_declaration + name: (field_identifier) @function.method) + +; Identifiers + +(type_identifier) @type +(field_identifier) @property +(identifier) @variable + +; Operators + +[ + "--" + "-" + "-=" + ":=" + "!" + "!=" + "..." + "*" + "*" + "*=" + "/" + "/=" + "&" + "&&" + "&=" + "%" + "%=" + "^" + "^=" + "+" + "++" + "+=" + "<-" + "<" + "<<" + "<<=" + "<=" + "=" + "==" + ">" + ">=" + ">>" + ">>=" + "|" + "|=" + "||" + "~" +] @operator + +; Keywords + +[ + "break" + "case" + "chan" + "const" + "continue" + "default" + "defer" + "else" + "fallthrough" + "for" + "func" + "go" + "goto" + "if" + "import" + "interface" + "map" + "package" + "range" + "return" + "select" + "struct" + "switch" + "type" + "var" +] @keyword + +; Literals + +[ + (interpreted_string_literal) + (raw_string_literal) + (rune_literal) +] @string + +(escape_sequence) @escape + +[ + (int_literal) + (float_literal) + (imaginary_literal) +] @number + +[ + (true) + (false) + (nil) + (iota) +] @constant.builtin + +(comment) @comment From 5ae7cdf36425821e60920323547586ddc0631a56 Mon Sep 17 00:00:00 2001 From: Billy Date: Sat, 7 Feb 2026 02:15:05 +0530 Subject: [PATCH 15/19] feat: highlight queries for lua, bash --- .../editor/text/queries/bash/highlights.scm | 56 +++++++++++ .../editor/text/queries/lua/highlights.scm | 95 +++++++++++++++++++ 2 files changed, 151 insertions(+) create mode 100644 src/biscuit/editor/text/queries/bash/highlights.scm create mode 100644 src/biscuit/editor/text/queries/lua/highlights.scm diff --git a/src/biscuit/editor/text/queries/bash/highlights.scm b/src/biscuit/editor/text/queries/bash/highlights.scm new file mode 100644 index 00000000..f33a7c2d --- /dev/null +++ b/src/biscuit/editor/text/queries/bash/highlights.scm @@ -0,0 +1,56 @@ +[ + (string) + (raw_string) + (heredoc_body) + (heredoc_start) +] @string + +(command_name) @function + +(variable_name) @property + +[ + "case" + "do" + "done" + "elif" + "else" + "esac" + "export" + "fi" + "for" + "function" + "if" + "in" + "select" + "then" + "unset" + "until" + "while" +] @keyword + +(comment) @comment + +(function_definition name: (word) @function) + +(file_descriptor) @number + +[ + (command_substitution) + (process_substitution) + (expansion) +]@embedded + +[ + "$" + "&&" + ">" + ">>" + "<" + "|" +] @operator + +( + (command (_) @constant) + (#match? @constant "^-") +) diff --git a/src/biscuit/editor/text/queries/lua/highlights.scm b/src/biscuit/editor/text/queries/lua/highlights.scm new file mode 100644 index 00000000..398b4b1a --- /dev/null +++ b/src/biscuit/editor/text/queries/lua/highlights.scm @@ -0,0 +1,95 @@ +; Keywords +"return" @keyword.return + +[ + "goto" + "in" + "local" +] @keyword + +"function" @keyword.function + +[ + "if" + "elseif" + "else" + "then" +] @keyword.conditional + +[ + "for" + "while" + "repeat" + "until" + "do" +] @keyword.repeat + +"end" @keyword + +[ + "and" + "not" + "or" +] @keyword.operator + +(break_statement) @keyword + +(true) @boolean +(false) @boolean + +(nil) @constant.builtin + +; Comments +(comment) @comment + +; Strings +(string) @string + +; Numbers +(number) @number + +; Operators +[ + "+" + "-" + "*" + "/" + "%" + "^" + "#" + "==" + "~=" + "<=" + ">=" + "<" + ">" + "=" + ".." +] @operator + +; Punctuation +[ + ";" + ":" + "," + "." +] @punctuation.delimiter + +[ + "(" + ")" + "{" + "}" + "[" + "]" +] @punctuation.bracket + +; Functions +(function_declaration name: (identifier) @function) +(function_call name: (identifier) @function.call) + +; Variables / identifiers +(identifier) @variable + +; Parameters +(parameters (identifier) @variable.parameter) From a349dcfce5e28885b6c3b0dd5d318a430f583a0b Mon Sep 17 00:00:00 2001 From: Billy Date: Sat, 7 Feb 2026 02:15:12 +0530 Subject: [PATCH 16/19] feat: highlight queries for markdown --- .../text/queries/markdown/highlights.scm | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/biscuit/editor/text/queries/markdown/highlights.scm diff --git a/src/biscuit/editor/text/queries/markdown/highlights.scm b/src/biscuit/editor/text/queries/markdown/highlights.scm new file mode 100644 index 00000000..9f738442 --- /dev/null +++ b/src/biscuit/editor/text/queries/markdown/highlights.scm @@ -0,0 +1,19 @@ +; Headings +[ + (atx_heading) + (setext_heading) +] @keyword + +; Code blocks +(fenced_code_block) @string +(fenced_code_block_delimiter) @punctuation.delimiter +(info_string) @label + +; Lists +[ + (list_marker_plus) + (list_marker_minus) + (list_marker_star) + (list_marker_dot) + (list_marker_parenthesis) +] @punctuation.special From a11241e3fadbedcdaca67479b33bb34242efab96 Mon Sep 17 00:00:00 2001 From: Billy Date: Sat, 7 Feb 2026 02:15:31 +0530 Subject: [PATCH 17/19] feat: highlight queries for swift, scala, php, java --- .../editor/text/queries/java/highlights.scm | 149 ++++++++ .../editor/text/queries/php/highlights.scm | 203 +++++++++++ .../editor/text/queries/scala/highlights.scm | 260 ++++++++++++++ .../editor/text/queries/swift/highlights.scm | 336 ++++++++++++++++++ 4 files changed, 948 insertions(+) create mode 100644 src/biscuit/editor/text/queries/java/highlights.scm create mode 100644 src/biscuit/editor/text/queries/php/highlights.scm create mode 100644 src/biscuit/editor/text/queries/scala/highlights.scm create mode 100644 src/biscuit/editor/text/queries/swift/highlights.scm diff --git a/src/biscuit/editor/text/queries/java/highlights.scm b/src/biscuit/editor/text/queries/java/highlights.scm new file mode 100644 index 00000000..b13b4f46 --- /dev/null +++ b/src/biscuit/editor/text/queries/java/highlights.scm @@ -0,0 +1,149 @@ +; Variables + +(identifier) @variable + +; Methods + +(method_declaration + name: (identifier) @function.method) +(method_invocation + name: (identifier) @function.method) +(super) @function.builtin + +; Annotations + +(annotation + name: (identifier) @attribute) +(marker_annotation + name: (identifier) @attribute) + +"@" @operator + +; Types + +(type_identifier) @type + +(interface_declaration + name: (identifier) @type) +(class_declaration + name: (identifier) @type) +(enum_declaration + name: (identifier) @type) + +((field_access + object: (identifier) @type) + (#match? @type "^[A-Z]")) +((scoped_identifier + scope: (identifier) @type) + (#match? @type "^[A-Z]")) +((method_invocation + object: (identifier) @type) + (#match? @type "^[A-Z]")) +((method_reference + . (identifier) @type) + (#match? @type "^[A-Z]")) + +(constructor_declaration + name: (identifier) @type) + +[ + (boolean_type) + (integral_type) + (floating_point_type) + (floating_point_type) + (void_type) +] @type.builtin + +; Constants + +((identifier) @constant + (#match? @constant "^_*[A-Z][A-Z\\d_]+$")) + +; Builtins + +(this) @variable.builtin + +; Literals + +[ + (hex_integer_literal) + (decimal_integer_literal) + (octal_integer_literal) + (decimal_floating_point_literal) + (hex_floating_point_literal) +] @number + +[ + (character_literal) + (string_literal) +] @string +(escape_sequence) @string.escape + +[ + (true) + (false) + (null_literal) +] @constant.builtin + +[ + (line_comment) + (block_comment) +] @comment + +; Keywords + +[ + "abstract" + "assert" + "break" + "case" + "catch" + "class" + "continue" + "default" + "do" + "else" + "enum" + "exports" + "extends" + "final" + "finally" + "for" + "if" + "implements" + "import" + "instanceof" + "interface" + "module" + "native" + "new" + "non-sealed" + "open" + "opens" + "package" + "permits" + "private" + "protected" + "provides" + "public" + "requires" + "record" + "return" + "sealed" + "static" + "strictfp" + "switch" + "synchronized" + "throw" + "throws" + "to" + "transient" + "transitive" + "try" + "uses" + "volatile" + "when" + "while" + "with" + "yield" +] @keyword diff --git a/src/biscuit/editor/text/queries/php/highlights.scm b/src/biscuit/editor/text/queries/php/highlights.scm new file mode 100644 index 00000000..2bf40364 --- /dev/null +++ b/src/biscuit/editor/text/queries/php/highlights.scm @@ -0,0 +1,203 @@ +[ + (php_tag) + (php_end_tag) +] @tag + +; Keywords + +[ + "and" + "as" + "break" + "case" + "catch" + "class" + "clone" + "const" + "continue" + "declare" + "default" + "do" + "echo" + "else" + "elseif" + "enddeclare" + "endfor" + "endforeach" + "endif" + "endswitch" + "endwhile" + "enum" + "exit" + "extends" + "finally" + "fn" + "for" + "foreach" + "function" + "global" + "goto" + "if" + "implements" + "include" + "include_once" + "instanceof" + "insteadof" + "interface" + "match" + "namespace" + "new" + "or" + "print" + "require" + "require_once" + "return" + "switch" + "throw" + "trait" + "try" + "use" + "while" + "xor" + "yield" + "yield from" + (abstract_modifier) + (final_modifier) + (readonly_modifier) + (static_modifier) + (visibility_modifier) +] @keyword + +(function_static_declaration "static" @keyword) + +; Namespace + +(namespace_definition + name: (namespace_name + (name) @module)) + +(namespace_name + (name) @module) + +(namespace_use_clause + [ + (name) @type + (qualified_name + (name) @type) + alias: (name) @type + ]) + +(namespace_use_clause + type: "function" + [ + (name) @function + (qualified_name + (name) @function) + alias: (name) @function + ]) + +(namespace_use_clause + type: "const" + [ + (name) @constant + (qualified_name + (name) @constant) + alias: (name) @constant + ]) + +(relative_name "namespace" @module.builtin) + +; Variables + +(relative_scope) @variable.builtin + +(variable_name) @variable + +(method_declaration name: (name) @constructor + (#eq? @constructor "__construct")) + +(object_creation_expression [ + (name) @constructor + (qualified_name (name) @constructor) + (relative_name (name) @constructor) +]) + +((name) @constant + (#match? @constant "^_?[A-Z][A-Z\\d_]+$")) +((name) @constant.builtin + (#match? @constant.builtin "^__[A-Z][A-Z\d_]+__$")) +(const_declaration (const_element (name) @constant)) + +; Types + +(primitive_type) @type.builtin +(cast_type) @type.builtin +(named_type [ + (name) @type + (qualified_name (name) @type) + (relative_name (name) @type) +]) @type +(named_type (name) @type.builtin + (#any-of? @type.builtin "static" "self")) + +(scoped_call_expression + scope: [ + (name) @type + (qualified_name (name) @type) + (relative_name (name) @type) + ]) + +; Functions + +(array_creation_expression "array" @function.builtin) +(list_literal "list" @function.builtin) +(exit_statement "exit" @function.builtin "(") + +(method_declaration + name: (name) @function.method) + +(function_call_expression + function: [ + (qualified_name (name)) + (relative_name (name)) + (name) + ] @function) + +(scoped_call_expression + name: (name) @function) + +(member_call_expression + name: (name) @function.method) + +(function_definition + name: (name) @function) + +; Member + +(property_element + (variable_name) @property) + +(member_access_expression + name: (variable_name (name)) @property) +(member_access_expression + name: (name) @property) + +; Basic tokens +[ + (string) + (string_content) + (encapsed_string) + (heredoc) + (heredoc_body) + (nowdoc_body) +] @string +(boolean) @constant.builtin +(null) @constant.builtin +(integer) @number +(float) @number +(comment) @comment + +((name) @variable.builtin + (#eq? @variable.builtin "this")) + +"$" @operator diff --git a/src/biscuit/editor/text/queries/scala/highlights.scm b/src/biscuit/editor/text/queries/scala/highlights.scm new file mode 100644 index 00000000..61637b0e --- /dev/null +++ b/src/biscuit/editor/text/queries/scala/highlights.scm @@ -0,0 +1,260 @@ +; CREDITS @stumash (stuart.mashaal@gmail.com) + +(field_expression field: (identifier) @property) +(field_expression value: (identifier) @type + (#match? @type "^[A-Z]")) + +(type_identifier) @type + +(class_definition + name: (identifier) @type) + +(enum_definition + name: (identifier) @type) + +(object_definition + name: (identifier) @type) + +(trait_definition + name: (identifier) @type) + +(full_enum_case + name: (identifier) @type) + +(simple_enum_case + name: (identifier) @type) + +;; variables + +(class_parameter + name: (identifier) @parameter) + +(self_type (identifier) @parameter) + +(interpolation (identifier) @none) +(interpolation (block) @none) + +;; types + +(type_definition + name: (type_identifier) @type.definition) + +;; val/var definitions/declarations + +(val_definition + pattern: (identifier) @variable) + +(var_definition + pattern: (identifier) @variable) + +(val_declaration + name: (identifier) @variable) + +(var_declaration + name: (identifier) @variable) + +; imports/exports + +(import_declaration + path: (identifier) @namespace) +((stable_identifier (identifier) @namespace)) + +((import_declaration + path: (identifier) @type) (#match? @type "^[A-Z]")) +((stable_identifier (identifier) @type) (#match? @type "^[A-Z]")) + +(export_declaration + path: (identifier) @namespace) +((stable_identifier (identifier) @namespace)) + +((export_declaration + path: (identifier) @type) (#match? @type "^[A-Z]")) +((stable_identifier (identifier) @type) (#match? @type "^[A-Z]")) + +((namespace_selectors (identifier) @type) (#match? @type "^[A-Z]")) + +; method invocation + +(call_expression + function: (identifier) @function.call) + +(call_expression + function: (operator_identifier) @function.call) + +(call_expression + function: (field_expression + field: (identifier) @method.call)) + +((call_expression + function: (identifier) @constructor) + (#match? @constructor "^[A-Z]")) + +(generic_function + function: (identifier) @function.call) + +(interpolated_string_expression + interpolator: (identifier) @function.call) + +; function definitions + +(function_definition + name: (identifier) @function) + +(parameter + name: (identifier) @parameter) + +(binding + name: (identifier) @parameter) + +; method definition + +(function_declaration + name: (identifier) @method) + +(function_definition + name: (identifier) @method) + +; expressions + +(infix_expression operator: (identifier) @operator) +(infix_expression operator: (operator_identifier) @operator) +(infix_type operator: (operator_identifier) @operator) +(infix_type operator: (operator_identifier) @operator) + +; literals + +(boolean_literal) @boolean +(integer_literal) @number +(floating_point_literal) @float + +[ + (string) + (character_literal) + (interpolated_string_expression) +] @string + +(interpolation "$" @punctuation.special) + +;; keywords + +(opaque_modifier) @type.qualifier +(infix_modifier) @keyword +(transparent_modifier) @type.qualifier +(open_modifier) @type.qualifier + +[ + "case" + "class" + "enum" + "extends" + "derives" + "finally" +;; `forSome` existential types not implemented yet +;; `macro` not implemented yet + "object" + "override" + "package" + "trait" + "type" + "val" + "var" + "with" + "given" + "using" + "end" + "implicit" + "extension" + "with" +] @keyword + +[ + "abstract" + "final" + "lazy" + "sealed" + "private" + "protected" +] @type.qualifier + +(inline_modifier) @storageclass + +(null_literal) @constant.builtin + +(wildcard) @parameter + +(annotation) @attribute + +;; special keywords + +"new" @keyword.operator + +[ + "else" + "if" + "match" + "then" +] @conditional + +[ + "(" + ")" + "[" + "]" + "{" + "}" +] @punctuation.bracket + +[ + "." + "," +] @punctuation.delimiter + +[ + "do" + "for" + "while" + "yield" +] @repeat + +"def" @keyword.function + +[ + "=>" + "<-" + "@" +] @operator + +["import" "export"] @include + +[ + "try" + "catch" + "throw" +] @exception + +"return" @keyword.return + +(comment) @spell @comment +(block_comment) @spell @comment + +;; `case` is a conditional keyword in case_block + +(case_block + (case_clause ("case") @conditional)) +(indented_cases + (case_clause ("case") @conditional)) + +(operator_identifier) @operator + +((identifier) @type (#match? @type "^[A-Z]")) +((identifier) @variable.builtin + (#match? @variable.builtin "^this$")) + +( + (identifier) @function.builtin + (#match? @function.builtin "^super$") +) + +;; Scala CLI using directives +(using_directive_key) @parameter +(using_directive_value) @string diff --git a/src/biscuit/editor/text/queries/swift/highlights.scm b/src/biscuit/editor/text/queries/swift/highlights.scm new file mode 100644 index 00000000..82ad68d4 --- /dev/null +++ b/src/biscuit/editor/text/queries/swift/highlights.scm @@ -0,0 +1,336 @@ +[ + "." + ";" + ":" + "," +] @punctuation.delimiter + +[ + "(" + ")" + "[" + "]" + "{" + "}" +] @punctuation.bracket + +; Identifiers +(type_identifier) @type + +[ + (self_expression) + (super_expression) +] @variable.builtin + +; Declarations +[ + "func" + "deinit" +] @keyword.function + +[ + (visibility_modifier) + (member_modifier) + (function_modifier) + (property_modifier) + (parameter_modifier) + (inheritance_modifier) + (mutation_modifier) +] @keyword.modifier + +(simple_identifier) @variable + +(function_declaration + (simple_identifier) @function.method) + +(protocol_function_declaration + name: (simple_identifier) @function.method) + +(init_declaration + "init" @constructor) + +(parameter + external_name: (simple_identifier) @variable.parameter) + +(parameter + name: (simple_identifier) @variable.parameter) + +(type_parameter + (type_identifier) @variable.parameter) + +(inheritance_constraint + (identifier + (simple_identifier) @variable.parameter)) + +(equality_constraint + (identifier + (simple_identifier) @variable.parameter)) + +[ + "protocol" + "extension" + "indirect" + "nonisolated" + "override" + "convenience" + "required" + "some" + "any" + "weak" + "unowned" + "didSet" + "willSet" + "subscript" + "let" + "var" + (throws) + (where_keyword) + (getter_specifier) + (setter_specifier) + (modify_specifier) + (else) + (as_operator) +] @keyword + +[ + "enum" + "struct" + "class" + "typealias" +] @keyword.type + +[ + "async" + "await" +] @keyword.coroutine + +(shebang_line) @keyword.directive + +(class_body + (property_declaration + (pattern + (simple_identifier) @variable.member))) + +(protocol_property_declaration + (pattern + (simple_identifier) @variable.member)) + +(navigation_expression + (navigation_suffix + (simple_identifier) @variable.member)) + +(value_argument + name: (value_argument_label + (simple_identifier) @variable.member)) + +(import_declaration + "import" @keyword.import) + +(enum_entry + "case" @keyword) + +(modifiers + (attribute + "@" @attribute + (user_type + (type_identifier) @attribute))) + +; Function calls +(call_expression + (simple_identifier) @function.call) ; foo() + +(call_expression + ; foo.bar.baz(): highlight the baz() + (navigation_expression + (navigation_suffix + (simple_identifier) @function.call))) + +(call_expression + (prefix_expression + (simple_identifier) @function.call)) ; .foo() + +((navigation_expression + (simple_identifier) @type) ; SomeType.method(): highlight SomeType as a type + (#match? @type "^[A-Z]")) + +(directive) @keyword.directive + +; See https://docs.swift.org/swift-book/documentation/the-swift-programming-language/lexicalstructure/#Keywords-and-Punctuation +[ + (diagnostic) + (availability_condition) + (playground_literal) + (key_path_string_expression) + (selector_expression) + (external_macro_definition) +] @function.macro + +(special_literal) @constant.macro + +; Statements +(for_statement + "for" @keyword.repeat) + +(for_statement + "in" @keyword.repeat) + +[ + "while" + "repeat" + "continue" + "break" +] @keyword.repeat + +(guard_statement + "guard" @keyword.conditional) + +(if_statement + "if" @keyword.conditional) + +(switch_statement + "switch" @keyword.conditional) + +(switch_entry + "case" @keyword) + +(switch_entry + "fallthrough" @keyword) + +(switch_entry + (default_keyword) @keyword) + +"return" @keyword.return + +(ternary_expression + [ + "?" + ":" + ] @keyword.conditional.ternary) + +[ + (try_operator) + "do" + (throw_keyword) + (catch_keyword) +] @keyword.exception + +(statement_label) @label + +; Comments +[ + (comment) + (multiline_comment) +] @comment @spell + +((comment) @comment.documentation + (#match? @comment.documentation "^///[^/]")) + +((comment) @comment.documentation + (#match? @comment.documentation "^///$")) + +((multiline_comment) @comment.documentation + (#match? @comment.documentation "^/[*][*][^*].*[*]/$")) + +; String literals +(line_str_text) @string + +(str_escaped_char) @string.escape + +(multi_line_str_text) @string + +(raw_str_part) @string + +(raw_str_end_part) @string + +(line_string_literal + [ + "\\(" + ")" + ] @punctuation.special) + +(multi_line_string_literal + [ + "\\(" + ")" + ] @punctuation.special) + +(raw_str_interpolation + [ + (raw_str_interpolation_start) + ")" + ] @punctuation.special) + +[ + "\"" + "\"\"\"" +] @string + +; Lambda literals +(lambda_literal + "in" @keyword.operator) + +; Basic literals +[ + (integer_literal) + (hex_literal) + (oct_literal) + (bin_literal) +] @number + +(real_literal) @number.float + +(boolean_literal) @boolean + +"nil" @constant.builtin + +(wildcard_pattern) @character.special + +; Regex literals +(regex_literal) @string.regexp + +; Operators +(custom_operator) @operator + +[ + "+" + "-" + "*" + "/" + "%" + "=" + "+=" + "-=" + "*=" + "/=" + "<" + ">" + "<<" + ">>" + "<=" + ">=" + "++" + "--" + "^" + "&" + "&&" + "|" + "||" + "~" + "%=" + "!=" + "!==" + "==" + "===" + "?" + "??" + "->" + "..<" + "..." + (bang) +] @operator + +(type_arguments + [ + "<" + ">" + ] @punctuation.bracket) From cee74c92b5d560f2a7b7f0c05fd94c51c3821b05 Mon Sep 17 00:00:00 2001 From: Billy Date: Sat, 7 Feb 2026 02:15:40 +0530 Subject: [PATCH 18/19] feat: highlight queries for c, ruby --- .../editor/text/queries/c/highlights.scm | 81 +++++++++ .../editor/text/queries/ruby/highlights.scm | 154 ++++++++++++++++++ 2 files changed, 235 insertions(+) create mode 100644 src/biscuit/editor/text/queries/c/highlights.scm create mode 100644 src/biscuit/editor/text/queries/ruby/highlights.scm diff --git a/src/biscuit/editor/text/queries/c/highlights.scm b/src/biscuit/editor/text/queries/c/highlights.scm new file mode 100644 index 00000000..8ee11890 --- /dev/null +++ b/src/biscuit/editor/text/queries/c/highlights.scm @@ -0,0 +1,81 @@ +(identifier) @variable + +((identifier) @constant + (#match? @constant "^[A-Z][A-Z\\d_]*$")) + +"break" @keyword +"case" @keyword +"const" @keyword +"continue" @keyword +"default" @keyword +"do" @keyword +"else" @keyword +"enum" @keyword +"extern" @keyword +"for" @keyword +"if" @keyword +"inline" @keyword +"return" @keyword +"sizeof" @keyword +"static" @keyword +"struct" @keyword +"switch" @keyword +"typedef" @keyword +"union" @keyword +"volatile" @keyword +"while" @keyword + +"#define" @keyword +"#elif" @keyword +"#else" @keyword +"#endif" @keyword +"#if" @keyword +"#ifdef" @keyword +"#ifndef" @keyword +"#include" @keyword +(preproc_directive) @keyword + +"--" @operator +"-" @operator +"-=" @operator +"->" @operator +"=" @operator +"!=" @operator +"*" @operator +"&" @operator +"&&" @operator +"+" @operator +"++" @operator +"+=" @operator +"<" @operator +"==" @operator +">" @operator +"||" @operator + +"." @delimiter +";" @delimiter + +(string_literal) @string +(system_lib_string) @string + +(null) @constant +(number_literal) @number +(char_literal) @number + +(field_identifier) @property +(statement_identifier) @label +(type_identifier) @type +(primitive_type) @type +(sized_type_specifier) @type + +(call_expression + function: (identifier) @function) +(call_expression + function: (field_expression + field: (field_identifier) @function)) +(function_declarator + declarator: (identifier) @function) +(preproc_function_def + name: (identifier) @function.special) + +(comment) @comment diff --git a/src/biscuit/editor/text/queries/ruby/highlights.scm b/src/biscuit/editor/text/queries/ruby/highlights.scm new file mode 100644 index 00000000..dd1c9139 --- /dev/null +++ b/src/biscuit/editor/text/queries/ruby/highlights.scm @@ -0,0 +1,154 @@ +(identifier) @variable + +((identifier) @function.method + (#is-not? local)) + +[ + "alias" + "and" + "begin" + "break" + "case" + "class" + "def" + "do" + "else" + "elsif" + "end" + "ensure" + "for" + "if" + "in" + "module" + "next" + "or" + "rescue" + "retry" + "return" + "then" + "unless" + "until" + "when" + "while" + "yield" +] @keyword + +((identifier) @keyword + (#match? @keyword "^(private|protected|public)$")) + +(constant) @constructor + +; Function calls + +"defined?" @function.method.builtin + +(call + method: [(identifier) (constant)] @function.method) + +((identifier) @function.method.builtin + (#eq? @function.method.builtin "require")) + +; Function definitions + +(alias (identifier) @function.method) +(setter (identifier) @function.method) +(method name: [(identifier) (constant)] @function.method) +(singleton_method name: [(identifier) (constant)] @function.method) + +; Identifiers + +[ + (class_variable) + (instance_variable) +] @property + +((identifier) @constant.builtin + (#match? @constant.builtin "^__(FILE|LINE|ENCODING)__$")) + +(file) @constant.builtin +(line) @constant.builtin +(encoding) @constant.builtin + +(hash_splat_nil + "**" @operator) @constant.builtin + +((constant) @constant + (#match? @constant "^[A-Z\\d_]+$")) + +[ + (self) + (super) +] @variable.builtin + +(block_parameter (identifier) @variable.parameter) +(block_parameters (identifier) @variable.parameter) +(destructured_parameter (identifier) @variable.parameter) +(hash_splat_parameter (identifier) @variable.parameter) +(lambda_parameters (identifier) @variable.parameter) +(method_parameters (identifier) @variable.parameter) +(splat_parameter (identifier) @variable.parameter) + +(keyword_parameter name: (identifier) @variable.parameter) +(optional_parameter name: (identifier) @variable.parameter) + +; Literals + +[ + (string) + (bare_string) + (subshell) + (heredoc_body) + (heredoc_beginning) +] @string + +[ + (simple_symbol) + (delimited_symbol) + (hash_key_symbol) + (bare_symbol) +] @string.special.symbol + +(regex) @string.special.regex +(escape_sequence) @escape + +[ + (integer) + (float) +] @number + +[ + (nil) + (true) + (false) +] @constant.builtin + +(interpolation + "#{" @punctuation.special + "}" @punctuation.special) @embedded + +(comment) @comment + +; Operators + +[ +"=" +"=>" +"->" +] @operator + +[ + "," + ";" + "." +] @punctuation.delimiter + +[ + "(" + ")" + "[" + "]" + "{" + "}" + "%w(" + "%i(" +] @punctuation.bracket From fdc14907e83700ddd3b8afeecebf545ff679c4d5 Mon Sep 17 00:00:00 2001 From: Billy Date: Sat, 7 Feb 2026 02:15:48 +0530 Subject: [PATCH 19/19] feat: highlight queries for zig, sql --- .../editor/text/queries/sql/highlights.scm | 82 ++++++++++++ .../editor/text/queries/zig/highlights.scm | 118 ++++++++++++++++++ 2 files changed, 200 insertions(+) create mode 100644 src/biscuit/editor/text/queries/sql/highlights.scm create mode 100644 src/biscuit/editor/text/queries/zig/highlights.scm diff --git a/src/biscuit/editor/text/queries/sql/highlights.scm b/src/biscuit/editor/text/queries/sql/highlights.scm new file mode 100644 index 00000000..f8ba4089 --- /dev/null +++ b/src/biscuit/editor/text/queries/sql/highlights.scm @@ -0,0 +1,82 @@ +; Keywords +[ + (keyword_select) + (keyword_from) + (keyword_where) + (keyword_and) + (keyword_as) + (keyword_asc) + (keyword_by) + (keyword_case) + (keyword_create) + (keyword_default) + (keyword_delete) + (keyword_distinct) + (keyword_else) + (keyword_end) + (keyword_group) + (keyword_having) + (keyword_insert) + (keyword_into) + (keyword_join) + (keyword_key) + (keyword_left) + (keyword_like) + (keyword_limit) + (keyword_on) + (keyword_order) + (keyword_primary) + (keyword_set) + (keyword_table) + (keyword_then) + (keyword_update) + (keyword_values) + (keyword_when) +] @keyword + +; Data types +[ + (keyword_int) + (keyword_varchar) + (keyword_boolean) +] @type + +; Literals +(literal) @string + +; Identifiers +(identifier) @variable +(field (identifier) @property) + +; Functions +(invocation (object_reference (identifier) @function.call)) + +; Operators +[ + "=" + "<>" + "<" + ">" + "<=" + ">=" + "+" + "-" + "*" + "/" +] @operator + +; Punctuation +[ + ";" + "," + "." +] @punctuation.delimiter + +[ + "(" + ")" +] @punctuation.bracket + +; Comments +(comment) @comment +(marginalia) @comment diff --git a/src/biscuit/editor/text/queries/zig/highlights.scm b/src/biscuit/editor/text/queries/zig/highlights.scm new file mode 100644 index 00000000..d08b6566 --- /dev/null +++ b/src/biscuit/editor/text/queries/zig/highlights.scm @@ -0,0 +1,118 @@ +; Keywords +[ + "const" + "var" + "pub" + "extern" + "export" + "comptime" + "inline" + "noinline" + "threadlocal" + "allowzero" + "volatile" + "linksection" + "addrspace" + "align" + "packed" +] @keyword + +"fn" @keyword.function + +"return" @keyword.return + +[ + "if" + "else" + "switch" +] @keyword.conditional + +[ + "while" + "for" +] @keyword.repeat + +[ + "try" + "catch" + "error" +] @keyword.exception + +[ + "struct" + "enum" + "union" + "opaque" +] @keyword.type + +[ + "and" + "or" + "orelse" +] @keyword.operator + +[ + "true" + "false" +] @boolean + +"null" @constant.builtin +"undefined" @constant.builtin +"unreachable" @constant.builtin + +; Types (PascalCase identifiers) +(BuildinTypeExpr) @type.builtin + +; Functions +(FnProto (IDENTIFIER) @function) + +; Builtins +(BUILTINIDENTIFIER) @function.builtin + +; Strings +(STRINGLITERALSINGLE) @string + +; Numbers +(INTEGER) @number + +; Identifiers +(IDENTIFIER) @variable + +; Operators +[ + "+" + "-" + "*" + "/" + "%" + "=" + "==" + "!=" + "<" + ">" + "<=" + ">=" + "!" + "++" + "<<" + ">>" + "." +] @operator + +; Punctuation +[ + ";" + ":" + "," +] @punctuation.delimiter + +[ + "(" + ")" + "{" + "}" + "[" + "]" +] @punctuation.bracket + +"@" @punctuation.special