Skip to content

Commit 53b039f

Browse files
committed
Add MVP port stuff
has a cast() that I don't want a recursive process import that breaks things also sucks to split up a datatype into receive/ due to conflicts but, works when there's no recursive import Fixes #89
1 parent 4fdda4e commit 53b039f

File tree

3 files changed

+84
-0
lines changed

3 files changed

+84
-0
lines changed

src/gleam/erlang/port.gleam

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,72 @@
77
/// [1]: https://erlang.org/doc/reference_manual/ports.html
88
///
99
pub type Port
10+
11+
12+
import gleam/erlang/port
13+
import gleam/erlang/atom
14+
import gleam/erlang/process
15+
import gleam/erlang/port/receive
16+
import gleam/dynamic
17+
18+
pub type PortName {
19+
Spawn(String)
20+
SpawnDriver(String)
21+
SpawnExecutable(String)
22+
Fd(in: Int, out: Int)
23+
}
24+
25+
pub fn spawn(command: String) -> PortName {
26+
Spawn(command)
27+
}
28+
29+
pub fn spawn_driver(command: String) -> PortName {
30+
SpawnDriver(command)
31+
}
32+
33+
pub fn spawn_executable(command: String) -> PortName {
34+
SpawnExecutable(command)
35+
}
36+
37+
38+
pub type PortOptions {
39+
Arg0(String)
40+
Args(List(String))
41+
Env(List(#(String, String)))
42+
Cd(String)
43+
Binary
44+
45+
UseStdio
46+
NouseStdio
47+
48+
Eof
49+
ExitStatus
50+
51+
Stream
52+
Line(Int)
53+
Packet(Int) // only 1, 2, & 4
54+
}
55+
56+
57+
@external(erlang, "erlang", "open_port")
58+
fn open_port(
59+
name: PortName,
60+
settings: List(PortOptions),
61+
) -> Port
62+
63+
@external(erlang, "erlang", "port_command")
64+
fn port_command(
65+
port: Port,
66+
data: BitArray,
67+
options: List(PortOptions),
68+
) -> Nil
69+
70+
71+
@external(erlang, "gleam_stdlib", "identity")
72+
@external(javascript, "../gleam_stdlib.mjs", "identity")
73+
fn cast(a: anything) -> dynamic.Dynamic
74+
75+
pub fn open(command: PortName, settings: List(PortOptions)) -> process.Subject(receive.PortData) {
76+
let port = open_port(command, settings)
77+
process.unsafely_create_subject(process.self(), cast(port))
78+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pub type PortData {
2+
Data(BitArray)
3+
ExitStatus(Int)
4+
Eof
5+
}

test/gleam/erlang/port_test.gleam

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
pub fn port_open_test() {
2+
let subject = port.run_open_port(
3+
port.spawn_executable("/bin/bash"),
4+
[port.Args(["-c", "echo hi | wc -c"]), port.UseStdio, port.ExitStatus, port.Binary]
5+
)
6+
assert Ok(receive.Data(<<"3\n">>)) == process.receive(subject, 100)
7+
assert Ok(receive.ExitStatus(0)) == process.receive(subject, 100)
8+
assert Error(Nil) == process.receive(subject, 100)
9+
}
10+

0 commit comments

Comments
 (0)