From 418fd7bb16eb7f85a13ef3150c8c196089e3273d Mon Sep 17 00:00:00 2001 From: Ky Bishop Date: Wed, 12 Feb 2025 12:01:16 -0500 Subject: [PATCH 1/2] Introduce newline-only mode --- lib/quokka/config.ex | 47 +++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/lib/quokka/config.ex b/lib/quokka/config.ex index f76272d..221e686 100644 --- a/lib/quokka/config.ex +++ b/lib/quokka/config.ex @@ -65,14 +65,16 @@ defmodule Quokka.Config do lift_alias_excluded_lastnames = (credo_opts[:lift_alias_excluded_lastnames] || []) |> Enum.map(&Atom.to_string/1) - reorder_configs = - if is_nil(config[:reorder_configs]), do: true, else: config[:reorder_configs] - inefficient_function_rewrites = if is_nil(config[:inefficient_function_rewrites]), do: true, else: config[:inefficient_function_rewrites] + newline_fixes_only = if is_nil(config[:newline_fixes_only]), do: false, else: config[:newline_fixes_only] + + reorder_configs = + if is_nil(config[:reorder_configs]), do: true, else: config[:reorder_configs] + rewrite_deprecations = if is_nil(config[:rewrite_deprecations]), do: true, else: config[:rewrite_deprecations] @@ -80,23 +82,24 @@ defmodule Quokka.Config do strict_module_layout_order = credo_opts[:strict_module_layout_order] || default_order :persistent_term.put(@key, %{ - block_pipe_flag: credo_opts[:block_pipe_flag] || false, block_pipe_exclude: credo_opts[:block_pipe_exclude] || [], - directories_included: Map.get(config[:files] || %{}, :included, []), + block_pipe_flag: credo_opts[:block_pipe_flag] || false, directories_excluded: Map.get(config[:files] || %{}, :excluded, []), + directories_included: Map.get(config[:files] || %{}, :included, []), inefficient_function_rewrites: inefficient_function_rewrites, large_numbers_gt: credo_opts[:large_numbers_gt] || :infinity, - line_length: credo_opts[:line_length] || 98, - pipe_chain_start_flag: credo_opts[:pipe_chain_start_flag] || false, - pipe_chain_start_excluded_functions: credo_opts[:pipe_chain_start_excluded_functions] || [], - pipe_chain_start_excluded_argument_types: credo_opts[:pipe_chain_start_excluded_argument_types] || [], - reorder_configs: reorder_configs, - rewrite_deprecations: rewrite_deprecations, lift_alias: credo_opts[:lift_alias] || false, lift_alias_depth: credo_opts[:lift_alias_depth] || 0, - lift_alias_excluded_namespaces: MapSet.new(lift_alias_excluded_namespaces ++ @stdlib), lift_alias_excluded_lastnames: MapSet.new(lift_alias_excluded_lastnames ++ @stdlib), + lift_alias_excluded_namespaces: MapSet.new(lift_alias_excluded_namespaces ++ @stdlib), lift_alias_frequency: credo_opts[:lift_alias_frequency] || 0, + line_length: credo_opts[:line_length] || 98, + newline_fixes_only: newline_fixes_only, + pipe_chain_start_excluded_argument_types: credo_opts[:pipe_chain_start_excluded_argument_types] || [], + pipe_chain_start_excluded_functions: credo_opts[:pipe_chain_start_excluded_functions] || [], + pipe_chain_start_flag: credo_opts[:pipe_chain_start_flag] || false, + reorder_configs: reorder_configs, + rewrite_deprecations: rewrite_deprecations, rewrite_multi_alias: credo_opts[:rewrite_multi_alias] || false, single_pipe_flag: credo_opts[:single_pipe_flag] || false, sort_order: credo_opts[:sort_order] || :alpha, @@ -117,14 +120,18 @@ defmodule Quokka.Config do end def get_styles() do - styles_to_remove = - for {module, flag_name} <- [ - {Configs, :reorder_configs}, - {Deprecations, :rewrite_deprecations} - ], - do: if(get(flag_name), do: nil, else: module) - - @styles -- styles_to_remove + if get(:newline_fixes_only) do + [Defs] + else + styles_to_remove = + for {module, flag_name} <- [ + {Configs, :reorder_configs}, + {Deprecations, :rewrite_deprecations} + ], + do: if(get(flag_name), do: nil, else: module) + + @styles -- styles_to_remove + end end def sort_order() do From 8fa7dd17b817c40b425895f2ce3d5644d065db43 Mon Sep 17 00:00:00 2001 From: Ky Bishop Date: Thu, 13 Feb 2025 14:30:06 -0500 Subject: [PATCH 2/2] doc fixups --- README.md | 100 +++++++++++++++++++++++++++++------------------------- 1 file changed, 54 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index 1b7406a..042ac64 100644 --- a/README.md +++ b/README.md @@ -4,15 +4,16 @@ # Quokka -A happy quokka with style +A happy quokka with style Quokka is an Elixir formatter plugin that's combination of `mix format` and `mix credo`, except instead of telling you what's wrong, it just rewrites the code for you. Quokka is a fork of [Styler](https://github.com/adobe/elixir-styler) that checks the Credo config to determine which rules to rewrite. Many common, non-controversial Credo style rules are rewritten automatically, while the controversial Credo style rules are rewritten based on your Credo configuration so you can customize your style. > #### WARNING {: .warning} +> > Quokka can change the behavior of your program! -> +> > In some cases, this can introduce bugs. It goes without saying, but look over your changes before committing to main :) -> +> > We recommend making changes in small chunks until all of the more dangerous > changes has been safely committed to the codebase @@ -38,6 +39,11 @@ Then add `Quokka` as a plugin to your `.formatter.exs` file And that's it! Now when you run `mix format` you'll also get the benefits of Quokka's Stylish Stylings. +### First Run + +You may want to initially run Quokka in "newline fixes only" mode. This will only fix spacing issues, making future PRs _much_ smaller and easier to digest. +See the example in the configuration section if you wish to do this. + **Speed**: Expect the first run to take some time as `Quokka` rewrites violations of styles and bottlenecks on disk I/O. Subsequent formats will take noticeably less time. ### Configuration @@ -56,16 +62,18 @@ in `.formatter.exs` to fine tune your setup: files: %{ included: ["lib/", ...], excluded: ["lib/example.ex", ...] - } + }, + newline_fixes_only: true | false ] ] ``` -| Option | Description | Default | -| --- | --- | --- | -| `:files` | Quokka gets files from `.formatter.exs[:inputs]`. However, in some cases you may need to selectively exclude/include files you wish to still run in `mix format`, but have different behavior with Quokka. | `%{included: [], excluded: []}` (all files included, none excluded) | -| `:inefficient_function_rewrites` | Rewrite inefficient functions to more efficient form | `true` | -| `:reorder_configs` | Alphabetize `config` by key in `config/*.exs` files | `true` | -| `:rewrite_deprecations` | Rewrite deprecated functions to their new form | `true` | + +| Option | Description | Default | +| -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | +| `:files` | Quokka gets files from `.formatter.exs[:inputs]`. However, in some cases you may need to selectively exclude/include files you wish to still run in `mix format`, but have different behavior with Quokka. | `%{included: [], excluded: []}` (all files included, none excluded) | +| `:inefficient_function_rewrites` | Rewrite inefficient functions to more efficient form | `true` | +| `:reorder_configs` | Alphabetize `config` by key in `config/*.exs` files | `true` | +| `:rewrite_deprecations` | Rewrite deprecated functions to their new form | `true` | ## Credo inspired rewrites @@ -77,7 +85,7 @@ some additional useful details such as links to detailed documentation and if the check can be configured further for fine tuning. > #### `:controversial` Credo checks {: .tip} -> +> > Quokka allows all `:controversial` Credo checks to be configurable. In many cases, > a Credo check can also be disabled to prevent rewriting. @@ -85,50 +93,50 @@ the check can be configured further for fine tuning. ### Credo.Check.Consistency -| Credo Check | Rewrite Description | Documentation | Configurable | -|-------------|-------------------|---------------|--------------| -| [`.MultiAliasImportRequireUse`](https://hexdocs.pm/credo/Credo.Check.Consistency.MultiAliasImportRequireUse.html) | Expands multi-alias/import statements | [Directive Expansion](docs/module_directives.md#directive-expansion) | | -| [`.ParameterPatternMatching`](https://hexdocs.pm/credo/Credo.Check.Consistency.ParameterPatternMatching.html) | Enforces consistent parameter pattern matching | [Parameter Pattern Matching](docs/styles.md#parameter-pattern-matching-consistency) | | +| Credo Check | Rewrite Description | Documentation | Configurable | +| ----------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- | ----------------------------------------------------------------------------------- | ------------ | +| [`.MultiAliasImportRequireUse`](https://hexdocs.pm/credo/Credo.Check.Consistency.MultiAliasImportRequireUse.html) | Expands multi-alias/import statements | [Directive Expansion](docs/module_directives.md#directive-expansion) | | +| [`.ParameterPatternMatching`](https://hexdocs.pm/credo/Credo.Check.Consistency.ParameterPatternMatching.html) | Enforces consistent parameter pattern matching | [Parameter Pattern Matching](docs/styles.md#parameter-pattern-matching-consistency) | | ### Credo.Check.Design -| Credo Check | Rewrite Description | Documentation | Configurable | -|-------------|-------------------|---------------|--------------| -| [`.AliasUsage`](https://hexdocs.pm/credo/Credo.Check.Design.AliasUsage.html) | Extracts repeated aliases | [Alias Lifting](docs/module_directives.md#alias-lifting) | ✓ | +| Credo Check | Rewrite Description | Documentation | Configurable | +| ---------------------------------------------------------------------------- | ------------------------- | -------------------------------------------------------- | ------------ | +| [`.AliasUsage`](https://hexdocs.pm/credo/Credo.Check.Design.AliasUsage.html) | Extracts repeated aliases | [Alias Lifting](docs/module_directives.md#alias-lifting) | ✓ | ### Credo.Check.Readability -| Credo Check | Rewrite Description | Documentation | Configurable | -|-------------|-------------------|---------------|--------------| -| [`.AliasOrder`](https://hexdocs.pm/credo/Credo.Check.Readability.AliasOrder.html) | Alphabetizes module directives | [Module Directives](docs/module_directives.md#directive-organization) | ✓ | -| [`.BlockPipe`](https://hexdocs.pm/credo/Credo.Check.Readability.BlockPipe.html) | (En\|dis)ables piping into blocks | [Pipe Chains](docs/pipes.md#pipe-start) | ✓ | -| [`.LargeNumbers`](https://hexdocs.pm/credo/Credo.Check.Readability.LargeNumbers.html) | Formats large numbers with underscores | [Number Formatting](docs/styles.md#large-base-10-numbers) | ✓ | -| [`.MaxLineLength`](https://hexdocs.pm/credo/Credo.Check.Readability.MaxLineLength.html) | Enforces maximum line length | [Line Length](docs/styles.md#line-length) | ✓ | -| [`.MultiAlias`](https://hexdocs.pm/credo/Credo.Check.Readability.MultiAlias.html) | Expands multi-alias statements | [Module Directives](docs/module_directives.md#directive-expansion) | ✓ | -| [`.OneArityFunctionInPipe`](https://hexdocs.pm/credo/Credo.Check.Readability.OneArityFunctionInPipe.html) | Optimizes pipe chains with single arity functions | [Pipe Chains](docs/pipes.md#add-parenthesis-to-function-calls-in-pipes) | | -| [`.ParenthesesOnZeroArityDefs`](https://hexdocs.pm/credo/Credo.Check.Readability.ParenthesesOnZeroArityDefs.html) | Enforces consistent function call parentheses | [Function Calls](docs/styles.md#add-parenthesis-to-0-arity-functions-and-macro-definitions) | ✓ | -| [`.PipeIntoAnonymousFunctions`](https://hexdocs.pm/credo/Credo.Check.Readability.PipeIntoAnonymousFunctions.html) | Optimizes pipes with anonymous functions | [Pipe Chains](docs/pipes.md#add-then-2-when-defining-and-calling-anonymous-functions-in-pipes) | | -| [`.PreferImplicitTry`](https://hexdocs.pm/credo/Credo.Check.Readability.PreferImplicitTry.html) | Simplifies try expressions | [Control Flow Macros](docs/styles.md#implicit-try) | | -| [`.SinglePipe`](https://hexdocs.pm/credo/Credo.Check.Readability.SinglePipe.html) | Optimizes pipe chains | [Pipe Chains](docs/pipes.md#unpiping-single-pipes) | ✓ | -| [`.StringSigils`](https://hexdocs.pm/credo/Credo.Check.Readability.StringSigils.html) | Replaces strings with sigils | [Strings to Sigils](docs/styles.md#strings-to-sigils) | | -| [`.StrictModuleLayout`](https://hexdocs.pm/credo/Credo.Check.Readability.StrictModuleLayout.html) | Enforces strict module layout | [Module Directives](docs/module_directives.md#directive-organization) | ✓ | -| [`.UnnecessaryAliasExpansion`](https://hexdocs.pm/credo/Credo.Check.Readability.UnnecessaryAliasExpansion.html) | Removes unnecessary alias expansions | [Module Directives](docs/module_directives.md#directive-expansion) | | -| [`.WithSingleClause`](https://hexdocs.pm/credo/Credo.Check.Readability.WithSingleClause.html) | Simplifies with statements | [Control Flow Macros](docs/control_flow_macros.md#with) | | +| Credo Check | Rewrite Description | Documentation | Configurable | +| ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- | ---------------------------------------------------------------------------------------------- | ------------ | +| [`.AliasOrder`](https://hexdocs.pm/credo/Credo.Check.Readability.AliasOrder.html) | Alphabetizes module directives | [Module Directives](docs/module_directives.md#directive-organization) | ✓ | +| [`.BlockPipe`](https://hexdocs.pm/credo/Credo.Check.Readability.BlockPipe.html) | (En\|dis)ables piping into blocks | [Pipe Chains](docs/pipes.md#pipe-start) | ✓ | +| [`.LargeNumbers`](https://hexdocs.pm/credo/Credo.Check.Readability.LargeNumbers.html) | Formats large numbers with underscores | [Number Formatting](docs/styles.md#large-base-10-numbers) | ✓ | +| [`.MaxLineLength`](https://hexdocs.pm/credo/Credo.Check.Readability.MaxLineLength.html) | Enforces maximum line length | [Line Length](docs/styles.md#line-length) | ✓ | +| [`.MultiAlias`](https://hexdocs.pm/credo/Credo.Check.Readability.MultiAlias.html) | Expands multi-alias statements | [Module Directives](docs/module_directives.md#directive-expansion) | ✓ | +| [`.OneArityFunctionInPipe`](https://hexdocs.pm/credo/Credo.Check.Readability.OneArityFunctionInPipe.html) | Optimizes pipe chains with single arity functions | [Pipe Chains](docs/pipes.md#add-parenthesis-to-function-calls-in-pipes) | | +| [`.ParenthesesOnZeroArityDefs`](https://hexdocs.pm/credo/Credo.Check.Readability.ParenthesesOnZeroArityDefs.html) | Enforces consistent function call parentheses | [Function Calls](docs/styles.md#add-parenthesis-to-0-arity-functions-and-macro-definitions) | ✓ | +| [`.PipeIntoAnonymousFunctions`](https://hexdocs.pm/credo/Credo.Check.Readability.PipeIntoAnonymousFunctions.html) | Optimizes pipes with anonymous functions | [Pipe Chains](docs/pipes.md#add-then-2-when-defining-and-calling-anonymous-functions-in-pipes) | | +| [`.PreferImplicitTry`](https://hexdocs.pm/credo/Credo.Check.Readability.PreferImplicitTry.html) | Simplifies try expressions | [Control Flow Macros](docs/styles.md#implicit-try) | | +| [`.SinglePipe`](https://hexdocs.pm/credo/Credo.Check.Readability.SinglePipe.html) | Optimizes pipe chains | [Pipe Chains](docs/pipes.md#unpiping-single-pipes) | ✓ | +| [`.StringSigils`](https://hexdocs.pm/credo/Credo.Check.Readability.StringSigils.html) | Replaces strings with sigils | [Strings to Sigils](docs/styles.md#strings-to-sigils) | | +| [`.StrictModuleLayout`](https://hexdocs.pm/credo/Credo.Check.Readability.StrictModuleLayout.html) | Enforces strict module layout | [Module Directives](docs/module_directives.md#directive-organization) | ✓ | +| [`.UnnecessaryAliasExpansion`](https://hexdocs.pm/credo/Credo.Check.Readability.UnnecessaryAliasExpansion.html) | Removes unnecessary alias expansions | [Module Directives](docs/module_directives.md#directive-expansion) | | +| [`.WithSingleClause`](https://hexdocs.pm/credo/Credo.Check.Readability.WithSingleClause.html) | Simplifies with statements | [Control Flow Macros](docs/control_flow_macros.md#with) | | ### Credo.Check.Refactor -| Credo Check | Rewrite Description | Documentation | Configurable | -|-------------|-------------------|---------------|--------------| -| [`.CondStatements`](https://hexdocs.pm/credo/Credo.Check.Refactor.CondStatements.html) | Simplifies boolean expressions | [Control Flow Macros](docs/control_flow_macros.md#cond) | | -| [`.FilterCount`](https://hexdocs.pm/credo/Credo.Check.Refactor.FilterCount.html) | Optimizes filter + count operations | [Styles](docs/styles.md#filter-count) | | -| [`.MapInto`](https://hexdocs.pm/credo/Credo.Check.Refactor.MapInto.html) | Optimizes map + into operations | [Styles](docs/styles.md#map-into) | | -| [`.MapJoin`](https://hexdocs.pm/credo/Credo.Check.Refactor.MapJoin.html) | Optimizes map + join operations | [Styles](docs/styles.md#map-join) | | -| [`.NegatedConditionsInUnless`](https://hexdocs.pm/credo/Credo.Check.Refactor.NegatedConditionsInUnless.html) | Simplifies negated conditions in unless | [Control Flow Macros](docs/control_flow_macros.md#if-and-unless) | | -| [`.NegatedConditionsWithElse`](https://hexdocs.pm/credo/Credo.Check.Refactor.NegatedConditionsWithElse.html) | Simplifies negated conditions with else | [Control Flow Macros](docs/control_flow_macros.md#negation-inversion) | | -| [`.PipeChainStart`](https://hexdocs.pm/credo/Credo.Check.Refactor.PipeChainStart.html) | Optimizes pipe chain start | [Pipe Chains](docs/pipes.md#pipe-start) | | -| [`.RedundantWithClauseResult`](https://hexdocs.pm/credo/Credo.Check.Refactor.RedundantWithClauseResult.html) | Removes redundant with clause results | [Control Flow Macros](docs/control_flow_macros.md#with) | | -| [`.UnlessWithElse`](https://hexdocs.pm/credo/Credo.Check.Refactor.UnlessWithElse.html) | Simplifies unless with else | [Control Flow Macros](docs/control_flow_macros.md#if-and-unless) | | -| [`.WithClauses`](https://hexdocs.pm/credo/Credo.Check.Refactor.WithClauses.html) | Optimizes with clauses | [Control Flow Macros](docs/control_flow_macros.md#with) | | +| Credo Check | Rewrite Description | Documentation | Configurable | +| ------------------------------------------------------------------------------------------------------------ | --------------------------------------- | --------------------------------------------------------------------- | ------------ | +| [`.CondStatements`](https://hexdocs.pm/credo/Credo.Check.Refactor.CondStatements.html) | Simplifies boolean expressions | [Control Flow Macros](docs/control_flow_macros.md#cond) | | +| [`.FilterCount`](https://hexdocs.pm/credo/Credo.Check.Refactor.FilterCount.html) | Optimizes filter + count operations | [Styles](docs/styles.md#filter-count) | | +| [`.MapInto`](https://hexdocs.pm/credo/Credo.Check.Refactor.MapInto.html) | Optimizes map + into operations | [Styles](docs/styles.md#map-into) | | +| [`.MapJoin`](https://hexdocs.pm/credo/Credo.Check.Refactor.MapJoin.html) | Optimizes map + join operations | [Styles](docs/styles.md#map-join) | | +| [`.NegatedConditionsInUnless`](https://hexdocs.pm/credo/Credo.Check.Refactor.NegatedConditionsInUnless.html) | Simplifies negated conditions in unless | [Control Flow Macros](docs/control_flow_macros.md#if-and-unless) | | +| [`.NegatedConditionsWithElse`](https://hexdocs.pm/credo/Credo.Check.Refactor.NegatedConditionsWithElse.html) | Simplifies negated conditions with else | [Control Flow Macros](docs/control_flow_macros.md#negation-inversion) | | +| [`.PipeChainStart`](https://hexdocs.pm/credo/Credo.Check.Refactor.PipeChainStart.html) | Optimizes pipe chain start | [Pipe Chains](docs/pipes.md#pipe-start) | | +| [`.RedundantWithClauseResult`](https://hexdocs.pm/credo/Credo.Check.Refactor.RedundantWithClauseResult.html) | Removes redundant with clause results | [Control Flow Macros](docs/control_flow_macros.md#with) | | +| [`.UnlessWithElse`](https://hexdocs.pm/credo/Credo.Check.Refactor.UnlessWithElse.html) | Simplifies unless with else | [Control Flow Macros](docs/control_flow_macros.md#if-and-unless) | | +| [`.WithClauses`](https://hexdocs.pm/credo/Credo.Check.Refactor.WithClauses.html) | Optimizes with clauses | [Control Flow Macros](docs/control_flow_macros.md#with) | |