{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE LambdaCase #-} {- | Copyright : © 2021-2023 Albert Krewinkel SPDX-License-Identifier : MIT Maintainer : Albert Krewinkel Marshaling/unmarshaling functions of table 'Cell' values. -} module Text.Pandoc.Lua.Marshal.Cell ( peekCell , peekCellFuzzy , pushCell , typeCell , mkCell ) where import Control.Applicative (optional) import Control.Monad ((<$!>)) import Data.Maybe (fromMaybe) import HsLua import Text.Pandoc.Lua.Marshal.Alignment (peekAlignment, pushAlignment) import Text.Pandoc.Lua.Marshal.Attr (peekAttr, pushAttr) import {-# SOURCE #-} Text.Pandoc.Lua.Marshal.Block ( peekBlocksFuzzy, pushBlocks ) import Text.Pandoc.Lua.Marshal.Filter (peekFilter) import Text.Pandoc.Lua.Marshal.Shared (walkBlocksAndInlines) import Text.Pandoc.Definition -- | Push a table cell as a table with fields @attr@, @alignment@, -- @row_span@, @col_span@, and @contents@. pushCell :: LuaError e => Cell -> LuaE e () pushCell = pushUD typeCell -- | Retrieves a 'Cell' object from the stack. peekCell :: LuaError e => Peeker e Cell peekCell = peekUD typeCell -- | Retrieves a 'Cell' from the stack, accepting either a 'pandoc Cell' -- userdata object or a table with fields @attr@, @alignment@, @row_span@, -- @col_span@, and @contents@. peekCellFuzzy :: LuaError e => Peeker e Cell peekCellFuzzy idx = liftLua (ltype idx) >>= \case TypeUserdata -> peekCell idx TypeTable -> do attr <- peekFieldRaw peekAttr "attr" idx algn <- peekFieldRaw peekAlignment "alignment" idx rs <- RowSpan <$!> peekFieldRaw peekIntegral "row_span" idx cs <- ColSpan <$!> peekFieldRaw peekIntegral "col_span" idx blks <- peekFieldRaw peekBlocksFuzzy "contents" idx return $! Cell attr algn rs cs blks _ -> failPeek =<< typeMismatchMessage "Cell or table" idx -- | Cell object type. typeCell :: LuaError e => DocumentedType e Cell typeCell = deftype "pandoc Cell" [ operation Eq $ defun "__eq" ### liftPure2 (\a b -> fromMaybe False ((==) <$> a <*> b)) <#> parameter (optional . peekCell) "Cell" "self" "" <#> parameter (optional . peekCell) "any" "object" "" =#> functionResult pushBool "boolean" "true iff the two values are equal" , operation Tostring $ lambda ### liftPure show <#> parameter peekCell "Cell" "self" "" =#> functionResult pushString "string" "native Haskell representation" ] [ property "attr" "cell attributes" (pushAttr, \(Cell attr _ _ _ _) -> attr) (peekAttr, \(Cell _ align rs cs blks) attr -> Cell attr align rs cs blks) , property "alignment" "alignment of cell contents" (pushAlignment, \(Cell _ align _ _ _) -> align) (peekAlignment, \(Cell attr _ rs cs blks) align -> Cell attr align rs cs blks) , property "row_span" "number of rows over which this cell spans" (pushIntegral, \(Cell _ _ (RowSpan rs) _ _) -> rs) (peekIntegral, \(Cell attr align _ cs blks) rs -> Cell attr align (RowSpan rs) cs blks) , property "col_span" "number of columns over which this cell spans" (pushIntegral, \(Cell _ _ _ (ColSpan rs) _) -> rs) (peekIntegral, \(Cell attr align rs _ blks) cs -> Cell attr align rs (ColSpan cs) blks) , property "contents" "cell contents" (pushBlocks, \(Cell _ _ _ _ blks) -> blks) (peekBlocksFuzzy, \(Cell attr align rs cs _) blks -> Cell attr align rs cs blks) , alias "content" "alias for contents" ["contents"] , alias "identifier" "cell ID" ["attr", "identifier"] , alias "classes" "cell classes" ["attr", "classes"] , alias "attributes" "cell attributes" ["attr", "attributes"] , method $ defun "walk" ### flip walkBlocksAndInlines <#> parameter peekCell "Cell" "self" "" <#> parameter peekFilter "Filter" "lua_filter" "table of filter functions" =#> functionResult pushCell "Cell" "modified cell" ] -- | Constructor function for 'Cell' values. mkCell :: LuaError e => DocumentedFunction e mkCell = defun "Cell" ### liftPure5 (\blocks mAlign mRowSpan mColSpan mAttr -> Cell (fromMaybe nullAttr mAttr) (fromMaybe AlignDefault mAlign) (maybe 1 RowSpan mRowSpan) (maybe 1 ColSpan mColSpan) blocks) <#> parameter peekBlocksFuzzy "Blocks" "blocks" "document contents" <#> opt (parameter peekAlignment "integer" "align" "cell alignment") <#> opt (parameter peekIntegral "integer" "row_span" "rows to span") <#> opt (parameter peekIntegral "integer" "col_span" "columns to span") <#> opt (parameter peekAttr "Attr" "attr" "cell attributes") =#> functionResult pushCell "Cell" "new Cell object"