{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE LambdaCase #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Foreign.Lua.Module.DocLayout (
pushModule
, preloadModule
, after_break
, before_non_blank
, blankline
, blanklines
, braces
, brackets
, cblock
, chomp
, concat
, cr
, double_quotes
, empty
, flush
, hang
, inside
, lblock
, literal
, nest
, nestle
, nowrap
, parens
, prefixed
, quotes
, rblock
, space
, vfill
, render
, is_empty
, height
, min_offset
, offset
, real_length
, update_column
, peekDoc
, pushDoc
)
where
import Prelude hiding (concat)
import Data.List (intersperse)
import Data.Text (Text)
import Foreign.Lua (Lua, NumResults (..), Optional,
Peekable, Pushable, StackIndex)
import Text.DocLayout (Doc, (<+>), ($$), ($+$))
import qualified Data.Text as T
import qualified Foreign.Lua as Lua
import qualified Foreign.Lua.Types.Peekable as Lua
import qualified Foreign.Lua.Userdata as Lua
import qualified Text.DocLayout as Doc
#if ! MIN_VERSION_base(4, 11, 0)
import Data.Monoid ((<>))
#endif
pushModule :: Lua NumResults
pushModule = do
Lua.newtable
Lua.addfield "empty" empty
Lua.addfield "blankline" blankline
Lua.addfield "cr" cr
Lua.addfield "space" space
Lua.addfunction "after_break" after_break
Lua.addfunction "before_non_blank" before_non_blank
Lua.addfunction "blanklines" blanklines
Lua.addfunction "braces" braces
Lua.addfunction "brackets" brackets
Lua.addfunction "cblock" cblock
Lua.addfunction "chomp" chomp
Lua.addfunction "concat" concat
Lua.addfunction "double_quotes" double_quotes
Lua.addfunction "flush" flush
Lua.addfunction "hang" hang
Lua.addfunction "inside" inside
Lua.addfunction "lblock" lblock
Lua.addfunction "literal" literal
Lua.addfunction "nest" nest
Lua.addfunction "nestle" nestle
Lua.addfunction "nowrap" nowrap
Lua.addfunction "parens" parens
Lua.addfunction "quotes" quotes
Lua.addfunction "prefixed" prefixed
Lua.addfunction "rblock" rblock
Lua.addfunction "vfill" vfill
Lua.addfunction "is_empty" is_empty
Lua.addfunction "offset" offset
Lua.addfunction "height" height
Lua.addfunction "min_offset" min_offset
Lua.addfunction "offset" offset
Lua.addfunction "real_length" real_length
Lua.addfunction "update_column" update_column
Lua.addfunction "render" render
return 1
preloadModule :: String -> Lua ()
preloadModule = flip Lua.preloadhs pushModule
render :: Doc Text -> Optional Int -> Lua Text
render doc optLength = return $ Doc.render (Lua.fromOptional optLength) doc
is_empty :: Doc Text -> Lua Bool
is_empty = return . Doc.isEmpty
offset :: Doc Text -> Lua Int
offset = return . Doc.offset
min_offset :: Doc Text -> Lua Int
min_offset = return . Doc.minOffset
update_column :: Doc Text -> Int -> Lua Int
update_column doc = return . Doc.updateColumn doc
height :: Doc Text -> Lua Int
height = return . Doc.height
real_length :: Text -> Lua Int
real_length = return . Doc.realLength
after_break :: Text -> Lua (Doc Text)
after_break = return . Doc.afterBreak
before_non_blank :: Doc Text -> Lua (Doc Text)
before_non_blank = return . Doc.beforeNonBlank
blankline :: Doc Text
blankline = Doc.blankline
blanklines :: Int -> Lua (Doc Text)
blanklines = return . Doc.blanklines
braces :: Doc Text -> Lua (Doc Text)
braces = return . Doc.braces
brackets :: Doc Text -> Lua (Doc Text)
brackets = return . Doc.brackets
cblock :: Int -> Doc Text -> Lua (Doc Text)
cblock width = return . Doc.cblock width
chomp :: Doc Text -> Lua (Doc Text)
chomp = return . Doc.chomp
concat :: [Doc Text] -> Optional (Doc Text) -> Lua (Doc Text)
concat docs optSep = return $
case Lua.fromOptional optSep of
Nothing -> mconcat docs
Just sep -> mconcat $ intersperse sep docs
cr :: Doc Text
cr = Doc.cr
double_quotes :: Doc Text -> Lua (Doc Text)
double_quotes = return . Doc.doubleQuotes
empty :: Doc Text
empty = Doc.empty
flush :: Doc Text -> Lua (Doc Text)
flush = return . Doc.flush
hang :: Int -> Doc Text -> Doc Text -> Lua (Doc Text)
hang ind start doc = return $ Doc.hang ind start doc
inside :: Doc Text -> Doc Text -> Doc Text -> Lua (Doc Text)
inside start end contents = return $ Doc.inside start end contents
lblock :: Int -> Doc Text -> Lua (Doc Text)
lblock width = return . Doc.lblock width
literal :: Text -> Lua (Doc Text)
literal = return . Doc.literal
nest :: Int -> Doc Text -> Lua (Doc Text)
nest ind = return . Doc.nest ind
nestle :: Doc Text -> Lua (Doc Text)
nestle = return . Doc.nestle
nowrap :: Doc Text -> Lua (Doc Text)
nowrap = return . Doc.nowrap
parens :: Doc Text -> Lua (Doc Text)
parens = return . Doc.parens
prefixed :: Text -> Doc Text -> Lua (Doc Text)
prefixed prefix = return . Doc.prefixed (T.unpack prefix)
quotes :: Doc Text -> Lua (Doc Text)
quotes = return . Doc.quotes
rblock :: Int -> Doc Text -> Lua (Doc Text)
rblock width = return . Doc.rblock width
space :: Doc Text
space = Doc.space
vfill :: Text -> Lua (Doc Text)
vfill = return . Doc.vfill
docTypeName :: String
docTypeName = "HsLua DocLayout.Doc"
peekDoc :: StackIndex -> Lua (Doc Text)
peekDoc idx = Lua.ltype idx >>= \case
Lua.TypeString -> let stringToDoc s = if T.null s
then Doc.empty
else Doc.literal s
in stringToDoc <$> Lua.peek idx
Lua.TypeNumber -> Doc.literal <$> Lua.peek idx
_ -> Lua.reportValueOnFailure docTypeName
(`Lua.toAnyWithName` docTypeName)
idx
instance Peekable (Doc Text) where
peek = peekDoc
pushDoc :: Doc Text -> Lua ()
pushDoc = Lua.pushAnyWithMetatable pushDocMT
where
pushDocMT = Lua.ensureUserdataMetatable docTypeName $ do
Lua.addfunction "__add" __add
Lua.addfunction "__concat" __concat
Lua.addfunction "__div" __div
Lua.addfunction "__eq" __eq
Lua.addfunction "__idiv" __idiv
Lua.addfunction "__tostring" __tostring
instance Pushable (Doc Text) where
push = pushDoc
__add :: Doc Text -> Doc Text -> Lua (Doc Text)
__add a b = return (a <+> b)
__concat :: Doc Text -> Doc Text -> Lua (Doc Text)
__concat a b = return (a <> b)
__div :: Doc Text -> Doc Text -> Lua (Doc Text)
__div a b = return (a $$ b)
__eq :: Doc Text -> Doc Text -> Lua Bool
__eq a b = return (a == b)
__idiv :: Doc Text -> Doc Text -> Lua (Doc Text)
__idiv a b = return (a $+$ b)
__tostring :: Doc Text -> Lua Text
__tostring d = return $ Doc.render Nothing d