diff options
| -rw-r--r-- | config.lua | 1 | ||||
| -rw-r--r-- | osd.lua | 36 | ||||
| -rw-r--r-- | rt.lua | 27 | ||||
| -rw-r--r-- | state.lua | 59 |
4 files changed, 90 insertions, 33 deletions
@@ -36,6 +36,7 @@ config.colour = { search_hl_empty = '778800', search_path = '666666', search_path_empty = '444444', + search_prefix = 'cc66ff', icon_sorted = '4488cc', icon_playing = '3366ff', icon_favourite = 'ff00ff', @@ -159,18 +159,38 @@ function mt:menu_title(menu) local col = menu.search_active and colour.selected or colour.title if menu.type == 'search' then - str = str:gsub('<text>', asscape(menu.search_text)) + local start = #menu.search_text - #menu.search_term + local prefix = menu.search_text:sub(1, start) + local term = menu.search_text:sub(start + 1) + + if str:find('<text>', 1, true) then + str = str:gsub('<text>', function() + return colour.search_prefix .. + asscape(prefix) .. col .. asscape(term) + end) + end if str:find('<text_with_cursor>', 1, true) then - str = str:gsub('<text_with_cursor>', - asscape(menu.search_text:sub( - 1, menu.search_cursor - 1)) .. - cursor_glyph .. - asscape(menu.search_text:sub( - menu.search_cursor))) + local idx = menu.search_cursor + if idx <= start then + prefix = asscape(prefix:sub(1, idx - 1)) .. + col .. cursor_glyph .. + colour.search_prefix .. + asscape(prefix:sub(idx)) + term = asscape(term) + else + idx = idx - start + prefix = asscape(prefix) + term = asscape(term:sub(1, idx - 1)) .. + cursor_glyph .. asscape(term:sub(idx)) + end + str = str:gsub('<text_with_cursor>', function() + return colour.search_prefix .. prefix .. col .. + term + end) end - str = str:gsub('<colour.info>', colour.info) + str = str:gsub('<colour%.info>', colour.info) str = str:gsub('<num_matches>', #menu.options) str = str:gsub('<num_total>', #menu.search_options) end @@ -628,7 +628,32 @@ local function search_text_transform(f, ...) return end - menu:set_search_text(str, pos) + local term + local filter + local prefix + if str:sub(1,1) == '\\' then + term = str:sub(2) + else + prefix, term = str:match('^(.-)//(.*)') + term = term or str + end + if prefix then + local fc = prefix:find('c') + local fm = prefix:find('m') + local fs = prefix:find('s') + local fg = prefix:find('g') + + filter = function(v) + return fc and (v.stream_type == 'live' or + v.stream_type == 'radio_streams') or + fm and v.stream_type == 'movie' or + fs and v.group_type == 'series' or + fg and v.type == 'group' and + v.group_type ~= 'series' + end + end + + menu:set_search_text(str, pos, term, filter) osd:dirty() end @@ -37,6 +37,7 @@ function mt:push_menu(t) if menu.type == 'search' then menu.search_options = menu.options menu.search_text = menu.search_text or '' + menu.search_term = menu.search_term or '' menu.search_cursor = menu.search_cursor or #menu.search_text + 1 menu:update_search_matches() @@ -85,6 +86,8 @@ end function menu_mt:save_checkpoint() self.checkpoint = { search_text = self.search_text, + search_term = self.search_term, + search_filter = self.search_filter, cursor = self.cursor, view_top = self.view_top, } @@ -92,7 +95,8 @@ end function menu_mt:restore_checkpoint() local t = self.checkpoint - self:set_search_text(t.search_text) + self:set_search_text( + t.search_text, nil, t.search_term, t.search_filter) self.cursor = t.cursor self.view_top = t.view_top end @@ -201,47 +205,54 @@ function menu_mt:set_search_cursor(pos) return true end -function menu_mt:set_search_text(str, pos) +function menu_mt:set_search_text(str, pos, term, filter) self.search_text = str + self.search_term = term + self.search_filter = filter self:set_search_cursor(pos or self.search_cursor) self:update_search_matches() end function menu_mt:update_search_matches() - if #self.search_text == 0 then + if not self.search_filter and #self.search_term == 0 then self.options = self.search_options return end -- no utf8 :( - local case_sensitive = not not self.search_text:find('%u') + local case_sensitive = not not self.search_term:find('%u') local options = {} for _, v in ipairs(self.search_options) do - local matches + if not self.search_filter or self.search_filter(v) then + local matches - local name = v.name - if not case_sensitive then - name = name:lower() - end + local name = v.name + if not case_sensitive then + name = name:lower() + end - local i, j = 0, 0 - while true do - i, j = name:find(self.search_text, j + 1, true) - if not i then - break + local i, j = 0, 0 + while true do + i, j = name:find(self.search_term, j + 1, true) + -- j < i avoids infinite loop on empty term + if not i or j < i then + break + end + matches = matches or {} + matches[#matches+1] = {start = i, stop = j} end - matches = matches or {} - matches[#matches+1] = {start = i, stop = j} - end - if matches then - -- search options may contain dynamic data that is - -- updated on redraw. using a proxy table instead of - -- copying prevents potential updates on every change - -- of search text. - options[#options+1] = setmetatable( - {matches = matches}, {__index = v}) + if matches then + -- search options may contain dynamic data that + -- is updated on redraw. using a proxy table + -- instead of copying prevents potential + -- updates on every change of search text. + options[#options+1] = setmetatable( + {matches = matches}, {__index = v}) + elseif i then + options[#options+1] = v + end end end |
