feat: Add better mapping support

This commit is contained in:
TJ DeVries
2020-08-31 00:06:33 -04:00
parent a6fe9721ac
commit 6b066cf9e8
7 changed files with 241 additions and 102 deletions

61
lua/telescope/WIP.lua Normal file
View File

@@ -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

View File

@@ -1,9 +1,14 @@
-- Actions functions that are useful for people creating their own mappings. -- Actions functions that are useful for people creating their own mappings.
local a = vim.api
local state = require('telescope.state') 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 --- Get the current picker object for the prompt
function actions.get_current_picker(prompt_bufnr) 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) actions.get_current_picker(prompt_bufnr):move_selection(change)
end 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 --- Get the current entry
function actions.get_selected_entry(prompt_bufnr) function actions.get_selected_entry(prompt_bufnr)
return actions.get_current_picker(prompt_bufnr):get_selection() return actions.get_current_picker(prompt_bufnr):get_selection()
end 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 return actions

View File

@@ -18,9 +18,6 @@ builtin.git_files = function(opts)
local show_preview = ifnil(opts.show_preview, true, opts.show_preview) 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 { local file_finder = finders.new {
static = true, static = true,
@@ -236,6 +233,4 @@ builtin.grep_string = function(opts)
} }
end end
return builtin return builtin

View File

@@ -149,6 +149,12 @@ finders.new = function(...)
return Finder:new(...) return Finder:new(...)
end end
-- We should add a few utility functions here...
--
-- finders.new_job
-- finders.new_one_shot_job
-- finders.new_table
finders.Finder = Finder finders.Finder = Finder
return finders return finders

View File

@@ -1,17 +1,36 @@
-- TODO: Customize keymap -- TODO: Customize keymap
local a = vim.api local a = vim.api
local actions = require('telescope.actions')
local state = require('telescope.state')
local mappings = {} 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, { mappings.apply_keymap(42, {
normal = { n = {
["<leader>x"] = "just do this string", ["<leader>x"] = "just do this string",
["<CR>"] = function(picker, prompt_bufnr) ["<CR>"] = function(picker, prompt_bufnr)
@@ -21,11 +40,49 @@ mappings.apply_keymap(42, {
vim.cmd(string.format(":e %s", filename)) vim.cmd(string.format(":e %s", filename))
end, end,
}, },
insert = {
i = {
} }
}) })
--]] --]]
mappings.apply_keymap = function(prompt_bufnr, buffer_keymap) 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 = "<C-O>"
end
a.nvim_buf_set_keymap(
prompt_bufnr,
mode,
key_bind,
string.format(
"%s:lua require('telescope.mappings').execute_keymap(%s, %s)<CR>",
prefix,
prompt_bufnr,
key_id
),
{
silent = true
}
)
end
end
end
vim.cmd(string.format( vim.cmd(string.format(
[[autocmd BufDelete %s :lua require('telescope.mappings').clear(%s)]], [[autocmd BufDelete %s :lua require('telescope.mappings').clear(%s)]],
@@ -34,95 +91,23 @@ mappings.apply_keymap = function(prompt_bufnr, buffer_keymap)
)) ))
end 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) mappings.clear = function(prompt_bufnr)
keymap_store[prompt_bufnr] = nil keymap_store[prompt_bufnr] = nil
end 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(
[[<C-O>:lua __TelescopeMapping(%s, %s, '%s')<CR>]],
prompt_bufnr,
results_bufnr,
table_key
),
{
silent = true,
}
)
end
default_mapper('i', '<c-n>', 'next_selection')
default_mapper('i', '<c-p>', 'previous_selection')
default_mapper('i', '<CR>', 'enter')
default_mapper('n', '<esc>', '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 return mappings

View File

@@ -1,6 +1,7 @@
local a = vim.api local a = vim.api
local popup = require('popup') local popup = require('popup')
local actions = require('telescope.actions')
local log = require('telescope.log') local log = require('telescope.log')
local mappings = require('telescope.mappings') local mappings = require('telescope.mappings')
local state = require('telescope.state') 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 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 = {
["<C-n>"] = actions.move_selection_next,
["<C-p>"] = actions.move_selection_previous,
["<CR>"] = actions.goto_file_selection,
},
n = {
["<esc>"] = actions.close,
},
}
-- Picker takes a function (`get_window_options`) that returns the configurations required for three windows: -- Picker takes a function (`get_window_options`) that returns the configurations required for three windows:
-- prompt -- prompt
-- results -- results
@@ -325,7 +338,8 @@ function Picker:find(opts)
finder = finder, 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]] vim.cmd [[startinsert]]
end end

View File

@@ -34,6 +34,27 @@ previewers.new = function(...)
return Previewer:new(...) return Previewer:new(...)
end 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 { previewers.vim_buffer = previewers.new {
preview_fn = function(_, entry, status) preview_fn = function(_, entry, status)
local value = entry.value local value = entry.value