Contributing Guide
How to contribute to Two-Face development.
Welcome!
Thank you for considering contributing to Two-Face! This document provides guidelines and information for contributors.
Ways to Contribute
Code Contributions
- Bug fixes
- New features
- Performance improvements
- Widget implementations
- Parser extensions
Non-Code Contributions
- Documentation improvements
- Bug reports
- Feature suggestions
- User support
- Testing and feedback
Getting Started
1. Fork and Clone
# Fork on GitHub, then clone your fork
git clone https://github.com/YOUR_USERNAME/two-face.git
cd two-face
2. Set Up Development Environment
# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Install dependencies (varies by platform)
# See building.md for platform-specific instructions
# Build
cargo build
# Run tests
cargo test
3. Create a Branch
git checkout -b feature/my-feature
# or
git checkout -b fix/bug-description
Development Workflow
Making Changes
- Write code following the style guide
- Add tests for new functionality
- Update documentation if needed
- Run checks before committing
Pre-Commit Checks
# Format code
cargo fmt
# Run linter
cargo clippy -- -D warnings
# Run tests
cargo test
# Check documentation
cargo doc --no-deps
Commit Messages
Follow conventional commit format:
type(scope): description
[optional body]
[optional footer]
Types:
feat: New featurefix: Bug fixdocs: Documentationrefactor: Code restructuringtest: Adding testschore: Maintenance
Examples:
feat(parser): add spell duration parsing
fix(widget): correct scrollback overflow
docs: update installation instructions
refactor(tui): extract render helpers
Pull Request Process
Before Submitting
- Code follows style guide
- All tests pass
- No clippy warnings
- Documentation updated
- Commit messages are clear
PR Description Template
## Description
Brief description of changes
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update
## Testing
How was this tested?
## Checklist
- [ ] Tests added
- [ ] Documentation updated
- [ ] No breaking changes (or documented)
Review Process
- Submit PR against
mainbranch - CI checks run automatically
- Maintainers review code
- Address feedback
- Merge when approved
Code Style
Rust Style
Follow standard Rust conventions:
#![allow(unused)]
fn main() {
// Use rustfmt defaults
cargo fmt
// Naming
fn function_name() {} // snake_case for functions
struct StructName {} // PascalCase for types
const CONSTANT: u32 = 1; // SCREAMING_SNAKE_CASE for constants
let variable_name = 1; // snake_case for variables
}
Documentation
#![allow(unused)]
fn main() {
/// Brief description of the function.
///
/// More detailed explanation if needed.
///
/// # Arguments
///
/// * `param` - Description of parameter
///
/// # Returns
///
/// Description of return value
///
/// # Examples
///
/// ```
/// let result = my_function("input");
/// assert_eq!(result, expected);
/// ```
pub fn my_function(param: &str) -> Result<Output> {
// ...
}
}
Error Handling
#![allow(unused)]
fn main() {
// Use Result for recoverable errors
fn parse_config(path: &Path) -> Result<Config, ConfigError> {
let content = fs::read_to_string(path)?;
let config: Config = toml::from_str(&content)?;
Ok(config)
}
// Use Option for optional values
fn find_widget(&self, name: &str) -> Option<&Widget> {
self.widgets.iter().find(|w| w.name() == name)
}
}
Testing
#![allow(unused)]
fn main() {
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_descriptive_name() {
// Arrange
let input = setup_test_data();
// Act
let result = function_under_test(input);
// Assert
assert_eq!(result, expected);
}
}
}
Issue Guidelines
Bug Reports
Include:
- Two-Face version
- Operating system
- Steps to reproduce
- Expected behavior
- Actual behavior
- Relevant logs
Template:
**Version**: 0.1.0
**OS**: Windows 10 / macOS 14 / Ubuntu 22.04
**Steps to Reproduce**:
1. Do this
2. Then this
3. See error
**Expected**: What should happen
**Actual**: What actually happens
**Logs**:
relevant log output
Feature Requests
Include:
- Use case description
- Proposed solution
- Alternatives considered
Template:
**Use Case**:
Why do you need this feature?
**Proposed Solution**:
How should it work?
**Alternatives**:
What other approaches did you consider?
Community Guidelines
Code of Conduct
- Be respectful and inclusive
- Focus on constructive feedback
- Help others learn
- Credit others’ work
- Assume good intentions
Communication
- GitHub Issues for bugs and features
- GitHub Discussions for questions
- Pull Request comments for code review
Getting Help
- Check existing documentation
- Search closed issues
- Ask in GitHub Discussions
- Be specific in your questions
Release Process
Version Numbering
Follow Semantic Versioning (SemVer):
- MAJOR: Breaking changes
- MINOR: New features (backwards compatible)
- PATCH: Bug fixes
Changelog
Update CHANGELOG.md with:
- Version number and date
- Breaking changes (if any)
- New features
- Bug fixes
- Known issues
Recognition
Contributors are recognized in:
CONTRIBUTORS.md- Release notes
- Project README
Thank you for contributing to Two-Face!
See Also
- Building - Build instructions
- Project Structure - Code organization
- Testing - Test guidelines