feat: multiselect icon (#1572)

* feat: add `multi_icon` option to pickers and corresponding highlight

* feat: allow `multi_icon` to be any length

* fix: adjust `selection_caret` highlighting
This commit is contained in:
Luke Kershaw
2022-01-05 22:42:29 +00:00
committed by GitHub
parent 749ce3b8ca
commit f285599440
5 changed files with 64 additions and 7 deletions

View File

@@ -184,6 +184,15 @@ telescope.setup({opts}) *telescope.setup()*
Default: ' '
*telescope.defaults.multi_icon*
multi_icon: ~
Symbol to add in front of a multi-selected result entry.
Replaces final character of |telescope.defaults.selection_caret| and
|telescope.defaults.entry_prefix| as appropriate.
To have no icon, set to the empty string.
Default: '+'
*telescope.defaults.initial_mode*
initial_mode: ~
Determines in which mode telescope starts. Valid Keys:

View File

@@ -245,6 +245,18 @@ append(
Default: ' ']]
)
append(
"multi_icon",
"+",
[[
Symbol to add in front of a multi-selected result entry.
Replaces final character of |telescope.defaults.selection_caret| and
|telescope.defaults.entry_prefix| as appropriate.
To have no icon, set to the empty string.
Default: '+']]
)
append(
"initial_mode",
"insert",

View File

@@ -27,6 +27,9 @@ local MultiSelect = require "telescope.pickers.multi"
local get_default = utils.get_default
local truncate = require("plenary.strings").truncate
local strdisplaywidth = require("plenary.strings").strdisplaywidth
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"
@@ -68,6 +71,8 @@ function Picker:new(opts)
prompt_prefix = get_default(opts.prompt_prefix, config.values.prompt_prefix),
selection_caret = get_default(opts.selection_caret, config.values.selection_caret),
entry_prefix = get_default(opts.entry_prefix, config.values.entry_prefix),
multi_icon = get_default(opts.multi_icon, config.values.multi_icon),
initial_mode = get_default(opts.initial_mode, config.values.initial_mode),
debounce = get_default(tonumber(opts.debounce), nil),
@@ -923,29 +928,45 @@ function Picker:set_selection(row)
-- Not sure.
local set_ok, set_errmsg = pcall(function()
local prompt = self:_get_prompt()
local prefix = function(sel, multi)
local t
if sel then
t = self.selection_caret
else
t = self.entry_prefix
end
if multi and type(self.multi_icon) == "string" then
t = truncate(t, strdisplaywidth(t) - strdisplaywidth(self.multi_icon), "") .. self.multi_icon
end
return t
end
-- This block handles removing the caret from beginning of previous selection (if still visible)
-- Check if previous selection is still visible
if self._selection_entry and self.manager:find_entry(self._selection_entry) then
-- Find the (possibly new) row of the old selection
local row_old_selection = self:get_row(self.manager:find_entry(self._selection_entry))
local old_multiselected = self:is_multi_selected(self._selection_entry)
local line = a.nvim_buf_get_lines(results_bufnr, row_old_selection, row_old_selection + 1, false)[1]
--Check if that row still has the caret
if string.sub(line, 0, #self.selection_caret) == self.selection_caret then
local old_caret = string.sub(line, 0, #prefix(true)) == prefix(true) and prefix(true)
or string.sub(line, 0, #prefix(true, true)) == prefix(true, true) and prefix(true, true)
if old_caret then
-- Only change the first couple characters, nvim_buf_set_text leaves the existing highlights
a.nvim_buf_set_text(
results_bufnr,
row_old_selection,
0,
row_old_selection,
#self.selection_caret,
{ self.entry_prefix }
#old_caret,
{ prefix(false, old_multiselected) }
)
self.highlighter:hi_multiselect(row_old_selection, self:is_multi_selected(self._selection_entry))
self.highlighter:hi_multiselect(row_old_selection, old_multiselected)
end
end
local caret = self.selection_caret
local caret = prefix(true, self:is_multi_selected(entry))
local display, display_highlights = entry_display.resolve(self, entry)
display = caret .. display
@@ -958,8 +979,8 @@ function Picker:set_selection(row)
end
a.nvim_buf_set_lines(results_bufnr, row, row + 1, false, { display })
-- don't highlight the ' ' at the end of caret
self.highlighter:hi_selection(row, caret:sub(1, -2))
-- don't highlight any whitespace at the end of caret
self.highlighter:hi_selection(row, caret:match "(.*%S)")
self.highlighter:hi_display(row, caret, display_highlights)
self.highlighter:hi_sorter(row, prompt, display)

View File

@@ -84,6 +84,20 @@ function Highlighter:hi_multiselect(row, is_selected)
if is_selected then
vim.api.nvim_buf_add_highlight(results_bufnr, ns_telescope_multiselection, "TelescopeMultiSelection", row, 0, -1)
if self.picker.multi_icon then
local line = vim.api.nvim_buf_get_lines(results_bufnr, row, row + 1, false)[1]
local pos = line:find(self.picker.multi_icon)
if pos and pos <= math.max(#self.picker.selection_caret, #self.picker.entry_prefix) then
vim.api.nvim_buf_add_highlight(
results_bufnr,
ns_telescope_multiselection,
"TelescopeMultiIcon",
row,
pos - 1,
pos - 1 + #self.picker.multi_icon
)
end
end
else
local existing_marks = vim.api.nvim_buf_get_extmarks(
results_bufnr,

View File

@@ -12,6 +12,7 @@ let g:loaded_telescope = 1
highlight default link TelescopeSelection Visual
highlight default link TelescopeSelectionCaret TelescopeSelection
highlight default link TelescopeMultiSelection Type
highlight default link TelescopeMultiIcon Identifier
" "Normal" in the floating windows created by telescope.
highlight default link TelescopeNormal Normal