Skip to content

Commit 4ccbf6a

Browse files
committed
feat(picker): keymap for starting a new session
1 parent 180e99d commit 4ccbf6a

File tree

2 files changed

+119
-15
lines changed

2 files changed

+119
-15
lines changed

lua/opencode/config.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ M.defaults = {
7171
},
7272
session_picker = {
7373
delete_session = { '<C-d>' },
74+
new_session = { '<C-n>' },
7475
},
7576
},
7677
ui = {

lua/opencode/ui/session_picker.lua

Lines changed: 118 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ local function format_session(session)
2121
return table.concat(parts, ' ~ ')
2222
end
2323

24-
local function telescope_ui(sessions, callback, on_delete)
24+
local function telescope_ui(sessions, callback, on_delete, on_new)
2525
local pickers = require('telescope.pickers')
2626
local finders = require('telescope.finders')
2727
local conf = require('telescope.config').values
@@ -99,14 +99,38 @@ local function telescope_ui(sessions, callback, on_delete)
9999
end
100100
end
101101

102+
-- Add new session mapping using shared callback
103+
local new_config = require('opencode.config').keymap.session_picker.new_session
104+
if new_config and new_config[1] then
105+
local key = new_config[1]
106+
local modes = new_config.mode or { 'i', 'n' }
107+
if type(modes) == 'string' then
108+
modes = { modes }
109+
end
110+
local new_fn = function()
111+
if on_new then
112+
local new_session = on_new()
113+
if new_session then
114+
actions.close(prompt_bufnr)
115+
if callback then
116+
callback(new_session)
117+
end
118+
end
119+
end
120+
end
121+
for _, mode in ipairs(modes) do
122+
map(mode, key, new_fn)
123+
end
124+
end
125+
102126
return true
103127
end,
104128
})
105129

106130
current_picker:find()
107131
end
108132

109-
local function fzf_ui(sessions, callback, on_delete)
133+
local function fzf_ui(sessions, callback, on_delete, on_new)
110134
local fzf_lua = require('fzf-lua')
111135
local config = require('opencode.config')
112136

@@ -143,6 +167,24 @@ local function fzf_ui(sessions, callback, on_delete)
143167
}
144168
end
145169

170+
-- New session action (shared on_new)
171+
local new_config = config.keymap.session_picker.new_session
172+
if new_config and new_config[1] then
173+
local key = require('fzf-lua.utils').neovim_bind_to_fzf(new_config[1])
174+
actions_config[key] = {
175+
fn = function()
176+
if on_new then
177+
local new_session = on_new()
178+
if new_session then
179+
table.insert(sessions, 1, new_session)
180+
end
181+
end
182+
end,
183+
header = 'new',
184+
reload = true,
185+
}
186+
end
187+
146188
fzf_lua.fzf_exec(function(fzf_cb)
147189
for _, session in ipairs(sessions) do
148190
fzf_cb(format_session(session))
@@ -165,7 +207,7 @@ local function fzf_ui(sessions, callback, on_delete)
165207
})
166208
end
167209

168-
local function mini_pick_ui(sessions, callback, on_delete)
210+
local function mini_pick_ui(sessions, callback, on_delete, on_new)
169211
local mini_pick = require('mini.pick')
170212
local config = require('opencode.config')
171213

@@ -202,6 +244,29 @@ local function mini_pick_ui(sessions, callback, on_delete)
202244
}
203245
end
204246

247+
-- New session mapping using shared on_new
248+
local new_config = config.keymap.session_picker.new_session
249+
if new_config and new_config[1] then
250+
mappings.new_session = {
251+
char = new_config[1],
252+
func = function()
253+
if on_new then
254+
local new_session = on_new()
255+
if new_session then
256+
table.insert(sessions, 1, new_session)
257+
items = vim.tbl_map(function(session)
258+
return {
259+
text = format_session(session),
260+
session = session,
261+
}
262+
end, sessions)
263+
mini_pick.set_picker_items(items)
264+
end
265+
end
266+
end,
267+
}
268+
end
269+
205270
mini_pick.start({
206271
source = {
207272
items = items,
@@ -217,7 +282,7 @@ local function mini_pick_ui(sessions, callback, on_delete)
217282
})
218283
end
219284

220-
local function snacks_picker_ui(sessions, callback, on_delete)
285+
local function snacks_picker_ui(sessions, callback, on_delete, on_new)
221286
local Snacks = require('snacks')
222287
local config = require('opencode.config')
223288

@@ -249,13 +314,9 @@ local function snacks_picker_ui(sessions, callback, on_delete)
249314
local key = delete_config[1]
250315
local mode = delete_config.mode or 'i'
251316

252-
opts.win = {
253-
input = {
254-
keys = {
255-
[key] = { 'session_delete', mode = mode },
256-
},
257-
},
258-
}
317+
opts.win = opts.win or {}
318+
opts.win.input = opts.win.input or { keys = {} }
319+
opts.win.input.keys[key] = { 'session_delete', mode = mode }
259320

260321
opts.actions.session_delete = function(picker, item)
261322
if item and on_delete then
@@ -271,6 +332,32 @@ local function snacks_picker_ui(sessions, callback, on_delete)
271332
end
272333
end
273334

335+
-- New session key using shared on_new
336+
local new_config = config.keymap.session_picker.new_session
337+
if new_config and new_config[1] then
338+
local key = new_config[1]
339+
local mode = new_config.mode or 'i'
340+
341+
opts.win = opts.win or {}
342+
opts.win.input = opts.win.input or { keys = {} }
343+
opts.win.input.keys[key] = { 'session_new', mode = mode }
344+
345+
opts.actions.session_new = function(picker)
346+
vim.schedule(function()
347+
if on_new then
348+
local new_session = on_new()
349+
if new_session then
350+
table.insert(sessions, 1, new_session)
351+
picker:close()
352+
if callback then
353+
callback(new_session)
354+
end
355+
end
356+
end
357+
end)
358+
end
359+
end
360+
274361
Snacks.picker.pick(opts)
275362
end
276363

@@ -298,15 +385,31 @@ function M.pick(sessions, callback)
298385
end)
299386
end
300387

388+
local function on_new()
389+
local parent_id
390+
for _, s in ipairs(sessions or {}) do
391+
if s.parentID ~= nil then
392+
parent_id = s.parentID
393+
break
394+
end
395+
end
396+
local state = require('opencode.state')
397+
local created = state.api_client:create_session(parent_id and { parentID = parent_id } or false):wait()
398+
if created and created.id then
399+
return require('opencode.session').get_by_id(created.id)
400+
end
401+
return nil
402+
end
403+
301404
vim.schedule(function()
302405
if picker_type == 'telescope' then
303-
telescope_ui(sessions, callback, on_delete)
406+
telescope_ui(sessions, callback, on_delete, on_new)
304407
elseif picker_type == 'fzf' then
305-
fzf_ui(sessions, callback, on_delete)
408+
fzf_ui(sessions, callback, on_delete, on_new)
306409
elseif picker_type == 'mini.pick' then
307-
mini_pick_ui(sessions, callback, on_delete)
410+
mini_pick_ui(sessions, callback, on_delete, on_new)
308411
elseif picker_type == 'snacks' then
309-
snacks_picker_ui(sessions, callback, on_delete)
412+
snacks_picker_ui(sessions, callback, on_delete, on_new)
310413
else
311414
callback(nil)
312415
end

0 commit comments

Comments
 (0)