Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ jobs:
}
mkdir -p ~/.local/share/nvim/site/pack/vendor/start
git clone --depth 1 https://github.com/nvim-lua/plenary.nvim ~/.local/share/nvim/site/pack/vendor/start/plenary.nvim
git clone --depth 1 https://github.com/MunifTanjim/nui.nvim ~/.local/share/nvim/site/pack/vendor/start/nui.nvim
git clone --depth 1 https://github.com/grapp-dev/nui-components.nvim ~/.local/share/nvim/site/pack/vendor/start/nui-components.nvim
ln -s $(pwd) ~/.local/share/nvim/site/pack/vendor/start

- name: Install latest stable `rustc`
uses: dtolnay/rust-toolchain@stable
with:
Expand Down
7 changes: 7 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,17 @@ on:
push:
tags:
- 'v*'
branches:
- master
pull_request:
jobs:
test:
name: Run tests
uses: ./.github/workflows/ci.yml
luarocks-upload:
needs: test
runs-on: ubuntu-22.04
if: github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/v')
steps:
- uses: actions/checkout@v3
- name: LuaRocks Upload
Expand Down
30 changes: 21 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,23 @@ vim.keymap.set('n', '<leader>sp', '<cmd>lua require("spectre").open_file_search(
})
```

You can also toggle between the legacy UI and the modern nui-based UI:

```lua
-- Toggle between legacy and modern UI
vim.keymap.set('n', '<leader>sU', '<cmd>lua require("spectre").toggle_ui()<CR>', {
desc = "Toggle between legacy and modern UI"
})

-- Switch to a specific UI
vim.keymap.set('n', '<leader>su', '<cmd>lua require("spectre").set_ui_type(false)<CR>', {
desc = "Use modern UI"
})
vim.keymap.set('n', '<leader>sL', '<cmd>lua require("spectre").set_ui_type(true)<CR>', {
desc = "Use legacy UI"
})
```

Use command: `:Spectre`

## Warnings
Expand Down Expand Up @@ -286,12 +303,9 @@ require('spectre').setup({
use_trouble_qf = false, -- use trouble.nvim as quickfix list
is_open_target_win = true, --open file on opener window
is_insert_mode = false, -- start open panel on is_insert_mode
is_block_ui_break = false -- mapping backspace and enter key to avoid ui break
open_template = {
-- an template to use on open function
-- see the 'custom function' section below to learn how to configure the template
-- { search_text = 'text1', replace_text = '', path = "" }
}
is_block_ui_break = false, -- mapping backspace and enter key to avoid ui break
open_template = {}, -- an template to use on open function
use_legacy_ui = false, -- set to true to use the legacy UI instead of nui-based modern UI
})

```
Expand Down Expand Up @@ -398,6 +412,4 @@ require('spectre').setup({ is_block_ui_break = true })

- Why is it called Spectre?

