diff --git a/lua/telescope/WIP.lua b/lua/telescope/WIP.lua new file mode 100644 index 0000000..cab745a --- /dev/null +++ b/lua/telescope/WIP.lua @@ -0,0 +1,61 @@ + +local finders = require('telescope.finders') +local previewers = require('telescope.previewers') +local pickers = require('telescope.pickers') +local sorters = require('telescope.sorters') + +local WIP = {} + +WIP.git_diff = function() + local file_picker = pickers.new { + previewer = previewers.new_termopen { + command = "git diff %s" + }, + } + + file_picker:find { + prompt = "Git Diff Viewier", + + finder = finders.new { + static = true, + + fn_command = function() + return { + command = 'git', + args = {'ls-files', '-m'} + } + end, + }, + + sorter = sorters.get_norcalli_sorter() + } +end + +-- TODO: Make it so that when you select stuff, it's inserted +-- TODO: Make it so the previewer shows the help text. +WIP.completion = function() + local results = {} + for k, v in pairs(vim.api) do + table.insert(results, k) + end + + local lsp_reference_finder = finders.new { + results = results + } + + -- local reference_previewer = previewers.qflist + local reference_picker = pickers.new { + -- previewer = reference_previewer + } + + reference_picker:find { + prompt = 'LSP References', + finder = lsp_reference_finder, + sorter = sorters.get_norcalli_sorter(), + } +end + +-- TODO: Use tree sitter to get "everything" in your current scope / file / etc. +-- Fuzzy find ofver it, go to its definition. + +return WIP diff --git a/lua/telescope/actions.lua b/lua/telescope/actions.lua index a03323b..abd5bf8 100644 --- a/lua/telescope/actions.lua +++ b/lua/telescope/actions.lua @@ -1,9 +1,14 @@ -- Actions functions that are useful for people creating their own mappings. +local a = vim.api + local state = require('telescope.state') -local actions = {} - +local actions = setmetatable({}, { + __index = function(t, k) + error("Actions does not have a value: " .. tostring(k)) + end +}) --- Get the current picker object for the prompt function actions.get_current_picker(prompt_bufnr) @@ -16,10 +21,62 @@ function actions.shift_current_selection(prompt_bufnr, change) actions.get_current_picker(prompt_bufnr):move_selection(change) end +function actions.move_selection_next(prompt_bufnr) + actions.shift_current_selection(prompt_bufnr, 1) +end + +function actions.move_selection_previous(prompt_bufnr) + actions.shift_current_selection(prompt_bufnr, -1) +end + --- Get the current entry function actions.get_selected_entry(prompt_bufnr) return actions.get_current_picker(prompt_bufnr):get_selection() end +function actions.goto_file_selection(prompt_bufnr) + local picker = actions.get_current_picker(prompt_bufnr) + local entry = actions.get_selected_entry(prompt_bufnr) + + if not entry then + print("[telescope] Nothing currently selected") + return + else + local value = entry.value + if not value then + print("Could not do anything with blank line...") + return + end + + -- TODO: This is not great. + if type(value) == "table" then + value = entry.display + end + + local sections = vim.split(value, ":") + + local filename = sections[1] + local row = tonumber(sections[2]) + local col = tonumber(sections[3]) + + vim.cmd(string.format([[bwipeout! %s]], prompt_bufnr)) + + a.nvim_set_current_win(picker.original_win_id or 0) + vim.cmd(string.format(":e %s", filename)) + + local bufnr = vim.api.nvim_get_current_buf() + a.nvim_buf_set_option(bufnr, 'buflisted', true) + if row and col then + a.nvim_win_set_cursor(0, {row, col}) + end + + vim.cmd [[stopinsert]] + end +end + +actions.close = function(prompt_bufnr) + vim.cmd(string.format([[bwipeout! %s]], prompt_bufnr)) +end + return actions diff --git a/lua/telescope/builtin.lua b/lua/telescope/builtin.lua index 7aa255b..4542108 100644 --- a/lua/telescope/builtin.lua +++ b/lua/telescope/builtin.lua @@ -18,9 +18,6 @@ builtin.git_files = function(opts) local show_preview = ifnil(opts.show_preview, true, opts.show_preview) - -- TODO: Auto select bottom row - -- TODO: filter out results when they don't match at all anymore. - local file_finder = finders.new { static = true, @@ -236,6 +233,4 @@ builtin.grep_string = function(opts) } end - - return builtin diff --git a/lua/telescope/finders.lua b/lua/telescope/finders.lua index 6fa4099..7866c87 100644 --- a/lua/telescope/finders.lua +++ b/lua/telescope/finders.lua @@ -149,6 +149,12 @@ finders.new = function(...) return Finder:new(...) end +-- We should add a few utility functions here... +-- +-- finders.new_job +-- finders.new_one_shot_job +-- finders.new_table + finders.Finder = Finder return finders diff --git a/lua/telescope/mappings.lua b/lua/telescope/mappings.lua index 38c664a..ba618d4 100644 --- a/lua/telescope/mappings.lua +++ b/lua/telescope/mappings.lua @@ -1,17 +1,36 @@ -- TODO: Customize keymap local a = vim.api -local actions = require('telescope.actions') -local state = require('telescope.state') - local mappings = {} -local keymap = {} -local keymap_store = {} +local keymap_store = setmetatable({}, { + __index = function(t, k) + rawset(t, k, {}) + + return rawget(t, k) + end +}) + +local _mapping_key_id = 0 +local get_next_id = function() + _mapping_key_id = _mapping_key_id + 1 + return _mapping_key_id +end + +local assign_function = function(prompt_bufnr, func) + local func_id = get_next_id() + + keymap_store[prompt_bufnr][func_id] = func + + return func_id +end + --[[ +Usage: + mappings.apply_keymap(42, { - normal = { + n = { ["x"] = "just do this string", [""] = function(picker, prompt_bufnr) @@ -21,11 +40,49 @@ mappings.apply_keymap(42, { vim.cmd(string.format(":e %s", filename)) end, }, - insert = { + + i = { } }) --]] mappings.apply_keymap = function(prompt_bufnr, buffer_keymap) + for mode, mode_map in pairs(buffer_keymap) do + for key_bind, key_func in pairs(mode_map) do + if type(key_func) == "string" then + a.nvim_buf_set_keymap( + prompt_bufnr, + mode, + key_bind, + key_func, + { + silent = true + } + ) + else + local key_id = assign_function(prompt_bufnr, key_func) + local prefix = "" + if mode == "i" then + prefix = "" + end + + a.nvim_buf_set_keymap( + prompt_bufnr, + mode, + key_bind, + string.format( + "%s:lua require('telescope.mappings').execute_keymap(%s, %s)", + prefix, + prompt_bufnr, + key_id + ), + { + silent = true + } + ) + + end + end + end vim.cmd(string.format( [[autocmd BufDelete %s :lua require('telescope.mappings').clear(%s)]], @@ -34,95 +91,23 @@ mappings.apply_keymap = function(prompt_bufnr, buffer_keymap) )) end +mappings.execute_keymap = function(prompt_bufnr, keymap_identifier) + local key_func = keymap_store[prompt_bufnr][keymap_identifier] + + assert( + key_func, + string.format( + "Unsure of how we got this failure: %s %s", + prompt_bufnr, + keymap_identifier + ) + ) + + key_func(prompt_bufnr) +end + mappings.clear = function(prompt_bufnr) keymap_store[prompt_bufnr] = nil end -mappings.set_keymap = function(prompt_bufnr, results_bufnr) - local function default_mapper(mode, map_key, table_key) - a.nvim_buf_set_keymap( - prompt_bufnr, - mode, - map_key, - string.format( - [[:lua __TelescopeMapping(%s, %s, '%s')]], - prompt_bufnr, - results_bufnr, - table_key - ), - { - silent = true, - } - ) - end - - default_mapper('i', '', 'next_selection') - default_mapper('i', '', 'previous_selection') - default_mapper('i', '', 'enter') - - default_mapper('n', '', 'escape') -end - - -function __TelescopeMapping(prompt_bufnr, results_bufnr, characters) - if keymap[characters] then - keymap[characters](prompt_bufnr, results_bufnr) - end -end - --- TODO: Refactor this to use shared code. --- TODO: Move from top to bottom, etc. --- TODO: It seems like doing this brings us back to the beginning of the prompt, which is not great. -keymap["next_selection"] = function(prompt_bufnr, _) - actions.shift_current_selection(prompt_bufnr, 1) -end - -keymap["previous_selection"] = function(prompt_bufnr, _) - actions.shift_current_selection(prompt_bufnr, -1) -end - -keymap["enter"] = function(prompt_bufnr, results_bufnr) - local picker = actions.get_current_picker(prompt_bufnr) - local entry = actions.get_selected_entry(prompt_bufnr) - - if not entry then - print("[telescope] Nothing currently selected") - return - else - local value = entry.value - if not value then - print("Could not do anything with blank line...") - return - end - - -- TODO: This is not great. - if type(value) == "table" then - value = entry.display - end - - local sections = vim.split(value, ":") - - local filename = sections[1] - local row = tonumber(sections[2]) - local col = tonumber(sections[3]) - - vim.cmd(string.format([[bwipeout! %s]], prompt_bufnr)) - - a.nvim_set_current_win(picker.original_win_id or 0) - vim.cmd(string.format(":e %s", filename)) - - local bufnr = vim.api.nvim_get_current_buf() - a.nvim_buf_set_option(bufnr, 'buflisted', true) - if row and col then - a.nvim_win_set_cursor(0, {row, col}) - end - - vim.cmd [[stopinsert]] - end -end - -keymap["escape"] = function(prompt_bufnr) - vim.cmd(string.format([[bwipeout! %s]], prompt_bufnr)) -end - return mappings diff --git a/lua/telescope/pickers.lua b/lua/telescope/pickers.lua index 4a08262..ce01f23 100644 --- a/lua/telescope/pickers.lua +++ b/lua/telescope/pickers.lua @@ -1,6 +1,7 @@ local a = vim.api local popup = require('popup') +local actions = require('telescope.actions') local log = require('telescope.log') local mappings = require('telescope.mappings') local state = require('telescope.state') @@ -16,6 +17,18 @@ local pickers = {} local ifnil = function(x, was_nil, was_not_nil) if x == nil then return was_nil else return was_not_nil end end +local default_mappings = { + i = { + [""] = actions.move_selection_next, + [""] = actions.move_selection_previous, + [""] = actions.goto_file_selection, + }, + + n = { + [""] = actions.close, + }, +} + -- Picker takes a function (`get_window_options`) that returns the configurations required for three windows: -- prompt -- results @@ -325,7 +338,8 @@ function Picker:find(opts) finder = finder, }) - mappings.set_keymap(prompt_bufnr, results_bufnr) + -- mappings.set_keymap(prompt_bufnr, results_bufnr) + mappings.apply_keymap(prompt_bufnr, opts.mappings or default_mappings) vim.cmd [[startinsert]] end diff --git a/lua/telescope/previewers.lua b/lua/telescope/previewers.lua index 3e79ad3..4743639 100644 --- a/lua/telescope/previewers.lua +++ b/lua/telescope/previewers.lua @@ -34,6 +34,27 @@ previewers.new = function(...) return Previewer:new(...) end +previewers.new_termopen = function(opts) + local entry_value = opts.get_value or function(entry) + return entry.value + end + + local command_string = opts.command + + return previewers.new { + preview_fn = function(_, entry, status) + local bufnr = vim.api.nvim_create_buf(false, true) + + vim.api.nvim_win_set_buf(status.preview_win, bufnr) + + -- HACK! Requires `termopen` to accept buffer argument. + vim.cmd(string.format("noautocmd call win_gotoid(%s)", status.preview_win)) + vim.fn.termopen(string.format(command_string, entry_value(entry))) + vim.cmd(string.format("noautocmd call win_gotoid(%s)", status.prompt_win)) + end + } +end + previewers.vim_buffer = previewers.new { preview_fn = function(_, entry, status) local value = entry.value