diff options
Diffstat (limited to 'ar/.config/mpv/script-modules/scroll-list.lua')
| -rw-r--r-- | ar/.config/mpv/script-modules/scroll-list.lua | 457 |
1 files changed, 274 insertions, 183 deletions
diff --git a/ar/.config/mpv/script-modules/scroll-list.lua b/ar/.config/mpv/script-modules/scroll-list.lua index 5d8f9fa..c1088f1 100644 --- a/ar/.config/mpv/script-modules/scroll-list.lua +++ b/ar/.config/mpv/script-modules/scroll-list.lua @@ -1,293 +1,384 @@ -local mp = require 'mp' +local mp = require("mp") local scroll_list = { - global_style = [[]], - header_style = [[{\q2\fs35\c&00ccff&}]], - list_style = [[{\q2\fs25\c&Hffffff&}]], - wrapper_style = [[{\c&00ccff&\fs16}]], - cursor_style = [[{\c&00ccff&}]], - selected_style = [[{\c&Hfce788&}]], - - cursor = [[➤\h]], - indent = [[\h\h\h\h]], - - num_entries = 16, - wrap = false, - empty_text = "no entries" + global_style = [[]], + header_style = [[{\q2\fs35\c&00ccff&}]], + list_style = [[{\q2\fs25\c&Hffffff&}]], + wrapper_style = [[{\c&00ccff&\fs16}]], + cursor_style = [[{\c&00ccff&}]], + selected_style = [[{\c&Hfce788&}]], + + cursor = [[➤\h]], + indent = [[\h\h\h\h]], + + num_entries = 16, + wrap = false, + empty_text = "no entries", } --formats strings for ass handling --this function is based on a similar function from https://github.com/mpv-player/mpv/blob/master/player/lua/console.lua#L110 function scroll_list.ass_escape(str, replace_newline) - if replace_newline == true then replace_newline = "\\\239\187\191n" end - - --escape the invalid single characters - str = str:gsub('[\\{}\n]', { - -- There is no escape for '\' in ASS (I think?) but '\' is used verbatim if - -- it isn't followed by a recognised character, so add a zero-width - -- non-breaking space - ['\\'] = '\\\239\187\191', - ['{'] = '\\{', - ['}'] = '\\}', - -- Precede newlines with a ZWNBSP to prevent ASS's weird collapsing of - -- consecutive newlines - ['\n'] = '\239\187\191\\N', - }) - - -- Turn leading spaces into hard spaces to prevent ASS from stripping them - str = str:gsub('\\N ', '\\N\\h') - str = str:gsub('^ ', '\\h') - - if replace_newline then - str = str:gsub("\\N", replace_newline) - end - return str + if replace_newline == true then + replace_newline = "\\\239\187\191n" + end + + --escape the invalid single characters + str = str:gsub("[\\{}\n]", { + -- There is no escape for '\' in ASS (I think?) but '\' is used verbatim if + -- it isn't followed by a recognised character, so add a zero-width + -- non-breaking space + ["\\"] = "\\\239\187\191", + ["{"] = "\\{", + ["}"] = "\\}", + -- Precede newlines with a ZWNBSP to prevent ASS's weird collapsing of + -- consecutive newlines + ["\n"] = "\239\187\191\\N", + }) + + -- Turn leading spaces into hard spaces to prevent ASS from stripping them + str = str:gsub("\\N ", "\\N\\h") + str = str:gsub("^ ", "\\h") + + if replace_newline then + str = str:gsub("\\N", replace_newline) + end + return str end --format and return the header string function scroll_list:format_header_string(str) - return str + return str end --appends the entered text to the overlay function scroll_list:append(text) - if text == nil then return end - self.ass.data = self.ass.data .. text - end + if text == nil then + return + end + self.ass.data = self.ass.data .. text +end --appends a newline character to the osd function scroll_list:newline() - self.ass.data = self.ass.data .. '\\N' + self.ass.data = self.ass.data .. "\\N" end --re-parses the list into an ass string --if the list is closed then it flags an update on the next open function scroll_list:update() - if self.hidden then self.flag_update = true - else self:update_ass() end + if self.hidden then + self.flag_update = true + else + self:update_ass() + end end --prints the header to the overlay function scroll_list:format_header() - self:append(self.header_style) - self:append(self:format_header_string(self.header)) - self:newline() + self:append(self.header_style) + self:append(self:format_header_string(self.header)) + self:newline() end --formats each line of the list and prints it to the overlay function scroll_list:format_line(index, item) - self:append(self.list_style) + self:append(self.list_style) - if index == self.selected then self:append(self.cursor_style..self.cursor..self.selected_style) - else self:append(self.indent) end + if index == self.selected then + self:append(self.cursor_style .. self.cursor .. self.selected_style) + else + self:append(self.indent) + end - self:append(item.style) - self:append(item.ass) - self:newline() + self:append(item.style) + self:append(item.ass) + self:newline() end --refreshes the ass text using the contents of the list function scroll_list:update_ass() - self.ass.data = self.global_style - self:format_header() - - if #self.list < 1 then - self:append(self.empty_text) - self.ass:update() - return - end - - local start = 1 - local finish = start+self.num_entries-1 - - --handling cursor positioning - local mid = math.ceil(self.num_entries/2)+1 - if self.selected+mid > finish then - local offset = self.selected - finish + mid - - --if we've overshot the end of the list then undo some of the offset - if finish + offset > #self.list then - offset = offset - ((finish+offset) - #self.list) - end - - start = start + offset - finish = finish + offset - end - - --making sure that we don't overstep the boundaries - if start < 1 then start = 1 end - local overflow = finish < #self.list - --this is necessary when the number of items in the dir is less than the max - if not overflow then finish = #self.list end - - --adding a header to show there are items above in the list - if start > 1 then self:append(self.wrapper_style..(start-1)..' item(s) above\\N\\N') end - - for i=start, finish do - self:format_line(i, self.list[i]) - end - - if overflow then self:append('\\N'..self.wrapper_style..#self.list-finish..' item(s) remaining') end - self.ass:update() + self.ass.data = self.global_style + self:format_header() + + if #self.list < 1 then + self:append(self.empty_text) + self.ass:update() + return + end + + local start = 1 + local finish = start + self.num_entries - 1 + + --handling cursor positioning + local mid = math.ceil(self.num_entries / 2) + 1 + if self.selected + mid > finish then + local offset = self.selected - finish + mid + + --if we've overshot the end of the list then undo some of the offset + if finish + offset > #self.list then + offset = offset - ((finish + offset) - #self.list) + end + + start = start + offset + finish = finish + offset + end + + --making sure that we don't overstep the boundaries + if start < 1 then + start = 1 + end + local overflow = finish < #self.list + --this is necessary when the number of items in the dir is less than the max + if not overflow then + finish = #self.list + end + + --adding a header to show there are items above in the list + if start > 1 then + self:append(self.wrapper_style .. (start - 1) .. " item(s) above\\N\\N") + end + + for i = start, finish do + self:format_line(i, self.list[i]) + end + + if overflow then + self:append("\\N" .. self.wrapper_style .. #self.list - finish .. " item(s) remaining") + end + self.ass:update() end --moves the selector down the list function scroll_list:scroll_down() - if self.selected < #self.list then - self.selected = self.selected + 1 - self:update_ass() - elseif self.wrap then - self.selected = 1 - self:update_ass() - end + if self.selected < #self.list then + self.selected = self.selected + 1 + self:update_ass() + elseif self.wrap then + self.selected = 1 + self:update_ass() + end end --moves the selector up the list function scroll_list:scroll_up() - if self.selected > 1 then - self.selected = self.selected - 1 - self:update_ass() - elseif self.wrap then - self.selected = #self.list - self:update_ass() - end + if self.selected > 1 then + self.selected = self.selected - 1 + self:update_ass() + elseif self.wrap then + self.selected = #self.list + self:update_ass() + end end --moves the selector to the list next page function scroll_list:move_pagedown() - if #self.list > self.num_entries then - self.selected = self.selected + self.num_entries - if self.selected > #self.list then self.selected = #self.list end - self:update_ass() - end + if #self.list > self.num_entries then + self.selected = self.selected + self.num_entries + if self.selected > #self.list then + self.selected = #self.list + end + self:update_ass() + end end --moves the selector to the list previous page function scroll_list:move_pageup() - if #self.list > self.num_entries then - self.selected = self.selected - self.num_entries - if self.selected < 1 then self.selected = 1 end - self:update_ass() - end + if #self.list > self.num_entries then + self.selected = self.selected - self.num_entries + if self.selected < 1 then + self.selected = 1 + end + self:update_ass() + end end --moves the selector to the list begin function scroll_list:move_begin() - if #self.list > 1 then - self.selected = 1 - self:update_ass() - end + if #self.list > 1 then + self.selected = 1 + self:update_ass() + end end --moves the selector to the list end function scroll_list:move_end() - if #self.list > 1 then - self.selected = #self.list - self:update_ass() - end + if #self.list > 1 then + self.selected = #self.list + self:update_ass() + end end --adds the forced keybinds function scroll_list:add_keybinds() - for _,v in ipairs(self.keybinds) do - mp.add_forced_key_binding(v[1], 'dynamic/'..self.ass.id..'/'..v[2], v[3], v[4]) - end + for _, v in ipairs(self.keybinds) do + mp.add_forced_key_binding(v[1], "dynamic/" .. self.ass.id .. "/" .. v[2], v[3], v[4]) + end end --removes the forced keybinds function scroll_list:remove_keybinds() - for _,v in ipairs(self.keybinds) do - mp.remove_key_binding('dynamic/'..self.ass.id..'/'..v[2]) - end + for _, v in ipairs(self.keybinds) do + mp.remove_key_binding("dynamic/" .. self.ass.id .. "/" .. v[2]) + end end --opens the list and sets the hidden flag function scroll_list:open_list() - self.hidden = false - if not self.flag_update then self.ass:update() - else self.flag_update = false ; self:update_ass() end + self.hidden = false + if not self.flag_update then + self.ass:update() + else + self.flag_update = false + self:update_ass() + end end --closes the list and sets the hidden flag function scroll_list:close_list() - self.hidden = true - self.ass:remove() + self.hidden = true + self.ass:remove() end --modifiable function that opens the list function scroll_list:open() - if self.hidden then self:add_keybinds() end - self:open_list() + if self.hidden then + self:add_keybinds() + end + self:open_list() end --modifiable function that closes the list function scroll_list:close() - self:remove_keybinds() - self:close_list() + self:remove_keybinds() + self:close_list() end --toggles the list function scroll_list:toggle() - if self.hidden then self:open() - else self:close() end + if self.hidden then + self:open() + else + self:close() + end end --clears the list in-place function scroll_list:clear() - local i = 1 - while self.list[i] do - self.list[i] = nil - i = i + 1 - end + local i = 1 + while self.list[i] do + self.list[i] = nil + i = i + 1 + end end --added alias for ipairs(list.list) for lua 5.1 function scroll_list:ipairs() - return ipairs(self.list) + return ipairs(self.list) end --append item to the end of the list function scroll_list:insert(item) - self.list[#self.list + 1] = item + self.list[#self.list + 1] = item end local metatable = { - __index = function(t, key) - if scroll_list[key] ~= nil then return scroll_list[key] - elseif key == "__current" then return t.list[t.selected] - elseif type(key) == "number" then return t.list[key] end - end, - __newindex = function(t, key, value) - if type(key) == "number" then rawset(t.list, key, value) - else rawset(t, key, value) end - end, - __scroll_list = scroll_list, - __len = function(t) return #t.list end, - __ipairs = function(t) return ipairs(t.list) end + __index = function(t, key) + if scroll_list[key] ~= nil then + return scroll_list[key] + elseif key == "__current" then + return t.list[t.selected] + elseif type(key) == "number" then + return t.list[key] + end + end, + __newindex = function(t, key, value) + if type(key) == "number" then + rawset(t.list, key, value) + else + rawset(t, key, value) + end + end, + __scroll_list = scroll_list, + __len = function(t) + return #t.list + end, + __ipairs = function(t) + return ipairs(t.list) + end, } --creates a new list object function scroll_list:new() - local vars - vars = { - ass = mp.create_osd_overlay('ass-events'), - hidden = true, - flag_update = true, - - header = "header \\N ----------------------------------------------", - list = {}, - selected = 1, - - keybinds = { - {'DOWN', 'scroll_down', function() vars:scroll_down() end, {repeatable = true}}, - {'UP', 'scroll_up', function() vars:scroll_up() end, {repeatable = true}}, - {'PGDWN', 'move_pagedown', function() vars:move_pagedown() end, {}}, - {'PGUP', 'move_pageup', function() vars:move_pageup() end, {}}, - {'HOME', 'move_begin', function() vars:move_begin() end, {}}, - {'END', 'move_end', function() vars:move_end() end, {}}, - {'ESC', 'close_browser', function() vars:close() end, {}} - } - } - return setmetatable(vars, metatable) + local vars + vars = { + ass = mp.create_osd_overlay("ass-events"), + hidden = true, + flag_update = true, + + header = "header \\N ----------------------------------------------", + list = {}, + selected = 1, + + keybinds = { + { + "DOWN", + "scroll_down", + function() + vars:scroll_down() + end, + { repeatable = true }, + }, + { + "UP", + "scroll_up", + function() + vars:scroll_up() + end, + { repeatable = true }, + }, + { + "PGDWN", + "move_pagedown", + function() + vars:move_pagedown() + end, + {}, + }, + { + "PGUP", + "move_pageup", + function() + vars:move_pageup() + end, + {}, + }, + { + "HOME", + "move_begin", + function() + vars:move_begin() + end, + {}, + }, + { + "END", + "move_end", + function() + vars:move_end() + end, + {}, + }, + { + "ESC", + "close_browser", + function() + vars:close() + end, + {}, + }, + }, + } + return setmetatable(vars, metatable) end return scroll_list:new() |
