-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Brian McGee <[email protected]>
- Loading branch information
1 parent
12db876
commit 9c13b18
Showing
10 changed files
with
665 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
# About the project | ||
|
||
`treefmt` is a formatting tool that saves you time: it provides developers with a universal way to trigger all | ||
formatters needed for the project in one place. | ||
|
||
## Background | ||
|
||
Typically, each project has its own code standards enforced by the project's owner. Any code contributions must match | ||
that given standard, i.e. be formatted in a specific manner. | ||
|
||
At first glance, the task of code formatting may seem trivial: the formatter can be automatically triggered when you | ||
save a file in your IDE. Indeed, formatting doesn't take much effort if you're working on a single project long term: | ||
setting up the formatters in your IDE won't take much of your time, and then you're ready to go. | ||
|
||
Contrary to that, if you're working on multiple projects at the same time, you may have to update your formatter | ||
configs in the IDE each time you switch between the projects. This is because formatter settings aren't | ||
project-specific --- they are set up globally for all projects. | ||
|
||
Alternatively, you can trigger formatters manually, one-by-one or in a script. Actually, for bigger projects, it's | ||
common to have a script that runs over your project's directories and calls formatters consequently. But it takes time | ||
to iterate through all the files. | ||
|
||
All the solutions take up a significant amount of time which a developer could spend doing the actual work. They also | ||
require you to remember which formatters and options are used by each project you are working on. | ||
|
||
`treefmt` solves these issues. | ||
|
||
## Why treefmt? | ||
|
||
`treefmt`'s configuration is project-specific, so you don't need to re-configure formatters each time you switch | ||
between projects, like you have to when working with formatters in the IDE. | ||
|
||
Contrary to calling formatters from the command line, there's no need to remember all the specific formatters required | ||
for each project. Once you set up the config, you can run the tool in any of your project's folders without any | ||
additional flags or options. | ||
|
||
Typically, formatters have different ways to say there was a specific error. With `treefmt`, you get a standardized | ||
output which is easier to understand than the variegated outputs of different formatters, so it takes less time to | ||
grasp what's wrong. | ||
|
||
In addition, `treefmt` works faster than the custom script solution because the changed files are cached and the | ||
formatters run only against them. Moreover, formatters are run in parallel, which makes the tool even faster. | ||
|
||
The difference may not be significant for smaller projects, but it gets quite visible as the project grows. For | ||
instance, take the caching optimization. | ||
|
||
It takes about 23 seconds to traverse a project of 40,559 files and no changes without caching: | ||
|
||
```console | ||
traversed 41273 files | ||
emitted 41273 files for processing | ||
formatted 34111 files (14338 changed) in 23.679s | ||
``` | ||
|
||
...while it takes **239 milliseconds** to traverse the same project with caching: | ||
|
||
```console | ||
traversed 41273 files | ||
emitted 0 files for processing | ||
formatted 0 files (0 changed) in 239ms | ||
``` | ||
|
||
The tool can be invoked manually or integrated into your CI. There's currently no integration with IDEs, but the feature is coming soon. | ||
|
||
## What we still need help with | ||
|
||
- **IDE integration:** Most of developers are used to formatting a file upon save in the IDE. So far, you can't use `treefmt` for this purpose, but we're working on it 😀 | ||
- **Pre-commit hook:** It's good to have your code checked for adherence to the project's standards before commit. `treefmt` pre-commit hook won't let you commit if you have formatting issues. | ||
|
||
As a next step, learn how to [install] and [run] `treefmt`. | ||
|
||
[install]: install.md | ||
[run]: usage.md |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
--- | ||
outline: deep | ||
--- | ||
|
||
# Configure Treefmt | ||
|
||
The `treefmt.toml` configuration file consists of a mixture of global options and formatter sections: | ||
|
||
```toml | ||
[global] | ||
excludes = ["*.md", "*.dat"] | ||
|
||
[formatter.elm] | ||
command = "elm-format" | ||
options = ["--yes"] | ||
includes = ["*.elm"] | ||
|
||
[formatter.go] | ||
command = "gofmt" | ||
options = ["-w"] | ||
includes = ["*.go"] | ||
|
||
[formatter.python] | ||
command = "black" | ||
includes = ["*.py"] | ||
|
||
# use the priority field to control the order of execution | ||
|
||
# run shellcheck first | ||
[formatter.shellcheck] | ||
command = "shellcheck" | ||
includes = ["*.sh"] | ||
priority = 0 # default is 0, but we set it here for clarity | ||
|
||
# shfmt second | ||
[formatter.shfmt] | ||
command = "shfmt" | ||
options = ["-s", "-w"] | ||
includes = ["*.sh"] | ||
priority = 1 | ||
``` | ||
|
||
## Global Options | ||
|
||
- `excludes` - an optional list of [glob patterns](#glob-patterns-format) used to exclude certain files from all formatters. | ||
|
||
## Formatter Options | ||
|
||
- `command` - the command to invoke when applying the formatter. | ||
- `options` - an optional list of args to be passed to `command`. | ||
- `includes` - a list of [glob patterns](#glob-patterns-format) used to determine whether the formatter should be applied against a given path. | ||
- `excludes` - an optional list of [glob patterns](#glob-patterns-format) used to exclude certain files from this formatter. | ||
- `priority` - influences the order of execution. Greater precedence is given to lower numbers, with the default being `0`. | ||
|
||
## Same file, multiple formatters? | ||
|
||
For each file, `treefmt` determines a list of formatters based on the configured `includes` / `excludes` rules. This list is | ||
then sorted, first by priority (lower the value, higher the precedence) and secondly by formatter name (lexicographically). | ||
|
||
The resultant sequence of formatters is used to create a batch key, and similarly matched files get added to that batch | ||
until it is full, at which point the files are passed to each formatter in turn. | ||
|
||
This means that `treefmt` **guarantees only one formatter will be operating on a given file at any point in time**. | ||
Another consequence is that formatting is deterministic for a given file and a given `treefmt` configuration. | ||
|
||
By setting the priority fields appropriately, you can control the order in which those formatters are applied for any | ||
files they _both happen to match on_. | ||
|
||
## Glob patterns format | ||
|
||
This is a variant of the Unix glob pattern. It supports all the usual | ||
selectors such as `*` and `?`. | ||
|
||
### Examples | ||
|
||
- `*.go` - match all files in the project that end with a ".go" file extension. | ||
- `vendor/*` - match all files under the vendor folder, recursively. | ||
|
||
## Supported Formatters | ||
|
||
Any formatter that follows the [spec] is supported out of the box. | ||
|
||
Already 60+ formatters are supported. | ||
|
||
To find examples, take a look at <https://github.com/numtide/treefmt-nix/tree/main/examples>. | ||
|
||
If you are a Nix user, you might also like <https://github.com/numtide/treefmt-nix>, which uses Nix to pull in the right formatter package and seamlessly integrates both together. | ||
|
||
[spec]: formatter-spec.md |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
--- | ||
outline: deep | ||
--- | ||
|
||
# Contribution guidelines | ||
|
||
This file contains instructions that will help you make a contribution. | ||
|
||
## Licensing | ||
|
||
The `treefmt` binaries and this user guide are licensed under the [MIT license](https://github.com/numtide/treefmt/blob/main/LICENSE). | ||
|
||
## Before you contribute | ||
|
||
Here you can take a look at the [existing issues](https://github.com/numtide/treefmt/issues). Feel free to contribute, but make sure you have a | ||
[GitHub account](https://github.com/join) first :slightly_smiling_face:. | ||
|
||
If you're new to open source, please read GitHub's guide on [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/). It's a quick read, | ||
and it's a great way to introduce yourself to how things work behind the scenes in open-source projects. | ||
|
||
Before sending a pull request, make sure that you've read all the guidelines. If you don't understand something, please | ||
[state your question clearly in an issue](https://github.com/numtide/treefmt/issues/new) or ask the community on the [treefmt matrix server](https://matrix.to/#/#treefmt:numtide.com). | ||
|
||
## Creating an issue | ||
|
||
If you need to create an issue, make sure to clearly describe it, including: | ||
|
||
- The steps to reproduce it (if it's a bug) | ||
- The version of `treefmt` used | ||
|
||
The cache database is stored in a `.db` file in the `~/.cache/treefmt/eval-cache` directory. | ||
|
||
## Making changes | ||
|
||
If you want to introduce changes to the project, please follow these steps: | ||
|
||
- Fork the repository on GitHub | ||
- Create a branch on your fork. Don't commit directly to main | ||
- Add the necessary tests for your changes | ||
- Run `treefmt` in the source directory before you commit your changes | ||
- Push your changes to the branch in your repository fork | ||
- Submit a pull request to the original repository | ||
|
||
Make sure you based your commits on logical and atomic units! | ||
|
||
## Examples of git history | ||
|
||
<details> | ||
|
||
<summary>Git history that we want to have</summary> | ||
|
||
``` | ||
* e3ed88b (HEAD -> contribution-guide, upstream/main, origin/main, origin/HEAD, main) Merge pull request #470 from zimbatm/fix_lru_cache | ||
|\ | ||
| * 1ab7d9f Use rayon for multithreading command | ||
|/ | ||
* e9c5bb4 Merge pull request #468 from zimbatm/multithread | ||
|\ | ||
| * de2d6cf Add lint property for Formatter struct | ||
| * cd2ed17 Fix impl on Formatter get_command() function | ||
|/ | ||
* 028c344 Merge pull request #465 from rayon/0.15.0-release | ||
|\ | ||
| * 7b619d6 0.15.0 release | ||
|/ | ||
* acdf7df Merge pull request #463 from zimbatm/support-multi-part-namespaces | ||
``` | ||
|
||
</details> | ||
|
||
<details> | ||
|
||
<summary>Git history that we are <b>trying</b> to avoid</summary> | ||
|
||
``` | ||
* 4c8aca8 Merge pull request #120 from zimbatm/add-rayon | ||
|\ | ||
| * fc2b449 use rayon for engine now | ||
| * 2304683 add rayon config | ||
| * 5285bd3 bump base image to F30 | ||
* | 4d0fbe2 Merge pull request #114 from rizary/create_method_create_release | ||
|\ \ | ||
| * | 36a9396 test changed | ||
| * | 22f681d method create release for github created | ||
* | | 2ef4ea1 Merge pull request #119 from rizary/config.rs | ||
|\ \ \ | ||
| |/ / | ||
|/| | | ||
| * | 5f1b8f0 unused functions removed | ||
* | | a93c361 Merge pull request #117 from zimbatm/add-getreleases-to-abstract | ||
|\ \ \ | ||
| |/ / | ||
|/| | | ||
| * | 0a97236 add get_releses for Cargo | ||
| * | 55e4c57 add get_releases/get_release into engine.rs | ||
|/ / | ||
* | badeddd Merge pull request #101 from zimbatm/extreme-cachin | ||
``` | ||
|
||
</details> | ||
|
||
Additionally, it's always good to work on improving documentation and adding examples. | ||
|
||
Thank you for considering contributing to `treefmt`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# FAQ | ||
|
||
## How does treefmt function? | ||
|
||
`Treefmt` traverses all your project's folders, maps files to specific code formatters, and formats the code | ||
accordingly. Other tools also traverse the filesystem, but not necessarily starting from the root of the project. | ||
|
||
Contrary to other formatters, `treefmt` doesn't preview the changes before writing them to a file. If you want to view | ||
the changes, you can always check the diff in your version control (we assume that your project is checked into a | ||
version control system). | ||
|
||
You can also rely on version control if errors were introduced into your code as a result of disruptions in the | ||
formatter's work. | ||
|
||
## How is the cache organized? | ||
|
||
At the moment, the cache is a [BoltDB] database file in which file paths are mapped to `mtimes`. | ||
|
||
The file is located in: | ||
|
||
``` | ||
~/.cache/treefmt/eval-cache/<hash-of-the-treefmt.toml-path>.db | ||
``` | ||
|
||
At the end of each run, the database is updated with the last formatting time entries. In this way, we can | ||
compare the last change time of the file to the last formatting time, and figure out which files need re-formatting. | ||
|
||
[BoltDB]: https://github.com/etcd-io/bbolt |
Oops, something went wrong.