git.fiddlerwoaroof.com
Browse code

feat: initial implementation

Edward Langley authored on 27/03/2022 05:06:17
Showing 7 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,2 @@
1
+#eval "$(lorri direnv)"
2
+use flake
0 3
new file mode 100644
... ...
@@ -0,0 +1,4 @@
1
+.direnv
2
+zig-out
3
+zig-cache
4
+*~
0 5
new file mode 100644
... ...
@@ -0,0 +1,42 @@
1
+#+TITLE: socket-based command runner
2
+#+TAGS: utilities
3
+#+AUTHOR: Ed Langley
4
+
5
+** Introduction
6
+
7
+Run a command everytime a line is written to a unix socket, passing
8
+the line written as the last argument to the command. Useful in an
9
+=after-save-hook= in emacs to run tests after the buffer is saved.
10
+Unlike file-watchers, this allows more precise control of when the
11
+tests are run, reducing the amount of time spent configuring ignore
12
+files and waiting for spurious reruns.
13
+
14
+** Building
15
+
16
+#+BEGIN_SRC zsh :results output :post proc
17
+  zig build --verbose 2>&1
18
+#+END_SRC
19
+
20
+** Usage
21
+
22
+#+BEGIN_SRC zsh
23
+rm /tmp/jest.sock ; $OLDPWD/zig-out/bin/zig-test /tmp/jest.sock npx jest --
24
+#+END_SRC
25
+
26
+#+NAME: proc
27
+#+BEGIN_SRC elisp :exports none
28
+  (defun fix (fn inp)
29
+    (cl-loop for old = inp then new
30
+             for new = (funcall fn inp)
31
+             until (equal new old)
32
+             finally (cl-return new)))
33
+  (s-join
34
+   "\n"
35
+   (funcall (fwoar/over (lambda (it)
36
+                          (    (lambda (v)
37
+                                 (s-replace-regexp " \\(--\\|#\\)" " \\\\\n  \\1" v))
38
+                               (s-replace-regexp "/nix/store/[^/]*/\\(.* \\)"
39
+                                                 "/nix/.../\\1"
40
+                                                 (s-replace "/Users/edwlan" "~" it)))))
41
+            (s-lines (s-trim *this*))))
42
+#+END_SRC
0 43
new file mode 100644
... ...
@@ -0,0 +1,34 @@
1
+const std = @import("std");
2
+
3
+pub fn build(b: *std.build.Builder) void {
4
+    // Standard target options allows the person running `zig build` to choose
5
+    // what target to build for. Here we do not override the defaults, which
6
+    // means any target is allowed, and the default is native. Other options
7
+    // for restricting supported target set are available.
8
+    const target = b.standardTargetOptions(.{});
9
+
10
+    // Standard release options allow the person running `zig build` to select
11
+    // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
12
+    const mode = b.standardReleaseOptions();
13
+
14
+    const exe = b.addExecutable("sigexec", "src/main.zig");
15
+    exe.setTarget(target);
16
+    exe.setBuildMode(mode);
17
+    exe.install();
18
+
19
+    const run_cmd = exe.run();
20
+    run_cmd.step.dependOn(b.getInstallStep());
21
+    if (b.args) |args| {
22
+        run_cmd.addArgs(args);
23
+    }
24
+
25
+    const run_step = b.step("run", "Run the app");
26
+    run_step.dependOn(&run_cmd.step);
27
+
28
+    const exe_tests = b.addTest("src/main.zig");
29
+    exe_tests.setTarget(target);
30
+    exe_tests.setBuildMode(mode);
31
+
32
+    const test_step = b.step("test", "Run unit tests");
33
+    test_step.dependOn(&exe_tests.step);
34
+}
0 35
new file mode 100644
... ...
@@ -0,0 +1,95 @@
1
+{
2
+  "nodes": {
3
+    "flake-compat": {
4
+      "flake": false,
5
+      "locked": {
6
+        "lastModified": 1648199409,
7
+        "narHash": "sha256-JwPKdC2PoVBkG6E+eWw3j6BMR6sL3COpYWfif7RVb8Y=",
8
+        "owner": "edolstra",
9
+        "repo": "flake-compat",
10
+        "rev": "64a525ee38886ab9028e6f61790de0832aa3ef03",
11
+        "type": "github"
12
+      },
13
+      "original": {
14
+        "owner": "edolstra",
15
+        "repo": "flake-compat",
16
+        "type": "github"
17
+      }
18
+    },
19
+    "flake-utils": {
20
+      "locked": {
21
+        "lastModified": 1629481132,
22
+        "narHash": "sha256-JHgasjPR0/J1J3DRm4KxM4zTyAj4IOJY8vIl75v/kPI=",
23
+        "owner": "numtide",
24
+        "repo": "flake-utils",
25
+        "rev": "997f7efcb746a9c140ce1f13c72263189225f482",
26
+        "type": "github"
27
+      },
28
+      "original": {
29
+        "owner": "numtide",
30
+        "repo": "flake-utils",
31
+        "type": "github"
32
+      }
33
+    },
34
+    "nixpkgs": {
35
+      "locked": {
36
+        "lastModified": 1648352901,
37
+        "narHash": "sha256-1R31hIpqA+3mKBSayiqUhCm21gw4YRioPuR1WqjlCwU=",
38
+        "owner": "nixos",
39
+        "repo": "nixpkgs",
40
+        "rev": "12417777b226eff91efee8b03578daa76c8178a3",
41
+        "type": "github"
42
+      },
43
+      "original": {
44
+        "owner": "nixos",
45
+        "ref": "12417777b226eff91efee8b03578daa76c8178a3",
46
+        "repo": "nixpkgs",
47
+        "type": "github"
48
+      }
49
+    },
50
+    "nixpkgs_2": {
51
+      "locked": {
52
+        "lastModified": 1631288242,
53
+        "narHash": "sha256-sXm4KiKs7qSIf5oTAmrlsEvBW193sFj+tKYVirBaXz0=",
54
+        "owner": "NixOS",
55
+        "repo": "nixpkgs",
56
+        "rev": "0e24c87754430cb6ad2f8c8c8021b29834a8845e",
57
+        "type": "github"
58
+      },
59
+      "original": {
60
+        "owner": "NixOS",
61
+        "ref": "nixpkgs-unstable",
62
+        "repo": "nixpkgs",
63
+        "type": "github"
64
+      }
65
+    },
66
+    "root": {
67
+      "inputs": {
68
+        "flake-compat": "flake-compat",
69
+        "nixpkgs": "nixpkgs",
70
+        "zig": "zig"
71
+      }
72
+    },
73
+    "zig": {
74
+      "inputs": {
75
+        "flake-utils": "flake-utils",
76
+        "nixpkgs": "nixpkgs_2"
77
+      },
78
+      "locked": {
79
+        "lastModified": 1648341617,
80
+        "narHash": "sha256-j4HXFD1eKxCFfMbBYhNnLmXZ7q6cahVqH/Hlq43v8RM=",
81
+        "owner": "arqv",
82
+        "repo": "zig-overlay",
83
+        "rev": "8d79efd701963ac3c9a55755de44e6fd4a6c8d76",
84
+        "type": "github"
85
+      },
86
+      "original": {
87
+        "owner": "arqv",
88
+        "repo": "zig-overlay",
89
+        "type": "github"
90
+      }
91
+    }
92
+  },
93
+  "root": "root",
94
+  "version": 7
95
+}
0 96
new file mode 100644
... ...
@@ -0,0 +1,30 @@
1
+{
2
+  inputs = {
3
+    nixpkgs = {
4
+      type = "github";
5
+      owner = "nixos";
6
+      repo = "nixpkgs";
7
+      ref = "12417777b226eff91efee8b03578daa76c8178a3";
8
+    };
9
+    zig.url = "github:arqv/zig-overlay";
10
+    flake-compat = {
11
+      url = "github:edolstra/flake-compat";
12
+      flake = false;
13
+    };
14
+  };
15
+
16
+  outputs = {
17
+    self,
18
+    nixpkgs,
19
+    zig,
20
+    flake-compat,
21
+  }: let
22
+    pkgs = nixpkgs.legacyPackages.aarch64-darwin;
23
+    zig091 = zig.packages.aarch64-darwin."0.9.1";
24
+  in
25
+    {
26
+      devShell.aarch64-darwin = pkgs.mkShell {
27
+        buildInputs = [zig091 nixpkgs.legacyPackages.aarch64-darwin.socat];
28
+      };
29
+    };
30
+}
0 31
new file mode 100644
... ...
@@ -0,0 +1,58 @@
1
+const std = @import("std");
2
+const net = std.net;
3
+
4
+// pub const io_mode = .evented;
5
+
6
+pub fn main() anyerror!void {
7
+    var allocator = std.heap.page_allocator;
8
+    const args = try std.process.argsAlloc(allocator);
9
+    defer std.process.argsFree(allocator, args);
10
+
11
+    const stdout = std.io.getStdOut().writer();
12
+    try stdout.print("{}", .{args.len});
13
+    try stdout.writeAll("\n");
14
+
15
+    var server = net.StreamServer.init(.{});
16
+    defer server.deinit();
17
+
18
+    try server.listen(net.Address.initUnix(args[1]) catch unreachable);
19
+    std.log.warn("listening at {}\n", .{server.listen_address});
20
+
21
+    while (true) {
22
+        const client = try allocator.create(Client);
23
+        client.* = Client{
24
+            .conn = try server.accept(),
25
+            .handle_frame = async client.handle(allocator, args[2..]),
26
+        };
27
+    }
28
+}
29
+
30
+fn nextLine(reader: anytype, buffer: []u8) !?[]const u8 {
31
+    var line = (try reader.readUntilDelimiterOrEof(
32
+        buffer,
33
+        '\n',
34
+    )) orelse return null;
35
+    // trim annoying windows-only carriage return character
36
+    return line;
37
+}
38
+
39
+const Client = struct {
40
+    conn: net.StreamServer.Connection,
41
+    handle_frame: @Frame(handle),
42
+    fn handle(self: *Client, allocator: std.mem.Allocator, args: []const []u8) !void {
43
+        var dynargs = std.ArrayList([]const u8).init(allocator);
44
+        defer dynargs.deinit();
45
+
46
+        try dynargs.appendSlice(args);
47
+
48
+        try self.conn.stream.writer().writeAll("server: howdy!");
49
+
50
+        // const stdout = std.io.getStdOut().writer();
51
+        var buffer: [1024]u8 = undefined;
52
+        var nl = (try nextLine(self.conn.stream.reader(), &buffer)).?;
53
+        try dynargs.append(nl);
54
+
55
+        const proc = try std.ChildProcess.init(dynargs.toOwnedSlice(), allocator);
56
+        _ = try nosuspend proc.spawn();
57
+    }
58
+};