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: ' ' 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* *telescope.defaults.initial_mode*
initial_mode: ~ initial_mode: ~
Determines in which mode telescope starts. Valid Keys: Determines in which mode telescope starts. Valid Keys:

View File

@@ -245,6 +245,18 @@ append(
Default: ' ']] 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( append(
"initial_mode", "initial_mode",
"insert", "insert",

View File

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

View File

@@ -84,6 +84,20 @@ function Highlighter:hi_multiselect(row, is_selected)
if is_selected then if is_selected then
vim.api.nvim_buf_add_highlight(results_bufnr, ns_telescope_multiselection, "TelescopeMultiSelection", row, 0, -1) 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 else
local existing_marks = vim.api.nvim_buf_get_extmarks( local existing_marks = vim.api.nvim_buf_get_extmarks(
results_bufnr, results_bufnr,

View File

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