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
|
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{- |
Module : Text.Pandoc.Lua.Module.CLI
Copyright : © 2022-2023 Albert Krewinkel
License : GPL-2.0-or-later
Maintainer : Albert Krewinkel <[email protected]>
Command line helpers
-}
module Text.Pandoc.Lua.Module.CLI
( documentedModule
) where
import Control.Applicative ((<|>))
import Data.Version (makeVersion)
import HsLua
import HsLua.REPL (defaultConfig, replWithEnv, setup)
import Text.Pandoc.App (defaultOpts, options, parseOptionsFromArgs)
import Text.Pandoc.Error (PandocError)
import Text.Pandoc.Lua.PandocLua ()
import qualified Data.Text as T
-- | Push the pandoc.types module on the Lua stack.
documentedModule :: Module PandocError
documentedModule = Module
{ moduleName = "pandoc.cli"
, moduleDescription =
"Command line options and argument parsing."
, moduleFields =
[ Field
{ fieldName = "default_options"
, fieldType = "table"
, fieldDescription = "Default CLI options, using a JSON-like " <>
"representation."
, fieldPushValue = pushViaJSON defaultOpts
}
]
, moduleFunctions =
[ defun "parse_options"
### parseOptions
<#> parameter peekArgs "{string,...}" "args"
"list of command line arguments"
=#> functionResult pushViaJSON "table"
"parsed options, using their JSON-like representation."
#? T.unlines
[ "Parses command line arguments into pandoc options."
, "Typically this function will be used in stand-alone pandoc Lua"
, "scripts, taking the list of arguments from the global `arg`."
]
`since` makeVersion [3, 0]
, repl `since` makeVersion [3, 1, 2]
]
, moduleOperations = []
, moduleTypeInitializers = []
}
where
peekArgs idx =
(,)
<$> (liftLua (rawgeti idx 0) *> (peekString top <|> pure "") `lastly` pop 1)
<*> peekList peekString idx
parseOptions (prg, args) =
liftIO (parseOptionsFromArgs options defaultOpts prg args) >>=
\case
Left e -> failLua $ "Cannot process info option: " ++ show e
Right opts -> pure opts
-- | Starts a REPL.
repl :: DocumentedFunction PandocError
repl = defun "repl"
### (\menvIdx -> do
let repl' = case menvIdx of
Nothing -> replWithEnv Nothing
Just envIdx -> do
settop envIdx
fillWithGlobals envIdx
replWithEnv . Just =<< ref registryindex
setup defaultConfig
repl')
<#> opt (parameter (typeChecked "table" istable pure) "table" "env"
("Extra environment; the global environment is merged into this" <>
" table."))
=?> T.unlines
[ "The result(s) of the last evaluated input, or nothing if the last"
, "input resulted in an error."
]
#? T.unlines
[ "Starts a read-eval-print loop (REPL). The function returns all"
, "values of the last evaluated input. Exit the REPL by pressing"
, "`ctrl-d` or `ctrl-c`; press `F1` to get a list of all key"
, "bindings."
, ""
, "The REPL is started in the global namespace, unless the `env`"
, "parameter is specified. In that case, the global namespace is"
, "merged into the given table and the result is used as `_ENV` value"
, "for the repl."
, ""
, "Specifically, local variables *cannot* be accessed, unless they"
, "are explicitly passed via the `env` parameter; e.g."
, ""
, " function Pandoc (doc)"
, " -- start repl, allow to access the `doc` parameter"
, " -- in the repl"
, " return pandoc.cli.repl{ doc = doc }"
, " end"
, ""
, "**Note**: it seems that the function exits immediately on Windows,"
, "without prompting for user input."
]
where
fillWithGlobals idx = do
-- Copy all global values into the table
pushglobaltable
pushnil
let copyval = next (nth 2) >>= \case
False -> return ()
True -> do
pushvalue (nth 2)
insert (nth 2)
rawset idx
copyval
copyval
pop 1 -- global table
|