From 44a0f32aede8f1d0ad15cce8d203ac67872adb50 Mon Sep 17 00:00:00 2001 From: Mike Bannister Date: Mon, 16 Mar 2026 18:25:01 -0400 Subject: [PATCH] feat: add Bash tree-sitter language support --- .../docs/core-concepts/plugin-system.mdx | 1 + src/kit/queries/bash/tags.scm | 5 ++ src/kit/tree_sitter_symbol_extractor.py | 4 ++ tests/test_bash_symbols.py | 57 +++++++++++++++++++ tests/test_symbol_extraction_multilang.py | 1 + tests/test_tree_sitter_languages.py | 1 + 6 files changed, 69 insertions(+) create mode 100644 src/kit/queries/bash/tags.scm create mode 100644 tests/test_bash_symbols.py diff --git a/docs/src/content/docs/core-concepts/plugin-system.mdx b/docs/src/content/docs/core-concepts/plugin-system.mdx index 1d497da9..6b90ffa5 100644 --- a/docs/src/content/docs/core-concepts/plugin-system.mdx +++ b/docs/src/content/docs/core-concepts/plugin-system.mdx @@ -24,6 +24,7 @@ kit comes with built-in support for 12+ programming languages: - **Dart** (`.dart`) - Classes, functions, mixins, enums, extensions - **HCL/Terraform** (`.hcl`, `.tf`) - Resources, variables, modules - **Haskell** (`.hs`) - Module header, functions (including lambda-binds), common type-level declarations +- **Bash** (`.sh`, `.bash`) - Function definitions Each language supports comprehensive symbol extraction including: - **Classes and interfaces** with inheritance relationships diff --git a/src/kit/queries/bash/tags.scm b/src/kit/queries/bash/tags.scm new file mode 100644 index 00000000..702962aa --- /dev/null +++ b/src/kit/queries/bash/tags.scm @@ -0,0 +1,5 @@ +;; tags.scm for Bash symbol extraction (tree-sitter-bash) + +; Function definitions (covers both "function name()" and "name()" syntax) +(function_definition + name: (word) @name) @definition.function diff --git a/src/kit/tree_sitter_symbol_extractor.py b/src/kit/tree_sitter_symbol_extractor.py index 273346f5..6e790d2f 100644 --- a/src/kit/tree_sitter_symbol_extractor.py +++ b/src/kit/tree_sitter_symbol_extractor.py @@ -34,6 +34,8 @@ ".hxx": "cpp", ".zig": "zig", ".cs": "csharp", + ".sh": "bash", + ".bash": "bash", } @@ -350,6 +352,8 @@ def reset_plugins(cls) -> None: ".hxx": "cpp", ".zig": "zig", ".cs": "csharp", + ".sh": "bash", + ".bash": "bash", } LANGUAGES.clear() LANGUAGES.update(original_languages) diff --git a/tests/test_bash_symbols.py b/tests/test_bash_symbols.py new file mode 100644 index 00000000..5cdf4804 --- /dev/null +++ b/tests/test_bash_symbols.py @@ -0,0 +1,57 @@ +import pytest + +from kit.tree_sitter_symbol_extractor import TreeSitterSymbolExtractor + +BASH_SAMPLE = """\ +function greet() { + echo "Hello, $1!" +} + +say_hi() { + echo "Hi there" +} +""" + + +def test_bash_parser_and_query_available(): + parser = TreeSitterSymbolExtractor.get_parser(".sh") + query = TreeSitterSymbolExtractor.get_query(".sh") + if not parser or not query: + pytest.skip("Bash parser or query not available in this environment") + + tree = parser.parse(BASH_SAMPLE.encode("utf-8")) + assert tree.root_node is not None + + +def test_bash_symbols(): + parser = TreeSitterSymbolExtractor.get_parser(".sh") + query = TreeSitterSymbolExtractor.get_query(".sh") + if not parser or not query: + pytest.skip("Bash parser or query not available in this environment") + + symbols = TreeSitterSymbolExtractor.extract_symbols(".sh", BASH_SAMPLE) + names = {s["name"] for s in symbols} + + assert "greet" in names + assert "say_hi" in names + assert all(s["type"] == "function" for s in symbols) + + +def test_bash_extensions(): + supported = TreeSitterSymbolExtractor.list_supported_languages() + assert "bash" in supported + assert ".sh" in supported["bash"] + assert ".bash" in supported["bash"] + + +def test_bash_extension_extracts_symbols(): + parser = TreeSitterSymbolExtractor.get_parser(".bash") + query = TreeSitterSymbolExtractor.get_query(".bash") + if not parser or not query: + pytest.skip("Bash parser or query not available in this environment") + + symbols = TreeSitterSymbolExtractor.extract_symbols(".bash", BASH_SAMPLE) + names = {s["name"] for s in symbols} + + assert "greet" in names + assert "say_hi" in names diff --git a/tests/test_symbol_extraction_multilang.py b/tests/test_symbol_extraction_multilang.py index 77767289..fd42129c 100644 --- a/tests/test_symbol_extraction_multilang.py +++ b/tests/test_symbol_extraction_multilang.py @@ -9,6 +9,7 @@ ".java": "class Bar { void foo() {} }\n", ".rs": "fn foo() {}\nstruct Bar;\n", ".zig": "pub fn foo() void {}\npub const Bar = struct {};\n", + ".sh": "function foo() { echo hello; }\n", } diff --git a/tests/test_tree_sitter_languages.py b/tests/test_tree_sitter_languages.py index f08160a9..92eb8530 100644 --- a/tests/test_tree_sitter_languages.py +++ b/tests/test_tree_sitter_languages.py @@ -12,6 +12,7 @@ "c": b"int foo() { return 42; }\n", "dart": b"int foo() { return 42; }\n", "zig": b"pub fn foo() void { }\n", + "bash": b"function foo() { echo hello; }\n", }