eisenhower.go

  1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
  2//
  3// SPDX-License-Identifier: AGPL-3.0-or-later
  4
  5package lunatask
  6
  7import (
  8	"errors"
  9	"fmt"
 10	"strings"
 11)
 12
 13// Eisenhower represents a quadrant in the Eisenhower priority matrix, which
 14// categorizes tasks by whether they are urgent (time-sensitive) and/or
 15// important (valuable toward your goals).
 16//
 17// The four quadrants guide what action to take:
 18//
 19//	                  | Urgent        | Not Urgent
 20//	------------------|---------------|-------------
 21//	Important         | Do Now (1)    | Do Later (3)
 22//	Not Important     | Delegate (2)  | Eliminate (4)
 23//
 24// Use [NewEisenhower] to compute the quadrant from boolean flags, or the
 25// builder methods [TaskBuilder.Important] and [TaskBuilder.Urgent] for a
 26// fluent API.
 27type Eisenhower int
 28
 29// Eisenhower matrix quadrants. See [Eisenhower] for the full matrix.
 30const (
 31	EisenhowerUncategorized Eisenhower = 0 // not yet categorized
 32	EisenhowerDoNow         Eisenhower = 1 // urgent + important
 33	EisenhowerDelegate      Eisenhower = 2 // urgent, not important
 34	EisenhowerDoLater       Eisenhower = 3 // important, not urgent
 35	EisenhowerEliminate     Eisenhower = 4 // neither urgent nor important
 36)
 37
 38// NewEisenhower returns the quadrant for the given flags:
 39//
 40//	NewEisenhower(true, true)   // DoNow
 41//	NewEisenhower(true, false)  // DoLater
 42//	NewEisenhower(false, true)  // Delegate
 43//	NewEisenhower(false, false) // Eliminate
 44func NewEisenhower(important, urgent bool) Eisenhower {
 45	switch {
 46	case important && urgent:
 47		return EisenhowerDoNow
 48	case urgent:
 49		return EisenhowerDelegate
 50	case important:
 51		return EisenhowerDoLater
 52	default:
 53		return EisenhowerEliminate
 54	}
 55}
 56
 57// String returns a human-readable description of the Eisenhower quadrant.
 58func (e Eisenhower) String() string {
 59	switch e {
 60	case EisenhowerUncategorized:
 61		return "uncategorized"
 62	case EisenhowerDoNow:
 63		return "do now (important + urgent)"
 64	case EisenhowerDelegate:
 65		return "delegate (urgent)"
 66	case EisenhowerDoLater:
 67		return "do later (important)"
 68	case EisenhowerEliminate:
 69		return "eliminate"
 70	default:
 71		return fmt.Sprintf("Eisenhower(%d)", e)
 72	}
 73}
 74
 75// IsUrgent reports whether e is in an urgent quadrant ([EisenhowerDoNow] or [EisenhowerDelegate]).
 76func (e Eisenhower) IsUrgent() bool {
 77	return e == EisenhowerDoNow || e == EisenhowerDelegate
 78}
 79
 80// IsImportant reports whether e is in an important quadrant ([EisenhowerDoNow] or [EisenhowerDoLater]).
 81func (e Eisenhower) IsImportant() bool {
 82	return e == EisenhowerDoNow || e == EisenhowerDoLater
 83}
 84
 85// Errors returned by Eisenhower operations.
 86var (
 87	// ErrInvalidEisenhower is returned when parsing an unknown Eisenhower quadrant string.
 88	ErrInvalidEisenhower = errors.New("invalid eisenhower quadrant")
 89)
 90
 91// ParseEisenhower parses a string to an Eisenhower quadrant value (case-insensitive).
 92// Valid values: "uncategorized", "do-now", "delegate", "do-later", "eliminate",
 93// as well as numeric strings "0" through "4".
 94func ParseEisenhower(str string) (Eisenhower, error) {
 95	switch strings.ToLower(str) {
 96	case "uncategorized", "0":
 97		return EisenhowerUncategorized, nil
 98	case "do-now", "donow", "1":
 99		return EisenhowerDoNow, nil
100	case "delegate", "2":
101		return EisenhowerDelegate, nil
102	case "do-later", "dolater", "3":
103		return EisenhowerDoLater, nil
104	case "eliminate", "4":
105		return EisenhowerEliminate, nil
106	default:
107		return 0, fmt.Errorf("%w: %q", ErrInvalidEisenhower, str)
108	}
109}