Skip to content

Commit 6c3ff1d

Browse files
authored
Merge pull request #30 from AuroBreeze/dev
Dev
2 parents 83afcc9 + 8756356 commit 6c3ff1d

File tree

8 files changed

+451
-17
lines changed

8 files changed

+451
-17
lines changed

Release.md

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

3+
## v1.5.12 (2025-11-06)
4+
5+
### 改进
6+
- Quickfix 可读性:所有诊断项自动加上分类前缀(`[error]`/`[warning]`),避免一眼看不出严重级别。
7+
- 长消息展示:
8+
- 优先使用增强版 Telescope Quickfix 视图(右侧预览默认软换行)。
9+
- 回退到 `:copen` 时,为 quickfix 窗口启用 `wrap/linebreak/breakindent`,长行不再被遮挡。
10+
11+
### 新增
12+
- 自定义编译命令(可选启用):
13+
- 新增 `compile.user_cmd`,可通过预设或追加参数自定义编译命令。
14+
- 保留默认行为:未启用或未弹窗时,仍使用内置命令构建。
15+
- Telescope 选择器(可选):
16+
-`compile.user_cmd.telescope.popup = true` 时,构建前弹出选择:
17+
- `[Use built-in]` 使用内置命令
18+
- `[Custom args…]` 在内置命令后追加参数(可记忆上次输入)
19+
- 预设项(presets) 使用完整模板命令(支持占位符)
20+
21+
### 配置示例
22+
```lua
23+
require('quick-c').setup({
24+
compile = {
25+
user_cmd = {
26+
enabled = true,
27+
telescope = { popup = true },
28+
-- 作为 [Custom args…] 输入框默认值(无历史时)
29+
default = { "-O2", "-DNDEBUG" }, -- 或 "-O2 -DNDEBUG"
30+
remember_last = true, -- 记住每项目最近一次输入
31+
-- 完整替换命令(argv 数组,避免 shell 解析问题)
32+
-- 支持占位符:{sources} {out} {cc} {ft}
33+
presets = {
34+
{ "{cc}", "-g", "-O0", "-Wall", "-Wextra", "{sources}", "-o", "{out}" },
35+
{ "{cc}", "-O2", "{sources}", "-o", "{out}" },
36+
},
37+
},
38+
},
39+
})
40+
```
41+
42+
### 行为
43+
- 未启用或未弹窗:编译行为与旧版完全一致。
44+
- 启用+弹窗:
45+
-`[Custom args…]` 时,默认值优先“上次输入”,否则使用 `default`
46+
- 选预设时,用完整模板命令替换内置命令。
47+
48+
### 兼容性
49+
- 无破坏性变更;旧配置无需修改即可继续使用。
50+
351
## v1.5.11 (2025-11-04)
452

553
### 修复

lua/quick-c/build.lua

