aboutsummaryrefslogtreecommitdiff
path: root/src/Text/Pandoc/Lua/Marshaling/ReaderOptions.hs
blob: 91eb22ae92a7279030a54e9a4ba6e69cff1a22e5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
{-# LANGUAGE LambdaCase           #-}
{-# LANGUAGE OverloadedStrings    #-}
{-# LANGUAGE ScopedTypeVariables  #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
{- |
   Module      : Text.Pandoc.Lua.Marshaling.ReaderOptions
   Copyright   : © 2012-2021 John MacFarlane
                 © 2017-2021 Albert Krewinkel
   License     : GNU GPL, version 2 or above

   Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
   Stability   : alpha

Marshaling instance for ReaderOptions and its components.
-}
module Text.Pandoc.Lua.Marshaling.ReaderOptions
  ( peekReaderOptions
  , pushReaderOptions
  , pushReaderOptionsReadonly
  ) where

import Data.Default (def)
import HsLua as Lua
import Text.Pandoc.Lua.Marshaling.List (pushPandocList)
import Text.Pandoc.Options (ReaderOptions (..))

--
-- Reader Options
--

-- | Retrieve a ReaderOptions value, either from a normal ReaderOptions
-- value, from a read-only object, or from a table with the same
-- keys as a ReaderOptions object.
peekReaderOptions :: LuaError e => Peeker e ReaderOptions
peekReaderOptions = retrieving "ReaderOptions" . \idx ->
  liftLua (ltype idx) >>= \case
    TypeUserdata -> choice [ peekUD typeReaderOptions
                           , peekUD typeReaderOptionsReadonly
                           ]
                           idx
    TypeTable    -> peekReaderOptionsTable idx
    _            -> failPeek =<<
                    typeMismatchMessage "ReaderOptions userdata or table" idx

-- | Pushes a ReaderOptions value as userdata object.
pushReaderOptions :: LuaError e => Pusher e ReaderOptions
pushReaderOptions = pushUD typeReaderOptions

-- | Pushes a ReaderOptions object, but makes it read-only.
pushReaderOptionsReadonly :: LuaError e => Pusher e ReaderOptions
pushReaderOptionsReadonly = pushUD typeReaderOptionsReadonly

-- | ReaderOptions object type for read-only values.
typeReaderOptionsReadonly :: LuaError e => DocumentedType e ReaderOptions
typeReaderOptionsReadonly = deftype "ReaderOptions (read-only)"
  [ operation Tostring $ lambda
    ### liftPure show
    <#> udparam typeReaderOptions "opts" "options to print in native format"
    =#> functionResult pushString "string" "Haskell representation"
  , operation Newindex $ lambda
    ### (failLua "This ReaderOptions value is read-only.")
    =?> "Throws an error when called, i.e., an assignment is made."
  ]
  readerOptionsMembers

-- | 'ReaderOptions' object type.
typeReaderOptions :: LuaError e => DocumentedType e ReaderOptions
typeReaderOptions = deftype "ReaderOptions"
  [ operation Tostring $ lambda
    ### liftPure show
    <#> udparam typeReaderOptions "opts" "options to print in native format"
    =#> functionResult pushString "string" "Haskell representation"
  ]
  readerOptionsMembers

-- | Member properties of 'ReaderOptions' Lua values.
readerOptionsMembers :: LuaError e
                     => [Member e (DocumentedFunction e) ReaderOptions]
readerOptionsMembers =
  [ property "abbreviations" ""
      (pushSet pushText, readerAbbreviations)
      (peekSet peekText, \opts x -> opts{ readerAbbreviations = x })
  , property "columns" ""
      (pushIntegral, readerColumns)
      (peekIntegral, \opts x -> opts{ readerColumns = x })
  , property "default_image_extension" ""
      (pushText, readerDefaultImageExtension)
      (peekText, \opts x -> opts{ readerDefaultImageExtension = x })
  , property "extensions" ""
      (pushString . show, readerExtensions)
      (peekRead, \opts x -> opts{ readerExtensions = x })
  , property "indented_code_classes" ""
      (pushPandocList pushText, readerIndentedCodeClasses)
      (peekList peekText, \opts x -> opts{ readerIndentedCodeClasses = x })
  , property "strip_comments" ""
      (pushBool, readerStripComments)
      (peekBool, \opts x -> opts{ readerStripComments = x })
  , property "standalone" ""
      (pushBool, readerStandalone)
      (peekBool, \opts x -> opts{ readerStandalone = x })
  , property "tab_stop" ""
      (pushIntegral, readerTabStop)
      (peekIntegral, \opts x -> opts{ readerTabStop = x })
  , property "track_changes" ""
      (pushString . show, readerTrackChanges)
      (peekRead, \opts x -> opts{ readerTrackChanges = x })
  ]

-- | Retrieves a 'ReaderOptions' object from a table on the stack, using
-- the default values for all missing fields.
--
-- Internally, this pushes the default reader options, sets each
-- key/value pair of the table in the userdata value, then retrieves the
-- object again. This will update all fields and complain about unknown
-- keys.
peekReaderOptionsTable :: LuaError e => Peeker e ReaderOptions
peekReaderOptionsTable idx = retrieving "ReaderOptions (table)" $ do
  liftLua $ do
    absidx <- absindex idx
    pushUD typeReaderOptions def
    let setFields = do
          next absidx >>= \case
            False -> return () -- all fields were copied
            True -> do
              pushvalue (nth 2) *> insert (nth 2)
              settable (nth 4) -- set in userdata object
              setFields
    pushnil -- first key
    setFields
  peekUD typeReaderOptions top

instance Pushable ReaderOptions where
  push = pushReaderOptions