summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--osd.lua41
-rw-r--r--rt.lua13
-rw-r--r--state.lua52
-rw-r--r--util.lua23
4 files changed, 80 insertions, 49 deletions
diff --git a/osd.lua b/osd.lua
index b9be340..2152863 100644
--- a/osd.lua
+++ b/osd.lua
@@ -244,6 +244,21 @@ function mt:draw_progress_bar(prog, fg, bg)
'{\\fsp'..-filled..'}\xe2\x80\x8b{\\fsp0}'
end
+local function hl_matches(str, matches, col, hl_col)
+ if not matches then
+ return col .. asscape(str)
+ end
+
+ local buf = ''
+ local n = 0
+ for _, match in ipairs(matches) do
+ buf = buf .. col .. asscape(str:sub(n + 1, match.start - 1)) ..
+ hl_col .. asscape(str:sub(match.start, match.stop))
+ n = match.stop
+ end
+ return buf .. col .. asscape(str:sub(n + 1))
+end
+
function mt:option_text(opt, info)
local str = opt.name
local col = opt.ended and colour.option_dim or colour.option
@@ -255,23 +270,9 @@ function mt:option_text(opt, info)
col = colour.group
end
- if opt.matches then
- local buf = ''
- local hl_col = info.empty and colour.search_hl_empty or
- colour.search_hl
- local n = 0
-
- for _, match in ipairs(opt.matches) do
- buf = buf .. col ..
- asscape(str:sub(n + 1, match.start - 1)) ..
- hl_col ..
- asscape(str:sub(match.start, match.stop))
- n = match.stop
- end
- str = buf .. col .. asscape(str:sub(n + 1))
- else
- str = col .. asscape(str)
- end
+ local hl_col = info.empty and colour.search_hl_empty or
+ colour.search_hl
+ str = hl_matches(str, opt.matches, col, hl_col)
if opt.type == 'group' and opt.group_type ~= 'series' then
str = col .. '[' .. str .. ']'
@@ -285,7 +286,11 @@ function mt:option_text(opt, info)
local opt_info = opt.info
if opt_info and #opt_info > 0 then
- str = str .. colour.info .. ' (' .. asscape(opt_info) .. ')'
+ str = str .. colour.info .. ' (' ..
+ hl_matches(
+ opt_info, opt.info_matches, colour.info,
+ hl_col) ..
+ ')'
end
if opt.active_programme then
diff --git a/rt.lua b/rt.lua
index f68d89f..8ed3dc9 100644
--- a/rt.lua
+++ b/rt.lua
@@ -621,6 +621,9 @@ function rt.open_option_info(opt)
end
end
+local F_NAME = {name = true}
+local F_INFO = {info = true}
+local F_BOTH = {name = true, info = true}
local function search_text_transform(f, ...)
local menu = state:menu()
local str, pos = f(menu.search_text, menu.search_cursor, ...)
@@ -642,14 +645,20 @@ local function search_text_transform(f, ...)
local fm = prefix:find('m')
local fs = prefix:find('s')
local fg = prefix:find('g')
+ local fe = prefix:find('e')
filter = function(v)
- return fc and (v.stream_type == 'live' or
- v.stream_type == 'radio_streams') or
+ local fields
+ local ch = v.stream_type == 'live' or
+ v.stream_type == 'radio_streams'
+ local name = fc and ch 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'
+ local info = fe and ch and v.info
+ return name and (info and F_BOTH or F_NAME) or
+ info and F_INFO
end
end
diff --git a/state.lua b/state.lua
index f7f2234..4db4837 100644
--- a/state.lua
+++ b/state.lua
@@ -213,6 +213,24 @@ function menu_mt:set_search_text(str, pos, term, filter)
self:update_search_matches()
end
+function menu_mt:_match_fields(v, fields, case_sensitive)
+ local nm = fields.name and
+ util.find_matches(
+ v.name, self.search_term, case_sensitive)
+ local im = fields.info and
+ util.find_matches(
+ v.info, self.search_term, case_sensitive)
+
+ if nm or im 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.
+ return setmetatable(
+ {matches = nm, info_matches = im}, {__index = v})
+ end
+end
+
+local F_NAME = {name = true}
function menu_mt:update_search_matches()
if not self.search_filter and #self.search_term == 0 then
self.options = self.search_options
@@ -224,35 +242,11 @@ function menu_mt:update_search_matches()
local options = {}
for _, v in ipairs(self.search_options) do
- 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 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
-
- 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
+ local fields = not self.search_filter and F_NAME or
+ self.search_filter(v)
+ if fields then
+ options[#options+1] = self.search_term == '' and v or
+ self:_match_fields(v, fields, case_sensitive)
end
end
diff --git a/util.lua b/util.lua
index d678a9e..ca693ba 100644
--- a/util.lua
+++ b/util.lua
@@ -155,6 +155,29 @@ function util.unflatten_table(src, dst)
return dst
end
+function util.find_matches(str, substr, case_sensitive)
+ if not str then
+ return
+ end
+
+ if not case_sensitive then
+ str = str:lower()
+ end
+
+ local matches
+ local i, j = 0, 0
+ while true do
+ i, j = str:find(substr, j + 1, true)
+ -- j < i avoids infinite loop on empty substr
+ if not i or j < i then
+ break
+ end
+ matches = matches or {}
+ matches[#matches+1] = {start = i, stop = j}
+ end
+ return matches or i and {}
+end
+
function util.str_seek_prev_char(str, pos)
return util.utf8_seek(str, pos, -1)
end