Skip to content

Commit a4635d8

Browse files
authored
Merge pull request #33 from AuroBreeze/dev
Dev
2 parents 26bbd94 + 81c1cff commit a4635d8

File tree

3 files changed

+98
-56
lines changed

3 files changed

+98
-56
lines changed

Release.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,31 @@
11
# Quick-c Release Notes
22

3+
## v1.5.15 (2025-12-04)
4+
5+
### 新增
6+
- cqM 目标记忆:每个 cwd 记住“上一次选择的目标”,再次打开列表会在顶部显示快捷项:`[Last target: <name>]`,可一键执行。
7+
8+
### 改进
9+
- cqM 选择器默认以“正常模式”打开(`initial_mode = 'normal'`),无需先退出插入模式。
10+
11+
### 修复
12+
- 终端已打开但未聚焦时,编辑页触发 cqM 发送命令会“切换/关闭”终端窗口的问题:
13+
- 不再在发送前强制 `open`,避免 betterTerm 的 toggle 行为。
14+
- 发送成功后按策略聚焦:优先聚焦已有终端窗口;无窗口时再兜底 `betterTerm.open`
15+
- 聚焦策略优先遵循 `betterterm.focus_on_run`;未启用 betterTerm 时回退到“无内置终端时才聚焦”。
16+
- `select_or_run_in_terminal` 的默认分支移除多余的 `open` 调用并稳定回退路径,避免潜在的循环加载与焦点抖动。
17+
18+
### 验证建议
19+
1) 打开一个终端窗口但保持未聚焦,在代码缓冲执行 `<leader>cqM` 选择目标:终端不应被关闭,若 `focus_on_run = true` 则会聚焦;为 `false` 不抢焦点。
20+
2) 连续两次选择同一目录下的某个目标,第二次列表顶部应出现 `[Last target: <name>]`,选择即可直接执行;当 `make.args.prompt = true` 时仍会弹出参数输入框。
21+
3) cqM 打开后处于正常模式,可直接使用 j/k、<CR> 操作。
22+
23+
### 兼容性
24+
- 无破坏性变更;默认行为与配置说明一致。
25+
26+
### 迁移指南
27+
- 无需迁移;如需跨会话持久化“上次目标”,后续将提供可选方案。
28+
329
## v1.5.14 (2025-11-27)
430

531
### 修复

lua/quick-c/telescope.lua

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ local M = {}
22
local U = require 'quick-c.util'
33
local T = require 'quick-c.terminal'
44
local LAST_ARGS = {}
5+
local LAST_TARGET = {}
56

