{"id":22862761,"url":"https://github.com/nedap/formatting-stack","last_synced_at":"2025-04-09T18:17:54.032Z","repository":{"id":39810837,"uuid":"168340001","full_name":"nedap/formatting-stack","owner":"nedap","description":"An efficient, smart, graceful composition of Clojure formatters, linters and such.","archived":false,"fork":false,"pushed_at":"2023-09-04T13:54:22.000Z","size":653,"stargazers_count":99,"open_issues_count":29,"forks_count":2,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-04-09T18:17:49.389Z","etag":null,"topics":["clojure","formatter","hacktoberfest","linting"],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"epl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nedap.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/contributing.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-01-30T12:34:04.000Z","updated_at":"2024-08-15T18:06:07.000Z","dependencies_parsed_at":"2025-02-24T04:14:14.203Z","dependency_job_id":"832e937c-71a8-4d90-aa1c-5fc09b6608da","html_url":"https://github.com/nedap/formatting-stack","commit_stats":null,"previous_names":[],"tags_count":60,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nedap%2Fformatting-stack","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nedap%2Fformatting-stack/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nedap%2Fformatting-stack/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nedap%2Fformatting-stack/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nedap","download_url":"https://codeload.github.com/nedap/formatting-stack/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248085328,"owners_count":21045139,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clojure","formatter","hacktoberfest","linting"],"created_at":"2024-12-13T10:14:42.144Z","updated_at":"2025-04-09T18:17:54.010Z","avatar_url":"https://github.com/nedap.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"# formatting-stack [![CircleCI](https://circleci.com/gh/nedap/formatting-stack.svg?style=svg\u0026circle-token=581a4a0fa4b19f0ac5c7d90d494c9df0c34cee68)](https://circleci.com/gh/nedap/formatting-stack)\n\n**formatting-stack** is a formatting/linting solution that can be integrated with:\n\n* your [Component](https://github.com/stuartsierra/component) (or [Integrant](https://github.com/weavejester/integrant), or bare [tools.namespace](https://github.com/clojure/tools.namespace)) system\n  * for instantaneous performance\n    * no cold-starts!\n  * and precise understanding of your codebase\n    * powered by Clojure's introspection capabilities (reified vars, namespaces), and occasionally `eval`\n  * and a reasonable triggering frequency\n    * so you don't format too frequently (format-on-save), or not frequently enough (git pre-commit hook)\n* Git status/branch information\n  * for some performance gains (typically only added/changed files will be processed)\n  * and also for gradual formatting\n* Anything you want\n  * A vanilla repl, Lein task, CI workflow...\n\nAs of today, it is integrated with:\n\n  * [cljfmt](https://github.com/weavejester/cljfmt)\n  * [how-to-ns](https://github.com/gfredericks/how-to-ns)\n  * [eastwood](https://github.com/jonase/eastwood)\n  * [clj-kondo](https://github.com/borkdude/clj-kondo)\n    * By default, both Eastwood and Kondo are enabled, each having some linters disabled, filling each other's gaps.\n  * [refactor-nrepl](https://github.com/clojure-emacs/refactor-nrepl)\n    * Used for \"clean unused imports\" functionality\n  * [all-my-files-should-end-with-exactly-one-newline-character](https://github.com/gfredericks/lein-all-my-files-should-end-with-exactly-one-newline-character)\n    * Configurable, you can ensure either 0 or 1 ending newlines per file.\n\nAnd it also bundles a few tiny linters of its own:\n\n  * [loc-per-ns](https://github.com/nedap/formatting-stack/blob/debdab8129dae7779d390216490625a3264c9d2c/src/formatting_stack/linters/loc_per_ns.clj) warns if a given NS surpasses a targeted LOC count.\n  * [ns-aliases](https://github.com/nedap/formatting-stack/blob/debdab8129dae7779d390216490625a3264c9d2c/src/formatting_stack/linters/ns_aliases.clj) warns if [Sierra's](https://stuartsierra.com/2015/05/10/clojure-namespace-aliases) aliasing guide is disregarded.\n  * [one-resource-per-ns](https://github.com/nedap/formatting-stack/blob/master/src/formatting_stack/linters/one_resource_per_ns.clj) warns if a Clojure namespace is defined in more than one file.\n  * [line-length](https://github.com/nedap/formatting-stack/blob/f1cf4206399a77a83fde4140095d4c59c10b1605/src/formatting_stack/linters/line_length.clj) warns when a given max line length is surpassed.\n\nIt is fully extensible: you can configure the bundled formatters, remove them, and/or add your own.\n\nWhenever it's safe, each formatter/linter will make full use of your CPU's cores. \n\nLinters' reports are presented under a unified format. \n\n## Smart code analysis\n\nAs mentioned, **formatting-stack** understands your codebase and its dependencies.\nIt knows which vars in the project are macros. It also reads the metadata of all function/macro vars.\n\nIt also associates `:style` metadata to your project's vars, in a clean manner, when needed.\n\nArmed with those powers, we can do two nifty things:\n\n* Inform cljfmt of indentation through metadata + config, using the [CIDER indent spec format](https://docs.cider.mx/cider/indent_spec.html)\n(by default, using an heuristic for cider-\u003ecljfmt format translation) or the cljfmt format (as a fallback).\n  * Recommendation: use metadata **for your own code**, use config for **third-party code** (that may be awaiting for a pull request)\n* Inform CIDER of indentation rules through config\n  * CIDER understands either metadata or emacs-specific rules, but not config\n\nYou can find examples of how to do such configuration in the [wiki](https://github.com/nedap/formatting-stack/wiki/Indentation-examples).\n\n## Graceful git strategies\n\nGit integration is documented at `formatting-stack.strategies`.\n\nThe general intent is to make formatting:\n\n* Efficient\n  * don't process non-touched files\n* Gradual\n  * don't format the whole project at once\n  * favor reviewable diffs - nobody can review (or learn from) whole-project diffs\n* Safe\n  * only format code that is completely staged by git\n    * else any bug in formatting code could destroy your unsaved changes\n\n...that's the default Git `strategy` anyway, apt for repl-driven development. You are free to supply an alternative strategy.\n\nCommonly needed alternative strategies are offered/documented in [branch-formatter](https://github.com/nedap/formatting-stack/blob/0d78f726555db175aa446f4a0a9d2e289cfdd540/src/formatting_stack/branch_formatter.clj) and [project-formatter](https://github.com/nedap/formatting-stack/blob/0d78f726555db175aa446f4a0a9d2e289cfdd540/src/formatting_stack/project_formatter.clj).\n\n## Consolidated reporting\n\nAs you can see in the screenshot, **formatting-stack** presents linters' outputs under a hierarchical, file-grouped format.\n\n\u003cimg width=\"710\" alt=\"Screenshot 2020-02-19 at 07 04 38\" src=\"https://user-images.githubusercontent.com/1162994/74806403-2aaa9700-52e6-11ea-8088-b073d82e2879.png\"\u003e\n\nAlternative reporters can be found in `./src/formatting_stack/reporters`, such as\n - `formatting-stack.pretty-line-printer` offers more concise output\n - `formatting-stack.file-writer` offers a file-output instead of stdout\n\n## Installation\n\n#### Coordinates\n\n```clojure\n[formatting-stack \"4.6.0\"]\n```\n\n**Also** you might have to add the [refactor-nrepl](https://github.com/clojure-emacs/refactor-nrepl) dependency.\n  * If you use tooling like CIDER, typically this dependency will be already injected into your classpath, so no action required in this case.\n  * Else, please add the latest version to your project (or personal [profile](https://github.com/technomancy/leiningen/blob/072dcd62dea0ea46413cf938878e2d31b76357c9/doc/PROFILES.md)).\n  * If this dependency isn't added, formatting-stack will degrade gracefully, using slightly fewer formatters/linters.\n\n### Reloaded Workflow integration\n\n* If you use the Component component, then `com.stuartsierra.component.repl/reset` will use formatting-stack, applying all its formatters/linters.\n  * You can find a working sample setup in [component_repl.clj](https://github.com/nedap/formatting-stack/blob/master/test-resources/component_repl.clj).\n* If you use the Integrant component, then `integrant.repl/reset` will use formatting-stack, applying all its formatters/linters.\n  * You can find a working sample setup in [integrant_repl.clj](https://github.com/nedap/formatting-stack/blob/master/test-resources/integrant_repl.clj).\n\nThe above can be good enough. However `reset`ting your system can be somewhat expensive,\nand you may find yourself using `clojure.tools.namespace.repl/refresh` instead.\n\nFor that case, you can create some facility (e.g. shortcut, snippet) for the following code:\n\n```clojure\n(clojure.tools.namespace.repl/refresh :after 'formatting-stack.core/format!)\n```\n\n### Vanilla integration\n\n[`formatting-stack.core/format!`](https://github.com/nedap/formatting-stack/blob/0d78f726555db175aa446f4a0a9d2e289cfdd540/src/formatting_stack/core.clj#L49) is a plain function, considered a public API, that is safe to invoke over REPL, a script, or anything you please.\n\n\u003e See also: [`format-and-lint-branch!`](https://github.com/nedap/formatting-stack/blob/5d66e2adffd1696af8b020c56d33d443b299aabd/src/formatting_stack/branch_formatter.clj#L84), [`format-and-lint-project!`](https://github.com/nedap/formatting-stack/blob/5d66e2adffd1696af8b020c56d33d443b299aabd/src/formatting_stack/project_formatter.clj#L84).\n\n## Advanced configuration\n\nIf you want to add custom members to the `format!` options (namely: `:formatters`, or `:strategies`, etc), a typical pattern would be:\n\n```clojure\n(formatting-stack.core/format! :formatters (conj formatting-stack.defaults/default-formatters my-custom-formatter))\n```\n\nYou can also pass `[]` for disabling a particular aspect:\n\n```clojure\n;; The default :formatters will be used, no :linters will be run:\n(formatting-stack.core/format! :linters [])\n```\n\n...And you can also override specific parameters (like max line length from 130 to 80) in a fine-grained manner, as documented in [customization_example.clj](https://github.com/nedap/formatting-stack/blob/master/test-resources/customization_example.clj).\n\n## [FAQ](https://github.com/nedap/formatting-stack/wiki/FAQ)\n\n## License\n\nCopyright © Nedap\n\nThis program and the accompanying materials are made available under the terms of the [Eclipse Public License 2.0](https://www.eclipse.org/legal/epl-2.0).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnedap%2Fformatting-stack","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnedap%2Fformatting-stack","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnedap%2Fformatting-stack/lists"}