地圖 (Jido) is a lightweight Unix TUI file explorer designed for speed and simplicity.
1const std = @import("std");
2const App = @import("./app.zig");
3const config = &@import("./config.zig").config;
4const zuid = @import("zuid");
5const environment = @import("./environment.zig");
6const vaxis = @import("vaxis");
7
8pub fn delete(app: *App) error{OutOfMemory}!void {
9 var message: ?[]const u8 = null;
10 defer if (message) |msg| app.alloc.free(msg);
11
12 const entry = (app.directories.getSelected() catch {
13 app.notification.write("Can not to delete item - no item selected.", .warn) catch {};
14 return;
15 }) orelse return;
16
17 var prev_path_buf: [std.fs.max_path_bytes]u8 = undefined;
18 const prev_path = app.directories.dir.realpath(entry.name, &prev_path_buf) catch {
19 message = try std.fmt.allocPrint(app.alloc, "Failed to delete '{s}' - unable to retrieve absolute path.", .{entry.name});
20 app.notification.write(message.?, .err) catch {};
21 if (app.file_logger) |file_logger| file_logger.write(message.?, .err) catch {};
22 return;
23 };
24 const prev_path_alloc = try app.alloc.dupe(u8, prev_path);
25
26 var trash_dir = dir: {
27 notfound: {
28 break :dir (config.trashDir() catch break :notfound) orelse break :notfound;
29 }
30 app.alloc.free(prev_path_alloc);
31 message = try std.fmt.allocPrint(app.alloc, "Failed to delete '{s}' - unable to retrieve trash directory.", .{entry.name});
32 app.notification.write(message.?, .err) catch {};
33 if (app.file_logger) |file_logger| file_logger.write(message.?, .err) catch {};
34 return;
35 };
36 defer trash_dir.close();
37
38 var trash_dir_path_buf: [std.fs.max_path_bytes]u8 = undefined;
39 const trash_dir_path = trash_dir.realpath(".", &trash_dir_path_buf) catch {
40 message = try std.fmt.allocPrint(app.alloc, "Failed to delete '{s}' - unable to retrieve absolute path for trash directory.", .{entry.name});
41 app.notification.write(message.?, .err) catch {};
42 if (app.file_logger) |file_logger| file_logger.write(message.?, .err) catch {};
43 return;
44 };
45
46 if (std.mem.eql(u8, prev_path_alloc, trash_dir_path)) {
47 app.notification.write("Can not delete trash directory.", .warn) catch {};
48 app.alloc.free(prev_path_alloc);
49 return;
50 }
51
52 const tmp_path = try std.fmt.allocPrint(app.alloc, "{s}/{s}-{s}", .{ trash_dir_path, entry.name, zuid.new.v4() });
53 if (app.directories.dir.rename(entry.name, tmp_path)) {
54 if (app.actions.push(.{
55 .delete = .{ .prev_path = prev_path_alloc, .new_path = tmp_path },
56 })) |prev_elem| {
57 app.alloc.free(prev_elem.delete.prev_path);
58 app.alloc.free(prev_elem.delete.new_path);
59 }
60 message = try std.fmt.allocPrint(app.alloc, "Deleted '{s}'.", .{entry.name});
61 app.notification.write(message.?, .info) catch {};
62
63 app.directories.removeSelected();
64 } else |err| {
65 app.alloc.free(prev_path_alloc);
66 app.alloc.free(tmp_path);
67
68 message = try std.fmt.allocPrint(app.alloc, "Failed to delete '{s}' - {}.", .{ entry.name, err });
69 app.notification.write(message.?, .err) catch {};
70 }
71}
72
73pub fn rename(app: *App) error{OutOfMemory}!void {
74 var message: ?[]const u8 = null;
75 defer if (message) |msg| app.alloc.free(msg);
76
77 const entry = (app.directories.getSelected() catch {
78 app.notification.write("Can not to rename item - no item selected.", .warn) catch {};
79 return;
80 }) orelse return;
81
82 var dir_prefix_buf: [std.fs.max_path_bytes]u8 = undefined;
83 const dir_prefix = app.directories.dir.realpath(".", &dir_prefix_buf) catch {
84 message = try std.fmt.allocPrint(app.alloc, "Failed to rename '{s}' - unable to retrieve absolute path.", .{entry.name});
85 app.notification.write(message.?, .err) catch {};
86 if (app.file_logger) |file_logger| file_logger.write(message.?, .err) catch {};
87 return;
88 };
89
90 const new_path = app.inputToSlice();
91
92 if (environment.fileExists(app.directories.dir, new_path)) {
93 message = try std.fmt.allocPrint(app.alloc, "Can not rename file - '{s}' already exists.", .{new_path});
94 app.notification.write(message.?, .warn) catch {};
95 } else {
96 app.directories.dir.rename(entry.name, new_path) catch |err| {
97 message = try std.fmt.allocPrint(app.alloc, "Failed to rename '{s}' - {}.", .{ new_path, err });
98 app.notification.write(message.?, .err) catch {};
99 if (app.file_logger) |file_logger| file_logger.write(message.?, .err) catch {};
100 return;
101 };
102
103 if (app.actions.push(.{
104 .rename = .{
105 .prev_path = try std.fs.path.join(app.alloc, &.{ dir_prefix, entry.name }),
106 .new_path = try std.fs.path.join(app.alloc, &.{ dir_prefix, new_path }),
107 },
108 })) |prev_elem| {
109 app.alloc.free(prev_elem.rename.prev_path);
110 app.alloc.free(prev_elem.rename.new_path);
111 }
112
113 try app.repopulateDirectory("");
114 app.text_input.clearAndFree();
115
116 message = try std.fmt.allocPrint(app.alloc, "Renamed '{s}' to '{s}'.", .{ entry.name, new_path });
117 app.notification.write(message.?, .info) catch {};
118 }
119
120 app.text_input.clearAndFree();
121}
122
123pub fn forceDelete(app: *App) error{OutOfMemory}!void {
124 const entry = (app.directories.getSelected() catch {
125 app.notification.write("Can not force delete item - no item selected.", .warn) catch {};
126 return;
127 }) orelse return;
128
129 app.directories.dir.deleteTree(entry.name) catch |err| {
130 const error_message = try std.fmt.allocPrint(app.alloc, "Failed to force delete '{s}' - {}.", .{ entry.name, err });
131 app.notification.write(error_message, .err) catch {};
132 return;
133 };
134
135 app.directories.removeSelected();
136}
137
138pub fn toggleHiddenFiles(app: *App) error{OutOfMemory}!void {
139 config.show_hidden = !config.show_hidden;
140
141 const prev_selected_name: []const u8, const prev_selected_err: bool = lbl: {
142 const selected = app.directories.getSelected() catch break :lbl .{ "", true };
143 if (selected == null) break :lbl .{ "", true };
144
145 break :lbl .{ try app.alloc.dupe(u8, selected.?.name), false };
146 };
147 defer if (!prev_selected_err) app.alloc.free(prev_selected_name);
148
149 try app.repopulateDirectory("");
150 app.text_input.clearAndFree();
151
152 for (app.directories.entries.all()) |entry| {
153 if (std.mem.eql(u8, entry.name, prev_selected_name)) return;
154 app.directories.entries.selected += 1;
155 }
156
157 // If it didn't find entry, reset selected.
158 app.directories.entries.selected = 0;
159}
160
161pub fn yank(app: *App) error{OutOfMemory}!void {
162 var message: ?[]const u8 = null;
163 defer if (message) |msg| app.alloc.free(msg);
164
165 if (app.yanked) |yanked| {
166 app.alloc.free(yanked.dir);
167 app.alloc.free(yanked.entry.name);
168 }
169
170 app.yanked = lbl: {
171 const entry = (app.directories.getSelected() catch {
172 app.notification.write("Can not yank item - no item selected.", .warn) catch {};
173 break :lbl null;
174 }) orelse break :lbl null;
175
176 switch (entry.kind) {
177 .file, .directory, .sym_link => {
178 break :lbl .{
179 .dir = try app.alloc.dupe(u8, app.directories.fullPath(".") catch {
180 message = try std.fmt.allocPrint(
181 app.alloc,
182 "Failed to yank '{s}' - unable to retrieve directory path.",
183 .{entry.name},
184 );
185 app.notification.write(message.?, .err) catch {};
186 if (app.file_logger) |file_logger| file_logger.write(message.?, .err) catch {};
187 break :lbl null;
188 }),
189 .entry = .{
190 .kind = entry.kind,
191 .name = try app.alloc.dupe(u8, entry.name),
192 },
193 };
194 },
195 else => {
196 message = try std.fmt.allocPrint(app.alloc, "Can not yank '{s}' - unsupported file type '{s}'.", .{ entry.name, @tagName(entry.kind) });
197 app.notification.write(message.?, .warn) catch {};
198 break :lbl null;
199 },
200 }
201 };
202
203 if (app.yanked) |y| {
204 message = try std.fmt.allocPrint(app.alloc, "Yanked '{s}'.", .{y.entry.name});
205 app.notification.write(message.?, .info) catch {};
206 }
207}
208
209pub fn paste(app: *App) error{ OutOfMemory, NoSpaceLeft }!void {
210 var message: ?[]const u8 = null;
211 defer if (message) |msg| app.alloc.free(msg);
212
213 const yanked = if (app.yanked) |y| y else return;
214
215 var new_path_buf: [std.fs.max_path_bytes]u8 = undefined;
216 const new_path_res = environment.checkDuplicatePath(&new_path_buf, app.directories.dir, yanked.entry.name) catch {
217 message = try std.fmt.allocPrint(app.alloc, "Failed to copy '{s}' - path too long.", .{yanked.entry.name});
218 app.notification.write(message.?, .err) catch {};
219 return;
220 };
221
222 switch (yanked.entry.kind) {
223 .directory => {
224 var source_dir = std.fs.openDirAbsolute(yanked.dir, .{ .iterate = true }) catch {
225 message = try std.fmt.allocPrint(app.alloc, "Failed to copy '{s}' - unable to open directory '{s}'.", .{ yanked.entry.name, yanked.dir });
226 app.notification.write(message.?, .err) catch {};
227 if (app.file_logger) |file_logger| file_logger.write(message.?, .err) catch {};
228 return;
229 };
230 defer source_dir.close();
231
232 var selected_dir = source_dir.openDir(yanked.entry.name, .{ .iterate = true }) catch {
233 message = try std.fmt.allocPrint(app.alloc, "Failed to copy '{s}' - unable to open directory '{s}'.", .{ yanked.entry.name, yanked.entry.name });
234 app.notification.write(message.?, .err) catch {};
235 if (app.file_logger) |file_logger| file_logger.write(message.?, .err) catch {};
236 return;
237 };
238 defer selected_dir.close();
239
240 var walker = selected_dir.walk(app.alloc) catch |err| {
241 message = try std.fmt.allocPrint(app.alloc, "Failed to copy '{s}' - unable to walk directory tree due to {}.", .{ yanked.entry.name, err });
242 app.notification.write(message.?, .err) catch {};
243 if (app.file_logger) |file_logger| file_logger.write(message.?, .err) catch {};
244 return;
245 };
246 defer walker.deinit();
247
248 // Make initial dir.
249 app.directories.dir.makeDir(new_path_res.path) catch |err| {
250 message = try std.fmt.allocPrint(app.alloc, "Failed to copy '{s}' - unable to create new directory due to {}.", .{ yanked.entry.name, err });
251 app.notification.write(message.?, .err) catch {};
252 if (app.file_logger) |file_logger| file_logger.write(message.?, .err) catch {};
253 return;
254 };
255
256 var errored = false;
257 var inner_path_buf: [std.fs.max_path_bytes]u8 = undefined;
258 while (walker.next() catch |err| {
259 message = try std.fmt.allocPrint(app.alloc, "Failed to copy one or more files - {}. A partial copy may have taken place.", .{err});
260 app.notification.write(message.?, .err) catch {};
261 if (app.file_logger) |file_logger| file_logger.write(message.?, .err) catch {};
262 return;
263 }) |entry| {
264 const path = try std.fmt.bufPrint(&inner_path_buf, "{s}{s}{s}", .{ new_path_res.path, std.fs.path.sep_str, entry.path });
265 switch (entry.kind) {
266 .directory => {
267 app.directories.dir.makeDir(path) catch {
268 message = try std.fmt.allocPrint(app.alloc, "Failed to copy '{s}' - unable to create containing directory '{s}'.", .{ entry.basename, path });
269 app.notification.write(message.?, .err) catch {};
270 if (app.file_logger) |file_logger| file_logger.write(message.?, .err) catch {};
271 errored = true;
272 };
273 },
274 .file, .sym_link => {
275 entry.dir.copyFile(entry.basename, app.directories.dir, path, .{}) catch |err| switch (err) {
276 error.FileNotFound => {
277 message = try std.fmt.allocPrint(app.alloc, "Failed to copy '{s}' - the original file was deleted or moved.", .{entry.path});
278 app.notification.write(message.?, .err) catch {};
279 if (app.file_logger) |file_logger| file_logger.write(message.?, .err) catch {};
280 errored = true;
281 },
282 else => {
283 message = try std.fmt.allocPrint(app.alloc, "Failed to copy '{s}' - {}.", .{ entry.path, err });
284 app.notification.write(message.?, .err) catch {};
285 if (app.file_logger) |file_logger| file_logger.write(message.?, .err) catch {};
286 errored = true;
287 },
288 };
289 },
290 else => {
291 message = try std.fmt.allocPrint(app.alloc, "Failed to copy '{s}' - unsupported file type '{s}'.", .{ entry.path, @tagName(entry.kind) });
292 app.notification.write(message.?, .err) catch {};
293 if (app.file_logger) |file_logger| file_logger.write(message.?, .err) catch {};
294 errored = true;
295 },
296 }
297 }
298
299 if (errored) {
300 app.notification.write("Failed to copy some items, check the log file for more details.", .err) catch {};
301 } else {
302 message = try std.fmt.allocPrint(app.alloc, "Copied '{s}'.", .{yanked.entry.name});
303 app.notification.write(message.?, .info) catch {};
304 }
305 },
306 .file, .sym_link => {
307 var source_dir = std.fs.openDirAbsolute(yanked.dir, .{ .iterate = true }) catch {
308 message = try std.fmt.allocPrint(app.alloc, "Failed to copy '{s}' - unable to open directory '{s}'.", .{ yanked.entry.name, yanked.dir });
309 app.notification.write(message.?, .err) catch {};
310 if (app.file_logger) |file_logger| file_logger.write(message.?, .err) catch {};
311 return;
312 };
313 defer source_dir.close();
314
315 std.fs.Dir.copyFile(
316 source_dir,
317 yanked.entry.name,
318 app.directories.dir,
319 new_path_res.path,
320 .{},
321 ) catch |err| switch (err) {
322 error.FileNotFound => {
323 message = try std.fmt.allocPrint(app.alloc, "Failed to copy '{s}' - the original file was deleted or moved.", .{yanked.entry.name});
324 app.notification.write(message.?, .err) catch {};
325 if (app.file_logger) |file_logger| file_logger.write(message.?, .err) catch {};
326 return;
327 },
328 else => {
329 message = try std.fmt.allocPrint(app.alloc, "Failed to copy '{s}' - {}.", .{ yanked.entry.name, err });
330 app.notification.write(message.?, .err) catch {};
331 if (app.file_logger) |file_logger| file_logger.write(message.?, .err) catch {};
332 return;
333 },
334 };
335
336 message = try std.fmt.allocPrint(app.alloc, "Copied '{s}'.", .{yanked.entry.name});
337 app.notification.write(message.?, .info) catch {};
338 },
339 else => {
340 message = try std.fmt.allocPrint(app.alloc, "Can not copy '{s}' - unsupported file type '{s}'.", .{ yanked.entry.name, @tagName(yanked.entry.kind) });
341 app.notification.write(message.?, .warn) catch {};
342 return;
343 },
344 }
345
346 // Append action to undo history.
347 var new_path_abs_buf: [std.fs.max_path_bytes]u8 = undefined;
348 const new_path_abs = app.directories.dir.realpath(new_path_res.path, &new_path_abs_buf) catch {
349 message = try std.fmt.allocPrint(
350 app.alloc,
351 "Failed to push copy action for '{s}' to undo history - unable to retrieve absolute directory path for '{s}'. This action will not be able to be undone via the `undo` keybind.",
352 .{ new_path_res.path, yanked.entry.name },
353 );
354 app.notification.write(message.?, .err) catch {};
355 if (app.file_logger) |file_logger| file_logger.write(message.?, .err) catch {};
356 return;
357 };
358
359 if (app.actions.push(.{
360 .paste = try app.alloc.dupe(u8, new_path_abs),
361 })) |prev_elem| {
362 app.alloc.free(prev_elem.delete.prev_path);
363 app.alloc.free(prev_elem.delete.new_path);
364 }
365
366 try app.repopulateDirectory("");
367 app.text_input.clearAndFree();
368}
369
370pub fn traverseLeft(app: *App) error{OutOfMemory}!void {
371 app.text_input.clearAndFree();
372
373 const dir = app.directories.dir.openDir("../", .{ .iterate = true }) catch |err| {
374 const message = try std.fmt.allocPrint(app.alloc, "Failed to read directory entries - {}.", .{err});
375 defer app.alloc.free(message);
376 app.notification.write(message, .err) catch {};
377 if (app.file_logger) |file_logger| file_logger.write(message, .err) catch {};
378 return;
379 };
380
381 app.directories.dir.close();
382 app.directories.dir = dir;
383
384 try app.repopulateDirectory("");
385 app.text_input.clearAndFree();
386
387 if (app.directories.history.pop()) |history| {
388 if (history < app.directories.entries.len()) {
389 app.directories.entries.selected = history;
390 }
391 }
392}
393
394pub fn traverseRight(app: *App) !void {
395 var message: ?[]const u8 = null;
396 defer if (message) |msg| app.alloc.free(msg);
397
398 const entry = (app.directories.getSelected() catch {
399 app.notification.write("Can not rename item - no item selected.", .warn) catch {};
400 return;
401 }) orelse return;
402
403 switch (entry.kind) {
404 .directory => {
405 app.text_input.clearAndFree();
406
407 const dir = app.directories.dir.openDir(entry.name, .{ .iterate = true }) catch |err| {
408 message = try std.fmt.allocPrint(app.alloc, "Failed to read directory entries - {}.", .{err});
409 app.notification.write(message.?, .err) catch {};
410 if (app.file_logger) |file_logger| file_logger.write(message.?, .err) catch {};
411 return;
412 };
413
414 app.directories.dir.close();
415 app.directories.dir = dir;
416 _ = app.directories.history.push(app.directories.entries.selected);
417 try app.repopulateDirectory("");
418 app.text_input.clearAndFree();
419 },
420 .file => {
421 if (environment.getEditor()) |editor| {
422 try app.vx.exitAltScreen(app.tty.anyWriter());
423 try app.vx.resetState(app.tty.anyWriter());
424 app.loop.stop();
425
426 environment.openFile(app.alloc, app.directories.dir, entry.name, editor) catch |err| {
427 message = try std.fmt.allocPrint(app.alloc, "Failed to open file '{s}' - {}.", .{ entry.name, err });
428 app.notification.write(message.?, .err) catch {};
429 if (app.file_logger) |file_logger| file_logger.write(message.?, .err) catch {};
430 };
431
432 try app.loop.start();
433 try app.vx.enterAltScreen(app.tty.anyWriter());
434 try app.vx.enableDetectedFeatures(app.tty.anyWriter());
435 app.vx.queueRefresh();
436 } else {
437 app.notification.write("Can not open file - $EDITOR not set.", .warn) catch {};
438 }
439 },
440 else => {},
441 }
442}
443
444pub fn createNewDir(app: *App) error{OutOfMemory}!void {
445 var message: ?[]const u8 = null;
446 defer if (message) |msg| app.alloc.free(msg);
447
448 const dir = app.inputToSlice();
449
450 app.directories.dir.makeDir(dir) catch |err| {
451 message = try std.fmt.allocPrint(app.alloc, "Failed to create directory '{s}' - {}", .{ dir, err });
452 app.notification.write(message.?, .err) catch {};
453 if (app.file_logger) |file_logger| file_logger.write(message.?, .err) catch {};
454 app.text_input.clearAndFree();
455 return;
456 };
457
458 try app.repopulateDirectory("");
459 app.text_input.clearAndFree();
460
461 message = try std.fmt.allocPrint(app.alloc, "Created new directory '{s}'.", .{dir});
462 app.notification.write(message.?, .info) catch {};
463}
464
465pub fn createNewFile(app: *App) error{OutOfMemory}!void {
466 var message: ?[]const u8 = null;
467 defer if (message) |msg| app.alloc.free(msg);
468
469 const file = app.inputToSlice();
470
471 if (environment.fileExists(app.directories.dir, file)) {
472 message = try std.fmt.allocPrint(app.alloc, "Can not create file - '{s}' already exists.", .{file});
473 app.notification.write(message.?, .warn) catch {};
474 } else {
475 _ = app.directories.dir.createFile(file, .{}) catch |err| {
476 message = try std.fmt.allocPrint(app.alloc, "Failed to create file '{s}' - {}", .{ file, err });
477 app.notification.write(message.?, .err) catch {};
478 if (app.file_logger) |file_logger| file_logger.write(message.?, .err) catch {};
479 app.text_input.clearAndFree();
480 return;
481 };
482
483 try app.repopulateDirectory("");
484 app.text_input.clearAndFree();
485
486 message = try std.fmt.allocPrint(app.alloc, "Created new file '{s}'.", .{file});
487 app.notification.write(message.?, .info) catch {};
488 }
489
490 app.text_input.clearAndFree();
491}
492
493pub fn undo(app: *App) error{OutOfMemory}!void {
494 var message: ?[]const u8 = null;
495 defer if (message) |msg| app.alloc.free(msg);
496
497 const action = app.actions.pop() orelse {
498 app.notification.write("There is nothing to undo.", .info) catch {};
499 return;
500 };
501
502 const selected = app.directories.entries.selected;
503
504 switch (action) {
505 .delete => |a| {
506 defer app.alloc.free(a.new_path);
507 defer app.alloc.free(a.prev_path);
508
509 var new_path_buf: [std.fs.max_path_bytes]u8 = undefined;
510 const new_path_res = environment.checkDuplicatePath(&new_path_buf, app.directories.dir, a.prev_path) catch {
511 message = try std.fmt.allocPrint(app.alloc, "Failed to undo delete '{s}' - path too long.", .{a.prev_path});
512 app.notification.write(message.?, .err) catch {};
513 if (app.file_logger) |file_logger| file_logger.write(message.?, .err) catch {};
514 return;
515 };
516
517 app.directories.dir.rename(a.new_path, new_path_res.path) catch |err| {
518 message = try std.fmt.allocPrint(app.alloc, "Failed to undo delete for '{s}' - {}.", .{ a.prev_path, err });
519 app.notification.write(message.?, .err) catch {};
520 if (app.file_logger) |file_logger| file_logger.write(message.?, .err) catch {};
521 return;
522 };
523
524 try app.repopulateDirectory("");
525 app.text_input.clearAndFree();
526
527 message = try std.fmt.allocPrint(app.alloc, "Restored '{s}' as '{s}'.", .{ a.prev_path, new_path_res.path });
528 app.notification.write(message.?, .info) catch {};
529 },
530 .rename => |a| {
531 defer app.alloc.free(a.new_path);
532 defer app.alloc.free(a.prev_path);
533
534 var new_path_buf: [std.fs.max_path_bytes]u8 = undefined;
535 const new_path_res = environment.checkDuplicatePath(&new_path_buf, app.directories.dir, a.prev_path) catch {
536 message = try std.fmt.allocPrint(app.alloc, "Failed to undo rename '{s}' - path too long.", .{a.prev_path});
537 app.notification.write(message.?, .err) catch {};
538 if (app.file_logger) |file_logger| file_logger.write(message.?, .err) catch {};
539 return;
540 };
541
542 app.directories.dir.rename(a.new_path, new_path_res.path) catch |err| {
543 message = try std.fmt.allocPrint(app.alloc, "Failed to undo rename for '{s}' - {}.", .{ a.new_path, err });
544 app.notification.write(message.?, .err) catch {};
545 if (app.file_logger) |file_logger| file_logger.write(message.?, .err) catch {};
546 return;
547 };
548
549 try app.repopulateDirectory("");
550 app.text_input.clearAndFree();
551
552 message = try std.fmt.allocPrint(app.alloc, "Reverted renaming of '{s}', now '{s}'.", .{ a.new_path, new_path_res.path });
553 app.notification.write(message.?, .info) catch {};
554 },
555 .paste => |path| {
556 defer app.alloc.free(path);
557
558 app.directories.dir.deleteTree(path) catch |err| {
559 message = try std.fmt.allocPrint(app.alloc, "Failed to delete '{s}' - {}.", .{ path, err });
560 app.notification.write(message.?, .err) catch {};
561 if (app.file_logger) |file_logger| file_logger.write(message.?, .err) catch {};
562 return;
563 };
564
565 try app.repopulateDirectory("");
566 app.text_input.clearAndFree();
567 },
568 }
569
570 app.directories.entries.selected = selected;
571}