{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} module PureScript.Ide.Pursuit where import qualified Control.Exception as E import Control.Lens import Control.Monad import Data.Aeson import Data.Aeson.Lens import Data.Maybe import Data.Text (Text) import qualified Data.Text as T import Network.HTTP.Client (HttpException (StatusCodeException)) import Network.Wreq import PureScript.Ide.Externs (typeParse) import PureScript.Ide.Types instance FromJSON PursuitResponse where parseJSON (Object o) = do package <- o .: "package" info <- o .: "info" (type' :: String) <- info .: "type" case type' of "module" -> do name <- info .: "module" return ModuleResponse { moduleResponseName = name , moduleResponsePackage = package } "declaration" -> do moduleName <- info .: "module" Right (ident,declType) <- typeParse <$> o .: "text" return DeclarationResponse { declarationResponseType = declType , declarationResponseModule = moduleName , declarationResponseIdent = ident , declarationResponsePackage = package } _ -> mzero parseJSON _ = mzero queryUrl :: String queryUrl = "http://pursuit.purescript.org/search" jsonOpts :: Text -> Options jsonOpts q = defaults & header "Accept" .~ ["application/json"] & param "q" .~ [q] -- We need to remove trailing dots because Pursuit will return a 400 otherwise -- TODO: remove this when the issue is fixed at Pursuit queryPursuit q = getWith (jsonOpts (T.dropWhileEnd (== '.') q)) queryUrl handler :: HttpException -> IO [a] handler (StatusCodeException{}) = return [] handler _ = return [] searchPursuitForDeclarations :: Text -> IO [PursuitResponse] searchPursuitForDeclarations query = (do r <- queryPursuit query let results = map fromJSON (r ^.. responseBody . values) return (mapMaybe isDeclarationResponse results)) `E.catch` handler where isDeclarationResponse (Success a@(DeclarationResponse{})) = Just a isDeclarationResponse _ = Nothing findPackagesForModuleIdent :: Text -> IO [PursuitResponse] findPackagesForModuleIdent query = (do r <- queryPursuit query let results = map fromJSON (r ^.. responseBody . values) return (mapMaybe isModuleResponse results)) `E.catch` handler where isModuleResponse (Success a@(ModuleResponse{})) = Just a isModuleResponse _ = Nothing