summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMatthias Andreas Benkard <code@mail.matthias.benkard.de>2025-08-13 20:10:42 +0200
committerMatthias Andreas Benkard <code@mail.matthias.benkard.de>2025-08-13 20:10:42 +0200
commitcdaecb2a0e4f5c25338cd7f11f3b881194068ac9 (patch)
tree95f0c7fca34507e36fd726370113d4297945896c /src
parent51a9d99310bff6df8f92963613595a69ec778991 (diff)
DIR: More DOS-like output.
Diffstat (limited to 'src')
-rw-r--r--src/eval.zig94
1 files changed, 88 insertions, 6 deletions
diff --git a/src/eval.zig b/src/eval.zig
index 472d896..ba7cff0 100644
--- a/src/eval.zig
+++ b/src/eval.zig
@@ -75,6 +75,66 @@ const InputSource = struct {
}
};
+fn formatDosPath(allocator: Allocator, path: []const u8) ![]const u8 {
+ var result = ArrayList(u8).init(allocator);
+ defer result.deinit();
+
+ // Convert path to DOS format with uppercase drive letter and backslashes
+ for (path) |ch| {
+ if (ch == '/') {
+ try result.append('\\');
+ } else {
+ try result.append(std.ascii.toUpper(ch));
+ }
+ }
+
+ // Ensure it starts with a drive letter if it's an absolute path
+ if (result.items.len == 0 or (result.items.len >= 1 and result.items[0] == '\\')) {
+ var prefixed = ArrayList(u8).init(allocator);
+ defer prefixed.deinit();
+ try prefixed.appendSlice("C:");
+ if (result.items.len > 0 and result.items[0] != '\\') {
+ try prefixed.append('\\');
+ }
+ try prefixed.appendSlice(result.items);
+ return allocator.dupe(u8, prefixed.items);
+ }
+
+ return allocator.dupe(u8, result.items);
+}
+
+fn formatDosDateTime(allocator: Allocator, timestamp_secs: i64) ![]const u8 {
+ const epoch_seconds = @as(u64, @intCast(@max(timestamp_secs, 0)));
+ const epoch_day = @divFloor(epoch_seconds, std.time.s_per_day);
+ const day_seconds = epoch_seconds % std.time.s_per_day;
+
+ // Calculate date (simplified)
+ var year: u32 = 1970; // Start from Unix epoch year
+ var remaining_days = epoch_day;
+
+ // Simple year calculation
+ while (remaining_days >= 365) {
+ const days_in_year: u64 = if (isLeapYear(year)) 366 else 365;
+ if (remaining_days < days_in_year) break;
+ remaining_days -= days_in_year;
+ year += 1;
+ }
+
+ // Simple month/day calculation (approximate)
+ const month = @min(@divFloor(remaining_days, 30) + 1, 12);
+ const day = @min(remaining_days % 30 + 1, 31);
+
+ // Calculate time
+ const hours = day_seconds / std.time.s_per_hour;
+ const minutes = (day_seconds % std.time.s_per_hour) / std.time.s_per_min;
+
+ // Format as MM-DD-YY HH:MMa (DOS style)
+ const am_pm = if (hours < 12) "a" else "p";
+ const display_hour = if (hours == 0) 12 else if (hours > 12) hours - 12 else hours;
+
+ return try std.fmt.allocPrint(allocator, "{d:0>2}-{d:0>2}-{d:0>2} {d:>2}:{d:0>2}{s}", .{ @as(u32, @intCast(month)), @as(u32, @intCast(day)), @as(u32, @intCast(year % 100)), @as(u32, @intCast(display_hour)), @as(u32, @intCast(minutes)), am_pm });
+}
+
pub fn executeCommand(command: Command, allocator: Allocator) !CommandStatus {
return executeCommandWithOutput(command, allocator, null, null);
}
@@ -206,7 +266,18 @@ fn executeCommandWithOutput(command: Command, allocator: Allocator, output_captu
var output_buffer = ArrayList(u8).init(allocator);
defer output_buffer.deinit();
- try output_buffer.writer().print("Directory of {s}\n\n", .{dir.path});
+ // Format path in DOS style with backslashes and uppercase drive letter
+ const formatted_path = try formatDosPath(allocator, dir.path);
+ defer allocator.free(formatted_path);
+
+ // Get volume label (simplified - just show drive)
+ const drive_letter = if (formatted_path.len >= 2 and formatted_path[1] == ':')
+ formatted_path[0]
+ else
+ 'C';
+ try output_buffer.writer().print(" Volume in drive {c} has no label\n", .{drive_letter});
+ try output_buffer.writer().print(" Volume Serial Number is 1234-5678\n", .{});
+ try output_buffer.writer().print("\n Directory of {s}\n\n", .{formatted_path});
var dir_iterator = std.fs.cwd().openDir(dir.path, .{ .iterate = true }) catch {
const error_msg = "File not found\n";
@@ -222,24 +293,35 @@ fn executeCommandWithOutput(command: Command, allocator: Allocator, output_captu
var iterator = dir_iterator.iterate();
var file_count: u32 = 0;
var dir_count: u32 = 0;
+ var total_file_bytes: u64 = 0;
while (try iterator.next()) |entry| {
+ const stat = dir_iterator.statFile(entry.name) catch continue;
+
+ // Convert timestamp to DOS date/time format
+ const mtime_secs = @divFloor(stat.mtime, std.time.ns_per_s);
+ const date_time = try formatDosDateTime(allocator, @intCast(mtime_secs));
+ defer allocator.free(date_time);
+
switch (entry.kind) {
.directory => {
- try output_buffer.writer().print("<DIR> {s}\n", .{entry.name});
+ try output_buffer.writer().print("{s} <DIR> {s}\n", .{ date_time, entry.name });
dir_count += 1;
},
.file => {
- const stat = dir_iterator.statFile(entry.name) catch continue;
- try output_buffer.writer().print("{d:>14} {s}\n", .{ stat.size, entry.name });
+ try output_buffer.writer().print("{s} {d:>14} {s}\n", .{ date_time, stat.size, entry.name });
file_count += 1;
+ total_file_bytes += stat.size;
},
else => {},
}
}
- try output_buffer.writer().print("\n{d} File(s)\n", .{file_count});
- try output_buffer.writer().print("{d} Dir(s)\n", .{dir_count});
+ // Get free disk space (simplified - just use a placeholder)
+ const bytes_free: u64 = 1024 * 1024 * 1024; // 1GB placeholder
+
+ try output_buffer.writer().print(" {d} File(s) {d:>14} bytes\n", .{ file_count, total_file_bytes });
+ try output_buffer.writer().print(" {d} Dir(s) {d:>14} bytes free\n", .{ dir_count, bytes_free });
if (output_capture) |capture| {
try capture.write(output_buffer.items);