2
2
{-# LANGUAGE OverloadedStrings #-}
3
3
{-# LANGUAGE CPP #-}
4
4
5
- module Haskell.Ide.Engine.Plugin.Ormolu ( ormoluDescriptor ) where
5
+ module Haskell.Ide.Engine.Plugin.Ormolu
6
+ ( ormoluDescriptor
7
+ )
8
+ where
6
9
7
- import Haskell.Ide.Engine.MonadTypes
10
+ import Haskell.Ide.Engine.MonadTypes
8
11
9
12
#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
20
30
#endif
21
31
22
32
ormoluDescriptor :: PluginId -> PluginDescriptor
@@ -34,24 +44,71 @@ ormoluDescriptor plId = PluginDescriptor
34
44
35
45
36
46
provider :: FormattingProvider
37
- provider _contents _uri _typ _opts =
38
47
#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
55
112
#else
56
- return $ IdeResultOk [] -- NOP formatter
113
+ provider _ _ _ _ = return $ IdeResultOk [] -- NOP formatter
57
114
#endif
0 commit comments