67
-- Enhanced quickfix Telescope: show detailed error preview on the right
78
function M.telescope_quickfix(config)
@@ -289,6 +290,7 @@ function M.telescope_make(
289290
pickers
290291
.new({}, {
291292
prompt_title = 'Make Targets (' .. cwd .. ')',
293+
initial_mode = 'normal',
292294
finder = finders.new_table {
293295
results = { { display = '[No Make targets found]', kind = 'empty' } },
294296
entry_maker = function(e)
@@ -320,6 +322,11 @@ function M.telescope_make(
320322
local function build_entries()
321323
local entries = {}
322324
table.insert(entries, { display = '[Custom args...]', kind = 'args' })
325+
-- prepend last target quick entry if available for this cwd
326+
local last = LAST_TARGET[cwd]
327+
if type(last) == 'string' and last ~= '' then
328+
table.insert(entries, { display = string.format('[Last target: %s]', last), kind = 'last', value = last })
329+
end
323330
local list = {}
324331
if mktargets.prioritize_phony ~= false then
325332
local a, b = {}, {}
@@ -356,6 +363,7 @@ function M.telescope_make(
356363
pickers
357364
.new({}, {
358365
prompt_title = title .. ' (' .. cwd .. ')',
366+
initial_mode = 'normal',
359367
finder = finders.new_table {
360368
results = entries,
361369
entry_maker = function(e)
@@ -531,6 +539,10 @@ function M.telescope_make(
531539
end
532540
local ui = vim.ui or {}
533541
if not ui.input then
542+
-- remember last selected explicit target
543+
if type(target) == 'string' and target ~= '' then
544+
LAST_TARGET[cwd] = target
545+
end
534546
make_run_in_cwd(target, cwd)
535547
return
536548
end
@@ -551,8 +563,14 @@ function M.telescope_make(
551563
else
552564
cmd = string.format('%s -C %s %s %s', prog, shell_quote_path(cwd), target or '', arg)
553565
end
566+
if type(target) == 'string' and target ~= '' then
567+
LAST_TARGET[cwd] = target
568+
end
554569
run_make_in_terminal(cmd)
555570
else
571+
if type(target) == 'string' and target ~= '' then
572+
LAST_TARGET[cwd] = target
573+
end
556574
make_run_in_cwd(target, cwd)
557575
end
558576
end)
@@ -596,10 +614,22 @@ function M.telescope_make(
596614
run_make_in_terminal(cmd)
597615
end)
598616
return
617+
elseif entry.kind == 'last' then
618+
local target = entry.value
619+
if mkargs.prompt ~= false then
620+
run_with_args(target)
621+
else
622+
LAST_TARGET[cwd] = target
623+
make_run_in_cwd(target, cwd)
624+
end
625+
return
599626
end
600627
if mkargs.prompt ~= false then
601628
run_with_args(entry.value)
602629
else
630+
if type(entry.value) == 'string' and entry.value ~= '' then
631+
LAST_TARGET[cwd] = entry.value
632+
end
603633
make_run_in_cwd(entry.value, cwd)
604634
end
605635
end

lua/quick-c/terminal.lua

Lines changed: 42 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -42,19 +42,8 @@ function T.run_in_betterterm(config, is_windows, cmd, notify_warn, notify_err, o
4242
local want_focus = (focus == true) and (opts.focus ~= false)
4343
local prev = vim.api.nvim_get_current_win()
4444
local prev_mode = (vim.api.nvim_get_mode and vim.api.nvim_get_mode().mode) or 'n'
45-
-- Open terminal if requested by config (open_if_closed) or when focusing is desired.
46-
-- Even when we don't want to steal focus, we still open the terminal to ensure the session exists,
47-
-- then immediately restore previous window to avoid key leakage and focus steal.
48-
if (open_first or focus) then
49-
pcall(betterTerm.open, idx)
50-
end
51-
if not want_focus then
52-
-- Restore immediately to avoid stealing focus
53-
pcall(vim.api.nvim_set_current_win, prev)
54-
if prev_mode:sub(1, 1) == 'n' then
55-
pcall(vim.cmd, 'stopinsert')
56-
end
57-
end
45+
-- Do not pre-open to avoid toggle-closing an already visible terminal window.
46+
-- We will try to send first; if it fails, we may open; if focusing is desired, we'll try to focus an existing window.
5847
vim.defer_fn(function()
5948
local ok_send, err = pcall(betterTerm.send, cmd .. (is_windows() and '\r' or '\n'), idx)
6049
if not ok_send then
@@ -64,8 +53,34 @@ function T.run_in_betterterm(config, is_windows, cmd, notify_warn, notify_err, o
6453
end
6554
return
6655
end
67-
-- Some versions of betterTerm may re-focus after open/send; if we don't want focus, restore again after send
68-
if not want_focus then
56+
-- Focus behavior after successful send
57+
if want_focus then
58+
-- Prefer focusing an existing terminal window to avoid toggle-close behavior
59+
local terms = T.list_open_builtin_terminals()
60+
if terms and #terms > 0 then
61+
local last = terms[#terms]
62+
pcall(vim.api.nvim_set_current_win, prev) -- ensure we have valid window context
63+
vim.defer_fn(function()
64+
pcall(function()
65+
-- try to focus existing terminal window displaying this buffer
66+
for _, win in ipairs(vim.api.nvim_list_wins()) do
67+
if vim.api.nvim_win_is_valid(win) and vim.api.nvim_win_get_buf(win) == last.bufnr then
68+
pcall(vim.api.nvim_set_current_win, win)
69+
return
70+
end
71+
end
72+
-- not found: as a fallback, open via betterTerm (may create or bring to front)
73+
pcall(betterTerm.open, idx)
74+
end)
75+
end, 60)
76+
else
77+
-- No terminal windows: open one now to show output
78+
vim.defer_fn(function()
79+
pcall(betterTerm.open, idx)
80+
end, 60)
81+
end
82+
else
83+
-- If not focusing, restore previous window to avoid stealing focus
6984
vim.defer_fn(function()
7085
pcall(vim.api.nvim_set_current_win, prev)
7186
if prev_mode:sub(1, 1) == 'n' then
@@ -78,9 +93,14 @@ function T.run_in_betterterm(config, is_windows, cmd, notify_warn, notify_err, o
7893
end
7994

8095
function T.run_make_in_terminal(config, is_windows, cmdline, notify_warn, notify_err)
81-
-- Auto-focus terminal when none is currently open; otherwise do not steal focus.
96+
-- Decide focus policy:
97+
-- - If betterTerm is enabled and focus_on_run ~= false, prefer focusing (honor user config).
98+
-- - Otherwise fallback to legacy behavior: focus only when no builtin terminal is open.
8299
local open_terms = T.list_open_builtin_terminals()
83-
local want_focus = (#open_terms == 0)
100+
local bt_cfg = config.betterterm or {}
101+
local prefer_bt = (bt_cfg.enabled ~= false)
102+
local cfg_focus = (bt_cfg.focus_on_run ~= false)
103+
local want_focus = (prefer_bt and cfg_focus) or (#open_terms == 0)
84104
if not T.run_in_betterterm(config, is_windows, cmdline, notify_warn, notify_err, { focus = want_focus }) then
85105
if not T.run_in_native_terminal(config, is_windows, cmdline, { focus = want_focus }) then
86106
notify_err 'Unable to run make: cannot open terminal'
@@ -170,52 +190,18 @@ function T.select_or_run_in_terminal(config, is_windows, cmdline, notify_warn, n
170190
actions.close(bufnr)
171191
local v = entry.value
172192
if v.kind == 'default' then
193+
-- Use unified focusing/selection policy inside run_make_in_terminal
173194
T.run_make_in_terminal(config, is_windows, cmdline, notify_warn, notify_err)
174-
do
175-
local ok_bt, betterTerm = pcall(require, 'betterTerm')
176-
if ok_bt and (config.betterterm and config.betterterm.enabled ~= false) then
177-
local idx = (config.betterterm and config.betterterm.index) or 0
178-
local focus_on_run = (config.betterterm and config.betterterm.focus_on_run) ~= false
179-
if focus_on_run then
180-
vim.defer_fn(function()
181-
pcall(betterTerm.open, idx)
182-
end, 120)
183-
end
184-
else
185-
-- Focus a builtin terminal window after sending, to honor explicit user choice
186-
vim.defer_fn(function()
187-
local terms = T.list_open_builtin_terminals()
188-
if terms and #terms > 0 then
189-
-- pick the last one (most recently opened)
190-
local last = terms[#terms]
191-
pcall(open_builtin_terminal_window, config, last.bufnr)
192-
end
193-
end, 120)
194-
end
195-
end
196195
else
197196
local ok = T.send_to_builtin_terminal(is_windows, v.job, cmdline, { bufnr = v.bufnr, config = config })
198197
if not ok then
199198
notify_warn 'Failed to send to selected terminal, using default strategy'
200199
T.run_make_in_terminal(config, is_windows, cmdline, notify_warn, notify_err)
201-
do
202-
local ok_bt, betterTerm = pcall(require, 'betterTerm')
203-
if ok_bt and (config.betterterm and config.betterterm.enabled ~= false) then
204-
local idx = (config.betterterm and config.betterterm.index) or 0
205-
local focus_on_run = (config.betterterm and config.betterterm.focus_on_run) ~= false
206-
if focus_on_run then
207-
vim.defer_fn(function()
208-
pcall(betterTerm.open, idx)
209-
end, 120)
210-
end
211-
end
212-
end
213-
end
214-
if ok then
215-
vim.defer_fn(function()
216-
pcall(open_builtin_terminal_window, config, v.bufnr)
217-
end, 120)
200+
return
218201
end
202+
vim.defer_fn(function()
203+
pcall(open_builtin_terminal_window, config, v.bufnr)
204+
end, 120)
219205
end
220206
end
221207
map('i', '<CR>', choose)

0 commit comments

Comments
 (0)