patto 0.2.0

🐙 Yet another plain text format for quick note taking and task management
# Using Trouble.nvim Sorter Option - Update Summary

## Overview

Refactored the deadline-based sorting implementation to use trouble.nvim's built-in `sorters` configuration option instead of manually adding sort keys to items.

## Key Changes

### Before (Manual Sort Keys)
```lua
-- In M.get()
items[#items + 1] = Item.new({
  -- ... other fields
  deadline_group = deadline_group,
  deadline_sort = sort_key,  -- Manual sort key stored in item
})

-- In mode config
sort = { "deadline_sort", "filename", "pos" },
```

### After (Using Trouble.nvim Sorters)
```lua
-- In M.config
M.config = {
  sorters = {
    deadline = function(item)
      -- Sorter function that computes sort key on-demand
      local _, sort_key = parse_deadline(item.item or {})
      return sort_key
    end,
  },
  modes = {
    patto_tasks_deadline = {
      sort = { "deadline", "filename", "pos" },  -- Reference sorter by name
      -- ...
    },
  },
}

-- In M.get()
items[#items + 1] = Item.new({
  -- ... other fields
  deadline_group = deadline_group,  -- Only need category, not sort key
})
```

## Benefits

1. **Cleaner Item Creation**: Don't need to store `deadline_sort` in every item
2. **Follows Trouble.nvim Convention**: Uses the built-in sorter system as intended
3. **On-Demand Computation**: Sort keys computed when needed, not stored
4. **More Maintainable**: Sorting logic is centralized in `M.config.sorters`

## How Trouble.nvim Sorters Work

From `trouble.nvim/lua/trouble/sort.lua`:

```lua
M.sorters = {
  pos = function(obj)
    return obj.pos[1] * 1000000 + obj.pos[2] * 1000
  end,
}

function M.sort(items, opts, ctx)
  -- For each sort field
  local sorter = ctx.opts.sorters[field.field] or M.sorters[field.field]
  if sorter then
    key = sorter(item)  -- Call sorter function to get key
  end
  -- Sort items by keys
end
```

### Sorter Function Signature
```lua
---@alias trouble.SorterFn fun(item: trouble.Item): any
```

- Takes a `trouble.Item` as input
- Returns any comparable value (number, string, boolean)
- Used during sorting to determine item order

## Implementation Details

### Custom Sorter Definition

```lua
M.config = {
  sorters = {
    deadline = function(item)
      -- Access the original task data from LSP
      local task = item.item or {}
      
      -- Compute sort key (timestamp)
      local _, sort_key = parse_deadline(task)
      
      -- Return numeric timestamp for chronological sorting
      -- Lower values sort first (earlier deadlines first)
      return sort_key
    end,
  },
}
```

### Sort Key Values

| Category | Sort Key Value |
|----------|----------------|
| Overdue (2024-11-10) | Actual timestamp (e.g., 1731196800) |
| Today | Actual timestamp (e.g., 1731369600) |
| Tomorrow | Actual timestamp (e.g., 1731456000) |
| This Week | Actual timestamp |
| This Month | Actual timestamp |
| Later | Actual timestamp |
| No Deadline | 9999999999 (sorts last) |
| Uninterpretable | 9999999998 (sorts second-to-last) |
| Invalid | 9999999997 (sorts third-to-last) |

### Multi-Level Sorting

```lua
sort = { "deadline", "filename", "pos" }
```

Trouble.nvim sorts by:
1. **deadline** (earliest first) - via custom sorter
2. **filename** (alphabetically) - via built-in field access
3. **pos** (position in file) - via built-in `pos` sorter

## Code Comparison

### Removed Lines
```lua
-- No longer needed in M.get()
local deadline_group, sort_key = parse_deadline(task)
items[#items + 1] = Item.new({
  deadline_sort = sort_key,  // REMOVED
})
```

### Changed Lines
```lua
-- parse_deadline still returns both values, but we only use category in M.get()
local deadline_group, _ = parse_deadline(task)  // Only use category

// In mode config
- sort = { "deadline_sort", "filename", "pos" },
+ sort = { "deadline", "filename", "pos" },
```

## Testing

Syntax validation passed:
```bash
nvim --headless -c "luafile lua/trouble/sources/patto_tasks.lua" -c "lua print('✓')" -c "q"
# ✓ patto_tasks source loads successfully
```

## References

- Trouble.nvim sorter implementation: `trouble.nvim/lua/trouble/sort.lua`
- Diagnostics source example: `trouble.nvim/lua/trouble/sources/diagnostics.lua`
- Config type definitions: `trouble.nvim/lua/trouble/config/init.lua`

## Summary

The refactoring makes the code:
- ✅ More idiomatic (follows trouble.nvim patterns)
- ✅ Cleaner (removes redundant data from items)
- ✅ More efficient (computes sort keys on-demand)
- ✅ Better documented (clear sorter function)
- ✅ Easier to maintain (centralized sorting logic)

No functional changes to the user-facing behavior - tasks still sort by deadline as before!