{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Text.Pandoc.Lua.Packages
( LuaPackageParams (..)
, installPandocPackageSearcher
) where
import Prelude
import Control.Monad (forM_)
import Data.ByteString (ByteString)
import Foreign.Lua (Lua, NumResults, liftIO)
import Text.Pandoc.Class (readDataFile, runIO, setUserDataDir)
import qualified Foreign.Lua as Lua
import Text.Pandoc.Lua.Module.Pandoc as Pandoc
import Text.Pandoc.Lua.Module.MediaBag as MediaBag
import Text.Pandoc.Lua.Module.System as System
import Text.Pandoc.Lua.Module.Types as Types
import Text.Pandoc.Lua.Module.Utils as Utils
data LuaPackageParams = LuaPackageParams
{ LuaPackageParams -> Maybe FilePath
luaPkgDataDir :: Maybe FilePath
}
installPandocPackageSearcher :: LuaPackageParams -> Lua ()
installPandocPackageSearcher :: LuaPackageParams -> Lua ()
installPandocPackageSearcher luaPkgParams :: LuaPackageParams
luaPkgParams = do
FilePath -> Lua ()
Lua.getglobal' "package.searchers"
Lua ()
shiftArray
(FilePath -> Lua NumResults) -> Lua ()
forall a. ToHaskellFunction a => a -> Lua ()
Lua.pushHaskellFunction (LuaPackageParams -> FilePath -> Lua NumResults
pandocPackageSearcher LuaPackageParams
luaPkgParams)
StackIndex -> Integer -> Lua ()
Lua.rawseti (CInt -> StackIndex
Lua.nthFromTop 2) 1
StackIndex -> Lua ()
Lua.pop 1
where
shiftArray :: Lua ()
shiftArray = [Integer] -> (Integer -> Lua ()) -> Lua ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [4, 3, 2, 1] ((Integer -> Lua ()) -> Lua ()) -> (Integer -> Lua ()) -> Lua ()
forall a b. (a -> b) -> a -> b
$ \i :: Integer
i -> do
StackIndex -> Integer -> Lua ()
Lua.rawgeti (-1) Integer
i
StackIndex -> Integer -> Lua ()
Lua.rawseti (-2) (Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ 1)
pandocPackageSearcher :: LuaPackageParams -> String -> Lua NumResults
pandocPackageSearcher :: LuaPackageParams -> FilePath -> Lua NumResults
pandocPackageSearcher pkgParams :: LuaPackageParams
pkgParams pkgName :: FilePath
pkgName =
case FilePath
pkgName of
"pandoc" -> let datadir :: Maybe FilePath
datadir = LuaPackageParams -> Maybe FilePath
luaPkgDataDir LuaPackageParams
pkgParams
in Lua NumResults -> Lua NumResults
forall a b. (ToHaskellFunction a, Num b) => a -> Lua b
pushWrappedHsFun (Maybe FilePath -> Lua NumResults
Pandoc.pushModule Maybe FilePath
datadir)
"pandoc.mediabag" -> Lua NumResults -> Lua NumResults
forall a b. (ToHaskellFunction a, Num b) => a -> Lua b
pushWrappedHsFun Lua NumResults
MediaBag.pushModule
"pandoc.system" -> Lua NumResults -> Lua NumResults
forall a b. (ToHaskellFunction a, Num b) => a -> Lua b
pushWrappedHsFun Lua NumResults
System.pushModule
"pandoc.types" -> Lua NumResults -> Lua NumResults
forall a b. (ToHaskellFunction a, Num b) => a -> Lua b
pushWrappedHsFun Lua NumResults
Types.pushModule
"pandoc.utils" -> let datadir :: Maybe FilePath
datadir = LuaPackageParams -> Maybe FilePath
luaPkgDataDir LuaPackageParams
pkgParams
in Lua NumResults -> Lua NumResults
forall a b. (ToHaskellFunction a, Num b) => a -> Lua b
pushWrappedHsFun (Maybe FilePath -> Lua NumResults
Utils.pushModule Maybe FilePath
datadir)
_ -> Lua NumResults
searchPureLuaLoader
where
pushWrappedHsFun :: a -> Lua b
pushWrappedHsFun f :: a
f = do
a -> Lua ()
forall a. ToHaskellFunction a => a -> Lua ()
Lua.pushHaskellFunction a
f
b -> Lua b
forall (m :: * -> *) a. Monad m => a -> m a
return 1
searchPureLuaLoader :: Lua NumResults
searchPureLuaLoader = do
let filename :: FilePath
filename = FilePath
pkgName FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ ".lua"
Maybe ByteString
modScript <- IO (Maybe ByteString) -> Lua (Maybe ByteString)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Maybe FilePath -> FilePath -> IO (Maybe ByteString)
dataDirScript (LuaPackageParams -> Maybe FilePath
luaPkgDataDir LuaPackageParams
pkgParams) FilePath
filename)
case Maybe ByteString
modScript of
Just script :: ByteString
script -> Lua NumResults -> Lua NumResults
forall a b. (ToHaskellFunction a, Num b) => a -> Lua b
pushWrappedHsFun (FilePath -> ByteString -> Lua NumResults
loadStringAsPackage FilePath
pkgName ByteString
script)
Nothing -> do
FilePath -> Lua ()
forall a. Pushable a => a -> Lua ()
Lua.push ("\n\tno file '" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
filename FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ "' in pandoc's datadir")
NumResults -> Lua NumResults
forall (m :: * -> *) a. Monad m => a -> m a
return 1
loadStringAsPackage :: String -> ByteString -> Lua NumResults
loadStringAsPackage :: FilePath -> ByteString -> Lua NumResults
loadStringAsPackage pkgName :: FilePath
pkgName script :: ByteString
script = do
Status
status <- ByteString -> Lua Status
Lua.dostring ByteString
script
if Status
status Status -> Status -> Bool
forall a. Eq a => a -> a -> Bool
== Status
Lua.OK
then NumResults -> Lua NumResults
forall (m :: * -> *) a. Monad m => a -> m a
return (1 :: NumResults)
else do
FilePath
msg <- Lua FilePath
forall a. Peekable a => Lua a
Lua.popValue
FilePath -> Lua NumResults
forall a. Pushable a => a -> Lua NumResults
Lua.raiseError ("Error while loading `" FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
pkgName FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> "`.\n" FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
msg)
dataDirScript :: Maybe FilePath -> FilePath -> IO (Maybe ByteString)
dataDirScript :: Maybe FilePath -> FilePath -> IO (Maybe ByteString)
dataDirScript datadir :: Maybe FilePath
datadir moduleFile :: FilePath
moduleFile = do
Either PandocError ByteString
res <- PandocIO ByteString -> IO (Either PandocError ByteString)
forall a. PandocIO a -> IO (Either PandocError a)
runIO (PandocIO ByteString -> IO (Either PandocError ByteString))
-> PandocIO ByteString -> IO (Either PandocError ByteString)
forall a b. (a -> b) -> a -> b
$ Maybe FilePath -> PandocIO ()
forall (m :: * -> *). PandocMonad m => Maybe FilePath -> m ()
setUserDataDir Maybe FilePath
datadir PandocIO () -> PandocIO ByteString -> PandocIO ByteString
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> FilePath -> PandocIO ByteString
forall (m :: * -> *). PandocMonad m => FilePath -> m ByteString
readDataFile FilePath
moduleFile
Maybe ByteString -> IO (Maybe ByteString)
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe ByteString -> IO (Maybe ByteString))
-> Maybe ByteString -> IO (Maybe ByteString)
forall a b. (a -> b) -> a -> b
$ case Either PandocError ByteString
res of
Left _ -> Maybe ByteString
forall a. Maybe a
Nothing
Right s :: ByteString
s -> ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just ByteString
s