stylish-haskell 0.8.1.0 → 0.9.0.0
raw patch · 10 files changed
+265/−291 lines, 10 filesdep +file-embeddep ~haskell-src-exts
Dependencies added: file-embed
Dependency ranges changed: haskell-src-exts
Files
- CHANGELOG +8/−0
- README.markdown +163/−0
- data/stylish-haskell.yaml +0/−224
- lib/Language/Haskell/Stylish/Config.hs +19/−22
- lib/Language/Haskell/Stylish/Parse.hs +4/−4
- lib/Language/Haskell/Stylish/Step/Imports.hs +5/−1
- src/Main.hs +4/−5
- stylish-haskell.cabal +36/−35
- tests/Language/Haskell/Stylish/Parse/Tests.hs +11/−0
- tests/Language/Haskell/Stylish/Step/Imports/Tests.hs +15/−0
CHANGELOG view
@@ -1,5 +1,13 @@ # CHANGELOG +- 0.9.0.0 (2017-12-26)+ * Embed the default configuration+ * Add platform-specific configuration paths (by Jan Tojnar)+ * Bump `haskell-src-exts` to 0.20+ * Avoid unpaired parenthesis when import doesn't specify any items (by+ Matthew Kennerly)+ * Remove shebang lines at the beginning of file (by Vaibhav Sagar)+ - 0.8.1.0 (2017-06-19) * Add `pad_module_names` option (by Yuriy Syrovetskiy) * Add `space_surround` option to import styling (by Linus Arver)
+ README.markdown view
@@ -0,0 +1,163 @@+stylish-haskell+===============++[](https://circleci.com/gh/jaspervdj/stylish-haskell)++Introduction+------------++A simple Haskell code prettifier. The goal is not to format all of the code in+a file, since I find those kind of tools often "get in the way". However,+manually cleaning up import statements etc. gets tedious very quickly.++This tool tries to help where necessary without getting in the way.++Installation+------------++You can install it using `stack install stylish-haskell` or `cabal install stylish-haskell`.++You can also install it using your package manager:+ * Debian 9 or later: `apt-get install stylish-haskell`+ * Ubuntu 16.10 or later: `apt-get install stylish-haskell`+ * Arch Linux: `pacman -S stylish-haskell`++Features+--------++- Aligns and sorts `import` statements+- Groups and wraps `{-# LANGUAGE #-}` pragmas, can remove (some) redundant+ pragmas+- Removes trailing whitespace+- Aligns branches in `case` and fields in records+- Converts line endings (customizable)+- Replaces tabs by four spaces (turned off by default)+- Replaces some ASCII sequences by their Unicode equivalents (turned off by+ default)++Feature requests are welcome! Use the [issue tracker] for that.++[issue tracker]: https://github.com/jaspervdj/stylish-haskell/issues++Example+-------++Turns:++```haskell+{-# LANGUAGE ViewPatterns, TemplateHaskell #-}+{-# LANGUAGE GeneralizedNewtypeDeriving,+ ViewPatterns,+ ScopedTypeVariables #-}++module Bad where++import Control.Applicative ((<$>))+import System.Directory (doesFileExist)++import qualified Data.Map as M+import Data.Map ((!), keys, Map)++data Point = Point+ { pointX, pointY :: Double+ , pointName :: String+ } deriving (Show)+```++into:++```haskell+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}++module Bad where++import Control.Applicative ((<$>))+import System.Directory (doesFileExist)++import Data.Map (Map, keys, (!))+import qualified Data.Map as M++data Point = Point+ { pointX, pointY :: Double+ , pointName :: String+ } deriving (Show)+```+Configuration+-------------++The tool is customizable to some extent. It tries to find a config file in the+following order:++1. A file passed to the tool using the `-c/--config` argument+2. `.stylish-haskell.yaml` in the current directory (useful for per-directory+ settings)+3. `.stylish-haskell.yaml` in the nearest ancestor directory (useful for+ per-project settings)+4. `stylish-haskell/config.yaml` in the platform’s configuration directory+ (on Windows, it is %APPDATA%, elsewhere it defaults to `~/.config` and+ can be overridden by the `XDG_CONFIG_HOME` environment variable;+ useful for user-wide settings)+5. `.stylish-haskell.yaml` in your home directory (useful for user-wide+ settings)+6. The default settings.++Use `stylish-haskell --defaults > .stylish-haskell.yaml` to dump a+well-documented default configuration to a file, this way you can get started+quickly.++VIM integration+---------------++Since it works as a filter it is pretty easy to integrate this with VIM.++You can call++ :%!stylish-haskell++and add a keybinding for it.++Or you can define `formatprg`++ :set formatprg=stylish-haskell++and then use `gq`.++There is also the [vim-stylish-haskell] plugin, which runs stylish-haskell+automatically when you save a Haskell file.++[vim-stylish-haskell]: https://github.com/nbouscal/vim-stylish-haskell++Emacs integration+-----------------++[haskell-mode] for Emacs supports `stylish-haskell`. For configuration,+see [the “Using external formatters” section][haskell-mode/format] of the+haskell-mode manual.++[haskell-mode]: https://github.com/haskell/haskell-mode+[haskell-mode/format]: http://haskell.github.io/haskell-mode/manual/latest/Autoformating.html++Atom integration+----------------++[ide-haskell] for Atom supports `stylish-haskell`.++[atom-beautify] for Atom supports Haskell using `stylish-haskell`.++[ide-haskell]: https://atom.io/packages/ide-haskell+[atom-beautify]: Https://atom.io/packages/atom-beautify++Credits+-------++Written and maintained by Jasper Van der Jeugt.++Contributors:++- Chris Done+- Hiromi Ishii+- Leonid Onokhov+- Michael Snoyman+- Mikhail Glushenkov
− data/stylish-haskell.yaml
@@ -1,224 +0,0 @@-# stylish-haskell configuration file-# ==================================--# The stylish-haskell tool is mainly configured by specifying steps. These steps-# are a list, so they have an order, and one specific step may appear more than-# once (if needed). Each file is processed by these steps in the given order.-steps:- # Convert some ASCII sequences to their Unicode equivalents. This is disabled- # by default.- # - unicode_syntax:- # # In order to make this work, we also need to insert the UnicodeSyntax- # # language pragma. If this flag is set to true, we insert it when it's- # # not already present. You may want to disable it if you configure- # # language extensions using some other method than pragmas. Default:- # # true.- # add_language_pragma: true-- # Align the right hand side of some elements. This is quite conservative- # and only applies to statements where each element occupies a single- # line.- - simple_align:- cases: true- top_level_patterns: true- records: true-- # Import cleanup- - imports:- # There are different ways we can align names and lists.- #- # - global: Align the import names and import list throughout the entire- # file.- #- # - file: Like global, but don't add padding when there are no qualified- # imports in the file.- #- # - group: Only align the imports per group (a group is formed by adjacent- # import lines).- #- # - none: Do not perform any alignment.- #- # Default: global.- align: global-- # The following options affect only import list alignment.- #- # List align has following options:- #- # - after_alias: Import list is aligned with end of import including- # 'as' and 'hiding' keywords.- #- # > import qualified Data.List as List (concat, foldl, foldr, head,- # > init, last, length)- #- # - with_alias: Import list is aligned with start of alias or hiding.- #- # > import qualified Data.List as List (concat, foldl, foldr, head,- # > init, last, length)- #- # - new_line: Import list starts always on new line.- #- # > import qualified Data.List as List- # > (concat, foldl, foldr, head, init, last, length)- #- # Default: after_alias- list_align: after_alias-- # Right-pad the module names to align imports in a group:- #- # - true: a little more readable- #- # > import qualified Data.List as List (concat, foldl, foldr,- # > init, last, length)- # > import qualified Data.List.Extra as List (concat, foldl, foldr,- # > init, last, length)- #- # - false: diff-safe- #- # > import qualified Data.List as List (concat, foldl, foldr, init,- # > last, length)- # > import qualified Data.List.Extra as List (concat, foldl, foldr,- # > init, last, length)- #- # Default: true- pad_module_names: true-- # Long list align style takes effect when import is too long. This is- # determined by 'columns' setting.- #- # - inline: This option will put as much specs on same line as possible.- #- # - new_line: Import list will start on new line.- #- # - new_line_multiline: Import list will start on new line when it's- # short enough to fit to single line. Otherwise it'll be multiline.- #- # - multiline: One line per import list entry.- # Type with constructor list acts like single import.- #- # > import qualified Data.Map as M- # > ( empty- # > , singleton- # > , ...- # > , delete- # > )- #- # Default: inline- long_list_align: inline-- # Align empty list (importing instances)- #- # Empty list align has following options- #- # - inherit: inherit list_align setting- #- # - right_after: () is right after the module name:- #- # > import Vector.Instances ()- #- # Default: inherit- empty_list_align: inherit-- # List padding determines indentation of import list on lines after import.- # This option affects 'long_list_align'.- #- # - <integer>: constant value- #- # - module_name: align under start of module name.- # Useful for 'file' and 'group' align settings.- list_padding: 4-- # Separate lists option affects formatting of import list for type- # or class. The only difference is single space between type and list- # of constructors, selectors and class functions.- #- # - true: There is single space between Foldable type and list of it's- # functions.- #- # > import Data.Foldable (Foldable (fold, foldl, foldMap))- #- # - false: There is no space between Foldable type and list of it's- # functions.- #- # > import Data.Foldable (Foldable(fold, foldl, foldMap))- #- # Default: true- separate_lists: true-- # Space surround option affects formatting of import lists on a single- # line. The only difference is single space after the initial- # parenthesis and a single space before the terminal parenthesis.- #- # - true: There is single space associated with the enclosing- # parenthesis.- #- # > import Data.Foo ( foo )- #- # - false: There is no space associated with the enclosing parenthesis- #- # > import Data.Foo (foo)- #- # Default: false- space_surround: false-- # Language pragmas- - language_pragmas:- # We can generate different styles of language pragma lists.- #- # - vertical: Vertical-spaced language pragmas, one per line.- #- # - compact: A more compact style.- #- # - compact_line: Similar to compact, but wrap each line with- # `{-#LANGUAGE #-}'.- #- # Default: vertical.- style: vertical-- # Align affects alignment of closing pragma brackets.- #- # - true: Brackets are aligned in same column.- #- # - false: Brackets are not aligned together. There is only one space- # between actual import and closing bracket.- #- # Default: true- align: true-- # stylish-haskell can detect redundancy of some language pragmas. If this- # is set to true, it will remove those redundant pragmas. Default: true.- remove_redundant: true-- # Replace tabs by spaces. This is disabled by default.- # - tabs:- # # Number of spaces to use for each tab. Default: 8, as specified by the- # # Haskell report.- # spaces: 8-- # Remove trailing whitespace- - trailing_whitespace: {}--# A common setting is the number of columns (parts of) code will be wrapped-# to. Different steps take this into account. Default: 80.-columns: 80--# By default, line endings are converted according to the OS. You can override-# preferred format here.-#-# - native: Native newline format. CRLF on Windows, LF on other OSes.-#-# - lf: Convert to LF ("\n").-#-# - crlf: Convert to CRLF ("\r\n").-#-# Default: native.-newline: native--# Sometimes, language extensions are specified in a cabal file or from the-# command line instead of using language pragmas in the file. stylish-haskell-# needs to be aware of these, so it can parse the file correctly.-#-# No language extensions are enabled by default.-# language_extensions:- # - TemplateHaskell- # - QuasiQuotes
lib/Language/Haskell/Stylish/Config.hs view
@@ -1,9 +1,10 @@ -------------------------------------------------------------------------------- {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-} module Language.Haskell.Stylish.Config ( Extensions , Config (..)- , defaultConfigFilePath+ , defaultConfigBytes , configFilePath , loadConfig ) where@@ -14,12 +15,13 @@ import Data.Aeson (FromJSON (..)) import qualified Data.Aeson as A import qualified Data.Aeson.Types as A-import Data.Maybe (fromMaybe) import qualified Data.ByteString as B+import qualified Data.FileEmbed as FileEmbed import Data.List (inits, intercalate) import Data.Map (Map) import qualified Data.Map as M+import Data.Maybe (fromMaybe) import Data.Yaml (decodeEither) import System.Directory import System.FilePath (joinPath,@@ -38,7 +40,6 @@ import qualified Language.Haskell.Stylish.Step.TrailingWhitespace as TrailingWhitespace import qualified Language.Haskell.Stylish.Step.UnicodeSyntax as UnicodeSyntax import Language.Haskell.Stylish.Verbose-import Paths_stylish_haskell (getDataFileName) --------------------------------------------------------------------------------@@ -65,26 +66,22 @@ ---------------------------------------------------------------------------------defaultConfigFilePath :: IO FilePath-defaultConfigFilePath = getDataFileName "data/stylish-haskell.yaml"+defaultConfigBytes :: B.ByteString+defaultConfigBytes = $(FileEmbed.embedFile "data/stylish-haskell.yaml") ---------------------------------------------------------------------------------configFilePath :: Verbose -> Maybe FilePath -> IO FilePath-configFilePath _ (Just userSpecified) = return userSpecified+configFilePath :: Verbose -> Maybe FilePath -> IO (Maybe FilePath)+configFilePath _ (Just userSpecified) = return (Just userSpecified) configFilePath verbose Nothing = do- current <- getCurrentDirectory- home <- getHomeDirectory- def <- defaultConfigFilePath- mbConfig <- search $+ current <- getCurrentDirectory+ configPath <- getXdgDirectory XdgConfig "stylish-haskell"+ home <- getHomeDirectory+ mbConfig <- search $ [d </> configFileName | d <- ancestors current] ++- [home </> configFileName, def]+ [configPath </> "config.yaml", home </> configFileName] - case mbConfig of- Just config -> return config- Nothing -> fail $- "Language.Haskell.Stylish.Config.configFilePath: " ++- "could not load default configuration at: " ++ def+ return mbConfig where -- All ancestors of a dir (including that dir) ancestors :: FilePath -> [FilePath]@@ -101,11 +98,11 @@ -------------------------------------------------------------------------------- loadConfig :: Verbose -> Maybe FilePath -> IO Config-loadConfig verbose mfp = do- fp <- configFilePath verbose mfp- verbose $ "Loading configuration at " ++ fp- bs <- B.readFile fp- case decodeEither bs of+loadConfig verbose userSpecified = do+ mbFp <- configFilePath verbose userSpecified+ verbose $ "Loading configuration at " ++ fromMaybe "<embedded>" mbFp+ bytes <- maybe (return defaultConfigBytes) B.readFile mbFp+ case decodeEither bytes of Left err -> error $ "Language.Haskell.Stylish.Config.loadConfig: " ++ err Right config -> return config
lib/Language/Haskell/Stylish/Parse.hs view
@@ -44,11 +44,11 @@ ----------------------------------------------------------------------------------- | Remove shebang from the first line+-- | Remove shebang lines unShebang :: String -> String-unShebang str- | "#!" `isPrefixOf` str = unlines $ ("" :) $ drop 1 $ lines str- | otherwise = str+unShebang str =+ let (shebangs, other) = break (not . ("#!" `isPrefixOf`)) (lines str) in+ unlines $ map (const "") shebangs ++ other --------------------------------------------------------------------------------
lib/Language/Haskell/Stylish/Step/Imports.hs view
@@ -311,7 +311,11 @@ ( mapSpecs ( withHead ("( " ++) . withTail (", " ++))- ++ [")"])+ ++ closer)+ where+ closer = if null importSpecs+ then []+ else [")"] paddedBase = base $ padImport $ compoundImportName imp
src/Main.hs view
@@ -6,10 +6,10 @@ -------------------------------------------------------------------------------- import Control.Monad (forM_, unless)+import qualified Data.ByteString.Char8 as BC8 import Data.Monoid ((<>)) import Data.Version (showVersion) import qualified Options.Applicative as OA-import qualified Paths_stylish_haskell import System.Exit (exitFailure) import qualified System.IO as IO import qualified System.IO.Strict as IO.Strict@@ -70,7 +70,7 @@ -------------------------------------------------------------------------------- stylishHaskellVersion :: String-stylishHaskellVersion = "stylish-haskell " <> showVersion Paths_stylish_haskell.version+stylishHaskellVersion = "stylish-haskell " <> showVersion version --------------------------------------------------------------------------------@@ -94,9 +94,8 @@ putStrLn stylishHaskellVersion else if saDefaults sa then do- fileName <- defaultConfigFilePath- verbose' $ "Dumping config from " ++ fileName- readUTF8File fileName >>= putStr+ verbose' "Dumping embedded config..."+ BC8.putStr defaultConfigBytes else do conf <- loadConfig verbose' (saConfig sa)
stylish-haskell.cabal view
@@ -1,5 +1,5 @@ Name: stylish-haskell-Version: 0.8.1.0+Version: 0.9.0.0 Synopsis: Haskell code prettifier Homepage: https://github.com/jaspervdj/stylish-haskell License: BSD3@@ -18,11 +18,9 @@ <https://github.com/jaspervdj/stylish-haskell/blob/master/README.markdown> -Data-files:- data/stylish-haskell.yaml- Extra-source-files:- CHANGELOG+ CHANGELOG,+ README.markdown Library Hs-source-dirs: lib@@ -49,16 +47,17 @@ Paths_stylish_haskell Build-depends:- aeson >= 0.6 && < 1.3,- base >= 4.8 && < 5,- bytestring >= 0.9 && < 0.11,- containers >= 0.3 && < 0.6,- directory >= 1.1 && < 1.4,- filepath >= 1.1 && < 1.5,- haskell-src-exts >= 1.18 && < 1.20,- mtl >= 2.0 && < 2.3,- syb >= 0.3 && < 0.8,- yaml >= 0.7 && < 0.9+ aeson >= 0.6 && < 1.3,+ base >= 4.8 && < 5,+ bytestring >= 0.9 && < 0.11,+ containers >= 0.3 && < 0.6,+ directory >= 1.1 && < 1.4,+ filepath >= 1.1 && < 1.5,+ file-embed >= 0.0.10 && < 0.1,+ haskell-src-exts >= 1.18 && < 1.21,+ mtl >= 2.0 && < 2.3,+ syb >= 0.3 && < 0.8,+ yaml >= 0.7 && < 0.9 Executable stylish-haskell Ghc-options: -Wall@@ -70,16 +69,17 @@ strict >= 0.3 && < 0.4, optparse-applicative >= 0.12 && < 0.15, -- Copied from regular dependencies...- aeson >= 0.6 && < 1.3,- base >= 4.8 && < 5,- bytestring >= 0.9 && < 0.11,- containers >= 0.3 && < 0.6,- directory >= 1.1 && < 1.4,- filepath >= 1.1 && < 1.5,- haskell-src-exts >= 1.18 && < 1.20,- mtl >= 2.0 && < 2.3,- syb >= 0.3 && < 0.8,- yaml >= 0.7 && < 0.9+ aeson >= 0.6 && < 1.3,+ base >= 4.8 && < 5,+ bytestring >= 0.9 && < 0.11,+ containers >= 0.3 && < 0.6,+ directory >= 1.1 && < 1.4,+ filepath >= 1.1 && < 1.5,+ file-embed >= 0.0.10 && < 0.1,+ haskell-src-exts >= 1.18 && < 1.21,+ mtl >= 2.0 && < 2.3,+ syb >= 0.3 && < 0.8,+ yaml >= 0.7 && < 0.9 Test-suite stylish-haskell-tests Ghc-options: -Wall@@ -116,16 +116,17 @@ test-framework >= 0.4 && < 0.9, test-framework-hunit >= 0.2 && < 0.4, -- Copied from regular dependencies...- aeson >= 0.6 && < 1.3,- base >= 4.8 && < 5,- bytestring >= 0.9 && < 0.11,- containers >= 0.3 && < 0.6,- directory >= 1.1 && < 1.4,- filepath >= 1.1 && < 1.5,- haskell-src-exts >= 1.18 && < 1.20,- mtl >= 2.0 && < 2.3,- syb >= 0.3 && < 0.8,- yaml >= 0.7 && < 0.9+ aeson >= 0.6 && < 1.3,+ base >= 4.8 && < 5,+ bytestring >= 0.9 && < 0.11,+ containers >= 0.3 && < 0.6,+ directory >= 1.1 && < 1.4,+ filepath >= 1.1 && < 1.5,+ file-embed >= 0.0.10 && < 0.1,+ haskell-src-exts >= 1.18 && < 1.21,+ mtl >= 2.0 && < 2.3,+ syb >= 0.3 && < 0.8,+ yaml >= 0.7 && < 0.9 Source-repository head Type: git
tests/Language/Haskell/Stylish/Parse/Tests.hs view
@@ -22,6 +22,7 @@ , testCase "Haskell2010 extension" testHaskell2010 , testCase "Shebang" testShebang , testCase "ShebangExt" testShebangExt+ , testCase "ShebangDouble" testShebangDouble , testCase "GADTs extension" testGADTs , testCase "KindSignatures extension" testKindSignatures , testCase "StandalonDeriving extension" testStandaloneDeriving@@ -79,6 +80,16 @@ testShebang :: Assertion testShebang = assert $ isRight $ parseModule [] Nothing $ unlines [ "#!runhaskell"+ , "module Main where"+ , "main = return ()"+ ]++--------------------------------------------------------------------------------++testShebangDouble :: Assertion+testShebangDouble = assert $ isRight $ parseModule [] Nothing $ unlines+ [ "#!nix-shell"+ , "#!nix-shell -i runhaskell -p haskellPackages.ghc" , "module Main where" , "main = return ()" ]
tests/Language/Haskell/Stylish/Step/Imports/Tests.hs view
@@ -52,6 +52,7 @@ , testCase "case 23" case23 , testCase "case 24" case24 , testCase "case 25" case25+ , testCase "case 26 (issue 185)" case26 ] @@ -662,4 +663,18 @@ , "import qualified Data.Maybe.Extra (Maybe(Just, Nothing))" , "" , "import Data.Foo (Foo (Foo,Bar), Goo(Goo))"+ ]+++--------------------------------------------------------------------------------+case26 :: Assertion+case26 = expected+ @=? testStep (step 80 options ) input'+ where+ options = defaultOptions { listAlign = NewLine, longListAlign = Multiline }+ input' = unlines+ [ "import Data.List"+ ]+ expected = unlines+ [ "import Data.List" ]