Skip to content
This repository was archived by the owner on Oct 7, 2020. It is now read-only.

Commit 6dffe13

Browse files
authored
Merge pull request #1602 from Avi-D-coder/ormolu-range
Ormolu range format support
2 parents 535d482 + 02cef7f commit 6dffe13

File tree

1 file changed

+87
-30
lines changed

1 file changed

+87
-30
lines changed

src/Haskell/Ide/Engine/Plugin/Ormolu.hs

+87-30
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,31 @@
22
{-# LANGUAGE OverloadedStrings #-}
33
{-# LANGUAGE CPP #-}
44

5-
module Haskell.Ide.Engine.Plugin.Ormolu ( ormoluDescriptor ) where
5+
module Haskell.Ide.Engine.Plugin.Ormolu
6+
( ormoluDescriptor
7+
)
8+
where
69

7-
import Haskell.Ide.Engine.MonadTypes
10+
import Haskell.Ide.Engine.MonadTypes
811

912
#if __GLASGOW_HASKELL__ >= 806
10-
import Control.Exception
11-
import Control.Monad
12-
import Control.Monad.IO.Class ( liftIO , MonadIO(..) )
13-
import Data.Aeson ( Value ( Null ) )
14-
import Data.List
15-
import Data.Maybe
16-
import qualified Data.Text as T
17-
import Ormolu
18-
import Haskell.Ide.Engine.PluginUtils
19-
import HIE.Bios.Types
13+
import Control.Exception
14+
import Control.Monad
15+
import Control.Monad.IO.Class ( liftIO
16+
, MonadIO(..)
17+
)
18+
import Data.Aeson ( Value(Null) )
19+
import Data.Char
20+
import Data.List
21+
import Data.Maybe
22+
import qualified Data.Text as T
23+
import GHC
24+
import Ormolu
25+
import Haskell.Ide.Engine.PluginUtils
26+
import Haskell.Ide.Engine.Support.HieExtras
27+
import HIE.Bios.Types
28+
import qualified DynFlags as D
29+
import qualified EnumSet as S
2030
#endif
2131

2232
ormoluDescriptor :: PluginId -> PluginDescriptor
@@ -34,24 +44,71 @@ ormoluDescriptor plId = PluginDescriptor
3444

3545

3646
provider :: FormattingProvider
37-
provider _contents _uri _typ _opts =
3847
#if __GLASGOW_HASKELL__ >= 806
39-
case _typ of
40-
FormatRange _ -> return $ IdeResultFail (IdeError PluginError (T.pack "Selection formatting for Ormolu is not currently supported.") Null)
41-
FormatText -> pluginGetFile _contents _uri $ \file -> do
42-
opts <- lookupComponentOptions file
43-
let opts' = map DynOption $ filter exop $ join $ maybeToList $ componentOptions <$> opts
44-
conf = Config opts' False False True False
45-
result <- liftIO $ try @OrmoluException (ormolu conf file (T.unpack _contents))
46-
47-
case result of
48-
Left err -> return $ IdeResultFail (IdeError PluginError (T.pack $ "ormoluCmd: " ++ show err) Null)
49-
Right new -> return $ IdeResultOk [TextEdit (fullRange _contents) new]
50-
where
51-
exop s =
52-
"-X" `isPrefixOf` s
53-
|| "-fplugin=" `isPrefixOf` s
54-
|| "-pgmF=" `isPrefixOf` s
48+
provider contents uri typ _ = pluginGetFile contents uri $ \fp -> do
49+
opts <- lookupComponentOptions fp
50+
let cradleOpts =
51+
map DynOption
52+
$ filter exop
53+
$ join
54+
$ maybeToList
55+
$ componentOptions
56+
<$> opts
57+
58+
fromDyn tcm _ () =
59+
let
60+
df = getDynFlags tcm
61+
pp =
62+
let p = D.sPgm_F $ D.settings df
63+
in if null p then [] else ["-pgmF=" <> p]
64+
pm = map (("-fplugin=" <>) . moduleNameString) $ D.pluginModNames df
65+
ex = map (("-X" <>) . show) $ S.toList $ D.extensionFlags df
66+
in
67+
return $ map DynOption $ pp <> pm <> ex
68+
fileOpts <- ifCachedModuleAndData fp cradleOpts fromDyn
69+
let
70+
conf o = Config o False False True False
71+
fmt :: T.Text -> [DynOption] -> IdeM (Either OrmoluException T.Text)
72+
fmt cont o =
73+
liftIO $ try @OrmoluException (ormolu (conf o) fp $ T.unpack cont)
74+
75+
case typ of
76+
FormatText -> ret (fullRange contents) <$> fmt contents cradleOpts
77+
FormatRange r ->
78+
let
79+
txt = T.lines $ extractRange r contents
80+
lineRange (Range (Position sl _) (Position el _)) =
81+
Range (Position sl 0) $ Position el $ T.length $ last txt
82+
hIsSpace (h : _) = T.all isSpace h
83+
hIsSpace _ = True
84+
fixS t = if hIsSpace txt && (not $ hIsSpace t) then "" : t else t
85+
fixE t = if T.all isSpace $ last txt then t else T.init t
86+
unStrip ws new =
87+
fixE $ T.unlines $ map (ws `T.append`) $ fixS $ T.lines new
88+
mStrip = case txt of
89+
(l : _) ->
90+
let ws = fst $ T.span isSpace l
91+
in (,) ws . T.unlines <$> traverse (T.stripPrefix ws) txt
92+
_ -> Nothing
93+
err = return $ IdeResultFail
94+
(IdeError
95+
PluginError
96+
(T.pack
97+
"You must format a whole block of code. Ormolu does not support arbitrary ranges."
98+
)
99+
Null
100+
)
101+
fmt' (ws, striped) =
102+
ret (lineRange r) <$> (fmap (unStrip ws) <$> fmt striped fileOpts)
103+
in
104+
maybe err fmt' mStrip
105+
where
106+
ret _ (Left err) = IdeResultFail
107+
(IdeError PluginError (T.pack $ "ormoluCmd: " ++ show err) Null)
108+
ret r (Right new) = IdeResultOk [TextEdit r new]
109+
110+
exop s =
111+
"-X" `isPrefixOf` s || "-fplugin=" `isPrefixOf` s || "-pgmF=" `isPrefixOf` s
55112
#else
56-
return $ IdeResultOk [] -- NOP formatter
113+
provider _ _ _ _ = return $ IdeResultOk [] -- NOP formatter
57114
#endif

0 commit comments

Comments
 (0)