Thanks to visit codestin.com
Credit goes to github.com

Skip to content

bmarwell/jfmt

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

jfmt

What is jfmt?

jfmt is an opinionated command-line Java formatter with a sane default configuration. It is built on top of the Eclipse JDT formatter engine โ€” but unlike the Eclipse IDE, jfmt runs completely standalone as a native binary or JAR.

Itโ€™s designed for developers who want:

  • predictable, idempotent formatting;

  • a fast, zero-configuration CLI tool;

  • an easy way to enforce consistent formatting locally and in CI.

In short: Run it locally before you commit. Let CI check it again. jfmt also normalizes all source files to UTF-8 encoding and Unix line endings (\n) to ensure consistent formatting across operating systems and editors. Thatโ€™s all you need.

Quick Start

  1. Install or build jfmt

    You can run jfmt as a native binary or as a portable JAR (see Compiling).

  2. Format your code locally

    # Format and rewrite all Java files
    jfmt write src/
    
    # Or just check which files need formatting
    jfmt list --all .
    
    # Show a diff of what would change
    jfmt diff --all .
  3. Workflow Summary

    Action

    Who

    Purpose

    jfmt write

    Developer

    Format files locally before committing

    jfmt diff

    CI pipeline

    Verify formatting consistency

    jfmt print

    Tooling

    Print the correctly formatted output for the given file

    jfmt list

    Developer or CI

    List unformatted files

Why not Spotless or Checkstyle?

Spotless and Checkstyle are Maven or Gradle plugins that integrate deeply into build lifecycles. jfmt, on the other hand, is a self-contained command-line tool designed to be lightweight and fast โ€” closer to gofmt or rustfmt.

Tool

Integration

Configuration

Typical Use

Spotless

Maven/Gradle plugin

Customizable

In build lifecycle

Checkstyle

Maven/Gradle plugin

Highly customizable

Style rule enforcement

jfmt

CLI tool / native binary

No config needed

Pre-commit & CI enforcement

jfmt complements these tools: you can use it alongside Checkstyle or in projects where build tooling is minimal.

Goals

  • ๐Ÿšซโ€‹โš™๏ธ No config file by default

  • ๐Ÿชž idempotent operation

    • do not do other/additional changes upon subsequent reformat operations

  • ๐Ÿ“ reading and writing

    • allows output on stdout or overwriting the input files

  • ๐Ÿšฏ no AST loss

    • do not swallow comments, intentional empty lines and line breaks, etc.

  • ๐Ÿš€ FAST

    • The project aims to create a GraalVM-based binary for most architectures, so it can operate almost as fast as gofmt or similar tools.

  • ๐Ÿง  consistent import ordering

    • automatically groups and sorts imports:

      1. all static imports first, followed by

      2. all other imports.

Synopsis

Usage: jfmt [-hlV] [COMMAND]
A command-line tool to format Java source code using JDT.
  -h, --help      Show this help message and exit.
  -l, --list      Just report the name of the files which are not indented correctly.
  -V, --version   Print version information and exit.
Commands:
  list        Just list files which are not formatted correctly without printing a diff or writing changes.
  write, fix  Write the formatted source code back to the file(s).
              If not given, the non-indented file(s) will be printed to stdout.
              Only the first file is printed, unless -a is also given.
  print       Print the correctly formatted output for the given file(s).
              Stops on the first file unless -a (--all) is given.
              In this case, the file name is printed before each output.
  diff        Output in diff format. Normal diff is used unless -u is also given.

list command

Usage: jfmt list [-ahV] [--no-color] [--config=<config>]
                 [--config-file=<configFile>] [--import-order=<importOrder>]
                 [--import-order-file=<importOrderFile>] <filesOrDirectories>...
Just list files which are not formatted correctly without printing a diff or
writing changes.
      <filesOrDirectories>...
                          Files or directory to scan and to format.
  -a, --all               Report all errors, not just the first one.
      --config=<config>   Named config. Default: builtin.
                          Available configs: builtin, equalsverifier
      --config-file=<configFile>
                          Path to a config file. If unset (default), the named
                            config (--config) will be used.
  -h, --help              Show this help message and exit.
      --import-order=<importOrder>
                          Named import order. Default: defaultorder. Available:
                            defaultorder, equalsverifier, google, eclipse,
                            intellij, enterprise
      --import-order-file=<importOrderFile>
                          Path to an import-order properties file. If set,
                            overrides --import-order.
      --no-color, --no-colour
                          Force no colored output, even if the terminal
                            supports it.
  -V, --version           Print version information and exit.

