Skip to content

Commit 879913f

Browse files
committed
Merge pull request #1 from FrigoEU/master
Updated to compiler version 0.7.5.0 + Stronger types
2 parents 013255c + 57a82ab commit 879913f

File tree

6 files changed

+197
-99
lines changed

6 files changed

+197
-99
lines changed

bower.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44
"description": "PureScript bindings to child_process.",
55
"license": "MIT",
66
"dependencies": {
7-
"purescript-events": "joneshf/purescript-events#~0.1.2"
7+
"purescript-functions": "~0.1.0-rc.1",
8+
"purescript-node-streams": "~0.1.3",
9+
"purescript-foreign": "~0.7.0"
10+
},
11+
"devDependencies": {
12+
"purescript-console": "~0.1.1"
813
}
914
}

src/Node/ChildProcess.js

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
"use strict";
2+
3+
// module Node.ChildProcess
4+
/* eslint-env node*/
5+
6+
exports.spawn = function spawn(command) {
7+
return function(args) {
8+
return function(opts) {
9+
return function() {
10+
return require("child_process").spawn(command, args, opts);
11+
};
12+
};
13+
};
14+
};
15+
exports.mkOnExit = function mkOnExit(nothing){
16+
return function(just){
17+
return function(signalConstr){
18+
return function onExit(cp){
19+
return function(cb){
20+
return function(){
21+
cp.on("exit", function(code, signal){
22+
cb(code ? just(code) : nothing, signal ? just(signalConstr(signal)) : nothing);
23+
});
24+
};
25+
};
26+
};
27+
};
28+
};
29+
};
30+
exports.mkOnClose = function mkOnClose(nothing){
31+
return function(just){
32+
return function(signalConstr){
33+
return function onClose(cp){
34+
return function(cb){
35+
return function(){
36+
cp.on("close", function(code, signal){
37+
cb(code ? just(code) : nothing, signal ? just(signalConstr(signal)) : nothing);
38+
});
39+
};
40+
};
41+
};
42+
};
43+
};
44+
};
45+
exports.onDisconnect = function onDisconnect(cp){
46+
return function(cb){
47+
return function(){
48+
cp.on("disconnect", cb);
49+
};
50+
};
51+
};
52+
exports.mkOnMessage = function mkOnMessage(nothing){
53+
return function(just){
54+
return function onMessage(cp){
55+
return function(cb){
56+
return function(){
57+
cp.on("message", function(mess, sendHandle){
58+
cb(mess, sendHandle ? just(sendHandle) : nothing);
59+
});
60+
};
61+
};
62+
};
63+
};
64+
};
65+
exports.onError = function onError(cp){
66+
return function(cb){
67+
return function(){
68+
cp.on("error", cb);
69+
};
70+
};
71+
};
72+
73+
exports.process = process;

src/Node/ChildProcess.purs