Lines changed: 206 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ local TASK = require 'quick-c.task'
44
local B = {}
55
local NAME_CACHE = {}
66
local LAST_EXE = {}
7+
local LAST_COMPILE_ARGS = {}
8+
79
local function cleanup_build_logs(base, max_keep)
810
local uv = vim.loop
911
local ok, req = pcall(uv.fs_scandir, base)
@@ -312,6 +314,7 @@ local function build_cmd(config, is_win, ft, sources, out)
312314
if not family then
313315
return nil
314316
end
317+
315318
if family == 'cl' then
316319
local args = { 'cl', '/Zi', '/Od' }
317320
for _, s in ipairs(sources) do
@@ -388,6 +391,176 @@ function B.get_output_name_async(config, sources, preset_name, cb, default_overr
388391
end
389392
end
390393

394+
-- Expand a template list with placeholders into argv list
395+
-- tmpl: array, elements may contain placeholders {sources} {out} {cc} {ft}
396+
local function expand_template_argv(tmpl, vars)
397+
local out = {}
398+
for _, part in ipairs(tmpl or {}) do
399+
if part == '{sources}' then
400+
for _, s in ipairs(vars.sources or {}) do table.insert(out, s) end
401+
elseif part == '{out}' then
402+
table.insert(out, vars.out)
403+
elseif part == '{cc}' then
404+
table.insert(out, vars.cc)
405+
elseif part == '{ft}' then
406+
table.insert(out, vars.ft)
407+
else
408+
local replaced = part
409+
replaced = replaced:gsub('%%{sources%%}', '{sources}')
410+
replaced = replaced:gsub('%%{out%%}', '{out}')
411+
replaced = replaced:gsub('%%{cc%%}', '{cc}')
412+
replaced = replaced:gsub('%%{ft%%}', '{ft}')
413+
replaced = replaced:gsub('{out}', vars.out)
414+
replaced = replaced:gsub('{cc}', vars.cc)
415+
replaced = replaced:gsub('{ft}', vars.ft)
416+
if replaced ~= '{sources}' then
417+
table.insert(out, replaced)
418+
else
419+
for _, s in ipairs(vars.sources or {}) do table.insert(out, s) end
420+
end
421+
end
422+
end
423+
return out
424+
end
425+
426+
local function clone_list(t)
427+
local o = {}
428+
for _, v in ipairs(t or {}) do table.insert(o, v) end
429+
return o
430+
end
431+
432+
local function project_key()
433+
local root = vim.fn.getcwd()
434+
return require('quick-c.util').norm(root)
435+
end
436+
437+
-- Let user optionally customize compile command via Telescope/ui
438+
-- cb(argv_or_nil): when nil, use built-in cmd
439+
local function choose_user_compile_cmd_async(config, is_win, ft, sources, exe, builtin_cmd, cb)
440+
local cc_name = (choose_compiler(config, is_win, ft))
441+
local cc = cc_name
442+
local ucfg = (config.compile and config.compile.user_cmd) or {}
443+
if not ucfg.enabled then
444+
cb(nil)
445+
return
446+
end
447+
local tel = (ucfg.telescope or {})
448+
if tel.popup ~= true then
449+
cb(nil)
450+
return
451+
end
452+
local presets = ucfg.presets or {}
453+
local entries = {}
454+
table.insert(entries, { display = '[Use built-in]', kind = 'builtin' })
455+
table.insert(entries, { display = '[Custom args...]', kind = 'args' })
456+
for idx, p in ipairs(presets) do
457+
local disp
458+
if type(p) == 'table' then
459+
disp = table.concat(p, ' ')
460+
else
461+
disp = tostring(p)
462+
end
463+
table.insert(entries, { display = disp, kind = 'preset', value = p, idx = idx })
464+
end
465+
local function finalize(choice)
466+
if not choice then
467+
cb(nil)
468+
return
469+
end
470+
if choice.kind == 'builtin' then
471+
cb(clone_list(builtin_cmd))
472+
return
473+
end
474+
if choice.kind == 'preset' then
475+
local tmpl = choice.value
476+
if type(tmpl) ~= 'table' then
477+
-- string template unsupported for robust argv; fall back to builtin
478+
cb(clone_list(builtin_cmd))
479+
return
480+
end
481+
local argv = expand_template_argv(tmpl, { sources = sources, out = exe, cc = cc or '', ft = ft })
482+
cb(argv)
483+
return
484+
end
485+
if choice.kind == 'args' then
486+
local key = project_key()
487+
local def_cfg = ucfg.default
488+
local def_from_cfg = ''
489+
if type(def_cfg) == 'table' then
490+
def_from_cfg = table.concat(def_cfg, ' ')
491+
elseif type(def_cfg) == 'string' then
492+
def_from_cfg = def_cfg
493+
end
494+
local def = ''
495+
if ucfg.remember_last ~= false then
496+
def = (LAST_COMPILE_ARGS[key] and LAST_COMPILE_ARGS[key] ~= '' and LAST_COMPILE_ARGS[key]) or def_from_cfg or ''
497+
else
498+
def = def_from_cfg or ''
499+
end
500+
local ui = vim.ui or {}
501+
if not ui.input then
502+
cb(clone_list(builtin_cmd))
503+
return
504+
end
505+
ui.input({ prompt = 'extra compile args: ', default = def }, function(arg)
506+
if ucfg.remember_last ~= false then LAST_COMPILE_ARGS[key] = arg or '' end
507+
if not arg or arg == '' then
508+
cb(clone_list(builtin_cmd))
509+
return
510+
end
511+
local argv = clone_list(builtin_cmd)
512+
for a in string.gmatch(arg, "[^%s]+") do table.insert(argv, a) end
513+
cb(argv)
514+
end)
515+
return
516+
end
517+
cb(nil)
518+
end
519+
local ok_t = pcall(require, 'telescope')
520+
if ok_t then
521+
local pickers = require 'telescope.pickers'
522+
local finders = require 'telescope.finders'
523+
local conf = require('telescope.config').values
524+
pickers
525+
.new({}, {
526+
prompt_title = tel.prompt_title or 'Quick-c Compile',
527+
finder = finders.new_table {
528+
results = entries,
529+
entry_maker = function(e)
530+
return { value = e, display = e.display, ordinal = e.display, kind = e.kind }
531+
end,
532+
},
533+
sorter = conf.generic_sorter {},
534+
attach_mappings = function(bufnr, map)
535+
local actions = require 'telescope.actions'
536+
local action_state = require 'telescope.actions.state'
537+
local function choose(pbuf)
538+
local entry = action_state.get_selected_entry()
539+
actions.close(pbuf)
540+
finalize(entry and entry.value or nil)
541+
end
542+
map('i', '<CR>', choose)
543+
map('n', '<CR>', choose)
544+
return true
545+
end,
546+
})
547+
:find()
548+
return
549+
end
550+
local ui = vim.ui or {}
551+
if ui.select then
552+
local items = {}
553+
for _, e in ipairs(entries) do table.insert(items, e.display) end
554+
ui.select(items, { prompt = tel.prompt_title or 'Quick-c Compile' }, function(sel)
555+
if not sel then finalize(nil) return end
556+
for _, e in ipairs(entries) do if e.display == sel then finalize(e) return end end
557+
finalize(nil)
558+
end)
559+
return
560+
end
561+
cb(nil)
562+
end
563+
391564
function B.build(config, notify, opts)
392565
opts = opts or {}
393566
local timeout_ms = (config.build and config.build.timeout_ms) or 0
@@ -422,16 +595,18 @@ function B.build(config, notify, opts)
422595
end
423596
local is_win = U.is_windows()
424597
local exe = resolve_out_path(config, sources, name)
425-
local cmd = build_cmd(config, is_win, ft, sources, exe)
426-
if not cmd then
598+
local builtin_cmd = build_cmd(config, is_win, ft, sources, exe)
599+
if not builtin_cmd then
427600
notify.err 'No available compiler found. Check PATH or set compile.prefer in setup()'
428601
if opts.on_exit then pcall(opts.on_exit, 1, nil) end
429602
done(1)
430603
return
431604
end
432-
local cmdline = table.concat(cmd, ' ')
433-
local all_stdout, all_stderr = {}, {}
434-
job_id = vim.fn.jobstart(cmd, {
605+
choose_user_compile_cmd_async(config, is_win, ft, sources, exe, builtin_cmd, function(user_argv)
606+
local cmd = user_argv or builtin_cmd
607+
local cmdline = table.concat(cmd, ' ')
608+
local all_stdout, all_stderr = {}, {}
609+
job_id = vim.fn.jobstart(cmd, {
435610
stdout_buffered = true,
436611
stderr_buffered = true,
437612
detach = false,
@@ -480,10 +655,28 @@ function B.build(config, notify, opts)
480655
end
481656
if should_open() then
482657
if diagcfg.use_telescope then
483-
local ok_tb, tb = pcall(require, 'telescope.builtin')
484-
if ok_tb then tb.quickfix() else vim.cmd 'copen' end
658+
local ok_qc, qct = pcall(require, 'quick-c.telescope')
659+
if ok_qc and qct and qct.telescope_quickfix then
660+
pcall(qct.telescope_quickfix, config)
661+
else
662+
local ok_tb, tb = pcall(require, 'telescope.builtin')
663+
if ok_tb and tb and tb.quickfix then
664+
pcall(tb.quickfix)
665+
else
666+
pcall(vim.cmd, 'copen')
667+
end
668+
end
485669
else
486-
vim.cmd 'copen'
670+
pcall(vim.cmd, 'copen')
671+
end
672+
if not (pcall(require, 'telescope')) then
673+
local info = vim.fn.getqflist({ winid = 1 }) or {}
674+
local wid = info.winid or 0
675+
if wid ~= 0 then
676+
pcall(vim.api.nvim_win_set_option, wid, 'wrap', true)
677+
pcall(vim.api.nvim_win_set_option, wid, 'linebreak', true)
678+
pcall(vim.api.nvim_win_set_option, wid, 'breakindent', true)
679+
end
487680
end
488681
end
489682
if should_jump() then
@@ -519,10 +712,11 @@ function B.build(config, notify, opts)
519712
done(code)
520713
end,
521714
})
522-
if (job_id or 0) <= 0 then
523-
notify.err 'Failed to start build process'
524-
done(1)
525-
end
715+
if (job_id or 0) <= 0 then
716+
notify.err 'Failed to start build process'
717+
done(1)
718+
end
719+
end)
526720
end, default_override)
527721
end,
528722
}

lua/quick-c/cmake.lua

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -453,14 +453,28 @@ function M.build_in_root(config, root, target, run_terminal)
453453
end
454454
if should_open() then
455455
if diagcfg.use_telescope then
456-
local ok_tb, tb = pcall(require, 'telescope.builtin')
457-
if ok_tb then
458-
tb.quickfix()
456+
local ok_qc, qct = pcall(require, 'quick-c.telescope')
457+
if ok_qc and qct and qct.telescope_quickfix then
458+
pcall(qct.telescope_quickfix, config)
459459
else
460-
vim.cmd 'copen'
460+
local ok_tb, tb = pcall(require, 'telescope.builtin')
461+
if ok_tb and tb and tb.quickfix then
462+
pcall(tb.quickfix)
463+
else
464+
pcall(vim.cmd, 'copen')
465+
end
461466
end
462467
else
463-
vim.cmd 'copen'
468+
pcall(vim.cmd, 'copen')
469+
end
470+
if not (pcall(require, 'telescope')) then
471+
local info = vim.fn.getqflist({ winid = 1 }) or {}
472+
local wid = info.winid or 0
473+
if wid ~= 0 then
474+
pcall(vim.api.nvim_win_set_option, wid, 'wrap', true)
475+
pcall(vim.api.nvim_win_set_option, wid, 'linebreak', true)
476+
pcall(vim.api.nvim_win_set_option, wid, 'breakindent', true)
477+
end
464478
end
465479
end
466480
if should_jump() then

lua/quick-c/config.lua

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,26 @@ C.defaults = {
2121
compile = {
2222
prefer = { c = nil, cpp = nil },
2323
prefer_force = false,
24+
-- 用户自定义编译命令:可通过模板或预设完全覆盖内置命令
25+
-- 当 enabled = true 时,构建流程会优先询问/选择自定义命令;未选择时回退到内置命令
26+
user_cmd = {
27+
enabled = true,
28+
-- 是否使用 Telescope 弹窗选择:包含 [Use built-in]、[Custom input...] 以及 presets
29+
telescope = {
30+
popup = false, -- 参考 make 的交互,默认不弹;开启后若未安装 telescope 将自动回退到 vim.ui
31+
prompt_title = 'Quick-c Compile',
32+
},
33+
-- 预设命令(推荐使用列表形式以避免 shell 解析问题):
34+
-- 必须使用完整的编译命令,这不是追加参数
35+
-- 允许占位符:{sources} {out} {cc} {ft}
36+
-- 例如:{ 'gcc', '-g', '-O0', '{sources}', '-o', '{out}' }
37+
presets = {},
38+
-- 自定义输入的默认模板(字符串或数组)。
39+
-- 这是弹窗后的追加命令
40+
default = nil,
41+
-- 记住每个项目最近一次输入(用于下次默认值)
42+
remember_last = true,
43+
},
2444
},
2545
-- compile_commands.json 相关配置
2646
compile_commands = {

0 commit comments

Comments
 (0)