diff options
| author | Roman Smrž <roman.smrz@seznam.cz> | 2026-09-04 19:25:09 +0200 |
|---|---|---|
| committer | Roman Smrž <roman.smrz@seznam.cz> | 2026-09-05 21:41:39 +0200 |
| commit | a9439b66ad8f7a8f4ba079a47ecfe1e76c2abc4b (patch) | |
| tree | 7ef225d63462349b8f5708cdceecc9010734e60a | |
| parent | c2c89cf5308ea5c490a4fe150cffc72ed09c4c1c (diff) | |
Expression expansion for shell arguments
Changelog: Lists can now be dollar-expanded in the shell interpreter to provide list of shell command arguments.
| -rw-r--r-- | src/Parser/Expr.hs | 1 | ||||
| -rw-r--r-- | src/Parser/Shell.hs | 8 | ||||
| -rw-r--r-- | src/Script/Shell.hs | 18 | ||||
| -rw-r--r-- | test/asset/shell/expansion.et | 13 | ||||
| -rw-r--r-- | test/script/shell.et | 17 |
5 files changed, 56 insertions, 1 deletions
diff --git a/src/Parser/Expr.hs b/src/Parser/Expr.hs index 89fa208..2d0b770 100644 --- a/src/Parser/Expr.hs +++ b/src/Parser/Expr.hs @@ -14,6 +14,7 @@ module Parser.Expr ( variable, constructor, + expressionExpansion, stringExpansion, functionArguments, diff --git a/src/Parser/Shell.hs b/src/Parser/Shell.hs index 45f00b9..a09eb43 100644 --- a/src/Parser/Shell.hs +++ b/src/Parser/Shell.hs @@ -92,11 +92,17 @@ parseRedirection = choice parseArgument :: TestParser (Expr ShellArgument) parseArgument = choice [ parseRedirection + , expressionExpansion "shell argument" <* sc , fmap ShellArgument <$> parseTextArgument ] parseArguments :: TestParser (Expr ShellArguments) -parseArguments = (ShellArguments <$>) . foldr (liftA2 (:)) (Pure []) <$> many parseArgument +parseArguments = do + arglists <- many $ choice + [ expressionExpansion "shell arguments" <* sc + , fmap (ShellArguments . (: [])) <$> parseArgument + ] + return $ fmap mconcat $ foldr (liftA2 (:)) (Pure []) $ arglists parseCommand :: TestParser (Expr ShellCommand) parseCommand = label "shell statement" $ do diff --git a/src/Script/Shell.hs b/src/Script/Shell.hs index 3e98e66..e7c8542 100644 --- a/src/Script/Shell.hs +++ b/src/Script/Shell.hs @@ -15,8 +15,10 @@ import Control.Monad.IO.Class import Control.Monad.Reader import Data.Maybe +import Data.Scientific import Data.Text (Text) import Data.Text qualified as T +import Data.Typeable import Foreign.C.Types import Foreign.Ptr @@ -67,6 +69,7 @@ data ShellCommand = ShellCommand } newtype ShellArguments = ShellArguments { fromShellArguments :: [ ShellArgument ] } + deriving (Semigroup, Monoid) data ShellArgument = ShellArgument Text @@ -97,10 +100,25 @@ instance ExprType ShellArguments where textExprType _ = T.pack "ShellArguments" textExprValue _ = "<shell-arguments>" + exprExpansionConvFrom = listToMaybe $ catMaybes + [ cast (ShellArguments . (: []) . ShellArgument) + , cast (ShellArguments . (: []) . ShellArgument . T.pack . show @Integer) + , cast (ShellArguments . (: []) . ShellArgument . T.pack . show @Scientific) + , cast (ShellArguments . map ShellArgument) + , cast (ShellArguments . map (ShellArgument . T.pack . show @Integer)) + , cast (ShellArguments . map (ShellArgument . T.pack . show @Scientific)) + ] + instance ExprType ShellArgument where textExprType _ = T.pack "ShellArgument" textExprValue _ = "<shell-argument>" + exprExpansionConvFrom = listToMaybe $ catMaybes + [ cast (ShellArgument) + , cast (ShellArgument . T.pack . show @Integer) + , cast (ShellArgument . T.pack . show @Scientific) + ] + data ShellExecInfo = ShellExecInfo { seiNode :: Node diff --git a/test/asset/shell/expansion.et b/test/asset/shell/expansion.et new file mode 100644 index 0000000..050efba --- /dev/null +++ b/test/asset/shell/expansion.et @@ -0,0 +1,13 @@ +test Test: + node n + + let str = "some string" + let int = 2 + let num = 4.5 + let list = [ "a b", "c d", "e", "f" ] + let ilist = [ 1 .. 5 ] + + shell on n as sh: + echo A $str B $int $num C + echo D $list E + echo F $ilist G diff --git a/test/script/shell.et b/test/script/shell.et index 3384353..4dca4a2 100644 --- a/test/script/shell.et +++ b/test/script/shell.et @@ -180,3 +180,20 @@ test ShellLogic: expect /run-test-result NegateNothing failed/ expect /run-done 1 0 0 1/ flush + + +test ShellVariableExpansion: + spawn as p + with p: + send "load ${scripts.path}/expansion.et" + local: + expect /(load-.*)/ capture done + guard (done == "load-done") + + send "run Test" + expect /child-stdout sh A some string B 2 4.5 C/ + expect /child-stdout sh D a b c d e f E/ + expect /child-stdout sh F 1 2 3 4 5 G/ + expect /run-test-result Test done/ + expect /run-done 1 1 0 0/ + flush |