1795cd4
Branches > main > 1795cd4 > files / nvim / pack / plugins / opt / conjure / dev / python / sandbox.py
Nvim - Replace fzf with a lua picker, use it for vim.ui.select
Commit: 1795cd4931b01904f523471844c325f60d84ba20
Parent: 149093b
6 changed files:
nvim/lua/colors.lua view file
@@ -148,3 +148,5 @@ hl(0, "Jump", {bg = highlight_bg}) hl(0, "JumpDisambiguator", {bg = highlight_bg, bold = true, fg = "#2ad6d6"})++hl(0, "PickerMatch", {fg = green})nvim/lua/fuzzy.lua view file
@@ -1,36 +0,0 @@-local api = vim.api-local fn = vim.fn--local ui = require("utils.ui")--local function fzf_window(win)- local tmp = fn.tempname()- local cmd = 'fzf --pointer=">" --gutter=" " --prompt="" --no-info --no-scrollbar' .. ">" .. fn.shellescape(tmp)-- fn.termopen({"sh", "-c", cmd}, {- on_exit = function()- pcall(api.nvim_win_close, win, true)- if fn.filereadable(tmp) == 1 then- local sel = fn.readfile(tmp)[1]- os.remove(tmp)- if sel and #sel > 0 then- vim.cmd("edit " .. fn.fnameescape(sel))- end- end- end})- vim.cmd("startinsert")-end--local function fuzzy_find()- if fn.executable("fzf") ~= 1 then- print("You don't have fzf, can't fuzzy find!")- else- local win = ui.open_fullscreen_window()- local ok = pcall(fzf_window, win)- if not ok then- pcall(api.nvim_win_close, win, true)- end- end-end--return {fuzzy_find = fuzzy_find}nvim/lua/keybindings.lua view file
@@ -46,7 +46,7 @@ keymap("n", "<Space>u", function() require("plugins.oil").open() end) -keymap("n", "<Space>g", function() require("fuzzy").fuzzy_find() end)+keymap("n", "<Space>g", function() require("picker").files() end) keymap({"n", "v", "o"}, ";", function() require("jump").jump() end) nvim/lua/lazy_ui.lua view file
@@ -10,3 +10,6 @@ group = group, callback = function() vim.hl.on_yank() end, })++--- Code actions and anything else that asks to pick from a list+vim.ui.select = function(...) require("picker").select(...) endnvim/lua/picker.lua view file
@@ -0,0 +1,132 @@+local api = vim.api+local fn = vim.fn++local ns = api.nvim_create_namespace("dev.grahp.picker")++local function float(row, height)+ local buf = api.nvim_create_buf(false, true)+ vim.bo[buf].bufhidden = "wipe"+ local win = api.nvim_open_win(buf, false, {+ relative = "editor",+ row = row,+ col = 0,+ width = vim.o.columns,+ height = height,+ style = "minimal",+ border = "none"+ })+ return win, buf+end++--- Fullscreen fuzzy picker, prompt at the bottom and matches going up from it+--- on_choice gets the picked string, or nil if cancelled+local function pick(items, on_choice)+ local orig_win = api.nvim_get_current_win()+ local orig_cursor = api.nvim_win_get_cursor(orig_win)+ local h = vim.o.lines - 1+ local list_win, list_buf = float(0, h)+ local prompt_win, prompt_buf = float(h, 1)+ vim.wo[list_win].cursorline = true+ api.nvim_set_current_win(prompt_win)++ local p = {items = items, query = "", matches = {}}+ local done = false++ local function query() return api.nvim_buf_get_lines(prompt_buf, 0, 1, false)[1] end++ local function refilter()+ p.query = query()+ local res = p.query == "" and {vim.list_slice(p.items, 1, h), {}}+ or fn.matchfuzzypos(p.items, p.query, {limit = h})+ p.matches = res[1]+ local lines = {}+ for row = 1, h do lines[row] = p.matches[h - row + 1] or "" end+ api.nvim_buf_set_lines(list_buf, 0, -1, false, lines)+ api.nvim_buf_clear_namespace(list_buf, ns, 0, -1)+ for i, positions in ipairs(res[2]) do+ for _, pos in ipairs(positions) do+ local col = vim.str_byteindex(p.matches[i], "utf-32", pos, false)+ api.nvim_buf_set_extmark(list_buf, ns, h - i, col, {end_col = col + 1, hl_group = "PickerMatch"})+ end+ end+ api.nvim_win_set_cursor(list_win, {h, 0})+ end++ local function close(choice)+ if done then return end+ done = true+ vim.cmd("stopinsert")+ pcall(api.nvim_win_close, prompt_win, true)+ pcall(api.nvim_win_close, list_win, true)+ vim.schedule(function()+ --- Leaving insert mode nudges the cursor left, code actions care about where it is+ pcall(api.nvim_win_set_cursor, orig_win, orig_cursor)+ on_choice(choice)+ end)+ end++ local function accept()+ --- TextChangedI waits for typeahead, so typing fast then <CR> can be stale+ if query() ~= p.query then refilter() end+ close(p.matches[h - api.nvim_win_get_cursor(list_win)[1] + 1])+ end++ local function move(d)+ return function()+ local row = api.nvim_win_get_cursor(list_win)[1] + d+ if row <= h and row > h - #p.matches then api.nvim_win_set_cursor(list_win, {row, 0}) end+ end+ end++ local keys = {["<CR>"] = accept,+ ["<Esc>"] = function() close() end,+ ["<C-c>"] = function() close() end,+ ["<Down>"] = move(1), ["<C-j>"] = move(1), ["<C-n>"] = move(1), ["<Tab>"] = move(1),+ ["<Up>"] = move(-1), ["<C-k>"] = move(-1), ["<C-p>"] = move(-1), ["<S-Tab>"] = move(-1)}+ for lhs, f in pairs(keys) do+ vim.keymap.set({"i", "n"}, lhs, f, {buffer = prompt_buf, nowait = true})+ end++ api.nvim_create_autocmd({"TextChangedI", "TextChanged"}, {buffer = prompt_buf, callback = refilter})+ api.nvim_create_autocmd("WinLeave", {buffer = prompt_buf, callback = function() close() end})++ function p.set_items(new)+ if not done then p.items = new; refilter() end+ end++ refilter()+ vim.cmd("startinsert")+ return p+end++local function lines_of(cmd, cb)+ vim.system(cmd, {text = true}, vim.schedule_wrap(function(res)+ cb(res.code == 0 and vim.split(res.stdout, "\n", {trimempty = true}) or nil)+ end))+end++--- Opens instantly, the file list fills in once git (or rg outside a repo) is done+local function files()+ local p = pick({}, function(file)+ if file then vim.cmd("edit " .. fn.fnameescape(file)) end+ end)+ lines_of({"git", "ls-files", "--cached", "--others", "--exclude-standard"}, function(found)+ if found then+ p.set_items(found)+ elseif fn.executable("rg") == 1 then+ lines_of({"rg", "--files", "--hidden", "--glob", "!.git"}, function(rg) p.set_items(rg or {}) end)+ end+ end)+end++--- Drop in for vim.ui.select (code actions and such)+local function select(items, opts, on_choice)+ local format = (opts or {}).format_item or tostring+ local texts = vim.tbl_map(function(item) return (format(item):gsub("\n", " ")) end, items)+ pick(texts, function(text)+ local idx = text and fn.index(texts, text) + 1+ on_choice(idx and items[idx], idx)+ end)+end++return {files = files, select = select}nvim/lua/utils/ui.lua view file
@@ -1,18 +0,0 @@--local api = vim.api-local o = vim.o--local function open_fullscreen_window()- local buf = api.nvim_create_buf(false, true)- return api.nvim_open_win(buf, true, {- relative = "editor",- row = 0,- col = 0,- width = o.columns,- height = o.lines,- style = "minimal",- border = "none"- })-end--return {open_fullscreen_window = open_fullscreen_window}