Skip to content

Commit cbe47ce

Browse files
jaspervdjjhrcek
andcommitted
Make it possible to search for config without getCurrentDirectory
Co-Authored-By: Jan Hrček <honza.hrk@gmail.com>
1 parent 12c9118 commit cbe47ce

File tree

6 files changed

+56
-23
lines changed

6 files changed

+56
-23
lines changed

CHANGELOG

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
# CHANGELOG
22

3+
- UNRELEASED
4+
* #482 Add `ConfigSearchStrategy` to allow avoiding `getCurrentDirectory`
5+
when loading config (by Jan Hrček)
6+
7+
This is breaking API change that can be fixed like this:
8+
9+
```diff
10+
-format Nothing maybeFile contents
11+
+format SearchFromCurrentDirectory maybeFile contents
12+
13+
-format (Just cfgFile) maybeFile content
14+
+format (UseConfig cfgFile) maybeFile content
15+
```
16+
317
- 0.14.6.0 (2024-01-19)
418
* #471 Support GHC 9.8 (by Michael Peyton Jones)
519
* #440 Fix dissappearing `DEPRECATED` pragma on module (by Lev Dvorkin)

lib/Language/Haskell/Stylish.hs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ module Language.Haskell.Stylish
1919
, module Language.Haskell.Stylish.Verbose
2020
, version
2121
, format
22-
, ConfigPath(..)
22+
, ConfigSearchStrategy(..)
2323
, Lines
2424
, Step
2525
) where
@@ -105,14 +105,17 @@ runSteps ::
105105
runSteps exts mfp steps ls =
106106
foldM (runStep exts mfp) ls steps
107107

108-
newtype ConfigPath = ConfigPath { unConfigPath :: FilePath }
109108

110-
-- |Formats given contents optionally using the config provided as first param.
111-
-- The second file path is the location from which the contents were read.
112-
-- If provided, it's going to be printed out in the error message.
113-
format :: Maybe ConfigPath -> Maybe FilePath -> String -> IO (Either String Lines)
114-
format maybeConfigPath maybeFilePath contents = do
115-
conf <- loadConfig (makeVerbose True) (fmap unConfigPath maybeConfigPath)
109+
-- | Formats given contents.
110+
format ::
111+
ConfigSearchStrategy
112+
-> Maybe FilePath
113+
-- ^ the location from which the contents to format were read.
114+
-- If provided, it's going to be printed out in the error message.
115+
-> String -- ^ the contents to format
116+
-> IO (Either String Lines)
117+
format configSearchStrategy maybeFilePath contents = do
118+
conf <- loadConfig (makeVerbose True) configSearchStrategy
116119
pure $ runSteps (configLanguageExtensions conf) maybeFilePath (configSteps conf) $ lines contents
117120

118121

