hslua-repl-0.1.2/0000755000000000000000000000000007346545000011757 5ustar0000000000000000hslua-repl-0.1.2/CHANGELOG.md0000644000000000000000000000114107346545000013565 0ustar0000000000000000# Changelog `hslua-repl` uses [PVP Versioning](https://pvp.haskell.org). ## hslua-repl-0.1.2 Released 2024-01-18. - Relaxed upper bound for text and bytestring, allowing text-2.1 and bytestring-0.12. ## hslua-repl-0.1.1 Released 2023-03-17. - Running the REPL in specific environments: the new `replWithEnv` function allows to load all inputs in an environment that's specified by a *Reference* value. ## hslua-repl-0.1.0 Released 2023-03-16. - A new package begins its way into the undiscovered land. May it live long and prosper. [PVP Versioning]: https://pvp.haskell.org hslua-repl-0.1.2/LICENSE0000644000000000000000000000205007346545000012761 0ustar0000000000000000Copyright © 2023-2024 Albert Krewinkel Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. hslua-repl-0.1.2/README.md0000644000000000000000000000057507346545000013245 0ustar0000000000000000hslua-repl ========== An embeddable, isocline-based Lua REPL. Example ------- ``` haskell {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TypeApplications #-} import HsLua.Core as Lua (Exception, openlibs, run) import HsLua.REPL (defaultREPLConfig, startREPL) -- | Run a default Lua interpreter. main :: IO () main = run @Lua.Exception $ do startREPL defaultREPLConfig ``` hslua-repl-0.1.2/app/0000755000000000000000000000000007346545000012537 5ustar0000000000000000hslua-repl-0.1.2/app/luarepl.hs0000644000000000000000000000141007346545000014533 0ustar0000000000000000{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TypeApplications #-} {- | Module : Main Copyright : © 2022-2024 Albert Krewinkel License : MIT Maintainer : Albert Krewinkel A simple Lua REPL. -} module Main (main) where import Control.Monad (void) import HsLua.Core as Lua (Exception, openlibs, run) import HsLua.REPL (Config (..), defaultConfig, repl, setup) import qualified Data.Text as T -- | Run a default Lua interpreter. main :: IO () main = run @Lua.Exception $ do let config = Config { replPrompt = "luarepl" , replInfo = replInfo defaultConfig `T.append` "\nREPL: © 2023-2024 Albert Krewinkel" , replHistory = Just ".luarepl-history" } openlibs setup config void repl hslua-repl-0.1.2/hslua-repl.cabal0000644000000000000000000000516407346545000015025 0ustar0000000000000000cabal-version: 2.2 name: hslua-repl version: 0.1.2 synopsis: Isocline-based Lua REPL description: An embeddable Lua REPL built with Isocline and HsLua. homepage: https://hslua.org/ bug-reports: https://github.com/hslua/hslua/issues license: MIT license-file: LICENSE author: Albert Krewinkel maintainer: Albert Krewinkel copyright: © 2023-2024 Albert Krewinkel category: Foreign build-type: Simple extra-doc-files: README.md CHANGELOG.md tested-with: GHC == 8.4.4 , GHC == 8.6.5 , GHC == 8.8.4 , GHC == 8.10.7 , GHC == 9.0.2 , GHC == 9.2.8 , GHC == 9.4.8 , GHC == 9.6.3 , GHC == 9.8.1 source-repository head type: git location: https://github.com/hslua/hslua subdir: hslua-repl Flag executable description: Compile `luarepl` standalone executable. default: False common common-options build-depends: base >= 4.9.1 && < 5 , hslua-core >= 2.3.1 && < 2.4 , text >= 1.2 && < 2.2 ghc-options: -Wall -Wcpp-undef -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-signatures -Wnoncanonical-monad-instances -Wpartial-fields -Wredundant-constraints -fhide-source-paths if impl(ghc >= 8.10) ghc-options: -Wunused-packages if impl(ghc >= 9.0) ghc-options: -Winvalid-haddock default-language: Haskell2010 library import: common-options hs-source-dirs: src exposed-modules: HsLua.REPL build-depends: base >= 4.11 && < 5 , bytestring >= 0.10 && < 0.13 , isocline >= 1.0 && < 1.1 , lua >= 2.3 && < 2.4 executable luarepl import: common-options hs-source-dirs: app main-is: luarepl.hs ghc-options: -rtsopts -with-rtsopts=-A8m -threaded if flag(executable) buildable: True build-depends: hslua-repl else buildable: False hslua-repl-0.1.2/src/HsLua/0000755000000000000000000000000007346545000013562 5ustar0000000000000000hslua-repl-0.1.2/src/HsLua/REPL.hs0000644000000000000000000001036107346545000014661 0ustar0000000000000000{-# LANGUAGE CPP #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE ScopedTypeVariables #-} {- | Module : HsLua.REPL Copyright : Copyright © 2017-2024 Albert Krewinkel License : MIT Maintainer : Albert Krewinkel Embeddable Lua interpreter interface. -} module HsLua.REPL ( -- * Run scripts as program repl , replWithEnv , setup , Config (..) , defaultConfig ) where import Control.Applicative ((<|>)) import Control.Monad (void, when) import Data.ByteString (ByteString) import Data.Text (Text) import Lua (pattern LUA_COPYRIGHT) import HsLua.Core import System.Console.Isocline import qualified Data.ByteString.Char8 as Char8 import qualified Data.Text as T import qualified Data.Text.IO as T import qualified HsLua.Core.Utf8 as UTF8 -- | Lua runner command line options. data Config = Config { replPrompt :: Text , replInfo :: Text , replHistory :: Maybe FilePath } defaultConfig :: Config defaultConfig = Config { replPrompt = "" , replInfo = T.pack LUA_COPYRIGHT , replHistory = Nothing } -- | Setup a new repl. Prints the version and extra info before the -- first prompt. setup :: Config -> LuaE e () setup config = do liftIO $ T.putStrLn (replInfo config) case replHistory config of Just histfile -> liftIO $ setHistory histfile 200 Nothing -> pure () -- | Checks if the error message hints at incomplete input. Removes the -- message from the stack in that case. incomplete :: LuaError e => LuaE e Bool incomplete = do let eofmark = "" msg <- tostring' top if eofmark `Char8.isSuffixOf` msg then True <$ pop 2 -- error message (duplicated by tostring') else False <$ pop 1 -- value pushed by tostring' -- | Load an input string, mark it as coming from @stdin@. loadinput :: ByteString -> LuaE e Status loadinput inp = loadbuffer inp "=stdin" -- | Try to load input while prepending a @return@ statement. loadExpression :: LuaError e => ByteString -> LuaE e () loadExpression input = loadinput ("return " <> input) >>= \case OK -> pure () -- yep, that worked _err -> throwErrorAsException -- | Load a multiline statement; prompts for more lines if the statement -- looks incomplete. loadStatement :: LuaError e => [ByteString] -- ^ input lines -> LuaE e () loadStatement lns = do loadinput (Char8.unlines $ reverse lns) >>= \case OK -> pure () ErrSyntax -> incomplete >>= \isincmplt -> if isincmplt then liftIO (readlineMaybe ">") >>= \case Nothing -> failLua "Multiline input aborted" Just input -> loadStatement (UTF8.fromString input : lns) else throwErrorAsException _ -> throwErrorAsException -- | Run a Lua REPL. repl :: LuaError e => LuaE e NumResults repl = replWithEnv Nothing -- | Run a Lua REPL, using the table in the given upvalue as the load -- environment. replWithEnv :: LuaError e => Maybe Reference -> LuaE e NumResults replWithEnv mEnvRef = try repl' >>= \case Right n -> pure n -- Ctrl-D or Ctrl-C Left err -> do -- something went wrong: report error, reset stack and try again void $ getglobal "print" pushException err call 1 0 settop 0 replWithEnv mEnvRef where repl' :: LuaError e => LuaE e NumResults repl' = liftIO (readlineMaybe "") >>= \case Nothing -> -- Return all values left on the stack as results NumResults . fromStackIndex <$> gettop Just inputStr -> do settop 0 -- reset stack let input = UTF8.fromString inputStr loadExpression input <|> loadStatement [input] -- take env (if any) and set it as the first upvalue of the loaded -- thunk. case mEnvRef of Nothing -> pure () Just envRef -> do getref registryindex envRef >>= \case TypeTable -> void $ setupvalue (nth 2) 1 _ -> pop 1 -- run loaded input callTrace 0 multret nvalues <- gettop -- duplicate everything and call print on the results checkstack' (fromIntegral (fromStackIndex nvalues) + 1) "repl'" when (nvalues > 0) $ do void $ getglobal "print" mapM_ pushvalue [1..nvalues] call (fromIntegral $ fromStackIndex nvalues) 0 repl'