History

console.lua: highlight matching parts of selectable items

fzy returns which characters matched the search for every item, so use this to highlight them. This defaults to a light blue color that is readable with both black and white (selected) backgrounds. The returned positions are just bytes, so we can't put ASS tags or escape sequences around each byte because that would break displaying multibyte UTF-8 characters. Only put them around sequences of matched positions, and only when the sequences start and end at actual character positions.

Guido Cella committed 1 year ago

Commit 72bb2271 parent a5700482 files · +78 −12Browse files

Unified · Split

2 files
  1. DOCS/man/console.rst +5 −0
  2. player/lua/console.lua +73 −12
DOCS/man/console.rst+5−0
@@ -218,6 +218,11 @@ Configurable Options · 217 unmodified lines
218218
219219 The background color of the selected item.
220220
221+``match_color``
222+ Default: ``#0088FF``
223+
224+ The color of characters that match the searched string.
225+
221226 ``case_sensitive``
222227 Default: no on Windows, yes on other platforms.
223228
player/lua/console.lua+73−12
@@ -42,6 +42,7 @@ local opts = { · 41 unmodified lines
4242 scale_with_window = "auto",
4343 selected_color = '#222222',
4444 selected_back_color = '#FFFFFF',
45+ match_color = '#0088FF',
4546 case_sensitive = platform ~= 'windows' and true or false,
4647 history_dedup = true,
4748 persist_history = false,
@@ -77,6 +78,8 @@ local terminal_styles = { · 29 unmodified lines
7778 selected_completion = '\027[7m',
7879 default_item = '\027[1m',
7980 disabled = '\027[38;5;8m',
81+ matched_position = '\027[34m',
82+ match_end = '\027[39m',
8083 }
8184
8285 local repl_active = false
@@ -183,6 +186,18 @@ local function len_utf8(str) · 100 unmodified lines
183186 return len
184187 end
185188
189+local function utf8_positions(str)
190+ local pos = 1
191+ local positions = {true}
192+
193+ while pos <= str:len() do
194+ pos = next_utf8(str, pos)
195+ positions[pos] = true
196+ end
197+
198+ return positions
199+end
200+
186201
187202 -- Functions to calculate the font width.
188203 local width_length_ratio = 0.5
@@ -467,9 +482,7 @@ local function fuzzy_find(needle, haystacks, case_sensitive) · 278 unmodified lines
467482
468483 return i[1] < j[1]
469484 end)
470− for i, value in ipairs(result) do
471− result[i] = value[1]
472− end
485+
473486 return result
474487 end
475488
@@ -480,6 +493,9 @@ local function get_matches_to_print(terminal) · 4 unmodified lines
480493
481494 local items = {}
482495 local max_lines = calculate_max_lines()
496+ local escape = terminal and function (str) return str end or ass_escape
497+ local highlight = terminal and terminal_styles.matched_position or
498+ '{\\1c&H' .. option_color_to_ass(opts.match_color) .. '}'
483499
484500 if selected_match < first_match_to_print then
485501 first_match_to_print = selected_match
@@ -491,27 +507,68 @@ local function get_matches_to_print(terminal) · 5 unmodified lines
491507 #matches)
492508
493509 for i = first_match_to_print, last_match_to_print do
494− local style = ''
510+ local item = ''
511+ local end_highlight = terminal and terminal_styles.match_end or '{\\1c}'
495512
496513 if terminal then
497514 if matches[i].index == default_item then
498− style = terminal_styles.default_item
515+ item = terminal_styles.default_item
499516 end
500517 if i == selected_match then
501− style = style .. terminal_styles.selected_completion
518+ item = item .. terminal_styles.selected_completion
502519 end
503520 else
504521 if i == selected_match then
505522 if searching_history and
506523 mp.get_property('osd-border-style') == 'outline-and-shadow' then
507− style = get_selected_ass()
524+ item = get_selected_ass()
525+ else
526+ item = '{\\1c&H' .. option_color_to_ass(opts.selected_color) .. '&}'
527+ end
528+ end_highlight = item
529+ end
530+ end
531+
532+ local char_positions = utf8_positions(matches[i].text)
533+ local start_of_last_match = matches[i].positions[1]
534+
535+ if not start_of_last_match then
536+ item = item .. escape(matches[i].text)
537+ elseif start_of_last_match > 1 then
538+ item = item .. escape(matches[i].text:sub(1, start_of_last_match - 1))
539+ end
540+
541+ for j, pos in ipairs(matches[i].positions) do
542+ local last_pos = matches[i].positions[j - 1]
543+
544+ if last_pos and pos > last_pos + 1 then
545+ if char_positions[start_of_last_match] and char_positions[last_pos + 1] then
546+ item = item .. highlight ..
547+ escape(matches[i].text:sub(start_of_last_match, last_pos)) ..
548+ end_highlight ..
549+ escape(matches[i].text:sub(last_pos + 1, pos - 1))
508550 else
509− style = '{\\1c&H' .. option_color_to_ass(opts.selected_color) .. '&}'
551+ item = item .. escape(matches[i].text:sub(start_of_last_match, pos - 1))
510552 end
553+
554+ start_of_last_match = pos
511555 end
512556 end
513557
514− items[#items + 1] = style .. matches[i].text
558+ if start_of_last_match then
559+ local last_pos = matches[i].positions[#matches[i].positions]
560+
561+ if char_positions[start_of_last_match] and char_positions[last_pos + 1] then
562+ item = item .. highlight ..
563+ escape(matches[i].text:sub(start_of_last_match, last_pos)) ..
564+ end_highlight ..
565+ escape(matches[i].text:sub(last_pos + 1))
566+ else
567+ item = item .. escape(matches[i].text:sub(start_of_last_match))
568+ end
569+ end
570+
571+ items[#items + 1] = item
515572 end
516573
517574 return items
@@ -864,7 +921,11 @@ local function handle_edit() · 346 unmodified lines
864921 if selectable_items then
865922 matches = {}
866923 for i, match in ipairs(fuzzy_find(line, selectable_items)) do
867− matches[i] = { index = match, text = selectable_items[match] }
924+ matches[i] = {
925+ index = match[1],
926+ text = selectable_items[match[1]],
927+ positions = match[2],
928+ }
868929 end
869930
870931 if line == '' and default_item then
@@ -1780,7 +1841,7 @@ complete = function () · 909 unmodified lines
17801841 completion_pos = completion_pos or 1
17811842 for i, match in ipairs(fuzzy_find(before_cur:sub(completion_pos),
17821843 completions, opts.case_sensitive)) do
1783− completion_buffer[i] = completions[match]
1844+ completion_buffer[i] = completions[match[1]]
17841845 end
17851846
17861847 render()
@@ -2100,7 +2161,7 @@ mp.register_script_message('complete', function(list, start_pos) · 313 unmodified lines
21002161 completion_append = ''
21012162 for i, match in ipairs(fuzzy_find(line:sub(completion_pos, cursor),
21022163 completions)) do
2103− completion_buffer[i] = completions[match]
2164+ completion_buffer[i] = completions[match[1]]
21042165 end
21052166
21062167 render()

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t