Lines changed: 98 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,98 @@
1-
module Node.ChildProcess where
2-
3-
import Control.Events (Event(..), EventEmitter)
4-
import Control.Monad.Eff (Eff())
5-
6-
import Data.Function (Fn0(), Fn1(), Fn2())
7-
8-
import Node.ChildProcess.Signal (Signal(..))
9-
10-
foreign import data Handle :: *
11-
foreign import data Spawn :: !
12-
foreign import data Stream :: ! -> *
13-
foreign import data Stderr :: !
14-
foreign import data Stdin :: !
15-
foreign import data Stdout :: !
16-
17-
newtype ChildProcess = ChildProcess ChildProcessRec
18-
19-
type ChildProcessRec =
20-
{ stderr :: Stream Stderr
21-
, stdin :: Stream Stdin
22-
, stdout :: Stream Stdout
23-
, pid :: Number
24-
, connected :: Boolean
25-
, kill :: forall eff. Fn1 Signal Boolean
26-
, send :: forall eff r. Fn2 { | r} Handle (Eff eff Unit)
27-
, disconnect :: forall eff. Fn0 (Eff eff Unit)
28-
}
29-
30-
type SpawnOptions =
31-
{ cwd :: String
32-
, stdio :: [String]
33-
, env :: forall r. { | r}
34-
, detached :: Boolean
35-
, uid :: Number
36-
, gid :: Number
37-
}
38-
39-
instance eventEmitterStreamStderr :: EventEmitter (Stream Stderr)
40-
instance eventEmitterStreamStdin :: EventEmitter (Stream Stdin)
41-
instance eventEmitterStreamStdout :: EventEmitter (Stream Stdout)
42-
43-
instance eventEmitterChildProcess :: EventEmitter ChildProcess
44-
45-
closeEvent :: Event
46-
closeEvent = Event "close"
47-
48-
disconnectEvent :: Event
49-
disconnectEvent = Event "disconnect"
50-
51-
errorEvent :: Event
52-
errorEvent = Event "error"
53-
54-
exitEvent :: Event
55-
exitEvent = Event "exit"
56-
57-
messageEvent :: Event
58-
messageEvent = Event "message"
59-
60-
foreign import spawn
61-
"function spawn(command) {\
62-
\ return function(args) {\
63-
\ return function(opts) {\
64-
\ return function() {\
65-
\ return require('child_process').spawn(command, args, opts);\
66-
\ }\
67-
\ }\
68-
\ }\
69-
\}" :: forall eff. String -> [String] -> SpawnOptions -> Eff (spawn :: Spawn | eff) ChildProcess
70-
71-
defaultSpawnOptions :: SpawnOptions
72-
defaultSpawnOptions =
73-
{ cwd: undefined
74-
, stdio: ["pipe", "pipe", "pipe"]
75-
, env: process.env
76-
, detached: false
77-
, uid: undefined
78-
, gid: undefined
79-
}
80-
81-
-- There's gotta be a better way.
82-
foreign import undefined :: forall a. a
83-
foreign import process :: forall r. {env :: { | r}}
1+
module Node.ChildProcess
2+
( Handle()
3+
, Spawn()
4+
, Stdin()
5+
, Stdout()
6+
, Stderr()
7+
, ChildProcess()
8+
, SpawnOptions()
9+
, ChildProcessError()
10+
, onExit
11+
, onClose
12+
, onDisconnect
13+
, onMessage
14+
, onError
15+
, spawn
16+
, defaultSpawnOptions
17+
) where
18+
19+
import Prelude
20+
21+
import Control.Monad.Eff (Eff())
22+
23+
import Data.Function (Fn0(), Fn1(), Fn2())
24+
import Data.Maybe (Maybe(..))
25+
import Data.Foreign (Foreign())
26+
27+
import Node.Stream (Readable(), Writable())
28+
import Node.ChildProcess.Signal (Signal(..))
29+
30+
foreign import data Handle :: *
31+
foreign import data Spawn :: !
32+
foreign import data Stdin :: !
33+
foreign import data Stdout :: !
34+
foreign import data Stderr :: !
35+
36+
type ChildProcess =
37+
{ stderr :: forall eff. Readable () (stderr :: Stderr | eff) String
38+
, stdin :: forall eff. Writable () (stdin :: Stdin | eff) String
39+
, stdout :: forall eff. Readable () (stdout :: Stdout | eff) String
40+
, pid :: Number
41+
, connected :: Boolean
42+
, kill :: forall eff. Fn1 Signal Boolean
43+
, send :: forall eff r. Fn2 { | r} Handle (Eff eff Unit)
44+
, disconnect :: forall eff. Fn0 (Eff eff Unit)
45+
}
46+
47+
type SpawnOptions =
48+
{ cwd :: String
49+
, stdio :: Array String
50+
, env :: forall r. { | r}
51+
, detached :: Boolean
52+
, uid :: Number
53+
, gid :: Number
54+
}
55+
56+
onExit :: forall eff. ChildProcess -> (Maybe Number -> Maybe Signal -> Eff eff Unit) -> Eff eff Unit
57+
onExit = mkOnExit Nothing Just Signal
58+
59+
onClose :: forall eff. ChildProcess -> (Maybe Number -> Maybe Signal -> Eff eff Unit) -> Eff eff Unit
60+
onClose = mkOnClose Nothing Just Signal
61+
62+
onMessage :: forall eff. ChildProcess -> (Foreign -> Maybe Handle -> Eff eff Unit) -> Eff eff Unit
63+
onMessage = mkOnMessage Nothing Just
64+
65+
foreign import onDisconnect :: forall eff. ChildProcess -> Eff eff Unit -> Eff eff Unit
66+
foreign import onError :: forall eff. ChildProcess -> (ChildProcessError -> Eff eff Unit) -> Eff eff Unit
67+
68+
foreign import spawn :: forall eff. String -> Array String -> SpawnOptions -> Eff (spawn :: Spawn | eff) ChildProcess
69+
70+
defaultSpawnOptions :: SpawnOptions
71+
defaultSpawnOptions =
72+
{ cwd: undefined
73+
, stdio: ["pipe", "pipe", "pipe"]
74+
, env: process.env
75+
, detached: false
76+
, uid: undefined
77+
, gid: undefined
78+
}
79+
80+
type ChildProcessError =
81+
{ code :: String
82+
, errno :: String
83+
, syscall :: String
84+
}
85+
86+
foreign import mkOnExit :: forall a eff.
87+
Maybe a -> (a -> Maybe a) -> (String -> Signal) ->
88+
ChildProcess -> (Maybe Number -> Maybe Signal -> Eff eff Unit) -> Eff eff Unit
89+
foreign import mkOnMessage :: forall a eff.
90+
Maybe a -> (a -> Maybe a) ->
91+
ChildProcess -> (Foreign -> Maybe Handle -> Eff eff Unit) -> Eff eff Unit
92+
foreign import mkOnClose :: forall a eff.
93+
Maybe a -> (a -> Maybe a) -> (String -> Signal) ->
94+
ChildProcess -> (Maybe Number -> Maybe Signal -> Eff eff Unit) -> Eff eff Unit
95+
96+
-- There's gotta be a better way.
97+
foreign import undefined :: forall a. a
98+
foreign import process :: forall r. {env :: { | r}}

