Skip to content
This repository was archived by the owner on Mar 22, 2021. It is now read-only.

Commit 6bbb097

Browse files
committed
Use hslua's new documented module feature
This allows to generate docs from the sources and improves error messages.
1 parent bdf840d commit 6bbb097

File tree

2 files changed

+127
-23
lines changed

2 files changed

+127
-23
lines changed

hslua-module-text.cabal

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ library
2626
exposed-modules: Foreign.Lua.Module.Text
2727
build-depends: base >= 4.8 && < 5
2828
, bytestring >= 0.10.2 && < 0.11
29-
, hslua >= 1.0.3 && < 1.3
29+
, hslua >= 1.2 && < 1.3
3030
, text >= 1 && < 1.3
3131
hs-source-dirs: src
3232
default-language: Haskell2010

src/Foreign/Lua/Module/Text.hs

Lines changed: 126 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
{-# LANGUAGE OverloadedStrings #-}
2+
{-# LANGUAGE TypeApplications #-}
23
{-|
34
Module : Foreign.Lua.Module.Text
4-
Copyright : © 2017–2019 Albert Krewinkel
5+
Copyright : © 2017–2020 Albert Krewinkel
56
License : MIT
67
Maintainer : Albert Krewinkel <[email protected]>
78
Stability : alpha
@@ -10,44 +11,147 @@ Portability : ForeignFunctionInterface
1011
Provide a lua module containing a selection of useful Text functions.
1112
-}
1213
module Foreign.Lua.Module.Text
13-
( pushModule
14+
15+
( -- * Module
16+
pushModule
17+
, preloadModule
18+
, documentedModule
19+
, description
20+
, functions
21+
22+
-- * Legacy
1423
, pushModuleText
1524
, preloadTextModule
16-
)where
25+
) where
1726

27+
import Prelude hiding (reverse)
1828
import Control.Applicative ((<$>))
1929
import Data.ByteString (ByteString)
2030
import Data.Text (Text)
2131
import Data.Maybe (fromMaybe)
2232
import Foreign.Lua (NumResults, Lua, Peekable, Pushable, ToHaskellFunction)
33+
import Foreign.Lua.Call
34+
import Foreign.Lua.Module hiding (preloadModule, pushModule)
35+
import Foreign.Lua.Peek (Peeker, peekIntegral, peekText)
36+
import Foreign.Lua.Push (pushIntegral, pushText)
2337
import qualified Foreign.Lua as Lua
2438
import qualified Data.Text as T
2539

40+
import qualified Foreign.Lua.Module as Module
41+
--
42+
-- Module
43+
--
44+
45+
-- | Textual description of the "text" module.
46+
description :: Text
47+
description =
48+
"UTF-8 aware text manipulation functions, implemented in Haskell."
49+
50+
documentedModule :: Module
51+
documentedModule = Module
52+
{ moduleName = "paths"
53+
, moduleFields = []
54+
, moduleDescription = description
55+
, moduleFunctions = functions
56+
}
57+
2658
-- | Pushes the @text@ module to the Lua stack.
2759
pushModule :: Lua NumResults
28-
pushModule = do
29-
Lua.newtable
30-
Lua.addfunction "lower" (return . T.toLower :: Text -> Lua Text)
31-
Lua.addfunction "upper" (return . T.toUpper :: Text -> Lua Text)
32-
Lua.addfunction "reverse" (return . T.reverse :: Text -> Lua Text)
33-
Lua.addfunction "len" (return . fromIntegral . T.length :: Text -> Lua Lua.Integer)
34-
Lua.addfunction "sub" sub
35-
return 1
36-
37-
-- | Legacy alias for '@pushModule@'.
60+
pushModule = 1 <$ Module.pushModule documentedModule
61+
3862
pushModuleText :: Lua NumResults
39-
pushModuleText = pushModule
63+
pushModuleText = 1 <$ Module.pushModule documentedModule
64+
65+
-- | Add the @text@ module under the given name to the table of
66+
-- preloaded packages.
67+
preloadModule :: String -> Lua ()
68+
preloadModule name = Module.preloadModule $
69+
documentedModule { moduleName = T.pack name }
4070

4171
-- | Add the text module under the given name to the table of preloaded
4272
-- packages.
4373
preloadTextModule :: String -> Lua ()
44-
preloadTextModule = flip Lua.preloadhs pushModule
74+
preloadTextModule = flip Lua.preloadhs pushModuleText
75+
76+
--
77+
-- Functions
78+
--
79+
80+
functions :: [(Text, HaskellFunction)]
81+
functions =
82+
[ ("len", len)
83+
, ("lower", lower)
84+
, ("reverse", reverse)
85+
, ("sub", sub)
86+
, ("upper", upper)
87+
]
88+
89+
-- | Wrapper for @'T.length'@.
90+
len :: HaskellFunction
91+
len = toHsFnPrecursor T.length
92+
<#> textParam "s"
93+
=#> intResult "length"
94+
#? "Determines the number of characters in a string."
95+
96+
-- | Wrapper for @'T.toLower'@.
97+
lower :: HaskellFunction
98+
lower = toHsFnPrecursor T.toLower
99+
<#> textParam "s"
100+
=#> textResult "Lowercase copy of `s`"
101+
#? "Convert a string to lower case"
102+
103+
-- | Wrapper for @'T.reverse'@.
104+
reverse :: HaskellFunction
105+
reverse = toHsFnPrecursor T.reverse
106+
<#> textParam "s"
107+
=#> textResult "Reversed `s`"
108+
#? "Reverses a string."
45109

46110
-- | Returns a substring, using Lua's string indexing rules.
47-
sub :: Text -> Lua.Integer -> Lua.Optional Lua.Integer -> Lua Text
48-
sub s i j =
49-
let i' = fromIntegral i
50-
j' = fromIntegral . fromMaybe (-1) $ Lua.fromOptional j
51-
fromStart = if i' >= 0 then i' - 1 else T.length s + i'
52-
fromEnd = if j' < 0 then -j' - 1 else T.length s - j'
53-
in return . T.dropEnd fromEnd . T.drop fromStart $ s
111+
sub :: HaskellFunction
112+
sub = toHsFnPrecursor substring
113+
<#> textParam "s"
114+
<#> textIndex "i" "substring start position"
115+
<#> textOptionalIndex "j" "substring end position"
116+
=#> textResult "text substring"
117+
#? "Returns a substring, using Lua's string indexing rules."
118+
where
119+
substring :: Text -> Int -> Maybe Int -> Text
120+
substring s i jopt =
121+
let j = fromMaybe (-1) jopt
122+
fromStart = if i >= 0 then i - 1 else T.length s + i
123+
fromEnd = if j < 0 then -j - 1 else T.length s - j
124+
in T.dropEnd fromEnd . T.drop fromStart $ s
125+
126+
-- | Wrapper for @'T.toUpper'@.
127+
upper :: HaskellFunction
128+
upper = toHsFnPrecursor T.toUpper
129+
<#> textParam "s"
130+
=#> textResult "Lowercase copy of `s`"
131+
#? "Convert a string to lower case"
132+
133+
--
134+
-- Parameters
135+
--
136+
137+
textParam :: Text -> Parameter Text
138+
textParam name =
139+
parameter peekText "string" name "UTF-8 encoded string"
140+
141+
textIndex :: Text -> Text -> Parameter Int
142+
textIndex = parameter (peekIntegral @Int) "integer"
143+
144+
textOptionalIndex :: Text -> Text -> Parameter (Maybe Int)
145+
textOptionalIndex = optionalParameter (peekIntegral @Int) "integer"
146+
147+
--
148+
-- Results
149+
--
150+
151+
textResult :: Text -- ^ Description
152+
-> FunctionResults Text
153+
textResult = functionResult pushText "string"
154+
155+
intResult :: Text -- ^ Description
156+
-> FunctionResults Int
157+
intResult = functionResult (pushIntegral @Int) "integer"

0 commit comments

Comments
 (0)