From a23d14079c056af3c63d7903dfd17b30c1e1b8d6 Mon Sep 17 00:00:00 2001 From: Albert Krewinkel Date: Wed, 15 Mar 2023 18:25:17 +0100 Subject: [PATCH] pandoc-cli: add a Lua REPL --- doc/pandoc-lua.md | 24 +++++++++++++++---- pandoc-cli/lua/PandocCLI/Lua.hs | 29 +++++++++++++++++++---- pandoc-cli/pandoc-cli.cabal | 5 ++-- pandoc-lua-engine/pandoc-lua-engine.cabal | 2 +- stack.yaml | 5 ++-- 5 files changed, 51 insertions(+), 14 deletions(-) diff --git a/doc/pandoc-lua.md b/doc/pandoc-lua.md index 5badbfb3277d..2a9a58594c9b 100644 --- a/doc/pandoc-lua.md +++ b/doc/pandoc-lua.md @@ -18,8 +18,10 @@ Furthermore, the globals `PANDOC_VERSION`, `PANDOC_STATE`, and `PANDOC_API_VERSION` are set at startup. If no script argument is given, then the script is assumed to be -passed in via *stdin*. Interactive mode is not supported at this -time. +passed in via *stdin*. When called without arguments, `pandoc-lua` +behaves as `pandoc-lua -v -i` when the standard input (`stdin`) is +a terminal, and as `pandoc-lua -` otherwise. On Windows the +program will always behave as if it was connected to a terminal. When called without the option `-E`, the interpreter checks for an environment variable `LUA_INIT` before running any argument. If @@ -41,7 +43,7 @@ the string itself. : Show version information. `-i` -: Not supported yet; print a warning to that effect. +: Enter interactive mode after running *script*. `-E` : Ignore environment variables. This is not fully implemented @@ -51,9 +53,23 @@ the string itself. `-W` : Turn warnings on. +# INTERACTIVE MODE + +In interactive mode, the Lua interpreter repeatedly prompts and +waits for a line. After reading a line, Lua first tries to +interpret the line as an expression. If it succeeds, it prints its +value. Otherwise, it interprets the line as a statement. If you +write an incomplete statement, the interpreter waits for its +completion by issuing a different prompt. + +Exit the interactive mode by pressing `Ctrl-D` or `Ctrl-C`, or by +typing `os.exit()`. The *Isocline* library is used for line +editing. Press `F1` to get a list of available keybindings; the +`ctrl` key is abbreviated as `^` in that list. + # AUTHORS -Copyright 2022 John MacFarlane (jgm@berkeley.edu) and +Copyright 2023 John MacFarlane (jgm@berkeley.edu) and contributors. Released under the [GPL], version 2 or later. This software carries no warranty of any kind. (See COPYRIGHT for full copyright and warranty notices.) diff --git a/pandoc-cli/lua/PandocCLI/Lua.hs b/pandoc-cli/lua/PandocCLI/Lua.hs index 368f9cf49cbc..07259af04f3e 100644 --- a/pandoc-cli/lua/PandocCLI/Lua.hs +++ b/pandoc-cli/lua/PandocCLI/Lua.hs @@ -11,6 +11,9 @@ module PandocCLI.Lua (runLuaInterpreter, getEngine) where import Control.Monad ((<=<)) import HsLua.CLI (EnvBehavior (..), Settings (..), runStandalone) +import System.Environment (lookupEnv) +import System.IO.Temp (withSystemTempFile) +import System.IO (hClose) import Text.Pandoc.Class (runIOorExplode) import Text.Pandoc.Error (handleError) import Text.Pandoc.Lua (runLua, runLuaNoEnv, getEngine) @@ -18,16 +21,32 @@ import Text.Pandoc.Version (pandocVersionText) -- | Runs pandoc as a Lua interpreter that is (mostly) compatible with -- the default @lua@ program shipping with Lua. +-- +-- The filename for the history of the REPL is taken from the +-- @PANDOC_REPL_HISTORY@ environment variable if possible. Otherwise a +-- new temporary file is used; it is removed after the REPL finishes. runLuaInterpreter :: String -- ^ Program name -> [String] -- ^ Command line arguments -> IO () runLuaInterpreter progName args = do - let settings = Settings - { settingsVersionInfo = "\nEmbedded in pandoc " <> pandocVersionText - , settingsRunner = runner - } - runStandalone settings progName args + -- We need some kind of temp + mbhistfile <- lookupEnv "PANDOC_REPL_HISTORY" + case mbhistfile of + Just histfile -> runStandaloneWithHistory histfile + Nothing -> withSystemTempFile "pandoc-hist" $ \fp handle -> do + -- We cannot pass a handle to the repl; the file will be re-opened + -- there. + hClose handle + runStandaloneWithHistory fp where + runStandaloneWithHistory histfile = do + let settings = Settings + { settingsVersionInfo = "\nEmbedded in pandoc " <> + pandocVersionText + , settingsRunner = runner + , settingsHistory = Just histfile + } + runStandalone settings progName args runner envBehavior = let runLua' = case envBehavior of IgnoreEnvVars -> runLuaNoEnv diff --git a/pandoc-cli/pandoc-cli.cabal b/pandoc-cli/pandoc-cli.cabal index 8d9df6c3818f..0d28b0f9da4e 100644 --- a/pandoc-cli/pandoc-cli.cabal +++ b/pandoc-cli/pandoc-cli.cabal @@ -85,8 +85,9 @@ executable pandoc hs-source-dirs: no-server if flag(lua) - build-depends: hslua-cli >= 1.3 && < 1.4, - pandoc-lua-engine >= 0.1 && < 0.2 + build-depends: hslua-cli >= 1.4 && < 1.5, + pandoc-lua-engine >= 0.1 && < 0.2, + temporary >= 1.1 && < 1.4 hs-source-dirs: lua else hs-source-dirs: no-lua diff --git a/pandoc-lua-engine/pandoc-lua-engine.cabal b/pandoc-lua-engine/pandoc-lua-engine.cabal index abaae611d861..697dd3bdaabc 100644 --- a/pandoc-lua-engine/pandoc-lua-engine.cabal +++ b/pandoc-lua-engine/pandoc-lua-engine.cabal @@ -114,7 +114,7 @@ library , lpeg >= 1.0.4 && < 1.1 , mtl >= 2.2 && < 2.4 , pandoc >= 3.1 && < 3.2 - , pandoc-lua-marshal >= 0.2.1 && < 0.3 + , pandoc-lua-marshal >= 0.2.2 && < 0.3 , pandoc-types >= 1.22 && < 1.24 , parsec >= 3.1 && < 3.2 , text >= 1.1.1 && < 2.1 diff --git a/stack.yaml b/stack.yaml index 6a536199a2e0..918d7d46e6d9 100644 --- a/stack.yaml +++ b/stack.yaml @@ -13,7 +13,7 @@ extra-deps: - hslua-2.3.0 - hslua-aeson-2.3.0.1 - hslua-classes-2.3.0 -- hslua-cli-1.3.0 +- hslua-cli-1.4.0 - hslua-core-2.3.0 - hslua-list-1.1.0.1 - hslua-marshalling-2.3.0 @@ -25,6 +25,7 @@ extra-deps: - hslua-module-zip-1.1.0 - hslua-objectorientation-2.3.0 - hslua-packaging-2.3.0 +- hslua-repl-0.1.0 - hslua-typing-0.1.0 - jira-wiki-markup-1.5.1 - lua-2.3.0 @@ -35,7 +36,7 @@ extra-deps: - texmath-0.12.6 - citeproc-0.8.1 - pandoc-types-1.23 -- pandoc-lua-marshal-0.2.1.1 +- pandoc-lua-marshal-0.2.2 - commonmark-pandoc-0.2.1.3 - skylighting-0.13.2.1 - skylighting-core-0.13.2.1