summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorSean Whitton <spwhitton@spwhitton.name>2018-05-13 10:42:46 -0700
committerSean Whitton <spwhitton@spwhitton.name>2018-05-13 10:42:46 -0700
commitb3102087ce4cfceb395ce981c4ac167a9d6b7642 (patch)
tree1feb8e3fd4a877a765afa6efa6c2a3be35dcbd7a
parent01298b15d95aec5945be8c5839045763d57657fc (diff)
parent7fac380bd83d51191e223560449d808e323d7ca6 (diff)
downloadstylish-haskell-b3102087ce4cfceb395ce981c4ac167a9d6b7642.tar.gz
Merge tag 'v0.9.2.0'
v0.9.2.0
-rw-r--r--.circleci/config.yml37
-rwxr-xr-x.circleci/release.sh44
-rw-r--r--.travis.yml19
-rw-r--r--CHANGELOG27
-rw-r--r--README.markdown17
-rw-r--r--data/stylish-haskell.yaml5
-rw-r--r--lib/Language/Haskell/Stylish/Align.hs4
-rw-r--r--lib/Language/Haskell/Stylish/Config.hs48
-rw-r--r--lib/Language/Haskell/Stylish/Parse.hs8
-rw-r--r--lib/Language/Haskell/Stylish/Step/Imports.hs15
-rw-r--r--lib/Language/Haskell/Stylish/Step/SimpleAlign.hs41
-rw-r--r--lib/Language/Haskell/Stylish/Step/Squash.hs62
-rw-r--r--lib/Language/Haskell/Stylish/Util.hs14
-rwxr-xr-xscripts/latest.sh21
-rwxr-xr-xscripts/stylish-haskell.sh4
-rw-r--r--src/Main.hs9
-rw-r--r--stack.yaml7
-rw-r--r--stylish-haskell.cabal76
-rw-r--r--tests/Language/Haskell/Stylish/Parse/Tests.hs11
-rw-r--r--tests/Language/Haskell/Stylish/Step/Imports/Tests.hs15
-rw-r--r--tests/Language/Haskell/Stylish/Step/SimpleAlign/Tests.hs18
-rw-r--r--tests/Language/Haskell/Stylish/Step/Squash/Tests.hs121
-rw-r--r--tests/TestSuite.hs2
23 files changed, 513 insertions, 112 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml
new file mode 100644
index 0000000..3845c0e
--- /dev/null
+++ b/.circleci/config.yml
@@ -0,0 +1,37 @@
+version: 2
+
+workflows:
+ version: 2
+ simple-workflow:
+ jobs:
+ - build:
+ filters:
+ tags:
+ only: /.*/
+
+jobs:
+ build:
+ docker:
+ - image: 'fpco/stack-build:latest'
+
+ steps:
+ - checkout
+ - restore_cache:
+ key: 'v1-stylish-haskell-{{ arch }}-{{ .Branch }}'
+ - run:
+ name: 'Update cabal indices'
+ command: 'cabal update'
+ - run:
+ name: 'Build and install'
+ command: 'cabal install --enable-tests --jobs=1'
+ - run:
+ name: 'Run tests'
+ command: 'cabal test'
+ - save_cache:
+ key: 'v1-stylish-haskell-{{ arch }}-{{ .Branch }}-{{ .Revision }}'
+ paths:
+ - '~/.cabal'
+ - '~/.ghc'
+ - run:
+ name: 'Upload release'
+ command: '.circleci/release.sh "$CIRCLE_TAG"'
diff --git a/.circleci/release.sh b/.circleci/release.sh
new file mode 100755
index 0000000..5586d24
--- /dev/null
+++ b/.circleci/release.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+set -o nounset -o errexit -o pipefail
+
+TAG="$1"
+SUFFIX="linux-$(uname -m)"
+USER="jaspervdj"
+REPOSITORY="$(basename -- *.cabal ".cabal")"
+BINARY="$REPOSITORY"
+
+echo "Tag: $TAG"
+echo "Suffix: $SUFFIX"
+echo "Repository: $REPOSITORY"
+
+$BINARY --version
+
+if [[ -z "$TAG" ]]; then
+ echo "Not a tagged build, skipping release..."
+ exit 0
+fi
+
+# Install ghr
+GHR_VERSION="v0.5.4"
+wget --quiet \
+ "https://github.com/tcnksm/ghr/releases/download/${GHR_VERSION}/ghr_${GHR_VERSION}_linux_386.zip"
+unzip ghr_${GHR_VERSION}_linux_386.zip
+
+# Install upx
+UPX_VERSION="3.94"
+wget --quiet \
+ "https://github.com/upx/upx/releases/download/v${UPX_VERSION}/upx-${UPX_VERSION}-amd64_linux.tar.xz"
+tar xf upx-${UPX_VERSION}-amd64_linux.tar.xz
+mv upx-${UPX_VERSION}-amd64_linux/upx .
+
+# Create tarball
+PACKAGE="$REPOSITORY-$TAG-$SUFFIX"
+mkdir -p "$PACKAGE"
+cp "$(which "$BINARY")" "$PACKAGE"
+./upx -q "$PACKAGE/$BINARY"
+cp CHANGELOG* LICENSE* README* "$PACKAGE"
+tar -czf "$PACKAGE.tar.gz" "$PACKAGE"
+rm -r "$PACKAGE"
+
+# Actually upload
+./ghr -u "$USER" -r "$REPOSITORY" "$TAG" "$PACKAGE.tar.gz"
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 5e5c816..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-sudo: false
-language: c # Choose a lightweight base image
-
-cache:
- directories:
- - $HOME/.stack
-
-addons:
- apt:
- packages:
- - libgmp-dev
-
-before_install:
-- mkdir -p ~/.local/bin
-- export PATH=$HOME/.local/bin:$PATH
-- travis_retry curl -L https://www.stackage.org/stack/linux-x86_64 | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'
-
-script:
-- stack --no-terminal test
diff --git a/CHANGELOG b/CHANGELOG
index 5a550bd..fd128f3 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,32 @@
# CHANGELOG
+- 0.9.2.0 (2018-05-01)
+ * Support alignment of case expressions with a single guard
+ * Add a new step to squash multiple spaces between some elements (by Martin
+ Huschenbett)
+
+- 0.9.1.1 (2018-04-26)
+ * Bump `aeson` to 1.3 for tests as well
+
+- 0.9.1.0 (2018-04-26)
+ * Support GHC 8.4.1 by adding instance SemiGroup ImportPortion (by George
+ Wilson)
+ * Bump `aeson` to 1.3
+
+- 0.9.0.2 (2018-01-03)
+ * Bump lower bound of `directory` to `1.2.3` for `getXdgDirectory`
+
+- 0.9.0.1 (2017-12-29)
+ * Fix missing Extra-source-file in cabal file
+
+- 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)
diff --git a/README.markdown b/README.markdown
index 335d8c6..88df2b7 100644
--- a/README.markdown
+++ b/README.markdown
@@ -83,9 +83,13 @@ following order:
settings)
3. `.stylish-haskell.yaml` in the nearest ancestor directory (useful for
per-project settings)
-4. `.stylish-haskell.yaml` in your home directory (useful for user-wide
+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)
-5. The default 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
@@ -133,6 +137,15 @@ Atom integration
[ide-haskell]: https://atom.io/packages/ide-haskell
[atom-beautify]: Https://atom.io/packages/atom-beautify
+Using with Continuous Integration
+---------------------------------
+
+You can quickly grab the latest binary and run `stylish-haskell` like so:
+
+ curl -sL https://raw.github.com/jaspervdj/stylish-haskell/master/scripts/latest.sh | sh -s .
+
+Where the `.` can be replaced with the arguments you pass to `stylish-haskell`.
+
Credits
-------
diff --git a/data/stylish-haskell.yaml b/data/stylish-haskell.yaml
index 10301be..c1d822d 100644
--- a/data/stylish-haskell.yaml
+++ b/data/stylish-haskell.yaml
@@ -198,6 +198,11 @@ steps:
# Remove trailing whitespace
- trailing_whitespace: {}
+ # Squash multiple spaces between the left and right hand sides of some
+ # elements into single spaces. Basically, this undoes the effect of
+ # simple_align but is a bit less conservative.
+ # - squash: {}
+
# 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
diff --git a/lib/Language/Haskell/Stylish/Align.hs b/lib/Language/Haskell/Stylish/Align.hs
index 8e6665f..53549b9 100644
--- a/lib/Language/Haskell/Stylish/Align.hs
+++ b/lib/Language/Haskell/Stylish/Align.hs
@@ -7,7 +7,6 @@ module Language.Haskell.Stylish.Align
--------------------------------------------------------------------------------
-import Data.Char (isSpace)
import Data.List (nub)
import qualified Language.Haskell.Exts as H
@@ -81,9 +80,6 @@ align maxColumns alignment
(pre, post) = splitAt column str
in [padRight longestLeft (trimRight pre) ++ trimLeft post]
- trimLeft = dropWhile isSpace
- trimRight = reverse . trimLeft . reverse
-
--------------------------------------------------------------------------------
-- | Checks that all the alignables appear on a single line, and that they do
diff --git a/lib/Language/Haskell/Stylish/Config.hs b/lib/Language/Haskell/Stylish/Config.hs
index 9fddbb5..19588b7 100644
--- a/lib/Language/Haskell/Stylish/Config.hs
+++ b/lib/Language/Haskell/Stylish/Config.hs
@@ -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 Control.Monad (forM, mzero)
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,
@@ -34,11 +36,11 @@ import Language.Haskell.Stylish.Step
import qualified Language.Haskell.Stylish.Step.Imports as Imports
import qualified Language.Haskell.Stylish.Step.LanguagePragmas as LanguagePragmas
import qualified Language.Haskell.Stylish.Step.SimpleAlign as SimpleAlign
+import qualified Language.Haskell.Stylish.Step.Squash as Squash
import qualified Language.Haskell.Stylish.Step.Tabs as Tabs
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 +67,22 @@ configFileName = ".stylish-haskell.yaml"
--------------------------------------------------------------------------------
-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 +99,11 @@ configFilePath verbose Nothing = do
--------------------------------------------------------------------------------
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
@@ -140,6 +138,7 @@ catalog = M.fromList
[ ("imports", parseImports)
, ("language_pragmas", parseLanguagePragmas)
, ("simple_align", parseSimpleAlign)
+ , ("squash", parseSquash)
, ("tabs", parseTabs)
, ("trailing_whitespace", parseTrailingWhitespace)
, ("unicode_syntax", parseUnicodeSyntax)
@@ -178,6 +177,11 @@ parseSimpleAlign c o = SimpleAlign.step
--------------------------------------------------------------------------------
+parseSquash :: Config -> A.Object -> A.Parser Step
+parseSquash _ _ = return Squash.step
+
+
+--------------------------------------------------------------------------------
parseImports :: Config -> A.Object -> A.Parser Step
parseImports config o = Imports.step
<$> pure (configColumns config)
diff --git a/lib/Language/Haskell/Stylish/Parse.hs b/lib/Language/Haskell/Stylish/Parse.hs
index 724ebe2..01def63 100644
--- a/lib/Language/Haskell/Stylish/Parse.hs
+++ b/lib/Language/Haskell/Stylish/Parse.hs
@@ -44,11 +44,11 @@ unCpp = unlines . go False . lines
--------------------------------------------------------------------------------
--- | 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
--------------------------------------------------------------------------------
diff --git a/lib/Language/Haskell/Stylish/Step/Imports.hs b/lib/Language/Haskell/Stylish/Step/Imports.hs
index 2284f3d..fc035a2 100644
--- a/lib/Language/Haskell/Stylish/Step/Imports.hs
+++ b/lib/Language/Haskell/Stylish/Step/Imports.hs
@@ -22,9 +22,9 @@ import Data.Char (toLower)
import Data.List (intercalate, sortBy)
import qualified Data.Map as M
import Data.Maybe (isJust, maybeToList)
-import Data.Monoid ((<>))
import Data.Ord (comparing)
import qualified Data.Set as S
+import Data.Semigroup (Semigroup ((<>)))
import qualified Language.Haskell.Exts as H
@@ -168,10 +168,13 @@ data ImportPortion l
= ImportSome [H.CName l] -- ^ @A(x, y, z)@
| ImportAll -- ^ @A(..)@
+instance Ord l => Semigroup (ImportPortion l) where
+ ImportSome a <> ImportSome b = ImportSome (setUnion a b)
+ _ <> _ = ImportAll
+
instance Ord l => Monoid (ImportPortion l) where
mempty = ImportSome []
- mappend (ImportSome a) (ImportSome b) = ImportSome (setUnion a b)
- mappend _ _ = ImportAll
+ mappend = (<>)
-- | O(n log n) union.
setUnion :: Ord a => [a] -> [a] -> [a]
@@ -311,7 +314,11 @@ prettyImport columns Options{..} padQualified padName longest imp
( mapSpecs
( withHead ("( " ++)
. withTail (", " ++))
- ++ [")"])
+ ++ closer)
+ where
+ closer = if null importSpecs
+ then []
+ else [")"]
paddedBase = base $ padImport $ compoundImportName imp
diff --git a/lib/Language/Haskell/Stylish/Step/SimpleAlign.hs b/lib/Language/Haskell/Stylish/Step/SimpleAlign.hs
index c83c482..924d6c5 100644
--- a/lib/Language/Haskell/Stylish/Step/SimpleAlign.hs
+++ b/lib/Language/Haskell/Stylish/Step/SimpleAlign.hs
@@ -8,6 +8,7 @@ module Language.Haskell.Stylish.Step.SimpleAlign
--------------------------------------------------------------------------------
import Data.Data (Data)
+import Data.List (foldl')
import Data.Maybe (maybeToList)
import qualified Language.Haskell.Exts as H
@@ -42,14 +43,30 @@ cases modu = [alts | H.Case _ _ alts <- everything modu]
--------------------------------------------------------------------------------
-altToAlignable :: H.Alt l -> Maybe (Alignable l)
-altToAlignable (H.Alt _ _ _ (Just _)) = Nothing
-altToAlignable (H.Alt ann pat rhs Nothing) = Just $ Alignable
- { aContainer = ann
- , aLeft = H.ann pat
- , aRight = H.ann rhs
- , aRightLead = length "-> "
- }
+-- | For this to work well, we require a way to merge annotations. This merge
+-- operation should follow the semigroup laws.
+altToAlignable :: (l -> l -> l) -> H.Alt l -> Maybe (Alignable l)
+altToAlignable _ (H.Alt _ _ _ (Just _)) = Nothing
+altToAlignable _ (H.Alt ann pat rhs@(H.UnGuardedRhs _ _) Nothing) = Just $
+ Alignable
+ { aContainer = ann
+ , aLeft = H.ann pat
+ , aRight = H.ann rhs
+ , aRightLead = length "-> "
+ }
+altToAlignable
+ merge
+ (H.Alt ann pat (H.GuardedRhss _ [H.GuardedRhs _ guards rhs]) Nothing) =
+ -- We currently only support the case where an alternative has a single
+ -- guarded RHS. If there are more, we would need to return multiple
+ -- `Alignable`s from this function, which would be a significant change.
+ Just $ Alignable
+ { aContainer = ann
+ , aLeft = foldl' merge (H.ann pat) (map H.ann guards)
+ , aRight = H.ann rhs
+ , aRightLead = length "-> "
+ }
+altToAlignable _ _ = Nothing
--------------------------------------------------------------------------------
@@ -101,9 +118,11 @@ step maxColumns config = makeStep "Cases" $ \ls (module', _) ->
, change_ <- align maxColumns aligns
]
- configured = concat $
- [changes cases altToAlignable | cCases config] ++
- [changes tlpats matchToAlignable | cTopLevelPatterns config] ++
+ configured = concat $
+ [ changes cases (altToAlignable H.mergeSrcSpan)
+ | cCases config
+ ] ++
+ [changes tlpats matchToAlignable | cTopLevelPatterns config] ++
[changes records fieldDeclToAlignable | cRecords config]
in applyChanges configured ls
diff --git a/lib/Language/Haskell/Stylish/Step/Squash.hs b/lib/Language/Haskell/Stylish/Step/Squash.hs
new file mode 100644
index 0000000..0eb4895
--- /dev/null
+++ b/lib/Language/Haskell/Stylish/Step/Squash.hs
@@ -0,0 +1,62 @@
+--------------------------------------------------------------------------------
+module Language.Haskell.Stylish.Step.Squash
+ ( step
+ ) where
+
+
+--------------------------------------------------------------------------------
+import Data.Maybe (mapMaybe)
+import qualified Language.Haskell.Exts as H
+
+
+--------------------------------------------------------------------------------
+import Language.Haskell.Stylish.Editor
+import Language.Haskell.Stylish.Step
+import Language.Haskell.Stylish.Util
+
+
+--------------------------------------------------------------------------------
+squash
+ :: (H.Annotated l, H.Annotated r)
+ => l H.SrcSpan -> r H.SrcSpan -> Maybe (Change String)
+squash left right
+ | H.srcSpanEndLine lAnn == H.srcSpanStartLine rAnn = Just $
+ changeLine (H.srcSpanEndLine lAnn) $ \str ->
+ let (pre, post) = splitAt (H.srcSpanEndColumn lAnn) str
+ in [trimRight pre ++ " " ++ trimLeft post]
+ | otherwise = Nothing
+ where
+ lAnn = H.ann left
+ rAnn = H.ann right
+
+
+--------------------------------------------------------------------------------
+squashFieldDecl :: H.FieldDecl H.SrcSpan -> Maybe (Change String)
+squashFieldDecl (H.FieldDecl _ names type')
+ | null names = Nothing
+ | otherwise = squash (last names) type'
+
+
+--------------------------------------------------------------------------------
+squashMatch :: H.Match H.SrcSpan -> Maybe (Change String)
+squashMatch (H.InfixMatch _ _ _ _ _ _) = Nothing
+squashMatch (H.Match _ name pats rhs _)
+ | null pats = squash name rhs
+ | otherwise = squash (last pats) rhs
+
+
+--------------------------------------------------------------------------------
+squashAlt :: H.Alt H.SrcSpan -> Maybe (Change String)
+squashAlt (H.Alt _ pat rhs _) = squash pat rhs
+
+
+--------------------------------------------------------------------------------
+step :: Step
+step = makeStep "Squash" $ \ls (module', _) ->
+ let module'' = fmap H.srcInfoSpan module'
+ changes = concat
+ [ mapMaybe squashAlt (everything module'')
+ , mapMaybe squashMatch (everything module'')
+ , mapMaybe squashFieldDecl (everything module'')
+ ]
+ in applyChanges changes ls
diff --git a/lib/Language/Haskell/Stylish/Util.hs b/lib/Language/Haskell/Stylish/Util.hs
index 54abef5..c634043 100644
--- a/lib/Language/Haskell/Stylish/Util.hs
+++ b/lib/Language/Haskell/Stylish/Util.hs
@@ -6,6 +6,8 @@ module Language.Haskell.Stylish.Util
, padRight
, everything
, infoPoints
+ , trimLeft
+ , trimRight
, wrap
, wrapRest
@@ -18,7 +20,7 @@ module Language.Haskell.Stylish.Util
--------------------------------------------------------------------------------
import Control.Arrow ((&&&), (>>>))
-import Data.Char (isAlpha)
+import Data.Char (isAlpha, isSpace)
import Data.Data (Data)
import qualified Data.Generics as G
import Data.Maybe (fromMaybe, listToMaybe,
@@ -69,6 +71,16 @@ infoPoints = H.srcInfoPoints >>> map (H.srcSpanStart &&& H.srcSpanEnd)
--------------------------------------------------------------------------------
+trimLeft :: String -> String
+trimLeft = dropWhile isSpace
+
+
+--------------------------------------------------------------------------------
+trimRight :: String -> String
+trimRight = reverse . trimLeft . reverse
+
+
+--------------------------------------------------------------------------------
wrap :: Int -- ^ Maximum line width
-> String -- ^ Leading string
-> Int -- ^ Indentation
diff --git a/scripts/latest.sh b/scripts/latest.sh
new file mode 100755
index 0000000..dc5c345
--- /dev/null
+++ b/scripts/latest.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+# Ported from https://raw.githubusercontent.com/ndmitchell/neil/master/misc/travis.sh
+
+set -e
+
+PACKAGE=stylish-haskell
+echo Downloading and running $PACKAGE...
+
+RELEASES=$(curl --silent https://github.com/jaspervdj/$PACKAGE/releases)
+URL=https://github.com/$(echo $RELEASES | grep -o '\"[^\"]*-linux-x86_64\.tar\.gz\"' | sed s/\"//g | head -n1)
+VERSION=$(echo $URL | sed -e 's/.*-\([\.0-9]\+\)-linux-x86_64\.tar\.gz/\1/')
+TEMP=$(mktemp --directory .$PACKAGE-XXXXX)
+
+cleanup(){
+ rm -r $TEMP
+}
+trap cleanup EXIT
+
+curl --progress-bar --location -o$TEMP/$PACKAGE.tar.gz $URL
+tar -xzf $TEMP/$PACKAGE.tar.gz -C$TEMP
+$TEMP/$PACKAGE-$VERSION/$PACKAGE $*
diff --git a/scripts/stylish-haskell.sh b/scripts/stylish-haskell.sh
new file mode 100755
index 0000000..a22712e
--- /dev/null
+++ b/scripts/stylish-haskell.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+# Ported from https://github.com/ndmitchell/hlint/blob/master/misc/travis.sh
+
+curl -sL https://raw.github.com/jaspervdj/stylish-haskell/master/scripts/latest.sh | sh -s -- stylish-haskell $*
diff --git a/src/Main.hs b/src/Main.hs
index 8eeb7ab..e71c795 100644
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -6,10 +6,10 @@ module Main
--------------------------------------------------------------------------------
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 @@ parseStylishArgs = StylishArgs
--------------------------------------------------------------------------------
stylishHaskellVersion :: String
-stylishHaskellVersion = "stylish-haskell " <> showVersion Paths_stylish_haskell.version
+stylishHaskellVersion = "stylish-haskell " <> showVersion version
--------------------------------------------------------------------------------
@@ -94,9 +94,8 @@ stylishHaskell sa = do
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)
diff --git a/stack.yaml b/stack.yaml
index ae1019c..ceda64e 100644
--- a/stack.yaml
+++ b/stack.yaml
@@ -1,9 +1,6 @@
flags: {}
packages:
- '.'
+resolver: lts-11.5
extra-deps:
-- 'optparse-applicative-0.14.0.0'
-resolver: 'nightly-2017-06-19'
-install-ghc: true
-system-ghc: false
-allow-newer: true
+- 'aeson-1.3.1.0'
diff --git a/stylish-haskell.cabal b/stylish-haskell.cabal
index aef50e4..31f9e23 100644
--- a/stylish-haskell.cabal
+++ b/stylish-haskell.cabal
@@ -1,5 +1,5 @@
Name: stylish-haskell
-Version: 0.8.1.0
+Version: 0.9.2.0
Synopsis: Haskell code prettifier
Homepage: https://github.com/jaspervdj/stylish-haskell
License: BSD3
@@ -18,11 +18,10 @@ Description:
<https://github.com/jaspervdj/stylish-haskell/blob/master/README.markdown>
-Data-files:
- data/stylish-haskell.yaml
-
Extra-source-files:
- CHANGELOG
+ CHANGELOG,
+ README.markdown,
+ data/stylish-haskell.yaml
Library
Hs-source-dirs: lib
@@ -33,6 +32,7 @@ Library
Language.Haskell.Stylish.Step.Imports
Language.Haskell.Stylish.Step.LanguagePragmas
Language.Haskell.Stylish.Step.SimpleAlign
+ Language.Haskell.Stylish.Step.Squash
Language.Haskell.Stylish.Step.Tabs
Language.Haskell.Stylish.Step.TrailingWhitespace
Language.Haskell.Stylish.Step.UnicodeSyntax
@@ -49,16 +49,18 @@ Library
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.4,
+ base >= 4.8 && < 5,
+ bytestring >= 0.9 && < 0.11,
+ containers >= 0.3 && < 0.6,
+ directory >= 1.2.3 && < 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,
+ semigroups >= 0.18 && < 0.19,
+ syb >= 0.3 && < 0.8,
+ yaml >= 0.7 && < 0.9
Executable stylish-haskell
Ghc-options: -Wall
@@ -70,16 +72,17 @@ Executable stylish-haskell
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.4,
+ base >= 4.8 && < 5,
+ bytestring >= 0.9 && < 0.11,
+ containers >= 0.3 && < 0.6,
+ directory >= 1.2.3 && < 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
@@ -97,6 +100,8 @@ Test-suite stylish-haskell-tests
Language.Haskell.Stylish.Step
Language.Haskell.Stylish.Step.SimpleAlign
Language.Haskell.Stylish.Step.SimpleAlign.Tests
+ Language.Haskell.Stylish.Step.Squash
+ Language.Haskell.Stylish.Step.Squash.Tests
Language.Haskell.Stylish.Step.Imports
Language.Haskell.Stylish.Step.Imports.Tests
Language.Haskell.Stylish.Step.LanguagePragmas
@@ -116,16 +121,17 @@ Test-suite stylish-haskell-tests
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.4,
+ base >= 4.8 && < 5,
+ bytestring >= 0.9 && < 0.11,
+ containers >= 0.3 && < 0.6,
+ directory >= 1.2.3 && < 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
diff --git a/tests/Language/Haskell/Stylish/Parse/Tests.hs b/tests/Language/Haskell/Stylish/Parse/Tests.hs
index 9806be2..a8ebf39 100644
--- a/tests/Language/Haskell/Stylish/Parse/Tests.hs
+++ b/tests/Language/Haskell/Stylish/Parse/Tests.hs
@@ -22,6 +22,7 @@ tests = testGroup "Language.Haskell.Stylish.Parse"
, 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
@@ -85,6 +86,16 @@ testShebang = assert $ isRight $ parseModule [] Nothing $ unlines
--------------------------------------------------------------------------------
+testShebangDouble :: Assertion
+testShebangDouble = assert $ isRight $ parseModule [] Nothing $ unlines
+ [ "#!nix-shell"
+ , "#!nix-shell -i runhaskell -p haskellPackages.ghc"
+ , "module Main where"
+ , "main = return ()"
+ ]
+
+--------------------------------------------------------------------------------
+
-- | These tests are for syntactic language extensions that should always be
-- enabled for parsing, even when the pragma is absent.
diff --git a/tests/Language/Haskell/Stylish/Step/Imports/Tests.hs b/tests/Language/Haskell/Stylish/Step/Imports/Tests.hs
index bc6772c..67c7c5a 100644
--- a/tests/Language/Haskell/Stylish/Step/Imports/Tests.hs
+++ b/tests/Language/Haskell/Stylish/Step/Imports/Tests.hs
@@ -52,6 +52,7 @@ tests = testGroup "Language.Haskell.Stylish.Step.Imports.Tests"
, testCase "case 23" case23
, testCase "case 24" case24
, testCase "case 25" case25
+ , testCase "case 26 (issue 185)" case26
]
@@ -663,3 +664,17 @@ case25 = expected
, ""
, "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"
+ ]
diff --git a/tests/Language/Haskell/Stylish/Step/SimpleAlign/Tests.hs b/tests/Language/Haskell/Stylish/Step/SimpleAlign/Tests.hs
index a57e6e9..b8afab4 100644
--- a/tests/Language/Haskell/Stylish/Step/SimpleAlign/Tests.hs
+++ b/tests/Language/Haskell/Stylish/Step/SimpleAlign/Tests.hs
@@ -25,6 +25,7 @@ tests = testGroup "Language.Haskell.Stylish.Step.SimpleAlign.Tests"
, testCase "case 05" case05
, testCase "case 06" case06
, testCase "case 07" case07
+ , testCase "case 08" case08
]
@@ -148,3 +149,20 @@ case07 =
, " , barqux :: Int"
, " }"
]
+
+
+--------------------------------------------------------------------------------
+case08 :: Assertion
+case08 = expected @=? testStep (step 80 defaultConfig) input
+ where
+ input = unlines
+ [ "canDrink mbAge = case mbAge of"
+ , " Just age | age > 18 -> True"
+ , " _ -> False"
+ ]
+
+ expected = unlines
+ [ "canDrink mbAge = case mbAge of"
+ , " Just age | age > 18 -> True"
+ , " _ -> False"
+ ]
diff --git a/tests/Language/Haskell/Stylish/Step/Squash/Tests.hs b/tests/Language/Haskell/Stylish/Step/Squash/Tests.hs
new file mode 100644
index 0000000..a785d9a
--- /dev/null
+++ b/tests/Language/Haskell/Stylish/Step/Squash/Tests.hs
@@ -0,0 +1,121 @@
+--------------------------------------------------------------------------------
+module Language.Haskell.Stylish.Step.Squash.Tests
+ ( tests
+ ) where
+
+
+--------------------------------------------------------------------------------
+import Test.Framework (Test, testGroup)
+import Test.Framework.Providers.HUnit (testCase)
+import Test.HUnit (Assertion, (@=?))
+
+
+--------------------------------------------------------------------------------
+import Language.Haskell.Stylish.Step.Squash
+import Language.Haskell.Stylish.Tests.Util
+
+
+--------------------------------------------------------------------------------
+tests :: Test
+tests = testGroup "Language.Haskell.Stylish.Step.SimpleSquash.Tests"
+ [ testCase "case 01" case01
+ , testCase "case 02" case02
+ , testCase "case 03" case03
+ , testCase "case 04" case04
+ , testCase "case 05" case05
+ ]
+
+
+--------------------------------------------------------------------------------
+case01 :: Assertion
+case01 = expected @=? testStep step input
+ where
+ input = unlines
+ [ "data Foo = Foo"
+ , " { foo :: Int"
+ , " , barqux :: String"
+ , " } deriving (Show)"
+ ]
+
+ expected = unlines
+ [ "data Foo = Foo"
+ , " { foo :: Int"
+ , " , barqux :: String"
+ , " } deriving (Show)"
+ ]
+
+
+--------------------------------------------------------------------------------
+case02 :: Assertion
+case02 = expected @=? testStep step input
+ where
+ input = unlines
+ [ "data Foo = Foo"
+ , " { fooqux"
+ , " , bar :: String"
+ , " } deriving (Show)"
+ ]
+
+ expected = unlines
+ [ "data Foo = Foo"
+ , " { fooqux"
+ , " , bar :: String"
+ , " } deriving (Show)"
+ ]
+
+
+--------------------------------------------------------------------------------
+case03 :: Assertion
+case03 = expected @=? testStep step input
+ where
+ input = unlines
+ [ "maybe y0 f mx ="
+ , " case mx of"
+ , " Nothing -> y0"
+ , " Just x -> f x"
+ ]
+
+ expected = unlines
+ [ "maybe y0 f mx ="
+ , " case mx of"
+ , " Nothing -> y0"
+ , " Just x -> f x"
+ ]
+
+
+--------------------------------------------------------------------------------
+case04 :: Assertion
+case04 = expected @=? testStep step input
+ where
+ input = unlines
+ [ "maybe y0 f mx ="
+ , " case mx of"
+ , " Nothing ->"
+ , " y0"
+ , " Just x ->"
+ , " f x"
+ ]
+
+ expected = unlines
+ [ "maybe y0 f mx ="
+ , " case mx of"
+ , " Nothing ->"
+ , " y0"
+ , " Just x ->"
+ , " f x"
+ ]
+
+
+--------------------------------------------------------------------------------
+case05 :: Assertion
+case05 = expected @=? testStep step input
+ where
+ input = unlines
+ [ "maybe y0 _ Nothing = y"
+ , "maybe _ f (Just x) = f x"
+ ]
+
+ expected = unlines
+ [ "maybe y0 _ Nothing = y"
+ , "maybe _ f (Just x) = f x"
+ ]
diff --git a/tests/TestSuite.hs b/tests/TestSuite.hs
index 853126d..27963a0 100644
--- a/tests/TestSuite.hs
+++ b/tests/TestSuite.hs
@@ -13,6 +13,7 @@ import qualified Language.Haskell.Stylish.Parse.Tests
import qualified Language.Haskell.Stylish.Step.Imports.Tests
import qualified Language.Haskell.Stylish.Step.LanguagePragmas.Tests
import qualified Language.Haskell.Stylish.Step.SimpleAlign.Tests
+import qualified Language.Haskell.Stylish.Step.Squash.Tests
import qualified Language.Haskell.Stylish.Step.Tabs.Tests
import qualified Language.Haskell.Stylish.Step.TrailingWhitespace.Tests
import qualified Language.Haskell.Stylish.Step.UnicodeSyntax.Tests
@@ -25,6 +26,7 @@ main = defaultMain
, Language.Haskell.Stylish.Step.Imports.Tests.tests
, Language.Haskell.Stylish.Step.LanguagePragmas.Tests.tests
, Language.Haskell.Stylish.Step.SimpleAlign.Tests.tests
+ , Language.Haskell.Stylish.Step.Squash.Tests.tests
, Language.Haskell.Stylish.Step.Tabs.Tests.tests
, Language.Haskell.Stylish.Step.TrailingWhitespace.Tests.tests
, Language.Haskell.Stylish.Step.UnicodeSyntax.Tests.tests