12 KiB
Contributing to GitType
Thank you for your interest in contributing to GitType! This document provides guidelines and information for contributors.
Table of Contents
- Code of Conduct
- Getting Started
- Development Setup
- Project Structure
- Making Changes
- Testing
- Submitting Changes
- Coding Standards
- Adding Language Support
Code of Conduct
This project follows a standard code of conduct. Please be respectful and constructive in all interactions.
Getting Started
Prerequisites
- Rust 1.70 or later
- Git
- Basic familiarity with Rust and CLI development
When developing in a Nix environment:
nix developwill create a development shell with all dependencies.
Development Setup
-
Fork and clone the repository:
git clone https://github.com/YOUR_USERNAME/gittype.git cd gittype -
Set up the development environment:
# Install dependencies and build cargo build # Run tests to ensure everything works cargo test # Try running the application cargo run -- --help -
Create a development branch:
git checkout -b feature/your-feature-name
Project Structure
gittype/
├── src/
│ ├── main.rs # CLI entry point
│ ├── lib.rs # Library root
│ ├── extractor/ # Code extraction logic
│ │ ├── mod.rs # Main extractor interface
│ │ ├── repository.rs # Repository loading
│ │ └── languages/ # Language-specific parsers
│ ├── game/ # Game logic and UI
│ │ ├── mod.rs # Game orchestration
│ │ ├── stage_manager.rs # Stage management
│ │ ├── scoring/ # Scoring system
│ │ └── screens/ # UI screens
│ └── database/ # Session storage
├── tests/ # Integration tests
├── Cargo.toml # Project configuration
└── README.md # Project documentation
Key Components
- Extractor: Handles parsing source code using tree-sitter
- Game: Manages typing challenges and user interface
- Database: Stores session history and statistics
- Scoring: Calculates accuracy, speed, and other metrics
Making Changes
Types of Contributions
- Bug Fixes: Fix issues in existing functionality
- Features: Add new functionality or improve existing features
- Performance: Optimize code performance
- Documentation: Improve or add documentation
- Language Support: Add support for new programming languages
Before You Start
- Check existing issues and PRs to avoid duplication
- For major features, consider opening an issue first to discuss
- Ensure your changes align with the project goals
Testing
Running Tests
# Run all tests
cargo test
# Run with output
cargo test -- --nocapture
# Run specific test
cargo test test_name
# Run integration tests
cargo test --test integration_tests
Generating Test Coverage
To generate a test coverage report, you'll need cargo-llvm-cov.
-
Install
cargo-llvm-cov:cargo install cargo-llvm-cov -
Generate the report:
cargo llvm-cov --all-features --workspace --lcov --output-path lcov.infoThis will create an
lcov.infofile which can be used by coverage visualization tools.
Test Coverage
- Unit tests for core logic components
- Integration tests for CLI functionality
- Test files in various languages for extractor testing
Writing Tests
- Add unit tests for new functions
- Include integration tests for CLI features
- Test edge cases and error conditions
- Use descriptive test names
Example:
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_extract_rust_functions() {
let code = r#"
fn example_function() {
println!("Hello, world!");
}
"#;
let extractor = RustExtractor::new();
let chunks = extractor.extract(code).unwrap();
assert_eq!(chunks.len(), 1);
assert_eq!(chunks[0].function_name(), "example_function");
}
}
Submitting Changes
Pull Request Process
-
Ensure your branch is up to date:
git checkout main git pull upstream main git checkout your-branch git rebase main -
Run the full test suite and checks:
cargo test cargo clippy --all-targets --all-features -- -D warnings cargo fmt --all -- --check -
Commit your changes:
git add . git commit -m "type: description of changes" -
Push to your fork:
git push origin your-branch -
Create a pull request:
- Use a descriptive title
- Explain what changes were made and why
- Reference any related issues
- Include screenshots for UI changes
Commit Message Format
Use conventional commit format:
type(scope): description
body (optional)
footer (optional)
Types:
feat: New featurefix: Bug fixdocs: Documentation changesstyle: Code style changes (formatting, etc.)refactor: Code refactoringperf: Performance improvementstest: Adding or updating testschore: Maintenance tasks
Examples:
feat: add support for Go language extractionfix: handle empty files in extractordocs: update installation instructions
Coding Standards
Rust Style
- Follow the Rust Style Guide
- Use
rustfmtfor formatting:cargo fmt - Use
clippyfor linting:cargo clippy - Write descriptive variable and function names
- Add documentation comments for public APIs
Code Quality
- Keep functions focused and reasonably sized
- Use meaningful error types and messages
- Handle all error cases appropriately
- Avoid unwrap() in production code - use proper error handling
- Write self-documenting code with good naming
Example Code Style
/// Extracts code chunks from a source file
pub fn extract_chunks(
file_path: &Path,
language: Language,
) -> Result<Vec<CodeChunk>, ExtractionError> {
let content = std::fs::read_to_string(file_path)
.map_err(|e| ExtractionError::FileRead(e))?;
let parser = create_parser(language)?;
let tree = parser.parse(&content, None)
.ok_or(ExtractionError::ParseFailed)?;
extract_from_tree(&tree, &content)
}
Adding Language Support
Steps to Add a New Language
-
Add the tree-sitter dependency:
# In Cargo.toml tree-sitter-newlang = "0.20" -
Create language definition:
// src/domain/models/languages/newlang.rs use crate::domain::models::Language; use crate::presentation::ui::Colors; use std::hash::Hash; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct NewLang; impl Language for NewLang { fn name(&self) -> &'static str { "newlang" } fn extensions(&self) -> Vec<&'static str> { vec!["nl"] } fn color(&self) -> ratatui::style::Color { Colors::lang_newlang() } fn display_name(&self) -> &'static str { "NewLang" } fn is_valid_comment_node(&self, node: tree_sitter::Node) -> bool { node.kind() == "comment" } } -
Create language-specific extractor:
// src/domain/services/source_code_parser/parsers/newlang.rs use super::LanguageExtractor; use crate::domain::models::ChunkType; use crate::{GitTypeError, Result}; use tree_sitter::{Node, Parser}; pub struct NewLangExtractor; impl LanguageExtractor for NewLangExtractor { fn tree_sitter_language(&self) -> tree_sitter::Language { tree_sitter_newlang::LANGUAGE.into() } fn query_patterns(&self) -> &str { "(function_declaration name: (identifier) @name) @function" } fn comment_query(&self) -> &str { "(comment) @comment" } fn capture_name_to_chunk_type(&self, capture_name: &str) -> Option<ChunkType> { match capture_name { "function" => Some(ChunkType::Function), _ => None, } } fn extract_name(&self, node: Node, source_code: &str, _capture_name: &str) -> Option<String> { // Extract identifier name from AST node None } fn middle_implementation_query(&self) -> &str { "" // Optional: for extracting code blocks within functions } fn middle_capture_name_to_chunk_type(&self, _capture_name: &str) -> Option<ChunkType> { None } } impl NewLangExtractor { pub fn create_parser() -> Result<Parser> { let mut parser = Parser::new(); parser.set_language(&tree_sitter_newlang::LANGUAGE.into()) .map_err(|e| GitTypeError::ExtractionFailed(format!("Failed to set NewLang language: {}", e)))?; Ok(parser) } } -
Register the language:
// In src/domain/models/languages/mod.rs pub mod newlang; pub use newlang::NewLang; // In src/domain/models/language.rs pub fn all_languages() -> Vec<Box<dyn Language>> { vec![ // ... other languages Box::new(NewLang), ] } // In src/domain/services/source_code_parser/parsers/mod.rs pub mod newlang; register_language!(NewLang, newlang, NewLangExtractor); -
Add color scheme support:
// In src/domain/models/color_scheme.rs - add field: pub lang_newlang: SerializableColor, // In src/presentation/ui/colors.rs - add method: pub fn lang_newlang() -> Color { Self::get_color_scheme().lang_newlang.into() } // Add to theme JSON files: // assets/languages/lang_dark.json // assets/languages/lang_light.json // assets/languages/lang_ascii.json "lang_newlang": {"r": 123, "g": 45, "b": 67} -
Add tests:
// tests/integration/languages/newlang/extractor.rs use crate::integration::languages::extractor::test_language_extractor; test_language_extractor! { name: test_newlang_function_extraction, language: "newlang", extension: "nl", source: r#" function hello() { print("Hello") } "#, total_chunks: 2, chunk_counts: { File: 1, Function: 1, } } -
Update documentation:
- Add to
README.mdsupported languages list - Add to
docs/supported-languages.mdwith extraction features - Update CLI help in
src/presentation/cli/args.rs - Add example code if needed
- Add to
Query Writing Guidelines
- Focus on extracting meaningful code units (functions, classes, methods)
- Ensure extracted chunks are self-contained
- Test queries with various code samples
- Consider edge cases and complex syntax
Release Distribution
GitType is distributed through several package managers. Most channels are updated automatically by the release workflow (.github/workflows/release.yml); a few require one-time setup.
winget (Windows)
The release workflow submits a manifest PR to microsoft/winget-pkgs via vedantmgoyal9/winget-releaser on every release.
One-time setup:
- The initial
0.10.0manifest lives under.winget/manifests/u/unhappychoice/gittype/0.10.0/and must be PR'd manually tomicrosoft/winget-pkgsonce. After it is merged, subsequent versions are added automatically. - Create a fork of
microsoft/winget-pkgsunder the owner account. - Create a GitHub PAT (classic) with
public_reposcope that can push to the fork, and register it as theWINGET_TOKENrepository secret.
Package identifier: unhappychoice.gittype
Getting Help
- Issues: Browse existing issues or create a new one
- Discussions: Use GitHub Discussions for questions
- Documentation: Check the README and code comments
Recognition
Contributors will be acknowledged in:
- CONTRIBUTORS.md file
- Release notes for significant contributions
- Repository insights and statistics
Thank you for contributing to GitType! 🚀