Lua: add a clone() method to all AST elements (#5572)

Closes: #5568
This commit is contained in:
Albert Krewinkel 2019-06-12 18:58:38 +02:00 committed by John MacFarlane
parent d81b9f55c1
commit 11bb862767
5 changed files with 112 additions and 1 deletions

View file

@ -28,6 +28,7 @@ local M = {}
M.List = require 'pandoc.List'
M.mediabag = require 'pandoc.mediabag'
M.system = require 'pandoc.system'
M.types = require 'pandoc.types'
M.utils = require 'pandoc.utils'
M.text = require 'text'
@ -280,6 +281,7 @@ end
-- @tparam {Block,...} blocks document content
-- @tparam[opt] Meta meta document meta data
M.Pandoc = AstElement:make_subtype'Pandoc'
M.Pandoc.behavior.clone = M.types.clone.Pandoc
function M.Pandoc:new (blocks, meta)
return {
blocks = ensureList(blocks),
@ -299,6 +301,7 @@ M.Doc = M.Pandoc
-- @function Meta
-- @tparam meta table table containing document meta information
M.Meta = AstElement:make_subtype'Meta'
M.Meta.behavior.clone = M.types.clone.Meta
function M.Meta:new (meta) return meta end
@ -306,6 +309,7 @@ function M.Meta:new (meta) return meta end
-- MetaValue
-- @section MetaValue
M.MetaValue = AstElement:make_subtype('MetaValue')
M.MetaValue.behavior.clone = M.types.clone.MetaValue
--- Meta blocks
-- @function MetaBlocks
@ -369,6 +373,7 @@ end
--- Block elements
M.Block = AstElement:make_subtype'Block'
M.Block.behavior.clone = M.types.clone.Block
--- Creates a block quote element
-- @function BlockQuote
@ -542,6 +547,7 @@ M.Table = M.Block:create_constructor(
--- Inline element class
M.Inline = AstElement:make_subtype'Inline'
M.Inline.behavior.clone = M.types.clone.Inline
--- Creates a Cite inline element
-- @function Cite
@ -898,6 +904,7 @@ function M.Attr:new (identifier, classes, attributes)
attributes = setmetatable(to_alist(attributes or {}), AttributeList)
return {identifier, classes, attributes}
end
M.Attr.behavior.clone = M.types.clone.Attr
M.Attr.behavior._field_names = {identifier = 1, classes = 2, attributes = 3}
M.Attr.behavior.__eq = utils.equals
M.Attr.behavior.__index = function(t, k)
@ -922,6 +929,7 @@ end
-- Citation
M.Citation = AstElement:make_subtype'Citation'
M.Citation.behavior.clone = M.types.clone.Citation
--- Creates a single citation.
-- @function Citation
@ -944,6 +952,7 @@ end
-- ListAttributes
M.ListAttributes = AstElement:make_subtype 'ListAttributes'
M.ListAttributes.behavior.clone = M.types.clone.ListAttributes
--- Creates a set of list attributes.
-- @function ListAttributes

View file

@ -644,6 +644,20 @@ This section describes the types of objects available to Lua
filters. See the [pandoc module](#module-pandoc}) for functions
to create these objects.
## Shared Properties
### `clone`
`clone ()`
All instances of the types listed here, with the exception of
read-only objects, can be cloned via the `clone()` method.
Usage:
local emph = pandoc.Emph {pandoc.Str 'important'}
local cloned_emph = emph:clone() -- note the colon
## Pandoc {#type-ref-pandoc}
Pandoc document
@ -1247,6 +1261,7 @@ Object equality is determined via
: delimiter of list numbers; one of `DefaultDelim`, `Period`,
`OneParen`, and `TwoParens` (string)
## Hierarchical Element {#type-ref-Element}
Hierarchical elements can be either *Sec* (sections) or *Blk*

View file

@ -14,7 +14,10 @@
Marshaling/unmarshaling instances for document AST elements.
-}
module Text.Pandoc.Lua.Marshaling.AST () where
module Text.Pandoc.Lua.Marshaling.AST
( LuaAttr (..)
, LuaListAttributes (..)
) where
import Prelude
import Control.Applicative ((<|>))

View file

@ -15,8 +15,11 @@ module Text.Pandoc.Lua.Module.Types
import Prelude
import Data.Version (Version)
import Foreign.Lua (Lua, NumResults)
import Text.Pandoc.Definition
import Text.Pandoc.Lua.Marshaling.AST (LuaAttr, LuaListAttributes)
import Text.Pandoc.Lua.Marshaling.Version ()
import Text.Pandoc.Lua.Util (addFunction)
import Text.Pandoc.Shared (Element (..))
import qualified Foreign.Lua as Lua
@ -25,4 +28,47 @@ pushModule :: Lua NumResults
pushModule = do
Lua.newtable
addFunction "Version" (return :: Version -> Lua Version)
pushCloneTable
Lua.setfield (Lua.nthFromTop 2) "clone"
return 1
pushCloneTable :: Lua NumResults
pushCloneTable = do
Lua.newtable
addFunction "Attr" cloneAttr
addFunction "Block" cloneBlock
addFunction "Citation" cloneCitation
addFunction "Element" cloneElement
addFunction "Inline" cloneInline
addFunction "Meta" cloneMeta
addFunction "MetaValue" cloneMetaValue
addFunction "ListAttributes" cloneListAttributes
addFunction "Pandoc" clonePandoc
return 1
cloneAttr :: LuaAttr -> Lua LuaAttr
cloneAttr = return
cloneBlock :: Block -> Lua Block
cloneBlock = return
cloneCitation :: Citation -> Lua Citation
cloneCitation = return
cloneElement :: Element -> Lua Element
cloneElement = return
cloneInline :: Inline -> Lua Inline
cloneInline = return
cloneListAttributes :: LuaListAttributes -> Lua LuaListAttributes
cloneListAttributes = return
cloneMeta :: Meta -> Lua Meta
cloneMeta = return
cloneMetaValue :: MetaValue -> Lua MetaValue
cloneMetaValue = return
clonePandoc :: Pandoc -> Lua Pandoc
clonePandoc = return

View file

@ -87,6 +87,44 @@ return {
end)
},
},
group 'clone' {
test('clones Attr', function ()
local attr = pandoc.Attr('test', {'my-class'}, {foo = 'bar'})
local cloned = attr:clone()
attr.identifier = ''
attr.classes = {}
attr.attributes = {}
assert.are_same(cloned.identifier, 'test')
assert.are_same(cloned.classes, {'my-class'})
assert.are_same(cloned.attributes.foo, 'bar')
end),
test('clones ListAttributes', function ()
local la = pandoc.ListAttributes(2, pandoc.DefaultStyle, pandoc.Period)
local cloned = la:clone()
la.start = 9
assert.are_same(cloned.start, 2)
end),
test('clones Para', function ()
local para = pandoc.Para {pandoc.Str 'Hello'}
local cloned = para:clone()
para.content[1].text = 'bye'
assert.are_same(cloned, pandoc.Para {pandoc.Str 'Hello'})
end),
test('clones Str', function ()
local str = pandoc.Str 'Hello'
local cloned = str:clone()
str.text = 'bye'
assert.are_same(cloned.text, 'Hello')
end),
test('clones Citation', function ()
local cite = pandoc.Citation('leibniz', pandoc.AuthorInText)
local cloned = cite:clone()
cite.id = 'newton'
assert.are_same(cloned.id, 'leibniz')
end),
},
group 'pipe' {
test('external string processing', function ()
if os_is_windows() then