diff options
author | Matthias Andreas Benkard <code@mail.matthias.benkard.de> | 2025-08-13 21:20:23 +0200 |
---|---|---|
committer | Matthias Andreas Benkard <code@mail.matthias.benkard.de> | 2025-08-13 21:20:23 +0200 |
commit | dfda112f0331b7514bc8cdce5c89b593ffefa9f2 (patch) | |
tree | 9aa1eebd9cf0eb86586b3fdc001922a550bdc862 | |
parent | b25e1f4a3d42024500a0987f2be55cba85672fbe (diff) |
Use 8.3 file names.
-rw-r--r-- | src/eval.zig | 106 |
1 files changed, 102 insertions, 4 deletions
diff --git a/src/eval.zig b/src/eval.zig index 2b55c21..91c03b0 100644 --- a/src/eval.zig +++ b/src/eval.zig @@ -80,14 +80,35 @@ fn formatDosPath(allocator: Allocator, path: []const u8) ![]const u8 { defer result.deinit(); // Convert path to DOS format with uppercase drive letter and backslashes + var converted_path = ArrayList(u8).init(allocator); + defer converted_path.deinit(); + for (path) |ch| { if (ch == '/') { - try result.append('\\'); + try converted_path.append('\\'); } else { - try result.append(std.ascii.toUpper(ch)); + try converted_path.append(std.ascii.toUpper(ch)); } } + // Split into components and convert each to 8.3 format + var it = std.mem.splitScalar(u8, converted_path.items, '\\'); + var first = true; + + while (it.next()) |component| { + if (component.len == 0) continue; + + if (!first) { + try result.append('\\'); + } + first = false; + + // Convert component to 8.3 format + const short_name = try convertTo83(allocator, component); + defer allocator.free(short_name); + try result.appendSlice(short_name); + } + // 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); @@ -103,6 +124,79 @@ fn formatDosPath(allocator: Allocator, path: []const u8) ![]const u8 { return allocator.dupe(u8, result.items); } +fn convertTo83(allocator: Allocator, filename: []const u8) ![]const u8 { + // Handle special directories + if (std.mem.eql(u8, filename, ".") or std.mem.eql(u8, filename, "..")) { + return allocator.dupe(u8, filename); + } + + // Handle drive letters (like C:) + if (filename.len == 2 and filename[1] == ':') { + return allocator.dupe(u8, filename); + } + + // Split filename and extension + var name_part: []const u8 = filename; + var ext_part: []const u8 = ""; + + if (std.mem.lastIndexOf(u8, filename, ".")) |dot_pos| { + if (dot_pos > 0) { // Don't treat leading dot as extension separator + name_part = filename[0..dot_pos]; + ext_part = filename[dot_pos + 1 ..]; + } + } + + // Clean name part (remove spaces and invalid chars, convert to uppercase) + var clean_name = ArrayList(u8).init(allocator); + defer clean_name.deinit(); + + for (name_part) |ch| { + if (std.ascii.isAlphanumeric(ch)) { + try clean_name.append(std.ascii.toUpper(ch)); + } else if (ch == '-' or ch == '_') { + try clean_name.append(ch); + } + // Skip spaces and other invalid characters + } + + // Clean extension part (max 3 chars, uppercase) + var clean_ext = ArrayList(u8).init(allocator); + defer clean_ext.deinit(); + + for (ext_part) |ch| { + if (clean_ext.items.len >= 3) break; + if (std.ascii.isAlphanumeric(ch)) { + try clean_ext.append(std.ascii.toUpper(ch)); + } + } + + // Build 8.3 filename + var result = ArrayList(u8).init(allocator); + defer result.deinit(); + + if (clean_name.items.len <= 8 and clean_ext.items.len <= 3) { + // Name fits in 8.3, use as-is + try result.appendSlice(clean_name.items); + if (clean_ext.items.len > 0) { + try result.append('.'); + try result.appendSlice(clean_ext.items); + } + } else { + // Need to abbreviate with ~1 + const max_name_len = if (clean_name.items.len > 6) 6 else clean_name.items.len; + try result.appendSlice(clean_name.items[0..max_name_len]); + try result.appendSlice("~1"); + + if (clean_ext.items.len > 0) { + try result.append('.'); + const max_ext_len = if (clean_ext.items.len > 3) 3 else clean_ext.items.len; + try result.appendSlice(clean_ext.items[0..max_ext_len]); + } + } + + 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); @@ -303,13 +397,17 @@ fn executeCommandWithOutput(command: Command, allocator: Allocator, output_captu const date_time = try formatDosDateTime(allocator, @intCast(mtime_secs)); defer allocator.free(date_time); + // Convert filename to 8.3 format + const short_name = try convertTo83(allocator, entry.name); + defer allocator.free(short_name); + switch (entry.kind) { .directory => { - try output_buffer.writer().print("{s} <DIR> {s}\n", .{ date_time, entry.name }); + try output_buffer.writer().print("{s} <DIR> {s}\n", .{ date_time, short_name }); dir_count += 1; }, .file => { - try output_buffer.writer().print("{s} {d:>14} {s}\n", .{ date_time, stat.size, entry.name }); + try output_buffer.writer().print("{s} {d:>14} {s}\n", .{ date_time, stat.size, short_name }); file_count += 1; total_file_bytes += stat.size; }, |