I wanted to call it `Search Panel` but this name is not cool.
I got the name of a hero on a game.
Spectre has a skill to find enemy on global map so I use it:)
I wanted to call it `
220 changes: 125 additions & 95 deletions lua/spectre/actions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,18 @@ local get_file_path = function(filename)
end

M.select_entry = function()
local t = M.get_current_entry()
if t == nil then
return nil
local entry = M.get_current_entry()
if not entry then
return
end
if config.is_open_target_win and state.target_winid ~= nil then
open_file(t.filename, t.lnum, t.col, state.target_winid)
else
open_file(t.filename, t.lnum, t.col)

local full_path = vim.fn.fnamemodify(entry.filename, ':p')
if not vim.fn.filereadable(full_path) then
return
end

vim.cmd('edit ' .. full_path)
api.nvim_win_set_cursor(0, { entry.lnum, entry.col - 1 })
end

M.get_state = function()
Expand All @@ -66,45 +69,64 @@ M.set_entry_finish = function(display_lnum)
end
end

M.get_current_entry = function()
if not state.total_item then
return
function M.get_current_entry()
local bufnr = api.nvim_get_current_buf()
local cursor_pos = api.nvim_win_get_cursor(0)
local line = api.nvim_buf_get_lines(bufnr, cursor_pos[1] - 1, cursor_pos[1], false)[1]

if not line then
return nil
end
local lnum = unpack(vim.api.nvim_win_get_cursor(0))
local item = state.total_item[lnum]
if item ~= nil and item.display_lnum == lnum - 1 then
local t = vim.deepcopy(item)
t.filename = get_file_path(item.filename)
return t

local filename, lnum, col = line:match('([^:]+):(%d+):(%d+):')
if not filename or not lnum or not col then
return nil
end

return {
filename = filename,
lnum = tonumber(lnum),
col = tonumber(col),
text = line:match(':[^:]+$'):sub(2),
}
end

M.get_all_entries = function()
function M.get_all_entries()
local entries = {}
for _, item in pairs(state.total_item) do
if not item.disable then
local t = vim.deepcopy(item)
t.filename = get_file_path(item.filename)
table.insert(entries, t)
for display_lnum, item in ipairs(state.total_item) do
if item and item.filename then
table.insert(entries, {
filename = item.filename,
lnum = item.lnum,
col = item.col,
text = item.text,
display_lnum = display_lnum - 1,
is_replace_finish = item.is_replace_finish or false,
})
end
end
return entries
end

M.send_to_qf = function()
local entries = M.get_all_entries()
vim.fn.setqflist(entries, 'r')
vim.fn.setqflist({}, 'r', {
title = string.format('Result Search: [%s]', state.query.search_query),
})
local trouble_avail, _ = pcall(require, 'trouble')
local status = trouble_avail and state.user_config.use_trouble_qf
if status then
vim.cmd([[Trouble quickfix win.relative=win focus=true]])
else
vim.cmd([[copen]])
if #entries == 0 then
vim.notify('No entries to send to quickfix')
return
end
return entries

local qf_list = {}
for _, entry in ipairs(entries) do
table.insert(qf_list, {
filename = entry.filename,
lnum = entry.lnum,
col = entry.col,
text = entry.text,
})
end

vim.fn.setqflist(qf_list)
vim.cmd('copen')
end

-- input that comand to run on vim
Expand Down Expand Up @@ -135,7 +157,7 @@ M.replace_cmd = function()
end
end

M.run_current_replace = function()
function M.run_current_replace()
local entry = M.get_current_entry()
if entry then
M.run_replace({ entry })
Expand All @@ -146,72 +168,72 @@ end

local is_running = false

M.run_replace = function(entries)
if is_running == true then
print('it is already running')
function M.run_replace(entries)
entries = entries or M.get_all_entries()
if #entries == 0 then
vim.notify('No entries to replace')
return
end
is_running = true
entries = entries or M.get_all_entries()
local replacer_creator = state_utils.get_replace_creator()
local done_item = 0
local error_item = 0
state.status_line = 'Run Replace.'
local replacer = replacer_creator:new(state_utils.get_replace_engine_config(), {
on_done = function(result)
if result.ref then
done_item = done_item + 1
state.status_line = 'Replace: ' .. done_item .. ' Error:' .. error_item
M.set_entry_finish(result.ref.display_lnum)
local value = result.ref
value.text = ' DONE'
vim.fn.setqflist(entries, 'r')
api.nvim_buf_set_extmark(
state.bufnr,
config.namespace,
value.display_lnum,
0,
{ virt_text = { { '󰄲 DONE', 'String' } }, virt_text_pos = 'eol' }
)
end
end,
on_error = function(result)
if type(result.value) == 'string' then
for line in result.value:gmatch('[^\r\n]+') do
print(line)

vim.schedule(function()
local replacer_creator = state_utils.get_replace_creator()
local replacer = replacer_creator:new(state_utils.get_replace_engine_config(), {
on_done = function(result)
if result.ref then
M.set_entry_finish(result.ref.display_lnum)
-- Update UI by adding a checkmark to the line
local bufnr = api.nvim_get_current_buf()
local line = result.ref.display_lnum
api.nvim_buf_set_extmark(
bufnr,
config.namespace,
line,
0,
{ virt_text = { { '✓', 'String' } }, virt_text_pos = 'eol' }
)
-- Trigger renderer redraw
if state.renderer then
print('redrawing')
state.renderer:redraw()
end
end
end,
on_error = function(result)
if result.ref then
vim.notify('Error replacing: ' .. result.value, vim.log.levels.ERROR)
-- Add error mark to the line
local bufnr = api.nvim_get_current_buf()
local line = result.ref.display_lnum
api.nvim_buf_set_extmark(
bufnr,
config.namespace,
line,
0,
{ virt_text = { { '✗', 'Error' } }, virt_text_pos = 'eol' }
)
-- Trigger renderer redraw
if state.renderer then
print('redrawing')
state.renderer:redraw()
end
end
end,
})

for _, entry in ipairs(entries) do
if not entry.is_replace_finish then
replacer:replace({
lnum = entry.lnum,
col = entry.col,
cwd = state.cwd,
display_lnum = entry.display_lnum,
filename = entry.filename,
search_text = state.query.search_query,
replace_text = state.query.replace_query,
})
end
if result.ref then
error_item = error_item + 1
local value = result.ref
value.text = 'ERROR'
vim.fn.setqflist(entries, 'r')
state.status_line = 'Replace: ' .. done_item .. ' Error:' .. error_item
api.nvim_buf_set_extmark(
state.bufnr,
config.namespace,
value.display_lnum,
0,
{ virt_text = { { '󰄱 ERROR', 'Error' } }, virt_text_pos = 'eol' }
)
end
end,
})
for _, value in pairs(entries) do
if not value.is_replace_finish then
replacer:replace({
lnum = value.lnum,
col = value.col,
cwd = state.cwd,
display_lnum = value.display_lnum,
filename = value.filename,
search_text = state.query.search_query,
replace_text = state.query.replace_query,
})
end
end
is_running = false
vim.cmd.checktime()
end)
end

M.delete_line_file_current = function()
Expand Down Expand Up @@ -245,6 +267,10 @@ M.run_delete_line = function(entries)
{ virt_text = { { '󰄲 DONE', 'String' } }, virt_text_pos = 'eol' }
)
end
-- Trigger renderer redraw
if state.renderer then
state.renderer:redraw()
end
end
end,
on_error = function(result)
Expand All @@ -262,6 +288,10 @@ M.run_delete_line = function(entries)
{ virt_text = { { '󰄱 ERROR', 'Error' } }, virt_text_pos = 'eol' }
)
end
-- Trigger renderer redraw
if state.renderer then
state.renderer:redraw()
end
end
end,
})
Expand Down
11 changes: 3 additions & 8 deletions lua/spectre/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,6 @@ local config = {
lnum_UI = 8, -- total line for ui you can edit it
line_result = 10, -- line begin result

-- result_padding = '│ ',
-- color_devicons = true,
-- line_sep_start = '┌-----------------------------------------',
-- result_padding = '¦ ',
-- line_sep = '├──────────────────────────────────────',

line_sep_start = '┌──────────────────────────────────────────────────────',
result_padding = '│ ',
line_sep = '└──────────────────────────────────────────────────────',
Expand Down Expand Up @@ -73,12 +67,12 @@ local config = {
['run_current_replace'] = {
map = '<leader>rc',
cmd = "<cmd>lua require('spectre.actions').run_current_replace()<CR>",
desc = 'replace item',
desc = 'replace current item',
},
['run_replace'] = {
map = '<leader>R',
cmd = "<cmd>lua require('spectre.actions').run_replace()<CR>",
desc = 'replace all',
desc = 'replace all items',
},
-- only show replace text in result UI
['change_view_mode'] = {
Expand Down Expand Up @@ -220,6 +214,7 @@ local config = {
is_insert_mode = false,
is_block_ui_break = false,
open_template = {},
ui = 'buffer',
}

return config
Loading
Loading