Contributing
Getting Started
git clone https://github.com/glottologist/towl.git
cd towl
cargo build
Requirements
- Rust 1.75+ (see
rust-toolchain.toml) - git on
PATH
Development Commands
# Build
cargo build
# Run all tests
cargo nextest run # preferred
cargo test # fallback
# Clippy (strict)
cargo clippy --all-targets --all-features
# Format
cargo fmt
# Run the binary
cargo run -- scan
cargo run -- scan -f json -o todos.json
cargo run -- config
cargo run -- init
Project Structure
See Architecture for a full layout. Key entry points:
src/bin/towl.rs-- CLI binarysrc/lib/mod.rs-- Library roottests/-- Integration and property-based tests
Testing
Test Hierarchy
Tests follow a strict hierarchy:
- proptest (property-based) -- First choice for pure functions, parsers, validators, serialisation roundtrips
- rstest (parameterized) -- For specific known cases (< 10 inputs with exact expected outputs)
- Standalone -- Last resort, for complex integration scenarios
Running Tests
# All tests
cargo nextest run
# Specific module
cargo nextest run scanner
# Property-based tests only
cargo nextest run proptest
# Integration tests only
cargo nextest run --test '*'
Code Style
- Follow Rust naming conventions (
snake_casefor functions,CamelCasefor types) - All public items need doc comments (
///) - No
#[allow(...)]attributes -- fix the underlying issue - No
.unwrap()/.expect()in production code -- use?with typed errors - No
asnumeric casts -- usetry_from/into/From - Minimise
.clone()-- prefer borrowing, see Clone Reduction Policy
Error Handling
- Use
thiserrorfor error type derivation - Each module defines its own error enum
- Errors propagate upward via
?and#[from] - Never silently discard
Resultvalues
Adding a New Output Format
- Create
src/lib/output/formatter/formatters/yourformat.rs - Implement the
Formattertrait - Add a variant to
FormatterImplinformatters/mod.rs - Add dispatch in
FormatterImpl::format() - Add a variant to
OutputFormatinsrc/lib/cli/mod.rs - Update the format-to-writer mapping in
Output::new() - Add tests (proptest for roundtrips, rstest for edge cases)
Adding a New TODO Type
- Add a variant to
TodoTypeinsrc/lib/comment/todo.rs - Update
Display,TryFrom<&str>,as_filter_str() - Add a default pattern to
default_todo_patterns()insrc/lib/config/types.rs - Add a pattern mapping in the parser
- Update tests
Pull Requests
- Keep PRs focused on a single change
- Include tests for new functionality
- Ensure
cargo clippypasses with zero warnings - Ensure
cargo fmtproduces no changes - Ensure all tests pass