1+ {-# LANGUAGE BlockArguments #-}
12{-# LANGUAGE TypeApplications #-}
23{-# LANGUAGE OverloadedStrings #-}
34{-# LANGUAGE CPP #-}
45
5- module Haskell.Ide.Engine.Plugin.Ormolu ( ormoluDescriptor ) where
6+ module Haskell.Ide.Engine.Plugin.Ormolu
7+ ( ormoluDescriptor
8+ )
9+ where
610
7- import Haskell.Ide.Engine.MonadTypes
11+ import Haskell.Ide.Engine.MonadTypes
812
913#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
14+ import Control.Exception
15+ import Control.Monad
16+ import Control.Monad.IO.Class ( liftIO
17+ , MonadIO (.. )
18+ )
19+ import Data.Aeson ( Value (Null ) )
20+ import Data.Char
21+ import Data.List
22+ import Data.Maybe
23+ import qualified Data.Text as T
24+ import Ormolu
25+ import Haskell.Ide.Engine.PluginUtils
26+ import HIE.Bios.Types
2027#endif
2128
2229ormoluDescriptor :: PluginId -> PluginDescriptor
@@ -34,24 +41,59 @@ ormoluDescriptor plId = PluginDescriptor
3441
3542
3643provider :: FormattingProvider
37- provider _contents _uri _typ _opts =
3844#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
45+ provider contents uri typ _ = pluginGetFile contents uri $ \ fp -> do
46+ opts <- lookupComponentOptions fp
47+ let opts' =
48+ map DynOption
49+ $ filter exop
50+ $ join
51+ $ maybeToList
52+ $ componentOptions
53+ <$> opts
54+ conf = Config opts' False False True False
55+ fmt :: T. Text -> IdeM (Either OrmoluException T. Text )
56+ fmt cont = liftIO $ try @ OrmoluException (ormolu conf fp $ T. unpack cont)
57+
58+ case typ of
59+ FormatText -> ret (fullRange contents) <$> fmt contents
60+ FormatRange r ->
61+ let
62+ txt = T. lines $ extractRange r contents
63+ lineRange (Range (Position sl _) (Position el _)) =
64+ Range (Position sl 0 ) $ Position el $ T. length $ last txt
65+ -- Pragmas will not be picked up in a non standard location.
66+ pragmas = (takeWhile (" {-#" `T.isPrefixOf` ) $ T. lines contents) <> [" " ]
67+ unStrip ws new =
68+ T. init $ T. unlines $ map (ws `T.append` ) $ drop (length pragmas) $ T. lines new
69+ mStrip = case txt of
70+ (l : _) ->
71+ let ws = fst $ T. span isSpace l
72+ in (,) ws . T. unlines <$> traverse (T. stripPrefix ws) txt
73+ _ -> Nothing
74+ in
75+ maybe
76+ (return $ IdeResultFail
77+ (IdeError
78+ PluginError
79+ (T. pack
80+ " You must format a whole block of code. Ormolu does not support arbitrary ranges."
81+ )
82+ Null
83+ )
84+ )
85+ (\ (ws, striped) ->
86+ ret (lineRange r)
87+ <$> (fmap (unStrip ws) <$> fmt (T. unlines pragmas <> striped))
88+ )
89+ mStrip
90+ where
91+ ret _ (Left err) = IdeResultFail
92+ (IdeError PluginError (T. pack $ " ormoluCmd: " ++ show err) Null )
93+ ret r (Right new) = IdeResultOk [TextEdit r new]
94+
95+ exop s =
96+ " -X" `isPrefixOf` s || " -fplugin=" `isPrefixOf` s || " -pgmF=" `isPrefixOf` s
5597#else
56- return $ IdeResultOk [] -- NOP formatter
98+ provider _ _ _ _ = return $ IdeResultOk [] -- NOP formatter
5799#endif
0 commit comments