meow
+72
-44
src/main.zig
+72
-44
src/main.zig
···
9
9
10
10
const usage =
11
11
\\Usage:
12
-
\\ lsr [options] [path]
12
+
\\ lsr [options] [path...]
13
13
\\
14
14
\\ --help Print this message and exit
15
15
\\ --version Print the version string
···
43
43
sort_by_mod_time: bool = false,
44
44
reverse_sort: bool = false,
45
45
46
-
directory: [:0]const u8 = ".",
46
+
directories: std.ArrayListUnmanaged([:0]const u8) = .empty,
47
47
file: ?[]const u8 = null,
48
48
49
49
winsize: ?posix.winsize = null,
···
253
253
}
254
254
},
255
255
.positional => {
256
-
cmd.opts.directory = arg;
256
+
try cmd.opts.directories.append(allocator, arg);
257
257
},
258
258
}
259
259
}
···
262
262
cmd.opts.colors = .default;
263
263
}
264
264
265
-
var ring: ourio.Ring = try .init(allocator, queue_size);
266
-
defer ring.deinit();
265
+
if (cmd.opts.directories.items.len == 0) {
266
+
try cmd.opts.directories.append(allocator, ".");
267
+
}
267
268
268
-
_ = try ring.open(cmd.opts.directory, .{ .DIRECTORY = true, .CLOEXEC = true }, 0, .{
269
-
.ptr = &cmd,
270
-
.cb = onCompletion,
271
-
.msg = @intFromEnum(Msg.cwd),
272
-
});
269
+
const multiple_dirs = cmd.opts.directories.items.len > 1;
273
270
274
-
if (cmd.opts.long) {
275
-
_ = try ring.open("/etc/localtime", .{ .CLOEXEC = true }, 0, .{
276
-
.ptr = &cmd,
277
-
.cb = onCompletion,
278
-
.msg = @intFromEnum(Msg.localtime),
279
-
});
280
-
_ = try ring.open("/etc/passwd", .{ .CLOEXEC = true }, 0, .{
281
-
.ptr = &cmd,
282
-
.cb = onCompletion,
283
-
.msg = @intFromEnum(Msg.passwd),
284
-
});
285
-
_ = try ring.open("/etc/group", .{ .CLOEXEC = true }, 0, .{
271
+
for (cmd.opts.directories.items, 0..) |directory, dir_idx| {
272
+
cmd.entries = &.{};
273
+
cmd.entry_idx = 0;
274
+
cmd.symlinks.clearRetainingCapacity();
275
+
cmd.groups.clearRetainingCapacity();
276
+
cmd.users.clearRetainingCapacity();
277
+
cmd.tz = null;
278
+
cmd.opts.file = null;
279
+
cmd.current_directory = directory;
280
+
281
+
var ring: ourio.Ring = try .init(allocator, queue_size);
282
+
defer ring.deinit();
283
+
284
+
_ = try ring.open(directory, .{ .DIRECTORY = true, .CLOEXEC = true }, 0, .{
286
285
.ptr = &cmd,
287
286
.cb = onCompletion,
288
-
.msg = @intFromEnum(Msg.group),
287
+
.msg = @intFromEnum(Msg.cwd),
289
288
});
290
-
}
291
289
292
-
try ring.run(.until_done);
290
+
if (cmd.opts.long) {
291
+
_ = try ring.open("/etc/localtime", .{ .CLOEXEC = true }, 0, .{
292
+
.ptr = &cmd,
293
+
.cb = onCompletion,
294
+
.msg = @intFromEnum(Msg.localtime),
295
+
});
296
+
_ = try ring.open("/etc/passwd", .{ .CLOEXEC = true }, 0, .{
297
+
.ptr = &cmd,
298
+
.cb = onCompletion,
299
+
.msg = @intFromEnum(Msg.passwd),
300
+
});
301
+
_ = try ring.open("/etc/group", .{ .CLOEXEC = true }, 0, .{
302
+
.ptr = &cmd,
303
+
.cb = onCompletion,
304
+
.msg = @intFromEnum(Msg.group),
305
+
});
306
+
}
307
+
308
+
try ring.run(.until_done);
293
309
294
-
if (cmd.entries.len == 0) return;
310
+
if (cmd.entries.len == 0) {
311
+
if (multiple_dirs and dir_idx < cmd.opts.directories.items.len - 1) {
312
+
try bw.writer().writeAll("\r\n");
313
+
}
314
+
continue;
315
+
}
295
316
296
-
std.sort.pdq(Entry, cmd.entries, cmd.opts, Entry.lessThan);
317
+
std.sort.pdq(Entry, cmd.entries, cmd.opts, Entry.lessThan);
297
318
298
-
if (cmd.opts.reverse_sort) {
299
-
std.mem.reverse(Entry, cmd.entries);
300
-
}
319
+
if (cmd.opts.reverse_sort) {
320
+
std.mem.reverse(Entry, cmd.entries);
321
+
}
301
322
302
-
if (cmd.opts.long) {
303
-
try printLong(cmd, bw.writer());
304
-
} else switch (cmd.opts.shortview) {
305
-
.columns => try printShortColumns(cmd, bw.writer()),
306
-
.oneline => try printShortOnePerLine(cmd, bw.writer()),
323
+
if (multiple_dirs) {
324
+
if (dir_idx > 0) try bw.writer().writeAll("\r\n");
325
+
try bw.writer().print("{s}:\r\n", .{directory});
326
+
}
327
+
328
+
if (cmd.opts.long) {
329
+
try printLong(cmd, bw.writer());
330
+
} else switch (cmd.opts.shortview) {
331
+
.columns => try printShortColumns(cmd, bw.writer()),
332
+
.oneline => try printShortOnePerLine(cmd, bw.writer()),
333
+
}
307
334
}
308
335
try bw.flush();
309
336
}
···
420
447
}
421
448
422
449
if (opts.useHyperlinks()) {
423
-
const path = try std.fs.path.join(cmd.arena, &.{ opts.directory, entry.name });
450
+
const path = try std.fs.path.join(cmd.arena, &.{ cmd.current_directory, entry.name });
424
451
try writer.print("\x1b]8;;file://{s}\x1b\\", .{path});
425
452
try writer.writeAll(entry.name);
426
453
try writer.writeAll("\x1b]8;;\x1b\\");
···
562
589
}
563
590
564
591
if (cmd.opts.useHyperlinks()) {
565
-
const path = try std.fs.path.join(cmd.arena, &.{ cmd.opts.directory, entry.name });
592
+
const path = try std.fs.path.join(cmd.arena, &.{ cmd.current_directory, entry.name });
566
593
try writer.print("\x1b]8;;file://{s}\x1b\\", .{path});
567
594
try writer.writeAll(entry.name);
568
595
try writer.writeAll("\x1b]8;;\x1b\\");
···
606
633
entries: []Entry = &.{},
607
634
entry_idx: usize = 0,
608
635
symlinks: std.StringHashMapUnmanaged(Symlink) = .empty,
636
+
current_directory: [:0]const u8 = ".",
609
637
610
638
tz: ?zeit.TimeZone = null,
611
639
groups: std.ArrayListUnmanaged(Group) = .empty,
···
786
814
787
815
// if the user specified a file (or something that couldn't be opened as a
788
816
// directory), then we open it's parent and apply a filter
789
-
const dirname = std.fs.path.dirname(cmd.opts.directory) orelse ".";
790
-
cmd.opts.file = std.fs.path.basename(cmd.opts.directory);
791
-
cmd.opts.directory = try cmd.arena.dupeZ(u8, dirname);
817
+
const dirname = std.fs.path.dirname(cmd.current_directory) orelse ".";
818
+
cmd.opts.file = std.fs.path.basename(cmd.current_directory);
819
+
cmd.current_directory = try cmd.arena.dupeZ(u8, dirname);
792
820
_ = try io.open(
793
-
cmd.opts.directory,
821
+
cmd.current_directory,
794
822
.{ .DIRECTORY = true, .CLOEXEC = true },
795
823
0,
796
824
.{
···
811
839
if (cmd.opts.useHyperlinks()) {
812
840
var buf: [std.fs.max_path_bytes]u8 = undefined;
813
841
const cwd = try std.os.getFdPath(fd, &buf);
814
-
cmd.opts.directory = try cmd.arena.dupeZ(u8, cwd);
842
+
cmd.current_directory = try cmd.arena.dupeZ(u8, cwd);
815
843
}
816
844
817
845
var temp_results: std.ArrayListUnmanaged(MinimalEntry) = .empty;
···
873
901
}
874
902
const path = try std.fs.path.joinZ(
875
903
cmd.arena,
876
-
&.{ cmd.opts.directory, entry.name },
904
+
&.{ cmd.current_directory, entry.name },
877
905
);
878
906
879
907
if (entry.kind == .sym_link) {
···
1040
1068
cmd.entry_idx += 1;
1041
1069
const path = try std.fs.path.joinZ(
1042
1070
cmd.arena,
1043
-
&.{ cmd.opts.directory, entry.name },
1071
+
&.{ cmd.current_directory, entry.name },
1044
1072
);
1045
1073
1046
1074
if (entry.kind == .sym_link) {
History
1 round
1 comment
themackabu.dev
submitted
#0
1 commit
expand
collapse
416908bf
feature: support listing multiple directories
meow
expand 1 comment
pull request successfully merged
Awesome work, thanks!