lib/Language/Haskell/Stylish/Config.hs

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
module Language.Haskell.Stylish.Config
77
( Extensions
88
, Config (..)
9+
, ConfigSearchStrategy (..)
910
, ExitCodeBehavior (..)
1011
, defaultConfigBytes
1112
, configFilePath
@@ -95,14 +96,27 @@ defaultConfigBytes = $(FileEmbed.embedFile "data/stylish-haskell.yaml")
9596

9697

9798
--------------------------------------------------------------------------------
98-
configFilePath :: Verbose -> Maybe FilePath -> IO (Maybe FilePath)
99-
configFilePath _ (Just userSpecified) = return (Just userSpecified)
100-
configFilePath verbose Nothing = do
101-
current <- getCurrentDirectory
99+
data ConfigSearchStrategy
100+
= -- | Don't try to search, just use given config file
101+
UseConfig FilePath
102+
| -- | Search for @.stylish-haskell.yaml@ starting from given directory.
103+
-- If not found, try all ancestor directories, @$XDG_CONFIG\/stylish-haskell\/config.yaml@ and @$HOME\/.stylish-haskell.yaml@ in order.
104+
-- If no config is found, default built-in config will be used.
105+
SearchFromDirectory FilePath
106+
| -- | Like SearchFromDirectory, but using current working directory as a starting point
107+
SearchFromCurrentDirectory
108+
109+
configFilePath :: Verbose -> ConfigSearchStrategy -> IO (Maybe FilePath)
110+
configFilePath _ (UseConfig userSpecified) = return (Just userSpecified)
111+
configFilePath verbose (SearchFromDirectory dir) = searchFrom verbose dir
112+
configFilePath verbose SearchFromCurrentDirectory = searchFrom verbose =<< getCurrentDirectory
113+
114+
searchFrom :: Verbose -> FilePath -> IO (Maybe FilePath)
115+
searchFrom verbose startDir = do
102116
configPath <- getXdgDirectory XdgConfig "stylish-haskell"
103-
home <- getHomeDirectory
117+
home <- getHomeDirectory
104118
search verbose $
105-
[d </> configFileName | d <- ancestors current] ++
119+
[d </> configFileName | d <- ancestors startDir] ++
106120
[configPath </> "config.yaml", home </> configFileName]
107121

108122
search :: Verbose -> [FilePath] -> IO (Maybe FilePath)
@@ -114,9 +128,9 @@ search verbose (f : fs) = do
114128
if exists then return (Just f) else search verbose fs
115129

116130
--------------------------------------------------------------------------------
117-
loadConfig :: Verbose -> Maybe FilePath -> IO Config
118-
loadConfig verbose userSpecified = do
119-
mbFp <- configFilePath verbose userSpecified
131+
loadConfig :: Verbose -> ConfigSearchStrategy -> IO Config
132+
loadConfig verbose configSearchStrategy = do
133+
mbFp <- configFilePath verbose configSearchStrategy
120134
verbose $ "Loading configuration at " ++ fromMaybe "<embedded>" mbFp
121135
bytes <- maybe (return defaultConfigBytes) B.readFile mbFp
122136
case decode1Strict bytes of

src/Main.hs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,9 @@ stylishHaskell sa = do
108108
BC8.putStr defaultConfigBytes
109109

110110
else do
111-
conf <- loadConfig verbose' (saConfig sa)
111+
conf <- loadConfig verbose' $ case saConfig sa of
112+
Nothing -> SearchFromCurrentDirectory
113+
Just fp -> UseConfig fp
112114
filesR <- case (saRecursive sa) of
113115
True -> findHaskellFiles (saVerbose sa) (saFiles sa)
114116
_ -> return $ saFiles sa

tests/Language/Haskell/Stylish/Config/Tests.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ createFilesAndGetConfig files = withTestDirTree $ do
9696
setCurrentDirectory "src"
9797
-- from that directory read the config file and extract extensions
9898
-- to make sure the search for .cabal file works
99-
loadConfig (const (pure ())) Nothing
99+
loadConfig (const (pure ())) SearchFromCurrentDirectory
100100

101101

102102
--------------------------------------------------------------------------------

tests/Language/Haskell/Stylish/Tests.hs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ tests = testGroup "Language.Haskell.Stylish.Tests"
3535

3636
--------------------------------------------------------------------------------
3737
case01 :: Assertion
38-
case01 = (@?= result) =<< format Nothing Nothing input
38+
case01 = (@?= result) =<< format SearchFromCurrentDirectory Nothing input
3939
where
4040
input = "module Herp where\ndata Foo = Bar | Baz { baz :: Int }"
4141
result = Right $ lines input
@@ -54,7 +54,7 @@ case02 = withTestDirTree $ do
5454
, " via: \"indent 2\""
5555
]
5656

57-
actual <- format (Just $ ConfigPath "test-config.yaml") Nothing input
57+
actual <- format (UseConfig "test-config.yaml") Nothing input
5858
actual @?= result
5959
where
6060
input = "module Herp where\ndata Foo = Bar | Baz { baz :: Int }"
@@ -79,7 +79,7 @@ case03 = withTestDirTree $ do
7979
, " via: \"indent 2\""
8080
]
8181

82-
actual <- format (Just $ ConfigPath "test-config.yaml") Nothing input
82+
actual <- format (UseConfig "test-config.yaml") Nothing input
8383
actual @?= result
8484
where
8585
input = unlines [ "module Herp where"
@@ -98,7 +98,7 @@ case03 = withTestDirTree $ do
9898

9999
--------------------------------------------------------------------------------
100100
case04 :: Assertion
101-
case04 = format Nothing (Just fileLocation) input >>= \case
101+
case04 = format SearchFromCurrentDirectory (Just fileLocation) input >>= \case
102102
Right _ -> assertFailure "expected error"
103103
Left err
104104
| fileLocation `isInfixOf` err

0 commit comments

Comments
 (0)