Skip to content

Commit c15b38a

Browse files
authored
Merge pull request #77 from MadKuntilanak/feat/support-fzflua
feat: add support for fzf-lua
2 parents 6f02cc3 + 7f82f19 commit c15b38a

File tree

4 files changed

+221
-0
lines changed

4 files changed

+221
-0
lines changed

lua/tiny-code-action/config.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ M.VALID_PICKERS = {
55
snacks = true,
66
select = true,
77
buffer = true,
8+
["fzf-lua"] = true,
89
}
910

1011
M.VALID_BACKENDS = {

lua/tiny-code-action/picker.lua

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ function M.get_picker_module(picker_name)
2929
elseif picker_name == "select" then
3030
vim.notify("Select picker is not available. Falling back to buffer.", vim.log.levels.WARN)
3131
return M.get_picker_module("buffer")
32+
elseif picker_name == "fzf-lua" then
33+
vim.notify("Fzflua picker is not available. No picker could be loaded.", vim.log.levels.ERROR)
34+
return M.get_picker_module("select")
3235
elseif picker_name == "buffer" then
3336
vim.notify("Buffer picker is not available. No picker could be loaded.", vim.log.levels.ERROR)
3437
return nil
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
local BasePicker = require("tiny-code-action.base.picker")
2+
3+
local M = BasePicker.new()
4+
5+
local function format_code_action(item)
6+
local formatted = M.format_code_action(item)
7+
8+
return {
9+
{ formatted.kind, formatted.kind_hl },
10+
{ " " },
11+
{ formatted.ordinal, "FzfLuaNormal" },
12+
{ " (" .. formatted.client .. ")", "Comment" },
13+
}
14+
end
15+
16+
M.get_ctx_extracted = function(selected, items, actions)
17+
local fzflua_util = require("fzf-lua.utils")
18+
19+
local str_ic = fzflua_util.strip_ansi_coloring(selected)
20+
21+
local idx = 0
22+
23+
for i, v in pairs(items) do
24+
local v_str = fzflua_util.strip_ansi_coloring(v)
25+
if v_str == str_ic then
26+
idx = i
27+
end
28+
end
29+
30+
return actions[idx]
31+
end
32+
33+
function M.create(config, results, bufnr)
34+
if not M.has_dependency("fzf-lua", "fzf-lua") then
35+
return
36+
end
37+
38+
local fzflua = require("fzf-lua")
39+
40+
local items = {}
41+
local actions = {}
42+
43+
M.config = config
44+
45+
for i, result in ipairs(results) do
46+
local action = result.action
47+
local client = result.client
48+
local context = result.context
49+
50+
actions[i] = {
51+
client = client,
52+
action = action,
53+
context = context,
54+
}
55+
56+
local formatted_action
57+
for _, act in pairs(actions) do
58+
formatted_action = format_code_action(act)
59+
end
60+
61+
local _kind = formatted_action[1]
62+
local _desc = formatted_action[3]
63+
local _from_client = formatted_action[4]
64+
65+
local kind_w_hl = fzflua.utils.ansi_from_hl(_kind[2], _kind[1])
66+
local desc_w_hl = fzflua.utils.ansi_from_hl(_desc[2], _desc[1])
67+
local client_w_hl = fzflua.utils.ansi_from_hl(_from_client[2], _from_client[1])
68+
69+
table.insert(items, string.format("%s %s %s", kind_w_hl, desc_w_hl, client_w_hl))
70+
end
71+
72+
---@diagnostic disable: missing-fields
73+
---@type fzf-lua.config.Winopts
74+
local winopts = {
75+
title = "Code actions",
76+
height = 0.65,
77+
width = 0.70,
78+
col = 0.50,
79+
row = 0.50,
80+
preview = {
81+
hidden = false,
82+
layout = "vertical",
83+
vertical = "up:60%",
84+
},
85+
}
86+
87+
if type(config.picker) == "table" then
88+
winopts = vim.tbl_deep_extend("force", winopts, config.picker.opts.winopts or {})
89+
end
90+
91+
local previewer = M.init_previewer("fzf-lua", config)
92+
93+
---@diagnostic disable: missing-fields
94+
---@type fzf-lua.config.Defaults
95+
local picker_opts = {
96+
previewer = previewer.term_previewer({
97+
bufnr = bufnr,
98+
items = items,
99+
actions = actions,
100+
}),
101+
actions = {
102+
["default"] = function(selected, _)
103+
if not selected then
104+
return
105+
end
106+
107+
local sel = M.get_ctx_extracted(selected[1], items, actions)
108+
if sel then
109+
M.apply_action(sel.action, sel.client, sel.context, bufnr)
110+
end
111+
end,
112+
},
113+
}
114+
115+
picker_opts.winopts = winopts
116+
117+
return fzflua.fzf_exec(items, picker_opts)
118+
end
119+
120+
return M
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
local BasePreviewer = require("tiny-code-action.base.previewer")
2+
local fzf_picker = require("tiny-code-action.pickers.fzf-lua")
3+
local utils = require("tiny-code-action.utils")
4+
5+
local M = BasePreviewer.new()
6+
7+
local function extract_preview_data(entry, opts)
8+
local ctx = fzf_picker.get_ctx_extracted(entry, opts.items, opts.actions)
9+
if not ctx then
10+
return { "No preview available for this action" }
11+
end
12+
13+
local action = ctx.action
14+
local client = ctx.client
15+
16+
local preview_content = M.preview_with_resolve(action, opts.bufnr, client)
17+
if not preview_content or vim.tbl_isempty(preview_content) then
18+
preview_content = { "No preview available for this action" }
19+
end
20+
21+
return preview_content
22+
end
23+
24+
local function preview_cmd(opts)
25+
local fzf_fzf = require("fzf-lua.previewer.fzf")
26+
local shell = require("fzf-lua.shell")
27+
28+
local CodeActionPreviewerCmd = fzf_fzf.cmd_async:extend()
29+
30+
function CodeActionPreviewerCmd:new(o, optsc)
31+
CodeActionPreviewerCmd.super.new(self, o, optsc)
32+
setmetatable(self, CodeActionPreviewerCmd)
33+
return self
34+
end
35+
36+
function CodeActionPreviewerCmd:cmdline(o)
37+
o = o or {}
38+
return shell.stringify_cmd(function(entry_str)
39+
if type(entry_str) ~= "table" then
40+
return "echo 'No preview available for this action'"
41+
end
42+
43+
local preview_content = extract_preview_data(entry_str[1], opts)
44+
local text = table.concat(preview_content, "\n")
45+
return "echo '" .. text .. "'"
46+
end, {}, "{}")
47+
end
48+
49+
return CodeActionPreviewerCmd
50+
end
51+
52+
local function preview_buf(opts)
53+
local fzf_builtin = require("fzf-lua.previewer.builtin")
54+
55+
local CodeActionPreviewerBuf = fzf_builtin.buffer_or_file:extend()
56+
57+
function CodeActionPreviewerBuf:new(o, optsc, fzf_win)
58+
CodeActionPreviewerBuf.super.new(self, o, optsc, fzf_win)
59+
setmetatable(self, CodeActionPreviewerBuf)
60+
return self
61+
end
62+
63+
function CodeActionPreviewerBuf:populate_preview_buf(entry_str)
64+
local preview_content = extract_preview_data(entry_str, opts)
65+
66+
local sanitized_preview = {}
67+
68+
for _, line in ipairs(preview_content) do
69+
if type(line) == "string" and line:find("\n") then
70+
local split_lines = vim.split(line, "\n", { plain = true })
71+
vim.list_extend(sanitized_preview, split_lines)
72+
else
73+
table.insert(sanitized_preview, line)
74+
end
75+
end
76+
77+
local temp_buf = self:get_tmp_buffer()
78+
79+
vim.api.nvim_buf_set_lines(temp_buf, 0, -1, false, sanitized_preview)
80+
utils.set_buf_option(temp_buf, "filetype", "diff")
81+
82+
self:set_preview_buf(temp_buf)
83+
self.win:update_preview_scrollbar()
84+
end
85+
86+
return CodeActionPreviewerBuf
87+
end
88+
89+
function M.term_previewer(opts)
90+
local backend_name = M.config and M.config.backend or "vim"
91+
if not backend_name or backend_name == "vim" then
92+
return preview_buf(opts)
93+
end
94+
return preview_cmd(opts)
95+
end
96+
97+
return M

0 commit comments

Comments
 (0)