packages feed

pandoc-lua-engine-0.5: src/Text/Pandoc/Lua/Global.hs

{-# LANGUAGE LambdaCase         #-}
{-# LANGUAGE OverloadedStrings  #-}
{- |
   Module      : Text.Pandoc.Lua
   Copyright   : Copyright © 2017-2024 Albert Krewinkel
   License     : GNU GPL, version 2 or above

   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>
   Stability   : alpha

Pandoc's Lua globals.
-}
module Text.Pandoc.Lua.Global
  ( Global (..)
  , setGlobals
  ) where

import HsLua as Lua
import HsLua.Module.Version (pushVersion)
import Text.Pandoc.Class ( getInputFiles, getOutputFile, getLog
                         , getRequestHeaders, getResourcePath, getSourceURL
                         , getUserDataDir, getTrace, getVerbosity
                         )
import Text.Pandoc.Definition (Pandoc, pandocTypesVersion)
import Text.Pandoc.Error (PandocError)
import Text.Pandoc.Lua.Marshal.List (pushPandocList)
import Text.Pandoc.Lua.Marshal.LogMessage (pushLogMessage)
import Text.Pandoc.Lua.Marshal.Pandoc (pushPandoc)
import Text.Pandoc.Lua.Marshal.ReaderOptions (pushReaderOptionsReadonly)
import Text.Pandoc.Lua.Marshal.WriterOptions (pushWriterOptions)
import Text.Pandoc.Lua.PandocLua (unPandocLua)
import Text.Pandoc.Options (ReaderOptions, WriterOptions)
import Text.Pandoc.Version (pandocVersion)

import qualified Data.Text as Text

-- | Permissible global Lua variables.
data Global =
    FORMAT Text.Text
  | PANDOC_API_VERSION
  | PANDOC_DOCUMENT Pandoc
  | PANDOC_READER_OPTIONS ReaderOptions
  | PANDOC_WRITER_OPTIONS WriterOptions
  | PANDOC_SCRIPT_FILE FilePath
  | PANDOC_STATE
  | PANDOC_VERSION
  -- Cannot derive instance of Data because of CommonState

-- | Set all given globals.
setGlobals :: [Global] -> LuaE PandocError ()
setGlobals = mapM_ setGlobal

setGlobal :: Global -> LuaE PandocError ()
setGlobal global = case global of
  -- This could be simplified if Global was an instance of Data.
  FORMAT format -> do
    Lua.pushText format
    Lua.setglobal "FORMAT"
  PANDOC_API_VERSION -> do
    pushVersion pandocTypesVersion
    Lua.setglobal "PANDOC_API_VERSION"
  PANDOC_DOCUMENT doc -> do
    pushPandoc doc
    Lua.setglobal "PANDOC_DOCUMENT"
  PANDOC_READER_OPTIONS ropts -> do
    pushReaderOptionsReadonly ropts
    Lua.setglobal "PANDOC_READER_OPTIONS"
  PANDOC_WRITER_OPTIONS wopts -> do
    pushWriterOptions wopts
    Lua.setglobal "PANDOC_WRITER_OPTIONS"
  PANDOC_SCRIPT_FILE filePath -> do
    Lua.pushString filePath
    Lua.setglobal "PANDOC_SCRIPT_FILE"
  PANDOC_STATE -> do
    -- The common state is an opaque value. We provide a table that
    -- contains the values accessible through the PandocMonad API. This
    -- is for backwards compatibility, as the state used to be exposed
    -- as a read-only object.
    Lua.newtable
    Lua.newmetatable "CommonStateInterface"
    Lua.pushHaskellFunction $ do
      Lua.forcePeek (peekText (Lua.nthBottom 2)) >>= \case
        "input_files" -> do
          pushPandocList pushString =<< unPandocLua getInputFiles
          return 1
        "output_file" -> do
          maybe pushnil pushString =<< unPandocLua getOutputFile
          return 1
        "log" -> do
          pushPandocList pushLogMessage =<< unPandocLua getLog
          return 1
        "request_headers" -> do
          pushPandocList (pushPair pushText pushText)
                   =<< unPandocLua getRequestHeaders
          return 1
        "resource_path" -> do
          pushPandocList pushString =<< unPandocLua getResourcePath
          return 1
        "source_url" -> do
          maybe pushnil pushText =<< unPandocLua getSourceURL
          return 1
        "user_data_dir" -> do
          maybe pushnil pushString =<< unPandocLua getUserDataDir
          return 1
        "trace" -> do
          pushBool =<< unPandocLua getTrace
          return 1
        "verbosity" -> do
          pushString . show =<< unPandocLua getVerbosity
          return 1
        _ ->
          failLua "Unknown key"
    Lua.setfield (Lua.nth 2) "__index"
    Lua.setmetatable (Lua.nth 2)
    Lua.setglobal "PANDOC_STATE"
  PANDOC_VERSION              -> do
    pushVersion pandocVersion
    Lua.setglobal "PANDOC_VERSION"