write/fix command

Usage: jfmt write [-ahV] [--no-color] [--config=<config>]
                  [--config-file=<configFile>] [--import-order=<importOrder>]
                  [--import-order-file=<importOrderFile>]
                  <filesOrDirectories>...
Write the formatted source code back to the file(s).
If not given, the non-indented file(s) will be printed to stdout.
Only the first file is printed, unless -e is also given.
      <filesOrDirectories>...
                          Files or directory to scan and to format.
  -a, --all               Report all errors, not just the first one.
      --config=<config>   Named config. Default: builtin.
                          Available configs: builtin, equalsverifier
      --config-file=<configFile>
                          Path to a config file. If unset (default), the named
                            config (--config) will be used.
  -h, --help              Show this help message and exit.
      --import-order=<importOrder>
                          Named import order. Default: defaultorder. Available:
                            defaultorder, equalsverifier, google, eclipse,
                            intellij, enterprise
      --import-order-file=<importOrderFile>
                          Path to an import-order properties file. If set,
                            overrides --import-order.
      --no-color, --no-colour
                          Force no colored output, even if the terminal
                            supports it.
  -V, --version           Print version information and exit.

diff command

Usage: jfmt diff [-ahuV] [--no-color] [--config=<config>]
                 [--config-file=<configFile>] [--context=<context>]
                 [--import-order=<importOrder>]
                 [--import-order-file=<importOrderFile>] <filesOrDirectories>...
Output in diff format. Normal diff is used unless -u is also given.
      <filesOrDirectories>...
                            Files or directory to scan and to format.
  -a, --all                 Report all errors, not just the first one.
      --config=<config>     Named config. Default: builtin.
                            Available configs: builtin, equalsverifier
      --config-file=<configFile>
                            Path to a config file. If unset (default), the
                              named config (--config) will be used.
      --context=<context>   Number of context lines when in unified diff mode
                              (-u). Defaults to 3.
  -h, --help                Show this help message and exit.
      --import-order=<importOrder>
                            Named import order. Default: defaultorder.
                              Available: defaultorder, equalsverifier, google,
                              eclipse, intellij, enterprise
      --import-order-file=<importOrderFile>
                            Path to an import-order properties file. If set,
                              overrides --import-order.
      --no-color, --no-colour
                            Force no colored output, even if the terminal
                              supports it.
  -u, --unified             Output diff in unified format.
                            Deactivated by default.
  -V, --version             Print version information and exit.

