|
1 | 1 | # clang-format-node
|
2 |
| -Node repackaging of the clang-format native binary based on angular/clang-format.🐉 |
| 2 | + |
| 3 | +[](https://github.com/lumirlumir/npm-clang-format-node/actions/workflows/lint.yml) |
| 4 | +[](https://github.com/lumirlumir/npm-clang-format-node/actions/workflows/test.yml) |
| 5 | +[](https://codecov.io/gh/lumirlumir/npm-clang-format-node) |
| 6 | +[](https://www.npmjs.com/package/clang-format-node) |
| 7 | +&color=violet) |
| 8 | + |
| 9 | +Node repackaging(wrapping) of the `clang-format` native binary inspired by ['angular/clang-format'](https://github.com/angular/clang-format).🐉 |
| 10 | + |
| 11 | +This package intends to release a new npm package for every **latest** release of the `clang-format`. It **checks** for the latest LLVM release every week, builds `clang-format` using its own pipeline, and makes a **pull request**. All processes are run automatically. If you are interested in build process, take a look at [`.github/workflows/llvm-build-bump-pr.yml`](/.github/workflows/llvm-build-bump-pr.yml) |
| 12 | + |
| 13 | +## Why I started this project |
| 14 | + |
| 15 | +['angular/clang-format'](https://github.com/angular/clang-format) is no longer maintained. (See [#79](https://github.com/angular/clang-format/issues/79) [#82](https://github.com/angular/clang-format/issues/82) [#83](https://github.com/angular/clang-format/pull/83)) Nevertheless, new versions of `clang-format` continue to be released. Bugs are fixed, and new features are added. However, using `clang-format` directly in a Node.js environment without any support can be somewhat cumbersome. So I decided to make a **new**, **maintained** one. |
| 16 | + |
| 17 | +Note that some feautures from 'angular/clang-format' are not included in this package. Specifically `check-clang-format` and `git-clang-format` are not used. There are a few reasons for this. Both commands **rely on Python**, so if you haven't installed Python, they cannot be executed. Many people would prefer if this package worked without dependencies beyond Node.js. **So, this package relies only on Node.js.** See the [Migration](#migration-from-angularclang-format) for alternative methods to `check-clang-format` and `git-clang-format`. |
| 18 | + |
| 19 | +## Supported OS platforms and architectures |
| 20 | + |
| 21 | +It supports **ALL** [**Tier1**](https://github.com/nodejs/node/blob/main/BUILDING.md#strategy) and some [**Tier2**](https://github.com/nodejs/node/blob/main/BUILDING.md#strategy) platforms of Node.js. *Note that the functionality cannot be guaranteed on platforms which is not mentioned below*. |
| 22 | + |
| 23 | +(To see the full list of platforms supported by Node.js, click [here](<https://github.com/nodejs/node/blob/main/BUILDING.md#platform-list>).) |
| 24 | + |
| 25 | +<br> | Operating System | Architectures | Versions | Support Type | |
| 26 | +---- | ---------------- | ---------------- | --------------------------------- | ------------ | |
| 27 | +1 | macOS | arm64 | >= 11.0 | Tier 1 | |
| 28 | +2 | macOS | x64 | >= 11.0 | Tier 1 | |
| 29 | +3 | GNU/Linux | armv7 | kernel >= 4.18, glibc >= 2.28 | Tier 1 | |
| 30 | +4 | GNU/Linux | arm64 | kernel >= 4.18, glibc >= 2.28 | Tier 1 | |
| 31 | +5 | GNU/Linux | ppc64le >=power8 | kernel >= 4.18, glibc >= 2.28 | Tier 2 | |
| 32 | +6 | GNU/Linux | s390x | kernel >= 4.18, glibc >= 2.28 | Tier 2 | |
| 33 | +7 | GNU/Linux | x64 | kernel >= 4.18, glibc >= 2.28 | Tier 1 | |
| 34 | +8 | Windows | x64 | >= Windows 10/Server 2016 | Tier 1 | |
| 35 | + |
| 36 | +> [!TIP] |
| 37 | +> |
| 38 | +> 1. If your platform isn't yet supported, you can build the `clang-format` native binary from the latest upstream clang sources. Refer to [`docs/llvm-build-linux.sh`](/docs/llvm-build-linux.sh) and [`docs/llvm-build-linux-x64.yml`](/docs/llvm-build-linux-x64.yml) for the Linux build scripts for **Shell** and **GitHub Actions**, respectively. |
| 39 | +> |
| 40 | +> 1. Or you can download `clang-format` native binary from [LLVM release assets](https://github.com/llvm/llvm-project/releases) that match your operating system platform and architecture like the lists below. |
| 41 | +> |
| 42 | +> - `clang+llvm-18.1.7-aarch64-linux-gnu.tar.xz` |
| 43 | +> - `clang+llvm-18.1.7-armv7a-linux-gnueabihf.tar.gz` |
| 44 | +> - `clang+llvm-18.1.7-powerpc64-ibm-aix-7.2.tar.xz` |
| 45 | +> - `clang+llvm-18.1.7-x86_64-pc-windows-msvc.tar.xz` |
| 46 | +> - `and more...` |
| 47 | +
|
| 48 | +## Installation |
| 49 | + |
| 50 | +### global |
| 51 | + |
| 52 | +```bash |
| 53 | +npm install -g clang-format-node |
| 54 | +``` |
| 55 | + |
| 56 | +```bash |
| 57 | +yarn global add clang-format-node |
| 58 | +``` |
| 59 | + |
| 60 | +### local(devDependencies) |
| 61 | + |
| 62 | +```bash |
| 63 | +npm install --save-dev clang-format-node |
| 64 | +``` |
| 65 | + |
| 66 | +```bash |
| 67 | +yarn add --dev clang-format-node |
| 68 | +``` |
| 69 | + |
| 70 | +## Usages |
| 71 | + |
| 72 | +If you want to learn more about `clang-format` itself, see the [`clang-format style options`](https://clang.llvm.org/docs/ClangFormatStyleOptions.html). |
| 73 | + |
| 74 | +> [!TIP] |
| 75 | +> |
| 76 | +> `clang-format` can take multiple files as arguments. |
| 77 | +> |
| 78 | +> ```bash |
| 79 | +> npx clang-format -n -Werror file1.cpp file2.cpp src/file3.cpp |
| 80 | +> ``` |
| 81 | +
|
| 82 | +### Basic |
| 83 | +
|
| 84 | +#### Global |
| 85 | +
|
| 86 | +```bash |
| 87 | +clang-format [options] [@<file>] [<file> ...] |
| 88 | +``` |
| 89 | +
|
| 90 | +#### Local |
| 91 | + |
| 92 | +Use `npx` to run a locally installed package. |
| 93 | + |
| 94 | +```bash |
| 95 | +npx clang-format [options] [@<file>] [<file> ...] |
| 96 | +``` |
| 97 | + |
| 98 | +#### Frequently used commands |
| 99 | + |
| 100 | +1. `--version`: Check the version of `clang-format`. |
| 101 | + |
| 102 | + ``` bash |
| 103 | + npx clang-format --version |
| 104 | + ``` |
| 105 | + |
| 106 | + Output example |
| 107 | + |
| 108 | + ```bash |
| 109 | + clang-format version 18.1.8 (https://github.com/llvm/llvm-project 3b5b5c1ec4a3095ab096dd780e84d7ab81f3d7ff) |
| 110 | + ``` |
| 111 | + |
| 112 | + - `https://github.com/llvm/llvm-project`: Git repository URL for the LLVM project, which includes Clang. |
| 113 | + - `3b5b5c1ec4a3095ab096dd780e84d7ab81f3d7ff`: The commit hash of the Git repository where the source code for that version is stored. This hash allows you to precisely trace which source code version was used to generate `clang-format`. |
| 114 | + |
| 115 | +1. `--help`: Help view additional options. |
| 116 | + |
| 117 | + ```bash |
| 118 | + npx clang-format --help |
| 119 | + ``` |
| 120 | + |
| 121 | +1. `--dry-run` or `-n`: Makes an **WARNING** when `example.cpp` is not correctly formatted. |
| 122 | + |
| 123 | + `--dry-run` and `-n` options are equivalent. |
| 124 | + |
| 125 | + ```bash |
| 126 | + npx clang-format --dry-run example.cpp |
| 127 | + ``` |
| 128 | + |
| 129 | + ```bash |
| 130 | + npx clang-format -n example.cpp |
| 131 | + ``` |
| 132 | + |
| 133 | +1. `-Werror --dry-run` or `-Werror -n`: Makes an **ERROR** when `example.cpp` is not correctly formatted. |
| 134 | + |
| 135 | + > Similar to `eslint` or `prettier --check` commands. |
| 136 | + |
| 137 | + `--dry-run` and `-n` options are equivalent. |
| 138 | + |
| 139 | + ```bash |
| 140 | + npx clang-format -Werror --dry-run example.cpp |
| 141 | + ``` |
| 142 | + |
| 143 | + ```bash |
| 144 | + npx clang-format -Werror -n example.cpp |
| 145 | + ``` |
| 146 | + |
| 147 | +1. `-i`: Automatically fix unformatted files. |
| 148 | + |
| 149 | + > Similar to `eslint --fix` or `prettier --write` commands. |
| 150 | + |
| 151 | + ```bash |
| 152 | + npx clang-format -i example.cpp |
| 153 | + ``` |
| 154 | + |
| 155 | +### Glob patterns |
| 156 | + |
| 157 | +Unfortunately, there is no way to apply `clang-format` recursively. `*.cpp` will only match files in the current directory, not subdirectories. Even `**/*` doesn't work. |
| 158 | +
|
| 159 | +**So, you need to use the `find` command in Linux.** If you are a Windows user, use ***git bash***. then you can use the `find` command. The `find` command recursively searches through directories. |
| 160 | +
|
| 161 | +It is simple but can produce an error if the [**Argument list is too long**](https://stackoverflow.com/questions/11289551/argument-list-too-long-error-for-rm-cp-mv-commands). In that case, use `xargs` |
| 162 | +
|
| 163 | +#### Basic |
| 164 | +
|
| 165 | +To recursively search for all `.cpp` files in the current directory, use: |
| 166 | +
|
| 167 | +```bash |
| 168 | +npx clang-format $(find . -name "*.cpp") |
| 169 | +``` |
| 170 | +
|
| 171 | +If the argument list is too long, use `xargs`. And if file names contain spaces or special characters, use `-print0` and `-0` options. `-print0` makes `find` output file names separated by null characters (`\0`), and `-0` tells `xargs` to correctly handle these null-separated file names. |
| 172 | +
|
| 173 | +```bash |
| 174 | +find . -name "*.cpp" -print0 | xargs -0 npx clang-format |
| 175 | +``` |
| 176 | +
|
| 177 | +#### With regular expressions |
| 178 | +
|
| 179 | +To recursively search for all `.cpp` and `.h` files in the current directory using a regular expression, use: |
| 180 | +
|
| 181 | +```bash |
| 182 | +npx clang-format $(find . -regex ".*\.\(cpp\|h\)") |
| 183 | +``` |
| 184 | +
|
| 185 | +#### With negation patterns |
| 186 | +
|
| 187 | +To exclude `excluded_file.cpp` from the `.cpp` files, use: |
| 188 | +
|
| 189 | +```bash |
| 190 | +npx clang-format $(find . -name "*.cpp" ! -name "excluded_file.cpp") |
| 191 | +``` |
| 192 | +
|
| 193 | +### [`.clang-format-ignore`](https://clang.llvm.org/docs/ClangFormat.html#clang-format-ignore) |
| 194 | +
|
| 195 | +You can create `.clang-format-ignore` files to make `clang-format` ignore certain files. A `.clang-format-ignore` file consists of patterns of file path names. It has the following format: |
| 196 | +
|
| 197 | +- A blank line is skipped. |
| 198 | +- Leading and trailing spaces of a line are trimmed. |
| 199 | +- A line starting with a hash (`#`) is a comment. |
| 200 | +- A non-comment line is a single pattern. |
| 201 | +- The slash (`/`) is used as the directory separator. |
| 202 | +- A pattern is relative to the directory of the `.clang-format-ignore` file (or the root directory if the pattern starts with a slash). Patterns containing drive names (e.g. `C:`) are not supported. |
| 203 | +- Patterns follow the rules specified in [**POSIX 2.13.1, 2.13.2, and Rule 1 of 2.13.3.**](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_13) |
| 204 | +- A pattern is negated if it starts with a bang (`!`). |
| 205 | +
|
| 206 | +To match all files in a directory, use e.g. `foo/bar/*`. To match all files in the directory of the `.clang-format-ignore` file, use `*`. Multiple `.clang-format-ignore` files are supported similar to the `.clang-format` files, with a lower directory level file voiding the higher level ones. |
| 207 | +
|
| 208 | +### Use with `husky` and `lint-staged` |
| 209 | +
|
| 210 | +Ensuring that changes to your code are properly formatted is an important part of your development workflow. Use `husky` and `lint-staged` for your continuous integration process. |
| 211 | +
|
| 212 | +#### `husky` (v8.x) |
| 213 | +
|
| 214 | +```bash |
| 215 | +# .husky/pre-commit |
| 216 | +
|
| 217 | +npx lint-staged |
| 218 | +``` |
| 219 | +
|
| 220 | +#### `lint-staged` (v15.x) |
| 221 | +
|
| 222 | +1. Check |
| 223 | +
|
| 224 | + ```jsonc |
| 225 | + /* package.json */ |
| 226 | +
|
| 227 | + { |
| 228 | + // ... |
| 229 | + "lint-staged": { |
| 230 | + "*.{c,cpp,h}": "npx clang-format -Werror -n", |
| 231 | + } |
| 232 | + // ... |
| 233 | + } |
| 234 | + ``` |
| 235 | +
|
| 236 | +1. Fix |
| 237 | +
|
| 238 | + ```jsonc |
| 239 | + /* package.json */ |
| 240 | +
|
| 241 | + { |
| 242 | + // ... |
| 243 | + "lint-staged": { |
| 244 | + "*.{c,cpp,h}": "npx clang-format -i", |
| 245 | + } |
| 246 | + // ... |
| 247 | + } |
| 248 | + ``` |
| 249 | +
|
| 250 | +> [!TIP] |
| 251 | +> |
| 252 | +> If `example1.cpp` and `example2.c` are staged, then `npx clang-format -Werror -n example1.cpp example2.c` will be excuted. |
| 253 | +
|
| 254 | +## Migration from 'angular/clang-format' |
| 255 | +
|
| 256 | +### `check-clang-format` |
| 257 | +
|
| 258 | +This package only uses native `clang-format` features to check formatting. The following commands will produce an error if the target files are not correctly formatted. So use them with `husky` and `lint-staged`. (`--dry-run` and `-n` options are equivalent.) |
| 259 | +
|
| 260 | +```bash |
| 261 | +npx clang-format -Werror --dry-run example.cpp |
| 262 | +``` |
| 263 | +
|
| 264 | +```bash |
| 265 | +npx clang-format -Werror -n example.cpp |
| 266 | +``` |
| 267 | +
|
| 268 | +### `git-clang-format` |
| 269 | +
|
| 270 | +Use [`husky`](https://typicode.github.io/husky/) and [`lint-staged`](https://github.com/lint-staged/lint-staged) for the `pre-commit` hook instead. See [Use with `husky` and `lint-staged`](#use-with-husky-and-lint-staged) for details. |
| 271 | +
|
| 272 | +## Contributing |
| 273 | +
|
| 274 | +Thanks for having attention to this package.🙇♂️ Issues and PRs are always welcome.🎉 |
| 275 | +
|
| 276 | +I recommend you to read the guides on [LLVM and clang-format mentioned in issues tab](https://github.com/lumirlumir/npm-clang-format-node/issues/new/choose) before contributing. |
| 277 | +
|
| 278 | +### Installation |
| 279 | +
|
| 280 | +1. Fork it. |
| 281 | +
|
| 282 | +1. Clone it to your local directory. ([Git](https://git-scm.com/downloads) is required.) |
| 283 | +
|
| 284 | + ```bash |
| 285 | + git clone https://github.com/lumirlumir/npm-clang-format-node.git |
| 286 | + ``` |
| 287 | +
|
| 288 | +1. Move to the `npm-clang-format-node` directory. |
| 289 | +
|
| 290 | + ```bash |
| 291 | + cd npm-clang-format-node |
| 292 | + ``` |
| 293 | +
|
| 294 | +1. Install npm packages. ([Node.js](https://nodejs.org/en) is required.) |
| 295 | +
|
| 296 | + ```bash |
| 297 | + npm install |
| 298 | + ``` |
| 299 | +
|
| 300 | +1. Edit codes. |
| 301 | +
|
| 302 | +1. Create `my-branch` branch. |
| 303 | +
|
| 304 | + ```bash |
| 305 | + git switch -c my-branch |
| 306 | + ``` |
| 307 | +
|
| 308 | +1. Commit your changes. (`husky` and `lint-staged` will lint and test your changed files!) |
| 309 | +
|
| 310 | + ```bash |
| 311 | + git commit -am "commit type: title" |
| 312 | + ``` |
| 313 | +
|
| 314 | +1. Push them to your remote branch. |
| 315 | +
|
| 316 | +1. Submit a pull request.👍 |
| 317 | +
|
| 318 | +### About `os.platform()` and `os.arch()` in Node.js |
| 319 | +
|
| 320 | +#### [os.platform()](https://nodejs.org/docs/v20.17.0/api/os.html#osplatform) |
| 321 | +
|
| 322 | +The return value is equivalent to `process.platform`. |
| 323 | +
|
| 324 | +OS | return value of `os.platform()` | |
| 325 | +------- | ---------------------------------- | |
| 326 | +macOS | `darwin` | |
| 327 | +Linux | `linux` | |
| 328 | +Windows | `win32` | |
| 329 | +
|
| 330 | +#### [os.arch()](https://nodejs.org/docs/v20.17.0/api/os.html#osarch) |
| 331 | +
|
| 332 | +The return value is equivalent to `process.arch`. |
| 333 | +
|
| 334 | +Architecture | return value of `os.arch()` | LLVM | Docker Platform | Docker Ubuntu Image | |
| 335 | +------------------ | ------------------------------ | --------- | --------------- | ------------------- | |
| 336 | +arm(armv7, armv7l) | `arm` | `ARM` | `arm/v7` | `arm32v7` | |
| 337 | +arm64 | `arm64` | `AArch64` | `arm64/v8` | `arm64v8` | |
| 338 | +ppc64le[^1] | `ppc64` | `PowerPC` | `ppc64le` | `ppc64le` | |
| 339 | +s390x | `s390x` | `SystemZ` | `s390x` | `s390x` | |
| 340 | +x64 | `x64` | `X86` | `amd64` | `amd64` | |
| 341 | +
|
| 342 | +[^1]: `le` stands for little-endian, but the `os.arch()` function does not distinguish between endianness and returns a single value. |
| 343 | +
|
| 344 | +### Build process |
| 345 | +
|
| 346 | +Some packages for **cross-compilation** have been deprecated, making it difficult to make build processes directly, so **cross-compilation** is not used. |
| 347 | +
|
| 348 | +**Linux** is built using QEMU and Docker. **macOS** and **Windows** are built using the `macos-13`, `macos-14`, and `windows-latest` runners on GitHub Actions. |
| 349 | +
|
| 350 | +## Versioning |
| 351 | +
|
| 352 | +This project adheres to [Semantic Versioning](https://semver.org/). |
| 353 | +
|
| 354 | +[LLVM versions](https://github.com/llvm/llvm-project/releases) are managed as dependencies, so upgrading the LLVM version is treated as a 'patch'. Additionally, the release title includes the LLVM version, like `v1.0.0 (llvmorg-18.1.8)`. |
| 355 | +
|
| 356 | +See [`.clang-format-version`](/.clang-format-version) to check the exact current LLVM version. |
| 357 | +
|
| 358 | +## Change Log |
| 359 | +
|
| 360 | +See [`CHANGELOG.md`](/CHANGELOG.md) |
| 361 | +
|
| 362 | +## License |
| 363 | +
|
| 364 | +[MIT](/LICENSE) under [LLVM Apache License 2.0](https://github.com/llvm/llvm-project/blob/main/LICENSE.TXT) |
0 commit comments