@@ -20,7 +20,11 @@ local M = {}
2020--- @type table<string , OpencodeQuickChatRunningSession>
2121local running_sessions = {}
2222
23- --- Creates an ephemeral session title
23+ --- Global keymaps that are active during quick chat sessions
24+ --- @type table<string , boolean>
25+ local active_global_keymaps = {}
26+
27+ --- Creates an quicklchat session title
2428--- @param buf integer Buffer handle
2529--- @return string title The session title
2630local function create_session_title (buf )
@@ -32,6 +36,69 @@ local function create_session_title(buf)
3236 return string.format (' [QuickChat] %s:%d (%s)' , relative_path , line_num , timestamp )
3337end
3438
39+ --- Removes global keymaps for quick chat
40+ local function teardown_global_keymaps ()
41+ if not next (active_global_keymaps ) then
42+ return
43+ end
44+
45+ for key , _ in pairs (active_global_keymaps ) do
46+ pcall (vim .keymap .del , { ' n' , ' i' }, key )
47+ end
48+
49+ active_global_keymaps = {}
50+ end
51+
52+ --- Cancels all running quick chat sessions
53+ local function cancel_all_quick_chat_sessions ()
54+ for session_id , session_info in pairs (running_sessions ) do
55+ if state .api_client then
56+ local ok , result = pcall (function ()
57+ return state .api_client :abort_session (session_id ):wait ()
58+ end )
59+
60+ if not ok then
61+ vim .notify (' Quick chat abort error: ' .. vim .inspect (result ), vim .log .levels .WARN )
62+ end
63+ end
64+
65+ if session_info and session_info .spinner then
66+ session_info .spinner :stop ()
67+ end
68+
69+ if config .values .debug .quick_chat and not config .values .debug .quick_chat .keep_session then
70+ state .api_client :delete_session (session_id ):catch (function (err )
71+ vim .notify (' Error deleting quicklchat session: ' .. vim .inspect (err ), vim .log .levels .WARN )
72+ end )
73+ end
74+
75+ running_sessions [session_id ] = nil
76+ end
77+
78+ -- Teardown keymaps once at the end
79+ teardown_global_keymaps ()
80+ vim .notify (' Quick chat cancelled by user' , vim .log .levels .WARN )
81+ end
82+
83+ --- Sets up global keymaps for quick chat
84+ local function setup_global_keymaps ()
85+ if next (active_global_keymaps ) then
86+ return
87+ end
88+
89+ local quick_chat_keymap = config .keymap .quick_chat or {}
90+ if quick_chat_keymap .cancel then
91+ vim .keymap .set (quick_chat_keymap .cancel .mode or { ' n' , ' i' }, quick_chat_keymap .cancel [1 ], function ()
92+ cancel_all_quick_chat_sessions ()
93+ end , {
94+ desc = quick_chat_keymap .cancel .desc or ' Cancel quick chat session' ,
95+ silent = true ,
96+ })
97+
98+ active_global_keymaps [quick_chat_keymap .cancel [1 ]] = true
99+ end
100+ end
101+
35102--- Helper to clean up session info and spinner
36103--- @param session_info table Session tracking info
37104--- @param session_id string Session ID
@@ -43,11 +110,17 @@ local function cleanup_session(session_info, session_id, message)
43110
44111 if config .debug .quick_chat and not config .debug .quick_chat .keep_session then
45112 state .api_client :delete_session (session_id ):catch (function (err )
46- vim .notify (' Error deleting ephemeral session: ' .. vim .inspect (err ), vim .log .levels .WARN )
113+ vim .notify (' Error deleting quicklchat session: ' .. vim .inspect (err ), vim .log .levels .WARN )
47114 end )
48115 end
49116
50117 running_sessions [session_id ] = nil
118+
119+ -- Check if there are no more running sessions and teardown global keymaps
120+ if not next (running_sessions ) then
121+ teardown_global_keymaps ()
122+ end
123+
51124 if message then
52125 vim .notify (message , vim .log .levels .WARN )
53126 end
@@ -67,7 +140,7 @@ local function extract_response_text(message)
67140 return vim .trim (response_text )
68141end
69142
70- --- Processes response from ephemeral session
143+ --- Processes response from quicklchat session
71144--- @param session_info table Session tracking info
72145--- @param messages OpencodeMessage[] Session messages
73146--- @return boolean success Whether the response was processed successfully
@@ -308,7 +381,7 @@ M.quick_chat = Promise.async(function(message, options, range)
308381 local quick_chat_session = core .create_new_session (title ):await ()
309382 if not quick_chat_session then
310383 spinner :stop ()
311- return Promise .new ():reject (' Failed to create ephemeral session' )
384+ return Promise .new ():reject (' Failed to create quicklchat session' )
312385 end
313386
314387 if config .debug .quick_chat and config .debug .quick_chat .set_active_session then
@@ -323,6 +396,9 @@ M.quick_chat = Promise.async(function(message, options, range)
323396 timestamp = vim .uv .now (),
324397 }
325398
399+ -- Set up global keymaps for quick chat
400+ setup_global_keymaps ()
401+
326402 local context_config = vim .tbl_deep_extend (' force' , create_context_config (range ~= nil ), options .context_config or {})
327403 local context_instance = context .new_instance (context_config )
328404 local params = create_message (message , buf , range , context_instance , options ):await ()
@@ -371,6 +447,7 @@ function M.setup()
371447 end
372448 end
373449 running_sessions = {}
450+ teardown_global_keymaps ()
374451 end ,
375452 })
376453end
0 commit comments