packages feed

haskell-language-server-0.8.0.0: plugins/default/src/Ide/Plugin/StylishHaskell.hs

module Ide.Plugin.StylishHaskell
  (
    descriptor
  , provider
  )
where

import           Control.Monad.IO.Class
import           Data.Text (Text)
import qualified Data.Text as T
import           Development.IDE (IdeState)
import           Ide.PluginUtils
import           Ide.Types
import           Language.Haskell.Stylish
import           Language.Haskell.LSP.Types            as J

import           System.Directory
import           System.FilePath

descriptor :: PluginId -> PluginDescriptor IdeState
descriptor plId = (defaultPluginDescriptor plId)
  { pluginFormattingProvider = Just provider
  }

-- | Formatter provider of stylish-haskell.
-- Formats the given source in either a given Range or the whole Document.
-- If the provider fails an error is returned that can be displayed to the user.
provider :: FormattingProvider IdeState IO
provider _lf _ideState typ contents fp _opts = do
  let file = fromNormalizedFilePath fp
  config <- liftIO $ loadConfigFrom file
  let (range, selectedContents) = case typ of
        FormatText    -> (fullRange contents, contents)
        FormatRange r -> (normalize r, extractRange r contents)
      result = runStylishHaskell file config selectedContents
  case result of
    Left  err -> return $ Left $ responseError $ T.pack $ "stylishHaskellCmd: " ++ err
    Right new -> return $ Right $ J.List [TextEdit range new]

-- | Recursively search in every directory of the given filepath for .stylish-haskell.yaml.
-- If no such file has been found, return default config.
loadConfigFrom :: FilePath -> IO Config
loadConfigFrom file = do
  currDir <- getCurrentDirectory
  setCurrentDirectory (takeDirectory file)
  config <- loadConfig (makeVerbose False) Nothing
  setCurrentDirectory currDir
  return config

-- | Run stylish-haskell on the given text with the given configuration.
runStylishHaskell :: FilePath           -- ^ Location of the file being formatted. Used for error message
                  -> Config             -- ^ Configuration for stylish-haskell
                  -> Text               -- ^ Text to format
                  -> Either String Text -- ^ Either formatted Text or an error message
runStylishHaskell file config = fmap fromLines . fmt . toLines
  where
    fromLines = T.pack . unlines
    fmt = runSteps (configLanguageExtensions config) (Just file) (configSteps config)
    toLines = lines . T.unpack