aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/program/aedifex/shell.lux
blob: 0215c08dabdc651d33f06f5a36c51d58fd8c5ed2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
(.module:
  [lux #*
   ["." host (#+ import:)]
   [abstract
    [monad (#+ do)]]
   [control
    ["." io (#+ IO)]
    ["." try (#+ Try)]
    ["." exception (#+ exception:)]
    [concurrency
     ["." promise]]]
   [data
    [text
     ["%" format (#+ format)]]
    [number
     ["." int]]]
   [world
    [file (#+ Path)]]]
  ["." // #_
   ["#." action (#+ Action)]])

(import: java/lang/String)

(import: java/io/InputStream)

(import: java/io/Reader)

(import: java/io/InputStreamReader
  (new [java/io/InputStream]))

(import: java/io/BufferedReader
  (new [java/io/Reader])
  (readLine [] #io #try java/lang/String))

(import: java/lang/Process
  (getInputStream [] java/io/InputStream)
  (getErrorStream [] java/io/InputStream)
  (waitFor [] #io #try int))

(import: java/io/File
  (new [java/lang/String]))

(import: java/lang/Runtime
  (#static getRuntime [] #io java/lang/Runtime)
  (exec [java/lang/String #? [java/lang/String] java/io/File] #io #try java/lang/Process))

(template [<exception>]
  [(exception: #export (<exception> {working-directory Text} {command Text} {error Text})
     (exception.report
      ["Working directory" (%.text working-directory)]
      ["Command" (%.text command)]
      ["Error" (%.text error)]))]

  [failure-to-execute-command]
  [failure-during-command-execution]
  )

(exception: #export (abnormal-exit {working-directory Text} {command Text} {code Int})
  (exception.report
   ["Working Directory" (%.text working-directory)]
   ["Command" (%.text command)]
   ["Code" (%.int code)]))

(def: (consume-stream working-directory command stream)
  (-> Text Path java/io/InputStream (IO (Try Any)))
  (let [reader (|> stream java/io/InputStreamReader::new java/io/BufferedReader::new)]
    (loop [_ []]
      (do io.monad
        [?line (java/io/BufferedReader::readLine reader)]
        (case ?line
          (#try.Success line)
          (exec (log! line)
            (recur []))
          
          (#try.Failure error)
          (wrap (exception.throw ..failure-during-command-execution [working-directory command error])))))))

(def: normal-exit
  +0)

(def: #export (execute command working-directory)
  (-> Text Path (Action Any))
  (promise.future
   (do {! io.monad}
     [runtime (java/lang/Runtime::getRuntime)
      ?process (java/lang/Runtime::exec command #.None (java/io/File::new working-directory) runtime)]
     (case ?process
       (#try.Success process)
       (do !
         [_ (..consume-stream working-directory command (java/lang/Process::getInputStream process))
          _ (..consume-stream working-directory command (java/lang/Process::getErrorStream process))
          ?exit-code (java/lang/Process::waitFor process)]
         (case ?exit-code
           (#try.Success exit-code)
           (if (int.= ..normal-exit exit-code)
             (wrap (#try.Success []))
             (wrap (exception.throw ..abnormal-exit [working-directory command exit-code])))

           (#try.Failure error)
           (wrap (exception.throw ..failure-to-execute-command [working-directory command error]))))
       
       (#try.Failure error)
       (wrap (exception.throw ..failure-to-execute-command [working-directory command error]))))))