feat: Action improvements (#472)
* feat: replace_map * feat: Add action_set and action_state * fix: Move all actions.get_ to action_state.get_ * fix: replace all internal references of _goto_file_selection_edit * feat: add some docs * fix: lint * feat: actions.select * remove mentions and usage of goto_file_selection APIs * feat: special case attach_mappings to be overridable and defaultable * Having goto_file_selection mappings will cause a error as well as replacing deprecated goto_file_selection methodes For config and replacing use this instead: - actions.select_default - actions.select_horizonal - actions.select_vertical - actions.select_tab Only replacing: - actions.set.edit -- for replacing all select functions * adds actions.state.select_key_to_edit_key Co-authored-by: Simon Hauser <Simon-Hauser@outlook.de>
This commit is contained in:
65
README.md
65
README.md
@@ -277,12 +277,15 @@ require('telescope').setup{
|
||||
-- To disable a keymap, put [map] = false
|
||||
-- So, to not map "<C-n>", just put
|
||||
["<c-x>"] = false,
|
||||
|
||||
-- Otherwise, just set the mapping to the function that you want it to be.
|
||||
["<C-i>"] = actions.goto_file_selection_split,
|
||||
["<C-i>"] = actions.select_horizontal,
|
||||
|
||||
-- Add up multiple actions
|
||||
["<CR>"] = actions.goto_file_selection_edit + actions.center,
|
||||
["<CR>"] = actions.select_default + actions.center,
|
||||
|
||||
-- You can perform as many actions in a row as you like
|
||||
["<CR>"] = actions.goto_file_selection_edit + actions.center + my_cool_custom_action,
|
||||
["<CR>"] = actions.select_default+ actions.center + my_cool_custom_action,
|
||||
},
|
||||
n = {
|
||||
["<esc>"] = actions.close,
|
||||
@@ -298,70 +301,40 @@ its `attach_mappings` key to a function, like this
|
||||
|
||||
```lua
|
||||
local actions = require('telescope.actions')
|
||||
local action_set = require('telescope.actions.set')
|
||||
-- Picker specific remapping
|
||||
------------------------------
|
||||
require('telescope.builtin').fd({ -- or new custom picker's attach_mappings field:
|
||||
attach_mappings = function(prompt_bufnr)
|
||||
-- This will replace select no mather on which key it is mapped by default
|
||||
actions.goto_file_selection_edit:replace(function()
|
||||
local entry = actions.get_selected_entry()
|
||||
action_set.select:replace(function(prompt_bufnr, type)
|
||||
local entry = action_state.get_selected_entry()
|
||||
actions.close(prompt_bufnr)
|
||||
print(vim.inspect(entry))
|
||||
-- Code here
|
||||
end)
|
||||
|
||||
-- You can also enhance an action with pre and post action which will run before of after an action
|
||||
actions.goto_file_selection_split:enhance ({
|
||||
action_set.select:enhance({
|
||||
pre = function()
|
||||
-- Will run before actions.goto_file_selection_split
|
||||
-- Will run before actions.select_default
|
||||
end,
|
||||
post = function()
|
||||
-- Will run after actions.goto_file_selection_split
|
||||
-- Will run after actions.select_default
|
||||
end,
|
||||
})
|
||||
|
||||
-- Or replace for all commands: edit, new, vnew and tab
|
||||
actions._goto_file_selection:replace(function(_, cmd)
|
||||
-- Or replace for all commands: default, horizontal, vertical, tab
|
||||
action_set.select:replace(function(_, type)
|
||||
print(cmd) -- Will print edit, new, vnew or tab depending on your keystroke
|
||||
end)
|
||||
|
||||
return true
|
||||
end,
|
||||
end,
|
||||
})
|
||||
```
|
||||
<!-- TODO: Move to wiki page made specifically for creating pickers -->
|
||||
<!-- To override a action, you have to use `attach_mappings` like this (prefered method): -->
|
||||
|
||||
<!-- ```lua -->
|
||||
<!-- function my_custom_picker(results) -->
|
||||
<!-- pickers.new(opts, { -->
|
||||
<!-- prompt_title = 'Custom Picker', -->
|
||||
<!-- finder = finders.new_table(results), -->
|
||||
<!-- sorter = sorters.fuzzy_with_index_bias(), -->
|
||||
<!-- attach_mappings = function(prompt_bufnr) -->
|
||||
<!-- -- This will replace select no mather on which key it is mapped by default -->
|
||||
<!-- actions.goto_file_selection_edit:replace(function() -->
|
||||
<!-- -- Code here -->
|
||||
<!-- end) -->
|
||||
<!-- -- You can also enhance an action with post and post action which will run before of after an action -->
|
||||
<!-- actions.goto_file_selection_split:enhance { -->
|
||||
<!-- pre = function() -->
|
||||
<!-- -- Will run before actions.goto_file_selection_split -->
|
||||
<!-- end, -->
|
||||
<!-- post = function() -->
|
||||
<!-- -- Will run after actions.goto_file_selection_split -->
|
||||
<!-- end, -->
|
||||
<!-- } -->
|
||||
<!-- -- Or replace for all commands: edit, new, vnew and tab -->
|
||||
<!-- actions._goto_file_selection:replace(function(_, cmd) -->
|
||||
<!-- print(cmd) -- Will print edit, new, vnew or tab depending on your keystroke -->
|
||||
<!-- end) -->
|
||||
<!-- return true -->
|
||||
<!-- end, -->
|
||||
<!-- }):find() -->
|
||||
<!-- end -->
|
||||
<!-- ``` -->
|
||||
<!-- See `lua/telescope/builtin.lua` for examples on how to `attach_mappings` in the prefered way. -->
|
||||
For more info, see [./developers.md](./developers.md)
|
||||
|
||||
## Pickers
|
||||
|
||||
@@ -610,6 +583,12 @@ function my_custom_picker(results)
|
||||
-- Map "<CR>" in insert mode to the function, actions.set_command_line
|
||||
map('i', '<CR>', actions.set_command_line)
|
||||
|
||||
-- If the return value of `attach_mappings` is true, then the other
|
||||
-- default mappings are still applies.
|
||||
--
|
||||
-- Return false if you don't want any other mappings applied.
|
||||
--
|
||||
-- A return value _must_ be returned. It is an error to not return anything.
|
||||
return true
|
||||
end,
|
||||
}):find()
|
||||
|
||||
56
developers.md
Normal file
56
developers.md
Normal file
@@ -0,0 +1,56 @@
|
||||
|
||||
|
||||
## Overriding actions/action_set
|
||||
|
||||
How to override what different functions / keys do.
|
||||
|
||||
TODO: Talk about what actions vs actions sets are
|
||||
|
||||
### Relevant Files
|
||||
|
||||
- `lua/telescope/actions/init.lua`
|
||||
- The most "user-facing" of the files, which has the actions we provide builtin
|
||||
- `lua/telescope/actions/set.lua`
|
||||
- The second most "user-facing" of the files. This provides actions that are consumed by several builtin actions, which allows for only overriding ONE item, instead of copying the same configuration / function several times.
|
||||
- `lua/telescope/actions/state.lua`
|
||||
- Provides APIs for interacting with the state of telescope while in actions.
|
||||
- These are most useful for writing your own actions and interacting with telescope at that time
|
||||
- `lua/telescope/actions/mt.lua`
|
||||
- You probably don't need to look at this, but it defines the behavior of actions.
|
||||
|
||||
### `:replace(function)`
|
||||
|
||||
Directly override an action with a new function
|
||||
|
||||
```lua
|
||||
local actions = require('telescope.actions')
|
||||
actions.select_default:replace(git_checkout_function)
|
||||
```
|
||||
|
||||
### `:replace_if(conditional, function)`
|
||||
|
||||
Override an action only when `conditional` returns true.
|
||||
|
||||
```lua
|
||||
local action_set = require('telescope.actions.set')
|
||||
action_set.select:replace_if(
|
||||
function()
|
||||
return action_state.get_selected_entry().path:sub(-1) == os_sep
|
||||
end, function(_, type)
|
||||
-- type is { "default", "horizontal", "vertical", "tab" }
|
||||
local path = actions.get_selected_entry().path
|
||||
actions.refresh(prompt_bufnr, gen_new_finder(vim.fn.expand(path:sub(1, -2))), { reset_prompt = true })
|
||||
end
|
||||
)
|
||||
```
|
||||
|
||||
### `:replace_map(configuration)`
|
||||
|
||||
```lua
|
||||
local action_set = require('telescope.actions.set')
|
||||
-- Use functions as keys to map to which function to execute when called.
|
||||
action_set.select:replace_map {
|
||||
[function(e) return e > 0 end] = function(e) return (e / 10) end,
|
||||
[function(e) return e == 0 end] = function(e) return (e + 10) end,
|
||||
}
|
||||
```
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
local make_entry = require('telescope.make_entry')
|
||||
local actions = require('telescope.actions')
|
||||
local action_state = require('telescope.actions.state')
|
||||
local finders = require('telescope.finders')
|
||||
local previewers = require('telescope.previewers')
|
||||
local pickers = require('telescope.pickers')
|
||||
@@ -70,7 +71,7 @@ WIP.reloader = function(opts)
|
||||
|
||||
attach_mappings = function(prompt_bufnr, map)
|
||||
local reload_package = function()
|
||||
local selection = actions.get_selected_entry(prompt_bufnr)
|
||||
local selection = action_state.get_selected_entry(prompt_bufnr)
|
||||
|
||||
actions.close(prompt_bufnr)
|
||||
|
||||
|
||||
@@ -3,162 +3,134 @@
|
||||
local a = vim.api
|
||||
|
||||
local log = require('telescope.log')
|
||||
local path = require('telescope.path')
|
||||
local state = require('telescope.state')
|
||||
local utils = require('telescope.utils')
|
||||
|
||||
local action_state = require('telescope.actions.state')
|
||||
local action_set = require('telescope.actions.set')
|
||||
|
||||
local transform_mod = require('telescope.actions.mt').transform_mod
|
||||
|
||||
local actions = setmetatable({}, {
|
||||
__index = function(_, k)
|
||||
error("Actions does not have a value: " .. tostring(k))
|
||||
-- TODO(conni2461): Remove deprecated messages
|
||||
if k:find('goto_file_selection') then
|
||||
error("`" .. k .. "` is removed and no longer usable. " ..
|
||||
"Use `require('telescope.actions').select_` instead. Take a look at developers.md for more Information.")
|
||||
elseif k == '_goto_file_selection' then
|
||||
error("`_goto_file_selection` is deprecated and no longer replaceable. " ..
|
||||
"Use `require('telescope.actions.set').edit` instead. Take a look at developers.md for more Information.")
|
||||
end
|
||||
|
||||
error("Key does not exist for 'telescope.actions': " .. tostring(k))
|
||||
end
|
||||
})
|
||||
|
||||
--- Get the current picker object for the prompt
|
||||
function actions.get_current_picker(prompt_bufnr)
|
||||
return state.get_status(prompt_bufnr).picker
|
||||
end
|
||||
-- TODO(conni2461): Remove deprecated messages
|
||||
local action_is_deprecated = function(name, err)
|
||||
local messager = err and error or log.info
|
||||
|
||||
--- Move the current selection of a picker {change} rows.
|
||||
--- Handles not overflowing / underflowing the list.
|
||||
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
|
||||
|
||||
function actions.add_selection(prompt_bufnr)
|
||||
local current_picker = actions.get_current_picker(prompt_bufnr)
|
||||
current_picker:add_selection(current_picker:get_selection_row())
|
||||
end
|
||||
|
||||
function actions.remove_selection(prompt_bufnr)
|
||||
local current_picker = actions.get_current_picker(prompt_bufnr)
|
||||
current_picker:remove_selection(current_picker:get_selection_row())
|
||||
end
|
||||
|
||||
function actions.toggle_selection(prompt_bufnr)
|
||||
local current_picker = actions.get_current_picker(prompt_bufnr)
|
||||
current_picker:toggle_selection(current_picker:get_selection_row())
|
||||
return messager(
|
||||
string.format("`actions.%s()` is deprecated."
|
||||
.. "Use require('telescope.actions.state').%s() instead",
|
||||
name,
|
||||
name
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
--- Get the current entry
|
||||
function actions.get_selected_entry()
|
||||
return state.get_global_key('selected_entry')
|
||||
-- TODO(1.0): Remove
|
||||
action_is_deprecated("get_selected_entry")
|
||||
return action_state.get_selected_entry()
|
||||
end
|
||||
|
||||
function actions.get_current_line()
|
||||
return state.get_global_key('current_line')
|
||||
-- TODO(1.0): Remove
|
||||
action_is_deprecated("get_current_line")
|
||||
return action_state.get_current_line()
|
||||
end
|
||||
|
||||
--- Get the current picker object for the prompt
|
||||
function actions.get_current_picker(prompt_bufnr)
|
||||
-- TODO(1.0): Remove
|
||||
action_is_deprecated("get_current_picker")
|
||||
return action_state.get_current_picker(prompt_bufnr)
|
||||
end
|
||||
|
||||
--- Move the selection to the next entry
|
||||
function actions.move_selection_next(prompt_bufnr)
|
||||
action_set.shift_selection(prompt_bufnr, 1)
|
||||
end
|
||||
|
||||
--- Move the selection to the previous entry
|
||||
function actions.move_selection_previous(prompt_bufnr)
|
||||
action_set.shift_selection(prompt_bufnr, -1)
|
||||
end
|
||||
|
||||
function actions.add_selection(prompt_bufnr)
|
||||
local current_picker = action_state.get_current_picker(prompt_bufnr)
|
||||
current_picker:add_selection(current_picker:get_selection_row())
|
||||
end
|
||||
|
||||
function actions.remove_selection(prompt_bufnr)
|
||||
local current_picker = action_state.get_current_picker(prompt_bufnr)
|
||||
current_picker:remove_selection(current_picker:get_selection_row())
|
||||
end
|
||||
|
||||
function actions.toggle_selection(prompt_bufnr)
|
||||
local current_picker = action_state.get_current_picker(prompt_bufnr)
|
||||
current_picker:toggle_selection(current_picker:get_selection_row())
|
||||
end
|
||||
|
||||
function actions.preview_scrolling_up(prompt_bufnr)
|
||||
actions.get_current_picker(prompt_bufnr).previewer:scroll_fn(-30)
|
||||
-- TODO: Make number configurable.
|
||||
action_state.get_current_picker(prompt_bufnr).previewer:scroll_fn(-30)
|
||||
end
|
||||
|
||||
function actions.preview_scrolling_down(prompt_bufnr)
|
||||
actions.get_current_picker(prompt_bufnr).previewer:scroll_fn(30)
|
||||
end
|
||||
|
||||
-- TODO: It seems sometimes we get bad styling.
|
||||
function actions._goto_file_selection(prompt_bufnr, command)
|
||||
local entry = actions.get_selected_entry(prompt_bufnr)
|
||||
|
||||
if not entry then
|
||||
print("[telescope] Nothing currently selected")
|
||||
return
|
||||
else
|
||||
local filename, row, col
|
||||
if entry.filename then
|
||||
filename = entry.path or entry.filename
|
||||
|
||||
-- TODO: Check for off-by-one
|
||||
row = entry.row or entry.lnum
|
||||
col = entry.col
|
||||
elseif not entry.bufnr then
|
||||
-- TODO: Might want to remove this and force people
|
||||
-- to put stuff into `filename`
|
||||
local value = entry.value
|
||||
if not value then
|
||||
print("Could not do anything with blank line...")
|
||||
return
|
||||
end
|
||||
|
||||
if type(value) == "table" then
|
||||
value = entry.display
|
||||
end
|
||||
|
||||
local sections = vim.split(value, ":")
|
||||
|
||||
filename = sections[1]
|
||||
row = tonumber(sections[2])
|
||||
col = tonumber(sections[3])
|
||||
end
|
||||
|
||||
local preview_win = state.get_status(prompt_bufnr).preview_win
|
||||
if preview_win then
|
||||
a.nvim_win_set_config(preview_win, {style = ''})
|
||||
end
|
||||
|
||||
local entry_bufnr = entry.bufnr
|
||||
|
||||
actions.close(prompt_bufnr)
|
||||
|
||||
if entry_bufnr then
|
||||
if command == 'edit' then
|
||||
vim.cmd(string.format(":buffer %d", entry_bufnr))
|
||||
elseif command == 'new' then
|
||||
vim.cmd(string.format(":sbuffer %d", entry_bufnr))
|
||||
elseif command == 'vnew' then
|
||||
vim.cmd(string.format(":vert sbuffer %d", entry_bufnr))
|
||||
elseif command == 'tabedit' then
|
||||
vim.cmd(string.format(":tab sb %d", entry_bufnr))
|
||||
end
|
||||
else
|
||||
filename = path.normalize(vim.fn.fnameescape(filename), vim.fn.getcwd())
|
||||
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
if filename ~= vim.api.nvim_buf_get_name(bufnr) then
|
||||
vim.cmd(string.format(":%s %s", command, filename))
|
||||
bufnr = vim.api.nvim_get_current_buf()
|
||||
a.nvim_buf_set_option(bufnr, "buflisted", true)
|
||||
end
|
||||
|
||||
if row and col then
|
||||
local ok, err_msg = pcall(a.nvim_win_set_cursor, 0, {row, col})
|
||||
if not ok then
|
||||
log.debug("Failed to move to cursor:", err_msg, row, col)
|
||||
end
|
||||
end
|
||||
end
|
||||
vim.api.nvim_command("doautocmd filetypedetect BufRead " .. vim.fn.fnameescape(filename))
|
||||
end
|
||||
-- TODO: Make number configurable.
|
||||
action_state.get_current_picker(prompt_bufnr).previewer:scroll_fn(30)
|
||||
end
|
||||
|
||||
function actions.center(_)
|
||||
vim.cmd(':normal! zz')
|
||||
end
|
||||
|
||||
function actions.goto_file_selection_edit(prompt_bufnr)
|
||||
actions._goto_file_selection(prompt_bufnr, "edit")
|
||||
function actions.select_default(prompt_bufnr)
|
||||
return action_set.select(prompt_bufnr, "default")
|
||||
end
|
||||
|
||||
function actions.goto_file_selection_split(prompt_bufnr)
|
||||
actions._goto_file_selection(prompt_bufnr, "new")
|
||||
function actions.select_horizontal(prompt_bufnr)
|
||||
return action_set.select(prompt_bufnr, "horizontal")
|
||||
end
|
||||
|
||||
function actions.goto_file_selection_vsplit(prompt_bufnr)
|
||||
actions._goto_file_selection(prompt_bufnr, "vnew")
|
||||
function actions.select_vertical(prompt_bufnr)
|
||||
return action_set.select(prompt_bufnr, "vertical")
|
||||
end
|
||||
|
||||
function actions.goto_file_selection_tabedit(prompt_bufnr)
|
||||
actions._goto_file_selection(prompt_bufnr, "tabedit")
|
||||
function actions.select_tab(prompt_bufnr)
|
||||
return action_set.select(prompt_bufnr, "tab")
|
||||
end
|
||||
|
||||
-- TODO: consider adding float!
|
||||
-- https://github.com/nvim-telescope/telescope.nvim/issues/365
|
||||
|
||||
function actions.file_edit(prompt_bufnr)
|
||||
return action_set.edit(prompt_bufnr, "edit")
|
||||
end
|
||||
|
||||
function actions.file_split(prompt_bufnr)
|
||||
return action_set.edit(prompt_bufnr, "new")
|
||||
end
|
||||
|
||||
function actions.file_vsplit(prompt_bufnr)
|
||||
return action_set.edit(prompt_bufnr, "vnew")
|
||||
end
|
||||
|
||||
function actions.file_tab(prompt_bufnr)
|
||||
return action_set.edit(prompt_bufnr, "tabedit")
|
||||
end
|
||||
|
||||
function actions.close_pum(_)
|
||||
@@ -168,7 +140,7 @@ function actions.close_pum(_)
|
||||
end
|
||||
|
||||
local do_close = function(prompt_bufnr, keepinsert)
|
||||
local picker = actions.get_current_picker(prompt_bufnr)
|
||||
local picker = action_state.get_current_picker(prompt_bufnr)
|
||||
local prompt_win = state.get_status(prompt_bufnr).prompt_win
|
||||
local original_win_id = picker.original_win_id
|
||||
|
||||
@@ -192,7 +164,7 @@ function actions.close(prompt_bufnr)
|
||||
end
|
||||
|
||||
actions.set_command_line = function(prompt_bufnr)
|
||||
local entry = actions.get_selected_entry(prompt_bufnr)
|
||||
local entry = action_state.get_selected_entry(prompt_bufnr)
|
||||
|
||||
actions.close(prompt_bufnr)
|
||||
vim.fn.histadd("cmd", entry.value)
|
||||
@@ -200,8 +172,8 @@ actions.set_command_line = function(prompt_bufnr)
|
||||
end
|
||||
|
||||
actions.edit_register = function(prompt_bufnr)
|
||||
local entry = actions.get_selected_entry(prompt_bufnr)
|
||||
local picker = actions.get_current_picker(prompt_bufnr)
|
||||
local entry = action_state.get_selected_entry(prompt_bufnr)
|
||||
local picker = action_state.get_current_picker(prompt_bufnr)
|
||||
|
||||
vim.fn.inputsave()
|
||||
local updated_value = vim.fn.input("Edit [" .. entry.value .. "] ❯ ", entry.content)
|
||||
@@ -222,7 +194,7 @@ actions.edit_register = function(prompt_bufnr)
|
||||
end
|
||||
|
||||
actions.paste_register = function(prompt_bufnr)
|
||||
local entry = actions.get_selected_entry(prompt_bufnr)
|
||||
local entry = action_state.get_selected_entry(prompt_bufnr)
|
||||
|
||||
actions.close(prompt_bufnr)
|
||||
|
||||
@@ -239,21 +211,21 @@ actions.paste_register = function(prompt_bufnr)
|
||||
end
|
||||
|
||||
actions.run_builtin = function(prompt_bufnr)
|
||||
local entry = actions.get_selected_entry(prompt_bufnr)
|
||||
local entry = action_state.get_selected_entry(prompt_bufnr)
|
||||
|
||||
do_close(prompt_bufnr, true)
|
||||
require('telescope.builtin')[entry.text]()
|
||||
end
|
||||
|
||||
actions.insert_symbol = function(prompt_bufnr)
|
||||
local selection = actions.get_selected_entry()
|
||||
local selection = action_state.get_selected_entry()
|
||||
actions.close(prompt_bufnr)
|
||||
vim.api.nvim_put({selection.value[1]}, '', true, true)
|
||||
end
|
||||
|
||||
-- TODO: Think about how to do this.
|
||||
actions.insert_value = function(prompt_bufnr)
|
||||
local entry = actions.get_selected_entry(prompt_bufnr)
|
||||
local entry = action_state.get_selected_entry(prompt_bufnr)
|
||||
|
||||
vim.schedule(function()
|
||||
actions.close(prompt_bufnr)
|
||||
@@ -263,15 +235,15 @@ actions.insert_value = function(prompt_bufnr)
|
||||
end
|
||||
|
||||
actions.git_checkout = function(prompt_bufnr)
|
||||
local cwd = actions.get_current_picker(prompt_bufnr).cwd
|
||||
local selection = actions.get_selected_entry()
|
||||
local cwd = action_state.get_current_picker(prompt_bufnr).cwd
|
||||
local selection = action_state.get_selected_entry()
|
||||
actions.close(prompt_bufnr)
|
||||
utils.get_os_command_output({ 'git', 'checkout', selection.value }, cwd)
|
||||
end
|
||||
|
||||
actions.git_staging_toggle = function(prompt_bufnr)
|
||||
local cwd = actions.get_current_picker(prompt_bufnr).cwd
|
||||
local selection = actions.get_selected_entry()
|
||||
local cwd = action_state.get_current_picker(prompt_bufnr).cwd
|
||||
local selection = action_state.get_selected_entry()
|
||||
|
||||
-- If parts of the file are staged and unstaged at the same time, stage
|
||||
-- changes. Else toggle between staged and unstaged if the file is tracked,
|
||||
@@ -296,7 +268,7 @@ local entry_to_qf = function(entry)
|
||||
end
|
||||
|
||||
actions.send_selected_to_qflist = function(prompt_bufnr)
|
||||
local picker = actions.get_current_picker(prompt_bufnr)
|
||||
local picker = action_state.get_current_picker(prompt_bufnr)
|
||||
|
||||
local qf_entries = {}
|
||||
for entry in pairs(picker.multi_select) do
|
||||
@@ -309,7 +281,7 @@ actions.send_selected_to_qflist = function(prompt_bufnr)
|
||||
end
|
||||
|
||||
actions.send_to_qflist = function(prompt_bufnr)
|
||||
local picker = actions.get_current_picker(prompt_bufnr)
|
||||
local picker = action_state.get_current_picker(prompt_bufnr)
|
||||
local manager = picker.manager
|
||||
|
||||
local qf_entries = {}
|
||||
|
||||
@@ -1,23 +1,41 @@
|
||||
local action_mt = {}
|
||||
|
||||
--- Checks all replacement combinations to determine which function to run.
|
||||
--- If no replacement can be found, then it will run the original function
|
||||
local run_replace_or_original = function(replacements, original_func, ...)
|
||||
for _, replacement_map in ipairs(replacements or {}) do
|
||||
for condition, replacement in pairs(replacement_map) do
|
||||
if condition == true or condition(...) then
|
||||
return replacement(...)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return original_func(...)
|
||||
end
|
||||
|
||||
action_mt.create = function(mod)
|
||||
local mt = {
|
||||
__call = function(t, ...)
|
||||
local values = {}
|
||||
for _, v in ipairs(t) do
|
||||
local func = t._replacements[v] or mod[v]
|
||||
|
||||
if t._pre[v] then
|
||||
t._pre[v](...)
|
||||
for _, action_name in ipairs(t) do
|
||||
if t._pre[action_name] then
|
||||
t._pre[action_name](...)
|
||||
end
|
||||
|
||||
local result = {func(...)}
|
||||
local result = {
|
||||
run_replace_or_original(
|
||||
t._replacements[action_name],
|
||||
mod[action_name],
|
||||
...
|
||||
)
|
||||
}
|
||||
for _, res in ipairs(result) do
|
||||
table.insert(values, res)
|
||||
end
|
||||
|
||||
if t._post[v] then
|
||||
t._post[v](...)
|
||||
if t._post[action_name] then
|
||||
t._post[action_name](...)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -54,8 +72,33 @@ action_mt.create = function(mod)
|
||||
function mt:replace(v)
|
||||
assert(#self == 1, "Cannot replace an already combined action")
|
||||
|
||||
return self:replace_map { [true] = v }
|
||||
end
|
||||
|
||||
function mt:replace_if(condition, replacement)
|
||||
assert(#self == 1, "Cannot replace an already combined action")
|
||||
|
||||
return self:replace_map { [condition] = replacement }
|
||||
end
|
||||
|
||||
--- Replace table with
|
||||
-- Example:
|
||||
--
|
||||
-- actions.select:replace_map {
|
||||
-- [function() return filetype == 'lua' end] = actions.file_split,
|
||||
-- [function() return filetype == 'other' end] = actions.file_split_edit,
|
||||
-- }
|
||||
function mt:replace_map(tbl)
|
||||
assert(#self == 1, "Cannot replace an already combined action")
|
||||
|
||||
local action_name = self[1]
|
||||
mt._replacements[action_name] = v
|
||||
|
||||
if not mt._replacements[action_name] then
|
||||
mt._replacements[action_name] = {}
|
||||
end
|
||||
|
||||
table.insert(mt._replacements[action_name], 1, tbl)
|
||||
return self
|
||||
end
|
||||
|
||||
function mt:enhance(opts)
|
||||
@@ -69,6 +112,8 @@ action_mt.create = function(mod)
|
||||
if opts.post then
|
||||
mt._post[action_name] = opts.post
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
return mt
|
||||
@@ -81,7 +126,9 @@ end
|
||||
action_mt.transform_mod = function(mod)
|
||||
local mt = action_mt.create(mod)
|
||||
|
||||
local redirect = {}
|
||||
-- Pass the metatable of the module if applicable.
|
||||
-- This allows for custom errors, lookups, etc.
|
||||
local redirect = setmetatable({}, getmetatable(mod) or {})
|
||||
|
||||
for k, _ in pairs(mod) do
|
||||
redirect[k] = action_mt.transform(k, mt)
|
||||
|
||||
125
lua/telescope/actions/set.lua
Normal file
125
lua/telescope/actions/set.lua
Normal file
@@ -0,0 +1,125 @@
|
||||
local a = vim.api
|
||||
|
||||
local log = require('telescope.log')
|
||||
local path = require('telescope.path')
|
||||
local state = require('telescope.state')
|
||||
|
||||
local action_state = require('telescope.actions.state')
|
||||
|
||||
local transform_mod = require('telescope.actions.mt').transform_mod
|
||||
|
||||
--- Telescope action sets are used to provide an interface for managing
|
||||
--- actions that all primarily do the same thing, but with slight tweaks.
|
||||
---
|
||||
--- For example, when editing files you may want it in the current split,
|
||||
--- a vertical split, etc. Instead of making users have to overwrite EACH
|
||||
--- of those every time they want to change this behavior, they can instead
|
||||
--- replace the `set` itself and then it will work great and they're done.
|
||||
local set = setmetatable({}, {
|
||||
__index = function(_, k)
|
||||
error("'telescope.actions.set' does not have a value: " .. tostring(k))
|
||||
end
|
||||
})
|
||||
|
||||
--- Move the current selection of a picker {change} rows.
|
||||
--- Handles not overflowing / underflowing the list.
|
||||
---@param prompt_bufnr number: The prompt bufnr
|
||||
---@param change number: The amount to shift the selection by
|
||||
set.shift_selection = function(prompt_bufnr, change)
|
||||
action_state.get_current_picker(prompt_bufnr):move_selection(change)
|
||||
end
|
||||
|
||||
--- Select the current entry. This is the action set to overwrite common
|
||||
--- actions by the user.
|
||||
---
|
||||
--- By default maps to editing a file.
|
||||
---@param prompt_bufnr number: The prompt bufnr
|
||||
---@param type string: The type of selection to make
|
||||
-- Valid types include: "default", "horizontal", "vertical", "tabedit"
|
||||
set.select = function(prompt_bufnr, type)
|
||||
return set.edit(prompt_bufnr, action_state.select_key_to_edit_key(type))
|
||||
end
|
||||
|
||||
--- Edit a file based on the current selection.
|
||||
---@param prompt_bufnr number: The prompt bufnr
|
||||
---@param command string: The command to use to open the file.
|
||||
-- Valid commands include: "edit", "new", "vedit", "tabedit"
|
||||
set.edit = function(prompt_bufnr, command)
|
||||
local entry = action_state.get_selected_entry()
|
||||
|
||||
if not entry then
|
||||
print("[telescope] Nothing currently selected")
|
||||
return
|
||||
else
|
||||
local filename, row, col
|
||||
if entry.filename then
|
||||
filename = entry.path or entry.filename
|
||||
|
||||
-- TODO: Check for off-by-one
|
||||
row = entry.row or entry.lnum
|
||||
col = entry.col
|
||||
elseif not entry.bufnr then
|
||||
-- TODO: Might want to remove this and force people
|
||||
-- to put stuff into `filename`
|
||||
local value = entry.value
|
||||
if not value then
|
||||
print("Could not do anything with blank line...")
|
||||
return
|
||||
end
|
||||
|
||||
if type(value) == "table" then
|
||||
value = entry.display
|
||||
end
|
||||
|
||||
local sections = vim.split(value, ":")
|
||||
|
||||
filename = sections[1]
|
||||
row = tonumber(sections[2])
|
||||
col = tonumber(sections[3])
|
||||
end
|
||||
|
||||
local preview_win = state.get_status(prompt_bufnr).preview_win
|
||||
if preview_win then
|
||||
a.nvim_win_set_config(preview_win, {style = ''})
|
||||
end
|
||||
|
||||
local entry_bufnr = entry.bufnr
|
||||
|
||||
require('telescope.actions').close(prompt_bufnr)
|
||||
|
||||
if entry_bufnr then
|
||||
if command == 'edit' then
|
||||
vim.cmd(string.format(":buffer %d", entry_bufnr))
|
||||
elseif command == 'new' then
|
||||
vim.cmd(string.format(":sbuffer %d", entry_bufnr))
|
||||
elseif command == 'vnew' then
|
||||
vim.cmd(string.format(":vert sbuffer %d", entry_bufnr))
|
||||
elseif command == 'tabedit' then
|
||||
vim.cmd(string.format(":tab sb %d", entry_bufnr))
|
||||
end
|
||||
else
|
||||
filename = path.normalize(vim.fn.fnameescape(filename), vim.fn.getcwd())
|
||||
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
if filename ~= vim.api.nvim_buf_get_name(bufnr) then
|
||||
vim.cmd(string.format(":%s %s", command, filename))
|
||||
bufnr = vim.api.nvim_get_current_buf()
|
||||
a.nvim_buf_set_option(bufnr, "buflisted", true)
|
||||
end
|
||||
|
||||
if row and col then
|
||||
local ok, err_msg = pcall(a.nvim_win_set_cursor, 0, {row, col})
|
||||
if not ok then
|
||||
log.debug("Failed to move to cursor:", err_msg, row, col)
|
||||
end
|
||||
end
|
||||
end
|
||||
vim.api.nvim_command("doautocmd filetypedetect BufRead " .. vim.fn.fnameescape(filename))
|
||||
end
|
||||
end
|
||||
|
||||
-- ==================================================
|
||||
-- Transforms modules and sets the corect metatables.
|
||||
-- ==================================================
|
||||
set = transform_mod(set)
|
||||
return set
|
||||
30
lua/telescope/actions/state.lua
Normal file
30
lua/telescope/actions/state.lua
Normal file
@@ -0,0 +1,30 @@
|
||||
local global_state = require('telescope.state')
|
||||
|
||||
local action_state = {}
|
||||
|
||||
--- Get the current entry
|
||||
function action_state.get_selected_entry()
|
||||
return global_state.get_global_key('selected_entry')
|
||||
end
|
||||
|
||||
--- Gets the current line
|
||||
function action_state.get_current_line()
|
||||
return global_state.get_global_key('current_line')
|
||||
end
|
||||
|
||||
--- Gets the current picker
|
||||
function action_state.get_current_picker(prompt_bufnr)
|
||||
return global_state.get_status(prompt_bufnr).picker
|
||||
end
|
||||
|
||||
local select_to_edit_map = {
|
||||
default = "edit",
|
||||
horizontal = "new",
|
||||
vertical = "vnew",
|
||||
tab = "tabedit",
|
||||
}
|
||||
function action_state.select_key_to_edit_key(type)
|
||||
return select_to_edit_map[type]
|
||||
end
|
||||
|
||||
return action_state
|
||||
@@ -1,4 +1,5 @@
|
||||
local actions = require('telescope.actions')
|
||||
local action_state = require('telescope.actions.state')
|
||||
local action_set = require('telescope.actions.set')
|
||||
local finders = require('telescope.finders')
|
||||
local make_entry = require('telescope.make_entry')
|
||||
local pickers = require('telescope.pickers')
|
||||
@@ -256,9 +257,9 @@ files.current_buffer_fuzzy_find = function(opts)
|
||||
},
|
||||
sorter = conf.generic_sorter(opts),
|
||||
attach_mappings = function()
|
||||
actions._goto_file_selection:enhance {
|
||||
action_set.select:enhance {
|
||||
post = function()
|
||||
local selection = actions.get_selected_entry()
|
||||
local selection = action_state.get_selected_entry()
|
||||
vim.api.nvim_win_set_cursor(0, {selection.lnum, 0})
|
||||
end,
|
||||
}
|
||||
@@ -292,9 +293,9 @@ files.tags = function(opts)
|
||||
previewer = previewers.ctags.new(opts),
|
||||
sorter = conf.generic_sorter(opts),
|
||||
attach_mappings = function()
|
||||
actions._goto_file_selection:enhance {
|
||||
action_set.select:enhance {
|
||||
post = function()
|
||||
local selection = actions.get_selected_entry()
|
||||
local selection = action_set.get_selected_entry()
|
||||
|
||||
if selection.scode then
|
||||
local scode = string.gsub(selection.scode, '[$]$', '')
|
||||
|
||||
@@ -47,7 +47,7 @@ git.commits = function(opts)
|
||||
previewer = previewers.git_commit_diff.new(opts),
|
||||
sorter = conf.file_sorter(opts),
|
||||
attach_mappings = function()
|
||||
actions.goto_file_selection_edit:replace(actions.git_checkout)
|
||||
actions.select_default:replace(actions.git_checkout)
|
||||
return true
|
||||
end
|
||||
}):find()
|
||||
@@ -67,7 +67,7 @@ git.bcommits = function(opts)
|
||||
previewer = previewers.git_commit_diff.new(opts),
|
||||
sorter = conf.file_sorter(opts),
|
||||
attach_mappings = function()
|
||||
actions.goto_file_selection_edit:replace(actions.git_checkout)
|
||||
actions.select_default:replace(actions.git_checkout)
|
||||
return true
|
||||
end
|
||||
}):find()
|
||||
@@ -101,7 +101,7 @@ git.branches = function(opts)
|
||||
previewer = previewers.git_branch_log.new(opts),
|
||||
sorter = conf.file_sorter(opts),
|
||||
attach_mappings = function()
|
||||
actions.goto_file_selection_edit:replace(actions.git_checkout)
|
||||
actions.select_default:replace(actions.git_checkout)
|
||||
return true
|
||||
end
|
||||
}):find()
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
local actions = require('telescope.actions')
|
||||
local action_set = require('telescope.actions.set')
|
||||
local action_state = require('telescope.actions.state')
|
||||
local finders = require('telescope.finders')
|
||||
local make_entry = require('telescope.make_entry')
|
||||
local path = require('telescope.path')
|
||||
@@ -47,7 +49,7 @@ internal.builtin = function(opts)
|
||||
previewer = previewers.builtin.new(opts),
|
||||
sorter = conf.generic_sorter(opts),
|
||||
attach_mappings = function(_)
|
||||
actions.goto_file_selection_edit:replace(actions.run_builtin)
|
||||
actions.select_default:replace(actions.run_builtin)
|
||||
return true
|
||||
end
|
||||
}):find()
|
||||
@@ -82,8 +84,8 @@ internal.planets = function(opts)
|
||||
previewer = previewers.cat.new(opts),
|
||||
sorter = conf.generic_sorter(opts),
|
||||
attach_mappings = function(prompt_bufnr)
|
||||
actions.goto_file_selection_edit:replace(function()
|
||||
local selection = actions.get_selected_entry()
|
||||
actions.select_default:replace(function()
|
||||
local selection = action_state.get_selected_entry()
|
||||
actions.close(prompt_bufnr)
|
||||
|
||||
print("Enjoy astronomy! You viewed:", selection.display)
|
||||
@@ -137,7 +139,7 @@ internal.symbols = function(opts)
|
||||
},
|
||||
sorter = conf.generic_sorter(opts),
|
||||
attach_mappings = function(_)
|
||||
actions.goto_file_selection_edit:replace(actions.insert_symbol)
|
||||
actions.select_default:replace(actions.insert_symbol)
|
||||
return true
|
||||
end
|
||||
}):find()
|
||||
@@ -168,8 +170,8 @@ internal.commands = function(opts)
|
||||
},
|
||||
sorter = conf.generic_sorter(opts),
|
||||
attach_mappings = function(prompt_bufnr)
|
||||
actions.goto_file_selection_edit:replace(function()
|
||||
local selection = actions.get_selected_entry()
|
||||
actions.select_default:replace(function()
|
||||
local selection = action_state.get_selected_entry()
|
||||
actions.close(prompt_bufnr)
|
||||
local val = selection.value
|
||||
local cmd = string.format([[:%s ]], val.name)
|
||||
@@ -285,8 +287,8 @@ internal.vim_options = function(opts)
|
||||
-- previewer = previewers.help.new(opts),
|
||||
sorter = conf.generic_sorter(opts),
|
||||
attach_mappings = function()
|
||||
actions.goto_file_selection_edit:replace(function()
|
||||
local selection = actions.get_selected_entry()
|
||||
actions.select_default:replace(function()
|
||||
local selection = action_state.get_selected_entry()
|
||||
local esc = ""
|
||||
|
||||
if vim.fn.mode() == "i" then
|
||||
@@ -411,14 +413,14 @@ internal.help_tags = function(opts)
|
||||
previewer = previewers.help.new(opts),
|
||||
sorter = conf.generic_sorter(opts),
|
||||
attach_mappings = function(prompt_bufnr)
|
||||
actions._goto_file_selection:replace(function(_, cmd)
|
||||
local selection = actions.get_selected_entry()
|
||||
action_set.select:replace(function(_, cmd)
|
||||
local selection = action_state.get_selected_entry()
|
||||
actions.close(prompt_bufnr)
|
||||
if cmd == 'edit' or cmd == 'new' then
|
||||
if cmd == 'default' or cmd == 'horizontal' then
|
||||
vim.cmd('help ' .. selection.value)
|
||||
elseif cmd == 'vnew' then
|
||||
elseif cmd == 'vertical' then
|
||||
vim.cmd('vert bo help ' .. selection.value)
|
||||
elseif cmd == 'tabedit' then
|
||||
elseif cmd == 'tab' then
|
||||
vim.cmd('tab help ' .. selection.value)
|
||||
end
|
||||
end)
|
||||
@@ -443,16 +445,16 @@ internal.man_pages = function(opts)
|
||||
previewer = previewers.man.new(opts),
|
||||
sorter = conf.generic_sorter(opts),
|
||||
attach_mappings = function(prompt_bufnr)
|
||||
actions._goto_file_selection:replace(function(_, cmd)
|
||||
local selection = actions.get_selected_entry()
|
||||
action_set.select:replace(function(_, cmd)
|
||||
local selection = action_state.get_selected_entry()
|
||||
local args = selection.section .. ' ' .. selection.value
|
||||
|
||||
actions.close(prompt_bufnr)
|
||||
if cmd == 'edit' or cmd == 'new' then
|
||||
if cmd == 'default' or cmd == 'horizontal' then
|
||||
vim.cmd('Man ' .. args)
|
||||
elseif cmd == 'vnew' then
|
||||
elseif cmd == 'vertical' then
|
||||
vim.cmd('vert bo Man ' .. args)
|
||||
elseif cmd == 'tabedit' then
|
||||
elseif cmd == 'tab' then
|
||||
vim.cmd('tab Man ' .. args)
|
||||
end
|
||||
end)
|
||||
@@ -487,8 +489,8 @@ internal.reloader = function(opts)
|
||||
sorter = conf.generic_sorter(opts),
|
||||
|
||||
attach_mappings = function(prompt_bufnr)
|
||||
actions.goto_file_selection_edit:replace(function()
|
||||
local selection = actions.get_selected_entry()
|
||||
actions.select_default:replace(function()
|
||||
local selection = action_state.get_selected_entry()
|
||||
|
||||
actions.close(prompt_bufnr)
|
||||
require('plenary.reload').reload_module(selection.value)
|
||||
@@ -566,8 +568,8 @@ internal.colorscheme = function(opts)
|
||||
-- TODO: better preview?
|
||||
sorter = conf.generic_sorter(opts),
|
||||
attach_mappings = function(prompt_bufnr)
|
||||
actions.goto_file_selection_edit:replace(function()
|
||||
local selection = actions.get_selected_entry()
|
||||
actions.select_default:replace(function()
|
||||
local selection = action_state.get_selected_entry()
|
||||
|
||||
actions.close(prompt_bufnr)
|
||||
vim.cmd("colorscheme " .. selection.value)
|
||||
@@ -618,7 +620,7 @@ internal.registers = function(opts)
|
||||
-- use levenshtein as n-gram doesn't support <2 char matches
|
||||
sorter = sorters.get_levenshtein_sorter(),
|
||||
attach_mappings = function(_, map)
|
||||
actions.goto_file_selection_edit:replace(actions.paste_register)
|
||||
actions.select_default:replace(actions.paste_register)
|
||||
map('i', '<C-e>', actions.edit_register)
|
||||
|
||||
return true
|
||||
@@ -657,8 +659,8 @@ internal.keymaps = function(opts)
|
||||
},
|
||||
sorter = conf.generic_sorter(opts),
|
||||
attach_mappings = function(prompt_bufnr)
|
||||
actions.goto_file_selection_edit:replace(function()
|
||||
local selection = actions.get_selected_entry()
|
||||
actions.select_default:replace(function()
|
||||
local selection = action_state.get_selected_entry()
|
||||
vim.api.nvim_feedkeys(
|
||||
vim.api.nvim_replace_termcodes(selection.value.lhs, true, false, true),
|
||||
"t", true)
|
||||
@@ -679,8 +681,8 @@ internal.filetypes = function(opts)
|
||||
},
|
||||
sorter = conf.generic_sorter(opts),
|
||||
attach_mappings = function(prompt_bufnr)
|
||||
actions.goto_file_selection_edit:replace(function()
|
||||
local selection = actions.get_selected_entry()
|
||||
actions.select_default:replace(function()
|
||||
local selection = action_state.get_selected_entry()
|
||||
actions.close(prompt_bufnr)
|
||||
vim.cmd('setfiletype ' .. selection[1])
|
||||
end)
|
||||
@@ -700,8 +702,8 @@ internal.highlights = function(opts)
|
||||
},
|
||||
sorter = conf.generic_sorter(opts),
|
||||
attach_mappings = function(prompt_bufnr)
|
||||
actions.goto_file_selection_edit:replace(function()
|
||||
local selection = actions.get_selected_entry()
|
||||
actions.select_default:replace(function()
|
||||
local selection = action_state.get_selected_entry()
|
||||
actions.close(prompt_bufnr)
|
||||
vim.cmd('hi ' .. selection.value)
|
||||
end)
|
||||
@@ -791,10 +793,10 @@ internal.autocommands = function(opts)
|
||||
previewer = previewers.autocommands.new(opts),
|
||||
sorter = conf.generic_sorter(opts),
|
||||
attach_mappings = function(prompt_bufnr)
|
||||
actions._goto_file_selection:replace(function(_, vim_cmd)
|
||||
local selection = actions.get_selected_entry()
|
||||
action_set.select:replace(function(_, type)
|
||||
local selection = action_state.get_selected_entry()
|
||||
actions.close(prompt_bufnr)
|
||||
vim.cmd(vim_cmd .. ' ' .. selection.value)
|
||||
vim.cmd(action_state.select_key_to_edit_key(type) .. ' ' .. selection.value)
|
||||
end)
|
||||
|
||||
return true
|
||||
@@ -815,8 +817,8 @@ internal.spell_suggest = function(opts)
|
||||
},
|
||||
sorter = conf.generic_sorter(opts),
|
||||
attach_mappings = function(prompt_bufnr)
|
||||
actions.goto_file_selection_edit:replace(function()
|
||||
local selection = actions.get_selected_entry()
|
||||
actions.select_default:replace(function()
|
||||
local selection = action_state.get_selected_entry()
|
||||
actions.close(prompt_bufnr)
|
||||
vim.cmd('normal! ciw' .. selection[1])
|
||||
vim.cmd('stopinsert')
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
local actions = require('telescope.actions')
|
||||
local action_state = require('telescope.actions.state')
|
||||
local finders = require('telescope.finders')
|
||||
local make_entry = require('telescope.make_entry')
|
||||
local pickers = require('telescope.pickers')
|
||||
@@ -116,8 +117,8 @@ lsp.code_actions = function(opts)
|
||||
end
|
||||
},
|
||||
attach_mappings = function(prompt_bufnr)
|
||||
actions.goto_file_selection_edit:replace(function()
|
||||
local selection = actions.get_selected_entry()
|
||||
actions.select_default:replace(function()
|
||||
local selection = action_state.get_selected_entry()
|
||||
actions.close(prompt_bufnr)
|
||||
local val = selection.value
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ function config.set_defaults(defaults)
|
||||
-- Otherwise, just set the mapping to the function that you want it to be.
|
||||
--
|
||||
-- ...,
|
||||
-- ["<C-i>"] = actions.goto_file_selection_split
|
||||
-- ["<C-i>"] = actions.select_default
|
||||
-- ...,
|
||||
--
|
||||
set("mappings", {})
|
||||
|
||||
@@ -16,10 +16,10 @@ mappings.default_mappings = config.values.default_mappings or {
|
||||
["<Down>"] = actions.move_selection_next,
|
||||
["<Up>"] = actions.move_selection_previous,
|
||||
|
||||
["<CR>"] = actions.goto_file_selection_edit + actions.center,
|
||||
["<C-x>"] = actions.goto_file_selection_split,
|
||||
["<C-v>"] = actions.goto_file_selection_vsplit,
|
||||
["<C-t>"] = actions.goto_file_selection_tabedit,
|
||||
["<CR>"] = actions.select_default + actions.center,
|
||||
["<C-x>"] = actions.select_horizontal,
|
||||
["<C-v>"] = actions.select_vertical,
|
||||
["<C-t>"] = actions.select_tab,
|
||||
|
||||
["<C-u>"] = actions.preview_scrolling_up,
|
||||
["<C-d>"] = actions.preview_scrolling_down,
|
||||
@@ -30,10 +30,10 @@ mappings.default_mappings = config.values.default_mappings or {
|
||||
|
||||
n = {
|
||||
["<esc>"] = actions.close,
|
||||
["<CR>"] = actions.goto_file_selection_edit + actions.center,
|
||||
["<C-x>"] = actions.goto_file_selection_split,
|
||||
["<C-v>"] = actions.goto_file_selection_vsplit,
|
||||
["<C-t>"] = actions.goto_file_selection_tabedit,
|
||||
["<CR>"] = actions.select_default + actions.center,
|
||||
["<C-x>"] = actions.select_horizontal,
|
||||
["<C-v>"] = actions.select_vertical,
|
||||
["<C-t>"] = actions.select_tab,
|
||||
|
||||
-- TODO: This would be weird if we switch the ordering.
|
||||
["j"] = actions.move_selection_next,
|
||||
@@ -153,8 +153,19 @@ mappings.apply_keymap = function(prompt_bufnr, attach_mappings, buffer_keymap)
|
||||
telescope_map(prompt_bufnr, mode, key_bind, key_func, opts)
|
||||
end
|
||||
|
||||
if attach_mappings and not attach_mappings(prompt_bufnr, map) then
|
||||
return
|
||||
if attach_mappings then
|
||||
local attach_results = attach_mappings(prompt_bufnr, map)
|
||||
|
||||
if attach_results == nil then
|
||||
error(
|
||||
"Attach mappings must always return a value. `true` means use default mappings, "
|
||||
.. "`false` means only use attached mappings"
|
||||
)
|
||||
end
|
||||
|
||||
if not attach_results then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
for mode, mode_map in pairs(buffer_keymap or {}) do
|
||||
|
||||
@@ -4,6 +4,7 @@ local popup = require('popup')
|
||||
require('telescope')
|
||||
|
||||
local actions = require('telescope.actions')
|
||||
local action_set = require('telescope.actions.set')
|
||||
local config = require('telescope.config')
|
||||
local debounce = require('telescope.debounce')
|
||||
local resolve = require('telescope.config.resolve')
|
||||
@@ -21,25 +22,6 @@ local EntryManager = require('telescope.entry_manager')
|
||||
|
||||
local get_default = utils.get_default
|
||||
|
||||
-- TODO: Make this work with deep extend I think.
|
||||
local extend = function(opts, defaults)
|
||||
local result = {}
|
||||
|
||||
for k, v in pairs(opts or {}) do
|
||||
assert(type(k) == 'string', "Should be string, opts")
|
||||
result[k] = v
|
||||
end
|
||||
|
||||
for k, v in pairs(defaults or {}) do
|
||||
if result[k] == nil then
|
||||
assert(type(k) == 'string', "Should be string, defaults")
|
||||
result[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
local ns_telescope_matching = a.nvim_create_namespace('telescope_matching')
|
||||
local ns_telescope_prompt = a.nvim_create_namespace('telescope_prompt')
|
||||
local ns_telescope_prompt_prefix = a.nvim_create_namespace('telescope_prompt_prefix')
|
||||
@@ -62,7 +44,10 @@ function Picker:new(opts)
|
||||
end
|
||||
|
||||
-- Reset actions for any replaced / enhanced actions.
|
||||
-- TODO: Think about how we could remember to NOT have to do this...
|
||||
-- I almost forgot once already, cause I'm not smart enough to always do it.
|
||||
actions._clear()
|
||||
action_set._clear()
|
||||
|
||||
local layout_strategy = get_default(opts.layout_strategy, config.values.layout_strategy)
|
||||
|
||||
@@ -1016,7 +1001,31 @@ end
|
||||
|
||||
|
||||
pickers.new = function(opts, defaults)
|
||||
return Picker:new(extend(opts, defaults))
|
||||
local result = {}
|
||||
|
||||
for k, v in pairs(opts or {}) do
|
||||
assert(type(k) == 'string', "Should be string, opts")
|
||||
result[k] = v
|
||||
end
|
||||
|
||||
for k, v in pairs(defaults or {}) do
|
||||
if result[k] == nil then
|
||||
assert(type(k) == 'string', "Should be string, defaults")
|
||||
result[k] = v
|
||||
else
|
||||
-- For attach mappings, we want people to be able to pass in another function
|
||||
-- and apply their mappings after we've applied our defaults.
|
||||
if k == 'attach_mappings' then
|
||||
local opt_value = result[k]
|
||||
result[k] = function(...)
|
||||
v(...)
|
||||
return opt_value(...)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return Picker:new(result)
|
||||
end
|
||||
|
||||
function pickers.on_close_prompt(prompt_bufnr)
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
local actions = require('telescope.actions')
|
||||
local action_set = require('telescope.actions.set')
|
||||
|
||||
local transform_mod = require('telescope.actions.mt').transform_mod
|
||||
|
||||
local eq = function(a, b)
|
||||
@@ -51,6 +54,69 @@ describe('actions', function()
|
||||
eq("x", a.x())
|
||||
end)
|
||||
|
||||
it('allows overriding an action only in specific cases with if', function()
|
||||
local a = transform_mod {
|
||||
x = function(e) return e * 10 end,
|
||||
y = function() return "y" end,
|
||||
}
|
||||
|
||||
-- actions.file_goto_selection_edit:replace(...)
|
||||
a.x:replace_if(
|
||||
function(e) return e > 0 end,
|
||||
function(e) return (e / 10) end
|
||||
)
|
||||
eq(-100, a.x(-10))
|
||||
eq(10, a.x(100))
|
||||
eq(1, a.x(10))
|
||||
|
||||
a._clear()
|
||||
eq(100, a.x(10))
|
||||
end)
|
||||
|
||||
it('allows overriding an action only in specific cases with mod', function()
|
||||
local a = transform_mod {
|
||||
x = function(e) return e * 10 end,
|
||||
y = function() return "y" end,
|
||||
}
|
||||
|
||||
-- actions.file_goto_selection_edit:replace(...)
|
||||
a.x:replace_map {
|
||||
[function(e) return e > 0 end] = function(e) return (e / 10) end,
|
||||
[function(e) return e == 0 end] = function(e) return (e + 10) end,
|
||||
}
|
||||
|
||||
eq(-100, a.x(-10))
|
||||
eq(10, a.x(100))
|
||||
eq(1, a.x(10))
|
||||
eq(10, a.x(0))
|
||||
|
||||
a._clear()
|
||||
eq(100, a.x(10))
|
||||
end)
|
||||
|
||||
it('continuous replacement', function()
|
||||
local a = transform_mod {
|
||||
x = function() return "cleared" end,
|
||||
y = function() return "y" end,
|
||||
}
|
||||
|
||||
-- Replace original, which becomes new fallback
|
||||
a.x:replace(function() return "negative" end)
|
||||
|
||||
-- actions.file_goto_selection_edit:replace(...)
|
||||
a.x:replace_map {
|
||||
[function(e) return e > 0 end] = function(e) return "positive" end,
|
||||
[function(e) return e == 0 end] = function(e) return "zero" end,
|
||||
}
|
||||
|
||||
eq("positive", a.x(10))
|
||||
eq("zero" , a.x(0))
|
||||
eq("negative", a.x(-10))
|
||||
|
||||
a._clear()
|
||||
eq("cleared", a.x(10))
|
||||
end)
|
||||
|
||||
it('enhance.pre', function()
|
||||
local a = transform_mod {
|
||||
x = function() return "x" end,
|
||||
@@ -159,4 +225,27 @@ describe('actions', function()
|
||||
a.x:replace(function(bufnr) return string.format("modified: %s", bufnr) end)
|
||||
eq("modified: 5", a.x(5))
|
||||
end)
|
||||
|
||||
describe('action_set', function()
|
||||
it('can replace `action_set.edit`', function()
|
||||
action_set.edit:replace(function(_, arg) return "replaced:" .. arg end)
|
||||
eq("replaced:edit", actions.file_edit())
|
||||
eq("replaced:vnew", actions.file_vsplit())
|
||||
end)
|
||||
|
||||
it('handles backwards compat with select and edit files', function()
|
||||
-- Reproduce steps:
|
||||
-- In config, we have { ["<CR>"] = actions.select, ... }
|
||||
-- In caller, we have actions._goto:replace(...)
|
||||
-- Person calls `select`, does not see update
|
||||
action_set.edit:replace(function(_, arg) return "default_to_edit:" .. arg end)
|
||||
eq("default_to_edit:edit", actions.select_default())
|
||||
|
||||
action_set.select:replace(function(_, arg) return "override_with_select:" .. arg end)
|
||||
eq("override_with_select:default", actions.select_default())
|
||||
|
||||
-- Sometimes you might want to change the default selection...
|
||||
-- but you don't want to prohibit the ability to edit the code...
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
@@ -1,202 +1,205 @@
|
||||
local assert = require('luassert')
|
||||
local picker = require('telescope.pickers')
|
||||
|
||||
local log = require('telescope.log')
|
||||
log.level = 'info'
|
||||
-- log.use_console = false
|
||||
local eq = assert.are.same
|
||||
|
||||
--[[
|
||||
lua RELOAD('plenary'); require("plenary.test_harness"):test_directory("busted", "./tests/automated")
|
||||
--]]
|
||||
describe('telescope', function()
|
||||
describe('Picker', function()
|
||||
describe('window_dimensions', function()
|
||||
it('', function()
|
||||
assert(true)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('Picker', function()
|
||||
describe('window_dimensions', function()
|
||||
it('', function()
|
||||
assert(true)
|
||||
describe('attach_mappings', function()
|
||||
it('should allow for passing in a function', function()
|
||||
local p = picker.new({}, { attach_mappings = function() return 1 end })
|
||||
eq(1, p.attach_mappings())
|
||||
end)
|
||||
|
||||
it('should override an attach mappings passed in by opts', function()
|
||||
local called_order = {}
|
||||
local p = picker.new({
|
||||
attach_mappings = function()
|
||||
table.insert(called_order, 'opts')
|
||||
end,
|
||||
}, {
|
||||
attach_mappings = function()
|
||||
table.insert(called_order, 'default')
|
||||
end
|
||||
})
|
||||
|
||||
p.attach_mappings()
|
||||
|
||||
eq({'default', 'opts'}, called_order)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('Sorters', function()
|
||||
describe('generic_fuzzy_sorter', function()
|
||||
it('sort matches well', function()
|
||||
local sorter = require('telescope.sorters').get_generic_fuzzy_sorter()
|
||||
|
||||
local exact_match = sorter:score('hello', {ordinal = 'hello'})
|
||||
local no_match = sorter:score('abcdef', {ordinal = 'ghijkl'})
|
||||
local ok_match = sorter:score('abcdef', {ordinal = 'ab'})
|
||||
|
||||
assert(exact_match < no_match, "exact match better than no match")
|
||||
assert(exact_match < ok_match, "exact match better than ok match")
|
||||
assert(ok_match < no_match, "ok match better than no match")
|
||||
end)
|
||||
|
||||
it('sorts multiple finds better', function()
|
||||
local sorter = require('telescope.sorters').get_generic_fuzzy_sorter()
|
||||
|
||||
local multi_match = sorter:score('generics', 'exercises/generics/generics2.rs')
|
||||
local one_match = sorter:score('abcdef', 'exercises/generics/README.md')
|
||||
|
||||
-- assert(multi_match < one_match)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('fuzzy_file', function()
|
||||
it('sort matches well', function()
|
||||
local sorter = require('telescope.sorters').get_fuzzy_file()
|
||||
|
||||
local exact_match = sorter:score('abcdef', {ordinal = 'abcdef'})
|
||||
local no_match = sorter:score('abcdef', {ordinal = 'ghijkl'})
|
||||
local ok_match = sorter:score('abcdef', {ordinal = 'ab'})
|
||||
|
||||
assert(
|
||||
exact_match < no_match,
|
||||
string.format("Exact match better than no match: %s %s", exact_match, no_match)
|
||||
)
|
||||
assert(
|
||||
exact_match < ok_match,
|
||||
string.format("Exact match better than OK match: %s %s", exact_match, ok_match)
|
||||
)
|
||||
assert(ok_match < no_match, "OK match better than no match")
|
||||
end)
|
||||
|
||||
it('sorts matches after last os sep better', function()
|
||||
local sorter = require('telescope.sorters').get_fuzzy_file()
|
||||
|
||||
local better_match = sorter:score('aaa', {ordinal = 'bbb/aaa'})
|
||||
local worse_match = sorter:score('aaa', {ordinal = 'aaa/bbb'})
|
||||
|
||||
assert(better_match < worse_match, "Final match should be stronger")
|
||||
end)
|
||||
|
||||
pending('sorts multiple finds better', function()
|
||||
local sorter = require('telescope.sorters').get_fuzzy_file()
|
||||
|
||||
local multi_match = sorter:score('generics', {ordinal = 'exercises/generics/generics2.rs'})
|
||||
local one_match = sorter:score('abcdef', {ordinal = 'exercises/generics/README.md'})
|
||||
|
||||
assert(multi_match < one_match)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('fzy', function()
|
||||
local sorter = require'telescope.sorters'.get_fzy_sorter()
|
||||
local function score(prompt, line)
|
||||
return sorter:score(prompt, {ordinal = line})
|
||||
end
|
||||
|
||||
describe("matches", function()
|
||||
it("exact matches", function()
|
||||
assert.True(score("a", "a") >= 0)
|
||||
assert.True(score("a.bb", "a.bb") >= 0)
|
||||
end)
|
||||
it("ignore case", function()
|
||||
assert.True(score("AbB", "abb") >= 0)
|
||||
assert.True(score("abb", "ABB") >= 0)
|
||||
end)
|
||||
it("partial matches", function()
|
||||
assert.True(score("a", "ab") >= 0)
|
||||
assert.True(score("a", "ba") >= 0)
|
||||
assert.True(score("aba", "baabbaab") >= 0)
|
||||
end)
|
||||
it("with delimiters between", function()
|
||||
assert.True(score("abc", "a|b|c") >= 0)
|
||||
end)
|
||||
it("with empty query", function()
|
||||
assert.True(score("", "") >= 0)
|
||||
assert.True(score("", "a") >= 0)
|
||||
end)
|
||||
it("rejects non-matches", function()
|
||||
assert.True(score("a", "") < 0)
|
||||
assert.True(score("a", "b") < 0)
|
||||
assert.True(score("aa", "a") < 0)
|
||||
assert.True(score("ba", "a") < 0)
|
||||
assert.True(score("ab", "a") < 0)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("scoring", function()
|
||||
it("prefers beginnings of words", function()
|
||||
assert.True(score("amor", "app/models/order") < score("amor", "app/models/zrder"))
|
||||
end)
|
||||
it("prefers consecutive letters", function()
|
||||
assert.True(score("amo", "app/models/foo") < score("amo", "app/m/foo"))
|
||||
assert.True(score("erf", "perfect") < score("erf", "terrific"))
|
||||
end)
|
||||
it("prefers contiguous over letter following period", function()
|
||||
assert.True(score("gemfil", "Gemfile") < score("gemfil", "Gemfile.lock"))
|
||||
end)
|
||||
it("prefers shorter matches", function()
|
||||
assert.True(score("abce", "abcdef") < score("abce", "abc de"));
|
||||
assert.True(score("abc", " a b c ") < score("abc", " a b c "));
|
||||
assert.True(score("abc", " a b c ") < score("abc", " a b c "));
|
||||
end)
|
||||
it("prefers shorter candidates", function()
|
||||
assert.True(score("test", "tests") < score("test", "testing"))
|
||||
end)
|
||||
it("prefers matches at the beginning", function()
|
||||
assert.True(score("ab", "abbb") < score("ab", "babb"))
|
||||
assert.True(score("test", "testing") < score("test", "/testing"))
|
||||
end)
|
||||
it("prefers matches at some locations", function()
|
||||
assert.True(score("a", "/a") < score("a", "ba"))
|
||||
assert.True(score("a", "bA") < score("a", "ba"))
|
||||
assert.True(score("a", ".a") < score("a", "ba"))
|
||||
end)
|
||||
end)
|
||||
|
||||
local function positions(prompt, line)
|
||||
return sorter:highlighter(prompt, line)
|
||||
end
|
||||
|
||||
describe("positioning", function()
|
||||
it("favors consecutive positions", function()
|
||||
assert.same({1, 5, 6}, positions("amo", "app/models/foo"))
|
||||
end)
|
||||
it("favors word beginnings", function()
|
||||
assert.same({1, 5, 12, 13}, positions("amor", "app/models/order"))
|
||||
end)
|
||||
it("works when there are no bonuses", function()
|
||||
assert.same({2, 4}, positions("as", "tags"))
|
||||
assert.same({3, 8}, positions("as", "examples.txt"))
|
||||
end)
|
||||
it("favors smaller groupings of positions", function()
|
||||
assert.same({3, 5, 7}, positions("abc", "a/a/b/c/c"))
|
||||
assert.same({3, 5}, positions("ab", "caacbbc"))
|
||||
end)
|
||||
it("handles exact matches", function()
|
||||
assert.same({1, 2, 3}, positions("foo", "foo"))
|
||||
end)
|
||||
it("ignores empty requests", function()
|
||||
assert.same({}, positions("", ""))
|
||||
assert.same({}, positions("", "foo"))
|
||||
assert.same({}, positions("foo", ""))
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('layout_strategies', function()
|
||||
describe('center', function()
|
||||
it('should handle large terminals', function()
|
||||
-- TODO: This could call layout_strategies.center w/ some weird edge case.
|
||||
-- and then assert stuff about the dimensions.
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('Sorters', function()
|
||||
describe('generic_fuzzy_sorter', function()
|
||||
it('sort matches well', function()
|
||||
local sorter = require('telescope.sorters').get_generic_fuzzy_sorter()
|
||||
|
||||
local exact_match = sorter:score('hello', {ordinal = 'hello'})
|
||||
local no_match = sorter:score('abcdef', {ordinal = 'ghijkl'})
|
||||
local ok_match = sorter:score('abcdef', {ordinal = 'ab'})
|
||||
|
||||
assert(exact_match < no_match, "exact match better than no match")
|
||||
assert(exact_match < ok_match, "exact match better than ok match")
|
||||
assert(ok_match < no_match, "ok match better than no match")
|
||||
end)
|
||||
|
||||
it('sorts multiple finds better', function()
|
||||
local sorter = require('telescope.sorters').get_generic_fuzzy_sorter()
|
||||
|
||||
local multi_match = sorter:score('generics', 'exercises/generics/generics2.rs')
|
||||
local one_match = sorter:score('abcdef', 'exercises/generics/README.md')
|
||||
|
||||
-- assert(multi_match < one_match)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('fuzzy_file', function()
|
||||
it('sort matches well', function()
|
||||
local sorter = require('telescope.sorters').get_fuzzy_file()
|
||||
|
||||
local exact_match = sorter:score('abcdef', {ordinal = 'abcdef'})
|
||||
local no_match = sorter:score('abcdef', {ordinal = 'ghijkl'})
|
||||
local ok_match = sorter:score('abcdef', {ordinal = 'ab'})
|
||||
|
||||
assert(
|
||||
exact_match < no_match,
|
||||
string.format("Exact match better than no match: %s %s", exact_match, no_match)
|
||||
)
|
||||
assert(
|
||||
exact_match < ok_match,
|
||||
string.format("Exact match better than OK match: %s %s", exact_match, ok_match)
|
||||
)
|
||||
assert(ok_match < no_match, "OK match better than no match")
|
||||
end)
|
||||
|
||||
it('sorts matches after last os sep better', function()
|
||||
local sorter = require('telescope.sorters').get_fuzzy_file()
|
||||
|
||||
local better_match = sorter:score('aaa', {ordinal = 'bbb/aaa'})
|
||||
local worse_match = sorter:score('aaa', {ordinal = 'aaa/bbb'})
|
||||
|
||||
assert(better_match < worse_match, "Final match should be stronger")
|
||||
end)
|
||||
|
||||
pending('sorts multiple finds better', function()
|
||||
local sorter = require('telescope.sorters').get_fuzzy_file()
|
||||
|
||||
local multi_match = sorter:score('generics', {ordinal = 'exercises/generics/generics2.rs'})
|
||||
local one_match = sorter:score('abcdef', {ordinal = 'exercises/generics/README.md'})
|
||||
|
||||
assert(multi_match < one_match)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('fzy', function()
|
||||
local sorter = require'telescope.sorters'.get_fzy_sorter()
|
||||
local function score(prompt, line)
|
||||
return sorter:score(prompt, {ordinal = line})
|
||||
end
|
||||
|
||||
describe("matches", function()
|
||||
it("exact matches", function()
|
||||
assert.True(score("a", "a") >= 0)
|
||||
assert.True(score("a.bb", "a.bb") >= 0)
|
||||
end)
|
||||
it("ignore case", function()
|
||||
assert.True(score("AbB", "abb") >= 0)
|
||||
assert.True(score("abb", "ABB") >= 0)
|
||||
end)
|
||||
it("partial matches", function()
|
||||
assert.True(score("a", "ab") >= 0)
|
||||
assert.True(score("a", "ba") >= 0)
|
||||
assert.True(score("aba", "baabbaab") >= 0)
|
||||
end)
|
||||
it("with delimiters between", function()
|
||||
assert.True(score("abc", "a|b|c") >= 0)
|
||||
end)
|
||||
it("with empty query", function()
|
||||
assert.True(score("", "") >= 0)
|
||||
assert.True(score("", "a") >= 0)
|
||||
end)
|
||||
it("rejects non-matches", function()
|
||||
assert.True(score("a", "") < 0)
|
||||
assert.True(score("a", "b") < 0)
|
||||
assert.True(score("aa", "a") < 0)
|
||||
assert.True(score("ba", "a") < 0)
|
||||
assert.True(score("ab", "a") < 0)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("scoring", function()
|
||||
it("prefers beginnings of words", function()
|
||||
assert.True(score("amor", "app/models/order") < score("amor", "app/models/zrder"))
|
||||
end)
|
||||
it("prefers consecutive letters", function()
|
||||
assert.True(score("amo", "app/models/foo") < score("amo", "app/m/foo"))
|
||||
assert.True(score("erf", "perfect") < score("erf", "terrific"))
|
||||
end)
|
||||
it("prefers contiguous over letter following period", function()
|
||||
assert.True(score("gemfil", "Gemfile") < score("gemfil", "Gemfile.lock"))
|
||||
end)
|
||||
it("prefers shorter matches", function()
|
||||
assert.True(score("abce", "abcdef") < score("abce", "abc de"));
|
||||
assert.True(score("abc", " a b c ") < score("abc", " a b c "));
|
||||
assert.True(score("abc", " a b c ") < score("abc", " a b c "));
|
||||
end)
|
||||
it("prefers shorter candidates", function()
|
||||
assert.True(score("test", "tests") < score("test", "testing"))
|
||||
end)
|
||||
it("prefers matches at the beginning", function()
|
||||
assert.True(score("ab", "abbb") < score("ab", "babb"))
|
||||
assert.True(score("test", "testing") < score("test", "/testing"))
|
||||
end)
|
||||
it("prefers matches at some locations", function()
|
||||
assert.True(score("a", "/a") < score("a", "ba"))
|
||||
assert.True(score("a", "bA") < score("a", "ba"))
|
||||
assert.True(score("a", ".a") < score("a", "ba"))
|
||||
end)
|
||||
end)
|
||||
|
||||
local function positions(prompt, line)
|
||||
return sorter:highlighter(prompt, line)
|
||||
end
|
||||
|
||||
describe("positioning", function()
|
||||
it("favors consecutive positions", function()
|
||||
assert.same({1, 5, 6}, positions("amo", "app/models/foo"))
|
||||
end)
|
||||
it("favors word beginnings", function()
|
||||
assert.same({1, 5, 12, 13}, positions("amor", "app/models/order"))
|
||||
end)
|
||||
it("works when there are no bonuses", function()
|
||||
assert.same({2, 4}, positions("as", "tags"))
|
||||
assert.same({3, 8}, positions("as", "examples.txt"))
|
||||
end)
|
||||
it("favors smaller groupings of positions", function()
|
||||
assert.same({3, 5, 7}, positions("abc", "a/a/b/c/c"))
|
||||
assert.same({3, 5}, positions("ab", "caacbbc"))
|
||||
end)
|
||||
it("handles exact matches", function()
|
||||
assert.same({1, 2, 3}, positions("foo", "foo"))
|
||||
end)
|
||||
it("ignores empty requests", function()
|
||||
assert.same({}, positions("", ""))
|
||||
assert.same({}, positions("", "foo"))
|
||||
assert.same({}, positions("foo", ""))
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('layout_strategies', function()
|
||||
describe('center', function()
|
||||
it('should handle large terminals', function()
|
||||
-- TODO: This could call layout_strategies.center w/ some weird edge case.
|
||||
-- and then assert stuff about the dimensions.
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
-- describe('file_finder', function()
|
||||
-- COMPLETED = false
|
||||
-- PASSED = false
|
||||
|
||||
-- require('tests.helpers').auto_find_files {
|
||||
-- input = 'pickers.lua',
|
||||
|
||||
-- condition = function()
|
||||
-- print(vim.api.nvim_buf_get_name(0))
|
||||
-- return string.find(vim.api.nvim_buf_get_name(0), 'pickers.lua')
|
||||
-- end,
|
||||
-- }
|
||||
|
||||
-- print("WAIT:", vim.wait(5000, function() return COMPLETED end))
|
||||
-- assert(PASSED)
|
||||
-- end)
|
||||
end)
|
||||
|
||||
Reference in New Issue
Block a user