|
|
@ -16,9 +16,6 @@ const c = @cImport({
|
|
16
|
16
|
});
|
|
17
|
17
|
const std = @import("std");
|
|
18
|
18
|
|
|
19
|
|
// TODO: restore commands
|
|
20
|
|
// TODO: instant output (for some commands like `py ...`, `go ...`, qcalc)
|
|
21
|
|
|
|
22
|
19
|
// commands wishlist:
|
|
23
|
20
|
// - search (e.g. default current dir + /usr/include)
|
|
24
|
21
|
// - launch with logs (default launcher, use systemd-run --user --unit=name name?)
|
|
|
@ -38,7 +35,7 @@ const ProcessWithOutput = struct {
|
|
38
|
35
|
stderr_buf: std.ArrayList(u8),
|
|
39
|
36
|
|
|
40
|
37
|
dead_fds: usize = 0,
|
|
41
|
|
max_output_bytes: usize = 50 * 1024,
|
|
|
38
|
max_output_bytes: usize,
|
|
42
|
39
|
|
|
43
|
40
|
cleanup_done: bool = false,
|
|
44
|
41
|
|
|
|
@ -112,6 +109,8 @@ const ProcessWithOutput = struct {
|
|
112
|
109
|
const nread = try std.os.read(poll_fds[0].fd, buf);
|
|
113
|
110
|
self.stdout_buf.items.len += nread;
|
|
114
|
111
|
|
|
|
112
|
std.debug.print("read {d} bytes ({d} total, {d} max)\n", .{ nread, self.stdout_buf.items.len, self.max_output_bytes });
|
|
|
113
|
|
|
115
|
114
|
// Remove the fd when the EOF condition is met.
|
|
116
|
115
|
remove_stdout = nread == 0;
|
|
117
|
116
|
} else {
|
|
|
@ -152,6 +151,7 @@ const ProcessWithOutput = struct {
|
|
152
|
151
|
};
|
|
153
|
152
|
|
|
154
|
153
|
const RegexRunner = struct {
|
|
|
154
|
name: []const u8,
|
|
155
|
155
|
run_always: bool,
|
|
156
|
156
|
process: ?ProcessWithOutput = null,
|
|
157
|
157
|
|
|
|
@ -201,7 +201,7 @@ const RegexRunner = struct {
|
|
201
|
201
|
return err;
|
|
202
|
202
|
},
|
|
203
|
203
|
};
|
|
204
|
|
//std.debug.print("{d} ({d})\n", .{process.stdout_buf.items.len, process.stderr_buf.items.len});
|
|
|
204
|
std.debug.print("{d} ({d})\n", .{ process.stdout_buf.items.len, process.stderr_buf.items.len });
|
|
205
|
205
|
if (process.stdout_buf.items.len > 0) {
|
|
206
|
206
|
return process.stdout();
|
|
207
|
207
|
} else if (process.stderr_buf.items.len > 0) {
|
|
|
@ -223,7 +223,7 @@ var cmd_buf: [100]u8 = undefined;
|
|
223
|
223
|
|
|
224
|
224
|
const GoDocRunner = struct {
|
|
225
|
225
|
fn init() RegexRunner {
|
|
226
|
|
return RegexRunner{ .run_always = true, .toArgv = toArgv, .isActive = isActive };
|
|
|
226
|
return RegexRunner{ .name = "go doc", .run_always = true, .toArgv = toArgv, .isActive = isActive };
|
|
227
|
227
|
}
|
|
228
|
228
|
|
|
229
|
229
|
fn isActive(cmd: []const u8) bool {
|
|
|
@ -239,7 +239,7 @@ const GoDocRunner = struct {
|
|
239
|
239
|
|
|
240
|
240
|
const PythonHelpRunner = struct {
|
|
241
|
241
|
fn init() RegexRunner {
|
|
242
|
|
return RegexRunner{ .run_always = true, .toArgv = toArgv, .isActive = isActive };
|
|
|
242
|
return RegexRunner{ .name = "python help", .run_always = true, .toArgv = toArgv, .isActive = isActive };
|
|
243
|
243
|
}
|
|
244
|
244
|
|
|
245
|
245
|
fn isActive(cmd: []const u8) bool {
|
|
|
@ -254,7 +254,7 @@ const PythonHelpRunner = struct {
|
|
254
|
254
|
|
|
255
|
255
|
const PythonRunner = struct {
|
|
256
|
256
|
fn init() RegexRunner {
|
|
257
|
|
return RegexRunner{ .run_always = true, .toArgv = toArgv, .isActive = isActive };
|
|
|
257
|
return RegexRunner{ .name = "python run", .run_always = true, .toArgv = toArgv, .isActive = isActive };
|
|
258
|
258
|
}
|
|
259
|
259
|
|
|
260
|
260
|
fn isActive(cmd: []const u8) bool {
|
|
|
@ -267,9 +267,39 @@ const PythonRunner = struct {
|
|
267
|
267
|
}
|
|
268
|
268
|
};
|
|
269
|
269
|
|
|
|
270
|
const HelpRunner = struct {
|
|
|
271
|
fn init() RegexRunner {
|
|
|
272
|
return RegexRunner{ .name = "--help", .run_always = true, .toArgv = toArgv, .isActive = isActive };
|
|
|
273
|
}
|
|
|
274
|
|
|
|
275
|
fn isActive(cmd: []const u8) bool {
|
|
|
276
|
return std.mem.endsWith(u8, cmd, " --help");
|
|
|
277
|
}
|
|
|
278
|
|
|
|
279
|
fn toArgv(cmd: []const u8) []const []const u8 {
|
|
|
280
|
_ = std.fmt.bufPrint(&cmd_buf, "{s}", .{cmd[0 .. cmd.len - " --help".len]}) catch "???";
|
|
|
281
|
return &[_][]const u8{ &cmd_buf, "--help" };
|
|
|
282
|
}
|
|
|
283
|
};
|
|
|
284
|
|
|
|
285
|
const ManPageRunner = struct {
|
|
|
286
|
fn init() RegexRunner {
|
|
|
287
|
return RegexRunner{ .name = "man page", .run_always = true, .toArgv = toArgv, .isActive = isActive };
|
|
|
288
|
}
|
|
|
289
|
|
|
|
290
|
fn isActive(cmd: []const u8) bool {
|
|
|
291
|
return cmd.len > "man ".len + 2 and std.mem.startsWith(u8, cmd, "man ");
|
|
|
292
|
}
|
|
|
293
|
|
|
|
294
|
fn toArgv(cmd: []const u8) []const []const u8 {
|
|
|
295
|
_ = std.fmt.bufPrint(&cmd_buf, "{s}", .{cmd["man ".len..]}) catch "???";
|
|
|
296
|
return &[_][]const u8{ "man", &cmd_buf };
|
|
|
297
|
}
|
|
|
298
|
};
|
|
|
299
|
|
|
270
|
300
|
const SearchRunner = struct {
|
|
271
|
301
|
fn init() RegexRunner {
|
|
272
|
|
return RegexRunner{ .run_always = true, .toArgv = toArgv, .isActive = isActive };
|
|
|
302
|
return RegexRunner{ .name = "search", .run_always = true, .toArgv = toArgv, .isActive = isActive };
|
|
273
|
303
|
}
|
|
274
|
304
|
|
|
275
|
305
|
fn isActive(cmd: []const u8) bool {
|
|
|
@ -284,7 +314,7 @@ const SearchRunner = struct {
|
|
284
|
314
|
|
|
285
|
315
|
const QalcRunner = struct {
|
|
286
|
316
|
fn init() RegexRunner {
|
|
287
|
|
return RegexRunner{ .run_always = true, .toArgv = toArgv, .isActive = isActive };
|
|
|
317
|
return RegexRunner{ .name = "qalc", .run_always = true, .toArgv = toArgv, .isActive = isActive };
|
|
288
|
318
|
}
|
|
289
|
319
|
|
|
290
|
320
|
fn isActive(cmd: []const u8) bool {
|
|
|
@ -366,6 +396,8 @@ pub fn main() !void {
|
|
366
|
396
|
GoDocRunner.init(),
|
|
367
|
397
|
PythonHelpRunner.init(),
|
|
368
|
398
|
PythonRunner.init(),
|
|
|
399
|
HelpRunner.init(),
|
|
|
400
|
ManPageRunner.init(),
|
|
369
|
401
|
SearchRunner.init(),
|
|
370
|
402
|
QalcRunner.init(),
|
|
371
|
403
|
};
|
|
|
@ -559,44 +591,6 @@ pub fn main() !void {
|
|
559
|
591
|
}
|
|
560
|
592
|
}
|
|
561
|
593
|
|
|
562
|
|
fn runCommand(raw_cmd: []const u8, allocator: *std.mem.Allocator) ![]const u8 {
|
|
563
|
|
const cmd = std.mem.trim(u8, std.mem.sliceTo(raw_cmd, 0), &std.ascii.spaces);
|
|
564
|
|
const argv = if (std.mem.startsWith(u8, cmd, "go "))
|
|
565
|
|
&[_][]const u8{ "go", "doc", cmd[3..] }
|
|
566
|
|
else if (std.mem.startsWith(u8, cmd, "py "))
|
|
567
|
|
&[_][]const u8{ "python", "-c", try std.fmt.allocPrint(allocator, "import {s}; help({s});", .{ std.mem.sliceTo(cmd["py ".len..], '.'), cmd["py ".len..] }) }
|
|
568
|
|
else if (std.mem.endsWith(u8, cmd, " --help"))
|
|
569
|
|
// TODO: handle --help that outputs on stderr
|
|
570
|
|
&[_][]const u8{ cmd[0..(cmd.len - " --help".len)], "--help" }
|
|
571
|
|
else if (std.mem.startsWith(u8, cmd, "man "))
|
|
572
|
|
// TODO: handle `man 5 sway`
|
|
573
|
|
&[_][]const u8{ "man", cmd["man ".len..] }
|
|
574
|
|
else if (std.mem.startsWith(u8, cmd, "s "))
|
|
575
|
|
&[_][]const u8{ "ag", cmd["s ".len..], "/home/luna/t/raylib/src", "/home/luna/k/the-thing/resources/ode-build/include" }
|
|
576
|
|
else if (cmd.len > 0 and std.ascii.isDigit(cmd[0]))
|
|
577
|
|
&[_][]const u8{ "qalc", "-terse", cmd }
|
|
578
|
|
else
|
|
579
|
|
&[_][]const u8{ "bash", "-c", cmd };
|
|
580
|
|
for (argv) |arg| {
|
|
581
|
|
std.debug.print("'{s}' ", .{arg});
|
|
582
|
|
}
|
|
583
|
|
const result = try std.ChildProcess.exec(.{ .allocator = allocator, .argv = argv, .max_output_bytes = 1024 * 1024 });
|
|
584
|
|
std.debug.print("stdout: '{s}'\n", .{result.stdout[0..std.math.min(100, result.stdout.len)]});
|
|
585
|
|
std.debug.print("stderr: '{s}'\n", .{result.stderr});
|
|
586
|
|
|
|
587
|
|
if (result.stdout.len > 0) {
|
|
588
|
|
allocator.free(result.stderr);
|
|
589
|
|
return result.stdout;
|
|
590
|
|
} else if (result.stderr.len > 0) {
|
|
591
|
|
allocator.free(result.stdout);
|
|
592
|
|
return result.stderr;
|
|
593
|
|
} else {
|
|
594
|
|
allocator.free(result.stdout);
|
|
595
|
|
allocator.free(result.stderr);
|
|
596
|
|
return std.fmt.allocPrint(allocator, "<no output>", .{});
|
|
597
|
|
}
|
|
598
|
|
}
|
|
599
|
|
|
|
600
|
594
|
// tests
|
|
601
|
595
|
|
|
602
|
596
|
test "trim []const u8" {
|