summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Vazgenovich Shakaryan <dvshakaryan@gmail.com>2026-02-04 23:06:15 -0800
committerDavid Vazgenovich Shakaryan <dvshakaryan@gmail.com>2026-02-04 23:06:15 -0800
commitca004728498a71afd401cf6b8cdc949742b7ea0f (patch)
tree64a08975359c0116b2be1bcd2a23b55ff20d1e68
parent2fbe621881f0ac3d7f74d117bc7f6de404a9a882 (diff)
downloadmpv-iptv-menu-ca004728498a71afd401cf6b8cdc949742b7ea0f.tar.gz
mpv-iptv-menu-ca004728498a71afd401cf6b8cdc949742b7ea0f.tar.xz
allow filtering search results by type
-rw-r--r--config.lua1
-rw-r--r--osd.lua36
-rw-r--r--rt.lua27
-rw-r--r--state.lua59
4 files changed, 90 insertions, 33 deletions
diff --git a/config.lua b/config.lua
index c044d57..84f7a74 100644
--- a/config.lua
+++ b/config.lua
@@ -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',
diff --git a/osd.lua b/osd.lua
index a793286..348f0d2 100644
--- a/osd.lua
+++ b/osd.lua
@@ -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
diff --git a/rt.lua b/rt.lua
index d49c59d..f68d89f 100644
--- a/rt.lua
+++ b/rt.lua
@@ -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
diff --git a/state.lua b/state.lua
index b5e07f5..f7f2234 100644
--- a/state.lua
+++ b/state.lua
@@ -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