hslua-repl-0.1.1/0000755000000000000000000000000007346545000011756 5ustar0000000000000000hslua-repl-0.1.1/CHANGELOG.md0000644000000000000000000000073107346545000013570 0ustar0000000000000000# Changelog `hslua-repl` uses [PVP Versioning](https://pvp.haskell.org). ## hslua-repl-0.1.0 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.1/LICENSE0000644000000000000000000000204307346545000012762 0ustar0000000000000000Copyright © 2023 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.1/README.md0000644000000000000000000000057507346545000013244 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.1/app/0000755000000000000000000000000007346545000012536 5ustar0000000000000000hslua-repl-0.1.1/app/luarepl.hs0000644000000000000000000000140307346545000014534 0ustar0000000000000000{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TypeApplications #-} {- | Module : Main Copyright : © 2022-2023 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 Albert Krewinkel" , replHistory = Just ".luarepl-history" } openlibs setup config void repl hslua-repl-0.1.1/hslua-repl.cabal0000644000000000000000000000505307346545000015021 0ustar0000000000000000cabal-version: 2.2 name: hslua-repl version: 0.1.1 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 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.5 , GHC == 9.4.4 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.1 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.12 , 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.1/src/HsLua/0000755000000000000000000000000007346545000013561 5ustar0000000000000000hslua-repl-0.1.1/src/HsLua/REPL.hs0000644000000000000000000001036107346545000014660 0ustar0000000000000000{-# LANGUAGE CPP #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE ScopedTypeVariables #-} {- | Module : HsLua.REPL Copyright : Copyright © 2017-2023 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'