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
218 218
219 The background color of the selected item.219 The background color of the selected item.
220 220
221``match_color``
222 Default: ``#0088FF``
223
224 The color of characters that match the searched string.
225
221``case_sensitive``226``case_sensitive``
222 Default: no on Windows, yes on other platforms.227 Default: no on Windows, yes on other platforms.
223 228
player/lua/console.lua+73−12
@@ -42,6 +42,7 @@ local opts = { · 41 unmodified lines
42 scale_with_window = "auto",42 scale_with_window = "auto",
43 selected_color = '#222222',43 selected_color = '#222222',
44 selected_back_color = '#FFFFFF',44 selected_back_color = '#FFFFFF',
45 match_color = '#0088FF',
45 case_sensitive = platform ~= 'windows' and true or false,46 case_sensitive = platform ~= 'windows' and true or false,
46 history_dedup = true,47 history_dedup = true,
47 persist_history = false,48 persist_history = false,
@@ -77,6 +78,8 @@ local terminal_styles = { · 29 unmodified lines
77 selected_completion = '\027[7m',78 selected_completion = '\027[7m',
78 default_item = '\027[1m',79 default_item = '\027[1m',
79 disabled = '\027[38;5;8m',80 disabled = '\027[38;5;8m',
81 matched_position = '\027[34m',
82 match_end = '\027[39m',
80}83}
81 84
82local repl_active = false85local repl_active = false
@@ -183,6 +186,18 @@ local function len_utf8(str) · 100 unmodified lines
183 return len186 return len
184end187end
185 188
189local 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
199end
200
186 201
187-- Functions to calculate the font width.202-- Functions to calculate the font width.
188local width_length_ratio = 0.5203local width_length_ratio = 0.5
@@ -467,9 +482,7 @@ local function fuzzy_find(needle, haystacks, case_sensitive) · 278 unmodified lines
467 482
468 return i[1] < j[1]483 return i[1] < j[1]
469 end)484 end)
470 for i, value in ipairs(result) do485
471 result[i] = value[1]
472 end
473 return result486 return result
474end487end
475 488
@@ -480,6 +493,9 @@ local function get_matches_to_print(terminal) · 4 unmodified lines
480 493
481 local items = {}494 local items = {}
482 local max_lines = calculate_max_lines()495 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) .. '}'
483 499
484 if selected_match < first_match_to_print then500 if selected_match < first_match_to_print then
485 first_match_to_print = selected_match501 first_match_to_print = selected_match
@@ -491,27 +507,68 @@ local function get_matches_to_print(terminal) · 5 unmodified lines
491 #matches)507 #matches)
492 508
493 for i = first_match_to_print, last_match_to_print do509 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}'
495 512
496 if terminal then513 if terminal then
497 if matches[i].index == default_item then514 if matches[i].index == default_item then
498 style = terminal_styles.default_item515 item = terminal_styles.default_item
499 end516 end
500 if i == selected_match then517 if i == selected_match then
501 style = style .. terminal_styles.selected_completion518 item = item .. terminal_styles.selected_completion
502 end519 end
503 else520 else
504 if i == selected_match then521 if i == selected_match then
505 if searching_history and522 if searching_history and
506 mp.get_property('osd-border-style') == 'outline-and-shadow' then523 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))
508 else550 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))
510 end552 end
553
554 start_of_last_match = pos
511 end555 end
512 end556 end
513 557
514 items[#items + 1] = style .. matches[i].text558 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
515 end572 end
516 573
517 return items574 return items
@@ -864,7 +921,11 @@ local function handle_edit() · 346 unmodified lines
864 if selectable_items then921 if selectable_items then
865 matches = {}922 matches = {}
866 for i, match in ipairs(fuzzy_find(line, selectable_items)) do923 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 }
868 end929 end
869 930
870 if line == '' and default_item then931 if line == '' and default_item then
@@ -1780,7 +1841,7 @@ complete = function () · 909 unmodified lines
1780 completion_pos = completion_pos or 11841 completion_pos = completion_pos or 1
1781 for i, match in ipairs(fuzzy_find(before_cur:sub(completion_pos),1842 for i, match in ipairs(fuzzy_find(before_cur:sub(completion_pos),
1782 completions, opts.case_sensitive)) do1843 completions, opts.case_sensitive)) do
1783 completion_buffer[i] = completions[match]1844 completion_buffer[i] = completions[match[1]]
1784 end1845 end
1785 1846
1786 render()1847 render()
@@ -2100,7 +2161,7 @@ mp.register_script_message('complete', function(list, start_pos) · 313 unmodified lines
2100 completion_append = ''2161 completion_append = ''
2101 for i, match in ipairs(fuzzy_find(line:sub(completion_pos, cursor),2162 for i, match in ipairs(fuzzy_find(line:sub(completion_pos, cursor),
2102 completions)) do2163 completions)) do
2103 completion_buffer[i] = completions[match]2164 completion_buffer[i] = completions[match[1]]
2104 end2165 end
2105 2166
2106 render()2167 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