packages feed

hslua-cli (empty) → 1.0.0

raw patch · 6 files changed

+370/−0 lines, 6 filesdep +basedep +bytestringdep +hslua-cli

Dependencies added: base, bytestring, hslua-cli, hslua-core, hslua-marshalling, lua, text

Files

+ CHANGELOG.md view
@@ -0,0 +1,9 @@+# Changelog++`hslua-cli` uses [PVP Versioning](https://pvp.haskell.org).++## hslua-cli-1.0.0++Released 2022-09-23.++-   Initial release.
+ LICENSE view
@@ -0,0 +1,23 @@+Copyright © 1994-2022 Lua.org, PUC-Rio.+Copyright © 2007-2012 Gracjan Polak+Copyright © 2012-2015 Ömer Sinan Ağacan+Copyright © 2016-2022 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.
+ README.md view
@@ -0,0 +1,26 @@+hslua-cli+=========++Library that allows to embed a standalone Lua interpreter into a+larger program. The provided command-line interface is mostly+compatible with that of the default `lua` executable that ships+with Lua.++Example+-------++``` haskell+import HsLua.Core  as Lua (Exception, openlibs, run)+import HsLua.CLI (Settings (..), runStandalone)++-- | Run a default Lua interpreter.+main :: IO ()+main = do+  let settings = Settings+        { settingsVersionInfo = "\nembedded in MyProgram"+        , settingsRunner = \action -> run $ do+            openlibs+            action+        }+  runStandalone @Lua.Exception settings+```
+ app/hslua.hs view
@@ -0,0 +1,24 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeApplications  #-}+{- |+Module      : Main+Copyright   : © 2022 Albert Krewinkel+License     : MIT+Maintainer  : Albert Krewinkel <albert@hslua.org>++Re-implementation of the standard Lua interpreter.+-}+module Main (main) where+import HsLua.Core  as Lua (Exception, openlibs, run)+import HsLua.CLI (Settings (..), runStandalone)++-- | Run a default Lua interpreter.+main :: IO ()+main = do+  let settings = Settings+        { settingsVersionInfo = ""+        , settingsRunner = \action -> run $ do+            openlibs+            action+        }+  runStandalone @Lua.Exception settings
+ hslua-cli.cabal view
@@ -0,0 +1,78 @@+cabal-version:       2.2+name:                hslua-cli+version:             1.0.0+synopsis:            Command-line interface for Lua+description:         Provides an embeddable command-line interface for Lua.+                     The interface is compatible with the standard Lua+                     interpreter, i.e., the `lua` executable provided in a+                     default Lua installation.+homepage:            https://hslua.org/+bug-reports:         https://github.com/hslua/hslua/issues+license:             MIT+license-file:        LICENSE+author:              Albert Krewinkel+maintainer:          Albert Krewinkel <albert@hslua.org>+copyright:           © 2022 Albert Krewinkel+category:            Foreign+build-type:          Simple+extra-doc-files:     README.md+                     CHANGELOG.md+tested-with:         GHC == 8.0.2+                   , GHC == 8.2.2+                   , GHC == 8.4.4+                   , GHC == 8.6.5+                   , GHC == 8.8.4+                   , GHC == 8.10.7+                   , GHC == 9.0.2+                   , GHC == 9.2.3++source-repository head+  type:                git+  location:            https://github.com/hslua/hslua+  subdir:              hslua-cli++Flag executable+  description:         Compile `hslua` standalone executable.+  default:             False++common common-options+  build-depends:       base              >= 4.9.1  && < 5+                     , bytestring+                     , hslua-core        >= 2.1    && < 2.3++  ghc-options:         -Wall+                       -Wcompat+                       -Widentities+                       -Wincomplete-uni-patterns+                       -Wincomplete-record-updates+  if impl(ghc >= 8.0)+    ghc-options:       -Wredundant-constraints+  if impl(ghc >= 8.2)+    ghc-options:       -fhide-source-paths+  if impl(ghc >= 8.4)+    ghc-options:       -Wmissing-export-lists+                       -Wpartial-fields+  if impl(ghc >= 8.8)+    ghc-options:       -Wmissing-deriving-strategies++  default-language:    Haskell2010++library+  import:              common-options+  hs-source-dirs:      src+  exposed-modules:     HsLua.CLI+  build-depends:       base              >= 4.9.1  && < 5+                     , hslua-marshalling >= 2.1    && < 2.3+                     , lua               >= 2.1    && < 2.3+                     , text              >= 1.2    && < 2.1++executable hslua+  import:              common-options+  hs-source-dirs:      app+  main-is:             hslua.hs+  ghc-options:         -rtsopts -with-rtsopts=-A8m -threaded+  if flag(executable)+    buildable:           True+    build-depends:       hslua-cli+  else+   buildable:            False
+ src/HsLua/CLI.hs view
@@ -0,0 +1,210 @@+{-# LANGUAGE LambdaCase        #-}+{-# LANGUAGE OverloadedStrings #-}+{- |+Module      : Text.Pandoc.Lua+Copyright   : Copyright © 2017-2022 Albert Krewinkel+License     : MIT+Maintainer  : Albert Krewinkel <albert@hslua.org>++Embeddable Lua interpreter interface.+-}+module HsLua.CLI+  ( -- * Run scripts as program+    runStandalone+  , Settings (..)+  ) where++import Control.Monad (unless, when, zipWithM_)+import Data.Bifunctor (first)+import Data.ByteString (ByteString)+import Data.Foldable (foldl')+import Data.Maybe (listToMaybe)+import Data.Text (Text)+import Foreign.Ptr (nullPtr)+import HsLua.Core (LuaE, LuaError)+import System.Console.GetOpt+import System.Environment (getArgs, getProgName)+import System.IO (hPutStrLn, stderr)+import qualified Lua.Auxiliary as Lua+import qualified Lua.Constants as Lua+import qualified HsLua.Core as Lua+import qualified HsLua.Marshalling as Lua+import qualified HsLua.Core.Types as Lua+import qualified Data.Text as T+import qualified Data.Text.IO as T+import qualified HsLua.Core.Utf8 as UTF8++-- | Settings for the Lua command line interface.+data Settings e = Settings+  { settingsVersionInfo :: Text+  , settingsRunner      :: LuaE e () -> IO ()+  }++-- | Get the Lua interpreter options from the command line. Throws an+-- error with usage instructions if parsing fails.+getOptions :: IO Options+getOptions = do+  rawArgs <- getArgs+  progName <- getProgName+  let (actions, args, errs) = getOpt RequireOrder luaOptions rawArgs+  unless (null errs) . ioError . userError $+    let usageHead = "Usage: " ++ progName ++ " [options] [script [args]]"+    in concat errs ++ usageInfo usageHead luaOptions++  let (mscript, arg) = first listToMaybe $ splitAt 1 args+  opts <- foldl' (>>=) (return defaultLuaOpts) actions+  return opts+    { optScript = mscript+    , optScriptArgs = arg+    , optProgName = progName+    , optAllArgs = rawArgs+    }++-- | Print version information to the terminal.+showVersion :: LuaError e => Text -> LuaE e ()+showVersion extraInfo = do+  _ <- Lua.getglobal "_VERSION"+  versionString <- Lua.forcePeek $ Lua.peekText Lua.top+  Lua.liftIO . T.putStrLn $ versionString `T.append` extraInfo++-- | Runs code given on the command line+runCode :: LuaError e => LuaCode -> LuaE e ()+runCode = \case+  ExecuteCode stat -> do+    status <- Lua.dostringTrace stat+    when (status /= Lua.OK)+      Lua.throwErrorAsException+  RequireModule g mod' -> do+    _ <- Lua.getglobal "require"+    Lua.pushName mod'+    status <- Lua.pcallTrace 1 1+    if status == Lua.OK+      then Lua.setglobal g+      else Lua.throwErrorAsException++-- | Uses the first command line argument as the name of a script file+-- and tries to run that script in Lua. Falls back to stdin if no file+-- is given. Any remaining args are passed to Lua via the global table+-- @arg@.+runStandalone :: LuaError e => Settings e -> IO ()+runStandalone settings = do+  opts <- getOptions+  settingsRunner settings $ do+    -- print version info+    when (optVersion opts) (showVersion $ settingsVersionInfo settings)++    -- push `arg` table+    case optScript opts of+      Just _script -> do+        let setField i x = Lua.pushString x *> Lua.rawseti (Lua.nth 2) i+        let nprogargs = length (optAllArgs opts) - length (optScriptArgs opts)+        let arg = optProgName opts : optAllArgs opts+        Lua.newtable+        zipWithM_ setField [-(fromIntegral nprogargs)..] arg+      Nothing -> do+        Lua.pushList Lua.pushString (optAllArgs opts)+        Lua.pushString (optProgName opts)+        Lua.rawseti (Lua.nth 2) 0+    Lua.setglobal "arg"++    -- run code statements and module loading instructions+    mapM_ runCode (reverse $ optExecute opts)++    let nargs = fromIntegral . length $ optScriptArgs opts+    result <- case optScript opts of+      -- `dofileTrace` should really accept a (Maybe FilePath)+      Just script | script /= "-" -> do+        Lua.loadfile script >>= \case+          Lua.OK -> do+            mapM_ Lua.pushString (optScriptArgs opts)+            Lua.pcallTrace nargs Lua.multret+          s      -> pure s+      Nothing | optVersion opts || not (null (optExecute opts)) ->+        pure Lua.OK+      _ -> do+        -- load script from stdin+        l <- Lua.state+        Lua.liftIO (Lua.luaL_loadfile l nullPtr) >>= \case+          Lua.LUA_OK -> do+            mapM_ Lua.pushString (optScriptArgs opts)+            Lua.pcallTrace nargs Lua.multret+          s          -> pure $ Lua.toStatus s++    when (result /= Lua.OK)+      Lua.throwErrorAsException++-- | Code to execute on startup.+data LuaCode =+    ExecuteCode ByteString+  | RequireModule Lua.Name Lua.Name++-- | Lua runner command line options.+data Options = Options+  { optNoEnv       :: Bool          -- ^ Ignore environment variables+  , optInteractive :: Bool          -- ^ Interactive+  , optVersion     :: Bool          -- ^ Show version info+  , optWarnings    :: Bool          -- ^ Whether warnings are enabled+  , optExecute     :: [LuaCode]     -- ^ code to execute, in reverse order+  , optProgName    :: String        -- ^ program name+  , optAllArgs     :: [String]      -- ^ all arguments+  , optScript      :: Maybe String  -- ^ script name, if any+  , optScriptArgs  :: [String]      -- ^ arguments passed to the script+  }++defaultLuaOpts :: Options+defaultLuaOpts = Options+  { optNoEnv = False+  , optInteractive = False+  , optVersion = False+  , optWarnings = False+  , optExecute = mempty+  , optProgName = mempty+  , optAllArgs = mempty+  , optScript = Nothing+  , optScriptArgs = mempty+  }++-- | Lua command line options.+luaOptions :: [OptDescr (Options -> IO Options)]+luaOptions =+  [ Option "e" []+    (flip ReqArg "stat" $ \stat opt -> return $+        let code = ExecuteCode $ UTF8.fromString stat+        in opt{ optExecute = code:optExecute opt })+    "execute string 'stat'"++  , Option "i" []+    (NoArg $ \opt -> do+        hPutStrLn stderr "[WARNING] Flag `-i` is not supported yet."+        return opt { optInteractive = True })+    "interactive mode -- currently not supported"++  , Option "l" []+    (flip ReqArg "mod" $ \mod' opt -> return $+      let toName = Lua.Name . UTF8.fromString+          code = case break (== '=') mod' of+            (glb, '=':m)  -> RequireModule (toName glb) (toName m)+            (glb, _    )  -> RequireModule (toName glb) (toName glb)+      in opt{ optExecute = code:optExecute opt })+    (unlines+     [ "require library 'mod' into global 'mod';"+     , "if 'mod' has the pattern 'g=module', then"+     , "require library 'module' into global 'g'"+     ])++  , Option "v" []+    (NoArg $ \opt -> return opt { optVersion = True })+    "show version information"++  , Option "E" []+    (NoArg $ \opt -> do+        hPutStrLn stderr "[WARNING] Flag `-E` is not supported yet."+        return opt { optNoEnv = True })+    "ignore environment variables -- currently not supported"++  , Option "W" []+    (NoArg $ \opt -> do+        hPutStrLn stderr "[WARNING] Flag `-W` is not supported yet."+        return opt { optWarnings = True })+    "turn warnings on -- currently not supported"+  ]