Skip to content

Commit

Permalink
Add sorting reminders when showing (#57)
Browse files Browse the repository at this point in the history
  • Loading branch information
keith authored May 22, 2023
1 parent 06955a3 commit 2957e38
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 7 deletions.
13 changes: 12 additions & 1 deletion Sources/RemindersLibrary/CLI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,16 @@ private struct Show: ParsableCommand {
@Flag(help: "Include completed items in output")
var includeCompleted = false

@Option(
name: .shortAndLong,
help: "Show the reminders in a specific order, one of: \(Sort.commaSeparatedCases)")
var sort: Sort = .none

@Option(
name: [.customShort("o"), .long],
help: "How the sort order should be applied, one of: \(CustomSortOrder.commaSeparatedCases)")
var sortOrder: CustomSortOrder = .ascending

@Option(
name: .shortAndLong,
help: "Show only reminders due on this date")
Expand All @@ -76,7 +86,8 @@ private struct Show: ParsableCommand {
}

reminders.showListItems(
withName: self.listName, dueOn: self.dueDate, displayOptions: displayOptions, outputFormat: format)
withName: self.listName, dueOn: self.dueDate, displayOptions: displayOptions,
outputFormat: format, sort: sort, sortOrder: sortOrder)
}
}

Expand Down
17 changes: 11 additions & 6 deletions Sources/RemindersLibrary/Reminders.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ private extension EKReminder {
}
}

private func format(_ reminder: EKReminder, at index: Int, listName: String? = nil) -> String {
private func format(_ reminder: EKReminder, at index: Int?, listName: String? = nil) -> String {
let dateString = formattedDueDate(from: reminder).map { " (\($0))" } ?? ""
let priorityString = Priority(reminder.mappedPriority).map { " (priority: \($0))" } ?? ""
let listString = listName.map { "\($0): " } ?? ""
let notesString = reminder.notes.map { " (\($0))" } ?? ""
return "\(listString)\(index): \(reminder.title ?? "<unknown>")\(notesString)\(dateString)\(priorityString)"
let indexString = index.map { "\($0): " } ?? ""
return "\(listString)\(indexString)\(reminder.title ?? "<unknown>")\(notesString)\(dateString)\(priorityString)"
}

public enum OutputFormat: String, ExpressibleByArgument {
Expand Down Expand Up @@ -128,15 +129,19 @@ public final class Reminders {
semaphore.wait()
}

func showListItems(withName name: String, dueOn dueDate: DateComponents?, displayOptions: DisplayOptions, outputFormat: OutputFormat) {
func showListItems(withName name: String, dueOn dueDate: DateComponents?, displayOptions: DisplayOptions,
outputFormat: OutputFormat, sort: Sort, sortOrder: CustomSortOrder)
{
let semaphore = DispatchSemaphore(value: 0)
let calendar = Calendar.current

self.reminders(on: [self.calendar(withName: name)], displayOptions: displayOptions) { reminders in
var matchingReminders = [(EKReminder, Int)]()
var matchingReminders = [(EKReminder, Int?)]()
let reminders = sort == .none ? reminders : reminders.sorted(by: sort.sortFunction(order: sortOrder))
for (i, reminder) in reminders.enumerated() {
let index = sort == .none ? i : nil
guard let dueDate = dueDate?.date else {
matchingReminders.append((reminder, i))
matchingReminders.append((reminder, index))
continue
}

Expand All @@ -147,7 +152,7 @@ public final class Reminders {
let sameDay = calendar.compare(
reminderDueDate, to: dueDate, toGranularity: .day) == .orderedSame
if sameDay {
matchingReminders.append((reminder, i))
matchingReminders.append((reminder, index))
}
}

Expand Down
34 changes: 34 additions & 0 deletions Sources/RemindersLibrary/Sort.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import ArgumentParser
import EventKit

public enum Sort: String, Decodable, ExpressibleByArgument, CaseIterable {
case none
case creationDate = "creation-date"
case dueDate = "due-date"

public static let commaSeparatedCases = Self.allCases.map { $0.rawValue }.joined(separator: ", ")

func sortFunction(order: CustomSortOrder) -> (EKReminder, EKReminder) -> Bool {
let comparison: (Date, Date) -> Bool = order == .ascending ? (<) : (>)
switch self {
case .none: return { _, _ in fatalError() }
case .creationDate: return { comparison($0.creationDate!, $1.creationDate!) }
case .dueDate: return {
switch ($0.dueDateComponents, $1.dueDateComponents) {
case (.none, .none): return false
case (.none, .some): return false
case (.some, .none): return true
case (.some, .some): return comparison($0.dueDateComponents!.date!, $1.dueDateComponents!.date!)
}
}
}
}
}

// TODO: Replace with SortOrder when we drop < macOS 12.0
public enum CustomSortOrder: String, Decodable, ExpressibleByArgument, CaseIterable {
case ascending
case descending

public static let commaSeparatedCases = Self.allCases.map { $0.rawValue }.joined(separator: ", ")
}

0 comments on commit 2957e38

Please sign in to comment.