style guide: rewrite for Rust, guard against cargo fmt
code_style_guide.md was the generic C++ formulation of the Modified Allman style: it mandated camelCase for functions (every function in this crate is Rust snake_case, and rustc warns otherwise), three of its five examples taught try/catch brace placement for a construct Rust does not have, all examples were C++, and it instructed saving a .clang-format that does not exist and would not format Rust anyway. Its final YAML block was also missing the closing fence, so renderers swallowed the tail of the document. Since README defers to CONTRIBUTING and CONTRIBUTING defers here for the full rules, the contributor path terminated in the one document that contradicted the code.
Rewrite it for Rust: same principles (tabs, opening brace on its own line, compact "} else {", spaces inside non-empty parentheses), plus the rules the code follows but no document stated — snake_case for functions and variables, spaces inside non-empty attribute brackets, no spaces inside generics, aligned columns, comments in English. Examples are now idiomatic Rust: if/else, match, Result with the ? operator in place of try/catch, if let, struct + impl with attributes. The file declares itself the canonical reference, with CONTRIBUTING's bullets as the summary.
Replace the .clang-format section with the verified rustfmt situation: rustfmt cannot express this style (no option exists for spaces inside parentheses or attribute brackets, the brace-style options are nightly-only, and even on nightly Allman opening braces cannot combine with a compact "} else {"). Ship a rustfmt.toml with disable_all_formatting = true — a stable option, verified a no-op on rustfmt 1.8.0 — so an accidental cargo fmt or editor format-on-save can no longer rewrite the tree.
This commit is contained in:
@@ -1,169 +1,136 @@
|
||||
# Code Style Guide
|
||||
|
||||
This project follows a **Modified Allman** brace and formatting style.
|
||||
It prioritizes **visual clarity, symmetry, and logical separation of blocks** over strict line compactness.
|
||||
This project follows a **Modified Allman** brace and formatting style, applied to Rust. It prioritizes **visual clarity, symmetry, and logical separation of blocks** over strict line compactness.
|
||||
|
||||
This file is the canonical style reference; the style bullets in [CONTRIBUTING.md](CONTRIBUTING.md) are a summary of it.
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
## Key principles
|
||||
|
||||
### Key Principles
|
||||
- Indentation with **tabs** (width = 4).
|
||||
- **Opening braces `{`** always start on a new line.
|
||||
- **`} else {`** and **`} catch {`** appear on the same line for compact flow.
|
||||
- **Spaces inside parentheses only when non-empty:**
|
||||
- `( arg1, arg2 )`
|
||||
- `main()`
|
||||
- **Classes and structs:** PascalCase
|
||||
- **Variables, objects, and functions:** camelCase
|
||||
- **Constants/macros:** UPPER_CASE_WITH_UNDERSCORES
|
||||
- Indentation with **tabs** (width = 4).
|
||||
- **Opening braces `{`** start on their own line — for `fn`, `impl`, `struct`, `enum`, `trait`, `mod`, `if`, `for`, `while`, `loop` and `match`.
|
||||
- **`} else {`** and **`} else if … {`** stay on the same line for compact flow.
|
||||
- **Spaces inside parentheses only when non-empty:**
|
||||
- `( arg1, arg2 )`
|
||||
- `main()`
|
||||
- **Spaces inside attribute brackets only when non-empty:** `#[ derive( Clone, Debug ) ]`, `#[ cfg( test ) ]`.
|
||||
- **No spaces inside generics:** `Vec<String>`, `Option<i32>`, `Element<Msg>`.
|
||||
- **Types, traits, and enum variants:** PascalCase.
|
||||
- **Functions, methods, variables, and modules:** snake_case (the Rust convention; `rustc` warns on anything else).
|
||||
- **Constants and statics:** UPPER_CASE_WITH_UNDERSCORES.
|
||||
- **Aligned columns** in consecutive struct fields, match arms, or `let` groups where it aids scanning.
|
||||
- **Comments in English**, only where the code cannot say it itself.
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
### `if / else` structure
|
||||
```cpp
|
||||
if ( condition )
|
||||
|
||||
```rust
|
||||
if condition
|
||||
{
|
||||
doSomething();
|
||||
do_something();
|
||||
} else if other_condition {
|
||||
do_other_thing();
|
||||
} else {
|
||||
doSomethingElse( arg1, arg2 );
|
||||
do_something_else( arg1, arg2 );
|
||||
}
|
||||
```
|
||||
|
||||
### `try / catch` structure
|
||||
```cpp
|
||||
try
|
||||
### `match` structure
|
||||
|
||||
```rust
|
||||
match points.len()
|
||||
{
|
||||
runOperation();
|
||||
} catch ( const std::exception& ex ) {
|
||||
handleError( ex );
|
||||
0 => None,
|
||||
1 => Some( points[0].value ),
|
||||
n => Some( total / n as f32 ),
|
||||
}
|
||||
```
|
||||
|
||||
### Class and method naming
|
||||
```cpp
|
||||
class DataAnalyzer
|
||||
### Error handling
|
||||
|
||||
Rust has no `try / catch`; recoverable errors travel as `Result` and propagate with `?`. The block style applies to the `match` when a result is handled in place:
|
||||
|
||||
```rust
|
||||
fn load_config( path: &Path ) -> Result<Config, ConfigError>
|
||||
{
|
||||
public:
|
||||
DataAnalyzer( const std::string& filePath )
|
||||
: filePath( filePath )
|
||||
let text = std::fs::read_to_string( path )?;
|
||||
match toml::from_str( &text )
|
||||
{
|
||||
Ok( cfg ) => Ok( cfg ),
|
||||
Err( e ) => Err( ConfigError::Parse( e ) ),
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
void processDataAndGenerateReport()
|
||||
`if let` follows the same brace rules as `if`:
|
||||
|
||||
```rust
|
||||
if let Some( ( rgba, w, h ) ) = icon( "general/right" )
|
||||
{
|
||||
it = it.trailing_icon( rgba, w, h );
|
||||
}
|
||||
```
|
||||
|
||||
### Structs, impls, and attributes
|
||||
|
||||
```rust
|
||||
#[ derive( Clone, Debug ) ]
|
||||
pub struct DataPoint
|
||||
{
|
||||
value: f32,
|
||||
label: String,
|
||||
}
|
||||
|
||||
impl DataPoint
|
||||
{
|
||||
pub fn new( value: f32, label: impl Into<String> ) -> Self
|
||||
{
|
||||
try
|
||||
Self
|
||||
{
|
||||
loadDataFromFile( filePath );
|
||||
analyzeResultsAndPrintSummary();
|
||||
} catch ( const std::runtime_error& error ) {
|
||||
std::cerr << "Error: " << error.what() << std::endl;
|
||||
value,
|
||||
label: label.into(),
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::string filePath;
|
||||
|
||||
void loadDataFromFile( const std::string& path )
|
||||
pub fn scaled( &self, factor: f32 ) -> f32
|
||||
{
|
||||
if ( path.empty() )
|
||||
if factor <= 0.0
|
||||
{
|
||||
throw std::runtime_error( "File path cannot be empty." );
|
||||
self.value
|
||||
} else {
|
||||
std::cout << "Loading data from: " << path << std::endl;
|
||||
self.value * factor
|
||||
}
|
||||
}
|
||||
|
||||
void analyzeResultsAndPrintSummary()
|
||||
{
|
||||
std::cout << "Analyzing data..." << std::endl;
|
||||
std::cout << "Summary: OK" << std::endl;
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### `main()` function
|
||||
```cpp
|
||||
int main()
|
||||
|
||||
```rust
|
||||
fn main()
|
||||
{
|
||||
DataAnalyzer analyzer( "results.csv" );
|
||||
let analyzer = DataAnalyzer::new( "results.csv" );
|
||||
|
||||
try
|
||||
if let Err( e ) = analyzer.process_and_report()
|
||||
{
|
||||
analyzer.processDataAndGenerateReport();
|
||||
} catch ( const std::exception& ex ) {
|
||||
std::cerr << "Unhandled exception: " << ex.what() << std::endl;
|
||||
eprintln!( "Error: {e}" );
|
||||
std::process::exit( 1 );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## `.clang-format` configuration
|
||||
## Tooling: do not run `cargo fmt`
|
||||
|
||||
Save this file as `.clang-format` in your project root:
|
||||
`rustfmt` cannot express this style, so **never run `cargo fmt` on this codebase** — it would rewrite every file into the default style. Specifically:
|
||||
|
||||
```yaml
|
||||
# === Style: Modified Allman (tabs, compact else/catch, and selective parentheses spacing) ===
|
||||
# Naming conventions:
|
||||
# · Classes and structs: PascalCase (e.g., MyClass, PlayerController)
|
||||
# · Variables, objects, and functions: camelCase (e.g., myVariable, calculateScore)
|
||||
# · Constants or macros: UPPER_CASE_WITH_UNDERSCORES
|
||||
# · if/else and try/catch share the same brace layout:
|
||||
# if ( condition )
|
||||
# {
|
||||
# ...
|
||||
# } else {
|
||||
# ...
|
||||
# }
|
||||
# try
|
||||
# {
|
||||
# ...
|
||||
# } catch ( const std::exception& e ) {
|
||||
# ...
|
||||
# }
|
||||
- There is **no rustfmt option for spaces inside parentheses or attribute brackets** (the historical `spaces_within_parens` options were removed from rustfmt).
|
||||
- The item brace styles (`brace_style`, `control_brace_style`) are **unstable, nightly-only** options.
|
||||
- Even on nightly, the combination of Allman opening braces with a compact `} else {` is not representable: `control_brace_style = "AlwaysNextLine"` also pushes `else` onto its own line.
|
||||
|
||||
BasedOnStyle: LLVM
|
||||
|
||||
IndentWidth: 4
|
||||
UseTab: Always
|
||||
|
||||
BraceWrapping:
|
||||
AfterClass: true
|
||||
AfterControlStatement: true
|
||||
AfterEnum: true
|
||||
AfterFunction: true
|
||||
AfterNamespace: true
|
||||
AfterStruct: true
|
||||
AfterUnion: true
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: false
|
||||
SplitEmptyRecord: false
|
||||
SplitEmptyNamespace: false
|
||||
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: false
|
||||
|
||||
SpaceBeforeParens: Always
|
||||
SpaceInEmptyParentheses: false
|
||||
SpaceInParens: true
|
||||
SpacesInAngles: false
|
||||
SpacesInCStyleCastParentheses: true
|
||||
SpacesInSquareBrackets: false
|
||||
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
ColumnLimit: 0
|
||||
AlignConsecutiveAssignments: true
|
||||
AlignConsecutiveDeclarations: true
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
|
||||
BreakBeforeBraces: Allman
|
||||
The repository ships a `rustfmt.toml` containing only `disable_all_formatting = true`, so an accidental `cargo fmt` — or an editor with format-on-save wired to rustfmt — is a no-op instead of a 40 000-line diff. Style is enforced by review, not by a formatter.
|
||||
|
||||
4
rustfmt.toml
Normal file
4
rustfmt.toml
Normal file
@@ -0,0 +1,4 @@
|
||||
# This codebase uses the Modified Allman style described in code_style_guide.md,
|
||||
# which rustfmt cannot express. Formatting is disabled so an accidental
|
||||
# `cargo fmt` (or editor format-on-save) is a no-op.
|
||||
disable_all_formatting = true
|
||||
Reference in New Issue
Block a user