Go package supporting clang-format with Protocol Buffers and C/C++ batch formatting capabilities.
π― Smart Proto Formatting: Intelligent clang-format package with Google style defaults β‘ Two Operation Modes: Both preview (DryRun) and in-place formatting support π Batch Processing: Project-wide .proto file formatting using recursive approach π Configurable Styles: Customizable formatting with JSON configuration π Comprehensive Logging: Detailed operation logs with structured output
go get github.com/go-xlan/clang-format@latestgo install github.com/go-xlan/clang-format/cmd/clang-format-batch@latestSetup clang-format as requirement:
# macOS
brew install clang-format
# Ubuntu/Debian
sudo apt-get install clang-format
# Check setup
clang-format --versionThe clang-format-batch command formats files in Git projects. It requires:
- Running from within a Git repo
- Valid file extensions specified via
--extensionsflag
Basic Examples:
# Format .proto files in current project
clang-format-batch --extensions=".proto"
# Format C/C++ files
clang-format-batch --extensions=".c,.cpp,.h"
# Format multiple file types
clang-format-batch --extensions=".proto,.c,.cpp,.h"
# Use short flag
clang-format-batch -e ".proto,.cc,.hh"Supported File Extensions:
.proto- Protocol Buffer files.c,.cpp,.cxx,.cc- C/C++ source files.h,.hpp,.hxx- C/C++ headers
Important Notes:
- Command must be run from within a Git repo
- Command processes matching files in project using recursive approach
- Hidden files and paths (starting with
.) are skipped - Source files are modified in-place (use version management!)
The protoformat package provides high-end API when formatting Protocol Buffer files:
package main
import (
"fmt"
"github.com/go-xlan/clang-format/protoformat"
"github.com/yyle88/must"
"github.com/yyle88/osexec"
"github.com/yyle88/rese"
)
func main() {
// Create execution configuration
execConfig := osexec.NewExecConfig()
// Create default Proto style (Google-based, 2-space indent)
style := protoformat.NewStyle()
// Preview .proto file formatting (DryRun)
// Returns formatted content without modifying the file
output := rese.V1(protoformat.DryRun(execConfig, "example.proto", style))
fmt.Println(string(output))
// Format single .proto file in-place
// Modifies the file with formatted content
output = rese.V1(protoformat.Format(execConfig, "example.proto", style))
// Format entire project (batch processing)
// Formats .proto files in DIR using recursive approach
must.Done(protoformat.FormatProject(execConfig, "./proto-project", style))
}Main Points:
DryRun()- Preview changes without modifying files (safe to use)Format()- Commit changes to single file (modifies file in-place)FormatProject()- Batch process .proto files in DIR- Uses Google Proto style as default (2-space indentation, no width limit)
You can customize formatting to match the project's coding standards:
// Create custom style based on LLVM conventions
customStyle := &clangformat.Style{
BasedOnStyle: "LLVM", // Base style template
IndentWidth: 4, // 4 spaces at each indent
ColumnLimit: 80, // Maximum line width
AlignConsecutiveAssignments: true, // Align = signs in columns
}
// Use custom style when formatting
output := rese.V1(protoformat.DryRun(execConfig, "example.proto", customStyle))Available Base Styles:
"Google"- Google C++ Style Guide (default)"LLVM"- LLVM coding standards"Chromium"- Chromium project style"Mozilla"- Mozilla style guide"WebKit"- WebKit style guide
Common Style Options:
IndentWidth- Count of spaces when indenting (common: 2 and 4)ColumnLimit- Maximum line width (0 = no limit)AlignConsecutiveAssignments- Align assignment operators in columns
The clangformat package provides foundation API when formatting clang-format supported files:
import "github.com/go-xlan/clang-format/clangformat"
// Create execution config and style
execConfig := osexec.NewExecConfig()
style := clangformat.NewStyle()
// Preview C++ file formatting
output := rese.V1(clangformat.DryRun(execConfig, "example.cpp", style))
// Format C++ file in-place
output = rese.V1(clangformat.Format(execConfig, "example.cpp", style))
// Batch format .cpp files in project
must.Done(clangformat.FormatProject(execConfig, "./src", ".cpp", style))Note: Unlike protoformat.FormatProject(), the clangformat.FormatProject() needs
a single file extension. To format multiple kinds, make multiple invocations:
// Format both .cpp and .h files
must.Done(clangformat.FormatProject(execConfig, "./src", ".cpp", style))
must.Done(clangformat.FormatProject(execConfig, "./src", ".h", style))Core Functions:
-
NewStyle() *Style- Creates default Google-based style configuration
- Returns style with 2-space indentation and no width limit
- Safe to change the data structure when customizing
-
DryRun(config *osexec.ExecConfig, path string, style *Style) ([]byte, error)- Preview formatting without file modification
- Returns formatted content as byte sequence
- Source file stays unchanged
- Use this when validating changes before commit
-
Format(config *osexec.ExecConfig, path string, style *Style) ([]byte, error)- Commit formatting changes to file in-place
- Modifies the file on disk
- Returns zero-length byte sequence on success (clang-format action)
- Warning: Source file is overwritten
-
FormatProject(config *osexec.ExecConfig, projectPath string, extension string, style *Style) error- Batch format files with specific extension in project
- Walks through DIR tree using recursive approach
- Skips hidden files and paths (starting with
.) - Processes one extension at a time
Core Functions:
-
NewStyle() *clangformat.Style- Creates Protocol Buffers optimized style configuration
- Same as
clangformat.NewStyle()but provides Proto-specific context - Returns Google-based style tuned when formatting .proto files
-
DryRun(config *osexec.ExecConfig, protoPath string, style *clangformat.Style) ([]byte, error)- Preview .proto file formatting without modification
- Wraps
clangformat.DryRun()with proto-specific context - Returns formatted Proto content
-
Format(config *osexec.ExecConfig, protoPath string, style *clangformat.Style) ([]byte, error)- Commit formatting changes to single .proto file in-place
- Wraps
clangformat.Format()with proto-specific context - Modifies file on disk
-
FormatProject(config *osexec.ExecConfig, projectPath string, style *clangformat.Style) error- Batch format .proto files in project
- Targets
.protoextension as default - Shows green success message on completion
- Provides detailed logging when processing each file
type Style struct {
BasedOnStyle string // "Google", "LLVM", "Chromium", etc.
IndentWidth int // Count of spaces when indenting
ColumnLimit int // Maximum line width (0 = no limit)
AlignConsecutiveAssignments bool // Align assignments at assignment signs
}MIT License. See LICENSE.
Contributions are welcome! Report bugs, suggest features, and contribute code:
- π Found a mistake? Open an issue on GitHub with reproduction steps
- π‘ Have a feature idea? Create an issue to discuss the suggestion
- π Documentation confusing? Report it so we can improve
- π Need new features? Share the use cases to help us understand requirements
- β‘ Performance issue? Help us optimize through reporting slow operations
- π§ Configuration problem? Ask questions about complex setups
- π’ Follow project progress? Watch the repo to get new releases and features
- π Success stories? Share how this package improved the workflow
- π¬ Feedback? We welcome suggestions and comments
New code contributions, follow this process:
- Fork: Fork the repo on GitHub (using the webpage UI).
- Clone: Clone the forked project (
git clone https://github.com/yourname/repo-name.git). - Navigate: Navigate to the cloned project (
cd repo-name) - Branch: Create a feature branch (
git checkout -b feature/xxx). - Code: Implement the changes with comprehensive tests
- Testing: (Golang project) Ensure tests pass (
go test ./...) and follow Go code style conventions - Documentation: Update documentation to support client-facing changes and use significant commit messages
- Stage: Stage changes (
git add .) - Commit: Commit changes (
git commit -m "Add feature xxx") ensuring backward compatible code - Push: Push to the branch (
git push origin feature/xxx). - PR: Open a merge request on GitHub (on the GitHub webpage) with detailed description.
Please ensure tests pass and include relevant documentation updates.
Welcome to contribute to this project via submitting merge requests and reporting issues.
Project Support:
- β Give GitHub stars if this project helps you
- π€ Share with teammates and (golang) programming friends
- π Write tech blogs about development tools and workflows - we provide content writing support
- π Join the ecosystem - committed to supporting open source and the (golang) development scene
Have Fun Coding with this package! πππ