Only keep total_items + Zig test update + pointless churn

This commit is contained in:
Yorhel 2021-05-24 11:02:26 +02:00
parent 7b3ebf9241
commit 9474aa4329
4 changed files with 84 additions and 80 deletions

View file

@ -85,8 +85,8 @@ fn sortLt(_: void, ap: ?*model.Entry, bp: ?*model.Entry) bool {
if (sortIntLt(a.blocks, b.blocks)) |r| return r;
},
.items => {
const ai = if (a.dir()) |d| d.total_items else 0;
const bi = if (b.dir()) |d| d.total_items else 0;
const ai = if (a.dir()) |d| d.items else 0;
const bi = if (b.dir()) |d| d.items else 0;
if (sortIntLt(ai, bi)) |r| return r;
if (sortIntLt(a.blocks, b.blocks)) |r| return r;
if (sortIntLt(a.size, b.size)) |r| return r;
@ -208,11 +208,15 @@ const Row = struct {
}
if (main.config.show_graph == .both) ui.addch(' ');
if (main.config.show_graph == .both or main.config.show_graph == .graph) {
const perblock = std.math.divCeil(u64, if (main.config.show_blocks) dir_max_blocks else dir_max_size, bar_size) catch unreachable;
const perblock = std.math.divFloor(u64, if (main.config.show_blocks) dir_max_blocks else dir_max_size, bar_size) catch unreachable;
const num = if (main.config.show_blocks) item.blocks else item.size;
var i: u32 = 0;
var siz: u64 = 0;
self.bg.fg(.graph);
while (i < bar_size) : (i += 1) ui.addch(if (i*perblock <= num) '#' else ' ');
while (i < bar_size) : (i += 1) {
siz = saturateAdd(siz, perblock);
ui.addch(if (siz <= num) '#' else ' ');
}
}
self.bg.fg(.default);
ui.addch(']');
@ -221,14 +225,16 @@ const Row = struct {
fn items(self: *Self) void {
if (!main.config.show_items) return;
defer self.col += 7;
const d = if (self.item) |d| d.dir() orelse return else return;
const n = d.total_items;
const n = (if (self.item) |d| d.dir() orelse return else return).items;
ui.move(self.row, self.col);
self.bg.fg(.num);
if (n < 1000)
ui.addprint(" {d:>4}", .{n})
else if (n < 100_000)
ui.addprint("{d:>6.3}", .{ @intToFloat(f32, n) / 1000 })
else if (n < 10_000) {
ui.addch(' ');
ui.addnum(self.bg, n);
} else if (n < 100_000)
ui.addnum(self.bg, n)
else if (n < 1000_000) {
ui.addprint("{d:>5.1}", .{ @intToFloat(f32, n) / 1000 });
self.bg.fg(.default);
@ -360,18 +366,20 @@ pub fn draw() !void {
ui.move(ui.rows-1, 0);
ui.hline(' ', ui.cols);
ui.move(ui.rows-1, 1);
ui.style(if (main.config.show_blocks) .bold_hd else .hd);
ui.addstr("Total disk usage: ");
ui.addsize(.hd, blocksToSize(dir_parents.top().entry.blocks));
ui.style(if (main.config.show_blocks) .hd else .bold_hd);
ui.addstr(" Apparent size: ");
ui.addsize(.hd, dir_parents.top().entry.size);
ui.addstr(" Items: ");
ui.addnum(.hd, dir_parents.top().total_items);
ui.addnum(.hd, dir_parents.top().items);
if (need_confirm_quit) drawQuit();
if (sel_row > 0) ui.move(sel_row, 0);
}
fn sortToggle(col: main.SortCol, default_order: main.SortOrder) void {
fn sortToggle(col: main.config.SortCol, default_order: main.config.SortOrder) void {
if (main.config.sort_col != col) main.config.sort_order = default_order
else if (main.config.sort_order == .asc) main.config.sort_order = .desc
else main.config.sort_order = .asc;

View file

@ -9,40 +9,38 @@ const c = @cImport(@cInclude("locale.h"));
pub const allocator = std.heap.c_allocator;
pub const SortCol = enum { name, blocks, size, items, mtime };
pub const SortOrder = enum { asc, desc };
pub const config = struct {
pub const SortCol = enum { name, blocks, size, items, mtime };
pub const SortOrder = enum { asc, desc };
pub const Config = struct {
same_fs: bool = true,
extended: bool = false,
follow_symlinks: bool = false,
exclude_caches: bool = false,
exclude_kernfs: bool = false,
exclude_patterns: std.ArrayList([:0]const u8) = std.ArrayList([:0]const u8).init(allocator),
pub var same_fs: bool = true;
pub var extended: bool = false;
pub var follow_symlinks: bool = false;
pub var exclude_caches: bool = false;
pub var exclude_kernfs: bool = false;
pub var exclude_patterns: std.ArrayList([:0]const u8) = std.ArrayList([:0]const u8).init(allocator);
update_delay: u64 = 100*std.time.ns_per_ms,
scan_ui: enum { none, line, full } = .full,
si: bool = false,
nc_tty: bool = false,
ui_color: enum { off, dark } = .off,
thousands_sep: []const u8 = ".",
pub var update_delay: u64 = 100*std.time.ns_per_ms;
pub var scan_ui: enum { none, line, full } = .full;
pub var si: bool = false;
pub var nc_tty: bool = false;
pub var ui_color: enum { off, dark } = .off;
pub var thousands_sep: []const u8 = ",";
show_hidden: bool = true,
show_blocks: bool = true,
show_items: bool = false,
show_mtime: bool = false,
show_graph: enum { off, graph, percent, both } = .graph,
sort_col: SortCol = .blocks,
sort_order: SortOrder = .desc,
sort_dirsfirst: bool = false,
pub var show_hidden: bool = true;
pub var show_blocks: bool = true;
pub var show_items: bool = false;
pub var show_mtime: bool = false;
pub var show_graph: enum { off, graph, percent, both } = .graph;
pub var sort_col: SortCol = .blocks;
pub var sort_order: SortOrder = .desc;
pub var sort_dirsfirst: bool = false;
read_only: bool = false,
can_shell: bool = true,
confirm_quit: bool = false,
pub var read_only: bool = false;
pub var can_shell: bool = true;
pub var confirm_quit: bool = false;
};
pub var config = Config{};
pub var state: enum { scan, browse } = .browse;
// Simple generic argument parser, supports getopt_long() style arguments.
@ -298,30 +296,30 @@ test "argument parser" {
const l = L{ .lst = &lst };
const T = struct {
a: Args(L),
fn opt(self: *@This(), isopt: bool, val: []const u8) void {
fn opt(self: *@This(), isopt: bool, val: []const u8) !void {
const o = self.a.next().?;
std.testing.expectEqual(isopt, o.opt);
std.testing.expectEqualStrings(val, o.val);
std.testing.expectEqual(o.is(val), isopt);
try std.testing.expectEqual(isopt, o.opt);
try std.testing.expectEqualStrings(val, o.val);
try std.testing.expectEqual(o.is(val), isopt);
}
fn arg(self: *@This(), val: []const u8) void {
std.testing.expectEqualStrings(val, self.a.arg());
fn arg(self: *@This(), val: []const u8) !void {
try std.testing.expectEqualStrings(val, self.a.arg());
}
};
var t = T{ .a = Args(L).init(l) };
t.opt(false, "a");
t.opt(true, "-a");
t.opt(true, "-b");
t.arg("cd=e");
t.opt(true, "--opt1");
t.arg("arg1");
t.opt(true, "--opt2");
t.arg("arg2");
t.opt(true, "-x");
t.arg("foo");
t.opt(false, "");
t.opt(false, "--arg");
t.opt(false, "");
t.opt(false, "-");
std.testing.expectEqual(t.a.next(), null);
try t.opt(false, "a");
try t.opt(true, "-a");
try t.opt(true, "-b");
try t.arg("cd=e");
try t.opt(true, "--opt1");
try t.arg("arg1");
try t.opt(true, "--opt2");
try t.arg("arg2");
try t.opt(true, "-x");
try t.arg("foo");
try t.opt(false, "");
try t.opt(false, "--arg");
try t.opt(false, "");
try t.opt(false, "-");
try std.testing.expectEqual(t.a.next(), null);
}

View file

@ -113,6 +113,7 @@ pub const Entry = packed struct {
if (self.ext()) |e|
if (p.entry.ext()) |pe|
if (e.mtime > pe.mtime) { pe.mtime = e.mtime; };
p.items = saturateAdd(p.items, 1);
// Hardlink in a subdirectory with a different device, only count it the first time.
if (self.link() != null and dev != p.dev) {
@ -128,12 +129,10 @@ pub const Entry = packed struct {
add_total = true;
p.shared_size = saturateAdd(p.shared_size, self.size);
p.shared_blocks = saturateAdd(p.shared_blocks, self.blocks);
p.shared_items = saturateAdd(p.shared_items, 1);
// Encountered this file in this dir the same number of times as its link count, meaning it's not shared with other dirs.
} else if(d.entry.key.num_files == l.nlink) {
p.shared_size = saturateSub(p.shared_size, self.size);
p.shared_blocks = saturateSub(p.shared_blocks, self.blocks);
p.shared_items = saturateSub(p.shared_items, 1);
}
} else {
add_total = true;
@ -141,7 +140,6 @@ pub const Entry = packed struct {
if(add_total) {
p.entry.size = saturateAdd(p.entry.size, self.size);
p.entry.blocks = saturateAdd(p.entry.blocks, self.blocks);
p.total_items = saturateAdd(p.total_items, 1);
}
}
}
@ -161,10 +159,7 @@ pub const Dir = packed struct {
// (space reclaimed by deleting a dir =~ entry. - shared_)
shared_blocks: u64,
shared_size: u64,
shared_items: u32,
total_items: u32,
// TODO: ncdu1 only keeps track of a total item count including duplicate hardlinks.
// That number seems useful, too. Include it somehow?
items: u32,
// Indexes into the global 'devices' array
dev: DevId,

View file

@ -118,25 +118,25 @@ pub fn shorten(in: [:0]const u8, max_width: u32) ![:0] const u8 {
return try arrayListBufZ(&shorten_buf);
}
fn shortenTest(in: [:0]const u8, max_width: u32, out: [:0]const u8) void {
std.testing.expectEqualStrings(out, shorten(in, max_width) catch unreachable);
fn shortenTest(in: [:0]const u8, max_width: u32, out: [:0]const u8) !void {
try std.testing.expectEqualStrings(out, try shorten(in, max_width));
}
test "shorten" {
_ = c.setlocale(c.LC_ALL, ""); // libc wcwidth() may not recognize Unicode without this
const t = shortenTest;
t("abcde", 3, "...");
t("abcde", 5, "abcde");
t("abcde", 4, "...e");
t("abcdefgh", 6, "a...gh");
t("abcdefgh", 7, "ab...gh");
t("", 16, "");
t("", 7, "...");
t("", 8, "...");
t("", 9, "...");
t("a", 8, "..."); // could optimize this, but w/e
t("a", 8, "...a");
t("", 15, "...");
try t("abcde", 3, "...");
try t("abcde", 5, "abcde");
try t("abcde", 4, "...e");
try t("abcdefgh", 6, "a...gh");
try t("abcdefgh", 7, "ab...gh");
try t("", 16, "");
try t("", 7, "...");
try t("", 8, "...");
try t("", 9, "...");
try t("a", 8, "..."); // could optimize this, but w/e
try t("a", 8, "...a");
try t("", 15, "...");
}
// ncurses_refs.c
@ -167,6 +167,9 @@ const styles = [_]StyleDef{
.{ .name = "bold",
.off = .{ .fg = -1, .bg = -1, .attr = c.A_BOLD },
.dark = .{ .fg = -1, .bg = -1, .attr = c.A_BOLD } },
.{ .name = "bold_hd",
.off = .{ .fg = -1, .bg = -1, .attr = c.A_BOLD|c.A_REVERSE },
.dark = .{ .fg = c.COLOR_BLACK, .bg = c.COLOR_CYAN, .attr = c.A_BOLD } },
.{ .name = "box_title",
.off = .{ .fg = -1, .bg = -1, .attr = c.A_BOLD },
.dark = .{ .fg = c.COLOR_BLUE, .bg = -1, .attr = c.A_BOLD } },