Skip to content

Commit 4725900

Browse files
committed
Render doc when tostring is called on it
1 parent 47119ab commit 4725900

2 files changed

Lines changed: 23 additions & 3 deletions

File tree

src/Foreign/Lua/Module/DocLayout.hs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ import Foreign.Lua (Lua, NumResults (..), Optional,
3434
import Text.DocLayout (Doc)
3535

3636
import qualified Foreign.Lua as Lua
37+
import qualified Foreign.Lua.Types.Peekable as Lua
38+
import qualified Foreign.Lua.Userdata as Lua
3739
import qualified Text.DocLayout as Doc
3840

3941
--
@@ -63,19 +65,32 @@ render doc optLength = return $ Doc.render (Lua.fromOptional optLength) doc
6365
-- Marshaling
6466
--
6567

68+
-- | Name used for the @Doc@ Lua userdata values.
69+
docTypeName :: String
70+
docTypeName = "HsLua DocLayout.Doc"
71+
6672
-- | Retrieve a @Doc Text@ value from the Lua stack. Strings are
6773
-- converted to plain @'Doc'@ values.
6874
peekDoc :: StackIndex -> Lua (Doc Text)
6975
peekDoc idx = Lua.ltype idx >>= \case
70-
Lua.TypeString -> Doc.literal <$> Lua.peek idx
71-
_ -> Lua.peekAny idx
76+
Lua.TypeString -> Doc.literal <$> Lua.peek idx
77+
_ -> Lua.reportValueOnFailure docTypeName
78+
(`Lua.toAnyWithName` docTypeName)
79+
idx
7280

7381
instance Peekable (Doc Text) where
7482
peek = peekDoc
7583

7684
-- | Push a @Doc Text@ value to the Lua stack.
7785
pushDoc :: Doc Text -> Lua ()
78-
pushDoc = Lua.pushAny
86+
pushDoc = Lua.pushAnyWithMetatable pushDocMT
87+
where
88+
pushDocMT = Lua.ensureUserdataMetatable docTypeName $
89+
Lua.addfunction "__tostring" __tostring
7990

8091
instance Pushable (Doc Text) where
8192
push = pushDoc
93+
94+
-- | Convert to string by rendering without reflowing.
95+
__tostring :: Doc Text -> Lua Text
96+
__tostring d = return $ Doc.render Nothing d

test/test-doclayout.lua

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ return {
2727
group 'Doc type' {
2828
test('strings can be used as Doc values', function ()
2929
assert.are_equal(doclayout.render('hello world'), 'hello world')
30+
end),
31+
32+
test('has tostring method', function ()
33+
local str = 'just a literal string for now'
34+
assert.are_equal(tostring(str), str)
3035
end)
3136
}
3237
}

0 commit comments

Comments
 (0)