From 883ae257911effd02f706d4811d1e74868db4e28 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 8 May 2026 15:13:00 +0100 Subject: [PATCH] fix: resolve reminder indexes from show view --- CHANGELOG.md | 1 + Sources/RemindCore/IDResolver.swift | 8 +++++--- Sources/remindctl/CommandHelpers.swift | 5 +++++ Sources/remindctl/Commands/CompleteCommand.swift | 2 +- Sources/remindctl/Commands/DeleteCommand.swift | 2 +- Sources/remindctl/Commands/EditCommand.swift | 2 +- Tests/RemindCoreTests/IDResolverTests.swift | 7 +++++++ 7 files changed, 21 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56cda1a..88d7f77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## Unreleased +- Resolve numeric edit/complete/delete indexes against the default `show` view instead of unrelated completed reminders. - Add a release helper for Homebrew tap updates; thanks @dinakars777. ## 0.2.0 - 2026-05-04 diff --git a/Sources/RemindCore/IDResolver.swift b/Sources/RemindCore/IDResolver.swift index 47ec595..3d715ed 100644 --- a/Sources/RemindCore/IDResolver.swift +++ b/Sources/RemindCore/IDResolver.swift @@ -5,18 +5,20 @@ public enum IDResolver { public static func resolve( _ inputs: [String], - from reminders: [ReminderItem] + from reminders: [ReminderItem], + numericFrom numericReminders: [ReminderItem]? = nil ) throws -> [ReminderItem] { let sorted = ReminderFiltering.sort(reminders) + let numericSorted = ReminderFiltering.sort(numericReminders ?? reminders) var resolved: [ReminderItem] = [] for input in inputs { let trimmed = input.trimmingCharacters(in: .whitespacesAndNewlines) if let index = Int(trimmed) { let idx = index - 1 - guard idx >= 0 && idx < sorted.count else { + guard idx >= 0 && idx < numericSorted.count else { throw RemindCoreError.invalidIdentifier(trimmed) } - resolved.append(sorted[idx]) + resolved.append(numericSorted[idx]) continue } diff --git a/Sources/remindctl/CommandHelpers.swift b/Sources/remindctl/CommandHelpers.swift index c4ae394..70a64e4 100644 --- a/Sources/remindctl/CommandHelpers.swift +++ b/Sources/remindctl/CommandHelpers.swift @@ -42,6 +42,11 @@ enum CommandHelpers { } } + static func resolveShowIdentifiers(_ inputs: [String], from reminders: [ReminderItem]) throws -> [ReminderItem] { + let defaultShowReminders = ReminderFiltering.apply(reminders, filter: .today) + return try IDResolver.resolve(inputs, from: reminders, numericFrom: defaultShowReminders) + } + private static func parseCustomRecurrence(_ normalized: String, original: String) throws -> RecurrenceRule { let parts = normalized.split(separator: " ") guard parts.count == 3, parts[0] == "every", let interval = Int(parts[1]), interval > 0 else { diff --git a/Sources/remindctl/Commands/CompleteCommand.swift b/Sources/remindctl/Commands/CompleteCommand.swift index 36fd26a..5c8c7f3 100644 --- a/Sources/remindctl/Commands/CompleteCommand.swift +++ b/Sources/remindctl/Commands/CompleteCommand.swift @@ -32,7 +32,7 @@ enum CompleteCommand { let store = RemindersStore() try await store.requestAccess() let reminders = try await store.reminders(in: nil) - let resolved = try IDResolver.resolve(inputs, from: reminders) + let resolved = try CommandHelpers.resolveShowIdentifiers(inputs, from: reminders) if values.flag("dryRun") { OutputRenderer.printReminders(resolved, format: runtime.outputFormat) diff --git a/Sources/remindctl/Commands/DeleteCommand.swift b/Sources/remindctl/Commands/DeleteCommand.swift index c79f258..2c5ba24 100644 --- a/Sources/remindctl/Commands/DeleteCommand.swift +++ b/Sources/remindctl/Commands/DeleteCommand.swift @@ -33,7 +33,7 @@ enum DeleteCommand { let store = RemindersStore() try await store.requestAccess() let reminders = try await store.reminders(in: nil) - let resolved = try IDResolver.resolve(inputs, from: reminders) + let resolved = try CommandHelpers.resolveShowIdentifiers(inputs, from: reminders) if values.flag("dryRun") { OutputRenderer.printReminders(resolved, format: runtime.outputFormat) diff --git a/Sources/remindctl/Commands/EditCommand.swift b/Sources/remindctl/Commands/EditCommand.swift index a7a7992..02ece2e 100644 --- a/Sources/remindctl/Commands/EditCommand.swift +++ b/Sources/remindctl/Commands/EditCommand.swift @@ -57,7 +57,7 @@ enum EditCommand { let store = RemindersStore() try await store.requestAccess() let reminders = try await store.reminders(in: nil) - let resolved = try IDResolver.resolve([input], from: reminders) + let resolved = try CommandHelpers.resolveShowIdentifiers([input], from: reminders) guard let reminder = resolved.first else { throw RemindCoreError.reminderNotFound(input) } diff --git a/Tests/RemindCoreTests/IDResolverTests.swift b/Tests/RemindCoreTests/IDResolverTests.swift index bcb3910..0cefe8f 100644 --- a/Tests/RemindCoreTests/IDResolverTests.swift +++ b/Tests/RemindCoreTests/IDResolverTests.swift @@ -38,6 +38,13 @@ struct IDResolverTests { #expect(resolved.first?.title == "First") } + @Test("Resolve numeric indexes from filtered show output") + func resolveIndexFromFilteredShowOutput() throws { + let all = sampleReminders() + let resolved = try IDResolver.resolve(["1"], from: all, numericFrom: [all[1]]) + #expect(resolved.first?.title == "Second") + } + @Test("Resolve by prefix") func resolvePrefix() throws { let resolved = try IDResolver.resolve(["abcd"], from: sampleReminders())