Skip to content

Commit 3ab034e

Browse files
Merge pull request #279 from unhappychoice/feature/add-zig-language-support
feat: Add Zig language support
2 parents 65895b6 + 3009e8b commit 3ab034e

24 files changed

+513
-33
lines changed

Cargo.lock

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ tree-sitter-cpp = "0.23"
4646
tree-sitter-haskell = "0.23"
4747
tree-sitter-dart = "0.0.4"
4848
tree-sitter-scala = "0.24"
49+
tree-sitter-zig = "1.0"
4950
crossterm = "0.29"
5051
ratatui = "0.29"
5152
rusqlite = { version = "0.37", features = ["bundled"] }

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
## Features ✨
1414

15-
- 🦀🐍⚡🐹💎🍎🎯☕🐘#️⃣🔧➕🎭🎯 **Multi-language**: Rust, TypeScript, JavaScript, Python, Go, Ruby, Swift, Kotlin, Java, PHP, C#, C, C++, Haskell, Dart, Scala (more languages incoming!)
15+
- 🦀🐍⚡🐹💎🍎🎯☕🐘#️⃣🔧➕🎭🎯 **Multi-language**: Rust, TypeScript, JavaScript, Python, Go, Ruby, Swift, Kotlin, Java, PHP, C#, C, C++, Haskell, Dart, Scala, Zig (more languages incoming!)
1616
- 📊 **Real-time metrics**: Live WPM, accuracy, and consistency tracking as you type
1717
- 🏆 **Ranking system**: Unlock developer titles from "Hello World Newbie" to "Quantum Computer" with ASCII art
1818
- 🎮 **Multiple game modes**: Normal, Time Attack, and custom difficulty levels (Easy to Zen)

assets/languages/lang_ascii.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,6 @@
1515
"lang_scala": "red",
1616
"lang_haskell": "magenta",
1717
"lang_dart": "cyan",
18+
"lang_zig": "yellow",
1819
"lang_default": "white"
1920
}

assets/languages/lang_dark.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,6 @@
1515
"lang_scala": {"r": 220, "g": 50, "b": 47},
1616
"lang_haskell": {"r": 94, "g": 80, "b": 134},
1717
"lang_dart": {"r": 0, "g": 180, "b": 240},
18+
"lang_zig": {"r": 249, "g": 169, "b": 60},
1819
"lang_default": {"r": 255, "g": 255, "b": 255}
1920
}

assets/languages/lang_light.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,6 @@
1515
"lang_scala": {"r": 220, "g": 50, "b": 47},
1616
"lang_haskell": {"r": 94, "g": 80, "b": 134},
1717
"lang_dart": {"r": 0, "g": 120, "b": 180},
18+
"lang_zig": {"r": 189, "g": 99, "b": 0},
1819
"lang_default": {"r": 64, "g": 64, "b": 64}
1920
}

docs/CONTRIBUTING.md

