Skip to content
Snippets Groups Projects
Commit c077c5be authored by Yorhel's avatar Yorhel
Browse files

Implement JSON file import

Performance is looking great, but the code is rather ugly and
potentially buggy. Also doesn't handle hard links without an "nlink"
field yet.

Error handling of the import code is different from what I've been doing
until now. That's intentional, I'll change error handling of other
pieces to call ui.die() directly rather than propagating error enums.
The approach is less testable but conceptually simpler, it's perfectly
fine for a tiny application like ncdu.
parent 9474aa43
No related branches found
No related tags found
No related merge requests found
zig-cache/ zig-cache/
zig-out/
ncdu.1 ncdu.1
*~ *~
*.swp *.swp
......
...@@ -28,7 +28,6 @@ backported to the C version, depending on how viable a proper Zig release is. ...@@ -28,7 +28,6 @@ backported to the C version, depending on how viable a proper Zig release is.
Missing features: Missing features:
- File import
- Lots of informational UI windows - Lots of informational UI windows
- Directory refresh - Directory refresh
- File deletion - File deletion
......
...@@ -324,11 +324,13 @@ pub fn draw() !void { ...@@ -324,11 +324,13 @@ pub fn draw() !void {
ui.addch('?'); ui.addch('?');
ui.style(.hd); ui.style(.hd);
ui.addstr(" for help"); ui.addstr(" for help");
if (main.config.read_only) { if (main.config.imported) {
ui.move(0, saturateSub(ui.cols, 10));
ui.addstr("[imported]");
} else if (main.config.read_only) {
ui.move(0, saturateSub(ui.cols, 10)); ui.move(0, saturateSub(ui.cols, 10));
ui.addstr("[readonly]"); ui.addstr("[readonly]");
} }
// TODO: [imported] indicator
ui.style(.default); ui.style(.default);
ui.move(1,0); ui.move(1,0);
...@@ -387,7 +389,7 @@ fn sortToggle(col: main.config.SortCol, default_order: main.config.SortOrder) vo ...@@ -387,7 +389,7 @@ fn sortToggle(col: main.config.SortCol, default_order: main.config.SortOrder) vo
sortDir(); sortDir();
} }
pub fn key(ch: i32) !void { pub fn keyInput(ch: i32) !void {
if (need_confirm_quit) { if (need_confirm_quit) {
switch (ch) { switch (ch) {
'y', 'Y' => if (need_confirm_quit) ui.quit(), 'y', 'Y' => if (need_confirm_quit) ui.quit(),
......
...@@ -37,6 +37,7 @@ pub const config = struct { ...@@ -37,6 +37,7 @@ pub const config = struct {
pub var sort_dirsfirst: bool = false; pub var sort_dirsfirst: bool = false;
pub var read_only: bool = false; pub var read_only: bool = false;
pub var imported: bool = false;
pub var can_shell: bool = true; pub var can_shell: bool = true;
pub var confirm_quit: bool = false; pub var confirm_quit: bool = false;
}; };
...@@ -164,7 +165,6 @@ fn readExcludeFile(path: []const u8) !void { ...@@ -164,7 +165,6 @@ fn readExcludeFile(path: []const u8) !void {
// TODO: Better error reporting // TODO: Better error reporting
pub fn main() !void { pub fn main() !void {
// Grab thousands_sep from the current C locale. // Grab thousands_sep from the current C locale.
// (We can safely remove this when not linking against libc, it's a somewhat obscure feature)
_ = c.setlocale(c.LC_ALL, ""); _ = c.setlocale(c.LC_ALL, "");
if (c.localeconv()) |locale| { if (c.localeconv()) |locale| {
if (locale.*.thousands_sep) |sep| { if (locale.*.thousands_sep) |sep| {
...@@ -176,8 +176,8 @@ pub fn main() !void { ...@@ -176,8 +176,8 @@ pub fn main() !void {
var args = Args(std.process.ArgIteratorPosix).init(std.process.ArgIteratorPosix.init()); var args = Args(std.process.ArgIteratorPosix).init(std.process.ArgIteratorPosix.init());
var scan_dir: ?[]const u8 = null; var scan_dir: ?[]const u8 = null;
var import_file: ?[]const u8 = null; var import_file: ?[:0]const u8 = null;
var export_file: ?[]const u8 = null; var export_file: ?[:0]const u8 = null;
var has_scan_ui = false; var has_scan_ui = false;
_ = args.next(); // program name _ = args.next(); // program name
while (args.next()) |opt| { while (args.next()) |opt| {
...@@ -197,7 +197,9 @@ pub fn main() !void { ...@@ -197,7 +197,9 @@ pub fn main() !void {
else if(opt.is("-0")) { has_scan_ui = true; config.scan_ui = .none; } else if(opt.is("-0")) { has_scan_ui = true; config.scan_ui = .none; }
else if(opt.is("-1")) { has_scan_ui = true; config.scan_ui = .line; } else if(opt.is("-1")) { has_scan_ui = true; config.scan_ui = .line; }
else if(opt.is("-2")) { has_scan_ui = true; config.scan_ui = .full; } else if(opt.is("-2")) { has_scan_ui = true; config.scan_ui = .full; }
else if(opt.is("-o") and export_file != null) ui.die("The -o flag can only be given once.\n", .{})
else if(opt.is("-o")) export_file = args.arg() else if(opt.is("-o")) export_file = args.arg()
else if(opt.is("-f") and import_file != null) ui.die("The -f flag can only be given once.\n", .{})
else if(opt.is("-f")) import_file = args.arg() else if(opt.is("-f")) import_file = args.arg()
else if(opt.is("--si")) config.si = true else if(opt.is("--si")) config.si = true
else if(opt.is("-L") or opt.is("--follow-symlinks")) config.follow_symlinks = true else if(opt.is("-L") or opt.is("--follow-symlinks")) config.follow_symlinks = true
...@@ -220,24 +222,28 @@ pub fn main() !void { ...@@ -220,24 +222,28 @@ pub fn main() !void {
ui.die("The --exclude-kernfs tag is currently only supported on Linux.\n", .{}); ui.die("The --exclude-kernfs tag is currently only supported on Linux.\n", .{});
const out_tty = std.io.getStdOut().isTty(); const out_tty = std.io.getStdOut().isTty();
const in_tty = std.io.getStdIn().isTty();
if (!has_scan_ui) { if (!has_scan_ui) {
if (export_file) |f| { if (export_file) |f| {
if (!out_tty or std.mem.eql(u8, f, "-")) config.scan_ui = .none if (!out_tty or std.mem.eql(u8, f, "-")) config.scan_ui = .none
else config.scan_ui = .line; else config.scan_ui = .line;
} }
} }
config.nc_tty = if (export_file) |f| std.mem.eql(u8, f, "-") else false; if (!in_tty and import_file == null and export_file == null)
ui.die("Standard input is not a TTY. Did you mean to import a file using '-f -'?\n", .{});
config.nc_tty = !in_tty or (if (export_file) |f| std.mem.eql(u8, f, "-") else false);
event_delay_timer = try std.time.Timer.start(); event_delay_timer = try std.time.Timer.start();
defer ui.deinit(); defer ui.deinit();
state = .scan;
var out_file = if (export_file) |f| ( var out_file = if (export_file) |f| (
if (std.mem.eql(u8, f, "-")) std.io.getStdOut() if (std.mem.eql(u8, f, "-")) std.io.getStdOut()
else try std.fs.cwd().createFile(f, .{}) else try std.fs.cwd().createFileZ(f, .{})
) else null; ) else null;
state = .scan; try if (import_file) |f| scan.importRoot(f, out_file)
try scan.scanRoot(scan_dir orelse ".", out_file); else scan.scanRoot(scan_dir orelse ".", out_file);
if (out_file != null) return; if (out_file != null) return;
config.scan_ui = .full; // in case we're refreshing from the UI, always in full mode. config.scan_ui = .full; // in case we're refreshing from the UI, always in full mode.
...@@ -274,8 +280,8 @@ pub fn handleEvent(block: bool, force_draw: bool) !void { ...@@ -274,8 +280,8 @@ pub fn handleEvent(block: bool, force_draw: bool) !void {
if (ch == 0) return; if (ch == 0) return;
if (ch == -1) return handleEvent(firstblock, true); if (ch == -1) return handleEvent(firstblock, true);
switch (state) { switch (state) {
.scan => try scan.key(ch), .scan => try scan.keyInput(ch),
.browse => try browser.key(ch), .browse => try browser.keyInput(ch),
} }
firstblock = false; firstblock = false;
} }
......
...@@ -196,10 +196,10 @@ pub const File = packed struct { ...@@ -196,10 +196,10 @@ pub const File = packed struct {
}; };
pub const Ext = packed struct { pub const Ext = packed struct {
mtime: u64, mtime: u64 = 0,
uid: u32, uid: u32 = 0,
gid: u32, gid: u32 = 0,
mode: u16, mode: u16 = 0,
}; };
comptime { comptime {
......
This diff is collapsed.
...@@ -285,7 +285,6 @@ pub fn init() void { ...@@ -285,7 +285,6 @@ pub fn init() void {
if (term == null) die("Error initializing ncurses.\n", .{}); if (term == null) die("Error initializing ncurses.\n", .{});
_ = c.set_term(term); _ = c.set_term(term);
} else { } else {
if (!std.io.getStdIn().isTty()) die("Standard input is not a TTY. Did you mean to import a file using '-f -'?\n", .{});
if (c.initscr() == null) die("Error initializing ncurses.\n", .{}); if (c.initscr() == null) die("Error initializing ncurses.\n", .{});
} }
updateSize(); updateSize();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment