mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-02-14 08:27:59 +08:00
feat(flygrep.nvim): support preview win
This commit is contained in:
parent
4269519d60
commit
ec46d40ee0
@ -5,7 +5,7 @@
|
|||||||
[![](https://spacevim.org/img/build-with-SpaceVim.svg)](https://spacevim.org)
|
[![](https://spacevim.org/img/build-with-SpaceVim.svg)](https://spacevim.org)
|
||||||
[![GPLv3 License](https://img.spacevim.org/license-GPLv3-blue.svg)](LICENSE)
|
[![GPLv3 License](https://img.spacevim.org/license-GPLv3-blue.svg)](LICENSE)
|
||||||
|
|
||||||
![Image](https://github.com/user-attachments/assets/49638d4c-4828-4d46-9c24-165102ef61a7)
|
![flygrep.nvim](https://img.spacevim.org/flygrep.nvim.gif)
|
||||||
|
|
||||||
<!-- vim-markdown-toc GFM -->
|
<!-- vim-markdown-toc GFM -->
|
||||||
|
|
||||||
@ -23,7 +23,6 @@
|
|||||||
|
|
||||||
`flygrep.nvim` is a neovim plugin that can be used to search code asynchronously in real time.
|
`flygrep.nvim` is a neovim plugin that can be used to search code asynchronously in real time.
|
||||||
|
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
- [neovim](https://github.com/neovim/neovim): >= v0.10.0
|
- [neovim](https://github.com/neovim/neovim): >= v0.10.0
|
||||||
@ -82,6 +81,7 @@ require('flygrep').setup({
|
|||||||
hidden_opt = { '--hidden' },
|
hidden_opt = { '--hidden' },
|
||||||
},
|
},
|
||||||
matched_higroup = 'IncSearch',
|
matched_higroup = 'IncSearch',
|
||||||
|
enable_preview = false,
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -95,6 +95,7 @@ require('flygrep').setup({
|
|||||||
| `<C-s>` | open item in split window |
|
| `<C-s>` | open item in split window |
|
||||||
| `<C-v>` | open item in vertical split window |
|
| `<C-v>` | open item in vertical split window |
|
||||||
| `<C-t>` | open item in new tabpage |
|
| `<C-t>` | open item in new tabpage |
|
||||||
|
| `<C-p>` | toggle preview window |
|
||||||
|
|
||||||
## Feedback
|
## Feedback
|
||||||
|
|
||||||
|
@ -1,3 +1,11 @@
|
|||||||
|
--=============================================================================
|
||||||
|
-- flygrep.lua
|
||||||
|
-- Copyright 2025 Eric Wong
|
||||||
|
-- Author: Eric Wong < wsdjeg@outlook.com >
|
||||||
|
-- URL: https://spacevim.org
|
||||||
|
-- License: GPLv3
|
||||||
|
--=============================================================================
|
||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
local conf = require('flygrep.config')
|
local conf = require('flygrep.config')
|
||||||
local job = require('spacevim.api.job')
|
local job = require('spacevim.api.job')
|
||||||
@ -18,6 +26,9 @@ local result_bufid = -1
|
|||||||
local result_winid = -1
|
local result_winid = -1
|
||||||
local prompt_bufid = -1
|
local prompt_bufid = -1
|
||||||
local prompt_winid = -1
|
local prompt_winid = -1
|
||||||
|
local preview_winid = -1
|
||||||
|
local preview_bufid = -1
|
||||||
|
local preview_timer_id = -1
|
||||||
|
|
||||||
local prompt_count_id
|
local prompt_count_id
|
||||||
local extns = vim.api.nvim_create_namespace('floatgrep_ext')
|
local extns = vim.api.nvim_create_namespace('floatgrep_ext')
|
||||||
@ -37,12 +48,57 @@ local function build_grep_command()
|
|||||||
for _, v in ipairs(conf.command.default_opts) do
|
for _, v in ipairs(conf.command.default_opts) do
|
||||||
table.insert(cmd, v)
|
table.insert(cmd, v)
|
||||||
end
|
end
|
||||||
if fix_string then table.insert(cmd, conf.command.fixed_string_opt) else table.insert(cmd, conf.command.expr_opt) end
|
if fix_string then
|
||||||
|
table.insert(cmd, conf.command.fixed_string_opt)
|
||||||
|
else
|
||||||
|
table.insert(cmd, conf.command.expr_opt)
|
||||||
|
end
|
||||||
table.insert(cmd, grep_input)
|
table.insert(cmd, grep_input)
|
||||||
table.insert(cmd, '.')
|
table.insert(cmd, '.')
|
||||||
return cmd
|
return cmd
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- 搜索结果行转换成文件名、光标位置
|
||||||
|
local function get_file_pos(line)
|
||||||
|
local filename = vim.fn.fnameescape(vim.fn.split(line, [[:\d\+:]])[1])
|
||||||
|
local linenr = vim.fn.str2nr(string.sub(vim.fn.matchstr(line, [[:\d\+:]]), 2, -2))
|
||||||
|
local colum = vim.fn.str2nr(string.sub(vim.fn.matchstr(line, [[\(:\d\+\)\@<=:\d\+:]]), 2, -2))
|
||||||
|
return filename, linenr, colum
|
||||||
|
end
|
||||||
|
local function preview_timer(t)
|
||||||
|
-- if preview win does exists, return
|
||||||
|
if not vim.api.nvim_win_is_valid(preview_winid) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local cursor = vim.api.nvim_win_get_cursor(result_winid)
|
||||||
|
local line = vim.api.nvim_buf_get_lines(result_bufid, cursor[1] - 1, cursor[1], false)[1]
|
||||||
|
if line == '' then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local filename, liner, colum = get_file_pos(line)
|
||||||
|
vim.api.nvim_buf_set_lines(preview_bufid, 0, -1, false, vim.fn.readfile(filename, ''))
|
||||||
|
local ft = vim.filetype.match({ filename = filename })
|
||||||
|
if ft then
|
||||||
|
vim.api.nvim_buf_set_option(preview_bufid, 'syntax', ft)
|
||||||
|
else
|
||||||
|
local ftdetect_autocmd = vim.api.nvim_get_autocmds({
|
||||||
|
group = 'filetypedetect',
|
||||||
|
event = 'BufRead',
|
||||||
|
pattern = '*.' .. vim.fn.fnamemodify(filename, ':e'),
|
||||||
|
})
|
||||||
|
-- logger.info(vim.inspect(ftdetect_autocmd))
|
||||||
|
if ftdetect_autocmd[1] then
|
||||||
|
if
|
||||||
|
ftdetect_autocmd[1].command and vim.startswith(ftdetect_autocmd[1].command, 'set filetype=')
|
||||||
|
then
|
||||||
|
ft = ftdetect_autocmd[1].command:gsub('set filetype=', '')
|
||||||
|
vim.api.nvim_buf_set_option(preview_bufid, 'syntax', ft)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
vim.api.nvim_win_set_cursor(preview_winid, { liner, colum })
|
||||||
|
end
|
||||||
|
|
||||||
local function grep_timer(t)
|
local function grep_timer(t)
|
||||||
vim.api.nvim_buf_set_lines(result_bufid, 0, -1, false, {})
|
vim.api.nvim_buf_set_lines(result_bufid, 0, -1, false, {})
|
||||||
if prompt_count_id then
|
if prompt_count_id then
|
||||||
@ -51,9 +107,17 @@ local function grep_timer(t)
|
|||||||
end
|
end
|
||||||
search_jobid = job.start(build_grep_command(), {
|
search_jobid = job.start(build_grep_command(), {
|
||||||
on_stdout = function(id, data)
|
on_stdout = function(id, data)
|
||||||
if id == search_jobid and vim.api.nvim_buf_is_valid(prompt_bufid) and vim.api.nvim_win_is_valid(prompt_winid) then
|
if
|
||||||
|
id == search_jobid
|
||||||
|
and vim.api.nvim_buf_is_valid(prompt_bufid)
|
||||||
|
and vim.api.nvim_win_is_valid(prompt_winid)
|
||||||
|
then
|
||||||
if vim.fn.getbufline(result_bufid, 1)[1] == '' then
|
if vim.fn.getbufline(result_bufid, 1)[1] == '' then
|
||||||
vim.api.nvim_buf_set_lines(result_bufid, 0, -1, false, data)
|
vim.api.nvim_buf_set_lines(result_bufid, 0, -1, false, data)
|
||||||
|
if conf.enable_preview then
|
||||||
|
vim.fn.timer_stop(preview_timer_id)
|
||||||
|
preview_timer_id = vim.fn.timer_start(500, preview_timer, { ['repeat'] = 1 })
|
||||||
|
end
|
||||||
else
|
else
|
||||||
vim.api.nvim_buf_set_lines(result_bufid, -1, -1, false, data)
|
vim.api.nvim_buf_set_lines(result_bufid, -1, -1, false, data)
|
||||||
end
|
end
|
||||||
@ -87,6 +151,43 @@ local function toggle_fix_string()
|
|||||||
vim.api.nvim_win_set_config(prompt_winid, conf)
|
vim.api.nvim_win_set_config(prompt_winid, conf)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function toggle_preview_win()
|
||||||
|
conf.enable_preview = not conf.enable_preview
|
||||||
|
local screen_width = math.floor(vim.o.columns * 0.8)
|
||||||
|
-- 起始位位置: lines * 10%, columns * 10%
|
||||||
|
local start_col = math.floor(vim.o.columns * 0.1)
|
||||||
|
local start_row = math.floor(vim.o.lines * 0.1)
|
||||||
|
-- 整体高度:lines 的 80%
|
||||||
|
local screen_height = math.floor(vim.o.lines * 0.8)
|
||||||
|
if conf.enable_preview then
|
||||||
|
if not vim.api.nvim_buf_is_valid(preview_bufid) then
|
||||||
|
preview_bufid = vim.api.nvim_create_buf(false, true)
|
||||||
|
end
|
||||||
|
preview_winid = vim.api.nvim_open_win(preview_bufid, false, {
|
||||||
|
relative = 'editor',
|
||||||
|
width = screen_width,
|
||||||
|
height = math.floor((screen_height - 5) / 2),
|
||||||
|
col = start_col,
|
||||||
|
row = start_row,
|
||||||
|
focusable = false,
|
||||||
|
border = 'rounded',
|
||||||
|
-- title = 'Result',
|
||||||
|
-- title_pos = 'center',
|
||||||
|
-- noautocmd = true,
|
||||||
|
})
|
||||||
|
local winopt = vim.api.nvim_win_get_config(result_winid)
|
||||||
|
winopt.row = start_row + math.floor((screen_height - 5) / 2) + 2
|
||||||
|
winopt.height = screen_height - 5 - math.floor((screen_height - 5) / 2) - 2
|
||||||
|
vim.api.nvim_win_set_config(result_winid, winopt)
|
||||||
|
else
|
||||||
|
vim.api.nvim_win_close(preview_winid, true)
|
||||||
|
local winopt = vim.api.nvim_win_get_config(result_winid)
|
||||||
|
winopt.row = start_row
|
||||||
|
winopt.height = screen_height - 5
|
||||||
|
vim.api.nvim_win_set_config(result_winid, winopt)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local function open_win()
|
local function open_win()
|
||||||
require('flygrep.highlight').def_higroup()
|
require('flygrep.highlight').def_higroup()
|
||||||
-- 窗口位置
|
-- 窗口位置
|
||||||
@ -126,6 +227,36 @@ local function open_win()
|
|||||||
sign_hl_group = 'Error',
|
sign_hl_group = 'Error',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if conf.enable_preview then
|
||||||
|
if not vim.api.nvim_buf_is_valid(preview_bufid) then
|
||||||
|
preview_bufid = vim.api.nvim_create_buf(false, true)
|
||||||
|
end
|
||||||
|
preview_winid = vim.api.nvim_open_win(preview_bufid, false, {
|
||||||
|
relative = 'editor',
|
||||||
|
width = screen_width,
|
||||||
|
height = math.floor((screen_height - 5) / 2),
|
||||||
|
col = start_col,
|
||||||
|
row = start_row,
|
||||||
|
focusable = false,
|
||||||
|
border = 'rounded',
|
||||||
|
-- title = 'Result',
|
||||||
|
-- title_pos = 'center',
|
||||||
|
-- noautocmd = true,
|
||||||
|
})
|
||||||
|
result_bufid = vim.api.nvim_create_buf(false, true)
|
||||||
|
result_winid = vim.api.nvim_open_win(result_bufid, false, {
|
||||||
|
relative = 'editor',
|
||||||
|
width = screen_width,
|
||||||
|
height = screen_height - 5 - math.floor((screen_height - 5) / 2) - 2,
|
||||||
|
col = start_col,
|
||||||
|
row = start_row + math.floor((screen_height - 5) / 2) + 2,
|
||||||
|
focusable = false,
|
||||||
|
border = 'rounded',
|
||||||
|
-- title = 'Result',
|
||||||
|
-- title_pos = 'center',
|
||||||
|
-- noautocmd = true,
|
||||||
|
})
|
||||||
|
else
|
||||||
result_bufid = vim.api.nvim_create_buf(false, true)
|
result_bufid = vim.api.nvim_create_buf(false, true)
|
||||||
result_winid = vim.api.nvim_open_win(result_bufid, false, {
|
result_winid = vim.api.nvim_open_win(result_bufid, false, {
|
||||||
relative = 'editor',
|
relative = 'editor',
|
||||||
@ -139,6 +270,7 @@ local function open_win()
|
|||||||
-- title_pos = 'center',
|
-- title_pos = 'center',
|
||||||
-- noautocmd = true,
|
-- noautocmd = true,
|
||||||
})
|
})
|
||||||
|
end
|
||||||
vim.api.nvim_set_option_value(
|
vim.api.nvim_set_option_value(
|
||||||
'winhighlight',
|
'winhighlight',
|
||||||
'NormalFloat:Normal,FloatBorder:WinSeparator',
|
'NormalFloat:Normal,FloatBorder:WinSeparator',
|
||||||
@ -164,7 +296,8 @@ local function open_win()
|
|||||||
if grep_input ~= '' then
|
if grep_input ~= '' then
|
||||||
pcall(vim.fn.matchdelete, search_hi_id, result_winid)
|
pcall(vim.fn.matchdelete, search_hi_id, result_winid)
|
||||||
pcall(vim.fn.timer_stop, grep_timer_id)
|
pcall(vim.fn.timer_stop, grep_timer_id)
|
||||||
search_hi_id = vim.fn.matchadd(conf.matched_higroup, grep_input, 10, -1, { window = result_winid })
|
search_hi_id =
|
||||||
|
vim.fn.matchadd(conf.matched_higroup, grep_input, 10, -1, { window = result_winid })
|
||||||
grep_timer_id = vim.fn.timer_start(conf.timeout, grep_timer, { ['repeat'] = 1 })
|
grep_timer_id = vim.fn.timer_start(conf.timeout, grep_timer, { ['repeat'] = 1 })
|
||||||
else
|
else
|
||||||
pcall(vim.fn.matchdelete, search_hi_id, result_winid)
|
pcall(vim.fn.matchdelete, search_hi_id, result_winid)
|
||||||
@ -181,17 +314,16 @@ local function open_win()
|
|||||||
vim.keymap.set('i', k, function()
|
vim.keymap.set('i', k, function()
|
||||||
vim.cmd('noautocmd stopinsert')
|
vim.cmd('noautocmd stopinsert')
|
||||||
vim.api.nvim_win_close(prompt_winid, true)
|
vim.api.nvim_win_close(prompt_winid, true)
|
||||||
|
vim.api.nvim_buf_set_lines(prompt_bufid, 0, -1, false, {})
|
||||||
vim.api.nvim_win_close(result_winid, true)
|
vim.api.nvim_win_close(result_winid, true)
|
||||||
|
vim.api.nvim_buf_set_lines(result_bufid, 0, -1, false, {})
|
||||||
|
if conf.enable_preview then
|
||||||
|
vim.api.nvim_win_close(preview_winid, true)
|
||||||
|
vim.api.nvim_buf_set_lines(preview_bufid, 0, -1, false, {})
|
||||||
|
end
|
||||||
end, { buffer = prompt_bufid })
|
end, { buffer = prompt_bufid })
|
||||||
end
|
end
|
||||||
|
|
||||||
-- 搜索结果行转换成文件名、光标位置
|
|
||||||
local function get_file_pos(line)
|
|
||||||
local filename = vim.fn.fnameescape(vim.fn.split(line, [[:\d\+:]])[1])
|
|
||||||
local linenr = vim.fn.str2nr(string.sub(vim.fn.matchstr(line, [[:\d\+:]]), 2, -2))
|
|
||||||
local colum = vim.fn.str2nr(string.sub(vim.fn.matchstr(line, [[\(:\d\+\)\@<=:\d\+:]]), 2, -2))
|
|
||||||
return filename, linenr, colum
|
|
||||||
end
|
|
||||||
-- 使用回车键打开光标所在的搜索结果,同时关闭界面
|
-- 使用回车键打开光标所在的搜索结果,同时关闭界面
|
||||||
local function open_item(cmd)
|
local function open_item(cmd)
|
||||||
vim.cmd('noautocmd stopinsert')
|
vim.cmd('noautocmd stopinsert')
|
||||||
@ -200,7 +332,13 @@ local function open_win()
|
|||||||
local filename, linenr, colum =
|
local filename, linenr, colum =
|
||||||
get_file_pos(vim.api.nvim_buf_get_lines(result_bufid, line_number - 1, line_number, false)[1])
|
get_file_pos(vim.api.nvim_buf_get_lines(result_bufid, line_number - 1, line_number, false)[1])
|
||||||
vim.api.nvim_win_close(prompt_winid, true)
|
vim.api.nvim_win_close(prompt_winid, true)
|
||||||
|
vim.api.nvim_buf_set_lines(prompt_bufid, 0, -1, false, {})
|
||||||
vim.api.nvim_win_close(result_winid, true)
|
vim.api.nvim_win_close(result_winid, true)
|
||||||
|
vim.api.nvim_buf_set_lines(result_bufid, 0, -1, false, {})
|
||||||
|
if conf.enable_preview then
|
||||||
|
vim.api.nvim_win_close(preview_winid, true)
|
||||||
|
vim.api.nvim_buf_set_lines(preview_bufid, 0, -1, false, {})
|
||||||
|
end
|
||||||
vim.cmd(cmd .. ' ' .. filename)
|
vim.cmd(cmd .. ' ' .. filename)
|
||||||
vim.api.nvim_win_set_cursor(0, { linenr, colum })
|
vim.api.nvim_win_set_cursor(0, { linenr, colum })
|
||||||
end
|
end
|
||||||
@ -231,18 +369,29 @@ local function open_win()
|
|||||||
vim.keymap.set('i', '<Tab>', function()
|
vim.keymap.set('i', '<Tab>', function()
|
||||||
local line_number = vim.api.nvim_win_get_cursor(result_winid)[1]
|
local line_number = vim.api.nvim_win_get_cursor(result_winid)[1]
|
||||||
pcall(vim.api.nvim_win_set_cursor, result_winid, { line_number + 1, 0 })
|
pcall(vim.api.nvim_win_set_cursor, result_winid, { line_number + 1, 0 })
|
||||||
|
if conf.enable_preview then
|
||||||
|
vim.fn.timer_stop(preview_timer_id)
|
||||||
|
preview_timer_id = vim.fn.timer_start(500, preview_timer, { ['repeat'] = 1 })
|
||||||
|
end
|
||||||
update_result_count()
|
update_result_count()
|
||||||
end, { buffer = prompt_bufid })
|
end, { buffer = prompt_bufid })
|
||||||
|
|
||||||
vim.keymap.set('i', '<S-Tab>', function()
|
vim.keymap.set('i', '<S-Tab>', function()
|
||||||
local line_number = vim.api.nvim_win_get_cursor(result_winid)[1]
|
local line_number = vim.api.nvim_win_get_cursor(result_winid)[1]
|
||||||
pcall(vim.api.nvim_win_set_cursor, result_winid, { line_number - 1, 0 })
|
pcall(vim.api.nvim_win_set_cursor, result_winid, { line_number - 1, 0 })
|
||||||
|
if conf.enable_preview then
|
||||||
|
vim.fn.timer_stop(preview_timer_id)
|
||||||
|
preview_timer_id = vim.fn.timer_start(500, preview_timer, { ['repeat'] = 1 })
|
||||||
|
end
|
||||||
update_result_count()
|
update_result_count()
|
||||||
end, { buffer = prompt_bufid })
|
end, { buffer = prompt_bufid })
|
||||||
vim.keymap.set('i', '<C-e>', function()
|
vim.keymap.set('i', '<C-e>', function()
|
||||||
toggle_fix_string()
|
toggle_fix_string()
|
||||||
update_result_count()
|
update_result_count()
|
||||||
end, { buffer = prompt_bufid })
|
end, { buffer = prompt_bufid })
|
||||||
|
vim.keymap.set('i', '<C-p>', function()
|
||||||
|
toggle_preview_win()
|
||||||
|
end, { buffer = prompt_bufid })
|
||||||
|
|
||||||
-- 高亮文件名及位置
|
-- 高亮文件名及位置
|
||||||
vim.fn.matchadd(
|
vim.fn.matchadd(
|
||||||
|
@ -40,6 +40,8 @@ M.timeout = 200
|
|||||||
|
|
||||||
M.matched_higroup = 'IncSearch'
|
M.matched_higroup = 'IncSearch'
|
||||||
|
|
||||||
|
M.enable_preview = false
|
||||||
|
|
||||||
M.setup = function(conf)
|
M.setup = function(conf)
|
||||||
if type(conf) ~= 'table' then
|
if type(conf) ~= 'table' then
|
||||||
return
|
return
|
||||||
|
Loading…
Reference in New Issue
Block a user