Skip to content

Commit ace226d

Browse files
committed
Add an option to run Fourmolu via the CLI interface of a separate binary, rather than the bundled library
This makes it easier to set up an environment (e.g. a Nix shell) which uses the same version of Fourmolu in HLS as from the command line. It can also be useful when Fourmolu has updated and we don't want to wait a month for an HLS release, or re-compile.
1 parent 0c21b0d commit ace226d

File tree

3 files changed

+35
-2
lines changed

3 files changed

+35
-2
lines changed

hls-plugin-api/src/Ide/Plugin/Config.hs

+3
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ data Config =
5050
{ checkParents :: CheckParents
5151
, checkProject :: !Bool
5252
, formattingProvider :: !T.Text
53+
, formattingCLI :: !Bool
5354
, maxCompletions :: !Int
5455
, plugins :: !(Map.Map T.Text PluginConfig)
5556
} deriving (Show,Eq)
@@ -62,6 +63,7 @@ instance Default Config where
6263
, formattingProvider = "ormolu"
6364
-- , formattingProvider = "floskell"
6465
-- , formattingProvider = "stylish-haskell"
66+
, formattingCLI = False
6567
, maxCompletions = 40
6668
, plugins = Map.empty
6769
}
@@ -78,6 +80,7 @@ parseConfig defValue = A.withObject "Config" $ \v -> do
7880
<$> (o .:? "checkParents" <|> v .:? "checkParents") .!= checkParents defValue
7981
<*> (o .:? "checkProject" <|> v .:? "checkProject") .!= checkProject defValue
8082
<*> o .:? "formattingProvider" .!= formattingProvider defValue
83+
<*> o .:? "formattingCLI" .!= formattingCLI defValue
8184
<*> o .:? "maxCompletions" .!= maxCompletions defValue
8285
<*> o .:? "plugin" .!= plugins defValue
8386

plugins/hls-fourmolu-plugin/hls-fourmolu-plugin.cabal

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ library
3030
, hls-plugin-api ^>=1.3
3131
, lens
3232
, lsp
33+
, process
3334
, text
3435

3536
default-language: Haskell2010

plugins/hls-fourmolu-plugin/src/Ide/Plugin/Fourmolu.hs

+31-2
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,28 @@ module Ide.Plugin.Fourmolu (
88
provider,
99
) where
1010

11-
import Control.Exception (try)
11+
import Control.Exception (IOException, try)
1212
import Control.Lens ((^.))
13+
import Control.Monad
1314
import Control.Monad.IO.Class
1415
import Data.Bifunctor (first)
16+
import Data.Maybe
1517
import qualified Data.Text as T
1618
import Development.IDE hiding (pluginHandlers)
1719
import Development.IDE.GHC.Compat as Compat hiding (Cpp)
1820
import qualified Development.IDE.GHC.Compat.Util as S
1921
import GHC.LanguageExtensions.Type (Extension (Cpp))
22+
import Ide.Plugin.Config (formattingCLI)
2023
import Ide.PluginUtils (makeDiffTextEdit)
2124
import Ide.Types
2225
import Language.LSP.Server hiding (defaultConfig)
2326
import Language.LSP.Types
2427
import Language.LSP.Types.Lens (HasTabSize (tabSize))
2528
import Ormolu
29+
import System.Exit
2630
import System.FilePath
31+
import System.IO (stderr, hPutStrLn)
32+
import System.Process
2733

2834
-- ---------------------------------------------------------------------
2935

@@ -41,7 +47,30 @@ provider ideState typ contents fp fo = withIndefiniteProgress title Cancellable
4147
fileOpts <- case hsc_dflags . hscEnv <$> ghc of
4248
Nothing -> return []
4349
Just df -> liftIO $ convertDynFlags df
44-
do
50+
useCLI <- formattingCLI <$> getConfig
51+
if useCLI
52+
then liftIO
53+
. fmap (join . first (mkError . show))
54+
. try @IOException
55+
$ do
56+
(exitCode, out, err) <-
57+
readProcessWithExitCode
58+
"fourmolu"
59+
( ["-d"]
60+
<> catMaybes
61+
[ ("--start-line=" <>) . show <$> regionStartLine region
62+
, ("--end-line=" <>) . show <$> regionEndLine region
63+
]
64+
<> map ("-o" <>) fileOpts
65+
)
66+
(T.unpack contents)
67+
hPutStrLn stderr err
68+
case exitCode of
69+
ExitSuccess ->
70+
pure . Right $ makeDiffTextEdit contents $ T.pack out
71+
ExitFailure n ->
72+
pure . Left . responseError $ "Fourmolu failed with exit code " <> T.pack (show n)
73+
else do
4574
let format printerOpts =
4675
first (mkError . show)
4776
<$> try @OrmoluException (makeDiffTextEdit contents <$> ormolu config fp' (T.unpack contents))

0 commit comments

Comments
 (0)