import-grouping
| Description | Rules for grouping import declarations |
|---|---|
| Options |
|
| Default | legacy |
| Ormolu | legacy |
| Since | v0.17.0.0 |
Some basic presets are provided but you can configure your own rules via a dedicated YAML configuration.
Predefined presets, usable directly as values for import-grouping:
legacy: adopt the legacy behavior (before version 0.17), i.e.,singlewhenrespectfulisfalseandpreservewhenrespectfulis true. Seerespectful.preserve: preserve the existing import groupssingle: single group of importsby-qualified: one group for unqualified imports, then one group for qualified importsby-scope: one group for external imports, then one group for imports targeting modules from the current Cabal projectby-scope-then-qualified: applyby-scopefirst, thenby-qualified
When the value for import-grouping is a list, that list defines the order for groups of import declarations. Each group are defined by a name and a set of rules:
name: "Text modules"
rules:
- glob: Data.Text
Any import declaration matching at least one of those rules will belong to that group.
By default, rules match all import declarations, either local or external, either qualified or unqualified, with explicit import list or hiding clauses, though with a high priority value.
The following are possible rule attributes:
glob: <pattern>: matches modules matching the provided<pattern>.*can be any character on the same module level.**can be any character and can span multiple module levels.import-list: any | explicit | hiding | none: when set,explicitonly matches import declarations with an explicit import list,hidingonly matches import declarations with thehidingclause,noneonly matches import declarations on a whole module (no explicit import list orhidingclause),anymatches all import declarations regardless of import lists orhidingclauses. When absent,anyis assumed.qualified: yes | no: when set,yesonly matches import declarations that are qualified, unlikenowhich only matches import declarations that are not qualified.scope: any | local | external: when set,anymatches all import declarations,localonly matches modules defined in the current Cabal project andexternalonly matches external modules. When absent,anyis assumed. Local modules are automatically detected. Developers can add custom modules through the--local-modulesCLI option. Seelocal-modulesfor more information.priority: <int>: in cases multiple rules from different groups match an import declaration, the value associated topriorityis used as a tie-breaker: the matching rule with the lowest priority wins, and the import declaration will belong to the group with that rule.
The following attributes are deprecated but still usable:
match: all: matches all modules with a high priority value.match: local-modules: matches local modules with a high priority value.
Here's an example used in the custom configuration:
import-grouping:
- name: "Text modules"
rules:
- glob: Data.Text
- name: "The rest"
rules:
- priority: 100
- name: "My internals and monads unqualified"
rules:
- scope: local
qualified: no
- glob: Control.Monad
qualified: no
- name: "My internals and monads qualified"
rules:
- scope: local
qualified: yes
- glob: Control.Monad
qualified: yes
- name: "Specific monads"
rules:
- glob: Control.Monad.**
Examples
import Control.Monad (Monad (..))
import qualified Control.Monad.Error as Error
import Control.Monad.State.Lazy (MonadState (..))
import Data.Maybe (maybe)
import Data.Text (Text)
import qualified Data.Text
import Data.Text.IO (hGetLine)
import SomeInternal.Module1 (anotherDefinition, someDefinition)
import SomeInternal.Module1.SubModuleA
import qualified SomeInternal.Module2 as Mod2
import qualified System.IO as SIO
import Text.Printf (printf)
import Control.Monad (Monad (..))
import Control.Monad.State.Lazy (MonadState (..))
import Data.Maybe (maybe)
import Data.Text (Text)
import Data.Text.IO (hGetLine)
import SomeInternal.Module1 (anotherDefinition, someDefinition)
import SomeInternal.Module1.SubModuleA
import Text.Printf (printf)
import qualified Control.Monad.Error as Error
import qualified Data.Text
import qualified SomeInternal.Module2 as Mod2
import qualified System.IO as SIO
import Control.Monad (Monad (..))
import qualified Control.Monad.Error as Error
import Control.Monad.State.Lazy (MonadState (..))
import Data.Maybe (maybe)
import Data.Text (Text)
import qualified Data.Text
import Data.Text.IO (hGetLine)
import qualified System.IO as SIO
import Text.Printf (printf)
import SomeInternal.Module1 (anotherDefinition, someDefinition)
import SomeInternal.Module1.SubModuleA
import qualified SomeInternal.Module2 as Mod2
import Control.Monad (Monad (..))
import Control.Monad.State.Lazy (MonadState (..))
import Data.Maybe (maybe)
import Data.Text (Text)
import Data.Text.IO (hGetLine)
import Text.Printf (printf)
import qualified Control.Monad.Error as Error
import qualified Data.Text
import qualified System.IO as SIO
import SomeInternal.Module1 (anotherDefinition, someDefinition)
import SomeInternal.Module1.SubModuleA
import qualified SomeInternal.Module2 as Mod2
import Data.Text (Text)
import qualified Data.Text
import Data.Maybe (maybe)
import Data.Text.IO (hGetLine)
import qualified System.IO as SIO
import Text.Printf (printf)
import Control.Monad (Monad (..))
import SomeInternal.Module1 (anotherDefinition, someDefinition)
import SomeInternal.Module1.SubModuleA
import qualified SomeInternal.Module2 as Mod2
import qualified Control.Monad.Error as Error
import Control.Monad.State.Lazy (MonadState (..))
For more examples, see the test files.