@@ 574,11 574,13 @@ fn drawTitle(self: *Self, writer: anytype, indicator: ?[]const u8) !void {
try writer.writeByte(' ');
try escape.moveCursor(writer, 0, prefix_len);
// TODO input line scrolling
- try writeLine(
+ if (try writeLine(
writer,
self.width - prefix_len,
context.mode.user_input.buffer.buffer.items,
- );
+ )) |d| {
+ try writer.writeByteNTimes(' ', d);
+ }
// The title bar must be the last thing we draw, otherwise the
// cursor will end up in an unexpected position.
@@ 591,18 593,24 @@ fn drawTitle(self: *Self, writer: anytype, indicator: ?[]const u8) !void {
.message => {
try context.mode.message.level.getAttr().dump(writer);
try writer.writeByte(' ');
- try writeLine(writer, self.width - 1, context.mode.message.message);
+ if (try writeLine(writer, self.width - 1, context.mode.message.message)) |d| {
+ try writer.writeByteNTimes(' ', d);
+ }
},
.nav => {
try setAttr(writer, .{ .bg = .green, .fg = .black });
try writer.writeByte(' ');
if (indicator) |indctr| {
debug.assert(indctr.len < min_width);
- try writeLine(writer, self.width - (indctr.len + 1), context.cwd.name);
+ if (try writeLine(writer, self.width - (indctr.len + 1), context.cwd.name)) |d| {
+ try writer.writeByteNTimes(' ', d);
+ }
try setAttr(writer, .{ .bg = .green, .fg = .black, .bold = true });
try writer.writeAll(indctr);
} else {
- try writeLine(writer, self.width - 1, context.cwd.name);
+ if (try writeLine(writer, self.width - 1, context.cwd.name)) |d| {
+ try writer.writeByteNTimes(' ', d);
+ }
}
},
}
@@ 653,8 661,7 @@ fn drawList(self: *Self, writer: anytype) !void {
context.selection_delta = 0;
}
-fn drawFileName(writer: anytype, y: usize, file: DirMap.Dir.File, selected: bool, width: usize) !void {
- // TODO Perhaps draw '/' to the end of directory names.
+fn drawFileName(writer: anytype, y: usize, file: DirMap.Dir.File, selected: bool, _width: usize) !void {
// TODO Draw '->target' after name of links
try setAttr(writer, switch (file.kind) {
.Directory => Attr{
@@ 678,16 685,25 @@ fn drawFileName(writer: anytype, y: usize, file: DirMap.Dir.File, selected: bool
.reverse = selected,
},
});
- try escape.moveCursor(writer, y, 0);
+
const prefix = if (file.mark) " -> " else " ";
+ const width = blk: {
+ const width = (if (_width >= 30) _width - 11 else _width) - prefix.len;
+ break :blk if (file.kind == .Directory) width - 1 else width;
+ };
+
+ try escape.moveCursor(writer, y, 0);
try writer.writeAll(prefix);
- if (width >= 30) {
- try writeLine(writer, width - (prefix.len + 11), file.name);
+ const d = try writeLine(writer, width, file.name);
+ if (file.kind == .Directory) {
+ try writer.writeByte('/');
+ }
+ if (d) |e| try writer.writeByteNTimes(' ', e);
+ if (_width >= 30) {
// TODO this is a workaround for writeLine() not recognizing
// double-wide characters.
- try escape.moveCursor(writer, y, width - 11);
-
+ // try escape.moveCursor(writer, y, _width - 11);
try writer.writeByte(' ');
try writer.writeByte(if (file.r_user) 'r' else '-');
try writer.writeByte(if (file.w_user) 'w' else '-');
@@ 699,27 715,27 @@ fn drawFileName(writer: anytype, y: usize, file: DirMap.Dir.File, selected: bool
try writer.writeByte(if (file.w_other) 'w' else '-');
try writer.writeByte(if (file.x_other) 'x' else '-');
try writer.writeByte(' ');
- } else {
- try writeLine(writer, width - prefix.len, file.name);
}
}
-fn writeLine(writer: anytype, width: usize, bytes: []const u8) !void {
+/// Use writer to write at most `width` of `bytes`, abbreviating with '…' if
+/// necessary. If the amount of written codepoints is less than `width`, returns
+/// the difference, null otherwise.
+fn writeLine(writer: anytype, width: usize, bytes: []const u8) !?usize {
var view = unicode.Utf8View.init(bytes) catch {
// File names with unicode characters not recognized by zigs unicode
// view are not uncommon, for example if a file name containts "emojis"
// or got corrupted during a download. Treating those bytes as u8 chars
// is definitely wrong, but better than crashing or displaying nothing.
- try writeLineNoUnicode(writer, width, bytes);
- return;
+ return try writeLineNoUnicode(writer, width, bytes);
};
- var i: usize = 0;
+ var written: usize = 0;
var it = view.iterator();
- while (it.nextCodepointSlice()) |cp| : (i += 1) {
- if (i == width) {
- return;
- } else if (i == width - 1) {
+ while (it.nextCodepointSlice()) |cp| : (written += 1) {
+ if (written == width) {
+ return null;
+ } else if (written == width - 1) {
// We only have room for one more codepoint. Look ahead to see if we
// need to draw '…'.
if (it.nextCodepointSlice()) |_| {
@@ 727,22 743,22 @@ fn writeLine(writer: anytype, width: usize, bytes: []const u8) !void {
} else {
try writer.writeAll(cp);
}
- return;
+ return null;
} else {
try writeCodePoint(writer, cp);
}
}
-
- if (i < width) try writer.writeByteNTimes(' ', width - i);
+ return width - written;
}
-fn writeLineNoUnicode(writer: anytype, width: usize, bytes: []const u8) !void {
+fn writeLineNoUnicode(writer: anytype, width: usize, bytes: []const u8) !?usize {
if (bytes.len > width) {
for (bytes[0 .. width - 1]) |char| try writeAscii(writer, char);
try writer.writeAll("…");
+ return null;
} else {
for (bytes) |char| try writeAscii(writer, char);
- try writer.writeByteNTimes(' ', width - (bytes.len));
+ return width - bytes.len;
}
}