src/Node/ChildProcess/Signal.purs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
module Node.ChildProcess.Signal
2-
( Signal()
2+
( Signal(..)
33
, sigabrt
44
, sigalrm
55
, sigbus
@@ -40,6 +40,8 @@ module Node.ChildProcess.Signal
4040
, sigxfsz
4141
) where
4242

43+
import Prelude (Show)
44+
4345
newtype Signal = Signal String
4446

4547
sigabrt = Signal "SIGABRT"

test/Node/ChildProcess.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
"use strict";
2+
3+
// module Test.Node.ChildProcess
4+
/* eslint-env node*/
5+
6+
exports.toString = function toString(x) {
7+
return x == null ? "null" : x.toString();
8+
};

test/Node/ChildProcess.purs

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,20 @@
11
module Test.Node.ChildProcess where
22

3+
import Prelude
4+
35
import Data.Function (mkFn2, runFn1)
46

5-
import Debug.Trace
7+
import Control.Monad.Eff.Console
68

79
import Node.ChildProcess
810
import Node.ChildProcess.Signal
9-
import Node.Events
11+
import Node.Stream (onData)
1012

11-
foreign import toString
12-
"function toString(x) {\
13-
\ return x == null ? 'null' : x.toString();\
14-
\}" :: forall a. a -> String
13+
foreign import toString :: forall a. a -> String
1514

1615
main = do
17-
ChildProcess ls <- spawn "ls" ["-la"] defaultSpawnOptions
18-
on closeEvent (mkFn2 \code sig ->
19-
trace $ "ls exited with code: " ++
20-
(toString code) ++
21-
"\nfrom signal: " ++
22-
(toString sig))
23-
(ChildProcess ls)
24-
on (Event "data") (toString >>> trace) ls.stdout
16+
ls <- spawn "ls" ["-la"] defaultSpawnOptions
17+
onClose ls \code sig ->
18+
log $ "ls exited with code: " ++ (toString code) ++ "\nfrom signal: " ++ (toString sig)
19+
onData ls.stdout (toString >>> log)
2520
pure $ runFn1 ls.kill sigterm

0 commit comments

Comments
 (0)