0 | module Data.Swirl.System
 1 |
 2 | import Data.String
 3 | import public Data.Swirl
 4 | import Data.Swirl.File
 5 |
 6 | import public Language.Implicits.IfUnsolved
 7 |
 8 | import System.File
 9 | import public System.File.Error
10 |
11 | %default covering
12 |
13 | ||| Run a system command emitting lines that are printed to its standard output
14 | ||| and returning exit code as the result value.
15 | ||| Lines except the last one would have the newline at the end.
16 | export
17 | runSysCmdOLn : HasIO io => (cmd : List String) -> Swirl io FileError Int String
18 | runSysCmdOLn cmd = mapFst fst $ bracket'
19 |   (succeedOrFail.by $ popen cmd Read)
20 |   (succeed.by . pclose)
21 |   readAsLines
22 |
23 | trimRLn : String -> String
24 | trimRLn str = do
25 |   let S n = length str
26 |     | Z => ""
27 |   if assert_total $ strIndex str (cast n) == '\n'
28 |     then substr 0 n str
29 |     else str
30 |
31 | ||| Run a system command emitting lines that are printed to its standard output
32 | ||| and returning exit code as the result value.
33 | ||| Lines do not have a trailing newline and information of whether the last line had it is lost.
34 | export
35 | runSysCmdO : HasIO io => (cmd : List String) -> Swirl io FileError Int String
36 | runSysCmdO = map trimRLn . filter (/= "") . runSysCmdOLn
37 |
38 | ||| Run a system command being fed a stream of input strings
39 | ||| and returning exit code (along with the feeding stream result).
40 | export total
41 | runSysCmdI : HasIO io => (cmd : List String) -> Swirl io e r String -> Swirl io (Either e FileError) (r, Int) Void
42 | runSysCmdI cmd sw = mapFst swap $ bracket'
43 |   (mapError Right $ succeedOrFail.by $ popen cmd WriteTruncate)
44 |   (succeed.by . pclose)
45 |   $ \inF => squashOuts' $ sw <&> succeedOrFail.by . fPutStr inF
46 |
47 | export total
48 | runSysCmdILn : HasIO io => (cmd : List String) -> Swirl io e r String -> Swirl io (Either e FileError) (r, Int) Void
49 | runSysCmdILn cmd = runSysCmdI cmd . map (++ "\n")
50 |