Lines changed: 133 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -293,45 +293,152 @@ pub fn extract_chunks(
293293
tree-sitter-newlang = "0.20"
294294
```
295295

296-
2. **Create language-specific extractor:**
296+
2. **Create language definition:**
297297
```rust
298-
// src/extractor/languages/newlang.rs
299-
use tree_sitter::Language;
300-
301-
extern "C" {
302-
fn tree_sitter_newlang() -> Language;
298+
// src/domain/models/languages/newlang.rs
299+
use crate::domain::models::Language;
300+
use crate::presentation::ui::Colors;
301+
use std::hash::Hash;
302+
303+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
304+
pub struct NewLang;
305+
306+
impl Language for NewLang {
307+
fn name(&self) -> &'static str {
308+
"newlang"
309+
}
310+
fn extensions(&self) -> Vec<&'static str> {
311+
vec!["nl"]
312+
}
313+
fn color(&self) -> ratatui::style::Color {
314+
Colors::lang_newlang()
315+
}
316+
fn display_name(&self) -> &'static str {
317+
"NewLang"
318+
}
319+
fn is_valid_comment_node(&self, node: tree_sitter::Node) -> bool {
320+
node.kind() == "comment"
321+
}
303322
}
304-
305-
pub fn language() -> Language {
306-
unsafe { tree_sitter_newlang() }
323+
```
324+
325+
3. **Create language-specific extractor:**
326+
```rust
327+
// src/domain/services/source_code_parser/parsers/newlang.rs
328+
use super::LanguageExtractor;
329+
use crate::domain::models::ChunkType;
330+
use crate::{GitTypeError, Result};
331+
use tree_sitter::{Node, Parser};
332+
333+
pub struct NewLangExtractor;
334+
335+
impl LanguageExtractor for NewLangExtractor {
336+
fn tree_sitter_language(&self) -> tree_sitter::Language {
337+
tree_sitter_newlang::LANGUAGE.into()
338+
}
339+
340+
fn query_patterns(&self) -> &str {
341+
"(function_declaration name: (identifier) @name) @function"
342+
}
343+
344+
fn comment_query(&self) -> &str {
345+
"(comment) @comment"
346+
}
347+
348+
fn capture_name_to_chunk_type(&self, capture_name: &str) -> Option<ChunkType> {
349+
match capture_name {
350+
"function" => Some(ChunkType::Function),
351+
_ => None,
352+
}
353+
}
354+
355+
fn extract_name(&self, node: Node, source_code: &str, _capture_name: &str) -> Option<String> {
356+
// Extract identifier name from AST node
357+
None
358+
}
359+
360+
fn middle_implementation_query(&self) -> &str {
361+
"" // Optional: for extracting code blocks within functions
362+
}
363+
364+
fn middle_capture_name_to_chunk_type(&self, _capture_name: &str) -> Option<ChunkType> {
365+
None
366+
}
367+
}
368+
369+
impl NewLangExtractor {
370+
pub fn create_parser() -> Result<Parser> {
371+
let mut parser = Parser::new();
372+
parser.set_language(&tree_sitter_newlang::LANGUAGE.into())
373+
.map_err(|e| GitTypeError::ExtractionFailed(format!("Failed to set NewLang language: {}", e)))?;
374+
Ok(parser)
375+
}
307376
}
308-
309-
pub const QUERY: &str = r#"
310-
(function_definition
311-
name: (identifier) @function.name) @function.definition
312-
"#;
313377
```
314378

315-
3. **Update the main extractor:**
379+
4. **Register the language:**
316380
```rust
317-
// src/extractor/mod.rs
318-
match language {
319-
Language::NewLang => languages::newlang::create_extractor(),
320-
// ... other languages
381+
// In src/domain/models/languages/mod.rs
382+
pub mod newlang;
383+
pub use newlang::NewLang;
384+
385+
// In src/domain/models/language.rs
386+
pub fn all_languages() -> Vec<Box<dyn Language>> {
387+
vec![
388+
// ... other languages
389+
Box::new(NewLang),
390+
]
321391
}
392+
393+
// In src/domain/services/source_code_parser/parsers/mod.rs
394+
pub mod newlang;
395+
register_language!(NewLang, newlang, NewLangExtractor);
396+
```
397+
398+
5. **Add color scheme support:**
399+
```rust
400+
// In src/domain/models/color_scheme.rs - add field:
401+
pub lang_newlang: SerializableColor,
402+
403+
// In src/presentation/ui/colors.rs - add method:
404+
pub fn lang_newlang() -> Color {
405+
Self::get_color_scheme().lang_newlang.into()
406+
}
407+
408+
// Add to theme JSON files:
409+
// assets/languages/lang_dark.json
410+
// assets/languages/lang_light.json
411+
// assets/languages/lang_ascii.json
412+
"lang_newlang": {"r": 123, "g": 45, "b": 67}
322413
```
323414

324-
4. **Add tests:**
415+
6. **Add tests:**
325416
```rust
326-
#[test]
327-
fn test_newlang_extraction() {
328-
// Test with sample code
417+
// tests/integration/languages/newlang/extractor.rs
418+
use crate::integration::languages::extractor::test_language_extractor;
419+
420+
test_language_extractor! {
421+
name: test_newlang_function_extraction,
422+
language: "newlang",
423+
extension: "nl",
424+
source: r#"
425+
function hello() {
426+
print("Hello")
427+
}
428+
"#,
429+
total_chunks: 2,
430+
chunk_counts: {
431+
File: 1,
432+
Function: 1,
433+
}
329434
}
330435
```
331436

332-
5. **Update documentation:**
333-
- Add to supported languages list in README.md
334-
- Include examples if needed
437+
7. **Update documentation:**
438+
- Add to `README.md` supported languages list
439+
- Add to `docs/supported-languages.md` with extraction features
440+
- Update CLI help in `src/presentation/cli/args.rs`
441+
- Add example code if needed
335442

336443
### Query Writing Guidelines
337444

docs/supported-languages.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
| Scala | `.sc`, `.scala` | `sc` | `tree_sitter_scala` |
2121
| Swift | `.swift` | - | `tree_sitter_swift` |
2222
| TypeScript | `.ts`, `.tsx` | `ts` | `tree_sitter_typescript` (TSX) |
23+
| Zig | `.zig` | - | `tree_sitter_zig` |
2324

2425
## Extraction Features
2526

@@ -157,6 +158,12 @@
157158
- **Namespaces** (`internal_module`) - Namespace declarations
158159
- **JSX Elements** (`jsx_element`, `jsx_self_closing_element`) - React components
159160

161+
### Zig
162+
- **Functions** (`function_declaration`) - Function definitions
163+
- **Structs** (`variable_declaration` with `struct_declaration`) - Struct type definitions
164+
- **Enums** (`variable_declaration` with `enum_declaration`) - Enum type definitions
165+
- **Unions** (`variable_declaration` with `union_declaration`) - Union type definitions
166+
160167
## Language-Specific Options
161168

162169
### Filtering by Language
@@ -173,7 +180,7 @@ gittype --langs rust,typescript,javascript,python
173180

174181
```toml
175182
[default]
176-
langs = ["rust", "typescript", "javascript", "python", "go", "ruby", "swift", "kotlin", "java", "php", "csharp", "c", "cpp", "haskell", "dart", "scala"]
183+
langs = ["rust", "typescript", "javascript", "python", "go", "ruby", "swift", "kotlin", "java", "php", "csharp", "c", "cpp", "haskell", "dart", "scala", "zig"]
177184
```
178185

179186
## Code Extraction Quality

docs/usage.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ Discover and practice typing with trending GitHub repositories. Repositories are
121121
| `--period` | Time period for trending (daily, weekly, monthly) | `daily` |
122122

123123
#### Supported Languages:
124-
- C, C#, C++, Dart, Go, Haskell, Java, JavaScript, Kotlin, PHP, Python, Ruby, Rust, Scala, Swift, TypeScript
124+
- C, C#, C++, Dart, Go, Haskell, Java, JavaScript, Kotlin, PHP, Python, Ruby, Rust, Scala, Swift, TypeScript, Zig
125125

126126
#### Examples:
127127
```bash

src/domain/models/color_scheme.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ pub struct ColorScheme {
146146
pub lang_scala: SerializableColor,
147147
pub lang_haskell: SerializableColor,
148148
pub lang_dart: SerializableColor,
149+
pub lang_zig: SerializableColor,
149150
pub lang_default: SerializableColor,
150151
}
151152

@@ -320,6 +321,10 @@ impl ColorScheme {
320321
.get("lang_dart")
321322
.cloned()
322323
.unwrap_or(SerializableColor::Name("blue".to_string())),
324+
lang_zig: lang_colors
325+
.get("lang_zig")
326+
.cloned()
327+
.unwrap_or(SerializableColor::Name("yellow".to_string())),
323328
lang_default: lang_colors
324329
.get("lang_default")
325330
.cloned()

0 commit comments

Comments
 (0)