|
| 1 | +local M = {} |
| 2 | +local config = require('opencode.config') |
| 3 | +local base_picker = require('opencode.ui.base_picker') |
| 4 | +local util = require('opencode.util') |
| 5 | +local history = require('opencode.history') |
| 6 | + |
| 7 | +---Format history entries for history picker |
| 8 | +---@param item table History item with text content |
| 9 | +---@param width number Picker width |
| 10 | +---@return PickerItem |
| 11 | +local function format_history_item(item, width) |
| 12 | + local entry = item.content or item.text or '' |
| 13 | + |
| 14 | + return base_picker.create_picker_item(entry:gsub('\n', '↵'), nil, 'ID: ' .. item.id, width) |
| 15 | +end |
| 16 | + |
| 17 | +function M.pick(callback) |
| 18 | + local history_entries = history.read() |
| 19 | + |
| 20 | + if #history_entries == 0 then |
| 21 | + vim.notify('No history entries found', vim.log.levels.INFO) |
| 22 | + return false |
| 23 | + end |
| 24 | + |
| 25 | + local history_items = {} |
| 26 | + for i, entry in ipairs(history_entries) do |
| 27 | + table.insert(history_items, { id = i, text = entry, content = entry }) |
| 28 | + end |
| 29 | + |
| 30 | + local actions = { |
| 31 | + delete = { |
| 32 | + key = config.keymap.history_picker.delete_entry, |
| 33 | + label = 'delete', |
| 34 | + multi_selection = true, |
| 35 | + fn = function(selected, opts) |
| 36 | + local entries_to_delete = type(selected) == 'table' and selected.id == nil and selected or { selected } |
| 37 | + |
| 38 | + local indices_to_remove = {} |
| 39 | + for _, entry_to_delete in ipairs(entries_to_delete) do |
| 40 | + local idx = util.find_index_of(opts.items, function(item) |
| 41 | + return item.id == entry_to_delete.id |
| 42 | + end) |
| 43 | + if idx > 0 then |
| 44 | + table.insert(indices_to_remove, idx) |
| 45 | + end |
| 46 | + end |
| 47 | + |
| 48 | + table.sort(indices_to_remove, function(a, b) |
| 49 | + return a > b |
| 50 | + end) |
| 51 | + |
| 52 | + local success = history.delete(indices_to_remove) |
| 53 | + if success then |
| 54 | + for _, idx in ipairs(indices_to_remove) do |
| 55 | + table.remove(opts.items, idx) |
| 56 | + end |
| 57 | + vim.notify('Deleted ' .. #entries_to_delete .. ' history entry(s)', vim.log.levels.INFO) |
| 58 | + else |
| 59 | + vim.notify('Failed to delete history entries', vim.log.levels.ERROR) |
| 60 | + end |
| 61 | + |
| 62 | + return opts.items |
| 63 | + end, |
| 64 | + reload = true, |
| 65 | + }, |
| 66 | + clear_all = { |
| 67 | + key = config.keymap.history_picker.clear_all, |
| 68 | + label = 'clear all', |
| 69 | + fn = function(_, opts) |
| 70 | + local success = history.clear() |
| 71 | + if success then |
| 72 | + opts.items = {} |
| 73 | + vim.notify('Cleared all history entries', vim.log.levels.INFO) |
| 74 | + else |
| 75 | + vim.notify('Failed to clear history entries', vim.log.levels.ERROR) |
| 76 | + end |
| 77 | + |
| 78 | + return opts.items |
| 79 | + end, |
| 80 | + reload = true, |
| 81 | + }, |
| 82 | + } |
| 83 | + |
| 84 | + return base_picker.pick({ |
| 85 | + items = history_items, |
| 86 | + format_fn = format_history_item, |
| 87 | + actions = actions, |
| 88 | + callback = function(selected_item) |
| 89 | + if selected_item and callback then |
| 90 | + callback(selected_item.content or selected_item.text) |
| 91 | + elseif selected_item then |
| 92 | + local input_window = require('opencode.ui.input_window') |
| 93 | + local state = require('opencode.state') |
| 94 | + local windows = state.windows |
| 95 | + if not input_window.mounted(windows) then |
| 96 | + require('opencode.core').open({ focus_input = true }) |
| 97 | + end |
| 98 | + ---@cast windows { input_win: integer, input_buf: integer } |
| 99 | + |
| 100 | + input_window.set_content(selected_item.content or selected_item.text) |
| 101 | + require('opencode.ui.mention').restore_mentions(windows.input_buf) |
| 102 | + input_window.focus_input() |
| 103 | + end |
| 104 | + end, |
| 105 | + title = 'Select History Entry', |
| 106 | + width = config.ui.picker_width or 100, |
| 107 | + }) |
| 108 | +end |
| 109 | + |
| 110 | +return M |
0 commit comments