11local T = {}
22
3- function T .run_in_native_terminal (config , is_windows , cmd )
3+ function T .run_in_native_terminal (config , is_windows , cmd , opts )
4+ opts = opts or {}
5+ local focus = (opts .focus ~= false )
6+ local prev = vim .api .nvim_get_current_win ()
47 if config .terminal .open then
58 vim .cmd ' botright split | terminal'
69 vim .cmd (string.format (' resize %d' , config .terminal .height or 12 ))
@@ -11,13 +14,16 @@ function T.run_in_native_terminal(config, is_windows, cmd)
1114 if not chan then
1215 return false
1316 end
17+ if not focus then
18+ pcall (vim .api .nvim_set_current_win , prev )
19+ end
1420 vim .defer_fn (function ()
1521 vim .fn .chansend (chan , cmd .. (is_windows () and ' \r ' or ' \n ' ))
1622 end , 100 )
1723 return true
1824end
1925
20- function T .run_in_betterterm (config , is_windows , cmd , notify_warn , notify_err )
26+ function T .run_in_betterterm (config , is_windows , cmd , notify_warn , notify_err , opts )
2127 local ok , betterTerm = pcall (require , ' betterTerm' )
2228 if not ok or config .betterterm .enabled == false then
2329 return false
@@ -27,14 +33,20 @@ function T.run_in_betterterm(config, is_windows, cmd, notify_warn, notify_err)
2733 local delay = cfg .send_delay or 200
2834 local focus = (cfg .focus_on_run ~= false )
2935 local open_first = (cfg .open_if_closed ~= false )
36+ opts = opts or {}
37+ local want_focus = (opts .focus ~= false )
38+ local prev = vim .api .nvim_get_current_win ()
3039 if open_first or focus then
3140 pcall (betterTerm .open , idx )
3241 end
42+ if not want_focus then
43+ pcall (vim .api .nvim_set_current_win , prev )
44+ end
3345 vim .defer_fn (function ()
3446 local ok_send , err = pcall (betterTerm .send , cmd .. (is_windows () and ' \r ' or ' \n ' ), idx )
3547 if not ok_send then
3648 notify_warn (' Failed to send to betterTerm, using native terminal: ' .. tostring (err ))
37- if not T .run_in_native_terminal (config , is_windows , cmd ) then
49+ if not T .run_in_native_terminal (config , is_windows , cmd , { focus = want_focus } ) then
3850 notify_err ' Failed to open native terminal'
3951 end
4052 return
@@ -44,8 +56,8 @@ function T.run_in_betterterm(config, is_windows, cmd, notify_warn, notify_err)
4456end
4557
4658function T .run_make_in_terminal (config , is_windows , cmdline , notify_warn , notify_err )
47- if not T .run_in_betterterm (config , is_windows , cmdline , notify_warn , notify_err ) then
48- if not T .run_in_native_terminal (config , is_windows , cmdline ) then
59+ if not T .run_in_betterterm (config , is_windows , cmdline , notify_warn , notify_err , { focus = false } ) then
60+ if not T .run_in_native_terminal (config , is_windows , cmdline , { focus = false } ) then
4961 notify_err ' Unable to run make: cannot open terminal'
5062 end
5163 end
8698
8799function T .send_to_builtin_terminal (is_windows , job , cmd , opts )
88100 opts = opts or {}
89- if opts .bufnr and vim .api .nvim_buf_is_valid (opts .bufnr ) then
90- pcall (open_builtin_terminal_window , opts .config or {}, opts .bufnr )
91- end
92101 local nl = is_windows () and ' \r ' or ' \n '
93102 return pcall (vim .fn .chansend , job , cmd .. nl )
94103end
@@ -98,7 +107,9 @@ function T.select_or_run_in_terminal(config, is_windows, cmdline, notify_warn, n
98107 local mode = ((config .make or {}).telescope or {}).choose_terminal or ' auto'
99108 local open_terms = T .list_open_builtin_terminals ()
100109 local ok_t = pcall (require , ' telescope' )
101- if mode == ' never' or not ok_t or (mode == ' auto' and # open_terms == 0 ) then
110+ -- Only open picker when explicitly requested (always) or when there are 2+ terminals.
111+ -- In auto mode with 0 or 1 terminals, run default strategy directly to avoid key leakage.
112+ if mode == ' never' or not ok_t or (mode == ' auto' and # open_terms <= 1 ) then
102113 return T .run_make_in_terminal (config , is_windows , cmdline , notify_warn , notify_err )
103114 end
104115 local pickers = require ' telescope.pickers'
@@ -111,39 +122,76 @@ function T.select_or_run_in_terminal(config, is_windows, cmdline, notify_warn, n
111122 local disp = string.format (' buf #%d | %s' , it .bufnr , (it .name ~= ' ' and it .name or ' terminal' ))
112123 table.insert (entries , { display = disp , kind = ' builtin' , job = it .job , bufnr = it .bufnr })
113124 end
114- pickers
115- . new ({}, {
116- prompt_title = ' quick-c: select terminal to send ' ,
117- finder = finders . new_table {
118- results = entries ,
119- entry_maker = function ( e )
120- return { value = e , display = e . display , ordinal = e . display }
121- end ,
122- },
123- sorter = conf . generic_sorter {} ,
124- attach_mappings = function ( _ , map )
125- local actions = require ' telescope.actions '
126- local action_state = require ' telescope.actions.state '
127- local function choose ( bufnr )
128- local entry = action_state . get_selected_entry ()
129- actions . close ( bufnr )
130- local v = entry . value
131- if v . kind == ' default ' then
132- T . run_make_in_terminal ( config , is_windows , cmdline , notify_warn , notify_err )
133- else
134- local ok = T . send_to_builtin_terminal ( is_windows , v . job , cmdline , { bufnr = v . bufnr , config = config } )
135- if not ok then
136- notify_warn ' Failed to send to selected terminal, using default strategy '
125+ vim . defer_fn ( function ()
126+ pickers
127+ . new ({}, {
128+ prompt_title = ' quick-c: select terminal to send ' ,
129+ initial_mode = ' normal ' ,
130+ finder = finders . new_table {
131+ results = entries ,
132+ entry_maker = function ( e )
133+ return { value = e , display = e . display , ordinal = e . display }
134+ end ,
135+ },
136+ sorter = conf . generic_sorter {},
137+ attach_mappings = function ( _ , map )
138+ local actions = require ' telescope.actions '
139+ local action_state = require ' telescope.actions.state '
140+ local function swallow_A ( )
141+ return true
142+ end
143+ local function choose ( bufnr )
144+ local entry = action_state . get_selected_entry ()
145+ actions . close ( bufnr )
146+ local v = entry . value
147+ if v . kind == ' default' then
137148 T .run_make_in_terminal (config , is_windows , cmdline , notify_warn , notify_err )
149+ do
150+ local ok_bt , betterTerm = pcall (require , ' betterTerm' )
151+ if ok_bt and (config .betterterm and config .betterterm .enabled ~= false ) then
152+ local idx = (config .betterterm and config .betterterm .index ) or 0
153+ local focus_on_run = (config .betterterm and config .betterterm .focus_on_run ) ~= false
154+ if focus_on_run then
155+ vim .defer_fn (function ()
156+ pcall (betterTerm .open , idx )
157+ end , 120 )
158+ end
159+ end
160+ end
161+ else
162+ local ok = T .send_to_builtin_terminal (is_windows , v .job , cmdline , { bufnr = v .bufnr , config = config })
163+ if not ok then
164+ notify_warn ' Failed to send to selected terminal, using default strategy'
165+ T .run_make_in_terminal (config , is_windows , cmdline , notify_warn , notify_err )
166+ do
167+ local ok_bt , betterTerm = pcall (require , ' betterTerm' )
168+ if ok_bt and (config .betterterm and config .betterterm .enabled ~= false ) then
169+ local idx = (config .betterterm and config .betterterm .index ) or 0
170+ local focus_on_run = (config .betterterm and config .betterterm .focus_on_run ) ~= false
171+ if focus_on_run then
172+ vim .defer_fn (function ()
173+ pcall (betterTerm .open , idx )
174+ end , 120 )
175+ end
176+ end
177+ end
178+ end
179+ if ok then
180+ vim .defer_fn (function ()
181+ pcall (open_builtin_terminal_window , config , v .bufnr )
182+ end , 120 )
183+ end
138184 end
139185 end
140- end
141- map (' i' , ' <CR>' , choose )
142- map (' n' , ' <CR>' , choose )
143- return true
144- end ,
145- })
146- :find ()
186+ map (' i' , ' <CR>' , choose )
187+ map (' n' , ' <CR>' , choose )
188+ map (' n' , ' A' , swallow_A )
189+ map (' i' , ' A' , swallow_A )
190+ return true
191+ end ,
192+ })
193+ :find ()
194+ end , 120 )
147195end
148196
149197return T
0 commit comments