Implementation

  • ๐Ÿ’ป Uses PicoCLI for command line parsing

  • ๐Ÿ“ Uses Eclipse JDT for formatting

  • โš™๏ธ Uses GraalVM for creating native, statically linked stand-alone binaries

  • ๐ŸŒ Automatically converts non-UTF-8 inputs to UTF-8 and replaces mixed or Windows line endings (\r\n) with Unix (\n) endings before formatting.

  • ๐Ÿงฉ Sorts import statements according to a default two-group scheme
    (0=#, 1= in Eclipse JDT syntax) โ€” static imports first, then all others.

Roadmap

Features:

  • โœ“ basic commands implemented

  • โœ“ basic tests implemented

  • โœ“ CI/CD implemented

  • [X] Formatting of import statements (#34)

  • โ Refinement of default formatting rules

Distribution:

  • โ native binaries for Linux, Windows, MacOS

  • โ package for Homebrew

  • โ package for Scoop

  • โ package for apt/dpkg

  • โ package for rpm/yum/dnf

  • โ package for Chocolatey

  • โ package for winget

  • โ package for SDKMAN

Compiling

  • Use Maven 4 or the Maven wrapper

  • JDK 25 required

You can use mvn verify to create a tested and verified runnable application archive using jreleaser. You can find and execute the archive in the path cli/target/jreleaser/assemble/jfmt/java-archive. More info about these kinds of archives can be found in my blog post: Creating an App Distribution with Apache Maven and JReleaser.

Please note that Java 25 or better needs to be installed on your system and must be in the PATH environment variable.

Native Binaries

Why use native binaries? Because they are fast, small, and do not require a JRE to be installed on the system.

Here is a simple comparison of this project running with both options:

Native Binary
โฏ time ./cli/target/jfmt-0.1.0-SNAPSHOT list --all .
Processing file: ./cli/src/main/java/io/github/bmarwell/jfmt/nio/PathUtils.java
Processing file: ./cli/src/test/resources/diff/SomeRecord.java
Not formatted correctly: ./cli/src/test/resources/diff/SomeRecord.java
Processing file: ./integration-tests/jreleaser-builtin/src/test/resources/correctly_formatted/CorrectlyFormatted.java
Processing file: ./integration-tests/jreleaser-builtin/src/test/resources/incorrectly_formatted/SomeRecord.java
Not formatted correctly: ./integration-tests/jreleaser-builtin/src/test/resources/incorrectly_formatted/SomeRecord.java
Processing file: ./integration-tests/jreleaser-builtin/src/test/java/io/github/bmarwell/jfmt/its/jreleaser/builtin/WriteCommandIT.java
Processing file: ./cli/src/test/java/io/github/bmarwell/jfmt/JFmtTest.java
Processing file: ./integration-tests/jreleaser-builtin/src/test/resources/write/t001/SomeRecord.java
Not formatted correctly: ./integration-tests/jreleaser-builtin/src/test/resources/write/t001/SomeRecord.java
[...]
jfmt list --all .  0,03s user 0,02s system 95% cpu 0,057 total
JAR Distribution
โฏ time ./cli/target/jreleaser/assemble/jfmt/java-archive/work/jfmt-0.1.0-SNAPSHOT/bin/jfmt list --all .
Processing file: ./cli/src/main/java/io/github/bmarwell/jfmt/nio/PathUtils.java
Processing file: ./cli/src/test/resources/diff/SomeRecord.java
Not formatted correctly: ./cli/src/test/resources/diff/SomeRecord.java
Processing file: ./integration-tests/jreleaser-builtin/src/test/resources/correctly_formatted/CorrectlyFormatted.java
Processing file: ./integration-tests/jreleaser-builtin/src/test/resources/incorrectly_formatted/SomeRecord.java
Not formatted correctly: ./integration-tests/jreleaser-builtin/src/test/resources/incorrectly_formatted/SomeRecord.java
[...]
jfmt list --all .  2,29s user 0,13s system 281% cpu 0,860 total
----

As you can see, the native binary is about three times faster than the JAR distribution.

Compiling native binaries on linux

By default, a profile dist-linux is activated, which will create a native binary for Linux x86_64 using musl. If you do not have musl and libz.a installed, you can use the profile '-Pnative,!dist-linux' to create a native binary using glibc instead.

Further reading

FAQ

Why not call it javafmt?

The JAVAยฎ brand name is a registered trademark of Oracle, and except in limited circumstances, may not be used without a written license from Oracle. The โ€œJavaโ€ name may be used in product, service, and event names without permission only in specific, limited ways.

โ€ฆ also, I wanted to keep the book open for the OpenJDK community to adopt an official tool with this name.

How opinionated is it?

While there is a default rule, you can use other named rules or even foreign config files created by Eclipse IDE as well. But I encourage everyone to use the default configuration โ€“ and letโ€™s discuss how well it is defined in the GitHub discussions and the issue tracker.

Contributing & Releasing

For information about the release process, including early access builds and official releases, see RELEASING.adoc.

Contributors

See CONTRIBUTORS.adoc for a list of all contributors.

License

This work is dual-licensed under Apache 2.0 and EUPL 1.2. You may choose either license when using this work.

SPDX-License-Identifier: Apache-2.0 OR EUPL-1.2

About

jfmt is an opinionated java source code formatter for the command line

Topics

Resources

License

Unknown and 2 other licenses found

Licenses found

Unknown
LICENSE
Apache-2.0
LICENSE.Apache-2.0
EUPL-1.2
LICENSE.EUPL-1.2

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 10

Languages