{-# LANGUAGE OverloadedStrings #-}
{- |
   Module      : Text.Pandoc.Lua.SourcePos
   Copyright   : © 2024 Albert Krewinkel
   License     : GPL-2.0-or-later
   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>

Helper function to retrieve the 'SourcePos' in a Lua script.
-}
module Text.Pandoc.Lua.SourcePos
  ( luaSourcePos
  ) where

import HsLua
import Text.Parsec.Pos (SourcePos, newPos)
import Text.Read (readMaybe)
import qualified Data.Text as T
import qualified HsLua.Core.Utf8 as UTF8

-- | Returns the current position in a Lua script.
--
-- The reporting level is the level of the call stack, for which the
-- position should be reported. There might not always be a position
-- available, e.g., in C functions.
luaSourcePos :: LuaError e
             => Int                -- ^ reporting level
             -> LuaE e (Maybe SourcePos)
luaSourcePos :: forall e. LuaError e => Int -> LuaE e (Maybe SourcePos)
luaSourcePos Int
lvl = do
  -- reporting levels:
  -- 0: this hook,
  -- 1: userdata wrapper function for the hook,
  -- 2: warn,
  -- 3: function calling warn.
  Int -> LuaE e ()
forall e. Int -> LuaE e ()
where' Int
lvl
  locStr <- ByteString -> Text
UTF8.toText (ByteString -> Text) -> LuaE e ByteString -> LuaE e Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StackIndex -> LuaE e ByteString
forall e. LuaError e => StackIndex -> LuaE e ByteString
tostring' StackIndex
top
  return $ do
    (prfx, sfx) <- T.breakOnEnd ":" <$> T.stripSuffix ": " locStr
    (source, _) <- T.unsnoc prfx
    line <- readMaybe (T.unpack sfx)
    -- We have no column information, so always use column 1
    Just $ newPos (T.unpack source) line 1