0
# Clang-Format
1
2
A Python distribution of the LLVM clang-format code formatting tool for C, C++, and CUDA. This package provides convenient installation and usage of clang-format without requiring separate LLVM development tools, making it ideal for development workflows, CI/CD pipelines, and pre-commit hooks.
3
4
## Package Information
5
6
- **Package Name**: clang-format
7
- **Language**: Python
8
- **Installation**: `pip install clang-format`
9
- **Alternative Installation**: `pipx install clang-format` (for isolated execution)
10
11
## Core Imports
12
13
```python
14
import clang_format
15
```
16
17
For accessing utility functions:
18
19
```python
20
from clang_format import get_executable
21
```
22
23
For accessing git integration and diff-based formatting:
24
25
```python
26
from clang_format import git_clang_format, clang_format_diff
27
```
28
29
## Basic Usage
30
31
### Command Line Usage
32
33
After installation, use the console scripts directly:
34
35
```bash
36
# Format a single file
37
clang-format main.cpp
38
39
# Format with specific style
40
clang-format -style=Google main.cpp
41
42
# Format in-place
43
clang-format -i main.cpp
44
45
# Format multiple files
46
clang-format *.cpp *.h
47
48
# Git integration - format staged changes
49
git-clang-format
50
51
# Format specific lines from diff
52
clang-format-diff.py
53
```
54
55
### Python API Usage
56
57
```python
58
import clang_format
59
import subprocess
60
61
# Get path to clang-format executable
62
exe_path = clang_format.get_executable('clang-format')
63
print(f"clang-format executable: {exe_path}")
64
65
# Use subprocess to run clang-format programmatically
66
result = subprocess.run([
67
exe_path,
68
'-style=LLVM',
69
'source.cpp'
70
], capture_output=True, text=True)
71
72
formatted_code = result.stdout
73
```
74
75
### Pre-commit Hook Usage
76
77
```yaml
78
repos:
79
- repo: https://github.com/pre-commit/mirrors-clang-format
80
rev: v21.1.0
81
hooks:
82
- id: clang-format
83
types_or: [c++, c, cuda]
84
```
85
86
## Architecture
87
88
The package uses a simple wrapper architecture:
89
90
- **Binary Distribution**: Native clang-format binaries bundled in `data/bin/` directory
91
- **Python Wrapper**: Utility functions to locate and execute the bundled executable
92
- **Console Scripts**: Entry points that bridge Python package to command-line tools
93
- **Build-time Integration**: Additional utilities (git-clang-format, clang-format-diff.py) copied from LLVM project during build
94
95
## Capabilities
96
97
### Executable Path Resolution
98
99
Utility function to get the full path to the bundled clang-format executable, enabling programmatic usage and integration with other tools.
100
101
```python { .api }
102
def get_executable(name):
103
"""
104
Get the full path to the specified executable.
105
106
Parameters:
107
- name: str, name of the executable (e.g., "clang-format")
108
109
Returns:
110
str: Full path to the executable in the package's data/bin directory
111
"""
112
```
113
114
**Usage Example:**
115
116
```python
117
import clang_format
118
import subprocess
119
120
# Get executable path
121
exe_path = clang_format.get_executable('clang-format')
122
123
# Use with subprocess for custom formatting
124
result = subprocess.run([
125
exe_path,
126
'-style=file', # Use .clang-format file
127
'-i', # Format in-place
128
'source.cpp'
129
], check=True)
130
```
131
132
### Main Entry Point
133
134
Primary entry point function that executes clang-format with command-line arguments. This function replicates command-line behavior within Python scripts.
135
136
```python { .api }
137
def clang_format():
138
"""
139
Execute clang-format with command-line arguments from sys.argv.
140
141
This function processes sys.argv[1:] as arguments and exits with
142
the subprocess return code. Intended for console script usage.
143
144
Raises:
145
SystemExit: Always exits with subprocess return code
146
"""
147
```
148
149
**Usage Example:**
150
151
```python
152
import sys
153
import clang_format
154
155
# Programmatically set arguments
156
sys.argv = ['clang-format', '-style=Google', 'main.cpp']
157
158
# Execute (will exit process)
159
clang_format.clang_format()
160
```
161
162
### Git Integration Module
163
164
Git-aware formatting that applies clang-format only to changed lines in commits or staging area, providing selective formatting for version-controlled codebases.
165
166
```python { .api }
167
def main():
168
"""
169
Main entry point for git-clang-format integration.
170
171
Processes command-line arguments and executes git-aware formatting,
172
applying clang-format selectively to changed lines in git repositories.
173
174
Returns:
175
int: Exit code (0 for no changes, 1 for changes applied)
176
"""
177
```
178
179
**Module Import:**
180
```python
181
from clang_format import git_clang_format
182
```
183
184
**Programmatic Usage:**
185
```python
186
import sys
187
from clang_format import git_clang_format
188
189
# Set arguments for git integration
190
sys.argv = ['git-clang-format', '--diff', 'HEAD~1']
191
192
# Execute git-aware formatting
193
result = git_clang_format.main()
194
print(f"Exit code: {result}")
195
```
196
197
### Diff-Based Formatting Module
198
199
Universal diff processor that applies clang-format to specific changed lines from unified diff input, compatible with any version control system.
200
201
```python { .api }
202
def main():
203
"""
204
Main entry point for diff-based selective formatting.
205
206
Reads unified diff from stdin and applies clang-format only to
207
the changed lines, supporting selective formatting workflows.
208
209
Returns:
210
int: Status code (1 if differences found, subprocess return code on failure)
211
"""
212
```
213
214
**Module Import:**
215
```python
216
from clang_format import clang_format_diff
217
```
218
219
**Programmatic Usage:**
220
```python
221
import sys
222
import io
223
from clang_format import clang_format_diff
224
225
# Prepare diff input
226
diff_content = """--- a/example.cpp
227
+++ b/example.cpp
228
@@ -1,3 +1,4 @@
229
int main() {
230
- return 0;
231
+ return 0;
232
+ // Comment
233
}
234
"""
235
236
# Redirect stdin and execute
237
old_stdin = sys.stdin
238
sys.stdin = io.StringIO(diff_content)
239
sys.argv = ['clang-format-diff.py', '-i']
240
241
result = clang_format_diff.main()
242
sys.stdin = old_stdin
243
```
244
245
### Console Script Integration
246
247
The package provides three console script entry points for different clang-format utilities:
248
249
#### clang-format
250
251
Main code formatting utility for C, C++, and CUDA source code.
252
253
**Console Command:**
254
```bash
255
clang-format [options] [files...]
256
```
257
258
**Entry Point:** `clang_format:clang_format`
259
260
**Common Options:**
261
- `-style=<style>`: Formatting style (LLVM, Google, Chromium, Mozilla, WebKit, Microsoft, GNU, file)
262
- `-i`: Format files in-place
263
- `--dry-run`: Don't write changes, just show what would be formatted
264
- `--sort-includes`: Sort #include directives
265
- `--verbose`: Show which files are being processed
266
267
#### git-clang-format
268
269
Git integration utility that formats only the lines changed in git commits or staging area.
270
271
**Console Command:**
272
```bash
273
git clang-format [git-options]
274
```
275
276
**Entry Point:** `clang_format.git_clang_format:main`
277
278
**Common Usage:**
279
- `git clang-format`: Format staged changes
280
- `git clang-format HEAD~1`: Format changes since last commit
281
- `git clang-format --diff`: Show formatting changes without applying
282
283
#### clang-format-diff.py
284
285
Diff-based formatting utility that applies clang-format to specific changed lines from unified diff format.
286
287
**Console Command:**
288
```bash
289
clang-format-diff.py [diff-options]
290
```
291
292
**Entry Point:** `clang_format.clang_format_diff:main`
293
294
**Common Usage:**
295
- `git diff HEAD~1 | clang-format-diff.py -i`: Format changes from diff
296
- `clang-format-diff.py -p1 < changes.patch`: Apply formatting to patch
297
298
### Integration Patterns
299
300
Common integration patterns for development workflows:
301
302
#### CI/CD Integration
303
304
```bash
305
# Install in CI environment
306
pip install clang-format
307
308
# Check formatting in CI
309
clang-format --dry-run --Werror *.cpp *.h
310
```
311
312
#### Development Workflow
313
314
```bash
315
# Install with pipx for isolated usage
316
pipx install clang-format
317
318
# Format before commit
319
git add .
320
git clang-format
321
git commit -m "Apply clang-format"
322
```
323
324
#### Python Script Integration
325
326
```python
327
import clang_format
328
import subprocess
329
import os
330
331
def format_project_files():
332
"""Format all C++ files in project."""
333
exe_path = clang_format.get_executable('clang-format')
334
335
for root, dirs, files in os.walk('.'):
336
for file in files:
337
if file.endswith(('.cpp', '.h', '.cc', '.hpp')):
338
filepath = os.path.join(root, file)
339
subprocess.run([exe_path, '-i', filepath], check=True)
340
print(f"Formatted: {filepath}")
341
342
# Usage
343
format_project_files()
344
```
345
346
## Error Handling
347
348
The package handles common error scenarios:
349
350
- **Missing executable**: If the bundled executable is not found, functions will raise `FileNotFoundError`
351
- **Invalid arguments**: Command-line argument errors are passed through from the underlying clang-format tool
352
- **Permission errors**: File permission issues are handled by the underlying subprocess calls
353
354
## Platform Support
355
356
- **Cross-platform**: Supports Windows, macOS, and Linux
357
- **Architecture support**: Binary wheels available for common architectures
358
- **Python versions**: Compatible with Python 3.x (check package metadata for specific version requirements)
359
360
## Additional Notes
361
362
The package includes internal helper functions that are not part of the public API. These functions handle the underlying process execution and are abstracted by the public interface.