diff --git a/src/console/main.zig b/src/console/main.zig index 6d19624..1824760 100644 --- a/src/console/main.zig +++ b/src/console/main.zig @@ -227,7 +227,7 @@ const Model = struct { break :colors .{ fg, bg }; }; - const text = try ctx.arena.dupe(u8, child.fullName.path); + const text = try ctx.arena.dupe(u8, child.displayName); const text_element = try ctx.arena.create(vxfw.Text); text_element.* = vxfw.Text{ .text = text, diff --git a/src/core/action/action_handler.zig b/src/core/action/action_handler.zig index 56f0c57..515992f 100644 --- a/src/core/action/action_handler.zig +++ b/src/core/action/action_handler.zig @@ -18,10 +18,10 @@ pub fn handle(action: Action, appState: *AppState, arena: std.mem.Allocator) !Ac } else return error.NoCurrentLocation; }, .SelectNext => { - return selectNextIndex(appState.currentTab, .Next); + return selectNextIndex(appState.currentTab, .Next, arena); }, .SelectPrevious => { - return selectNextIndex(appState.currentTab, .Previous); + return selectNextIndex(appState.currentTab, .Previous, arena); }, } @@ -35,29 +35,38 @@ const SelectStep = enum { PreviousPage, }; -fn selectNextIndex(currentTab: *Tab, step: SelectStep) ActionResult { - const index = blk: { +fn selectNextIndex(currentTab: *Tab, step: SelectStep, arena: std.mem.Allocator) !ActionResult { + const item = item: { currentTab.currentItems.mutex.lock(); defer currentTab.currentItems.mutex.unlock(); - const currentItems = currentTab.currentItems.data orelse return ActionResult.None; - if (currentTab.currentItem) |*currentItem| { - const index = indexOf(Arc(*models.Item), models.FullName, currentItems.items, currentItem, arcFullNameEql); - if (index) |i| { - break :blk switch (step) { - .Next => i +| 1, - .Previous => i -| 1, - .NextPage => i +| 8, - .PreviousPage => i +| 8, - }; + const index = blk: { + if (currentTab.currentItem) |*currentItem| { + const index = indexOf(Arc(*models.Item), models.FullName, currentItems.items, currentItem, arcFullNameEql); + if (index) |i| { + break :blk switch (step) { + .Next => i +| 1, + .Previous => i -| 1, + .NextPage => i +| 8, + .PreviousPage => i +| 8, + }; + } } - } - break :blk 0; + break :blk 0; + }; + + const arc = currentItems.items[index]; + const arc_copy = arc.retain(); + defer if (arc_copy.releaseUnwrap()) |item| item.deinit(); + + break :item models.FullName{ + .path = try arena.dupe(u8, arc_copy.value.*.fullName.path), + }; }; - currentTab.selectItem(index) catch { + currentTab.selectItem(item) catch { //TODO }; return ActionResult.Handled; diff --git a/src/core/tab/tab.zig b/src/core/tab/tab.zig index dcb2eb9..f20a93f 100644 --- a/src/core/tab/tab.zig +++ b/src/core/tab/tab.zig @@ -4,6 +4,7 @@ pub const Tab = struct { currentItems: locked(?std.ArrayList(Arc(*Item))), currentLocationChanged: Observable(?*Container), currentItem: ?models.FullName, + currentRequestedItem: ?models.FullName, threadPool: *std.Thread.Pool, rootProvider: *RootProvider, @@ -18,6 +19,7 @@ pub const Tab = struct { .currentItems = .{ .data = null }, .currentLocationChanged = Observable(?*Container).init(allocator), .currentLocation = null, + .currentRequestedItem = null, .currentItem = null, .threadPool = threadPool, .rootProvider = rootProvider, @@ -52,31 +54,83 @@ pub const Tab = struct { }; self.currentLocationChanged.notify(newLocationContainer); - //TODO: Proper error handling - std.Thread.Pool.spawn(self.threadPool, loadItemsWrapper, .{ self, newLocationContainer }) catch unreachable; - - self.selectItem(0) catch { + self.updateCurrentItem() catch { self.currentItem = null; }; + + //TODO: Proper error handling + std.Thread.Pool.spawn(self.threadPool, loadItemsWrapper, .{ self, newLocationContainer }) catch unreachable; } - pub fn selectItem(self: *Tab, index: usize) !void { + pub fn selectItem(self: *Tab, requested_selected: models.FullName) !void { self.currentItems.mutex.lock(); defer self.currentItems.mutex.unlock(); - const currentItems = self.currentItems.data orelse return error.Error; - - if (index >= currentItems.items.len) { - return error.OutOfRange; - } - - if (self.currentItem) |currentItem| { - self.allocator.free(currentItem.path); - } - - self.currentItem = models.FullName{ - .path = try self.allocator.dupe(u8, currentItems.items[index].value.*.fullName.path), + self.currentRequestedItem = models.FullName{ + .path = try self.allocator.dupe(u8, requested_selected.path), }; + + return self.updateCurrentItem(); + } + + fn updateCurrentItem(self: *Tab) !void { + const currentRequestedItem = self.currentRequestedItem orelse return; + + // The requested is already selected + if (self.currentItem) |currentItem| { + if (std.mem.order(u8, currentRequestedItem.path, currentItem.path) == .eq) return; + } + + const currentItems = self.currentItems.data orelse return error.Error; + if (currentItems.items.len == 0) return error.Error; + + // Looking for the requested + const foundIndex = for (0..currentItems.items.len) |i| { + const arc_item = currentItems.items[i]; + const arc_copy = arc_item.retain(); + defer if (arc_copy.releaseUnwrap()) |item| item.deinit(); + + const comp = std.mem.order(u8, arc_copy.value.*.fullName.path, currentRequestedItem.path); + if (comp == .eq) { + break i; + } + if (comp == .lt) { + break i -| 1; + } + } else null; + + if (foundIndex) |i| { + const arc_item = currentItems.items[i]; + const arc_copy = arc_item.retain(); + defer if (arc_copy.releaseUnwrap()) |item| item.deinit(); + + self.setSelectedItemInner(models.FullName{ + .path = try self.allocator.dupe(u8, arc_copy.value.*.fullName.path), + }); + + return; + } + + //TODO: use lastdeepestselectedpath + + // Fallback to first item + { + const arc_item = currentItems.items[0]; + const arc_copy = arc_item.retain(); + defer if (arc_copy.releaseUnwrap()) |item| item.deinit(); + + self.setSelectedItemInner(models.FullName{ + .path = try self.allocator.dupe(u8, arc_copy.value.*.fullName.path), + }); + } + } + + fn setSelectedItemInner(self: *Tab, newSelectedItem: models.FullName) void { + if (self.currentItem) |current| { + self.allocator.free(current.path); + } + + self.currentItem = newSelectedItem; } fn loadItemsWrapper(self: *Tab, location: *Container) void { @@ -123,15 +177,18 @@ pub const Tab = struct { self.currentItems.mutex.lock(); defer self.currentItems.mutex.unlock(); - const index = for (self.currentItems.data.?.items, 0..) |item, i| { + const insertIndex = for (self.currentItems.data.?.items, 0..) |item, i| { if (compareByDisplayName(resolvedItem, item.value.*)) break i; } else null; + const arc = try Arc(*Item).init(self.allocator, resolvedItem); - if (index) |i| { + if (insertIndex) |i| { try self.currentItems.data.?.insert(i, arc); } else { try self.currentItems.data.?.append(arc); } + + self.updateCurrentItem() catch {}; } }