emacs-module-0.2: src/Data/Emacs/Module/Doc.hs
----------------------------------------------------------------------------
-- |
-- Module : Data.Emacs.Module.Doc
-- Copyright : (c) Sergey Vinokurov 2022
-- License : Apache-2.0 (see LICENSE)
-- Maintainer : serg.foo@gmail.com
--
-- Defines type that provides function's documentation that would be visible
-- in Emacs.
----------------------------------------------------------------------------
{-# LANGUAGE MagicHash #-}
module Data.Emacs.Module.Doc
( Doc
, mkLiteralDoc
, mkTextDoc
, useDocAsCString
) where
import Data.String
import Data.Text (Text)
import Data.Text qualified as T
import Data.Text.Foreign qualified as T
import Foreign.C.String
import GHC.Exts
data Doc
= StaticDoc Addr#
| DynamicDoc !Text
instance Show Doc where
show = \case
DynamicDoc x -> show x
StaticDoc addr -> show (unpackCString# addr)
instance IsString Doc where
{-# INLINE fromString #-}
fromString = mkStringDoc
mkStringDoc :: String -> Doc
mkStringDoc = mkTextDoc . T.pack
{-# INLINE [0] mkStringDoc #-}
{-# RULES
"Doc string literal" forall s .
mkStringDoc (unpackCString# s) = mkLiteralDoc s
#-}
-- | Indended to be used with unboxed string literals like this
--
-- @
-- mkLiteralDoc "foo"#
-- @
{-# INLINE mkLiteralDoc #-}
mkLiteralDoc :: Addr# -> Doc
mkLiteralDoc = StaticDoc
-- | Turn abritrary bytestring into 'Doc'.
{-# INLINE mkTextDoc #-}
mkTextDoc :: Text -> Doc
mkTextDoc = DynamicDoc
{-# INLINE useDocAsCString #-}
useDocAsCString :: Doc -> (CString -> IO a) -> IO a
useDocAsCString doc f = case doc of
StaticDoc addr -> f (Ptr addr)
DynamicDoc str -> T.withCString str f