Liking cljdoc? Tell your friends :D

formatting-stack CircleCI

formatting-stack is a formatting/linting solution that can be integrated with:

  • your Component (or Integrant, or bare tools.namespace) system
    • for instantaneous performance
      • no cold-starts!
    • and precise understanding of your codebase
      • powered by Clojure's introspection capabilities (reified vars, namespaces), and occasionally eval
    • and a reasonable triggering frequency
      • so you don't format too frequently (format-on-save), or not frequently enough (git pre-commit hook)
  • Git status/branch information
    • for some performance gains (typically only added/changed files will be processed)
    • and also for gradual formatting
  • Anything you want
    • A vanilla repl, Lein task, CI workflow...

As of today, it is integrated with:

And it also bundles a few tiny linters of its own:

It is fully extensible: you can configure the bundled formatters, remove them, and/or add your own.

Whenever it's safe, each formatter/linter will make full use of your CPU's cores.

Linters' reports are presented under a unified format.

Smart code analysis

As mentioned, formatting-stack understands your codebase and its dependencies. It knows which vars in the project are macros. It also reads the metadata of all function/macro vars.

It also associates :style metadata to your project's vars, in a clean manner, when needed.

Armed with those powers, we can do two nifty things:

  • Inform cljfmt of indentation through metadata + config, using the CIDER indent spec format (by default, using an heuristic for cider->cljfmt format translation) or the cljfmt format (as a fallback).
    • Recommendation: use metadata for your own code, use config for third-party code (that may be awaiting for a pull request)
  • Inform CIDER of indentation rules through config
    • CIDER understands either metadata or emacs-specific rules, but not config

You can find examples of how to do such configuration in the wiki.

Graceful git strategies

Git integration is documented at formatting-stack.strategies.

The general intent is to make formatting:

  • Efficient
    • don't process non-touched files
  • Gradual
    • don't format the whole project at once
    • favor reviewable diffs - nobody can review (or learn from) whole-project diffs
  • Safe
    • only format code that is completely staged by git
      • else any bug in formatting code could destroy your unsaved changes

...that's the default Git strategy anyway, apt for repl-driven development. You are free to supply an alternative strategy.

Commonly needed alternative strategies are offered/documented in branch-formatter and project-formatter.

Consolidated reporting

As you can see in the screenshot, formatting-stack presents linters' outputs under a hierarchical, file-grouped format.

Screenshot 2020-02-19 at 07 04 38

Installation

Coordinates

[formatting-stack "3.1.1-alpha2"]

Also you might have to add the refactor-nrepl dependency.

  • If you use tooling like CIDER, typically this dependency will be already injected into your classpath, so no action required in this case.
  • Else, please add the latest version to your project (or personal profile).
  • If this dependency isn't added, formatting-stack will degrade gracefully, using slightly fewer formatters/linters.

Component/Integrant integration

formatting-stack provides components that you can integrate into your system.

The provided components are fully configurable. See formatting-stack.core, formatting-stack.component, formatting-stack.integrant.

Reloaded Workflow integration

  • If you use the Component component, then com.stuartsierra.component.repl/reset will use formatting-stack, applying all its formatters/linters.
  • If you use the Integrant component, then integrant.repl/reset will use formatting-stack, applying all its formatters/linters.

The above can be good enough. However resetting your system can be somewhat expensive, and you may find yourself using clojure.tools.namespace.repl/refresh instead.

For that case, you can create some facility (e.g. shortcut, snippet) for the following code:

(clojure.tools.namespace.repl/refresh :after 'formatting-stack.core/format!)

Vanilla integration

formatting-stack.core/format! is a plain function, considered a public API, that is safe to invoke over REPL, a script, or anything you please.

Advanced configuration

If you want to add custom members to the format! options (namely: :formatters, or :strategies, etc), a typical pattern would be:

(formatting-stack.core/format! :formatters (conj formatting-stack.defaults/default-formatters my-custom-formatter))

You can also pass [] for disabling a particular aspect:

;; The default :formatters will be used, no :linters will be run:
(formatting-stack.core/format! :linters [])

If you need something more fine-grained, you are encouraged to copy the contents of the formatting-stack.defaults ns to your project, adapting things as needed. That ns is a deliberately thin and data-only one, with the precise purpose of being forked at no cost.

We might implement an easier way to configure the stack: #38

FAQ

License

Copyright © Nedap

This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0.

Can you improve this documentation? These fine people already did:
vemv & Jeroen de Jong
Edit on GitHub

cljdoc is a website building & hosting documentation for Clojure/Script libraries

× close