fix-imports 1.0.5 → 1.1.0
raw patch · 6 files changed
+121/−57 lines, 6 files
Files
- README +2/−3
- changelog.md +39/−0
- dot-fix-imports +35/−0
- fix-imports.cabal +11/−7
- src/Config.hs +28/−44
- src/Main.hs +6/−3
README view
@@ -16,6 +16,5 @@ fixity parse. I don't know why it does that, but if you get a crash like that you can add your custom operators to the Config. -It can be a little slow. Most of this is probably that it rebuilds the-package index on every run. So if you have a large package db and it's too-slow, caching the package index would probably help.+It can be a little slow. Most of the time is haskell-src-exts parsing the+module.
+ changelog.md view
@@ -0,0 +1,39 @@+1.1.0++- Rename import-order to import-order-first, and add import-order-last.++1.0.5++- support haskell-src-exts > 1.16++- add 'language' field to .fix-imports, to turn on local extensions++1.0.3 and 1.0.4++- upgrade to haskell-src-exts-1.16++1.0.2++- Fix bug where a qualified import with >1 dot wasn't found. And don't+mess with Prelude.++1.0.1++- Fix a bunch of bugs: properly recognize unqualified imports as imports,+never import the current module, don't pick up modules with the same suffix+but a different name.++1.0.0++- Change name from FixImports to fix-imports, which is more unixy.++- Change ghc-pkg parsing from String to Text. It's noticeably faster.++- Add a more flexible system for prioritizing imports.+When there are several possibilities for a module name, they are all given+to a single function to decide. The config file moved from+fix-imports-priority to .fix-imports and can now specify sort orders for+packages and modules by prefix.++- Make -i includes for non-existent dirs ignored instead of causing an+error.
+ dot-fix-imports view
@@ -0,0 +1,35 @@+-- fix-imports looks for a .fix-imports file in the current directory for+-- per-project configuration.+--+-- The syntax is the same as the ghc-pkg output: word, colon, and a list+-- of words. A line with leading space is a continuation of the previous+-- line. Comments are written with "--".++-- Include extra directories on the search path. Directories passed via -i+-- go before this list.+include: dist/build/my-project/my-project-tmp++-- Control the sorting of the import list by prefix.+-- These go in the given order, before other imports.+import-order-first: Util Midi Ui Cmd Derive Perform Instrument Local+ LogView App+-- These go in the given order, but after all the other imports.+import-order-last: Global++-- When there are multiple candidates for a module, pick ones from a+-- particular package first, or last.+prio-package-high:+-- haskell98 and ghc export a lot of toplevel modules that most programs+-- don't want to import.+prio-package-low: haskell98 ghc Cabal++-- ... or pick a particular module name prefix first, or last.+prio-module-high: Ui+prio-module-low: GHC++-- Otherwise, the module with the least number of dots is picked. Usually+-- packages put the most "public" modules at the top, e.g. IO should choose+-- System.IO, not Data.Text.Lazy.IO++-- Space separate list of extensions that are enabled by default.+language: GeneralizedNewtypeDeriving
fix-imports.cabal view
@@ -1,5 +1,5 @@ name: fix-imports-version: 1.0.5+version: 1.1.0 cabal-version: >= 1.6 build-type: Simple synopsis: Program to manage the imports of a haskell module@@ -10,8 +10,8 @@ import block according to some heuristic you can define. This only works for qualified imports! Unqualified imports are left untouched. .- It's most convenient if bound to an editor key.- .+ It's most convenient if bound to an editor key. See the included vimrc+ for an example. You may have to cabal unpack or git clone to see it. category: Editor, Haskell, IDE license: BSD3@@ -19,13 +19,17 @@ author: Evan Laforge maintainer: Evan Laforge <qdunkan@gmail.com> stability: stable-tested-with: GHC>=7.0.3+tested-with: GHC>=8.0.2 data-files: README, vimrc-extra-source-files: src/*.hs+extra-source-files:+ src/*.hs+ changelog.md+ vimrc+ dot-fix-imports source-repository head- type: darcs- location: http://hub.darcs.net/elaforge/fix-imports+ type: git+ location: git://github.com/elaforge/fix-imports.git executable fix-imports main-is: Main.hs
src/Config.hs view
@@ -33,7 +33,7 @@ empty = Config { includes = [] , language = []- , showImports = formatGroups $ ImportOrder []+ , showImports = formatGroups $ ImportOrder [] [] , pickModule = makePickModule defaultPriorities } @@ -45,8 +45,10 @@ } deriving (Show) -- | Sort order for local modules.-newtype ImportOrder = ImportOrder [Types.ModuleName]- deriving (Show)+data ImportOrder = ImportOrder {+ importFirst :: [Types.ModuleName]+ , importLast :: [Types.ModuleName]+ } deriving (Show) parseLanguage :: [String] -> ([String], [Extension.Extension]) parseLanguage = Either.partitionEithers . map parse@@ -129,17 +131,23 @@ -- An unqualified import will follow a qualified one. The Prelude, if -- imported, always goes first. formatGroups :: ImportOrder -> [Types.ImportLine] -> String-formatGroups (ImportOrder order) imports =+formatGroups order imports = unlines $ joinGroups [ showGroups (group (Util.sortOn packagePrio package)) , showGroups (group (Util.sortOn localPrio local)) ] where- packagePrio imp = (fromEnum (name imp /= prelude), name imp,- qualifiedPrio imp)- localPrio imp = (listPriority (topModule imp) (map Types.moduleName order),- name imp, qualifiedPrio imp)- qualifiedPrio imp = fromEnum (not (qualifiedImport imp))+ packagePrio imp =+ ( name imp /= prelude+ , name imp+ , qualifiedPrio imp+ )+ localPrio imp =+ ( localPriority order (topModule imp)+ , name imp+ , qualifiedPrio imp+ )+ qualifiedPrio = not . qualifiedImport name = Types.importModule (local, package) = List.partition Types.importIsLocal imports group = collapse . Util.groupOn topModule@@ -154,10 +162,17 @@ joinGroups = List.intercalate [""] . filter (not . null) prelude = Types.ModuleName "Prelude" -listPriority :: (Eq a) => a -> [a] -> (Int, Maybe Int)-listPriority x xs = case List.elemIndex x xs of- Nothing -> (1, Nothing)- Just k -> (0, Just k)+-- | Modules whose top level element is in 'importFirst' go first, ones in+-- 'importLast' go last, and the rest go in the middle.+localPriority :: ImportOrder -> String -> (Int, Maybe Int)+localPriority order importTop = case List.elemIndex importTop firsts of+ Just k -> (-1, Just k)+ Nothing -> case List.elemIndex importTop lasts of+ Nothing -> (0, Nothing)+ Just k -> (1, Just k)+ where+ firsts = map Types.moduleName (importFirst order)+ lasts = map Types.moduleName (importLast order) qualifiedImport :: Types.ImportLine -> Bool qualifiedImport = Haskell.importQualified . Types.importDecl@@ -174,34 +189,3 @@ , Haskell.ribbonsPerLine = 1 } mode = Haskell.defaultMode--{---- t0 = map localPrio imports -- formatGroups priorities (map mkImport imports)-t0 = formatGroups priorities imports- where- imports = map mkImport- [ ("Data.List", True, Just "List", False)- , ("Prelude", False, Nothing, False)- , ("Prelude", True, Nothing, False)- , local "A.B"- , local "A.C"- , local "C.A"- , local "B.A"- , local "B.B"- , local "B.C"- , local "B.D"- ]- local name = (name, True, Nothing, True)- mkImport (name, qualified, importAs, local) = Types.ImportLine decl [] local- where- decl = Haskell.ImportDecl empty (Haskell.ModuleName empty name)- qualified False Nothing (fmap (Haskell.ModuleName empty) importAs)- Nothing- empty = Haskell.SrcSpanInfo (Haskell.SrcSpan "" 0 0 0 0) []-- priorities = ["A", "B"]- localPrio imp = (listPriority (topModule imp) priorities,- name imp, fromEnum (qualifiedImport imp))- topModule = takeWhile (/='.') . Types.moduleName . Types.importModule- name = Types.importModule--}
src/Main.hs view
@@ -3,7 +3,6 @@ -- -- More documentation in "FixImports". module Main where-import Control.Monad import qualified Data.List as List import qualified Data.Map as Map import qualified Data.Text as Text@@ -43,12 +42,16 @@ (unknownLanguage, language) = Config.parseLanguage (get "language") unknownFields = Map.keys fields List.\\ valid valid =- [ "include", "import-order"+ [ "include"+ , "import-order-first", "import-order-last" , "prio-package-high", "prio-package-low" , "prio-module-high", "prio-module-low" , "language" ]- order = Config.ImportOrder (getModules "import-order")+ order = Config.ImportOrder+ { Config.importFirst = getModules "import-order-first"+ , Config.importLast = getModules "import-order-last"+ } prios = Config.Priorities (get "prio-package-high", get "prio-package-low") (getModules "prio-module-high", getModules "prio-module-low") fields = Map.fromList [(Text.unpack section, map Text.unpack words)